Mercurial > clickerconvert
diff src/xlsx/xlsxchart.cpp @ 1:93d3106bb9a4
Add qt xlsx library
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Tue, 22 Mar 2016 10:38:08 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xlsx/xlsxchart.cpp Tue Mar 22 10:38:08 2016 +0100 @@ -0,0 +1,645 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me> +** All right reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ + +#include "xlsxchart_p.h" +#include "xlsxworksheet.h" +#include "xlsxcellrange.h" +#include "xlsxutility_p.h" + +#include <QIODevice> +#include <QXmlStreamReader> +#include <QXmlStreamWriter> +#include <QDebug> + +QT_BEGIN_NAMESPACE_XLSX + +ChartPrivate::ChartPrivate(Chart *q, Chart::CreateFlag flag) + :AbstractOOXmlFilePrivate(q, flag), chartType(static_cast<Chart::ChartType>(0)) +{ + +} + +ChartPrivate::~ChartPrivate() +{ + +} + +/*! + * \class Chart + * \inmodule QtXlsx + * \brief Main class for the charts. + */ + +/*! + \enum Chart::ChartType + + \value CT_Area + \value CT_Area3D, + \value CT_Line, + \value CT_Line3D, + \value CT_Scatter, + \value CT_Pie, + \value CT_Pie3D, + \value CT_Doughnut, + \value CT_Bar, + \value CT_Bar3D, + + \omitvalue CT_Stock, + \omitvalue CT_Radar, + \omitvalue CT_OfPie, + \omitvalue CT_Surface, + \omitvalue CT_Surface3D, + \omitvalue CT_Bubble +*/ + +/*! + * \internal + */ +Chart::Chart(AbstractSheet *parent, CreateFlag flag) + :AbstractOOXmlFile(new ChartPrivate(this, flag)) +{ + d_func()->sheet = parent; +} + +/*! + * Destroys the chart. + */ +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) +{ + Q_D(Chart); + if (!range.isValid()) + return; + if (sheet && sheet->sheetType() != AbstractSheet::ST_WorkSheet) + return; + if (!sheet && d->sheet->sheetType() != AbstractSheet::ST_WorkSheet) + return; + + QString sheetName = sheet ? sheet->sheetName() : d->sheet->sheetName(); + //In case sheetName contains space or ' + sheetName = escapeSheetName(sheetName); + + if (range.columnCount() == 1 || range.rowCount() == 1) { + QSharedPointer<XlsxSeries> series = QSharedPointer<XlsxSeries>(new XlsxSeries); + series->numberDataSource_numRef = sheetName + QLatin1String("!") + range.toString(true, true); + d->seriesList.append(series); + } else if (range.columnCount() < range.rowCount()) { + //Column based series + int firstDataColumn = range.firstColumn(); + QString axDataSouruce_numRef; + if (d->chartType == CT_Scatter || d->chartType == CT_Bubble) { + firstDataColumn += 1; + CellRange subRange(range.firstRow(), range.firstColumn(), range.lastRow(), range.firstColumn()); + axDataSouruce_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true); + } + + for (int col=firstDataColumn; col<=range.lastColumn(); ++col) { + CellRange subRange(range.firstRow(), col, range.lastRow(), col); + QSharedPointer<XlsxSeries> series = QSharedPointer<XlsxSeries>(new XlsxSeries); + series->axDataSource_numRef = axDataSouruce_numRef; + series->numberDataSource_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true); + d->seriesList.append(series); + } + + } else { + //Row based series + int firstDataRow = range.firstRow(); + QString axDataSouruce_numRef; + if (d->chartType == CT_Scatter || d->chartType == CT_Bubble) { + firstDataRow += 1; + CellRange subRange(range.firstRow(), range.firstColumn(), range.firstRow(), range.lastColumn()); + axDataSouruce_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true); + } + + for (int row=firstDataRow; row<=range.lastRow(); ++row) { + CellRange subRange(row, range.firstColumn(), row, range.lastColumn()); + QSharedPointer<XlsxSeries> series = QSharedPointer<XlsxSeries>(new XlsxSeries); + series->axDataSource_numRef = axDataSouruce_numRef; + series->numberDataSource_numRef = sheetName + QLatin1String("!") + subRange.toString(true, true); + d->seriesList.append(series); + } + } +} + +/*! + * Set the type of the chart to \a type + */ +void Chart::setChartType(ChartType type) +{ + Q_D(Chart); + d->chartType = type; +} + +/*! + * \internal + * + */ +void Chart::setChartStyle(int id) +{ + Q_UNUSED(id) + //!Todo +} + +/*! + * \internal + */ +void Chart::saveToXmlFile(QIODevice *device) const +{ + Q_D(const Chart); + + QXmlStreamWriter writer(device); + + writer.writeStartDocument(QStringLiteral("1.0"), true); + writer.writeStartElement(QStringLiteral("c:chartSpace")); + writer.writeAttribute(QStringLiteral("xmlns:c"), QStringLiteral("http://schemas.openxmlformats.org/drawingml/2006/chart")); + writer.writeAttribute(QStringLiteral("xmlns:a"), QStringLiteral("http://schemas.openxmlformats.org/drawingml/2006/main")); + writer.writeAttribute(QStringLiteral("xmlns:r"), QStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/relationships")); + + d->saveXmlChart(writer); + + writer.writeEndElement();//c:chartSpace + writer.writeEndDocument(); +} + +/*! + * \internal + */ +bool Chart::loadFromXmlFile(QIODevice *device) +{ + Q_D(Chart); + + QXmlStreamReader reader(device); + while (!reader.atEnd()) { + reader.readNextStartElement(); + if (reader.tokenType() == QXmlStreamReader::StartElement) { + if (reader.name() == QLatin1String("chart")) { + if (!d->loadXmlChart(reader)) + return false; + } + } + } + return true; +} + +bool ChartPrivate::loadXmlChart(QXmlStreamReader &reader) +{ + Q_ASSERT(reader.name() == QLatin1String("chart")); + + while (!reader.atEnd()) { + reader.readNextStartElement(); + if (reader.tokenType() == QXmlStreamReader::StartElement) { + if (reader.name() == QLatin1String("plotArea")) { + if (!loadXmlPlotArea(reader)) + return false; + } else if (reader.name() == QLatin1String("legend")) { + //!Todo + } + } else if (reader.tokenType() == QXmlStreamReader::EndElement && + reader.name() == QLatin1String("chart")) { + break; + } + } + return true; +} + +bool ChartPrivate::loadXmlPlotArea(QXmlStreamReader &reader) +{ + Q_ASSERT(reader.name() == QLatin1String("plotArea")); + + while (!reader.atEnd()) { + reader.readNextStartElement(); + if (reader.tokenType() == QXmlStreamReader::StartElement) { + if (reader.name() == QLatin1String("layout")) { + //!ToDo + } else if (reader.name().endsWith(QLatin1String("Chart"))) { + //For pieChart, barChart, ... + loadXmlXxxChart(reader); + } else if (reader.name().endsWith(QLatin1String("Ax"))) { + //For valAx, catAx, serAx, dateAx + loadXmlAxis(reader); + } + + } else if (reader.tokenType() == QXmlStreamReader::EndElement && + reader.name() == QLatin1String("plotArea")) { + break; + } + } + return true; +} + +bool ChartPrivate::loadXmlXxxChart(QXmlStreamReader &reader) +{ + QStringRef name = reader.name(); + if (name == QLatin1String("pieChart")) chartType = Chart::CT_Pie; + 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: "<<name; + + while (!reader.atEnd()) { + reader.readNextStartElement(); + if (reader.tokenType() == QXmlStreamReader::StartElement) { + if (reader.name() == QLatin1String("ser")) { + loadXmlSer(reader); + } else if (reader.name() == QLatin1String("axId")) { + + } + } else if (reader.tokenType() == QXmlStreamReader::EndElement + && reader.name() == name) { + break; + } + } + return true; +} + +bool ChartPrivate::loadXmlSer(QXmlStreamReader &reader) +{ + Q_ASSERT(reader.name() == QLatin1String("ser")); + + QSharedPointer<XlsxSeries> series = QSharedPointer<XlsxSeries>(new XlsxSeries); + seriesList.append(series); + + while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement + && reader.name() == QLatin1String("ser"))) { + if (reader.readNextStartElement()) { + QStringRef name = reader.name(); + if (name == QLatin1String("cat") || name == QLatin1String("xVal")) { + while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement + && reader.name() == name)) { + if (reader.readNextStartElement()) { + if (reader.name() == QLatin1String("numRef")) + series->axDataSource_numRef = loadXmlNumRef(reader); + } + } + } else if (name == QLatin1String("val") || name == QLatin1String("yVal")) { + while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement + && reader.name() == name)) { + if (reader.readNextStartElement()) { + if (reader.name() == QLatin1String("numRef")) + series->numberDataSource_numRef = loadXmlNumRef(reader); + } + } + } else if (name == QLatin1String("extLst")) { + while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement + && reader.name() == name)) { + reader.readNextStartElement(); + } + } + } + } + + return true; +} + + +QString ChartPrivate::loadXmlNumRef(QXmlStreamReader &reader) +{ + Q_ASSERT(reader.name() == QLatin1String("numRef")); + + while (!reader.atEnd() && !(reader.tokenType() == QXmlStreamReader::EndElement + && reader.name() == QLatin1String("numRef"))) { + if (reader.readNextStartElement()) { + if (reader.name() == QLatin1String("f")) + return reader.readElementText(); + } + } + + return QString(); +} + +void ChartPrivate::saveXmlChart(QXmlStreamWriter &writer) const +{ + writer.writeStartElement(QStringLiteral("c:chart")); + writer.writeStartElement(QStringLiteral("c:plotArea")); + 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); + writer.writeEndElement(); //plotArea + +// saveXmlLegend(writer); + + writer.writeEndElement(); //chart +} + +void ChartPrivate::saveXmlPieChart(QXmlStreamWriter &writer) const +{ + QString name = chartType==Chart::CT_Pie ? QStringLiteral("c:pieChart") : QStringLiteral("c:pie3DChart"); + + writer.writeStartElement(name); + + //Do the same behavior as Excel, Pie prefer varyColors + 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.writeEndElement(); //pieChart, pie3DChart +} + +void ChartPrivate::saveXmlBarChart(QXmlStreamWriter &writer) const +{ + QString name = chartType==Chart::CT_Bar ? QStringLiteral("c:barChart") : QStringLiteral("c:bar3DChart"); + + writer.writeStartElement(name); + + writer.writeEmptyElement(QStringLiteral("c:barDir")); + 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))); + } + + //Note: Bar3D have 2~3 axes + Q_ASSERT(axisList.size()==2 || (axisList.size()==3 && chartType==Chart::CT_Bar3D)); + + 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) + 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))); + 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||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_Val, 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) { + writer.writeEmptyElement(QStringLiteral("c:axId")); + writer.writeAttribute(QStringLiteral("val"), QString::number(axisList[i]->axisId)); + } + + 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<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 +{ + 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)); + + if (!ser->axDataSource_numRef.isEmpty()) { + if (chartType == Chart::CT_Scatter || chartType == Chart::CT_Bubble) + writer.writeStartElement(QStringLiteral("c:xVal")); + else + writer.writeStartElement(QStringLiteral("c:cat")); + writer.writeStartElement(QStringLiteral("c:numRef")); + writer.writeTextElement(QStringLiteral("c:f"), ser->axDataSource_numRef); + writer.writeEndElement();//c:numRef + writer.writeEndElement();//c:cat or c:xVal + } + + if (!ser->numberDataSource_numRef.isEmpty()) { + if (chartType == Chart::CT_Scatter || chartType == Chart::CT_Bubble) + writer.writeStartElement(QStringLiteral("c:yVal")); + else + writer.writeStartElement(QStringLiteral("c:val")); + writer.writeStartElement(QStringLiteral("c:numRef")); + writer.writeTextElement(QStringLiteral("c:f"), ser->numberDataSource_numRef); + writer.writeEndElement();//c:numRef + writer.writeEndElement();//c:val or c:yVal + } + + writer.writeEndElement();//c:ser +} + +bool ChartPrivate::loadXmlAxis(QXmlStreamReader &reader) +{ + 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; + + axisList.append(QSharedPointer<XlsxAxis>(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.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) { + break; + } + } + + return true; +} + +void ChartPrivate::saveXmlAxes(QXmlStreamWriter &writer) const +{ + for (int i=0; i<axisList.size(); ++i) { + XlsxAxis *axis = 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(axis->axisId)); + + 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(axis->crossAx)); + + writer.writeEndElement();//name + } +} + +QT_END_NAMESPACE_XLSX