diff --git a/examples/xlsx/chart/main.cpp b/examples/xlsx/chart/main.cpp index 8a2282c..87eef04 100644 --- a/examples/xlsx/chart/main.cpp +++ b/examples/xlsx/chart/main.cpp @@ -1,6 +1,7 @@ #include #include "xlsxdocument.h" #include "xlsxpiechart.h" +#include "xlsxbarchart.h" #include "xlsxworksheet.h" using namespace QXlsx; @@ -16,9 +17,13 @@ int main() //![0] //![1] - PieChart *chart = new PieChart; - chart->addSeries(CellRange("A1:A9"), sheet->sheetName()); - sheet->insertChart(3, 3, chart, QSize(300, 300)); + PieChart *pieChart = new PieChart; + pieChart->addSeries(CellRange("A1:A9"), sheet->sheetName()); + sheet->insertChart(3, 3, pieChart, QSize(300, 300)); + + BarChart *barChart = new BarChart; + barChart->addSeries(CellRange("A1:A9"), sheet->sheetName()); + sheet->insertChart(6, 6, barChart, QSize(300, 300)); //![1] //![2] diff --git a/src/xlsx/qtxlsx.pri b/src/xlsx/qtxlsx.pri index acbb57a..b366c39 100755 --- a/src/xlsx/qtxlsx.pri +++ b/src/xlsx/qtxlsx.pri @@ -43,7 +43,9 @@ HEADERS += $$PWD/xlsxdocpropscore_p.h \ $$PWD/xlsxabstractchart.h \ $$PWD/xlsxabstractchart_p.h \ $$PWD/xlsxpiechart.h \ - $$PWD/xlsxpiechart_p.h + $$PWD/xlsxpiechart_p.h \ + $$PWD/xlsxbarchart.h \ + $$PWD/xlsxbarchart_p.h SOURCES += $$PWD/xlsxdocpropscore.cpp \ $$PWD/xlsxdocpropsapp.cpp \ @@ -72,4 +74,5 @@ SOURCES += $$PWD/xlsxdocpropscore.cpp \ $$PWD/xlsxooxmlfile.cpp \ $$PWD/xlsxchartfile.cpp \ $$PWD/xlsxabstractchart.cpp \ - $$PWD/xlsxpiechart.cpp + $$PWD/xlsxpiechart.cpp \ + $$PWD/xlsxbarchart.cpp diff --git a/src/xlsx/xlsxabstractchart.cpp b/src/xlsx/xlsxabstractchart.cpp index 7b39fab..cf6c402 100644 --- a/src/xlsx/xlsxabstractchart.cpp +++ b/src/xlsx/xlsxabstractchart.cpp @@ -28,6 +28,8 @@ #include "xlsxchartfile_p.h" #include "xlsxcellrange.h" #include "xlsxutility_p.h" +#include +#include QT_BEGIN_NAMESPACE_XLSX @@ -42,6 +44,27 @@ AbstractChartPrivate::~AbstractChartPrivate() } +bool AbstractChartPrivate::loadXmlSer(QXmlStreamReader &reader) +{ + Q_ASSERT(reader.name() == QLatin1String("ser")); + + while (!reader.atEnd()) { + reader.readNextStartElement(); + if (reader.tokenType() == QXmlStreamReader::StartElement) { + if (reader.name() == QLatin1String("f")) { + XlsxSeries *series = new XlsxSeries; + series->numRef = reader.readElementText(); + seriesList.append(QSharedPointer(series)); + } + } else if (reader.tokenType() == QXmlStreamReader::EndElement + && reader.name() == QLatin1String("ser")) { + break; + } + } + + return true; +} + /*! * \class AbstractChart * @@ -83,4 +106,118 @@ void AbstractChart::addSeries(const CellRange &range, const QString &sheet) d->seriesList.append(QSharedPointer(series)); } +bool AbstractChart::loadAxisFromXml(QXmlStreamReader &reader) +{ + Q_D(AbstractChart); + Q_ASSERT(reader.name().endsWith(QLatin1String("Ax"))); + QString name = reader.name().toString(); + + XlsxAxis *axis = new XlsxAxis; + if (name == QLatin1String("valAx")) + axis->type = XlsxAxis::T_Val; + else if (name == QLatin1String("catAx")) + axis->type = XlsxAxis::T_Cat; + else if (name == QLatin1String("serAx")) + axis->type = XlsxAxis::T_Ser; + else + axis->type = XlsxAxis::T_Date; + + d->axisList.append(QSharedPointer(axis)); + + while (!reader.atEnd()) { + reader.readNextStartElement(); + if (reader.tokenType() == QXmlStreamReader::StartElement) { + if (reader.name() == QLatin1String("axPos")) { + QXmlStreamAttributes attrs = reader.attributes(); + QStringRef pos = attrs.value(QLatin1String("val")); + if (pos==QLatin1String("l")) + axis->axisPos = XlsxAxis::Left; + else if (pos==QLatin1String("r")) + axis->axisPos = XlsxAxis::Right; + else if (pos==QLatin1String("b")) + axis->axisPos = XlsxAxis::Bottom; + else + axis->axisPos = XlsxAxis::Top; + } + } else if (reader.tokenType() == QXmlStreamReader::EndElement + && reader.name() == name) { + break; + } + } + + return true; +} + +void AbstractChart::saveAxisToXml(QXmlStreamWriter &writer) const +{ + Q_D(const AbstractChart); + + for (int i=0; iaxisList.size(); ++i) { + XlsxAxis *axis = d->axisList[i].data(); + QString name; + switch (axis->type) { + case XlsxAxis::T_Cat: + name = QStringLiteral("c:catAx"); + break; + case XlsxAxis::T_Val: + name = QStringLiteral("c:valAx"); + break; + case XlsxAxis::T_Ser: + name = QStringLiteral("c:serAx"); + break; + case XlsxAxis::T_Date: + name = QStringLiteral("c:dateAx"); + break; + default: + break; + } + + QString pos; + switch (axis->axisPos) { + case XlsxAxis::Top: + pos = QStringLiteral("t"); + break; + case XlsxAxis::Bottom: + pos = QStringLiteral("b"); + break; + case XlsxAxis::Left: + pos = QStringLiteral("l"); + break; + case XlsxAxis::Right: + pos = QStringLiteral("r"); + break; + default: + break; + } + + writer.writeStartElement(name); + writer.writeEmptyElement(QStringLiteral("c:axId")); + writer.writeAttribute(QStringLiteral("val"), QString::number(i+1)); + + writer.writeStartElement(QStringLiteral("c:scaling")); + writer.writeEmptyElement(QStringLiteral("c:orientation")); + writer.writeAttribute(QStringLiteral("val"), QStringLiteral("minMax")); + writer.writeEndElement();//c:scaling + + writer.writeEmptyElement(QStringLiteral("c:axPos")); + writer.writeAttribute(QStringLiteral("val"), pos); + + writer.writeEmptyElement(QStringLiteral("c:crossAx")); + writer.writeAttribute(QStringLiteral("val"), QString::number(i%2==0 ? i+2 : i)); + + writer.writeEndElement();//name + } +} + +bool AbstractChart::loadLegendFromXml(QXmlStreamReader &reader) +{ + + return false; +} + +void AbstractChart::saveLegendToXml(QXmlStreamWriter &writer) const +{ + +} + QT_END_NAMESPACE_XLSX diff --git a/src/xlsx/xlsxabstractchart.h b/src/xlsx/xlsxabstractchart.h index 8c59896..6855071 100644 --- a/src/xlsx/xlsxabstractchart.h +++ b/src/xlsx/xlsxabstractchart.h @@ -52,8 +52,14 @@ public: protected: friend class ChartFile; AbstractChart(AbstractChartPrivate *d); - virtual bool loadFromXml(QXmlStreamReader &reader) = 0; - virtual void saveToXml(QXmlStreamWriter &writer) const = 0; + virtual bool loadXxxChartFromXml(QXmlStreamReader &reader) = 0; + virtual void saveXxxChartToXml(QXmlStreamWriter &writer) const = 0; + + bool loadAxisFromXml(QXmlStreamReader &reader); + void saveAxisToXml(QXmlStreamWriter &writer) const; + + bool loadLegendFromXml(QXmlStreamReader &reader); + void saveLegendToXml(QXmlStreamWriter &writer) const; AbstractChartPrivate * d_ptr; }; diff --git a/src/xlsx/xlsxabstractchart_p.h b/src/xlsx/xlsxabstractchart_p.h index 8de858a..29a02ca 100644 --- a/src/xlsx/xlsxabstractchart_p.h +++ b/src/xlsx/xlsxabstractchart_p.h @@ -50,6 +50,38 @@ public: QString numRef; }; +class XlsxAxis +{ +public: + enum Type + { + T_Cat, + T_Val, + T_Date, + T_Ser + }; + + enum Pos + { + Left, + Right, + Top, + Bottom + }; + + XlsxAxis(){} + + XlsxAxis(Type t, Pos p) + :type(t), axisPos(p) + { + axisId = -1; + } + + int axisId; + Type type; + Pos axisPos; //l,r,b,t +}; + class AbstractChartPrivate { Q_DECLARE_PUBLIC(AbstractChart) @@ -57,7 +89,10 @@ public: AbstractChartPrivate(AbstractChart *chart); virtual ~AbstractChartPrivate(); + bool loadXmlSer(QXmlStreamReader &reader); + QList > seriesList; + QList> axisList; ChartFile *cf; AbstractChart *q_ptr; }; diff --git a/src/xlsx/xlsxchartfile.cpp b/src/xlsx/xlsxchartfile.cpp index 75d83a4..92358b4 100644 --- a/src/xlsx/xlsxchartfile.cpp +++ b/src/xlsx/xlsxchartfile.cpp @@ -27,6 +27,7 @@ #include "xlsxabstractchart.h" #include "xlsxabstractchart_p.h" #include "xlsxpiechart.h" +#include "xlsxbarchart.h" #include #include #include @@ -77,7 +78,8 @@ bool ChartFile::loadFromXmlFile(QIODevice *device) reader.readNextStartElement(); if (reader.tokenType() == QXmlStreamReader::StartElement) { if (reader.name() == QLatin1String("chart")) { - loadXmlChart(reader); + if (!loadXmlChart(reader)) + return false; } } } @@ -92,7 +94,10 @@ bool ChartFile::loadXmlChart(QXmlStreamReader &reader) reader.readNextStartElement(); if (reader.tokenType() == QXmlStreamReader::StartElement) { if (reader.name() == QLatin1String("plotArea")) { - loadXmlPlotArea(reader); + if (!loadXmlPlotArea(reader)) + return false; + } else if (reader.name() == QLatin1String("legend")) { + m_chart->loadLegendFromXml(reader); } } else if (reader.tokenType() == QXmlStreamReader::EndElement && reader.name() == QLatin1String("chart")) { @@ -109,20 +114,28 @@ bool ChartFile::loadXmlPlotArea(QXmlStreamReader &reader) while (!reader.atEnd()) { reader.readNextStartElement(); if (reader.tokenType() == QXmlStreamReader::StartElement) { - AbstractChart *chart = 0; if (reader.name() == QLatin1String("layout")) { //... - } else if (reader.name() == QLatin1String("pieChart")) { - chart = new PieChart; - chart->loadFromXml(reader); - } else if (reader.name() == QLatin1String("")) { - + } else if (reader.name().endsWith(QLatin1String("Chart"))) { + //!Todo: each plotArea can have more than one xxxChart + AbstractChart *chart = 0; + if (reader.name() == QLatin1String("pieChart")) { + chart = new PieChart; + } else if (reader.name() == QLatin1String("barChart")) { + chart = new BarChart; + } else { + //Not support + return false; + } + if (chart) { + chart->loadXxxChartFromXml(reader); + setChart(chart); + } + } else if (reader.name().endsWith(QLatin1String("Ax"))) { + //For valAx, catAx, serAx, dateAx + m_chart->loadAxisFromXml(reader); } - if (chart) { - chart->loadFromXml(reader); - setChart(chart); - } } else if (reader.tokenType() == QXmlStreamReader::EndElement && reader.name() == QLatin1String("plotArea")) { break; @@ -135,11 +148,11 @@ bool ChartFile::saveXmlChart(QXmlStreamWriter &writer) const { writer.writeStartElement(QStringLiteral("c:chart")); writer.writeStartElement(QStringLiteral("c:plotArea")); - m_chart->saveToXml(writer); + m_chart->saveXxxChartToXml(writer); + m_chart->saveAxisToXml(writer); writer.writeEndElement(); //plotArea -// writer.writeStartElement(QStringLiteral("c:legend")); -// writer.writeEndElement(); //legend + m_chart->saveLegendToXml(writer); writer.writeEndElement(); //chart return true; diff --git a/src/xlsx/xlsxpiechart.cpp b/src/xlsx/xlsxpiechart.cpp index b6dd748..580f003 100644 --- a/src/xlsx/xlsxpiechart.cpp +++ b/src/xlsx/xlsxpiechart.cpp @@ -46,7 +46,7 @@ PieChart::PieChart() { } -bool PieChart::loadFromXml(QXmlStreamReader &reader) +bool PieChart::loadXxxChartFromXml(QXmlStreamReader &reader) { Q_ASSERT(reader.name() == QLatin1String("pieChart")); @@ -66,28 +66,7 @@ bool PieChart::loadFromXml(QXmlStreamReader &reader) return true; } -bool PieChartPrivate::loadXmlSer(QXmlStreamReader &reader) -{ - Q_ASSERT(reader.name() == QLatin1String("ser")); - - while (!reader.atEnd()) { - reader.readNextStartElement(); - if (reader.tokenType() == QXmlStreamReader::StartElement) { - if (reader.name() == QLatin1String("f")) { - XlsxSeries *series = new XlsxSeries; - series->numRef = reader.readElementText(); - seriesList.append(QSharedPointer(series)); - } - } else if (reader.tokenType() == QXmlStreamReader::EndElement - && reader.name() == QLatin1String("ser")) { - break; - } - } - - return true; -} - -void PieChart::saveToXml(QXmlStreamWriter &writer) const +void PieChart::saveXxxChartToXml(QXmlStreamWriter &writer) const { Q_D(const PieChart); diff --git a/src/xlsx/xlsxpiechart.h b/src/xlsx/xlsxpiechart.h index 36f82d7..0fa9a8a 100644 --- a/src/xlsx/xlsxpiechart.h +++ b/src/xlsx/xlsxpiechart.h @@ -40,8 +40,8 @@ public: PieChart(); protected: - bool loadFromXml(QXmlStreamReader &reader); - void saveToXml(QXmlStreamWriter &writer) const; + bool loadXxxChartFromXml(QXmlStreamReader &reader); + void saveXxxChartToXml(QXmlStreamWriter &writer) const; }; QT_END_NAMESPACE_XLSX diff --git a/src/xlsx/xlsxpiechart_p.h b/src/xlsx/xlsxpiechart_p.h index ccba799..f15378c 100644 --- a/src/xlsx/xlsxpiechart_p.h +++ b/src/xlsx/xlsxpiechart_p.h @@ -48,8 +48,6 @@ class PieChartPrivate : public AbstractChartPrivate public: PieChartPrivate(PieChart *chart); - - bool loadXmlSer(QXmlStreamReader &reader); }; QT_END_NAMESPACE_XLSX