18 changed files with 844 additions and 7 deletions
@ -0,0 +1,9 @@ |
|||||
|
TARGET = hello |
||||
|
|
||||
|
#include(../../../src/xlsx/qtxlsx.pri) |
||||
|
QT+=xlsx |
||||
|
|
||||
|
CONFIG += console |
||||
|
CONFIG -= app_bundle |
||||
|
|
||||
|
SOURCES += main.cpp |
@ -0,0 +1,10 @@ |
|||||
|
/*! |
||||
|
\example conditionalformatting |
||||
|
\title Conditional Formatting Example |
||||
|
\brief This is a conditional formatting example. |
||||
|
\ingroup qtxlsx-examples |
||||
|
|
||||
|
This example demonstrates how to create a new |
||||
|
.xlsx file containin conditional formatting |
||||
|
with Qt Xlsx Library. So lets see how this is achieved. |
||||
|
*/ |
@ -0,0 +1,56 @@ |
|||||
|
#include <QtCore> |
||||
|
#include "xlsxdocument.h" |
||||
|
#include "xlsxconditionalformatting.h" |
||||
|
|
||||
|
using namespace QXlsx; |
||||
|
|
||||
|
int main() |
||||
|
{ |
||||
|
//![0]
|
||||
|
Document xlsx; |
||||
|
Format hFmt; |
||||
|
hFmt.setFontBold(true); |
||||
|
xlsx.write("B1", "(-inf,40)", hFmt); |
||||
|
xlsx.write("D1", "[30,70]", hFmt); |
||||
|
|
||||
|
for (int row=3; row<22; ++row) { |
||||
|
for (int col=2; col<22; ++col) |
||||
|
xlsx.write(row, col, qrand() % 100); |
||||
|
} |
||||
|
//![0]
|
||||
|
|
||||
|
//![1]
|
||||
|
ConditionalFormatting cf1; |
||||
|
Format fmt1; |
||||
|
fmt1.setFontColor(Qt::green); |
||||
|
fmt1.setBorderStyle(Format::BorderDashed); |
||||
|
cf1.addHighlightCellsRule(ConditionalFormatting::Highlight_LessThan, "40", fmt1); |
||||
|
cf1.addRange("B3:B21"); |
||||
|
xlsx.addConditionalFormatting(cf1); |
||||
|
//![1]
|
||||
|
|
||||
|
//![cf2]
|
||||
|
ConditionalFormatting cf2; |
||||
|
Format fmt2; |
||||
|
fmt2.setBorderStyle(Format::BorderDotted); |
||||
|
fmt2.setBorderColor(Qt::blue); |
||||
|
cf2.addHighlightCellsRule(ConditionalFormatting::Highlight_Between, "30", "70", fmt2); |
||||
|
cf2.addRange("D3:D21"); |
||||
|
xlsx.addConditionalFormatting(cf2); |
||||
|
//![cf2]
|
||||
|
|
||||
|
//![cf3]
|
||||
|
ConditionalFormatting cf3; |
||||
|
Format fmt3; |
||||
|
fmt3.setFontStrikeOut(true); |
||||
|
cf3.addHighlightCellsRule(ConditionalFormatting::Highlight_BeginsWith, "2", fmt3); |
||||
|
cf3.addRange("F3:F21"); |
||||
|
xlsx.addConditionalFormatting(cf3); |
||||
|
//![cf3]
|
||||
|
|
||||
|
//![2]
|
||||
|
xlsx.save(); |
||||
|
//![2]
|
||||
|
|
||||
|
return 0; |
||||
|
} |
@ -0,0 +1,392 @@ |
|||||
|
/****************************************************************************
|
||||
|
** Copyright (c) 2013 Debao Zhang <hello@debao.me> |
||||
|
** All right reserved. |
||||
|
** |
||||
|
** Permission is hereby granted, free of charge, to any person obtaining |
||||
|
** a copy of this software and associated documentation files (the |
||||
|
** "Software"), to deal in the Software without restriction, including |
||||
|
** without limitation the rights to use, copy, modify, merge, publish, |
||||
|
** distribute, sublicense, and/or sell copies of the Software, and to |
||||
|
** permit persons to whom the Software is furnished to do so, subject to |
||||
|
** the following conditions: |
||||
|
** |
||||
|
** The above copyright notice and this permission notice shall be |
||||
|
** included in all copies or substantial portions of the Software. |
||||
|
** |
||||
|
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
||||
|
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
||||
|
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
||||
|
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
||||
|
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
||||
|
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
||||
|
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||||
|
** |
||||
|
****************************************************************************/ |
||||
|
|
||||
|
#include "xlsxconditionalformatting.h" |
||||
|
#include "xlsxconditionalformatting_p.h" |
||||
|
#include "xlsxworksheet.h" |
||||
|
#include "xlsxcellrange.h" |
||||
|
|
||||
|
#include <QXmlStreamReader> |
||||
|
#include <QXmlStreamWriter> |
||||
|
#include <QDebug> |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
ConditionalFormattingPrivate::ConditionalFormattingPrivate() |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
ConditionalFormattingPrivate::ConditionalFormattingPrivate(const ConditionalFormattingPrivate &other) |
||||
|
:QSharedData(other) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
ConditionalFormattingPrivate::~ConditionalFormattingPrivate() |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* \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_SatisfyFormula |
||||
|
*/ |
||||
|
|
||||
|
/*!
|
||||
|
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. |
||||
|
*/ |
||||
|
bool ConditionalFormatting::addHighlightCellsRule(HighlightRuleType type, const QString &formula1, const QString &formula2, const Format &format, bool stopIfTrue) |
||||
|
{ |
||||
|
if (format.isEmpty()) |
||||
|
return false; |
||||
|
|
||||
|
bool skipFormula1 = false; |
||||
|
|
||||
|
QSharedPointer<XlsxCfRuleData> 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; |
||||
|
skipFormula1 = 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)"); |
||||
|
skipFormula1 = true; |
||||
|
} else if (type == Highlight_NoErrors) { |
||||
|
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("notContainsErrors"); |
||||
|
cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("NOT(ISERROR(%1))"); |
||||
|
skipFormula1 = true; |
||||
|
} else if (type == Highlight_Blanks) { |
||||
|
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("containsBlanks"); |
||||
|
cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("LEN(TRIM(%1))=0"); |
||||
|
skipFormula1 = true; |
||||
|
} else if (type == Highlight_NoBlanks) { |
||||
|
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("notContainsBlanks"); |
||||
|
cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("LEN(TRIM(%1))>0"); |
||||
|
skipFormula1 = 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"); |
||||
|
skipFormula1 = 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 { |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
cfRule->dxfFormat = format; |
||||
|
if (stopIfTrue) |
||||
|
cfRule->attrs[XlsxCfRuleData::A_stopIfTrue] = true; |
||||
|
if (!formula1.isEmpty() && !skipFormula1) |
||||
|
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. |
||||
|
*/ |
||||
|
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); |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Returns the ranges on which the validation will be applied. |
||||
|
*/ |
||||
|
QList<CellRange> ConditionalFormatting::ranges() const |
||||
|
{ |
||||
|
return d->ranges; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Add the \a cell on which the conditional formatting will apply to. |
||||
|
*/ |
||||
|
void ConditionalFormatting::addCell(const QString &cell) |
||||
|
{ |
||||
|
d->ranges.append(CellRange(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)); |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Add the \a range on which the conditional formatting will apply to. |
||||
|
*/ |
||||
|
void ConditionalFormatting::addRange(const QString &range) |
||||
|
{ |
||||
|
d->ranges.append(CellRange(range)); |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
\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)); |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
\overload |
||||
|
Add the \a range on which the conditional formatting will apply to. |
||||
|
*/ |
||||
|
void ConditionalFormatting::addRange(const CellRange &range) |
||||
|
{ |
||||
|
d->ranges.append(range); |
||||
|
} |
||||
|
|
||||
|
bool ConditionalFormatting::loadFromXml(QXmlStreamReader &reader) const |
||||
|
{ |
||||
|
Q_ASSERT(reader.name() == QStringLiteral("conditionalFormatting")); |
||||
|
|
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
bool ConditionalFormatting::saveToXml(QXmlStreamWriter &writer) const |
||||
|
{ |
||||
|
writer.writeStartElement(QStringLiteral("conditionalFormatting")); |
||||
|
QStringList sqref; |
||||
|
foreach (CellRange range, ranges()) |
||||
|
sqref.append(range.toString()); |
||||
|
writer.writeAttribute(QStringLiteral("sqref"), sqref.join(QLatin1Char(' '))); |
||||
|
|
||||
|
for (int i=0; i<d->cfRules.size(); ++i) { |
||||
|
const QSharedPointer<XlsxCfRuleData> &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)); |
||||
|
if (rule->attrs.contains(XlsxCfRuleData::A_stopIfTrue)) |
||||
|
writer.writeAttribute(QStringLiteral("stopIfTrue"), rule->attrs[XlsxCfRuleData::A_stopIfTrue].toString()); |
||||
|
if (rule->attrs.contains(XlsxCfRuleData::A_aboveAverage)) |
||||
|
writer.writeAttribute(QStringLiteral("aboveAverage"), rule->attrs[XlsxCfRuleData::A_aboveAverage].toString()); |
||||
|
if (rule->attrs.contains(XlsxCfRuleData::A_percent)) |
||||
|
writer.writeAttribute(QStringLiteral("percent"), rule->attrs[XlsxCfRuleData::A_percent].toString()); |
||||
|
if (rule->attrs.contains(XlsxCfRuleData::A_bottom)) |
||||
|
writer.writeAttribute(QStringLiteral("bottom"), rule->attrs[XlsxCfRuleData::A_bottom].toString()); |
||||
|
if (rule->attrs.contains(XlsxCfRuleData::A_operator)) |
||||
|
writer.writeAttribute(QStringLiteral("operator"), rule->attrs[XlsxCfRuleData::A_operator].toString()); |
||||
|
if (rule->attrs.contains(XlsxCfRuleData::A_text)) |
||||
|
writer.writeAttribute(QStringLiteral("text"), rule->attrs[XlsxCfRuleData::A_text].toString()); |
||||
|
if (rule->attrs.contains(XlsxCfRuleData::A_timePeriod)) |
||||
|
writer.writeAttribute(QStringLiteral("timePeriod"), rule->attrs[XlsxCfRuleData::A_timePeriod].toString()); |
||||
|
if (rule->attrs.contains(XlsxCfRuleData::A_rank)) |
||||
|
writer.writeAttribute(QStringLiteral("rank"), rule->attrs[XlsxCfRuleData::A_rank].toString()); |
||||
|
if (rule->attrs.contains(XlsxCfRuleData::A_stdDev)) |
||||
|
writer.writeAttribute(QStringLiteral("stdDev"), rule->attrs[XlsxCfRuleData::A_stdDev].toString()); |
||||
|
if (rule->attrs.contains(XlsxCfRuleData::A_equalAverage)) |
||||
|
writer.writeAttribute(QStringLiteral("equalAverage"), rule->attrs[XlsxCfRuleData::A_equalAverage].toString()); |
||||
|
|
||||
|
if (rule->attrs.contains(XlsxCfRuleData::A_formula1_temp)) { |
||||
|
QString startCell = ranges()[0].toString().split(QLatin1Char(':'))[0]; |
||||
|
writer.writeTextElement(QStringLiteral("formula"), rule->attrs[XlsxCfRuleData::A_formula1_temp].toString().arg(startCell)); |
||||
|
} else if (rule->attrs.contains(XlsxCfRuleData::A_formula1)) { |
||||
|
writer.writeTextElement(QStringLiteral("formula"), rule->attrs[XlsxCfRuleData::A_formula1].toString()); |
||||
|
} |
||||
|
if (rule->attrs.contains(XlsxCfRuleData::A_formula2)) |
||||
|
writer.writeTextElement(QStringLiteral("formula"), rule->attrs[XlsxCfRuleData::A_formula2].toString()); |
||||
|
if (rule->attrs.contains(XlsxCfRuleData::A_formula3)) |
||||
|
writer.writeTextElement(QStringLiteral("formula"), rule->attrs[XlsxCfRuleData::A_formula3].toString()); |
||||
|
|
||||
|
writer.writeEndElement(); //cfRule
|
||||
|
} |
||||
|
|
||||
|
writer.writeEndElement(); //conditionalFormatting
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
@ -0,0 +1,119 @@ |
|||||
|
/****************************************************************************
|
||||
|
** Copyright (c) 2013 Debao Zhang <hello@debao.me> |
||||
|
** All right reserved. |
||||
|
** |
||||
|
** Permission is hereby granted, free of charge, to any person obtaining |
||||
|
** a copy of this software and associated documentation files (the |
||||
|
** "Software"), to deal in the Software without restriction, including |
||||
|
** without limitation the rights to use, copy, modify, merge, publish, |
||||
|
** distribute, sublicense, and/or sell copies of the Software, and to |
||||
|
** permit persons to whom the Software is furnished to do so, subject to |
||||
|
** the following conditions: |
||||
|
** |
||||
|
** The above copyright notice and this permission notice shall be |
||||
|
** included in all copies or substantial portions of the Software. |
||||
|
** |
||||
|
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
||||
|
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
||||
|
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
||||
|
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
||||
|
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
||||
|
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
||||
|
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||||
|
** |
||||
|
****************************************************************************/ |
||||
|
#ifndef QXLSX_XLSXCONDITIONALFORMATTING_H |
||||
|
#define QXLSX_XLSXCONDITIONALFORMATTING_H |
||||
|
|
||||
|
#include "xlsxglobal.h" |
||||
|
#include <QSharedDataPointer> |
||||
|
#include <QString> |
||||
|
#include <QList> |
||||
|
|
||||
|
class QXmlStreamReader; |
||||
|
class QXmlStreamWriter; |
||||
|
class ConditionalFormattingTest; |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class CellRange; |
||||
|
class Format; |
||||
|
class Worksheet; |
||||
|
|
||||
|
class ConditionalFormattingPrivate; |
||||
|
class Q_XLSX_EXPORT ConditionalFormatting |
||||
|
{ |
||||
|
public: |
||||
|
enum HighlightRuleType { |
||||
|
Highlight_LessThan, |
||||
|
Highlight_LessThanOrEqual, |
||||
|
Highlight_Equal, |
||||
|
Highlight_NotEqual, |
||||
|
Highlight_GreaterThanOrEqual, |
||||
|
Highlight_GreaterThan, |
||||
|
Highlight_Between, |
||||
|
Highlight_NotBetween, |
||||
|
|
||||
|
Highlight_ContainsText, |
||||
|
Highlight_NotContainsText, |
||||
|
Highlight_BeginsWith, |
||||
|
Highlight_EndsWith, |
||||
|
|
||||
|
Highlight_TimePeriod, |
||||
|
|
||||
|
Highlight_Duplicate, |
||||
|
Highlight_Unique, |
||||
|
Highlight_Blanks, |
||||
|
Highlight_NoBlanks, |
||||
|
Highlight_Errors, |
||||
|
Highlight_NoErrors, |
||||
|
|
||||
|
Highlight_Top, |
||||
|
Highlight_TopPercent, |
||||
|
Highlight_Bottom, |
||||
|
Highlight_BottomPercent, |
||||
|
|
||||
|
Highlight_AboveAverage, |
||||
|
Highlight_AboveOrEqualAverage, |
||||
|
Highlight_AboveStdDev1, |
||||
|
Highlight_AboveStdDev2, |
||||
|
Highlight_AboveStdDev3, |
||||
|
Highlight_BelowAverage, |
||||
|
Highlight_BelowOrEqualAverage, |
||||
|
Highlight_BelowStdDev1, |
||||
|
Highlight_BelowStdDev2, |
||||
|
Highlight_BelowStdDev3, |
||||
|
|
||||
|
Highlight_Expression |
||||
|
}; |
||||
|
|
||||
|
ConditionalFormatting(); |
||||
|
ConditionalFormatting(const ConditionalFormatting &other); |
||||
|
~ConditionalFormatting(); |
||||
|
|
||||
|
bool addHighlightCellsRule(HighlightRuleType type, const Format &format, bool stopIfTrue=false); |
||||
|
bool addHighlightCellsRule(HighlightRuleType type, const QString &formula1, const Format &format, bool stopIfTrue=false); |
||||
|
bool addHighlightCellsRule(HighlightRuleType type, const QString &formula1, const QString &formula2, const Format &format, bool stopIfTrue=false); |
||||
|
|
||||
|
QList<CellRange> ranges() const; |
||||
|
|
||||
|
void addCell(const QString &cell); |
||||
|
void addCell(int row, int col); |
||||
|
void addRange(const QString &range); |
||||
|
void addRange(int firstRow, int firstCol, int lastRow, int lastCol); |
||||
|
void addRange(const CellRange &range); |
||||
|
|
||||
|
//needed by QSharedDataPointer!!
|
||||
|
ConditionalFormatting &operator=(const ConditionalFormatting &other); |
||||
|
|
||||
|
private: |
||||
|
friend class Worksheet; |
||||
|
friend class ::ConditionalFormattingTest; |
||||
|
bool saveToXml(QXmlStreamWriter &writer) const; |
||||
|
bool loadFromXml(QXmlStreamReader &reader) const; |
||||
|
QSharedDataPointer<ConditionalFormattingPrivate> d; |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
|
||||
|
#endif // QXLSX_XLSXCONDITIONALFORMATTING_H
|
@ -0,0 +1,94 @@ |
|||||
|
/****************************************************************************
|
||||
|
** Copyright (c) 2013 Debao Zhang <hello@debao.me> |
||||
|
** All right reserved. |
||||
|
** |
||||
|
** Permission is hereby granted, free of charge, to any person obtaining |
||||
|
** a copy of this software and associated documentation files (the |
||||
|
** "Software"), to deal in the Software without restriction, including |
||||
|
** without limitation the rights to use, copy, modify, merge, publish, |
||||
|
** distribute, sublicense, and/or sell copies of the Software, and to |
||||
|
** permit persons to whom the Software is furnished to do so, subject to |
||||
|
** the following conditions: |
||||
|
** |
||||
|
** The above copyright notice and this permission notice shall be |
||||
|
** included in all copies or substantial portions of the Software. |
||||
|
** |
||||
|
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
||||
|
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
||||
|
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
||||
|
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
||||
|
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
||||
|
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
||||
|
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||||
|
** |
||||
|
****************************************************************************/ |
||||
|
|
||||
|
#ifndef XLSXCONDITIONALFORMATTING_P_H |
||||
|
#define XLSXCONDITIONALFORMATTING_P_H |
||||
|
|
||||
|
//
|
||||
|
// W A R N I N G
|
||||
|
// -------------
|
||||
|
//
|
||||
|
// This file is not part of the Qt Xlsx API. It exists for the convenience
|
||||
|
// of the Qt Xlsx. This header file may change from
|
||||
|
// version to version without notice, or even be removed.
|
||||
|
//
|
||||
|
// We mean it.
|
||||
|
//
|
||||
|
|
||||
|
#include "xlsxConditionalFormatting.h" |
||||
|
#include "xlsxformat.h" |
||||
|
#include <QSharedData> |
||||
|
#include <QSharedPointer> |
||||
|
#include <QMap> |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class XlsxCfRuleData |
||||
|
{ |
||||
|
public: |
||||
|
enum Attribute { |
||||
|
A_type, |
||||
|
A_dxfId, |
||||
|
//A_priority,
|
||||
|
A_stopIfTrue, |
||||
|
A_aboveAverage, |
||||
|
A_percent, |
||||
|
A_bottom, |
||||
|
A_operator, |
||||
|
A_text, |
||||
|
A_timePeriod, |
||||
|
A_rank, |
||||
|
A_stdDev, |
||||
|
A_equalAverage, |
||||
|
|
||||
|
A_dxfFormat, |
||||
|
A_formula1, |
||||
|
A_formula2, |
||||
|
A_formula3, |
||||
|
A_formula1_temp |
||||
|
}; |
||||
|
|
||||
|
XlsxCfRuleData() |
||||
|
:priority(1) |
||||
|
{} |
||||
|
|
||||
|
int priority; |
||||
|
Format dxfFormat; |
||||
|
QMap<int, QVariant> attrs; |
||||
|
}; |
||||
|
|
||||
|
class ConditionalFormattingPrivate : public QSharedData |
||||
|
{ |
||||
|
public: |
||||
|
ConditionalFormattingPrivate(); |
||||
|
ConditionalFormattingPrivate(const ConditionalFormattingPrivate &other); |
||||
|
~ConditionalFormattingPrivate(); |
||||
|
|
||||
|
QList<QSharedPointer<XlsxCfRuleData> >cfRules; |
||||
|
QList<CellRange> ranges; |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
#endif // XLSXCONDITIONALFORMATTING_P_H
|
@ -0,0 +1,83 @@ |
|||||
|
#include "xlsxconditionalformatting.h" |
||||
|
#include "xlsxformat.h" |
||||
|
#include "private/xlsxconditionalformatting_p.h" |
||||
|
|
||||
|
#include <QString> |
||||
|
#include <QtTest> |
||||
|
#include <QBuffer> |
||||
|
#include <QXmlStreamWriter> |
||||
|
|
||||
|
using namespace QXlsx; |
||||
|
|
||||
|
class ConditionalFormattingTest : public QObject |
||||
|
{ |
||||
|
Q_OBJECT |
||||
|
|
||||
|
public: |
||||
|
ConditionalFormattingTest(); |
||||
|
|
||||
|
private Q_SLOTS: |
||||
|
void testHighlightRules(); |
||||
|
void testHighlightRules_data(); |
||||
|
}; |
||||
|
|
||||
|
ConditionalFormattingTest::ConditionalFormattingTest() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
void ConditionalFormattingTest::testHighlightRules_data() |
||||
|
{ |
||||
|
QTest::addColumn<int>("type"); |
||||
|
QTest::addColumn<QString>("formula1"); |
||||
|
QTest::addColumn<QString>("formula2"); |
||||
|
QTest::addColumn<QByteArray>("result"); |
||||
|
|
||||
|
QTest::newRow("lessThan")<<(int)ConditionalFormatting::Highlight_LessThan |
||||
|
<<"100" |
||||
|
<<QString() |
||||
|
<<QByteArray("<cfRule type=\"cellIs\" dxfId=\"0\" priority=\"1\" operator=\"lessThan\"><formula>100</formula></cfRule>"); |
||||
|
QTest::newRow("between")<<(int)ConditionalFormatting::Highlight_Between |
||||
|
<<"4" |
||||
|
<<"20" |
||||
|
<<QByteArray("<cfRule type=\"cellIs\" dxfId=\"0\" priority=\"1\" operator=\"between\"><formula>4</formula><formula>20</formula></cfRule>"); |
||||
|
|
||||
|
QTest::newRow("containsText")<<(int)ConditionalFormatting::Highlight_ContainsText |
||||
|
<<"Qt" |
||||
|
<<QString() |
||||
|
<<QByteArray("<cfRule type=\"containsText\" dxfId=\"0\" priority=\"1\" operator=\"containsText\" text=\"Qt\">"); |
||||
|
QTest::newRow("beginsWith")<<(int)ConditionalFormatting::Highlight_BeginsWith |
||||
|
<<"Qt" |
||||
|
<<QString() |
||||
|
<<QByteArray("<cfRule type=\"beginsWith\" dxfId=\"0\" priority=\"1\" operator=\"beginsWith\" text=\"Qt\"><formula>LEFT(C3,LEN"); //(\"Qt\"))=\"Qt\"</formula></cfRule>");
|
||||
|
QTest::newRow("duplicateValues")<<(int)ConditionalFormatting::Highlight_Duplicate |
||||
|
<<QString() |
||||
|
<<QString() |
||||
|
<<QByteArray("<cfRule type=\"duplicateValues\" dxfId=\"0\" priority=\"1\"/>"); |
||||
|
} |
||||
|
|
||||
|
void ConditionalFormattingTest::testHighlightRules() |
||||
|
{ |
||||
|
QFETCH(int, type); |
||||
|
QFETCH(QString, formula1); |
||||
|
QFETCH(QString, formula2); |
||||
|
QFETCH(QByteArray, result); |
||||
|
|
||||
|
Format fmt; |
||||
|
fmt.setFontBold(true); |
||||
|
fmt.setDxfIndex(0); |
||||
|
|
||||
|
ConditionalFormatting cf; |
||||
|
cf.addHighlightCellsRule((ConditionalFormatting::HighlightRuleType)type, formula1, formula2, fmt); |
||||
|
cf.addRange("C3:C10"); |
||||
|
|
||||
|
QBuffer buffer; |
||||
|
buffer.open(QIODevice::WriteOnly); |
||||
|
QXmlStreamWriter writer(&buffer); |
||||
|
cf.saveToXml(writer); |
||||
|
qDebug()<<buffer.buffer(); |
||||
|
QVERIFY(buffer.buffer().contains(result)); |
||||
|
} |
||||
|
|
||||
|
QTEST_APPLESS_MAIN(ConditionalFormattingTest) |
||||
|
|
||||
|
#include "tst_conditionalformattingtest.moc" |
@ -0,0 +1,12 @@ |
|||||
|
QT += testlib xlsx xlsx-private |
||||
|
CONFIG += testcase |
||||
|
DEFINES += XLSX_TEST |
||||
|
|
||||
|
TARGET = tst_conditionalformattingtest |
||||
|
CONFIG += console |
||||
|
CONFIG -= app_bundle |
||||
|
|
||||
|
TEMPLATE = app |
||||
|
|
||||
|
SOURCES += tst_conditionalformattingtest.cpp |
||||
|
DEFINES += SRCDIR=\\\"$$PWD/\\\" |
Loading…
Reference in new issue