// xlsxconditionalformatting.cpp #include #include #include #include #include "xlsxconditionalformatting.h" #include "xlsxconditionalformatting_p.h" #include "xlsxworksheet.h" #include "xlsxcellrange.h" #include "xlsxstyles_p.h" QT_BEGIN_NAMESPACE_XLSX ConditionalFormattingPrivate::ConditionalFormattingPrivate() { } ConditionalFormattingPrivate::ConditionalFormattingPrivate(const ConditionalFormattingPrivate &other) :QSharedData(other) { } ConditionalFormattingPrivate::~ConditionalFormattingPrivate() { } void ConditionalFormattingPrivate::writeCfVo(QXmlStreamWriter &writer, const XlsxCfVoData &cfvo) const { writer.writeEmptyElement(QStringLiteral("cfvo")); QString type; switch(cfvo.type) { case ConditionalFormatting::VOT_Formula: type=QStringLiteral("formula"); break; case ConditionalFormatting::VOT_Max: type=QStringLiteral("max"); break; case ConditionalFormatting::VOT_Min: type=QStringLiteral("min"); break; case ConditionalFormatting::VOT_Num: type=QStringLiteral("num"); break; case ConditionalFormatting::VOT_Percent: type=QStringLiteral("percent"); break; case ConditionalFormatting::VOT_Percentile: type=QStringLiteral("percentile"); break; default: break; } writer.writeAttribute(QStringLiteral("type"), type); writer.writeAttribute(QStringLiteral("val"), cfvo.value); if (!cfvo.gte) writer.writeAttribute(QStringLiteral("gte"), QStringLiteral("0")); } /*! * \class ConditionalFormatting * \brief Conditional formatting for single cell or ranges * \inmodule QtXlsx * * The conditional formatting can be applied to a single cell or ranges of cells. */ /*! \enum ConditionalFormatting::HighlightRuleType \value Highlight_LessThan \value Highlight_LessThanOrEqual \value Highlight_Equal \value Highlight_NotEqual \value Highlight_GreaterThanOrEqual \value Highlight_GreaterThan \value Highlight_Between \value Highlight_NotBetween \value Highlight_ContainsText \value Highlight_NotContainsText \value Highlight_BeginsWith \value Highlight_EndsWith \value Highlight_TimePeriod \value Highlight_Duplicate \value Highlight_Unique \value Highlight_Blanks \value Highlight_NoBlanks \value Highlight_Errors \value Highlight_NoErrors \value Highlight_Top \value Highlight_TopPercent \value Highlight_Bottom \value Highlight_BottomPercent \value Highlight_AboveAverage \value Highlight_AboveOrEqualAverage \value Highlight_BelowAverage \value Highlight_BelowOrEqualAverage \value Highlight_AboveStdDev1 \value Highlight_AboveStdDev2 \value Highlight_AboveStdDev3 \value Highlight_BelowStdDev1 \value Highlight_BelowStdDev2 \value Highlight_BelowStdDev3 \value Highlight_Expression */ /*! \enum ConditionalFormatting::ValueObjectType \value VOT_Formula \value VOT_Max \value VOT_Min \value VOT_Num \value VOT_Percent \value VOT_Percentile */ /*! Construct a conditional formatting object */ ConditionalFormatting::ConditionalFormatting() :d(new ConditionalFormattingPrivate()) { } /*! Constructs a copy of \a other. */ ConditionalFormatting::ConditionalFormatting(const ConditionalFormatting &other) :d(other.d) { } /*! Assigns \a other to this conditional formatting and returns a reference to this conditional formatting. */ ConditionalFormatting &ConditionalFormatting::operator=(const ConditionalFormatting &other) { this->d = other.d; return *this; } /*! * Destroy the object. */ ConditionalFormatting::~ConditionalFormatting() { } /*! * Add a hightlight rule with the given \a type, \a formula1, \a formula2, * \a format and \a stopIfTrue. * Return false if failed. */ bool ConditionalFormatting::addHighlightCellsRule(HighlightRuleType type, const QString &formula1, const QString &formula2, const Format &format, bool stopIfTrue) { if (format.isEmpty()) return false; bool skipFormula = false; QSharedPointer cfRule(new XlsxCfRuleData); if (type >= Highlight_LessThan && type <= Highlight_NotBetween) { cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("cellIs"); QString op; switch (type) { case Highlight_Between: op = QStringLiteral("between"); break; case Highlight_Equal: op = QStringLiteral("equal"); break; case Highlight_GreaterThan: op = QStringLiteral("greaterThan"); break; case Highlight_GreaterThanOrEqual: op = QStringLiteral("greaterThanOrEqual"); break; case Highlight_LessThan: op = QStringLiteral("lessThan"); break; case Highlight_LessThanOrEqual: op = QStringLiteral("lessThanOrEqual"); break; case Highlight_NotBetween: op = QStringLiteral("notBetween"); break; case Highlight_NotEqual: op = QStringLiteral("notEqual"); break; default: break; } cfRule->attrs[XlsxCfRuleData::A_operator] = op; } else if (type >= Highlight_ContainsText && type <= Highlight_EndsWith) { if (type == Highlight_ContainsText) { cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("containsText"); cfRule->attrs[XlsxCfRuleData::A_operator] = QStringLiteral("containsText"); cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("NOT(ISERROR(SEARCH(\"%1\",%2)))").arg(formula1); } else if (type == Highlight_NotContainsText) { cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("notContainsText"); cfRule->attrs[XlsxCfRuleData::A_operator] = QStringLiteral("notContains"); cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("ISERROR(SEARCH(\"%2\",%1))").arg(formula1); } else if (type == Highlight_BeginsWith) { cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("beginsWith"); cfRule->attrs[XlsxCfRuleData::A_operator] = QStringLiteral("beginsWith"); cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("LEFT(%2,LEN(\"%1\"))=\"%1\"").arg(formula1); } else { cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("endsWith"); cfRule->attrs[XlsxCfRuleData::A_operator] = QStringLiteral("endsWith"); cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("RIGHT(%2,LEN(\"%1\"))=\"%1\"").arg(formula1); } cfRule->attrs[XlsxCfRuleData::A_text] = formula1; skipFormula = true; } else if (type == Highlight_TimePeriod) { cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("timePeriod"); //:Todo return false; } else if (type == Highlight_Duplicate) { cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("duplicateValues"); } else if (type == Highlight_Unique) { cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("uniqueValues"); } else if (type == Highlight_Errors) { cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("containsErrors"); cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("ISERROR(%1)"); skipFormula = true; } else if (type == Highlight_NoErrors) { cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("notContainsErrors"); cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("NOT(ISERROR(%1))"); skipFormula = true; } else if (type == Highlight_Blanks) { cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("containsBlanks"); cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("LEN(TRIM(%1))=0"); skipFormula = true; } else if (type == Highlight_NoBlanks) { cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("notContainsBlanks"); cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("LEN(TRIM(%1))>0"); skipFormula = true; } else if (type >= Highlight_Top && type <= Highlight_BottomPercent) { cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("top10"); if (type == Highlight_Bottom || type == Highlight_BottomPercent) cfRule->attrs[XlsxCfRuleData::A_bottom] = QStringLiteral("1"); if (type == Highlight_TopPercent || type == Highlight_BottomPercent) cfRule->attrs[XlsxCfRuleData::A_percent] = QStringLiteral("1"); cfRule->attrs[XlsxCfRuleData::A_rank] = !formula1.isEmpty() ? formula1 : QStringLiteral("10"); skipFormula = true; } else if (type >= Highlight_AboveAverage && type <= Highlight_BelowStdDev3) { cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("aboveAverage"); if (type >= Highlight_BelowAverage && type <= Highlight_BelowStdDev3) cfRule->attrs[XlsxCfRuleData::A_aboveAverage] = QStringLiteral("0"); if (type == Highlight_AboveOrEqualAverage || type == Highlight_BelowOrEqualAverage) cfRule->attrs[XlsxCfRuleData::A_equalAverage] = QStringLiteral("1"); if (type == Highlight_AboveStdDev1 || type == Highlight_BelowStdDev1) cfRule->attrs[XlsxCfRuleData::A_stdDev] = QStringLiteral("1"); else if (type == Highlight_AboveStdDev2 || type == Highlight_BelowStdDev2) cfRule->attrs[XlsxCfRuleData::A_stdDev] = QStringLiteral("2"); else if (type == Highlight_AboveStdDev3 || type == Highlight_BelowStdDev3) cfRule->attrs[XlsxCfRuleData::A_stdDev] = QStringLiteral("3"); } else if (type == Highlight_Expression){ cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("expression"); } else { return false; } cfRule->dxfFormat = format; if (stopIfTrue) cfRule->attrs[XlsxCfRuleData::A_stopIfTrue] = true; if (!skipFormula) { if (!formula1.isEmpty()) cfRule->attrs[XlsxCfRuleData::A_formula1] = formula1.startsWith(QLatin1String("=")) ? formula1.mid(1) : formula1; if (!formula2.isEmpty()) cfRule->attrs[XlsxCfRuleData::A_formula2] = formula2.startsWith(QLatin1String("=")) ? formula2.mid(1) : formula2; } d->cfRules.append(cfRule); return true; } /*! * \overload * * Add a hightlight rule with the given \a type \a format and \a stopIfTrue. */ bool ConditionalFormatting::addHighlightCellsRule(HighlightRuleType type, const Format &format, bool stopIfTrue) { if ((type >= Highlight_AboveAverage && type <= Highlight_BelowStdDev3) || (type >= Highlight_Duplicate && type <= Highlight_NoErrors)) { return addHighlightCellsRule(type, QString(), QString(), format, stopIfTrue); } return false; } /*! * \overload * * Add a hightlight rule with the given \a type, \a formula, \a format and \a stopIfTrue. * Return false if failed. */ bool ConditionalFormatting::addHighlightCellsRule(HighlightRuleType type, const QString &formula, const Format &format, bool stopIfTrue) { if (type == Highlight_Between || type == Highlight_NotBetween) return false; return addHighlightCellsRule(type, formula, QString(), format, stopIfTrue); } /*! * Add a dataBar rule with the given \a color, \a type1, \a val1 * , \a type2, \a val2, \a showData and \a stopIfTrue. * Return false if failed. */ bool ConditionalFormatting::addDataBarRule(const QColor &color, ValueObjectType type1, const QString &val1, ValueObjectType type2, const QString &val2, bool showData, bool stopIfTrue) { QSharedPointer cfRule(new XlsxCfRuleData); cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("dataBar"); cfRule->attrs[XlsxCfRuleData::A_color1] = XlsxColor(color); if (stopIfTrue) cfRule->attrs[XlsxCfRuleData::A_stopIfTrue] = true; if (!showData) cfRule->attrs[XlsxCfRuleData::A_hideData] = true; XlsxCfVoData cfvo1(type1, val1); XlsxCfVoData cfvo2(type2, val2); cfRule->attrs[XlsxCfRuleData::A_cfvo1] = QVariant::fromValue(cfvo1); cfRule->attrs[XlsxCfRuleData::A_cfvo2] = QVariant::fromValue(cfvo2); d->cfRules.append(cfRule); return true; } /*! * \overload * Add a dataBar rule with the given \a color, \a showData and \a stopIfTrue. */ bool ConditionalFormatting::addDataBarRule(const QColor &color, bool showData, bool stopIfTrue) { return addDataBarRule(color, VOT_Min, QStringLiteral("0"), VOT_Max, QStringLiteral("0"), showData, stopIfTrue); } /*! * Add a colorScale rule with the given \a minColor, \a maxColor and \a stopIfTrue. * Return false if failed. */ bool ConditionalFormatting::add2ColorScaleRule(const QColor &minColor, const QColor &maxColor, bool stopIfTrue) { ValueObjectType type1 = VOT_Min; ValueObjectType type2 = VOT_Max; QString val1 = QStringLiteral("0"); QString val2 = QStringLiteral("0"); QSharedPointer cfRule(new XlsxCfRuleData); cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("colorScale"); cfRule->attrs[XlsxCfRuleData::A_color1] = XlsxColor(minColor); cfRule->attrs[XlsxCfRuleData::A_color2] = XlsxColor(maxColor); if (stopIfTrue) cfRule->attrs[XlsxCfRuleData::A_stopIfTrue] = true; XlsxCfVoData cfvo1(type1, val1); XlsxCfVoData cfvo2(type2, val2); cfRule->attrs[XlsxCfRuleData::A_cfvo1] = QVariant::fromValue(cfvo1); cfRule->attrs[XlsxCfRuleData::A_cfvo2] = QVariant::fromValue(cfvo2); d->cfRules.append(cfRule); return true; } /*! * Add a colorScale rule with the given \a minColor, \a midColor, \a maxColor and \a stopIfTrue. * Return false if failed. */ bool ConditionalFormatting::add3ColorScaleRule(const QColor &minColor, const QColor &midColor, const QColor &maxColor, bool stopIfTrue) { ValueObjectType type1 = VOT_Min; ValueObjectType type2 = VOT_Percent; ValueObjectType type3 = VOT_Max; QString val1 = QStringLiteral("0"); QString val2 = QStringLiteral("50"); QString val3 = QStringLiteral("0"); QSharedPointer cfRule(new XlsxCfRuleData); cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("colorScale"); cfRule->attrs[XlsxCfRuleData::A_color1] = XlsxColor(minColor); cfRule->attrs[XlsxCfRuleData::A_color2] = XlsxColor(midColor); cfRule->attrs[XlsxCfRuleData::A_color3] = XlsxColor(maxColor); if (stopIfTrue) cfRule->attrs[XlsxCfRuleData::A_stopIfTrue] = true; XlsxCfVoData cfvo1(type1, val1); XlsxCfVoData cfvo2(type2, val2); XlsxCfVoData cfvo3(type3, val3); cfRule->attrs[XlsxCfRuleData::A_cfvo1] = QVariant::fromValue(cfvo1); cfRule->attrs[XlsxCfRuleData::A_cfvo2] = QVariant::fromValue(cfvo2); cfRule->attrs[XlsxCfRuleData::A_cfvo3] = QVariant::fromValue(cfvo3); d->cfRules.append(cfRule); return true; } /*! Returns the ranges on which the validation will be applied. */ QList ConditionalFormatting::ranges() const { return d->ranges; } /*! Add the \a cell on which the conditional formatting will apply to. */ void ConditionalFormatting::addCell(const CellReference &cell) { d->ranges.append(CellRange(cell, cell)); } /*! \overload Add the cell(\a row, \a col) on which the conditional formatting will apply to. */ void ConditionalFormatting::addCell(int row, int col) { d->ranges.append(CellRange(row, col, row, col)); } /*! \overload Add the range(\a firstRow, \a firstCol, \a lastRow, \a lastCol) on which the conditional formatting will apply to. */ void ConditionalFormatting::addRange(int firstRow, int firstCol, int lastRow, int lastCol) { d->ranges.append(CellRange(firstRow, firstCol, lastRow, lastCol)); } /*! Add the \a range on which the conditional formatting will apply to. */ void ConditionalFormatting::addRange(const CellRange &range) { d->ranges.append(range); } bool ConditionalFormattingPrivate::readCfRule(QXmlStreamReader &reader, XlsxCfRuleData *rule, Styles *styles) { Q_ASSERT(reader.name() == QLatin1String("cfRule")); QXmlStreamAttributes attrs = reader.attributes(); if (attrs.hasAttribute(QLatin1String("type"))) rule->attrs[XlsxCfRuleData::A_type] = attrs.value(QLatin1String("type")).toString(); if (attrs.hasAttribute(QLatin1String("dxfId"))) { int id = attrs.value(QLatin1String("dxfId")).toString().toInt(); if (styles) rule->dxfFormat = styles->dxfFormat(id); else rule->dxfFormat.setDxfIndex(id); } rule->priority = attrs.value(QLatin1String("priority")).toString().toInt(); if (attrs.value(QLatin1String("stopIfTrue")) == QLatin1String("1")) { //default is false rule->attrs[XlsxCfRuleData::A_stopIfTrue] = QLatin1String("1"); } if (attrs.value(QLatin1String("aboveAverage")) == QLatin1String("0")) { //default is true rule->attrs[XlsxCfRuleData::A_aboveAverage] = QLatin1String("0"); } if (attrs.value(QLatin1String("percent")) == QLatin1String("1")) { //default is false rule->attrs[XlsxCfRuleData::A_percent] = QLatin1String("1"); } if (attrs.value(QLatin1String("bottom")) == QLatin1String("1")) { //default is false rule->attrs[XlsxCfRuleData::A_bottom] = QLatin1String("1"); } if (attrs.hasAttribute(QLatin1String("operator"))) rule->attrs[XlsxCfRuleData::A_operator] = attrs.value(QLatin1String("operator")).toString(); if (attrs.hasAttribute(QLatin1String("text"))) rule->attrs[XlsxCfRuleData::A_text] = attrs.value(QLatin1String("text")).toString(); if (attrs.hasAttribute(QLatin1String("timePeriod"))) rule->attrs[XlsxCfRuleData::A_timePeriod] = attrs.value(QLatin1String("timePeriod")).toString(); if (attrs.hasAttribute(QLatin1String("rank"))) rule->attrs[XlsxCfRuleData::A_rank] = attrs.value(QLatin1String("rank")).toString(); if (attrs.hasAttribute(QLatin1String("stdDev"))) rule->attrs[XlsxCfRuleData::A_stdDev] = attrs.value(QLatin1String("stdDev")).toString(); if (attrs.value(QLatin1String("equalAverage")) == QLatin1String("1")) { //default is false rule->attrs[XlsxCfRuleData::A_equalAverage] = QLatin1String("1"); } while (!reader.atEnd()) { reader.readNextStartElement(); if (reader.tokenType() == QXmlStreamReader::StartElement) { if (reader.name() == QLatin1String("formula")) { const QString f = reader.readElementText(); if (!rule->attrs.contains(XlsxCfRuleData::A_formula1)) rule->attrs[XlsxCfRuleData::A_formula1] = f; else if (!rule->attrs.contains(XlsxCfRuleData::A_formula2)) rule->attrs[XlsxCfRuleData::A_formula2] = f; else if (!rule->attrs.contains(XlsxCfRuleData::A_formula3)) rule->attrs[XlsxCfRuleData::A_formula3] = f; } else if (reader.name() == QLatin1String("dataBar")) { readCfDataBar(reader, rule); } else if (reader.name() == QLatin1String("colorScale")) { readCfColorScale(reader, rule); } } if (reader.tokenType() == QXmlStreamReader::EndElement && reader.name() == QStringLiteral("conditionalFormatting")) { break; } } return true; } bool ConditionalFormattingPrivate::readCfDataBar(QXmlStreamReader &reader, XlsxCfRuleData *rule) { Q_ASSERT(reader.name() == QLatin1String("dataBar")); QXmlStreamAttributes attrs = reader.attributes(); if (attrs.value(QLatin1String("showValue")) == QLatin1String("0")) rule->attrs[XlsxCfRuleData::A_hideData] = QStringLiteral("1"); while (!reader.atEnd()) { reader.readNextStartElement(); if (reader.tokenType() == QXmlStreamReader::StartElement) { if (reader.name() == QLatin1String("cfvo")) { XlsxCfVoData data; readCfVo(reader, data); if (!rule->attrs.contains(XlsxCfRuleData::A_cfvo1)) rule->attrs[XlsxCfRuleData::A_cfvo1] = QVariant::fromValue(data); else rule->attrs[XlsxCfRuleData::A_cfvo2] = QVariant::fromValue(data); } else if (reader.name() == QLatin1String("color")) { XlsxColor color; color.loadFromXml(reader); rule->attrs[XlsxCfRuleData::A_color1] = color; } } if (reader.tokenType() == QXmlStreamReader::EndElement && reader.name() == QStringLiteral("dataBar")) { break; } } return true; } bool ConditionalFormattingPrivate::readCfColorScale(QXmlStreamReader &reader, XlsxCfRuleData *rule) { Q_ASSERT(reader.name() == QLatin1String("colorScale")); while (!reader.atEnd()) { reader.readNextStartElement(); if (reader.tokenType() == QXmlStreamReader::StartElement) { if (reader.name() == QLatin1String("cfvo")) { XlsxCfVoData data; readCfVo(reader, data); if (!rule->attrs.contains(XlsxCfRuleData::A_cfvo1)) rule->attrs[XlsxCfRuleData::A_cfvo1] = QVariant::fromValue(data); else if (!rule->attrs.contains(XlsxCfRuleData::A_cfvo2)) rule->attrs[XlsxCfRuleData::A_cfvo2] = QVariant::fromValue(data); else rule->attrs[XlsxCfRuleData::A_cfvo2] = QVariant::fromValue(data); } else if (reader.name() == QLatin1String("color")) { XlsxColor color; color.loadFromXml(reader); if (!rule->attrs.contains(XlsxCfRuleData::A_color1)) rule->attrs[XlsxCfRuleData::A_color1] = color; else if (!rule->attrs.contains(XlsxCfRuleData::A_color2)) rule->attrs[XlsxCfRuleData::A_color2] = color; else rule->attrs[XlsxCfRuleData::A_color3] = color; } } if (reader.tokenType() == QXmlStreamReader::EndElement && reader.name() == QStringLiteral("colorScale")) { break; } } return true; } bool ConditionalFormattingPrivate::readCfVo(QXmlStreamReader &reader, XlsxCfVoData &cfvo) { Q_ASSERT(reader.name() == QStringLiteral("cfvo")); QXmlStreamAttributes attrs = reader.attributes(); QString type = attrs.value(QLatin1String("type")).toString(); ConditionalFormatting::ValueObjectType t; if (type == QLatin1String("formula")) t = ConditionalFormatting::VOT_Formula; else if (type == QLatin1String("max")) t = ConditionalFormatting::VOT_Max; else if (type == QLatin1String("min")) t = ConditionalFormatting::VOT_Min; else if (type == QLatin1String("num")) t = ConditionalFormatting::VOT_Num; else if (type == QLatin1String("percent")) t = ConditionalFormatting::VOT_Percent; else //if (type == QLatin1String("percentile")) t = ConditionalFormatting::VOT_Percentile; cfvo.type = t; cfvo.value = attrs.value(QLatin1String("val")).toString(); if (attrs.value(QLatin1String("gte")) == QLatin1String("0")) { //default is true cfvo.gte = false; } return true; } bool ConditionalFormatting::loadFromXml(QXmlStreamReader &reader, Styles *styles) { Q_ASSERT(reader.name() == QStringLiteral("conditionalFormatting")); d->ranges.clear(); d->cfRules.clear(); QXmlStreamAttributes attrs = reader.attributes(); const QString sqref = attrs.value(QLatin1String("sqref")).toString(); const auto sqrefParts = sqref.split(QLatin1Char(' ')); for (const QString &range : sqrefParts) { this->addRange(range); } while (!reader.atEnd()) { reader.readNextStartElement(); if (reader.tokenType() == QXmlStreamReader::StartElement) { if (reader.name() == QLatin1String("cfRule")) { QSharedPointer cfRule(new XlsxCfRuleData); d->readCfRule(reader, cfRule.data(), styles); d->cfRules.append(cfRule); } } if (reader.tokenType() == QXmlStreamReader::EndElement && reader.name() == QStringLiteral("conditionalFormatting")) { break; } } return true; } bool ConditionalFormatting::saveToXml(QXmlStreamWriter &writer) const { writer.writeStartElement(QStringLiteral("conditionalFormatting")); QStringList sqref; const auto rangeList = ranges(); for (const CellRange &range : rangeList) { sqref.append(range.toString()); } writer.writeAttribute(QStringLiteral("sqref"), sqref.join(QLatin1String(" "))); for (int i=0; icfRules.size(); ++i) { const QSharedPointer &rule = d->cfRules[i]; writer.writeStartElement(QStringLiteral("cfRule")); writer.writeAttribute(QStringLiteral("type"), rule->attrs[XlsxCfRuleData::A_type].toString()); if (rule->dxfFormat.dxfIndexValid()) writer.writeAttribute(QStringLiteral("dxfId"), QString::number(rule->dxfFormat.dxfIndex())); writer.writeAttribute(QStringLiteral("priority"), QString::number(rule->priority)); auto it = rule->attrs.constFind(XlsxCfRuleData::A_stopIfTrue); if (it != rule->attrs.constEnd()) writer.writeAttribute(QStringLiteral("stopIfTrue"), it.value().toString()); it = rule->attrs.constFind(XlsxCfRuleData::A_aboveAverage); if (it != rule->attrs.constEnd()) writer.writeAttribute(QStringLiteral("aboveAverage"), it.value().toString()); it = rule->attrs.constFind(XlsxCfRuleData::A_percent); if (it != rule->attrs.constEnd()) writer.writeAttribute(QStringLiteral("percent"), it.value().toString()); it = rule->attrs.constFind(XlsxCfRuleData::A_bottom); if (it != rule->attrs.constEnd()) writer.writeAttribute(QStringLiteral("bottom"), it.value().toString()); it = rule->attrs.constFind(XlsxCfRuleData::A_operator); if (it != rule->attrs.constEnd()) writer.writeAttribute(QStringLiteral("operator"), it.value().toString()); it = rule->attrs.constFind(XlsxCfRuleData::A_text); if (it != rule->attrs.constEnd()) writer.writeAttribute(QStringLiteral("text"), it.value().toString()); it = rule->attrs.constFind(XlsxCfRuleData::A_timePeriod); if (it != rule->attrs.constEnd()) writer.writeAttribute(QStringLiteral("timePeriod"), it.value().toString()); it = rule->attrs.constFind(XlsxCfRuleData::A_rank); if (it != rule->attrs.constEnd()) writer.writeAttribute(QStringLiteral("rank"), it.value().toString()); it = rule->attrs.constFind(XlsxCfRuleData::A_stdDev); if (it != rule->attrs.constEnd()) writer.writeAttribute(QStringLiteral("stdDev"), it.value().toString()); it = rule->attrs.constFind(XlsxCfRuleData::A_equalAverage); if (it != rule->attrs.constEnd()) writer.writeAttribute(QStringLiteral("equalAverage"), it.value().toString()); if (rule->attrs[XlsxCfRuleData::A_type] == QLatin1String("dataBar")) { writer.writeStartElement(QStringLiteral("dataBar")); if (rule->attrs.contains(XlsxCfRuleData::A_hideData)) writer.writeAttribute(QStringLiteral("showValue"), QStringLiteral("0")); d->writeCfVo(writer, rule->attrs[XlsxCfRuleData::A_cfvo1].value()); d->writeCfVo(writer, rule->attrs[XlsxCfRuleData::A_cfvo2].value()); rule->attrs[XlsxCfRuleData::A_color1].value().saveToXml(writer); writer.writeEndElement();//dataBar } else if (rule->attrs[XlsxCfRuleData::A_type] == QLatin1String("colorScale")) { writer.writeStartElement(QStringLiteral("colorScale")); d->writeCfVo(writer, rule->attrs[XlsxCfRuleData::A_cfvo1].value()); d->writeCfVo(writer, rule->attrs[XlsxCfRuleData::A_cfvo2].value()); it = rule->attrs.constFind(XlsxCfRuleData::A_cfvo3); if (it != rule->attrs.constEnd()) d->writeCfVo(writer, it.value().value()); rule->attrs[XlsxCfRuleData::A_color1].value().saveToXml(writer); rule->attrs[XlsxCfRuleData::A_color2].value().saveToXml(writer); it = rule->attrs.constFind(XlsxCfRuleData::A_color3); if (it != rule->attrs.constEnd()) it.value().value().saveToXml(writer); writer.writeEndElement();//colorScale } it = rule->attrs.constFind(XlsxCfRuleData::A_formula1_temp); if (it != rule->attrs.constEnd()) { QString str = ( ranges().begin() )->toString(); QString startCell = *( str.split(QLatin1Char(':')).begin() ); writer.writeTextElement(QStringLiteral("formula"), it.value().toString().arg(startCell)); } else if ((it = rule->attrs.constFind(XlsxCfRuleData::A_formula1)) != rule->attrs.constEnd()) { writer.writeTextElement(QStringLiteral("formula"), it.value().toString()); } it = rule->attrs.constFind(XlsxCfRuleData::A_formula2); if (it != rule->attrs.constEnd()) writer.writeTextElement(QStringLiteral("formula"), it.value().toString()); it = rule->attrs.constFind(XlsxCfRuleData::A_formula3); if (it != rule->attrs.constEnd()) writer.writeTextElement(QStringLiteral("formula"), it.value().toString()); writer.writeEndElement(); //cfRule } writer.writeEndElement(); //conditionalFormatting return true; } QT_END_NAMESPACE_XLSX