diff --git a/examples/xlsx/conditionalformatting/main.cpp b/examples/xlsx/conditionalformatting/main.cpp index 7beab28..298238d 100644 --- a/examples/xlsx/conditionalformatting/main.cpp +++ b/examples/xlsx/conditionalformatting/main.cpp @@ -67,8 +67,10 @@ int main() //![cf5] //![2] - xlsx.save(); + xlsx.saveAs("Book1.xlsx"); //![2] + Document xlsx2("Book1.xlsx"); + xlsx2.saveAs("Book2.xlsx"); return 0; } diff --git a/src/xlsx/xlsxconditionalformatting.cpp b/src/xlsx/xlsxconditionalformatting.cpp index 031aa58..f933fa5 100644 --- a/src/xlsx/xlsxconditionalformatting.cpp +++ b/src/xlsx/xlsxconditionalformatting.cpp @@ -27,6 +27,7 @@ #include "xlsxconditionalformatting_p.h" #include "xlsxworksheet.h" #include "xlsxcellrange.h" +#include "xlsxstyles_p.h" #include #include @@ -50,7 +51,7 @@ ConditionalFormattingPrivate::~ConditionalFormattingPrivate() } -void ConditionalFormattingPrivate::writeCfVo(const XlsxCfVoData &cfvo, QXmlStreamWriter &writer) const +void ConditionalFormattingPrivate::writeCfVo(QXmlStreamWriter &writer, const XlsxCfVoData &cfvo) const { writer.writeEmptyElement(QStringLiteral("cfvo")); QString type; @@ -443,11 +444,207 @@ void ConditionalFormatting::addRange(const CellRange &range) d->ranges.append(range); } -bool ConditionalFormatting::loadFromXml(QXmlStreamReader &reader) const +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")) { + 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, styles); + } else if (reader.name() == QLatin1String("colorScale")) { + readCfColorScale(reader, rule, styles); + } + } + if (reader.tokenType() == QXmlStreamReader::EndElement + && reader.name() == QStringLiteral("conditionalFormatting")) { + break; + } + } + return true; +} + +bool ConditionalFormattingPrivate::readCfDataBar(QXmlStreamReader &reader, XlsxCfRuleData *rule, Styles *styles) +{ + 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, styles); + 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, Styles *styles) +{ + 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, styles); + 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")); - return false; + d->ranges.clear(); + d->cfRules.clear(); + QXmlStreamAttributes attrs = reader.attributes(); + QString sqref = attrs.value(QLatin1String("sqref")).toString(); + foreach (QString range, sqref.split(QLatin1Char(' '))) + 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 @@ -490,16 +687,16 @@ bool ConditionalFormatting::saveToXml(QXmlStreamWriter &writer) const writer.writeStartElement(QStringLiteral("dataBar")); if (rule->attrs.contains(XlsxCfRuleData::A_hideData)) writer.writeAttribute(QStringLiteral("showValue"), QStringLiteral("0")); - d->writeCfVo(rule->attrs[XlsxCfRuleData::A_cfvo1].value(), writer); - d->writeCfVo(rule->attrs[XlsxCfRuleData::A_cfvo2].value(), writer); + 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(rule->attrs[XlsxCfRuleData::A_cfvo1].value(), writer); - d->writeCfVo(rule->attrs[XlsxCfRuleData::A_cfvo2].value(), writer); + d->writeCfVo(writer, rule->attrs[XlsxCfRuleData::A_cfvo1].value()); + d->writeCfVo(writer, rule->attrs[XlsxCfRuleData::A_cfvo2].value()); if (rule->attrs.contains(XlsxCfRuleData::A_cfvo3)) - d->writeCfVo(rule->attrs[XlsxCfRuleData::A_cfvo3].value(), writer); + d->writeCfVo(writer, rule->attrs[XlsxCfRuleData::A_cfvo3].value()); rule->attrs[XlsxCfRuleData::A_color1].value().saveToXml(writer); rule->attrs[XlsxCfRuleData::A_color2].value().saveToXml(writer); diff --git a/src/xlsx/xlsxconditionalformatting.h b/src/xlsx/xlsxconditionalformatting.h index 0644873..25289f2 100644 --- a/src/xlsx/xlsxconditionalformatting.h +++ b/src/xlsx/xlsxconditionalformatting.h @@ -40,6 +40,7 @@ QT_BEGIN_NAMESPACE_XLSX class CellRange; class Format; class Worksheet; +class Styles; class ConditionalFormattingPrivate; class Q_XLSX_EXPORT ConditionalFormatting @@ -125,7 +126,7 @@ private: friend class Worksheet; friend class ::ConditionalFormattingTest; bool saveToXml(QXmlStreamWriter &writer) const; - bool loadFromXml(QXmlStreamReader &reader) const; + bool loadFromXml(QXmlStreamReader &reader, Styles *styles=0); QSharedDataPointer d; }; diff --git a/src/xlsx/xlsxconditionalformatting_p.h b/src/xlsx/xlsxconditionalformatting_p.h index 149c7d7..ff78d90 100644 --- a/src/xlsx/xlsxconditionalformatting_p.h +++ b/src/xlsx/xlsxconditionalformatting_p.h @@ -115,7 +115,11 @@ public: ConditionalFormattingPrivate(const ConditionalFormattingPrivate &other); ~ConditionalFormattingPrivate(); - void writeCfVo(const XlsxCfVoData& cfvo, QXmlStreamWriter &writer) const; + void writeCfVo(QXmlStreamWriter &writer, const XlsxCfVoData& cfvo) const; + bool readCfVo(QXmlStreamReader &reader, XlsxCfVoData& cfvo); + bool readCfRule(QXmlStreamReader &reader, XlsxCfRuleData *cfRule, Styles *styles); + bool readCfDataBar(QXmlStreamReader &reader, XlsxCfRuleData *cfRule, Styles *styles); + bool readCfColorScale(QXmlStreamReader &reader, XlsxCfRuleData *cfRule, Styles *styles); QList >cfRules; QList ranges; diff --git a/src/xlsx/xlsxstyles.cpp b/src/xlsx/xlsxstyles.cpp index 2024ae0..e38d1c2 100755 --- a/src/xlsx/xlsxstyles.cpp +++ b/src/xlsx/xlsxstyles.cpp @@ -1266,6 +1266,8 @@ bool Styles::loadFromXmlFile(QIODevice *device) readCellXfs(reader); } else if (reader.name() == QLatin1String("cellStyles")) { + } else if (reader.name() == QLatin1String("dxfs")) { + readDxfs(reader); } } diff --git a/src/xlsx/xlsxworksheet.cpp b/src/xlsx/xlsxworksheet.cpp index cfd9421..4082c89 100755 --- a/src/xlsx/xlsxworksheet.cpp +++ b/src/xlsx/xlsxworksheet.cpp @@ -2255,6 +2255,10 @@ bool Worksheet::loadFromXmlFile(QIODevice *device) d->readMergeCells(reader); } else if (reader.name() == QLatin1String("dataValidations")) { d->readDataValidations(reader); + } else if (reader.name() == QLatin1String("conditionalFormatting")) { + ConditionalFormatting cf; + cf.loadFromXml(reader, workbook()->styles()); + d->conditionalFormattingList.append(cf); } } }