Browse Source

Code refactoring: Add more basic chart support

master
Debao Zhang 11 years ago
parent
commit
28f3262e86
  1. 23
      examples/xlsx/chart/main.cpp
  2. 186
      src/xlsx/xlsxchart.cpp
  3. 18
      src/xlsx/xlsxchart_p.h

23
examples/xlsx/chart/main.cpp

@ -30,6 +30,29 @@ int main()
bar3DChart->setChartType(Chart::CT_Bar3D); bar3DChart->setChartType(Chart::CT_Bar3D);
bar3DChart->addSeries(CellRange("A1:A9")); 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] //![1]
//![2] //![2]

186
src/xlsx/xlsxchart.cpp

@ -31,6 +31,7 @@
#include <QIODevice> #include <QIODevice>
#include <QXmlStreamReader> #include <QXmlStreamReader>
#include <QXmlStreamWriter> #include <QXmlStreamWriter>
#include <QDebug>
QT_BEGIN_NAMESPACE_XLSX 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("pie3DChart")) chartType = Chart::CT_Pie3D;
else if (name == QLatin1String("barChart")) chartType = Chart::CT_Bar; else if (name == QLatin1String("barChart")) chartType = Chart::CT_Bar;
else if (name == QLatin1String("bar3DChart")) chartType = Chart::CT_Bar3D; 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: "<<name;
while (!reader.atEnd()) { while (!reader.atEnd()) {
reader.readNextStartElement(); reader.readNextStartElement();
@ -229,7 +237,32 @@ void ChartPrivate::saveXmlChart(QXmlStreamWriter &writer) const
{ {
writer.writeStartElement(QStringLiteral("c:chart")); writer.writeStartElement(QStringLiteral("c:chart"));
writer.writeStartElement(QStringLiteral("c:plotArea")); writer.writeStartElement(QStringLiteral("c:plotArea"));
saveXmlXxxChart(writer); switch (chartType) {
case Chart::CT_Pie:
case Chart::CT_Pie3D:
saveXmlPieChart(writer);
break;
case Chart::CT_Bar:
case Chart::CT_Bar3D:
saveXmlBarChart(writer);
break;
case Chart::CT_Line:
case Chart::CT_Line3D:
saveXmlLineChart(writer);
break;
case Chart::CT_Scatter:
saveXmlScatterChart(writer);
break;
case Chart::CT_Area:
case Chart::CT_Area3D:
saveXmlAreaChart(writer);
break;
case Chart::CT_Doughnut:
saveXmlDoughnutChart(writer);
break;
default:
break;
}
saveXmlAxes(writer); saveXmlAxes(writer);
writer.writeEndElement(); //plotArea writer.writeEndElement(); //plotArea
@ -238,48 +271,148 @@ void ChartPrivate::saveXmlChart(QXmlStreamWriter &writer) const
writer.writeEndElement(); //chart writer.writeEndElement(); //chart
} }
void ChartPrivate::saveXmlXxxChart(QXmlStreamWriter &writer) const void ChartPrivate::saveXmlPieChart(QXmlStreamWriter &writer) const
{ {
QString t; QString name = chartType==Chart::CT_Pie ? QStringLiteral("c:pieChart") : QStringLiteral("c:pie3DChart");
switch (chartType) {
case Chart::CT_Pie: t = QStringLiteral("c:pieChart"); break; writer.writeStartElement(name);
case Chart::CT_Pie3D: t = QStringLiteral("c:pie3DChart"); break;
case Chart::CT_Bar: t = QStringLiteral("c:barChart"); break; //Do the same behavior as Excel, Pie prefer varyColors
case Chart::CT_Bar3D: t = QStringLiteral("c:bar3DChart"); break; writer.writeEmptyElement(QStringLiteral("c:varyColors"));
default: break; writer.writeAttribute(QStringLiteral("val"), QStringLiteral("1"));
for (int i=0; i<seriesList.size(); ++i)
saveXmlSer(writer, seriesList[i].data(), i);
writer.writeEndElement(); //pieChart, pie3DChart
} }
writer.writeStartElement(t); //pieChart, barChart, ... void ChartPrivate::saveXmlBarChart(QXmlStreamWriter &writer) const
{
QString name = chartType==Chart::CT_Bar ? QStringLiteral("c:barChart") : QStringLiteral("c:bar3DChart");
writer.writeStartElement(name);
if (chartType==Chart::CT_Bar || chartType==Chart::CT_Bar3D) {
writer.writeEmptyElement(QStringLiteral("c:barDir")); writer.writeEmptyElement(QStringLiteral("c:barDir"));
writer.writeAttribute(QStringLiteral("val"), QStringLiteral("col")); writer.writeAttribute(QStringLiteral("val"), QStringLiteral("col"));
for (int i=0; i<seriesList.size(); ++i)
saveXmlSer(writer, seriesList[i].data(), i);
if (axisList.isEmpty()) {
//The order the axes??
const_cast<ChartPrivate*>(this)->axisList.append(QSharedPointer<XlsxAxis>(new XlsxAxis(XlsxAxis::T_Cat, XlsxAxis::Bottom, 0, 1)));
const_cast<ChartPrivate*>(this)->axisList.append(QSharedPointer<XlsxAxis>(new XlsxAxis(XlsxAxis::T_Val, XlsxAxis::Left, 1, 0)));
} }
if (chartType==Chart::CT_Pie || chartType==Chart::CT_Pie3D) { //Note: Bar3D have 2~3 axes
//Do the same behavior as Excel, Pie prefer varyColors Q_ASSERT(axisList.size()==2 || (axisList.size()==3 && chartType==Chart::CT_Bar3D));
writer.writeEmptyElement(QStringLiteral("c:varyColors"));
writer.writeAttribute(QStringLiteral("val"), QStringLiteral("1")); for (int i=0; i<axisList.size(); ++i) {
writer.writeEmptyElement(QStringLiteral("c:axId"));
writer.writeAttribute(QStringLiteral("val"), QString::number(axisList[i]->axisId));
} }
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<seriesList.size(); ++i) for (int i=0; i<seriesList.size(); ++i)
saveXmlSer(writer, seriesList[i].data(), i); saveXmlSer(writer, seriesList[i].data(), i);
if (chartType == Chart::CT_Bar || chartType==Chart::CT_Bar3D) {
if (axisList.isEmpty()) { if (axisList.isEmpty()) {
const_cast<ChartPrivate*>(this)->axisList.append(QSharedPointer<XlsxAxis>(new XlsxAxis(XlsxAxis::T_Cat, XlsxAxis::Left))); const_cast<ChartPrivate*>(this)->axisList.append(QSharedPointer<XlsxAxis>(new XlsxAxis(XlsxAxis::T_Cat, XlsxAxis::Bottom, 0, 1)));
const_cast<ChartPrivate*>(this)->axisList.append(QSharedPointer<XlsxAxis>(new XlsxAxis(XlsxAxis::T_Val, XlsxAxis::Bottom))); const_cast<ChartPrivate*>(this)->axisList.append(QSharedPointer<XlsxAxis>(new XlsxAxis(XlsxAxis::T_Val, XlsxAxis::Left, 1, 0)));
if (chartType==Chart::CT_Line3D)
const_cast<ChartPrivate*>(this)->axisList.append(QSharedPointer<XlsxAxis>(new XlsxAxis(XlsxAxis::T_Ser, XlsxAxis::Bottom, 2, 0)));
} }
Q_ASSERT(axisList.size()==2 || (axisList.size()==3 && chartType==Chart::CT_Bar3D)); Q_ASSERT((axisList.size()==2||chartType==Chart::CT_Line)|| (axisList.size()==3 && chartType==Chart::CT_Line3D));
for (int i=0; i<axisList.size(); ++i) {
writer.writeEmptyElement(QStringLiteral("c:axId"));
writer.writeAttribute(QStringLiteral("val"), QString::number(axisList[i]->axisId));
}
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<seriesList.size(); ++i)
saveXmlSer(writer, seriesList[i].data(), i);
if (axisList.isEmpty()) {
const_cast<ChartPrivate*>(this)->axisList.append(QSharedPointer<XlsxAxis>(new XlsxAxis(XlsxAxis::T_Cat, XlsxAxis::Bottom, 0, 1)));
const_cast<ChartPrivate*>(this)->axisList.append(QSharedPointer<XlsxAxis>(new XlsxAxis(XlsxAxis::T_Val, XlsxAxis::Left, 1, 0)));
}
Q_ASSERT(axisList.size()==2);
for (int i=0; i<axisList.size(); ++i) { for (int i=0; i<axisList.size(); ++i) {
writer.writeEmptyElement(QStringLiteral("c:axId")); writer.writeEmptyElement(QStringLiteral("c:axId"));
writer.writeAttribute(QStringLiteral("val"), QString::number(i+1)); writer.writeAttribute(QStringLiteral("val"), QString::number(axisList[i]->axisId));
} }
writer.writeEndElement(); //c:scatterChart
} }
writer.writeEndElement(); //pieChart, barChart, ... 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<seriesList.size(); ++i)
saveXmlSer(writer, seriesList[i].data(), i);
if (axisList.isEmpty()) {
const_cast<ChartPrivate*>(this)->axisList.append(QSharedPointer<XlsxAxis>(new XlsxAxis(XlsxAxis::T_Cat, XlsxAxis::Bottom, 0, 1)));
const_cast<ChartPrivate*>(this)->axisList.append(QSharedPointer<XlsxAxis>(new XlsxAxis(XlsxAxis::T_Val, XlsxAxis::Left, 1, 0)));
}
//Note: Area3D have 2~3 axes
Q_ASSERT(axisList.size()==2 || (axisList.size()==3 && chartType==Chart::CT_Area3D));
for (int i=0; i<axisList.size(); ++i) {
writer.writeEmptyElement(QStringLiteral("c:axId"));
writer.writeAttribute(QStringLiteral("val"), QString::number(axisList[i]->axisId));
}
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; i<seriesList.size(); ++i)
saveXmlSer(writer, seriesList[i].data(), i);
writer.writeStartElement(QStringLiteral("c:holeSize"));
writer.writeAttribute(QStringLiteral("val"), QString::number(50));
writer.writeEndElement();
} }
void ChartPrivate::saveXmlSer(QXmlStreamWriter &writer, XlsxSeries *ser, int id) const void ChartPrivate::saveXmlSer(QXmlStreamWriter &writer, XlsxSeries *ser, int id) const
@ -289,6 +422,9 @@ void ChartPrivate::saveXmlSer(QXmlStreamWriter &writer, XlsxSeries *ser, int id)
writer.writeAttribute(QStringLiteral("val"), QString::number(id)); writer.writeAttribute(QStringLiteral("val"), QString::number(id));
writer.writeEmptyElement(QStringLiteral("c:order")); writer.writeEmptyElement(QStringLiteral("c:order"));
writer.writeAttribute(QStringLiteral("val"), QString::number(id)); writer.writeAttribute(QStringLiteral("val"), QString::number(id));
if (chartType == Chart::CT_Scatter)
writer.writeStartElement(QStringLiteral("c:yVal"));
else
writer.writeStartElement(QStringLiteral("c:val")); writer.writeStartElement(QStringLiteral("c:val"));
writer.writeStartElement(QStringLiteral("c:numRef")); writer.writeStartElement(QStringLiteral("c:numRef"));
writer.writeTextElement(QStringLiteral("c:f"), ser->numRef); writer.writeTextElement(QStringLiteral("c:f"), ser->numRef);
@ -328,6 +464,10 @@ bool ChartPrivate::loadXmlAxis(QXmlStreamReader &reader)
axis->axisPos = XlsxAxis::Bottom; axis->axisPos = XlsxAxis::Bottom;
else else
axis->axisPos = XlsxAxis::Top; 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 } else if (reader.tokenType() == QXmlStreamReader::EndElement
&& reader.name() == name) { && reader.name() == name) {
@ -362,7 +502,7 @@ void ChartPrivate::saveXmlAxes(QXmlStreamWriter &writer) const
writer.writeStartElement(name); writer.writeStartElement(name);
writer.writeEmptyElement(QStringLiteral("c:axId")); 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.writeStartElement(QStringLiteral("c:scaling"));
writer.writeEmptyElement(QStringLiteral("c:orientation")); writer.writeEmptyElement(QStringLiteral("c:orientation"));
@ -373,7 +513,7 @@ void ChartPrivate::saveXmlAxes(QXmlStreamWriter &writer) const
writer.writeAttribute(QStringLiteral("val"), pos); writer.writeAttribute(QStringLiteral("val"), pos);
writer.writeEmptyElement(QStringLiteral("c:crossAx")); 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 writer.writeEndElement();//name
} }

18
src/xlsx/xlsxchart_p.h

@ -51,7 +51,8 @@ class XlsxSeries
{ {
public: public:
QString numRef; QString numRef;// For scatterChart, means y values
QString numRef_x;
}; };
class XlsxAxis class XlsxAxis
@ -75,15 +76,15 @@ public:
XlsxAxis(){} XlsxAxis(){}
XlsxAxis(Type t, Pos p) XlsxAxis(Type t, Pos p, int id, int crossId)
:type(t), axisPos(p) :type(t), axisPos(p), axisId(id), crossAx(crossId)
{ {
axisId = -1;
} }
int axisId;
Type type; Type type;
Pos axisPos; //l,r,b,t Pos axisPos; //l,r,b,t
int axisId;
int crossAx;
}; };
class ChartPrivate : public OOXmlFilePrivate class ChartPrivate : public OOXmlFilePrivate
@ -101,7 +102,12 @@ public:
bool loadXmlAxis(QXmlStreamReader &reader); bool loadXmlAxis(QXmlStreamReader &reader);
void saveXmlChart(QXmlStreamWriter &writer) const; 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 saveXmlSer(QXmlStreamWriter &writer, XlsxSeries *ser, int id) const;
void saveXmlAxes(QXmlStreamWriter &writer) const; void saveXmlAxes(QXmlStreamWriter &writer) const;

Loading…
Cancel
Save