mirror of
https://github.com/QtExcel/QXlsx.git
synced 2025-01-30 05:02:52 +08:00
+ Extended handling of the headers in a BarChart
+ Added enabling of legend in a BarChart + Added enabling of Grid lines in a BarChart + Added test class for extended BarChart
This commit is contained in:
parent
246a85a419
commit
49347a26b5
@ -30,7 +30,7 @@ public:
|
|||||||
CT_OfPieChart, CT_SurfaceChart, CT_Surface3DChart,
|
CT_OfPieChart, CT_SurfaceChart, CT_Surface3DChart,
|
||||||
CT_BubbleChart,
|
CT_BubbleChart,
|
||||||
};
|
};
|
||||||
enum ChartAxisPos { Left, Right, Top, Bottom };
|
enum ChartAxisPos { None=-1, Left=0, Right, Top, Bottom };
|
||||||
private:
|
private:
|
||||||
friend class AbstractSheet;
|
friend class AbstractSheet;
|
||||||
friend class Worksheet;
|
friend class Worksheet;
|
||||||
@ -41,11 +41,15 @@ private:
|
|||||||
public:
|
public:
|
||||||
~Chart();
|
~Chart();
|
||||||
public:
|
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 setChartType(ChartType type);
|
||||||
void setChartStyle(int id);
|
void setChartStyle(int id);
|
||||||
void setAxisTitle(Chart::ChartAxisPos pos, QString axisTitle);
|
void setAxisTitle(Chart::ChartAxisPos pos, QString axisTitle);
|
||||||
void setChartTitle(QString strchartTitle);
|
void setChartTitle(QString strchartTitle);
|
||||||
|
void setChartLegend(Chart::ChartAxisPos legendPos, bool overlap = false);
|
||||||
|
void setGridlinesEnable(bool majorGridlinesEnable = false, bool minorGridlinesEnable = false);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool loadFromXmlFile(QIODevice *device);
|
bool loadFromXmlFile(QIODevice *device);
|
||||||
void saveToXmlFile(QIODevice *device) const;
|
void saveToXmlFile(QIODevice *device) const;
|
||||||
|
@ -22,8 +22,11 @@ class XlsxSeries
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
//At present, we care about number cell ranges only!
|
//At present, we care about number cell ranges only!
|
||||||
QString numberDataSource_numRef; // yval, val
|
QString numberDataSource_numRef = ""; // yval, val
|
||||||
QString axDataSource_numRef; // xval, cat
|
QString axDataSource_numRef = ""; // xval, cat
|
||||||
|
QString headerH_numRef = "";
|
||||||
|
QString headerV_numRef = "";
|
||||||
|
bool swapHeader = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class XlsxAxis
|
class XlsxAxis
|
||||||
@ -76,7 +79,9 @@ public:
|
|||||||
bool loadXmlXxxChart(QXmlStreamReader &reader);
|
bool loadXmlXxxChart(QXmlStreamReader &reader);
|
||||||
bool loadXmlSer(QXmlStreamReader &reader);
|
bool loadXmlSer(QXmlStreamReader &reader);
|
||||||
QString loadXmlNumRef(QXmlStreamReader &reader);
|
QString loadXmlNumRef(QXmlStreamReader &reader);
|
||||||
|
QString loadXmlStrRef(QXmlStreamReader &reader);
|
||||||
bool loadXmlChartTitle(QXmlStreamReader &reader);
|
bool loadXmlChartTitle(QXmlStreamReader &reader);
|
||||||
|
bool loadXmlChartLegend(QXmlStreamReader &reader);
|
||||||
protected:
|
protected:
|
||||||
bool loadXmlChartTitleTx(QXmlStreamReader &reader);
|
bool loadXmlChartTitleTx(QXmlStreamReader &reader);
|
||||||
bool loadXmlChartTitleTxRich(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_pPr(QXmlStreamReader &reader, XlsxAxis* axis);
|
||||||
bool loadXmlAxisEG_AxShared_Title_Tx_Rich_P_R(QXmlStreamReader &reader, XlsxAxis* axis);
|
bool loadXmlAxisEG_AxShared_Title_Tx_Rich_P_R(QXmlStreamReader &reader, XlsxAxis* axis);
|
||||||
|
|
||||||
|
QString readSubTree(QXmlStreamReader &reader);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void saveXmlChart(QXmlStreamWriter &writer) const;
|
void saveXmlChart(QXmlStreamWriter &writer) const;
|
||||||
void saveXmlChartTitle(QXmlStreamWriter &writer) const;
|
void saveXmlChartTitle(QXmlStreamWriter &writer) const;
|
||||||
@ -108,6 +115,8 @@ public:
|
|||||||
void saveXmlDoughnutChart(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 saveXmlAxis(QXmlStreamWriter &writer) const;
|
void saveXmlAxis(QXmlStreamWriter &writer) const;
|
||||||
|
void saveXmlChartLegend(QXmlStreamWriter &writer) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void saveXmlAxisCatAx(QXmlStreamWriter &writer, XlsxAxis* axis) const;
|
void saveXmlAxisCatAx(QXmlStreamWriter &writer, XlsxAxis* axis) const;
|
||||||
void saveXmlAxisDateAx(QXmlStreamWriter &writer, XlsxAxis* axis) const;
|
void saveXmlAxisDateAx(QXmlStreamWriter &writer, XlsxAxis* axis) const;
|
||||||
@ -126,6 +135,12 @@ public:
|
|||||||
QMap< XlsxAxis::AxisPos, QString > axisNames;
|
QMap< XlsxAxis::AxisPos, QString > axisNames;
|
||||||
QString chartTitle;
|
QString chartTitle;
|
||||||
AbstractSheet* sheet;
|
AbstractSheet* sheet;
|
||||||
|
Chart::ChartAxisPos legendPos;
|
||||||
|
bool legendOverlay;
|
||||||
|
bool majorGridlinesEnabled;
|
||||||
|
bool minorGridlinesEnabled;
|
||||||
|
|
||||||
|
QString layout; // only for storing a readed file
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE_XLSX
|
QT_END_NAMESPACE_XLSX
|
||||||
|
@ -48,7 +48,14 @@ ChartPrivate::~ChartPrivate()
|
|||||||
Chart::Chart(AbstractSheet *parent, CreateFlag flag)
|
Chart::Chart(AbstractSheet *parent, CreateFlag flag)
|
||||||
: AbstractOOXmlFile(new ChartPrivate(this, flag))
|
: AbstractOOXmlFile(new ChartPrivate(this, flag))
|
||||||
{
|
{
|
||||||
|
Q_D(Chart);
|
||||||
|
|
||||||
d_func()->sheet = parent;
|
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.
|
* 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);
|
Q_D(Chart);
|
||||||
|
|
||||||
@ -82,10 +89,12 @@ void Chart::addSeries(const CellRange &range, AbstractSheet *sheet)
|
|||||||
series->numberDataSource_numRef = sheetName + QLatin1String("!") + range.toString(true, true);
|
series->numberDataSource_numRef = sheetName + QLatin1String("!") + range.toString(true, true);
|
||||||
d->seriesList.append(series);
|
d->seriesList.append(series);
|
||||||
}
|
}
|
||||||
else if (range.columnCount() < range.rowCount())
|
else if ((range.columnCount() < range.rowCount()) || swapHeaders )
|
||||||
{
|
{
|
||||||
//Column based series
|
//Column based series
|
||||||
|
int firstDataRow = range.firstRow();
|
||||||
int firstDataColumn = range.firstColumn();
|
int firstDataColumn = range.firstColumn();
|
||||||
|
|
||||||
QString axDataSouruce_numRef;
|
QString axDataSouruce_numRef;
|
||||||
if (d->chartType == CT_ScatterChart || d->chartType == CT_BubbleChart)
|
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);
|
axDataSouruce_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( headerH )
|
||||||
|
{
|
||||||
|
firstDataRow += 1;
|
||||||
|
}
|
||||||
|
if( headerV )
|
||||||
|
{
|
||||||
|
firstDataColumn += 1;
|
||||||
|
}
|
||||||
|
|
||||||
for (int col=firstDataColumn; col<=range.lastColumn(); ++col)
|
for (int col=firstDataColumn; col<=range.lastColumn(); ++col)
|
||||||
{
|
{
|
||||||
CellRange subRange(range.firstRow(), col, range.lastRow(), col);
|
CellRange subRange(firstDataRow, col, range.lastRow(), col);
|
||||||
QSharedPointer<XlsxSeries> series = QSharedPointer<XlsxSeries>(new XlsxSeries);
|
QSharedPointer<XlsxSeries> series = QSharedPointer<XlsxSeries>(new XlsxSeries);
|
||||||
series->axDataSource_numRef = axDataSouruce_numRef;
|
series->axDataSource_numRef = axDataSouruce_numRef;
|
||||||
series->numberDataSource_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true);
|
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);
|
d->seriesList.append(series);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,6 +147,8 @@ void Chart::addSeries(const CellRange &range, AbstractSheet *sheet)
|
|||||||
{
|
{
|
||||||
//Row based series
|
//Row based series
|
||||||
int firstDataRow = range.firstRow();
|
int firstDataRow = range.firstRow();
|
||||||
|
int firstDataColumn = range.firstColumn();
|
||||||
|
|
||||||
QString axDataSouruce_numRef;
|
QString axDataSouruce_numRef;
|
||||||
if (d->chartType == CT_ScatterChart || d->chartType == CT_BubbleChart)
|
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);
|
axDataSouruce_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( headerH )
|
||||||
|
{
|
||||||
|
firstDataRow += 1;
|
||||||
|
}
|
||||||
|
if( headerV )
|
||||||
|
{
|
||||||
|
firstDataColumn += 1;
|
||||||
|
}
|
||||||
|
|
||||||
for (int row=firstDataRow; row<=range.lastRow(); ++row)
|
for (int row=firstDataRow; row<=range.lastRow(); ++row)
|
||||||
{
|
{
|
||||||
CellRange subRange(row, range.firstColumn(), row, range.lastColumn());
|
CellRange subRange(row, firstDataColumn, row, range.lastColumn());
|
||||||
QSharedPointer<XlsxSeries> series = QSharedPointer<XlsxSeries>(new XlsxSeries);
|
QSharedPointer<XlsxSeries> series = QSharedPointer<XlsxSeries>(new XlsxSeries);
|
||||||
series->axDataSource_numRef = axDataSouruce_numRef;
|
series->axDataSource_numRef = axDataSouruce_numRef;
|
||||||
series->numberDataSource_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true);
|
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);
|
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
|
* \internal
|
||||||
*/
|
*/
|
||||||
@ -270,15 +360,22 @@ bool Chart::loadFromXmlFile(QIODevice *device)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool ChartPrivate::loadXmlChart(QXmlStreamReader &reader)
|
bool ChartPrivate::loadXmlChart(QXmlStreamReader &reader)
|
||||||
{
|
{
|
||||||
Q_ASSERT(reader.name() == QLatin1String("chart"));
|
Q_ASSERT(reader.name() == QLatin1String("chart"));
|
||||||
|
|
||||||
|
// qDebug() << "-------------- loadXmlChart";
|
||||||
|
|
||||||
while (!reader.atEnd())
|
while (!reader.atEnd())
|
||||||
{
|
{
|
||||||
reader.readNextStartElement();
|
reader.readNextStartElement();
|
||||||
|
|
||||||
|
// qDebug() << "-------------1- " << reader.name();
|
||||||
|
|
||||||
if (reader.tokenType() == QXmlStreamReader::StartElement)
|
if (reader.tokenType() == QXmlStreamReader::StartElement)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (reader.name() == QLatin1String("plotArea"))
|
if (reader.name() == QLatin1String("plotArea"))
|
||||||
{
|
{
|
||||||
if (!loadXmlPlotArea(reader))
|
if (!loadXmlPlotArea(reader))
|
||||||
@ -295,10 +392,11 @@ bool ChartPrivate::loadXmlChart(QXmlStreamReader &reader)
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (reader.name() == QLatin1String("legend"))
|
// else if (reader.name() == QLatin1String("legend"))
|
||||||
{
|
// {
|
||||||
//!Todo
|
// loadXmlChartLegend(reader);
|
||||||
}
|
// qDebug() << "-------------- loadXmlChartLegend";
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
else if (reader.tokenType() == QXmlStreamReader::EndElement &&
|
else if (reader.tokenType() == QXmlStreamReader::EndElement &&
|
||||||
reader.name() == QLatin1String("chart") )
|
reader.name() == QLatin1String("chart") )
|
||||||
@ -347,6 +445,8 @@ bool ChartPrivate::loadXmlPlotArea(QXmlStreamReader &reader)
|
|||||||
|
|
||||||
while (!reader.atEnd())
|
while (!reader.atEnd())
|
||||||
{
|
{
|
||||||
|
// qDebug() << "-------------2- " << reader.name();
|
||||||
|
|
||||||
if (reader.isStartElement())
|
if (reader.isStartElement())
|
||||||
{
|
{
|
||||||
if (!loadXmlPlotAreaElement(reader))
|
if (!loadXmlPlotAreaElement(reader))
|
||||||
@ -354,6 +454,11 @@ bool ChartPrivate::loadXmlPlotArea(QXmlStreamReader &reader)
|
|||||||
qDebug() << "[debug] failed to load plotarea element.";
|
qDebug() << "[debug] failed to load plotarea element.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
else if (reader.name() == QLatin1String("legend")) // Why here?
|
||||||
|
{
|
||||||
|
loadXmlChartLegend(reader);
|
||||||
|
// qDebug() << "-------------- loadXmlChartLegend";
|
||||||
|
}
|
||||||
|
|
||||||
reader.readNext();
|
reader.readNext();
|
||||||
}
|
}
|
||||||
@ -370,8 +475,8 @@ bool ChartPrivate::loadXmlPlotAreaElement(QXmlStreamReader &reader)
|
|||||||
{
|
{
|
||||||
if (reader.name() == QLatin1String("layout"))
|
if (reader.name() == QLatin1String("layout"))
|
||||||
{
|
{
|
||||||
//!ToDo
|
//!ToDo extract attributes
|
||||||
// layout
|
layout = readSubTree(reader);
|
||||||
}
|
}
|
||||||
else if (reader.name().endsWith(QLatin1String("Chart")))
|
else if (reader.name().endsWith(QLatin1String("Chart")))
|
||||||
{
|
{
|
||||||
@ -555,8 +660,22 @@ bool ChartPrivate::loadXmlSer(QXmlStreamReader &reader)
|
|||||||
{
|
{
|
||||||
if (reader.readNextStartElement())
|
if (reader.readNextStartElement())
|
||||||
{
|
{
|
||||||
|
//TODO beide Header noch auswerten RTR 2019.11
|
||||||
QStringRef name = reader.name();
|
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") )
|
name == QLatin1String("xVal") )
|
||||||
{
|
{
|
||||||
while ( !reader.atEnd() &&
|
while ( !reader.atEnd() &&
|
||||||
@ -567,6 +686,9 @@ bool ChartPrivate::loadXmlSer(QXmlStreamReader &reader)
|
|||||||
{
|
{
|
||||||
if (reader.name() == QLatin1String("numRef"))
|
if (reader.name() == QLatin1String("numRef"))
|
||||||
series->axDataSource_numRef = loadXmlNumRef(reader);
|
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();
|
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
|
void ChartPrivate::saveXmlChart(QXmlStreamWriter &writer) const
|
||||||
{
|
{
|
||||||
//----------------------------------------------------
|
//----------------------------------------------------
|
||||||
@ -625,13 +766,18 @@ void ChartPrivate::saveXmlChart(QXmlStreamWriter &writer) const
|
|||||||
//----------------------------------------------------
|
//----------------------------------------------------
|
||||||
// c:title
|
// c:title
|
||||||
|
|
||||||
saveXmlChartTitle(writer); // wrtie 'chart title'
|
saveXmlChartTitle(writer); // write 'chart title'
|
||||||
|
|
||||||
//----------------------------------------------------
|
//----------------------------------------------------
|
||||||
// c:plotArea
|
// c:plotArea
|
||||||
|
|
||||||
writer.writeStartElement(QStringLiteral("c:plotArea"));
|
writer.writeStartElement(QStringLiteral("c:plotArea"));
|
||||||
|
|
||||||
|
// a little workaround for Start- and EndElement with starting ">" and ending without ">"
|
||||||
|
writer.device()->write("><c:layout>"); //layout
|
||||||
|
writer.device()->write(layout.toUtf8());
|
||||||
|
writer.device()->write("</c:layout"); //layout
|
||||||
|
|
||||||
// dev35
|
// dev35
|
||||||
switch (chartType)
|
switch (chartType)
|
||||||
{
|
{
|
||||||
@ -663,7 +809,8 @@ void ChartPrivate::saveXmlChart(QXmlStreamWriter &writer) const
|
|||||||
|
|
||||||
writer.writeEndElement(); // c:plotArea
|
writer.writeEndElement(); // c:plotArea
|
||||||
|
|
||||||
//!TODO: save-legend // c:legend
|
// c:legend
|
||||||
|
saveXmlChartLegend(writer); // c:legend
|
||||||
|
|
||||||
writer.writeEndElement(); // c:chart
|
writer.writeEndElement(); // c:chart
|
||||||
}
|
}
|
||||||
@ -760,7 +907,7 @@ bool ChartPrivate::loadXmlChartTitleTxRichP_R(QXmlStreamReader &reader)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// wrtie 'chart title'
|
// write 'chart title'
|
||||||
void ChartPrivate::saveXmlChartTitle(QXmlStreamWriter &writer) const
|
void ChartPrivate::saveXmlChartTitle(QXmlStreamWriter &writer) const
|
||||||
{
|
{
|
||||||
if ( chartTitle.isEmpty() )
|
if ( chartTitle.isEmpty() )
|
||||||
@ -903,6 +1050,62 @@ void ChartPrivate::saveXmlChartTitle(QXmlStreamWriter &writer) const
|
|||||||
}
|
}
|
||||||
// }}
|
// }}
|
||||||
|
|
||||||
|
|
||||||
|
// write 'chart legend'
|
||||||
|
void ChartPrivate::saveXmlChartLegend(QXmlStreamWriter &writer) const
|
||||||
|
{
|
||||||
|
if ( legendPos == Chart::ChartAxisPos::None )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// <c:legend>
|
||||||
|
// <c:legendPos val="r"/>
|
||||||
|
// <c:overlay val="0"/>
|
||||||
|
// </c:legend>
|
||||||
|
|
||||||
|
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
|
void ChartPrivate::saveXmlPieChart(QXmlStreamWriter &writer) const
|
||||||
{
|
{
|
||||||
QString name = chartType == Chart::CT_PieChart ? QStringLiteral("c:pieChart") : QStringLiteral("c:pie3DChart");
|
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
|
void ChartPrivate::saveXmlSer(QXmlStreamWriter &writer, XlsxSeries *ser, int id) const
|
||||||
{
|
{
|
||||||
|
|
||||||
writer.writeStartElement(QStringLiteral("c:ser"));
|
writer.writeStartElement(QStringLiteral("c:ser"));
|
||||||
writer.writeEmptyElement(QStringLiteral("c:idx"));
|
writer.writeEmptyElement(QStringLiteral("c:idx"));
|
||||||
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));
|
||||||
|
|
||||||
|
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 (!ser->axDataSource_numRef.isEmpty())
|
||||||
{
|
{
|
||||||
if (chartType == Chart::CT_ScatterChart || chartType == Chart::CT_BubbleChart)
|
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:numRef
|
||||||
writer.writeEndElement();//c:cat or c:xVal
|
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)
|
if (chartType == Chart::CT_ScatterChart || chartType == Chart::CT_BubbleChart)
|
||||||
writer.writeStartElement(QStringLiteral("c:yVal"));
|
writer.writeStartElement(QStringLiteral("c:yVal"));
|
||||||
else
|
else
|
||||||
@ -1274,11 +1511,13 @@ bool ChartPrivate::loadXmlAxisEG_AxShared(QXmlStreamReader &reader, XlsxAxis* ax
|
|||||||
}
|
}
|
||||||
else if ( reader.name() == QLatin1String("majorGridlines") )
|
else if ( reader.name() == QLatin1String("majorGridlines") )
|
||||||
{
|
{
|
||||||
//!TODO
|
//!TODO anything else?
|
||||||
|
majorGridlinesEnabled = true;
|
||||||
}
|
}
|
||||||
else if ( reader.name() == QLatin1String("minorGridlines") )
|
else if ( reader.name() == QLatin1String("minorGridlines") )
|
||||||
{
|
{
|
||||||
//!TODO
|
//!TODO anything else?
|
||||||
|
minorGridlinesEnabled = true;
|
||||||
}
|
}
|
||||||
else if ( reader.name() == QLatin1String("title") )
|
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
|
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
|
saveXmlAxisEG_AxShared_Title(writer, axis); // "c:title" CT_Title
|
||||||
|
|
||||||
writer.writeEmptyElement(QStringLiteral("c:crossAx")); // crossAx (mandatory value)
|
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("</" + reader.qualifiedName().toString() + ">");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
QT_END_NAMESPACE_XLSX
|
||||||
|
@ -36,6 +36,7 @@ DEFINES += QT_DEPRECATED_WARNINGS
|
|||||||
SOURCES += \
|
SOURCES += \
|
||||||
calendar.cpp \
|
calendar.cpp \
|
||||||
chart.cpp \
|
chart.cpp \
|
||||||
|
chartextended.cpp \
|
||||||
chartsheet.cpp \
|
chartsheet.cpp \
|
||||||
datavalidation.cpp \
|
datavalidation.cpp \
|
||||||
definename.cpp \
|
definename.cpp \
|
||||||
|
84
TestExcel/chartextended.cpp
Normal file
84
TestExcel/chartextended.cpp
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
// chart.cpp
|
||||||
|
|
||||||
|
#include <QtGlobal>
|
||||||
|
#include <QtCore>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
@ -35,6 +35,13 @@ int definename()
|
|||||||
xlsx.write(12, 3, "=SUM(MyCol_3)*Factor");
|
xlsx.write(12, 3, "=SUM(MyCol_3)*Factor");
|
||||||
//![2]
|
//![2]
|
||||||
|
|
||||||
xlsx.saveAs("definename.xlsx");
|
xlsx.saveAs("definename1.xlsx");
|
||||||
|
|
||||||
|
Document xlsx2("definename1.xlsx");
|
||||||
|
if ( xlsx2.load() )
|
||||||
|
{
|
||||||
|
xlsx2.saveAs("definename2.xlsx");
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ using namespace QXlsx;
|
|||||||
extern int hello();
|
extern int hello();
|
||||||
extern int calendar();
|
extern int calendar();
|
||||||
extern int chart();
|
extern int chart();
|
||||||
|
extern int chartExtended();
|
||||||
extern int chartsheet();
|
extern int chartsheet();
|
||||||
extern int datavalidation();
|
extern int datavalidation();
|
||||||
extern int definename();
|
extern int definename();
|
||||||
@ -55,6 +56,7 @@ int main(int argc, char *argv[])
|
|||||||
readStyle();
|
readStyle();
|
||||||
calendar();
|
calendar();
|
||||||
chart();
|
chart();
|
||||||
|
chartExtended();
|
||||||
chartsheet();
|
chartsheet();
|
||||||
datavalidation();
|
datavalidation();
|
||||||
definename();
|
definename();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user