From 28f3262e869cede4d1c2bfc0149c581aae9c424c Mon Sep 17 00:00:00 2001 From: Debao Zhang Date: Sun, 19 Jan 2014 21:51:57 +0800 Subject: [PATCH] Code refactoring: Add more basic chart support --- examples/xlsx/chart/main.cpp | 23 ++++ src/xlsx/xlsxchart.cpp | 202 +++++++++++++++++++++++++++++------ src/xlsx/xlsxchart_p.h | 18 ++-- 3 files changed, 206 insertions(+), 37 deletions(-) diff --git a/examples/xlsx/chart/main.cpp b/examples/xlsx/chart/main.cpp index d1ad599..bae6ee0 100644 --- a/examples/xlsx/chart/main.cpp +++ b/examples/xlsx/chart/main.cpp @@ -30,6 +30,29 @@ int main() bar3DChart->setChartType(Chart::CT_Bar3D); bar3DChart->addSeries(CellRange("A1:A9")); + Chart *lineChart = xlsx.insertChart(43, 3, QSize(300, 300)); + lineChart->setChartType(Chart::CT_Line); + lineChart->addSeries(CellRange("A1:A9")); + + Chart *line3DChart = xlsx.insertChart(43, 7, QSize(300, 300)); + line3DChart->setChartType(Chart::CT_Line3D); + line3DChart->addSeries(CellRange("A1:A9")); + + Chart *areaChart = xlsx.insertChart(63, 3, QSize(300, 300)); + areaChart->setChartType(Chart::CT_Area); + areaChart->addSeries(CellRange("A1:A9")); + + Chart *area3DChart = xlsx.insertChart(63, 7, QSize(300, 300)); + area3DChart->setChartType(Chart::CT_Area3D); + area3DChart->addSeries(CellRange("A1:A9")); + + Chart *scatterChart = xlsx.insertChart(83, 3, QSize(300, 300)); + scatterChart->setChartType(Chart::CT_Scatter); + scatterChart->addSeries(CellRange("A1:A9")); + + Chart *doughnutChart = xlsx.insertChart(103, 3, QSize(300, 300)); + doughnutChart->setChartType(Chart::CT_Doughnut); + doughnutChart->addSeries(CellRange("A1:A9")); //![1] //![2] diff --git a/src/xlsx/xlsxchart.cpp b/src/xlsx/xlsxchart.cpp index ce0c80d..39b6ab4 100644 --- a/src/xlsx/xlsxchart.cpp +++ b/src/xlsx/xlsxchart.cpp @@ -31,6 +31,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE_XLSX @@ -187,6 +188,13 @@ bool ChartPrivate::loadXmlXxxChart(QXmlStreamReader &reader) else if (name == QLatin1String("pie3DChart")) chartType = Chart::CT_Pie3D; else if (name == QLatin1String("barChart")) chartType = Chart::CT_Bar; else if (name == QLatin1String("bar3DChart")) chartType = Chart::CT_Bar3D; + else if (name == QLatin1String("lineChart")) chartType = Chart::CT_Line; + else if (name == QLatin1String("line3DChart")) chartType = Chart::CT_Line3D; + else if (name == QLatin1String("scatterChart")) chartType = Chart::CT_Scatter; + else if (name == QLatin1String("areaChart")) chartType = Chart::CT_Area; + else if (name == QLatin1String("area3DChart")) chartType = Chart::CT_Area3D; + else if (name == QLatin1String("doughnutChart")) chartType = Chart::CT_Doughnut; + else qDebug()<<"Cann't load chart: "<(this)->axisList.append(QSharedPointer(new XlsxAxis(XlsxAxis::T_Cat, XlsxAxis::Bottom, 0, 1))); + const_cast(this)->axisList.append(QSharedPointer(new XlsxAxis(XlsxAxis::T_Val, XlsxAxis::Left, 1, 0))); } - writer.writeStartElement(t); //pieChart, barChart, ... + //Note: Bar3D have 2~3 axes + Q_ASSERT(axisList.size()==2 || (axisList.size()==3 && chartType==Chart::CT_Bar3D)); - if (chartType==Chart::CT_Bar || chartType==Chart::CT_Bar3D) { - writer.writeEmptyElement(QStringLiteral("c:barDir")); - writer.writeAttribute(QStringLiteral("val"), QStringLiteral("col")); + for (int i=0; iaxisId)); + } + + writer.writeEndElement(); //barChart, bar3DChart +} + +void ChartPrivate::saveXmlLineChart(QXmlStreamWriter &writer) const +{ + QString name = chartType==Chart::CT_Line ? QStringLiteral("c:lineChart") : QStringLiteral("c:line3DChart"); + + writer.writeStartElement(name); + + writer.writeEmptyElement(QStringLiteral("grouping")); + + for (int i=0; i(this)->axisList.append(QSharedPointer(new XlsxAxis(XlsxAxis::T_Cat, XlsxAxis::Bottom, 0, 1))); + const_cast(this)->axisList.append(QSharedPointer(new XlsxAxis(XlsxAxis::T_Val, XlsxAxis::Left, 1, 0))); + if (chartType==Chart::CT_Line3D) + const_cast(this)->axisList.append(QSharedPointer(new XlsxAxis(XlsxAxis::T_Ser, XlsxAxis::Bottom, 2, 0))); } - if (chartType==Chart::CT_Pie || chartType==Chart::CT_Pie3D) { - //Do the same behavior as Excel, Pie prefer varyColors - writer.writeEmptyElement(QStringLiteral("c:varyColors")); - writer.writeAttribute(QStringLiteral("val"), QStringLiteral("1")); + Q_ASSERT((axisList.size()==2||chartType==Chart::CT_Line)|| (axisList.size()==3 && chartType==Chart::CT_Line3D)); + + for (int i=0; iaxisId)); } + writer.writeEndElement(); //lineChart, line3DChart +} + +void ChartPrivate::saveXmlScatterChart(QXmlStreamWriter &writer) const +{ + const QString name = QStringLiteral("c:scatterChart"); + + writer.writeStartElement(name); + + writer.writeEmptyElement(QStringLiteral("c:scatterStyle")); + for (int i=0; i(this)->axisList.append(QSharedPointer(new XlsxAxis(XlsxAxis::T_Cat, XlsxAxis::Left))); - const_cast(this)->axisList.append(QSharedPointer(new XlsxAxis(XlsxAxis::T_Val, XlsxAxis::Bottom))); - } + if (axisList.isEmpty()) { + const_cast(this)->axisList.append(QSharedPointer(new XlsxAxis(XlsxAxis::T_Cat, XlsxAxis::Bottom, 0, 1))); + const_cast(this)->axisList.append(QSharedPointer(new XlsxAxis(XlsxAxis::T_Val, XlsxAxis::Left, 1, 0))); + } - Q_ASSERT(axisList.size()==2 || (axisList.size()==3 && chartType==Chart::CT_Bar3D)); + Q_ASSERT(axisList.size()==2); - for (int i=0; iaxisId)); + } + + writer.writeEndElement(); //c:scatterChart +} + +void ChartPrivate::saveXmlAreaChart(QXmlStreamWriter &writer) const +{ + QString name = chartType==Chart::CT_Area ? QStringLiteral("c:areaChart") : QStringLiteral("c:area3DChart"); + + writer.writeStartElement(name); + + writer.writeEmptyElement(QStringLiteral("grouping")); + + for (int i=0; i(this)->axisList.append(QSharedPointer(new XlsxAxis(XlsxAxis::T_Cat, XlsxAxis::Bottom, 0, 1))); + const_cast(this)->axisList.append(QSharedPointer(new XlsxAxis(XlsxAxis::T_Val, XlsxAxis::Left, 1, 0))); } - writer.writeEndElement(); //pieChart, barChart, ... + //Note: Area3D have 2~3 axes + Q_ASSERT(axisList.size()==2 || (axisList.size()==3 && chartType==Chart::CT_Area3D)); + + for (int i=0; iaxisId)); + } + + writer.writeEndElement(); //lineChart, line3DChart +} + +void ChartPrivate::saveXmlDoughnutChart(QXmlStreamWriter &writer) const +{ + QString name = QStringLiteral("c:doughnutChart"); + + writer.writeStartElement(name); + + writer.writeEmptyElement(QStringLiteral("c:varyColors")); + writer.writeAttribute(QStringLiteral("val"), QStringLiteral("1")); + + for (int i=0; inumRef); writer.writeEndElement();//c:numRef @@ -328,6 +464,10 @@ bool ChartPrivate::loadXmlAxis(QXmlStreamReader &reader) axis->axisPos = XlsxAxis::Bottom; else axis->axisPos = XlsxAxis::Top; + } else if (reader.name() == QLatin1String("axId")) { + axis->axisId = reader.attributes().value(QLatin1String("val")).toString().toInt(); + } else if (reader.name() == QLatin1String("crossAx")) { + axis->crossAx = reader.attributes().value(QLatin1String("val")).toString().toInt(); } } else if (reader.tokenType() == QXmlStreamReader::EndElement && reader.name() == name) { @@ -362,7 +502,7 @@ void ChartPrivate::saveXmlAxes(QXmlStreamWriter &writer) const writer.writeStartElement(name); writer.writeEmptyElement(QStringLiteral("c:axId")); - writer.writeAttribute(QStringLiteral("val"), QString::number(i+1)); + writer.writeAttribute(QStringLiteral("val"), QString::number(axis->axisId)); writer.writeStartElement(QStringLiteral("c:scaling")); writer.writeEmptyElement(QStringLiteral("c:orientation")); @@ -373,7 +513,7 @@ void ChartPrivate::saveXmlAxes(QXmlStreamWriter &writer) const writer.writeAttribute(QStringLiteral("val"), pos); writer.writeEmptyElement(QStringLiteral("c:crossAx")); - writer.writeAttribute(QStringLiteral("val"), QString::number(i%2==0 ? i+2 : i)); + writer.writeAttribute(QStringLiteral("val"), QString::number(axis->crossAx)); writer.writeEndElement();//name } diff --git a/src/xlsx/xlsxchart_p.h b/src/xlsx/xlsxchart_p.h index b0d1fa5..7076150 100644 --- a/src/xlsx/xlsxchart_p.h +++ b/src/xlsx/xlsxchart_p.h @@ -51,7 +51,8 @@ class XlsxSeries { public: - QString numRef; + QString numRef;// For scatterChart, means y values + QString numRef_x; }; class XlsxAxis @@ -75,15 +76,15 @@ public: XlsxAxis(){} - XlsxAxis(Type t, Pos p) - :type(t), axisPos(p) + XlsxAxis(Type t, Pos p, int id, int crossId) + :type(t), axisPos(p), axisId(id), crossAx(crossId) { - axisId = -1; } - int axisId; Type type; Pos axisPos; //l,r,b,t + int axisId; + int crossAx; }; class ChartPrivate : public OOXmlFilePrivate @@ -101,7 +102,12 @@ public: bool loadXmlAxis(QXmlStreamReader &reader); void saveXmlChart(QXmlStreamWriter &writer) const; - void saveXmlXxxChart(QXmlStreamWriter &writer) const; + void saveXmlPieChart(QXmlStreamWriter &writer) const; + void saveXmlBarChart(QXmlStreamWriter &writer) const; + void saveXmlLineChart(QXmlStreamWriter &writer) const; + void saveXmlScatterChart(QXmlStreamWriter &writer) const; + void saveXmlAreaChart(QXmlStreamWriter &writer) const; + void saveXmlDoughnutChart(QXmlStreamWriter &writer) const; void saveXmlSer(QXmlStreamWriter &writer, XlsxSeries *ser, int id) const; void saveXmlAxes(QXmlStreamWriter &writer) const;