diff --git a/QXlsx/header/xlsxchart.h b/QXlsx/header/xlsxchart.h index 14dd3ba..99bcccf 100644 --- a/QXlsx/header/xlsxchart.h +++ b/QXlsx/header/xlsxchart.h @@ -30,7 +30,7 @@ public: CT_OfPieChart, CT_SurfaceChart, CT_Surface3DChart, CT_BubbleChart, }; - enum ChartAxisPos { Left, Right, Top, Bottom }; + enum ChartAxisPos { None=-1, Left=0, Right, Top, Bottom }; private: friend class AbstractSheet; friend class Worksheet; @@ -41,11 +41,15 @@ private: public: ~Chart(); public: - void addSeries(const CellRange &range, AbstractSheet* sheet = NULL); +// void addSeries(const CellRange &range, AbstractSheet* sheet = NULL); + void addSeries(const CellRange &range, AbstractSheet *sheet = NULL, bool headerH = false, bool headerV = false, bool swapHeaders = false); void setChartType(ChartType type); void setChartStyle(int id); void setAxisTitle(Chart::ChartAxisPos pos, QString axisTitle); void setChartTitle(QString strchartTitle); + void setChartLegend(Chart::ChartAxisPos legendPos, bool overlap = false); + void setGridlinesEnable(bool majorGridlinesEnable = false, bool minorGridlinesEnable = false); + public: bool loadFromXmlFile(QIODevice *device); void saveToXmlFile(QIODevice *device) const; diff --git a/QXlsx/header/xlsxchart_p.h b/QXlsx/header/xlsxchart_p.h index 3c1826c..6c1982c 100644 --- a/QXlsx/header/xlsxchart_p.h +++ b/QXlsx/header/xlsxchart_p.h @@ -22,8 +22,11 @@ class XlsxSeries { public: //At present, we care about number cell ranges only! - QString numberDataSource_numRef; // yval, val - QString axDataSource_numRef; // xval, cat + QString numberDataSource_numRef = ""; // yval, val + QString axDataSource_numRef = ""; // xval, cat + QString headerH_numRef = ""; + QString headerV_numRef = ""; + bool swapHeader = false; }; class XlsxAxis @@ -76,7 +79,9 @@ public: bool loadXmlXxxChart(QXmlStreamReader &reader); bool loadXmlSer(QXmlStreamReader &reader); QString loadXmlNumRef(QXmlStreamReader &reader); + QString loadXmlStrRef(QXmlStreamReader &reader); bool loadXmlChartTitle(QXmlStreamReader &reader); + bool loadXmlChartLegend(QXmlStreamReader &reader); protected: bool loadXmlChartTitleTx(QXmlStreamReader &reader); bool loadXmlChartTitleTxRich(QXmlStreamReader &reader); @@ -97,6 +102,8 @@ protected: bool loadXmlAxisEG_AxShared_Title_Tx_Rich_P_pPr(QXmlStreamReader &reader, XlsxAxis* axis); bool loadXmlAxisEG_AxShared_Title_Tx_Rich_P_R(QXmlStreamReader &reader, XlsxAxis* axis); + QString readSubTree(QXmlStreamReader &reader); + public: void saveXmlChart(QXmlStreamWriter &writer) const; void saveXmlChartTitle(QXmlStreamWriter &writer) const; @@ -108,6 +115,8 @@ public: void saveXmlDoughnutChart(QXmlStreamWriter &writer) const; void saveXmlSer(QXmlStreamWriter &writer, XlsxSeries *ser, int id) const; void saveXmlAxis(QXmlStreamWriter &writer) const; + void saveXmlChartLegend(QXmlStreamWriter &writer) const; + protected: void saveXmlAxisCatAx(QXmlStreamWriter &writer, XlsxAxis* axis) const; void saveXmlAxisDateAx(QXmlStreamWriter &writer, XlsxAxis* axis) const; @@ -126,6 +135,12 @@ public: QMap< XlsxAxis::AxisPos, QString > axisNames; QString chartTitle; AbstractSheet* sheet; + Chart::ChartAxisPos legendPos; + bool legendOverlay; + bool majorGridlinesEnabled; + bool minorGridlinesEnabled; + + QString layout; // only for storing a readed file }; QT_END_NAMESPACE_XLSX diff --git a/QXlsx/source/xlsxchart.cpp b/QXlsx/source/xlsxchart.cpp index b28be35..d583241 100644 --- a/QXlsx/source/xlsxchart.cpp +++ b/QXlsx/source/xlsxchart.cpp @@ -48,7 +48,14 @@ ChartPrivate::~ChartPrivate() Chart::Chart(AbstractSheet *parent, CreateFlag flag) : AbstractOOXmlFile(new ChartPrivate(this, flag)) { + Q_D(Chart); + d_func()->sheet = parent; + + d->legendPos = Chart::ChartAxisPos::None; + d->legendOverlay = false; + d->majorGridlinesEnabled = false; + d->minorGridlinesEnabled = false; } /*! @@ -61,7 +68,7 @@ Chart::~Chart() /*! * Add the data series which is in the range \a range of the \a sheet. */ -void Chart::addSeries(const CellRange &range, AbstractSheet *sheet) +void Chart::addSeries(const CellRange &range, AbstractSheet *sheet, bool headerH, bool headerV, bool swapHeaders) { Q_D(Chart); @@ -82,10 +89,12 @@ void Chart::addSeries(const CellRange &range, AbstractSheet *sheet) series->numberDataSource_numRef = sheetName + QLatin1String("!") + range.toString(true, true); d->seriesList.append(series); } - else if (range.columnCount() < range.rowCount()) + else if ((range.columnCount() < range.rowCount()) || swapHeaders ) { //Column based series + int firstDataRow = range.firstRow(); int firstDataColumn = range.firstColumn(); + QString axDataSouruce_numRef; if (d->chartType == CT_ScatterChart || d->chartType == CT_BubbleChart) { @@ -94,12 +103,42 @@ void Chart::addSeries(const CellRange &range, AbstractSheet *sheet) axDataSouruce_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true); } + if( headerH ) + { + firstDataRow += 1; + } + if( headerV ) + { + firstDataColumn += 1; + } + for (int col=firstDataColumn; col<=range.lastColumn(); ++col) { - CellRange subRange(range.firstRow(), col, range.lastRow(), col); + CellRange subRange(firstDataRow, col, range.lastRow(), col); QSharedPointer series = QSharedPointer(new XlsxSeries); series->axDataSource_numRef = axDataSouruce_numRef; series->numberDataSource_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true); + + if( headerH ) + { + CellRange subRange(range.firstRow(), col, range.firstRow(), col); + series->headerH_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true); + } + else + { + series->headerH_numRef = ""; + } + if( headerV ) + { + CellRange subRange(firstDataRow, range.firstColumn(), range.lastRow(), range.firstColumn()); + series->headerV_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true); + } + else + { + series->headerV_numRef = ""; + } + series->swapHeader = swapHeaders; + d->seriesList.append(series); } @@ -108,6 +147,8 @@ void Chart::addSeries(const CellRange &range, AbstractSheet *sheet) { //Row based series int firstDataRow = range.firstRow(); + int firstDataColumn = range.firstColumn(); + QString axDataSouruce_numRef; if (d->chartType == CT_ScatterChart || d->chartType == CT_BubbleChart) { @@ -116,12 +157,43 @@ void Chart::addSeries(const CellRange &range, AbstractSheet *sheet) axDataSouruce_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true); } + if( headerH ) + { + firstDataRow += 1; + } + if( headerV ) + { + firstDataColumn += 1; + } + for (int row=firstDataRow; row<=range.lastRow(); ++row) { - CellRange subRange(row, range.firstColumn(), row, range.lastColumn()); + CellRange subRange(row, firstDataColumn, row, range.lastColumn()); QSharedPointer series = QSharedPointer(new XlsxSeries); series->axDataSource_numRef = axDataSouruce_numRef; series->numberDataSource_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true); + + if( headerH ) + { + CellRange subRange(range.firstRow(), firstDataColumn, range.firstRow(), range.lastColumn()); + series->headerH_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true); + } + else + { + series->headerH_numRef = ""; + } + + if( headerV ) + { + CellRange subRange(row, range.firstColumn(), row, range.firstColumn()); + series->headerV_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true); + } + else + { + series->headerV_numRef = ""; + } + series->swapHeader = swapHeaders; + d->seriesList.append(series); } } @@ -183,6 +255,24 @@ void Chart::setChartTitle(QString strchartTitle) } +void Chart::setChartLegend(QXlsx::Chart::ChartAxisPos legendPos, bool overlay) +{ + Q_D(Chart); + + d->legendPos = legendPos; + d->legendOverlay = overlay; +} + + +void Chart::setGridlinesEnable(bool majorGridlinesEnable, bool minorGridlinesEnable) +{ + Q_D(Chart); + + d->majorGridlinesEnabled = majorGridlinesEnable; + d->minorGridlinesEnabled = minorGridlinesEnable; +} + + /*! * \internal */ @@ -270,15 +360,22 @@ bool Chart::loadFromXmlFile(QIODevice *device) return true; } + bool ChartPrivate::loadXmlChart(QXmlStreamReader &reader) { Q_ASSERT(reader.name() == QLatin1String("chart")); +// qDebug() << "-------------- loadXmlChart"; + while (!reader.atEnd()) { reader.readNextStartElement(); + +// qDebug() << "-------------1- " << reader.name(); + if (reader.tokenType() == QXmlStreamReader::StartElement) { + if (reader.name() == QLatin1String("plotArea")) { if (!loadXmlPlotArea(reader)) @@ -295,10 +392,11 @@ bool ChartPrivate::loadXmlChart(QXmlStreamReader &reader) } } - else if (reader.name() == QLatin1String("legend")) - { - //!Todo - } +// else if (reader.name() == QLatin1String("legend")) +// { +// loadXmlChartLegend(reader); +// qDebug() << "-------------- loadXmlChartLegend"; +// } } else if (reader.tokenType() == QXmlStreamReader::EndElement && reader.name() == QLatin1String("chart") ) @@ -347,6 +445,8 @@ bool ChartPrivate::loadXmlPlotArea(QXmlStreamReader &reader) while (!reader.atEnd()) { +// qDebug() << "-------------2- " << reader.name(); + if (reader.isStartElement()) { if (!loadXmlPlotAreaElement(reader)) @@ -354,6 +454,11 @@ bool ChartPrivate::loadXmlPlotArea(QXmlStreamReader &reader) qDebug() << "[debug] failed to load plotarea element."; return false; } + else if (reader.name() == QLatin1String("legend")) // Why here? + { + loadXmlChartLegend(reader); +// qDebug() << "-------------- loadXmlChartLegend"; + } reader.readNext(); } @@ -370,8 +475,8 @@ bool ChartPrivate::loadXmlPlotAreaElement(QXmlStreamReader &reader) { if (reader.name() == QLatin1String("layout")) { - //!ToDo - // layout + //!ToDo extract attributes + layout = readSubTree(reader); } else if (reader.name().endsWith(QLatin1String("Chart"))) { @@ -555,8 +660,22 @@ bool ChartPrivate::loadXmlSer(QXmlStreamReader &reader) { if (reader.readNextStartElement()) { + //TODO beide Header noch auswerten RTR 2019.11 QStringRef name = reader.name(); - if ( name == QLatin1String("cat") || + if ( name == QLatin1String("tx") ) + { + while ( !reader.atEnd() && + !(reader.tokenType() == QXmlStreamReader::EndElement && + reader.name() == name)) + { + if (reader.readNextStartElement()) + { + if (reader.name() == QLatin1String("strRef")) + series->headerV_numRef = loadXmlStrRef(reader); + } + } + } + else if ( name == QLatin1String("cat") || name == QLatin1String("xVal") ) { while ( !reader.atEnd() && @@ -567,6 +686,9 @@ bool ChartPrivate::loadXmlSer(QXmlStreamReader &reader) { if (reader.name() == QLatin1String("numRef")) series->axDataSource_numRef = loadXmlNumRef(reader); + else + if (reader.name() == QLatin1String("strRef")) + series->headerH_numRef = loadXmlStrRef(reader); } } } @@ -616,6 +738,25 @@ QString ChartPrivate::loadXmlNumRef(QXmlStreamReader &reader) return QString(); } + +QString ChartPrivate::loadXmlStrRef(QXmlStreamReader &reader) +{ + Q_ASSERT(reader.name() == QLatin1String("strRef")); + + while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement + && reader.name() == QLatin1String("strRef"))) + { + if (reader.readNextStartElement()) + { + if (reader.name() == QLatin1String("f")) + return reader.readElementText(); + } + } + + return QString(); +} + + void ChartPrivate::saveXmlChart(QXmlStreamWriter &writer) const { //---------------------------------------------------- @@ -625,13 +766,18 @@ void ChartPrivate::saveXmlChart(QXmlStreamWriter &writer) const //---------------------------------------------------- // c:title - saveXmlChartTitle(writer); // wrtie 'chart title' + saveXmlChartTitle(writer); // write 'chart title' //---------------------------------------------------- // c:plotArea writer.writeStartElement(QStringLiteral("c:plotArea")); + // a little workaround for Start- and EndElement with starting ">" and ending without ">" + writer.device()->write(">"); //layout + writer.device()->write(layout.toUtf8()); + writer.device()->write(" +// +// +// + + writer.writeStartElement(QStringLiteral("c:legend")); + + writer.writeStartElement(QStringLiteral("c:legendPos")); + QString pos; + switch( legendPos ) + { + case Chart::ChartAxisPos::Right: + pos = "r"; + break; + + case Chart::ChartAxisPos::Left: + pos = "l"; + break; + + case Chart::ChartAxisPos::Top: + pos = "t"; + break; + + case Chart::ChartAxisPos::Bottom: + pos = "b"; + break; + + default: + pos = "r"; + break; + } + writer.writeAttribute(QStringLiteral("val"), pos); + writer.writeEndElement(); // c:legendPos + + writer.writeStartElement(QStringLiteral("c:overlay")); + if( legendOverlay ) + { + writer.writeAttribute(QStringLiteral("val"), QStringLiteral("1")); + } + else + { + writer.writeAttribute(QStringLiteral("val"), QStringLiteral("0")); + } + writer.writeEndElement(); // c:overlay + + writer.writeEndElement(); // c:legend +} + + void ChartPrivate::saveXmlPieChart(QXmlStreamWriter &writer) const { QString name = chartType == Chart::CT_PieChart ? QStringLiteral("c:pieChart") : QStringLiteral("c:pie3DChart"); @@ -1072,12 +1275,44 @@ void ChartPrivate::saveXmlDoughnutChart(QXmlStreamWriter &writer) const void ChartPrivate::saveXmlSer(QXmlStreamWriter &writer, XlsxSeries *ser, int id) const { + writer.writeStartElement(QStringLiteral("c:ser")); writer.writeEmptyElement(QStringLiteral("c:idx")); writer.writeAttribute(QStringLiteral("val"), QString::number(id)); writer.writeEmptyElement(QStringLiteral("c:order")); writer.writeAttribute(QStringLiteral("val"), QString::number(id)); + QString header1; + QString header2; + if( ser->swapHeader ) + { + header1 = ser->headerH_numRef; + header2 = ser->headerV_numRef; + } + else + { + header1 = ser->headerV_numRef; + header2 = ser->headerH_numRef; + } + + if( !header1.isEmpty() ) + { + writer.writeStartElement(QStringLiteral("c:tx")); + writer.writeStartElement(QStringLiteral("c:strRef")); + writer.writeTextElement(QStringLiteral("c:f"), header1); + writer.writeEndElement(); + writer.writeEndElement(); + } + if( !header2.isEmpty() ) + { + writer.writeStartElement(QStringLiteral("c:cat")); + writer.writeStartElement(QStringLiteral("c:strRef")); + writer.writeTextElement(QStringLiteral("c:f"), header2); + writer.writeEndElement(); + writer.writeEndElement(); + } + +#if 0 if (!ser->axDataSource_numRef.isEmpty()) { if (chartType == Chart::CT_ScatterChart || chartType == Chart::CT_BubbleChart) @@ -1094,8 +1329,10 @@ void ChartPrivate::saveXmlSer(QXmlStreamWriter &writer, XlsxSeries *ser, int id) writer.writeEndElement();//c:numRef writer.writeEndElement();//c:cat or c:xVal } +#endif - if (!ser->numberDataSource_numRef.isEmpty()) { + if (!ser->numberDataSource_numRef.isEmpty()) + { if (chartType == Chart::CT_ScatterChart || chartType == Chart::CT_BubbleChart) writer.writeStartElement(QStringLiteral("c:yVal")); else @@ -1274,11 +1511,13 @@ bool ChartPrivate::loadXmlAxisEG_AxShared(QXmlStreamReader &reader, XlsxAxis* ax } else if ( reader.name() == QLatin1String("majorGridlines") ) { - //!TODO + //!TODO anything else? + majorGridlinesEnabled = true; } else if ( reader.name() == QLatin1String("minorGridlines") ) { - //!TODO + //!TODO anything else? + minorGridlinesEnabled = true; } else if ( reader.name() == QLatin1String("title") ) { @@ -1865,6 +2104,15 @@ void ChartPrivate::saveXmlAxisEG_AxShared(QXmlStreamWriter &writer, XlsxAxis* ax writer.writeAttribute(QStringLiteral("val"), pos); // ST_AxPos } + if( majorGridlinesEnabled ) + { + writer.writeEmptyElement("c:majorGridlines"); + } + if( minorGridlinesEnabled ) + { + writer.writeEmptyElement("c:minorGridlines"); + } + saveXmlAxisEG_AxShared_Title(writer, axis); // "c:title" CT_Title writer.writeEmptyElement(QStringLiteral("c:crossAx")); // crossAx (mandatory value) @@ -1988,4 +2236,105 @@ QString ChartPrivate::GetAxisName(XlsxAxis* axis) const } +/// +/// \brief ChartPrivate::readSubTree +/// \param reader +/// \return +/// +QString ChartPrivate::readSubTree(QXmlStreamReader &reader) +{ + QString treeString; + QString prefix; + QStringRef treeName = reader.name(); + + while (!reader.atEnd()) + { + reader.readNextStartElement(); + if (reader.tokenType() == QXmlStreamReader::StartElement) + { + prefix = reader.prefix().toString(); + + treeString += QString("<" + reader.qualifiedName().toString() ); + + foreach(const QXmlStreamAttribute &attr, reader.attributes()) + { + treeString += QString( " " + attr.name().toString() + "=\"" + attr.value().toString() + "\""); + } + treeString += ">"; + } + else if (reader.tokenType() == QXmlStreamReader::EndElement ) + { + if( reader.name() == treeName) + { + break; + } + treeString += QString(""); + } + } + + return treeString; +} + + +/// +/// \brief ChartPrivate::loadXmlChartLegend +/// \param reader +/// \return +/// +bool ChartPrivate::loadXmlChartLegend(QXmlStreamReader &reader) +{ + + Q_ASSERT(reader.name() == QLatin1String("legend")); + + while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement + && reader.name() == QLatin1String("legend"))) + { + if (reader.readNextStartElement()) + { + if (reader.name() == QLatin1String("legendPos")) // c:legendPos + { + QString pos = reader.attributes().value(QLatin1String("val")).toString(); + if( pos.compare("r",Qt::CaseInsensitive) == 0) + { + legendPos = Chart::ChartAxisPos::Right; + } + else + if( pos.compare("l",Qt::CaseInsensitive) == 0) + { + legendPos = Chart::ChartAxisPos::Left; + } + else + if( pos.compare("t",Qt::CaseInsensitive) == 0) + { + legendPos = Chart::ChartAxisPos::Top; + } + else + if( pos.compare("b",Qt::CaseInsensitive) == 0) + { + legendPos = Chart::ChartAxisPos::Bottom; + } + else + { + legendPos = Chart::ChartAxisPos::None; + } + } + else + if (reader.name() == QLatin1String("overlay")) // c:legendPos + { + QString pos = reader.attributes().value(QLatin1String("val")).toString(); + if( pos.compare("1",Qt::CaseInsensitive) == 0) + { + legendOverlay = true; + } + else + { + legendOverlay = false; + } + } + } + } + + return false; +} + QT_END_NAMESPACE_XLSX diff --git a/TestExcel/TestExcel.pro b/TestExcel/TestExcel.pro index 2c859ad..67d37f7 100644 --- a/TestExcel/TestExcel.pro +++ b/TestExcel/TestExcel.pro @@ -36,6 +36,7 @@ DEFINES += QT_DEPRECATED_WARNINGS SOURCES += \ calendar.cpp \ chart.cpp \ + chartextended.cpp \ chartsheet.cpp \ datavalidation.cpp \ definename.cpp \ diff --git a/TestExcel/chartextended.cpp b/TestExcel/chartextended.cpp new file mode 100644 index 0000000..b00e202 --- /dev/null +++ b/TestExcel/chartextended.cpp @@ -0,0 +1,84 @@ +// chart.cpp + +#include +#include +#include + +#include "xlsxdocument.h" +#include "xlsxcellrange.h" +#include "xlsxchart.h" + +using namespace QXlsx; + +/* + * Test Chart with title, gridlines, legends, multiple headers + * + */ + +int chartExtended() +{ + Document xlsx; + for (int i=1; i<10; ++i) + { + xlsx.write(1, i+1, "Pos " + QString::number(i)); + } + + xlsx.write(2, 1, "Set 1"); + xlsx.write(3, 1, "Set 2"); + + for (int i=1; i<10; ++i) + { + xlsx.write(2, i+1, i*i*i); //A2:A10 + xlsx.write(3, i+1, i*i); //B2:B10 + } + + + Chart *barChart1 = xlsx.insertChart(4, 3, QSize(300, 300)); + barChart1->setChartType(Chart::CT_BarChart); + barChart1->setChartLegend(Chart::ChartAxisPos::Right); + barChart1->setChartTitle("Test1"); + // Messreihen + barChart1->addSeries(CellRange(1,1,3,10), NULL, true, true, false); + + Chart *barChart2 = xlsx.insertChart(4, 9, QSize(300, 300)); + barChart2->setChartType(Chart::CT_BarChart); + barChart2->setChartLegend(Chart::ChartAxisPos::Right); + barChart2->setChartTitle("Test2"); + barChart2->setGridlinesEnable(true); + // Messreihen + barChart2->addSeries(CellRange(1,1,3,10), NULL, true, true, true); + + Chart *barChart3 = xlsx.insertChart(24, 3, QSize(300, 300)); + barChart3->setChartType(Chart::CT_BarChart); + barChart3->setChartLegend(Chart::ChartAxisPos::Left); + barChart3->setChartTitle("Test3"); + // Messreihen + barChart3->addSeries(CellRange(1,1,3,10)); + + Chart *barChart4 = xlsx.insertChart(24, 9, QSize(300, 300)); + barChart4->setChartType(Chart::CT_BarChart); + barChart4->setChartLegend(Chart::ChartAxisPos::Top); + barChart4->setChartTitle("Test4"); + // Messreihen + barChart4->addSeries(CellRange(1,1,3,10)); + + Chart *barChart5 = xlsx.insertChart(44, 9, QSize(300, 300)); + barChart5->setChartType(Chart::CT_BarChart); + barChart5->setChartLegend(Chart::ChartAxisPos::Bottom); + barChart5->setChartTitle("Test5"); + // Messreihen + barChart5->addSeries(CellRange(1,1,3,10)); + + + //![2] + xlsx.saveAs("chartExtended1.xlsx"); + //![2] + + Document xlsx2("chartExtended1.xlsx"); + if ( xlsx2.load() ) + { + xlsx2.saveAs("chartExtended2.xlsx"); + } + + return 0; +} diff --git a/TestExcel/definename.cpp b/TestExcel/definename.cpp index 88db905..08a0409 100644 --- a/TestExcel/definename.cpp +++ b/TestExcel/definename.cpp @@ -35,6 +35,13 @@ int definename() xlsx.write(12, 3, "=SUM(MyCol_3)*Factor"); //![2] - xlsx.saveAs("definename.xlsx"); + xlsx.saveAs("definename1.xlsx"); + + Document xlsx2("definename1.xlsx"); + if ( xlsx2.load() ) + { + xlsx2.saveAs("definename2.xlsx"); + } + return 0; } diff --git a/TestExcel/main.cpp b/TestExcel/main.cpp index 9aeaa33..4c4d792 100644 --- a/TestExcel/main.cpp +++ b/TestExcel/main.cpp @@ -19,6 +19,7 @@ using namespace QXlsx; extern int hello(); extern int calendar(); extern int chart(); +extern int chartExtended(); extern int chartsheet(); extern int datavalidation(); extern int definename(); @@ -54,7 +55,8 @@ int main(int argc, char *argv[]) hello(); readStyle(); calendar(); - chart(); + chart(); + chartExtended(); chartsheet(); datavalidation(); definename();