diff --git a/examples/xlsx/chartsheet/chartsheet.pro b/examples/xlsx/chartsheet/chartsheet.pro new file mode 100644 index 0000000..327b163 --- /dev/null +++ b/examples/xlsx/chartsheet/chartsheet.pro @@ -0,0 +1,9 @@ +TARGET = chartsheet + +#include(../../../src/xlsx/qtxlsx.pri) +QT+=xlsx + +CONFIG += console +CONFIG -= app_bundle + +SOURCES += main.cpp diff --git a/examples/xlsx/chartsheet/main.cpp b/examples/xlsx/chartsheet/main.cpp new file mode 100644 index 0000000..c3e7a38 --- /dev/null +++ b/examples/xlsx/chartsheet/main.cpp @@ -0,0 +1,32 @@ +#include +#include "xlsxdocument.h" +#include "xlsxchartsheet.h" +#include "xlsxcellrange.h" +#include "xlsxchart.h" + +using namespace QXlsx; + +int main() +{ + //![0] + Document xlsx; + for (int i=1; i<10; ++i) + xlsx.write(i, 1, i*i); + //![0] + + //![1] + xlsx.addSheet("Chart1", AbstractSheet::ST_ChartSheet); + Chartsheet *sheet = static_cast(xlsx.currentSheet()); + Chart *barChart = sheet->chart(); + barChart->setChartType(Chart::CT_Bar); + barChart->addSeries(CellRange("A1:A9"), xlsx.sheet("Sheet1")); + //![1] + + //![2] + xlsx.saveAs("Book1.xlsx"); + //![2] + + Document xlsx2("Book1.xlsx"); + xlsx2.saveAs("Book2.xlsx"); + return 0; +} diff --git a/examples/xlsx/xlsx.pro b/examples/xlsx/xlsx.pro index d4e75da..c0bedc4 100644 --- a/examples/xlsx/xlsx.pro +++ b/examples/xlsx/xlsx.pro @@ -15,6 +15,7 @@ SUBDIRS = hello \ worksheetoperations \ hyperlinks \ chart \ + chartsheet \ demo qtHaveModule(widgets): SUBDIRS += xlsxwidget diff --git a/src/xlsx/xlsxchart.cpp b/src/xlsx/xlsxchart.cpp index f637a14..86eae8d 100644 --- a/src/xlsx/xlsxchart.cpp +++ b/src/xlsx/xlsxchart.cpp @@ -93,9 +93,13 @@ Chart::~Chart() /*! * Add the data series which is in the range \a range of the \a sheet. */ -void Chart::addSeries(const CellRange &range, Worksheet *sheet) +void Chart::addSeries(const CellRange &range, AbstractSheet *sheet) { Q_D(Chart); + if (sheet && sheet->sheetType() != AbstractSheet::ST_WorkSheet) + return; + if (!sheet && d->sheet->sheetType() != AbstractSheet::ST_WorkSheet) + return; QString serRef = sheet ? sheet->sheetName() : d->sheet->sheetName(); diff --git a/src/xlsx/xlsxchart.h b/src/xlsx/xlsxchart.h index 86febeb..fcd8e2d 100644 --- a/src/xlsx/xlsxchart.h +++ b/src/xlsx/xlsxchart.h @@ -67,7 +67,7 @@ public: ~Chart(); - void addSeries(const CellRange &range, Worksheet *sheet=0); + void addSeries(const CellRange &range, AbstractSheet *sheet=0); void setChartType(ChartType type); void setChartStyle(int id); diff --git a/src/xlsx/xlsxchartsheet.cpp b/src/xlsx/xlsxchartsheet.cpp index 61b6dc3..5cf477c 100644 --- a/src/xlsx/xlsxchartsheet.cpp +++ b/src/xlsx/xlsxchartsheet.cpp @@ -28,6 +28,7 @@ #include "xlsxutility_p.h" #include "xlsxdrawing_p.h" #include "xlsxdrawinganchor_p.h" +#include "xlsxchart.h" #include #include @@ -36,8 +37,9 @@ QT_BEGIN_NAMESPACE_XLSX ChartsheetPrivate::ChartsheetPrivate(Chartsheet *p, Chartsheet::CreateFlag flag) - : AbstractSheetPrivate(p, flag) + : AbstractSheetPrivate(p, flag), chart(0) { + } ChartsheetPrivate::~ChartsheetPrivate() @@ -57,6 +59,21 @@ Chartsheet::Chartsheet(const QString &name, int id, Workbook *workbook, CreateFl :AbstractSheet(name, id, workbook, new ChartsheetPrivate(this, flag)) { setSheetType(ST_ChartSheet); + + if (flag == Chartsheet::F_NewFromScratch) { + d_func()->drawing = QSharedPointer(new Drawing(this, flag)); + + DrawingAbsoluteAnchor *anchor = new DrawingAbsoluteAnchor(drawing(), DrawingAnchor::Picture); + + anchor->pos = QPoint(0, 0); + anchor->ext = QSize(9293679, 6068786); + + QSharedPointer chart = QSharedPointer(new Chart(this, flag)); + chart->setChartType(Chart::CT_Bar); + anchor->setObjectGraphicFrame(chart); + + d_func()->chart = chart.data(); + } } /*! diff --git a/src/xlsx/xlsxdocument.cpp b/src/xlsx/xlsxdocument.cpp index 270a19d..c08af12 100644 --- a/src/xlsx/xlsxdocument.cpp +++ b/src/xlsx/xlsxdocument.cpp @@ -246,18 +246,34 @@ bool DocumentPrivate::savePackage(QIODevice *device) const DocPropsApp docPropsApp(DocPropsApp::F_NewFromScratch); DocPropsCore docPropsCore(DocPropsCore::F_NewFromScratch); - // save sheet xml files - for (int i=0; isheetCount(); ++i) { - AbstractSheet *sheet = workbook->sheet(i); - if (sheet->sheetType() == AbstractSheet::ST_WorkSheet) { - contentTypes->addWorksheetName(QStringLiteral("sheet%1").arg(i+1)); - docPropsApp.addPartTitle(sheet->sheetName()); - - zipWriter.addFile(QStringLiteral("xl/worksheets/sheet%1.xml").arg(i+1), sheet->saveToXmlData()); - Relationships *rel = sheet->relationships(); - if (!rel->isEmpty()) - zipWriter.addFile(QStringLiteral("xl/worksheets/_rels/sheet%1.xml.rels").arg(i+1), rel->saveToXmlData()); - } + // save worksheet xml files + QList > worksheets = workbook->getSheetsByTypes(AbstractSheet::ST_WorkSheet); + if (!worksheets.isEmpty()) + docPropsApp.addHeadingPair(QStringLiteral("Worksheets"), worksheets.size()); + for (int i=0; i sheet = worksheets[i]; + contentTypes->addWorksheetName(QStringLiteral("sheet%1").arg(i+1)); + docPropsApp.addPartTitle(sheet->sheetName()); + + zipWriter.addFile(QStringLiteral("xl/worksheets/sheet%1.xml").arg(i+1), sheet->saveToXmlData()); + Relationships *rel = sheet->relationships(); + if (!rel->isEmpty()) + zipWriter.addFile(QStringLiteral("xl/worksheets/_rels/sheet%1.xml.rels").arg(i+1), rel->saveToXmlData()); + } + + //save chartsheet xml files + QList > chartsheets = workbook->getSheetsByTypes(AbstractSheet::ST_ChartSheet); + if (!chartsheets.isEmpty()) + docPropsApp.addHeadingPair(QStringLiteral("Chartsheets"), chartsheets.size()); + for (int i=0; i sheet = chartsheets[i]; + contentTypes->addWorksheetName(QStringLiteral("sheet%1").arg(i+1)); + docPropsApp.addPartTitle(sheet->sheetName()); + + zipWriter.addFile(QStringLiteral("xl/chartsheets/sheet%1.xml").arg(i+1), sheet->saveToXmlData()); + Relationships *rel = sheet->relationships(); + if (!rel->isEmpty()) + zipWriter.addFile(QStringLiteral("xl/chartsheets/_rels/sheet%1.xml.rels").arg(i+1), rel->saveToXmlData()); } // save external links xml files @@ -291,8 +307,6 @@ bool DocumentPrivate::savePackage(QIODevice *device) const docPropsApp.setProperty(name, q->documentProperty(name)); docPropsCore.setProperty(name, q->documentProperty(name)); } - if (workbook->sheetCount()) - docPropsApp.addHeadingPair(QStringLiteral("Worksheets"), workbook->sheetCount()); contentTypes->addDocPropApp(); contentTypes->addDocPropCore(); zipWriter.addFile(QStringLiteral("docProps/app.xml"), docPropsApp.saveToXmlData()); diff --git a/src/xlsx/xlsxworkbook.cpp b/src/xlsx/xlsxworkbook.cpp index e1ce433..7d9d574 100755 --- a/src/xlsx/xlsxworkbook.cpp +++ b/src/xlsx/xlsxworkbook.cpp @@ -26,6 +26,7 @@ #include "xlsxworkbook_p.h" #include "xlsxsharedstrings_p.h" #include "xlsxworksheet.h" +#include "xlsxchartsheet.h" #include "xlsxstyles_p.h" #include "xlsxformat.h" #include "xlsxworksheet_p.h" @@ -61,7 +62,8 @@ WorkbookPrivate::WorkbookPrivate(Workbook *q, Workbook::CreateFlag flag) : firstsheet = 0; table_count = 0; - last_sheet_index = 0; + last_worksheet_index = 0; + last_chartsheet_index = 0; last_sheet_id = 0; } @@ -195,9 +197,16 @@ AbstractSheet *Workbook::addSheet(const QString &name, int sheetId, AbstractShee Q_D(Workbook); if (sheetId > d->last_sheet_id) d->last_sheet_id = sheetId; - - Worksheet *sheet = new Worksheet(name, sheetId, this, F_LoadFromExists); - d->sheets.append(QSharedPointer(sheet)); + AbstractSheet *sheet=0; + if (type == AbstractSheet::ST_WorkSheet) { + sheet = new Worksheet(name, sheetId, this, F_LoadFromExists); + } else if (type == AbstractSheet::ST_ChartSheet) { + sheet = new Chartsheet(name, sheetId, this, F_LoadFromExists); + } else { + qWarning("unsupported sheet type."); + Q_ASSERT(false); + } + d->sheets.append(QSharedPointer(sheet)); d->sheetNames.append(name); return sheet; } @@ -205,22 +214,37 @@ AbstractSheet *Workbook::addSheet(const QString &name, int sheetId, AbstractShee AbstractSheet *Workbook::insertSheet(int index, const QString &name, AbstractSheet::SheetType type) { Q_D(Workbook); - QString worksheetName = createSafeSheetName(name); - if (!worksheetName.isEmpty()) { + QString sheetName = createSafeSheetName(name); + if (!sheetName.isEmpty()) { //If user given an already in-used name, we should not continue any more! - if (d->sheetNames.contains(worksheetName)) + if (d->sheetNames.contains(sheetName)) return 0; } else { - do { - ++d->last_sheet_index; - worksheetName = QStringLiteral("Sheet%1").arg(d->last_sheet_index); - } while (d->sheetNames.contains(worksheetName)); + if (type == AbstractSheet::ST_WorkSheet) { + do { + ++d->last_worksheet_index; + sheetName = QStringLiteral("Sheet%1").arg(d->last_worksheet_index); + } while (d->sheetNames.contains(sheetName)); + } else if (type == AbstractSheet::ST_ChartSheet) { + do { + ++d->last_chartsheet_index; + sheetName = QStringLiteral("Chart%1").arg(d->last_chartsheet_index); + } while (d->sheetNames.contains(sheetName)); + } else { + qWarning("unsupported sheet type."); + return 0; + } } ++d->last_sheet_id; - Worksheet *sheet = new Worksheet(worksheetName, d->last_sheet_id, this, F_NewFromScratch); - d->sheets.insert(index, QSharedPointer(sheet)); - d->sheetNames.insert(index, worksheetName); + AbstractSheet *sheet; + if (type == AbstractSheet::ST_WorkSheet) + sheet = new Worksheet(sheetName, d->last_sheet_id, this, F_NewFromScratch); + else + sheet = new Chartsheet(sheetName, d->last_sheet_id, this, F_NewFromScratch); + + d->sheets.insert(index, QSharedPointer(sheet)); + d->sheetNames.insert(index, sheetName); d->activesheetIndex = index; return sheet; } @@ -384,6 +408,20 @@ QList Workbook::drawings() return ds; } +/*! + * \internal + */ +QList > Workbook::getSheetsByTypes(AbstractSheet::SheetType type) const +{ + Q_D(const Workbook); + QList > list; + for (int i=0; isheets.size(); ++i) { + if (d->sheets[i]->sheetType() == type) + list.append(d->sheets[i]); + } + return list; +} + void Workbook::saveToXmlFile(QIODevice *device) const { Q_D(const Workbook); @@ -424,8 +462,10 @@ void Workbook::saveToXmlFile(QIODevice *device) const writer.writeEndElement();//bookViews writer.writeStartElement(QStringLiteral("sheets")); - for (int i=0; isheets.size(); ++i) { - QSharedPointer sheet = d->sheets[i]; + //work sheets + QList > worksheets = getSheetsByTypes(AbstractSheet::ST_WorkSheet); + for (int i=0; i sheet = worksheets[i]; writer.writeEmptyElement(QStringLiteral("sheet")); writer.writeAttribute(QStringLiteral("name"), sheet->sheetName()); writer.writeAttribute(QStringLiteral("sheetId"), QString::number(sheet->sheetId())); @@ -435,6 +475,20 @@ void Workbook::saveToXmlFile(QIODevice *device) const d->relationships->addDocumentRelationship(QStringLiteral("/worksheet"), QStringLiteral("worksheets/sheet%1.xml").arg(i+1)); writer.writeAttribute(QStringLiteral("r:id"), QStringLiteral("rId%1").arg(d->relationships->count())); } + + //chart sheets + QList > chartsheets = getSheetsByTypes(AbstractSheet::ST_ChartSheet); + for (int i=0; i sheet = chartsheets[i]; + writer.writeEmptyElement(QStringLiteral("sheet")); + writer.writeAttribute(QStringLiteral("name"), sheet->sheetName()); + writer.writeAttribute(QStringLiteral("sheetId"), QString::number(sheet->sheetId())); + if (sheet->isHidden()) + writer.writeAttribute(QStringLiteral("state"), QStringLiteral("hidden")); + + d->relationships->addDocumentRelationship(QStringLiteral("/chartsheet"), QStringLiteral("chartsheets/sheet%1.xml").arg(i+1)); + writer.writeAttribute(QStringLiteral("r:id"), QStringLiteral("rId%1").arg(d->relationships->count())); + } writer.writeEndElement();//sheets if (d->externalLinks.size() > 0) { diff --git a/src/xlsx/xlsxworkbook.h b/src/xlsx/xlsxworkbook.h index 7420434..288e853 100755 --- a/src/xlsx/xlsxworkbook.h +++ b/src/xlsx/xlsxworkbook.h @@ -102,6 +102,7 @@ private: Theme *theme(); QList images(); QList drawings(); + QList > getSheetsByTypes(AbstractSheet::SheetType type) const; QStringList worksheetNames() const; AbstractSheet *addSheet(const QString &name, int sheetId, AbstractSheet::SheetType type = AbstractSheet::ST_WorkSheet); }; diff --git a/src/xlsx/xlsxworkbook_p.h b/src/xlsx/xlsxworkbook_p.h index d8ccfbd..727d97f 100644 --- a/src/xlsx/xlsxworkbook_p.h +++ b/src/xlsx/xlsxworkbook_p.h @@ -96,7 +96,8 @@ public: int table_count; //Used to generate new sheet name and id - int last_sheet_index; + int last_worksheet_index; + int last_chartsheet_index; int last_sheet_id; };