From d82003e707409db8c58f3517d66022c7b883d581 Mon Sep 17 00:00:00 2001 From: 123 <1239877983@qq.com> Date: Sat, 12 Apr 2025 21:02:37 +0800 Subject: [PATCH] 2025-04-12T21:02:36 --- experiment_data/analysis_state/sample.xlsx | Bin 0 -> 47735 bytes src/AnalysTool.pro | 190 +- src/data/filemanager.cpp | 6 +- src/data/filemanager.h | 21 +- src/data/pointcalculate.cpp | 22 +- src/data/pointcalculate.h | 4 +- src/data/xlsxhandler.cpp | 71 + src/data/xlsxhandler.h | 15 + src/global.h | 28 +- src/main.cpp | 11 +- src/thirdparty/QtXlsxWriter-0.3.0/.gitignore | 45 + src/thirdparty/QtXlsxWriter-0.3.0/.qmake.conf | 6 + src/thirdparty/QtXlsxWriter-0.3.0/README.md | 135 + .../QtXlsxWriter-0.3.0/examples/examples.pro | 3 + .../examples/xlsx/calendar/calendar.pro | 9 + .../examples/xlsx/calendar/main.cpp | 145 + .../examples/xlsx/chart/chart.pro | 9 + .../examples/xlsx/chart/main.cpp | 78 + .../examples/xlsx/chartsheet/chartsheet.pro | 9 + .../examples/xlsx/chartsheet/main.cpp | 32 + .../conditionalformatting.pro | 9 + .../doc/src/conditionalformatting.qdoc | 10 + .../xlsx/conditionalformatting/main.cpp | 76 + .../xlsx/datavalidation/datavalidation.pro | 9 + .../examples/xlsx/datavalidation/main.cpp | 22 + .../examples/xlsx/definename/definename.pro | 9 + .../examples/xlsx/definename/main.cpp | 33 + .../examples/xlsx/demo/demo.pro | 9 + .../xlsx/demo/doc/images/xlsx_demo.gif | Bin 0 -> 222011 bytes .../examples/xlsx/demo/doc/src/demo.qdoc | 8 + .../examples/xlsx/demo/main.cpp | 296 +++ .../doc/images/doc_property.png | Bin 0 -> 32276 bytes .../doc/src/documentproperty.qdoc | 11 + .../documentproperty/documentproperty.pro | 10 + .../examples/xlsx/documentproperty/main.cpp | 20 + .../xlsx/extractdata/doc/src/extractdata.qdoc | 16 + .../examples/xlsx/extractdata/extractdata.pro | 9 + .../examples/xlsx/extractdata/main.cpp | 41 + .../xlsx/formulas/doc/src/formulas.qdoc | 24 + .../examples/xlsx/formulas/formulas.pro | 9 + .../examples/xlsx/formulas/main.cpp | 92 + .../examples/xlsx/hello/doc/images/hello.png | Bin 0 -> 15311 bytes .../examples/xlsx/hello/doc/src/hello.qdoc | 22 + .../examples/xlsx/hello/hello.pro | 9 + .../examples/xlsx/hello/main.cpp | 25 + .../examples/xlsx/hyperlinks/hyperlinks.pro | 9 + .../examples/xlsx/hyperlinks/main.cpp | 25 + .../examples/xlsx/image/image.pro | 9 + .../examples/xlsx/image/main.cpp | 19 + .../mergecells/doc/images/xlsx-mergecells.png | Bin 0 -> 30545 bytes .../xlsx/mergecells/doc/src/mergecells.qdoc | 19 + .../examples/xlsx/mergecells/main.cpp | 26 + .../examples/xlsx/mergecells/mergecells.pro | 9 + .../examples/xlsx/numberformat/main.cpp | 52 + .../xlsx/numberformat/numberformat.pro | 12 + .../xlsx/richtext/doc/images/richtext.png | Bin 0 -> 23923 bytes .../xlsx/richtext/doc/src/richtext.qdoc | 11 + .../examples/xlsx/richtext/main.cpp | 43 + .../examples/xlsx/richtext/richtext.pro | 9 + .../examples/xlsx/rowcolumn/main.cpp | 38 + .../examples/xlsx/rowcolumn/rowcolumn.pro | 9 + .../examples/xlsx/style/doc/src/style.qdoc | 10 + .../examples/xlsx/style/main.cpp | 48 + .../examples/xlsx/style/style.pro | 9 + .../doc/src/worksheetoperations.qdoc | 8 + .../xlsx/worksheetoperations/main.cpp | 53 + .../worksheetoperations.pro | 9 + .../QtXlsxWriter-0.3.0/examples/xlsx/xlsx.pro | 23 + .../examples/xlsx/xlsxwidget/main.cpp | 41 + .../xlsx/xlsxwidget/xlsxsheetmodel.cpp | 205 ++ .../examples/xlsx/xlsxwidget/xlsxsheetmodel.h | 63 + .../xlsx/xlsxwidget/xlsxsheetmodel_p.h | 56 + .../examples/xlsx/xlsxwidget/xlsxwidget.pro | 12 + src/thirdparty/QtXlsxWriter-0.3.0/qtxlsx.pro | 1 + src/thirdparty/QtXlsxWriter-0.3.0/src/src.pro | 3 + .../src/xlsx/doc/qtxlsx.qdocconf | 75 + .../src/xlsx/doc/snippets/doc_src_qtxlsx.cpp | 8 + .../src/xlsx/doc/snippets/doc_src_qtxlsx.pro | 3 + .../src/xlsx/doc/src/examples.qdoc | 8 + .../src/xlsx/doc/src/qtxlsx-index.qdoc | 72 + .../src/xlsx/doc/src/qtxlsx.qdoc | 36 + .../src/xlsx/doc/src/usage.qdoc | 83 + .../QtXlsxWriter-0.3.0/src/xlsx/qtxlsx.pri | 84 + .../QtXlsxWriter-0.3.0/src/xlsx/xlsx.pro | 16 + .../src/xlsx/xlsxabstractooxmlfile.cpp | 119 + .../src/xlsx/xlsxabstractooxmlfile.h | 70 + .../src/xlsx/xlsxabstractooxmlfile_p.h | 64 + .../src/xlsx/xlsxabstractsheet.cpp | 206 ++ .../src/xlsx/xlsxabstractsheet.h | 76 + .../src/xlsx/xlsxabstractsheet_p.h | 64 + .../QtXlsxWriter-0.3.0/src/xlsx/xlsxcell.cpp | 178 ++ .../QtXlsxWriter-0.3.0/src/xlsx/xlsxcell.h | 77 + .../QtXlsxWriter-0.3.0/src/xlsx/xlsxcell_p.h | 69 + .../src/xlsx/xlsxcellformula.cpp | 259 ++ .../src/xlsx/xlsxcellformula.h | 78 + .../src/xlsx/xlsxcellformula_p.h | 64 + .../src/xlsx/xlsxcellrange.cpp | 147 ++ .../src/xlsx/xlsxcellrange.h | 79 + .../src/xlsx/xlsxcellreference.cpp | 174 ++ .../src/xlsx/xlsxcellreference.h | 66 + .../QtXlsxWriter-0.3.0/src/xlsx/xlsxchart.cpp | 645 +++++ .../QtXlsxWriter-0.3.0/src/xlsx/xlsxchart.h | 89 + .../QtXlsxWriter-0.3.0/src/xlsx/xlsxchart_p.h | 125 + .../src/xlsx/xlsxchartsheet.cpp | 159 ++ .../src/xlsx/xlsxchartsheet.h | 56 + .../src/xlsx/xlsxchartsheet_p.h | 56 + .../QtXlsxWriter-0.3.0/src/xlsx/xlsxcolor.cpp | 198 ++ .../QtXlsxWriter-0.3.0/src/xlsx/xlsxcolor_p.h | 92 + .../src/xlsx/xlsxconditionalformatting.cpp | 735 ++++++ .../src/xlsx/xlsxconditionalformatting.h | 135 + .../src/xlsx/xlsxconditionalformatting_p.h | 131 + .../src/xlsx/xlsxcontenttypes.cpp | 205 ++ .../src/xlsx/xlsxcontenttypes_p.h | 88 + .../src/xlsx/xlsxdatavalidation.cpp | 552 ++++ .../src/xlsx/xlsxdatavalidation.h | 123 + .../src/xlsx/xlsxdatavalidation_p.h | 69 + .../src/xlsx/xlsxdocpropsapp.cpp | 157 ++ .../src/xlsx/xlsxdocpropsapp_p.h | 72 + .../src/xlsx/xlsxdocpropscore.cpp | 168 ++ .../src/xlsx/xlsxdocpropscore_p.h | 65 + .../src/xlsx/xlsxdocument.cpp | 1046 ++++++++ .../src/xlsx/xlsxdocument.h | 133 + .../src/xlsx/xlsxdocument_p.h | 69 + .../src/xlsx/xlsxdrawing.cpp | 87 + .../src/xlsx/xlsxdrawing_p.h | 72 + .../src/xlsx/xlsxdrawinganchor.cpp | 529 ++++ .../src/xlsx/xlsxdrawinganchor_p.h | 151 ++ .../src/xlsx/xlsxformat.cpp | 1432 ++++++++++ .../QtXlsxWriter-0.3.0/src/xlsx/xlsxformat.h | 282 ++ .../src/xlsx/xlsxformat_p.h | 161 ++ .../QtXlsxWriter-0.3.0/src/xlsx/xlsxglobal.h | 49 + .../src/xlsx/xlsxmediafile.cpp | 99 + .../src/xlsx/xlsxmediafile_p.h | 80 + .../src/xlsx/xlsxnumformatparser.cpp | 94 + .../src/xlsx/xlsxnumformatparser_p.h | 51 + .../src/xlsx/xlsxrelationships.cpp | 189 ++ .../src/xlsx/xlsxrelationships_p.h | 87 + .../src/xlsx/xlsxrichstring.cpp | 343 +++ .../src/xlsx/xlsxrichstring.h | 89 + .../src/xlsx/xlsxrichstring_p.h | 60 + .../src/xlsx/xlsxsharedstrings.cpp | 400 +++ .../src/xlsx/xlsxsharedstrings_p.h | 98 + .../src/xlsx/xlsxsimpleooxmlfile.cpp | 56 + .../src/xlsx/xlsxsimpleooxmlfile_p.h | 59 + .../src/xlsx/xlsxstyles.cpp | 1334 ++++++++++ .../src/xlsx/xlsxstyles_p.h | 139 + .../QtXlsxWriter-0.3.0/src/xlsx/xlsxtheme.cpp | 237 ++ .../QtXlsxWriter-0.3.0/src/xlsx/xlsxtheme_p.h | 59 + .../src/xlsx/xlsxutility.cpp | 276 ++ .../src/xlsx/xlsxutility_p.h | 68 + .../src/xlsx/xlsxworkbook.cpp | 693 +++++ .../src/xlsx/xlsxworkbook.h | 114 + .../src/xlsx/xlsxworkbook_p.h | 107 + .../src/xlsx/xlsxworksheet.cpp | 2344 +++++++++++++++++ .../src/xlsx/xlsxworksheet.h | 158 ++ .../src/xlsx/xlsxworksheet_p.h | 233 ++ .../src/xlsx/xlsxzipreader.cpp | 74 + .../src/xlsx/xlsxzipreader_p.h | 67 + .../src/xlsx/xlsxzipwriter.cpp | 68 + .../src/xlsx/xlsxzipwriter_p.h | 63 + .../QtXlsxWriter-0.3.0/sync.profile | 7 + .../QtXlsxWriter-0.3.0/tests/auto/auto.pro | 16 + .../auto/cellreference/cellreference.pro | 19 + .../cellreference/tst_cellreferencetest.cpp | 83 + .../tests/auto/cmake/CMakeLists.txt | 9 + .../tests/auto/cmake/cmake.pro | 7 + .../tests/auto/document/document.pro | 13 + .../tests/auto/document/tst_documenttest.cpp | 365 +++ .../tests/auto/format/format.pro | 12 + .../tests/auto/format/tst_formattest.cpp | 57 + .../tests/auto/propsapp/propsapp.pro | 13 + .../auto/propsapp/tst_docpropsapptest.cpp | 44 + .../tests/auto/propscore/propscore.pro | 13 + .../auto/propscore/tst_propscoretest.cpp | 46 + .../auto/relationships/relationships.pro | 19 + .../relationships/tst_relationshipstest.cpp | 47 + .../tests/auto/richstring/richstring.pro | 12 + .../auto/richstring/tst_richstringtest.cpp | 41 + .../auto/sharedstrings/sharedstrings.pro | 13 + .../sharedstrings/tst_sharedstringstest.cpp | 164 ++ .../tests/auto/styles/styles.pro | 13 + .../tests/auto/styles/tst_stylestest.cpp | 171 ++ .../tests/auto/utility/tst_utilitytest.cpp | 223 ++ .../tests/auto/utility/utility.pro | 18 + .../tests/auto/worksheet/tst_worksheet.cpp | 302 +++ .../tests/auto/worksheet/worksheet.pro | 18 + .../tst_conditionalformattingtest.cpp | 103 + .../xlsxconditionalformatting.pro | 12 + .../auto/zipreader/tst_zipreadertest.cpp | 40 + .../tests/auto/zipreader/zipreader.pro | 18 + .../tests/benchmarks/benchmarks.pro | 3 + .../benchmarks/xmlspace/tst_xmlspacetest.cpp | 98 + .../tests/benchmarks/xmlspace/xmlspace.pro | 13 + .../QtXlsxWriter-0.3.0/tests/tests.pro | 2 + src/ui/centralwidget.cpp | 4 +- src/ui/centralwidget.h | 2 +- src/{ => ui}/rightwidget.cpp | 0 src/{ => ui}/rightwidget.h | 0 src/ui/specificheatcomparisonmethodform.cpp | 2 +- 199 files changed, 22191 insertions(+), 135 deletions(-) create mode 100644 experiment_data/analysis_state/sample.xlsx create mode 100644 src/data/xlsxhandler.cpp create mode 100644 src/data/xlsxhandler.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/.gitignore create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/.qmake.conf create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/README.md create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/examples.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/calendar/calendar.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/calendar/main.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/chart/chart.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/chart/main.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/chartsheet/chartsheet.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/chartsheet/main.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/conditionalformatting/conditionalformatting.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/conditionalformatting/doc/src/conditionalformatting.qdoc create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/conditionalformatting/main.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/datavalidation/datavalidation.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/datavalidation/main.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/definename/definename.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/definename/main.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/demo/demo.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/demo/doc/images/xlsx_demo.gif create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/demo/doc/src/demo.qdoc create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/demo/main.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/documentproperty/doc/images/doc_property.png create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/documentproperty/doc/src/documentproperty.qdoc create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/documentproperty/documentproperty.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/documentproperty/main.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/extractdata/doc/src/extractdata.qdoc create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/extractdata/extractdata.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/extractdata/main.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/formulas/doc/src/formulas.qdoc create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/formulas/formulas.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/formulas/main.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/hello/doc/images/hello.png create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/hello/doc/src/hello.qdoc create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/hello/hello.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/hello/main.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/hyperlinks/hyperlinks.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/hyperlinks/main.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/image/image.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/image/main.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/mergecells/doc/images/xlsx-mergecells.png create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/mergecells/doc/src/mergecells.qdoc create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/mergecells/main.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/mergecells/mergecells.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/numberformat/main.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/numberformat/numberformat.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/richtext/doc/images/richtext.png create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/richtext/doc/src/richtext.qdoc create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/richtext/main.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/richtext/richtext.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/rowcolumn/main.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/rowcolumn/rowcolumn.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/style/doc/src/style.qdoc create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/style/main.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/style/style.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/worksheetoperations/doc/src/worksheetoperations.qdoc create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/worksheetoperations/main.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/worksheetoperations/worksheetoperations.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/xlsx.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/xlsxwidget/main.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/xlsxwidget/xlsxsheetmodel.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/xlsxwidget/xlsxsheetmodel.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/xlsxwidget/xlsxsheetmodel_p.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/xlsxwidget/xlsxwidget.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/qtxlsx.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/src.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/doc/qtxlsx.qdocconf create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/doc/snippets/doc_src_qtxlsx.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/doc/snippets/doc_src_qtxlsx.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/doc/src/examples.qdoc create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/doc/src/qtxlsx-index.qdoc create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/doc/src/qtxlsx.qdoc create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/doc/src/usage.qdoc create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/qtxlsx.pri create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsx.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxabstractooxmlfile.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxabstractooxmlfile.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxabstractooxmlfile_p.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxabstractsheet.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxabstractsheet.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxabstractsheet_p.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcell.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcell.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcell_p.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcellformula.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcellformula.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcellformula_p.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcellrange.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcellrange.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcellreference.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcellreference.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxchart.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxchart.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxchart_p.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxchartsheet.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxchartsheet.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxchartsheet_p.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcolor.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcolor_p.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxconditionalformatting.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxconditionalformatting.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxconditionalformatting_p.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcontenttypes.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcontenttypes_p.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdatavalidation.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdatavalidation.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdatavalidation_p.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdocpropsapp.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdocpropsapp_p.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdocpropscore.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdocpropscore_p.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdocument.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdocument.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdocument_p.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdrawing.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdrawing_p.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdrawinganchor.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdrawinganchor_p.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxformat.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxformat.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxformat_p.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxglobal.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxmediafile.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxmediafile_p.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxnumformatparser.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxnumformatparser_p.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxrelationships.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxrelationships_p.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxrichstring.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxrichstring.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxrichstring_p.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxsharedstrings.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxsharedstrings_p.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxsimpleooxmlfile.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxsimpleooxmlfile_p.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxstyles.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxstyles_p.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxtheme.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxtheme_p.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxutility.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxutility_p.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxworkbook.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxworkbook.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxworkbook_p.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxworksheet.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxworksheet.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxworksheet_p.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxzipreader.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxzipreader_p.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxzipwriter.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxzipwriter_p.h create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/sync.profile create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/tests/auto/auto.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/tests/auto/cellreference/cellreference.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/tests/auto/cellreference/tst_cellreferencetest.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/tests/auto/cmake/CMakeLists.txt create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/tests/auto/cmake/cmake.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/tests/auto/document/document.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/tests/auto/document/tst_documenttest.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/tests/auto/format/format.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/tests/auto/format/tst_formattest.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/tests/auto/propsapp/propsapp.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/tests/auto/propsapp/tst_docpropsapptest.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/tests/auto/propscore/propscore.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/tests/auto/propscore/tst_propscoretest.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/tests/auto/relationships/relationships.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/tests/auto/relationships/tst_relationshipstest.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/tests/auto/richstring/richstring.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/tests/auto/richstring/tst_richstringtest.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/tests/auto/sharedstrings/sharedstrings.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/tests/auto/sharedstrings/tst_sharedstringstest.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/tests/auto/styles/styles.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/tests/auto/styles/tst_stylestest.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/tests/auto/utility/tst_utilitytest.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/tests/auto/utility/utility.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/tests/auto/worksheet/tst_worksheet.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/tests/auto/worksheet/worksheet.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/tests/auto/xlsxconditionalformatting/tst_conditionalformattingtest.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/tests/auto/xlsxconditionalformatting/xlsxconditionalformatting.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/tests/auto/zipreader/tst_zipreadertest.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/tests/auto/zipreader/zipreader.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/tests/benchmarks/benchmarks.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/tests/benchmarks/xmlspace/tst_xmlspacetest.cpp create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/tests/benchmarks/xmlspace/xmlspace.pro create mode 100644 src/thirdparty/QtXlsxWriter-0.3.0/tests/tests.pro rename src/{ => ui}/rightwidget.cpp (100%) rename src/{ => ui}/rightwidget.h (100%) diff --git a/experiment_data/analysis_state/sample.xlsx b/experiment_data/analysis_state/sample.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..866245e668e068f1845521a330400a8f645ba106 GIT binary patch literal 47735 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 &dataVtr) +void readExperimentFile(const QString fileName, QVector &dataVtr) { if(fileName.isEmpty()){ return; @@ -90,7 +90,7 @@ void readExperimentFile(const QString fileName, QVector &dataVtr QString line = in.readLine(); QStringList values = line.split(" "); if (values.size() == 2) { - ExperimentData data; + Global::ExperimentData data; data.sampleTemp = values[0].toFloat(); data.dsc = values[1].toFloat(); // dataVtr.append(data); diff --git a/src/data/filemanager.h b/src/data/filemanager.h index 2e2c430..1d472f3 100644 --- a/src/data/filemanager.h +++ b/src/data/filemanager.h @@ -3,9 +3,11 @@ #include #include -#include +#include +#include #include "protocol.h" +#include "global.h" namespace FileManager{ const QString ExperimentDirPath = QDir::currentPath()+"/../experiment_data"; @@ -13,27 +15,14 @@ const QString SampleDataFloder = ExperimentDirPath + "/sample_data"; const QString BaseLineFolder = ExperimentDirPath + "/base_line"; const QString AnalysisStateFolder = ExperimentDirPath + "/analysis_state"; -struct ExperimentData { - float sampleTemp; - float dsc; -}; - -struct ExpeInfo -{ - QString sampleName; - float sampleWeight; - QString date; - QString userName; -}; - -extern ExpeInfo _expeInfo; +extern Global::ExpeInfo _expeInfo; extern QFile _expeFile; void createExperimentFile(); void writeExperimentFile(const CommonData&); void close(); -void readExperimentFile(const QString fileName,QVector&); +void readExperimentFile(const QString fileName,QVector&); void test(); }; diff --git a/src/data/pointcalculate.cpp b/src/data/pointcalculate.cpp index 01e881d..ff94c92 100644 --- a/src/data/pointcalculate.cpp +++ b/src/data/pointcalculate.cpp @@ -3,11 +3,11 @@ #include "pointcalculate.h" #include "logger.h" -QVectorPointCalculate:: _dataVtr; +QVectorPointCalculate:: _dataVtr; QPointF PointCalculate::_peakPoint; QPointF PointCalculate::_leftSelectedPoint,PointCalculate::_rightSelectedPoint; -void PointCalculate::setExperimentData(const QVector &dataVtr) +void PointCalculate::setExperimentData(const QVector &dataVtr) { _dataVtr = dataVtr; @@ -15,8 +15,8 @@ void PointCalculate::setExperimentData(const QVector PointCalculate::getPeakPointGroup() { QVector pointVtr; - for(FileManager::ExperimentData& ed:_dataVtr) { + for(Global::ExperimentData& ed:_dataVtr) { if(ed.sampleTemp >= _leftSelectedPoint.x() && ed.sampleTemp <= _rightSelectedPoint.x()){ pointVtr.push_back(QPointF(ed.sampleTemp,ed.dsc)); @@ -274,7 +274,7 @@ void PointCalculate::updateStartEndPoint() { //需要在a1和a2之间查询是否有高于a1和a2之间的点,若存在,则重新给a1、a2赋值 - for(FileManager::ExperimentData& ed:_dataVtr){ + for(Global::ExperimentData& ed:_dataVtr){ if(ed.sampleTemp > _leftSelectedPoint.x() && ed.sampleTemp < _peakPoint.x()){ if(ed.dsc > _leftSelectedPoint.y()){ _leftSelectedPoint.setX(ed.sampleTemp); @@ -333,7 +333,7 @@ QPointF PointCalculate::calculateIntersection(const QPointF p1,const QPointF p2, QPair PointCalculate::getCurveInflectionPointTangent(const float x1,const float x2) { std::vector dataVtr; - for(FileManager::ExperimentData& ed:_dataVtr){ + for(Global::ExperimentData& ed:_dataVtr){ if(x1 < ed.sampleTemp && ed.sampleTemp < x2){ dataVtr.push_back(ed.sampleTemp); } @@ -374,7 +374,7 @@ QPointF PointCalculate::getClosestPointByX(const float targetX) QPointF resultPointF; float minDiff = std::numeric_limits::max(); - for(FileManager::ExperimentData &ed:_dataVtr){ + for(Global::ExperimentData &ed:_dataVtr){ float diff = std::abs(ed.sampleTemp - targetX); if (diff < minDiff) { minDiff = diff; @@ -429,8 +429,8 @@ QPair PointCalculate::getStartAndEndPoint() return qMakePair(QPointF(), QPointF()); } - FileManager::ExperimentData startPoint = _dataVtr.at(0); - FileManager::ExperimentData endPoint = _dataVtr.at(_dataVtr.size() - 1); + Global::ExperimentData startPoint = _dataVtr.at(0); + Global::ExperimentData endPoint = _dataVtr.at(_dataVtr.size() - 1); return qMakePair( QPointF(startPoint.sampleTemp,startPoint.dsc), @@ -457,7 +457,7 @@ QPointF PointCalculate::getClosestPointByY(const float left,const float right,co float minValue = std::numeric_limits::infinity(); // 初始化为正无穷 QPointF closestPoint; - for (const FileManager::ExperimentData& ed : _dataVtr) { + for (const Global::ExperimentData& ed : _dataVtr) { if (left < ed.sampleTemp && ed.sampleTemp < right) { float diff = std::abs(ed.dsc - valueY); if (diff < minValue) { diff --git a/src/data/pointcalculate.h b/src/data/pointcalculate.h index 9deb811..d05f3bc 100644 --- a/src/data/pointcalculate.h +++ b/src/data/pointcalculate.h @@ -6,7 +6,7 @@ #include "filemanager.h" namespace PointCalculate{ -void setExperimentData(const QVector&); +void setExperimentData(const QVector&); QPair getStartAndEndPoint(); @@ -51,7 +51,7 @@ QPointF calculateIntersection(const QPointF p1,const QPointF p2, QVector getPeakPointGroup(); std::vector movingAverage(const std::vector& data, int windowSize); -extern QVector _dataVtr; +extern QVector _dataVtr; extern QPointF _peakPoint; extern QPointF _leftSelectedPoint,_rightSelectedPoint; } diff --git a/src/data/xlsxhandler.cpp b/src/data/xlsxhandler.cpp new file mode 100644 index 0000000..c66a778 --- /dev/null +++ b/src/data/xlsxhandler.cpp @@ -0,0 +1,71 @@ +#include "xlsxhandler.h" +#include "global.h" +#include "logger.h" + +void XlsxHandler::test() +{ + QString sourceFilePath = QDir::currentPath() + "/sample.xlsx"; + qDebug()<<"fileName:"<dimension().rowCount(); + int colCount = workSheet->dimension().columnCount(); + qDebug() << "row:" << rowCount << "col:" << colCount; + + logde<<"0:"<cellAt(1, 1)->value().toString().toStdString(); + qDebug()<cellAt(1, 1)->value().toString(); + + + int index = 2; + Global::ExperimentInfo ei; + ei.sampleName = workSheet->cellAt(index++, 2)->value().toString(); + logde<<"sample name:"<cellAt(index++, 2)->value().toString(); + ei.date = workSheet->cellAt(index++, 2)->value().toString(); + ei.operatorName = workSheet->cellAt(index++, 2)->value().toString(); + ei.phaseSize = workSheet->cellAt(index++, 2)->value().toInt(); + + QVector phaseVtr; + for(int i = 0;i < ei.phaseSize;i++){ + Phase phase; + readPhaseData(workSheet,phase); + phaseVtr.push_back(phase); + } + +} + +void XlsxHandler::readPhaseData(QXlsx::Worksheet *workSheet, Phase &phase) +{ + const int startIndex = 9; +#if 0 + int index = startIndex; + phase.phaseName = workSheet->cellAt(index++, 2)->value().toString(); + phase.phaseWeight = workSheet->cellAt(index++, 2)->value().toString(); +#endif +} diff --git a/src/data/xlsxhandler.h b/src/data/xlsxhandler.h new file mode 100644 index 0000000..069b50c --- /dev/null +++ b/src/data/xlsxhandler.h @@ -0,0 +1,15 @@ +#ifndef XLSXHANDLER_H +#define XLSXHANDLER_H + +#include + +#include "xlsxdocument.h" +#include "protocol.h" + +namespace XlsxHandler { + void test(); + void readFile(const QString filePath); + void readPhaseData(QXlsx::Worksheet*,Phase&); +} + +#endif // XLSX_H diff --git a/src/global.h b/src/global.h index 66f1684..cd80afe 100644 --- a/src/global.h +++ b/src/global.h @@ -1,11 +1,11 @@ -#ifndef GLOBAL_H -#define GLOBAL_H +#ifndef __GLOBAL_H +#define __GLOBAL_H #include #include #include -#include "filemanager.h" +//#include "filemanager.h" class Global:public QObject { @@ -34,7 +34,27 @@ public: DeviceConnectionStatus getDeviceConnectionStatus(){return _deviceConnectStatus;} #endif - QVector>> _curveDataVtr; + struct ExperimentData { + float sampleTemp; + float dsc; + }; + + struct ExpeInfo + { + QString sampleName; + float sampleWeight; + QString date; + QString userName; + }; + struct ExperimentInfo{ + QString sampleName; + QString sampleWeight; + QString date; + QString operatorName; + int phaseSize; + }; + + QVector>> _curveDataVtr; signals: void sigModeModify(const Mode); diff --git a/src/main.cpp b/src/main.cpp index 46d3fc0..c053c4a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,17 +9,24 @@ #include "experimentsettingform.h" #include "filemanager.h" #include "logger.h" +#include "xlsxhandler.h" int main(int argc, char *argv[]) { + QTextCodec *codec = QTextCodec::codecForName("UTF-8"); + QTextCodec::setCodecForLocale(codec); + Logger::instance(); logde<<"main..."; QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); // 启用高DPI缩放 QApplication a(argc, argv); - MainWindow w; - w.show(); +// MainWindow w; +// w.show(); + + XlsxHandler::test(); + // FileManager::test(); diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/.gitignore b/src/thirdparty/QtXlsxWriter-0.3.0/.gitignore new file mode 100644 index 0000000..838be4c --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/.gitignore @@ -0,0 +1,45 @@ +syntax: glob +*.pro.user* +*.autosave +*.app +*.moc +*.prl +Makefile* +doc/html/ +*.framework/ +*.xcodeproj/ +debug/ +release/ +qtc-gdbmacros/ +*.rej +*.orig +*.obj +*.swp +*.dll +*.exp +*.ilk +*.pdb +*.lib +Thumbs.db +moc_*.cpp +qrc_*.cpp +*.o +*.so.* +*.so +*.pdb +ui_*.h +*~ +.qmake.cache +lib/* +*.orig +*.exe +*.vcproj +*.vcproj.*.user +*_resource.rc +*.sln +*.idb +*.ncb +*.suo + +*.zip +*.xlsx diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/.qmake.conf b/src/thirdparty/QtXlsxWriter-0.3.0/.qmake.conf new file mode 100644 index 0000000..b56c957 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/.qmake.conf @@ -0,0 +1,6 @@ +#Workaround for Issue #60 +CONFIG += git_build + +load(qt_build_config) + +MODULE_VERSION = 0.3.0 diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/README.md b/src/thirdparty/QtXlsxWriter-0.3.0/README.md new file mode 100644 index 0000000..43b321d --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/README.md @@ -0,0 +1,135 @@ +Documentation: http://qtxlsx.debao.me + +QtXlsx is a library that can read and write Excel files. It doesn't require Microsoft Excel and can be used in any platform that Qt5 supported. +The library can be used to + +* Generate a new .xlsx file from scratch +* Extract data from an existing .xlsx file +* Edit an existing .xlsx file + +## Getting Started + +> * For linux user, if your Qt is installed through package manager tools such "apt-get", make sure that you have installed the Qt5 develop package *qtbase5-private-dev* + +### Usage(1): Use Xlsx as Qt5's addon module + +#### Building the module + +> **Note**: Perl is needed in this step. + +* Download the source code. + +* Put the source code in any directory you like + +* Go to top directory of the project in a terminal and run + +``` + qmake + make + make install +``` + +The library, the header files, and others will be installed to your system. + +> ```make html_docs``` can be used to generate documentations of the library, and ```make check``` can be used to run unit tests of the library. + +#### Using the module + +* Add following line to your qmake's project file: + +``` + QT += xlsx +``` + +* Then, using Qt Xlsx in your code + +```cpp + #include + int main() + { + QXlsx::Document xlsx; + xlsx.write("A1", "Hello Qt!"); + xlsx.saveAs("Test.xlsx"); + return 0; + } +``` + +### Usage(2): Use source code directly + +The package contains a **qtxlsx.pri** file that allows you to integrate the component into applications that use qmake for the build step. + +* Download the source code. + +* Put the source code in any directory you like. For example, 3rdparty: + +``` + |-- project.pro + |-- .... + |-- 3rdparty\ + | |-- qtxlsx\ + | | +``` + +* Add following line to your qmake project file: + +``` + include(3rdparty/qtxlsx/src/xlsx/qtxlsx.pri) +``` + +> **Note**: If you like, you can copy all files from *src/xlsx* to your application's source path. Then add following line to your project file: + +> ``` + include(qtxlsx.pri) +``` + +> **Note**: If you do not use qmake, you need to define the following macro manually + +> ``` + XLSX_NO_LIB +``` + + +* Then, using Qt Xlsx in your code + +```cpp + #include "xlsxdocument.h" + int main() + { + QXlsx::Document xlsx; + xlsx.write("A1", "Hello Qt!"); + xlsx.saveAs("Test.xlsx"); + return 0; + } +``` + +## References + +* http://www.ecma-international.org/publications/standards/Ecma-376.htm +* http://www.iso.org/iso/catalogue_detail?csnumber=51463 +* http://msdn.microsoft.com/en-us/library/ee908652%28v=office.12%29.aspx +* http://www.datypic.com/sc/ooxml/ + +### General + +* https://github.com/jmcnamara/XlsxWriter +* http://openpyxl.readthedocs.org +* http://officeopenxml.com/anatomyofOOXML-xlsx.php +* http://www.libxl.com +* http://closedxml.codeplex.com/ +* http://epplus.codeplex.com/ +* http://excelpackage.codeplex.com/ +* http://spreadsheetlight.com/ + +### Number formats + +* http://msdn.microsoft.com/en-us/library/ff529356%28v=office.12%29.aspx +* http://www.ozgrid.com/Excel/excel-custom-number-formats.htm +* http://stackoverflow.com/questions/894805/excel-number-format-what-is-409 +* http://office.microsoft.com/en-001/excel-help/create-a-custom-number-format-HP010342372.aspx + +### Formula + +* http://msdn.microsoft.com/en-us/library/ff533995%28v=office.12%29.aspx +* http://msdn.microsoft.com/en-us/library/dd906358%28v=office.12%29.aspx +* http://homepages.ecs.vuw.ac.nz/~elvis/db/Excel.shtml +* http://ewbi.blogs.com/develops/2004/12/excel_formula_p.html diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/examples.pro b/src/thirdparty/QtXlsxWriter-0.3.0/examples/examples.pro new file mode 100644 index 0000000..13479a4 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/examples.pro @@ -0,0 +1,3 @@ +TEMPLATE = subdirs +SUBDIRS = xlsx + diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/calendar/calendar.pro b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/calendar/calendar.pro new file mode 100644 index 0000000..a986e00 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/calendar/calendar.pro @@ -0,0 +1,9 @@ +TARGET = calendar + +#include(../../../src/xlsx/qtxlsx.pri) +QT+=xlsx + +CONFIG += console +CONFIG -= app_bundle + +SOURCES += main.cpp diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/calendar/main.cpp b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/calendar/main.cpp new file mode 100644 index 0000000..3ad957e --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/calendar/main.cpp @@ -0,0 +1,145 @@ +#include +#include "xlsxdocument.h" +#include "xlsxformat.h" +#include "xlsxcellrange.h" +#include "xlsxworksheet.h" + +QTXLSX_USE_NAMESPACE + +int main(int argc, char **argv) +{ + QCoreApplication app(argc, argv); + + //Select a proper locale + //QLocale::setDefault(QLocale(QLocale::English)); + + Document xlsx; + QDate today(QDate::currentDate()); + for (int month=1; month<=12; ++month) { + xlsx.addSheet(QLocale().monthName(month)); + xlsx.currentWorksheet()->setGridLinesVisible(false); + + //the header row + Format headerStyle; + headerStyle.setFontSize(48); + headerStyle.setFontColor(Qt::darkBlue); + headerStyle.setHorizontalAlignment(Format::AlignHCenter); + headerStyle.setVerticalAlignment(Format::AlignVCenter); + xlsx.setRowHeight(1, 80); + xlsx.write("A1", QString("%1 %2").arg(QLocale().monthName(month)).arg(today.year())); + xlsx.mergeCells("A1:N1", headerStyle); + + //header with month titles + for (int day=1; day<=7; ++day) { + Format monthStyle; + monthStyle.setFontSize(12); + monthStyle.setFontColor(Qt::white); + monthStyle.setFontBold(true); + monthStyle.setHorizontalAlignment(Format::AlignHCenter); + monthStyle.setVerticalAlignment(Format::AlignVCenter); + monthStyle.setFillPattern(Format::PatternSolid); + monthStyle.setPatternBackgroundColor(Qt::darkBlue); + + xlsx.setColumnWidth(day*2-1, day*2-1, 5); + xlsx.setColumnWidth(day*2, day*2, 13); + xlsx.write(2, day*2-1, QLocale().dayName(day)); + xlsx.mergeCells(CellRange(2, day*2-1, 2, day*2), monthStyle); + } + + QColor borderColor = QColor(Qt::gray); + + Format weekendLeftStyle; + weekendLeftStyle.setFontSize(14); + weekendLeftStyle.setFontBold(true); + weekendLeftStyle.setHorizontalAlignment(Format::AlignLeft); + weekendLeftStyle.setVerticalAlignment(Format::AlignTop); + weekendLeftStyle.setPatternBackgroundColor(QColor("#93CCEA")); + weekendLeftStyle.setLeftBorderStyle(Format::BorderThin); + weekendLeftStyle.setLeftBorderColor(borderColor); + weekendLeftStyle.setBottomBorderStyle(Format::BorderThin); + weekendLeftStyle.setBottomBorderColor(borderColor); + + Format weekendRightStyle; + weekendRightStyle.setHorizontalAlignment(Format::AlignHCenter); + weekendRightStyle.setVerticalAlignment(Format::AlignTop); + weekendRightStyle.setPatternBackgroundColor(QColor("#93CCEA")); + weekendRightStyle.setRightBorderStyle(Format::BorderThin); + weekendRightStyle.setRightBorderColor(borderColor); + weekendRightStyle.setBottomBorderStyle(Format::BorderThin); + weekendRightStyle.setBottomBorderColor(borderColor); + + Format workdayLeftStyle; + workdayLeftStyle.setHorizontalAlignment(Format::AlignLeft); + workdayLeftStyle.setVerticalAlignment(Format::AlignTop); + workdayLeftStyle.setPatternBackgroundColor(Qt::white); + workdayLeftStyle.setLeftBorderStyle(Format::BorderThin); + workdayLeftStyle.setLeftBorderColor(borderColor); + workdayLeftStyle.setBottomBorderStyle(Format::BorderThin); + workdayLeftStyle.setBottomBorderColor(borderColor); + + Format workdayRightStyle; + workdayRightStyle.setHorizontalAlignment(Format::AlignHCenter); + workdayRightStyle.setVerticalAlignment(Format::AlignTop); + workdayRightStyle.setPatternBackgroundColor(Qt::white); + workdayRightStyle.setRightBorderStyle(Format::BorderThin); + workdayRightStyle.setRightBorderColor(borderColor); + workdayRightStyle.setBottomBorderStyle(Format::BorderThin); + workdayRightStyle.setBottomBorderColor(borderColor); + + Format greyLeftStyle; + greyLeftStyle.setPatternBackgroundColor(Qt::lightGray); + greyLeftStyle.setLeftBorderStyle(Format::BorderThin); + greyLeftStyle.setLeftBorderColor(borderColor); + greyLeftStyle.setBottomBorderStyle(Format::BorderThin); + greyLeftStyle.setBottomBorderColor(borderColor); + + Format greyRightStyle; + greyRightStyle.setPatternBackgroundColor(Qt::lightGray); + greyRightStyle.setRightBorderStyle(Format::BorderThin); + greyRightStyle.setRightBorderColor(borderColor); + greyRightStyle.setBottomBorderStyle(Format::BorderThin); + greyRightStyle.setBottomBorderColor(borderColor); + + int rownum = 3; + for (int day=1; day<=31; ++day) { + QDate date(today.year(), month, day); + if (!date.isValid()) + break; + xlsx.setRowHeight(rownum, 100); + int dow = date.dayOfWeek(); + int colnum = dow*2-1; + + if (dow <= 5) { + xlsx.write(rownum, colnum, day, workdayLeftStyle); + xlsx.write(rownum, colnum+1, QVariant(), workdayRightStyle); + } else { + xlsx.write(rownum, colnum, day, weekendLeftStyle); + xlsx.write(rownum, colnum+1, QVariant(), weekendRightStyle); + } + + if (day == 1 && dow != 1) {//First day + for (int i=1; i +#include "xlsxdocument.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*i); //A1:A9 + xlsx.write(i, 2, i*i); //B1:B9 + xlsx.write(i, 3, i*i-1); //C1:C9 + } + //![0] + + //![1] + Chart *pieChart = xlsx.insertChart(3, 3, QSize(300, 300)); + pieChart->setChartType(Chart::CT_Pie); + pieChart->addSeries(CellRange("A1:A9")); + pieChart->addSeries(CellRange("B1:B9")); + pieChart->addSeries(CellRange("C1:C9")); + + Chart *pie3DChart = xlsx.insertChart(3, 9, QSize(300, 300)); + pie3DChart->setChartType(Chart::CT_Pie3D); + pie3DChart->addSeries(CellRange("A1:C9")); + + Chart *barChart = xlsx.insertChart(23, 3, QSize(300, 300)); + barChart->setChartType(Chart::CT_Bar); + barChart->addSeries(CellRange("A1:C9")); + + Chart *bar3DChart = xlsx.insertChart(23, 9, QSize(300, 300)); + bar3DChart->setChartType(Chart::CT_Bar3D); + bar3DChart->addSeries(CellRange("A1:C9")); + + Chart *lineChart = xlsx.insertChart(43, 3, QSize(300, 300)); + lineChart->setChartType(Chart::CT_Line); + lineChart->addSeries(CellRange("A1:C9")); + + Chart *line3DChart = xlsx.insertChart(43, 9, QSize(300, 300)); + line3DChart->setChartType(Chart::CT_Line3D); + line3DChart->addSeries(CellRange("A1:C9")); + + Chart *areaChart = xlsx.insertChart(63, 3, QSize(300, 300)); + areaChart->setChartType(Chart::CT_Area); + areaChart->addSeries(CellRange("A1:C9")); + + Chart *area3DChart = xlsx.insertChart(63, 9, QSize(300, 300)); + area3DChart->setChartType(Chart::CT_Area3D); + area3DChart->addSeries(CellRange("A1:C9")); + + Chart *scatterChart = xlsx.insertChart(83, 3, QSize(300, 300)); + scatterChart->setChartType(Chart::CT_Scatter); + //Will generate three lines. + scatterChart->addSeries(CellRange("A1:A9")); + scatterChart->addSeries(CellRange("B1:B9")); + scatterChart->addSeries(CellRange("C1:C9")); + + Chart *scatterChart_2 = xlsx.insertChart(83, 9, QSize(300, 300)); + scatterChart_2->setChartType(Chart::CT_Scatter); + //Will generate two lines. + scatterChart_2->addSeries(CellRange("A1:C9")); + + Chart *doughnutChart = xlsx.insertChart(103, 3, QSize(300, 300)); + doughnutChart->setChartType(Chart::CT_Doughnut); + doughnutChart->addSeries(CellRange("A1:C9")); + //![1] + + //![2] + xlsx.saveAs("Book1.xlsx"); + //![2] + + Document xlsx2("Book1.xlsx"); + xlsx2.saveAs("Book2.xlsx"); + return 0; +} diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/chartsheet/chartsheet.pro b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/chartsheet/chartsheet.pro new file mode 100644 index 0000000..327b163 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/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/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/chartsheet/main.cpp b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/chartsheet/main.cpp new file mode 100644 index 0000000..c3e7a38 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/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/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/conditionalformatting/conditionalformatting.pro b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/conditionalformatting/conditionalformatting.pro new file mode 100644 index 0000000..10d2978 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/conditionalformatting/conditionalformatting.pro @@ -0,0 +1,9 @@ +TARGET = hello + +#include(../../../src/xlsx/qtxlsx.pri) +QT+=xlsx + +CONFIG += console +CONFIG -= app_bundle + +SOURCES += main.cpp diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/conditionalformatting/doc/src/conditionalformatting.qdoc b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/conditionalformatting/doc/src/conditionalformatting.qdoc new file mode 100644 index 0000000..39e2461 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/conditionalformatting/doc/src/conditionalformatting.qdoc @@ -0,0 +1,10 @@ +/*! + \example conditionalformatting + \title Conditional Formatting Example + \brief This is a conditional formatting example. + \ingroup qtxlsx-examples + + This example demonstrates how to create a new + .xlsx file containin conditional formatting + with Qt Xlsx Library. So lets see how this is achieved. +*/ diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/conditionalformatting/main.cpp b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/conditionalformatting/main.cpp new file mode 100644 index 0000000..298238d --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/conditionalformatting/main.cpp @@ -0,0 +1,76 @@ +#include +#include "xlsxdocument.h" +#include "xlsxconditionalformatting.h" + +using namespace QXlsx; + +int main() +{ + //![0] + Document xlsx; + Format hFmt; + hFmt.setFontBold(true); + xlsx.write("B1", "(-inf,40)", hFmt); + xlsx.write("C1", "[30,70]", hFmt); + xlsx.write("D1", "startsWith 2", hFmt); + xlsx.write("E1", "dataBar", hFmt); + xlsx.write("F1", "colorScale", hFmt); + + for (int row=3; row<22; ++row) { + for (int col=2; col<22; ++col) + xlsx.write(row, col, qrand() % 100); + } + //![0] + + //![cf1] + ConditionalFormatting cf1; + Format fmt1; + fmt1.setFontColor(Qt::green); + fmt1.setBorderStyle(Format::BorderDashed); + cf1.addHighlightCellsRule(ConditionalFormatting::Highlight_LessThan, "40", fmt1); + cf1.addRange("B3:B21"); + xlsx.addConditionalFormatting(cf1); + //![cf1] + + //![cf2] + ConditionalFormatting cf2; + Format fmt2; + fmt2.setBorderStyle(Format::BorderDotted); + fmt2.setBorderColor(Qt::blue); + cf2.addHighlightCellsRule(ConditionalFormatting::Highlight_Between, "30", "70", fmt2); + cf2.addRange("C3:C21"); + xlsx.addConditionalFormatting(cf2); + //![cf2] + + //![cf3] + ConditionalFormatting cf3; + Format fmt3; + fmt3.setFontStrikeOut(true); + fmt3.setFontBold(true); + cf3.addHighlightCellsRule(ConditionalFormatting::Highlight_BeginsWith, "2", fmt3); + cf3.addRange("D3:D21"); + xlsx.addConditionalFormatting(cf3); + //![cf3] + + //![cf4] + ConditionalFormatting cf4; + cf4.addDataBarRule(Qt::blue); + cf4.addRange("E3:E21"); + xlsx.addConditionalFormatting(cf4); + //![cf4] + + //![cf5] + ConditionalFormatting cf5; + cf5.add2ColorScaleRule(Qt::blue, Qt::red); + cf5.addRange("F3:F21"); + xlsx.addConditionalFormatting(cf5); + //![cf5] + + //![2] + xlsx.saveAs("Book1.xlsx"); + //![2] + + Document xlsx2("Book1.xlsx"); + xlsx2.saveAs("Book2.xlsx"); + return 0; +} diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/datavalidation/datavalidation.pro b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/datavalidation/datavalidation.pro new file mode 100644 index 0000000..441bc66 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/datavalidation/datavalidation.pro @@ -0,0 +1,9 @@ +TARGET = datavalidation + +#include(../../../src/xlsx/qtxlsx.pri) +QT+=xlsx + +CONFIG += console +CONFIG -= app_bundle + +SOURCES += main.cpp diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/datavalidation/main.cpp b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/datavalidation/main.cpp new file mode 100644 index 0000000..a2ab4f2 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/datavalidation/main.cpp @@ -0,0 +1,22 @@ +#include +#include "xlsxdocument.h" +#include "xlsxdatavalidation.h" + +QTXLSX_USE_NAMESPACE + +int main() +{ + Document xlsx; + xlsx.write("A1", "A2 and A3:E5 only accept the number between 33 and 99"); + + //![1] + DataValidation validation(DataValidation::Whole, DataValidation::Between, "33", "99"); + validation.addRange("A2"); + validation.addRange("A3:E5"); + validation.setPromptMessage("Please Input Integer between 33 and 99"); + xlsx.addDataValidation(validation); + //![1] + + xlsx.save(); + return 0; +} diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/definename/definename.pro b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/definename/definename.pro new file mode 100644 index 0000000..d2ba173 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/definename/definename.pro @@ -0,0 +1,9 @@ +TARGET = definename + +#include(../../../src/xlsx/qtxlsx.pri) +QT+=xlsx + +CONFIG += console +CONFIG -= app_bundle + +SOURCES += main.cpp diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/definename/main.cpp b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/definename/main.cpp new file mode 100644 index 0000000..9491eb2 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/definename/main.cpp @@ -0,0 +1,33 @@ +#include +#include "xlsxdocument.h" + +QTXLSX_USE_NAMESPACE + +int main() +{ + //![0] + Document xlsx; + for (int i=1; i<=10; ++i) { + xlsx.write(i, 1, i); + xlsx.write(i, 2, i*i); + xlsx.write(i, 3, i*i*i); + } + //![0] + //![1] + xlsx.defineName("MyCol_1", "=Sheet1!$A$1:$A$10"); + xlsx.defineName("MyCol_2", "=Sheet1!$B$1:$B$10", "This is comments"); + xlsx.defineName("MyCol_3", "=Sheet1!$C$1:$C$10", "", "Sheet1"); + xlsx.defineName("Factor", "=0.5"); + //![1] + //![2] + xlsx.write(11, 1, "=SUM(MyCol_1)"); + xlsx.write(11, 2, "=SUM(MyCol_2)"); + xlsx.write(11, 3, "=SUM(MyCol_3)"); + xlsx.write(12, 1, "=SUM(MyCol_1)*Factor"); + xlsx.write(12, 2, "=SUM(MyCol_2)*Factor"); + xlsx.write(12, 3, "=SUM(MyCol_3)*Factor"); + //![2] + + xlsx.save(); + return 0; +} diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/demo/demo.pro b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/demo/demo.pro new file mode 100644 index 0000000..10c4270 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/demo/demo.pro @@ -0,0 +1,9 @@ +TARGET = demo + +#include(../../../src/xlsx/qtxlsx.pri) +QT+=xlsx + +CONFIG += console +CONFIG -= app_bundle + +SOURCES += main.cpp diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/demo/doc/images/xlsx_demo.gif b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/demo/doc/images/xlsx_demo.gif new file mode 100644 index 0000000000000000000000000000000000000000..0af0799dfa8d69546685110c88348fd1cb2e745f GIT binary patch literal 222011 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≺?k=*%joad&8c!PWwimRs)$Vi@#@g|V& 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

W@?eJFajA3p-bM6W=Z5cyt8dGf>W9<&p zW@M4?)}U{Puy5qX?+DZHOyh4D^KUf+a5fWgHzRNyGw@|VexR%0C9#8anNonu6EUR-V}559r)c=`2|7aF>CbB3AJvB zC#>fRUBy)9Kb?Wojpf+5gYU@DYyMPL(-g+QX6fQ4Y^}ZT50<^cJ1DC|t=ltiyoln7 zuERzC3RU`>b*q-)3Y5^pFtr31&pWW=-QBT7I3K z7#%1fByaDqy);L0yox_tRq+d1&&bnsvWvn_?`UV~s8GiVVm&7-*9=e|KJ4_5&$(O!2~~W>%HP zcZJY*MHgoF-Eo{=ByBC`Tsh&^D)?lUH~m#_oQT-7V|QcsXo!z^LwwgRM5!$A&uA~` zls#ydKJM_Q>6-TVkgt?T4=R!mFP^4oEP^~?cj4n}_?Ulq|05@nvMSMQ_QTk(oWJ;0 z_tR+~>|Hk8phrVBto27vkVv0ZcQ$!sepGZvcb3s*^vpW+at?Z6M%=Xbl*d1hBd3kIZ;j4xjbzshtuGB!mkf5$2ebNa2$Qb^AD1ITjZQRaB-4<@}4}b9=fATMX^IsR@ zrgktVdodsH*+*J|r!`-e+Y?ALyPAS7@g!GZ;McuJ^nA;X3a z7lPXIZz9Et7B6DVsBt65j;;K33@LIX$&9H2l}xE}WyMpXSi+3ikrXMJHvVr?990S@ z&zPZ5^$e;qP%5EDNBV(vl%<(0Q=TY^8gjM z3zF@ueDmkf&J&K#9n-XQmZ__+WQ|?r>+LCJdoNi#JW1T-kt*fw)VEaNlZRV2o_RTa zv&|a@a-cs#!u2N0YLcA{&nQ}kU~X16sX}u z+HDuagaNehkBAe#Fj05pwGf0wEm{QLb}5Xg14R>%W#dHSop%ufI9Oz!cLfv(2t`Da zW#mM=&DI-aO1LLnWyN8JoM!c5NyvQ*1;Sr{{B;?cfZG9507VJ@g9lj(Qp6y3I8+Gd zL~{N^r-dl>m?1@aPQ)jO*acCdMS)_pVt6o4)B;&9RwN^KDflqa1UmjRX{D6%*yBVD zkOgE#LSk2dlK+TG>Zqmu!z64@{wA4}#9ekALCIx_<(3MC`K2ehx-}+tWuD0Vcd_L>ppVbjMsGt@Zx}BnoQiNzuJB0`SsiZnudQqmDZt5vTpjL;f zsqapNs;aHA+McVF!787XoY7jVK({&+W|#hXDH>dw4x1*M6S-O4u@%k<@tx;o2(87^ zz7$@dCknbTSt+Vm6N?+a$n8XqdROkH7@dpmk3kltsk=vxI*9Uh%<(aSik=r`9tm*9&u^Zm*@cvC&;KCCgYw^Y_t}RGQ9^(S!JTgHqdXuBxb{=*Y zJW;HB68zBjLUb)cjc$D9t4`|F2QKoo??#j=SNwW3zkk#(H|{Fc3YC;U#_Vr!Q}W-w z02siB@Je6>8=yjzCLLf+Bw^BHply&PG0iQDb95kariJjrpYK)$yjJO~fBN#74gPN!u>SyPSN~yN^T

2^~mH1!5BsXLC7= zAQ6IA(^}TZ0y-xGsz4Vk5Xi_!#X}XyMdw@8w|W%98x=@yUHk{93ZyPDhOtOT66KQ0 zNUt;6D~&T;^b9ne{v*vzQj>1htR*%#sm zT}*22mWr;XqU)*XimIlj+Lx-T@ti#sX;!xy)RT4*tUVHI?Z`?uvuX;hno_H#*xDnv z>IJUmWm}`Y?h%rgq`pxkw03b42g+++4lF^Z#H(ReNs7ZA9t})%?5Z6T7%YrT z)-al@ll3Oj+tYlmPfWZlX+~Eq3^p>khCvjADcLA2J}OeOE0@ZsYnT&qvQse2+unFb zvr^`URUDuIi7B82kM8t;?FH(43&_LRKJOyZv#qhN$KME5=)a7?nt+!`!Qn#DL{cQ% zBeCPHBVQ4O5?s0WAD?3cVe(k2$xj9h<}{4mDG#YkNy5mLL(EYM zBteEBRq0P<{vFpg3JmS%Sn)#SB^JL-y#nLKYv9 zPlvhy^!dT)qAJ?!32SU13k?lOUJQcfH$PW&e)ZsdTn+ zq~QDC13&n}A3pJmZ~WsUKl#dEKJ%OJ{O3bI`qH01^{XF!JM=Omd9eQQxA2AUga7+u zCwc{p)Z4`{O_V_YeQ~ozR5;17H9O;9{{t0UF=| z{vu!kD&PV#U;`!~DolX`Dj)<(UA5)eTS=3o-=U=RA>4+3Ej3gHkEArTG%36y|oDd7?_ zVG}yx6GCAWO5qezVHH~86=Gp&m4FcxVHbMg59*)}3g8$H;73uy8KPkts^J>4VH>*P z8?GTEOu;I^VH#!v1lD05>Y*EEf+tMD9s*(@3gQ`BLMDLVAR=NSDq^LnT_`C1PSGYT_nxVkdfHC)UC%*Z~+cLMb-F4(xy_s^TiL;wnx;CV0XA6i~q| zQo#~<0Yz*<5P5%DmR&pg(e4`-< zggBDp7%o;KnB`eoz*#0jTB>DRqNQ7^C0oMfSZRTcg-sUWPq#6jP8sLBo%)kto zDPW~mj%QDrfZ*)pSN?|OSd!&OO+tbys0A!2 zgDU8QK4@SVnBk{C4}mwD$J!?Y61k_<%oW$Th;+ymgrpa<5`|4i=t?X z!l+t;!3V@>j1D9So@HgyXc*9Fjq+%Y_GpdPXcioSkgDZCHsV=|CTW_ckvgf6vgRyE z>6A+8ZdU0MP-&KG>6UV7mwKs}#sVwYK^UMxnW6y?#J~)=f-B5G4A8(Sl)@)~f*<&v zncAtD$^k51=bmQ46KJOvctI}iBneOec>d?1isvx?K`4wuqdMxNLTaQ+>ZDR?rCREx zT52hv=cZ~Zrh4k9f@-K|AgDxwxO6#u9=(HxQA`s+*>gXi! zsI_*hwSudH5^1g&GpYrpR6 zD~Kr;n8CmjY;hi^4A=miasns>0v|-d6A)~~4y+nzf)``~7GP|~VyvH<0-y?NPL99{ z6zZvx>`y9cAc#WBs_e?LY|Far%ff8T%IwU>Y!CE-4%}?cjsnf{Y|r}a&(5q)^k>QH zqzR0es@^24x+<&&;9{Yl1(bnevY*thAJwM*pBM<{1&F}~oZlEs0V+tW#6|)tNP)zT z!3CJX*%Is+1SZk;?gtbu zXPUv`E-q#gEEaq~#3pX!4s7B&Zr-9nB7{N~NGuh6faij)<5B@;j;`XGf#;qs<(}?i zt}f|frV}XU5fCiwT7c}D0qu_Fz~Zj$hAkRUf*){h#KP_o4DY};LGB)J?H;e~CU5PU zLGm)M@;a~a3MTIgt{1SvD`@ZbzQS&DZ}$e~63FHfXs>Kq0QrtD_=>M$k}vq4ul7EH z1z?5zZg2bs<`aA`_Xcd<@&F9L07?GRfG3PXCDh+y1)u@eVn7+6ahZxi8l$lqv$36~!6f*h7Gv#Ty73*O!Qq-I z3YaT-v<=4x>ke1Ic6G8#m(B>OQWKXN5=W|>a%CS#_V zQo#{?@+YH#D39_Hc(N&%DgG&w@|~)ICHR3BXmKcmvME0SD%WzE#xE+P!7bminfCH7 z*X}OU@-S;L8iWD%D&Q0(K{8vwG8dpSKl3s}Gb=#zG*2@%J2NZ9?-OVC4_<&^t2^A zvKq9tTYoiM$Mswb=UdzLR}ZHwe{x=rW?mmbbdK&{_p}^b0`T^#wq!%LW%o1~Aaep*b6`qyHe+)%hjwUNb2eY|H-qyxqqYK$sY~av7YMLA z>j4ac!4N=!7UwAg&$Grpus!GG1Xu7r^K%q%!9RP!aU*wfEBA6UcXK=Ub3=D@JNFNG z0d-q9KudRaYxj0@cXa2$Mt3v@e{>IzG)b4^N9D8yM5lT?^?J9r8nE|!7d24}^>CuW zUOqy8>-Qu6SONs@_kN?n1^jn_=Qn|m0S4svf$O(||2KpGwB=pIFIf( zk81b_JOYMyIEUxAhle_>LdJBm6j!OZbrQcOz&*BeJ-V_jr#Z!6P`qlmB;=Pq}GMxs*e>lv6pBTe*Zc zf+Vs6Dv0@*lWh`=xfGarnUgu1i#eOKxthQEo2$8)V+EZ*0iDY)nUlGghCv$m`JV%N z8el;efP!qp;1_g(HU|15$n$RVc0GSAPKK;L3wO!(GZz$hcWe5lbGma2K^Oc0sEc~1 zlY0KCYq}lu0Y^tL(e7{$`*155LaPEXtS;6{+WM{IdamnwuB*Xbvf?E`penRtBhbMG ztYWd3BC>x029)Bmo1(KfJF_Ua5B`DC zH$tO3ddBv4q~j!^T5zSGYCms5(s#kvgMHYG{n(Rz*_-{@qkY<&y%2E0548Q;dx6@^ z{oK=i-KV`5?7=96_XQiRtG{}zFRghm79*EaNMmC?knc*|9<4({$mdR2Vnjyf`Sxm0V=>g=TELAKyKt)E@$#_@MHe-Prvb} zE0Z39B$Vc8O8%01fAwNMw$f=Apn@gD{`RY@B$zJ}xW8h;fBXmL{F`t6{=a|z3+DVs z{y_496aa)5Qa@>|o`3c^IxN+sJry%+MT%9*|O4^z83GRhe zCOK%xmp6YNeR}jtjHq`{o(K{6^3llAWG71&JK-fg^8X*eN3~VT~u)kKkCYm#;5u+ zL_)z1+i|eO7HjM=R)idq$RdqA63HZ$G!hllh#U=zETnL9$ttZpQnn~PypqcA86w^yd5JC$sJpB~ZP(>Y;)KdOUJr&hdRb7?UR$X1yi!O#( zBGX!JmGs6OdF0VY#vB_%ieQBume^vAJr>zyl@&I>{FZ$d+GCrQGTLgby*9XJuicj0 zZiUU(S#QOK7F=q_J-6Cv%{^D$cHMm5lho_$7{gAM)}n&_g9J{swym0p_Zrk#Eo>Zqljn(C^pz8dSS zwceWRuD$*m?6AL}Lz0%vJ{#?{)n1$Jw%vXk?*6#to}2Ev?Y^5aMfBdA@4o&18*snt z&?NA}4Oe6mIyO0+@x~p09P-E|pPcf_Ex#P|%r)Pf^Ugh&T$3>BXheq8xz8q$_!5N z*b0@>_cUXd5(dNYHMiv?5wcT9GpSS@O(j`QHImYDI@+}yJw1QK^IO+{aJ^rz>!<7U zzOJL2mVORbyuBBu{`cd9V`hsBvugF?m%lHWegF31k^0zzv-UCml#O3>aw{BeN|s~) zk{dnMV9K7!Gdwm0O7905FsXw2pzYFrZ`r zc}sf;mKq3a`5Wbgl>XyVXo#0n73E}f;Ec({xR+}`CEx4f1|}y0wc5iR?V_78{XG7| zOsOWC(4TOf-LmZwMFqK|5WQ96?aika6&63ST>c~BGdhhmlcg>3+JBrME6tRG>z8d3 zZ4Tf+#+V6bSL_g>1Ny0@1zQJ`;zs@r>$RN`rN%pOm z1@mBkP>>tVf1K-FCLkp5L)r$yDyNIB9L%==8C^yD@AJTC9upJ3hx!+3 zRd0%)c|I5Ur9PyoKaW1+f1bD{4GPCeeBj2IFBzU+DAlQmC!C}62HE^kBqdI}p?WNN$~9oc9| zr};`Uo8EE}p&MgDc1ePo_b~9~DKVTm0I?>XhT7J;l=)dT)_WF)SCze#V8tN=rp)uX zJ6?qwPlXKfnQetXobKgf(a>&Yd-?2H%hTMO1uoN&Cnn9y)#Ub)amiveUk5Xt-IRi79N#p2&rBSbwYPaZ& z+@QWl9Sn0;=I^{!ic11Am)Y&dZi{+MtQ~Cxr~r}DN=G`QUdHk2TKtlzyM~f0F4`xqKR4Ym^-D&H)SV@yfQ5z zk_=~Ywz1W2uu0(S^o2iI*BnaUoQU2T!G6RVbRT<@pENwdtDJ6k(^-(_g?XV(V~mD5 zt>I?DakENhLB4RM>2G>nP9KC^3#~N5$;IA2<=u<@NIULt(Co_9kFmiv4Xm9)*sP=S zPxIC^B2Sp-(fWeAnDPkMgVB893*a_z;1qE9z`nP6VZk3F3d;3xG4+b z$|Pg$r`K7f?aFeP=b~=p!$>R&ZnfvviCuc|e69+)O~{^_82i}O`yeji82hhj=BJ(; zyW*47><7<-KJ`sJcpc|j(;nV)`Clqqi<4%0Eu)@% z)hrE~HQF~ZBzgUJLVC>8?AmhNyT!4EYwi0CD1pg^UfZxa(7=88tMvSd=C~4|U7tAB67a`oi*m)ROU|^V#QWS7K!*Zwq z&d~rUPq(XUI~*(n18c?AUj#-=4a!J)Dv)c=(=~ zXqW;{+WIBe)Xy5kcfQJe)b$aS66F@xsn6l*yNGKsPFHWl?q4}7$NIARZa6K%$*ZIf z?Eoz~U;SDk1vS5N(GzewfTY9c%LpR?8sx&JM*#Ld*ew~_ zPGUeJ!#@z=cpaewVw(Ce`O9csAihq5w~@fzbp!qdNU;tXMn**lQF{weF*;NN8J#3V zA1Xkn>d?o?m~i*YfZy@ULtEiLNU0IG4cd_ja2=ED?Wvo7k-uyVZST_SWgHO z`?taAQ%|qxG0iPRP=M(gq4;r0a~h%#fUlBR*imRs+i9+aH1|TK&hOuAvOA|`SdZIu zKMKQj9l=q9@0Zcu{zK{ZrN7V+`TFmti3ANe!R)U6JK^X^wvmbK{z^RE4v+ed$Jtb0z=>-#TYYTpIMw!3rGDAL|8T558LnRX7i5 zFurY>F4Z&-!5?lgIzoVlWQaEXA}&MW(RkOR<*vt7jq5WFr9(m_2ylF0u2tbVr0~3| z&#u#uK$v^C9U825ZwGLjxrCc{Us2!jMYKi?9<>f2d4cFvAiN1=eWx`&21pw;wo8Uv zp02MB_i{A6nyi-po z16|L(L!>Ei%^ldt0L1kd3q7kG)RHF`=}&hzdklcsEDd7+7DFGNZ5b>A&jF9vlA=xD%dG|t2F+_?TB4vrF;z01q>5YsebQI*UHyPK+!z6RP4;7>0_4rZ1 zCmllCI3fKZZYM<1=*8NSP0}r0(0iYIdhFQ_=NmZKcrzB#jQs*_X#m4WvatWkaMwq} zu!XzD?W z(IX+g00>s>r+{!y}P*HGtQA2yw&@4DBSEbG|x$a(Xu^TG>e zqD63`wKCE6exkV%zKDzM)2}YPOY?xySyECBfITgd*c%-Pa6RA@q~LS$F9Hrk1Rq?c zbW>=EEEqlfCcXzGv&>15%y+LcG0!I7Zbq;&J$gBKSgAZ*{%O&XGo6wbe577^r1Acd z7NgYm;MDFzCtL(>b7S%QWvFY)qeJ(PMnfn7OTBU+;cM5RFypfA z=5%@p&i7D?J9lBYIb#zm(Re@_T$U*w&kSQ_g)Imo%CcfoC?+txP@8qAEIV~P`xq-H zJtQZ)EGKU~=M*bf5t6Gc%dK$Bah^`a)?)TSsFC}}2fI%t9m zSh8^;I^CfQpqLsLS%`|P%ZqG9MM>jDP9g=xoO&5xxEL3&7ZrP#7jKy;_A@RC5S0X% zmxw1y!i-BJM5Wt$Y5huU{NdvdRHN6WF>83}2I-FTrlERb4W!91v9wmRAl=V8`=L{Re~nHiXr<8>wa3hwfF| z=1N!V%{=tvw<7hYa`o2<_4jhMRzn9=5dI69DS!+^tBq9E?8#~~lNyWA8f#UJ?PQI; zNv%_8t*ffmysxxdMqf<$d^=X7+;T+u6{3`iez%tr{X>6Ox)U~^uiV>LSr6LwEUk+U ztv{ryPn|5MblN7W>S^wbMJe0|q7;QTC{+y=lMU)44O$5eQk`v7-R{>@n?f7ARgD)W z8!wqO4TLrgs+xu-n{Jt$yBm7$zUrLTBvjx*I|&|qs%m~Yc_4?&co*98N!9XovgNx; zD_q>_d>i}r_cJH^;8_L8s{oZQCYTD&TZr4NE81+Q+U(iwPU3dw3%QqpIxW6qy|}}> zqGQWchabB$K-?Kz(J7wl3}bgih`aWF?J%Bc&D{e}6n7u0=uVyLKF01z7x!dW^yE$T zoMQJX#Fo9vir$K;UNyU~R@_%#(bqWD*TTNgF22xRap8v|pZT>5ZUC$Xe%4O{KMDLK N@RPt#0{`Cx{ufM4RTcmM literal 0 HcmV?d00001 diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/demo/doc/src/demo.qdoc b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/demo/doc/src/demo.qdoc new file mode 100644 index 0000000..dafabc9 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/demo/doc/src/demo.qdoc @@ -0,0 +1,8 @@ +/*! + \example demo + \title Qt Xlsx Demo + \brief This is a demo which is used to show features of the library + \ingroup qtxlsx-examples + + \image xlsx_demo.gif +*/ diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/demo/main.cpp b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/demo/main.cpp new file mode 100644 index 0000000..7d1e854 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/demo/main.cpp @@ -0,0 +1,296 @@ +#include +#include "xlsxdocument.h" +#include "xlsxformat.h" +#include "xlsxcellrange.h" +#include "xlsxworksheet.h" + +QTXLSX_USE_NAMESPACE + +void writeHorizontalAlignCell(Document &xlsx, const QString &cell, const QString &text, Format::HorizontalAlignment align) +{ + Format format; + format.setHorizontalAlignment(align); + format.setBorderStyle(Format::BorderThin); + xlsx.write(cell, text, format); +} + +void writeVerticalAlignCell(Document &xlsx, const QString &range, const QString &text, Format::VerticalAlignment align) +{ + Format format; + format.setVerticalAlignment(align); + format.setBorderStyle(Format::BorderThin); + CellRange r(range); + xlsx.write(r.firstRow(), r.firstColumn(), text); + xlsx.mergeCells(r, format); +} + +void writeBorderStyleCell(Document &xlsx, const QString &cell, const QString &text, Format::BorderStyle bs) +{ + Format format; + format.setBorderStyle(bs); + xlsx.write(cell, text, format); +} + +void writeSolidFillCell(Document &xlsx, const QString &cell, const QColor &color) +{ + Format format; + format.setPatternBackgroundColor(color); + xlsx.write(cell, QVariant(), format); +} + +void writePatternFillCell(Document &xlsx, const QString &cell, Format::FillPattern pattern, const QColor &color) +{ + Format format; + format.setPatternForegroundColor(color); + format.setFillPattern(pattern); + xlsx.write(cell, QVariant(), format); +} + +void writeBorderAndFontColorCell(Document &xlsx, const QString &cell, const QString &text, const QColor &color) +{ + Format format; + format.setBorderStyle(Format::BorderThin); + format.setBorderColor(color); + format.setFontColor(color); + xlsx.write(cell, text, format); +} + +void writeFontNameCell(Document &xlsx, const QString &cell, const QString &text) +{ + Format format; + format.setFontName(text); + format.setFontSize(16); + xlsx.write(cell, text, format); +} + +void writeFontSizeCell(Document &xlsx, const QString &cell, int size) +{ + Format format; + format.setFontSize(size); + xlsx.write(cell, "Qt Xlsx", format); +} + +void writeInternalNumFormatsCell(Document &xlsx, int row, double value, int numFmt) +{ + Format format; + format.setNumberFormatIndex(numFmt); + xlsx.write(row, 1, value); + xlsx.write(row, 2, QString("Builtin NumFmt %1").arg(numFmt)); + xlsx.write(row, 3, value, format); +} + +void writeCustomNumFormatsCell(Document &xlsx, int row, double value, const QString &numFmt) +{ + Format format; + format.setNumberFormat(numFmt); + xlsx.write(row, 1, value); + xlsx.write(row, 2, numFmt); + xlsx.write(row, 3, value, format); +} + +int main() +{ + Document xlsx; + + //--------------------------------------------------------------- + //Create the first sheet (Otherwise, default "Sheet1" will be created) + xlsx.addSheet("Aligns & Borders"); + xlsx.setColumnWidth(2, 20); //Column B + xlsx.setColumnWidth(8, 12); //Column H + xlsx.currentWorksheet()->setGridLinesVisible(false); + + //Alignment + writeHorizontalAlignCell(xlsx, "B3", "AlignLeft", Format::AlignLeft); + writeHorizontalAlignCell(xlsx, "B5", "AlignHCenter", Format::AlignHCenter); + writeHorizontalAlignCell(xlsx, "B7", "AlignRight", Format::AlignRight); + writeVerticalAlignCell(xlsx, "D3:D7", "AlignTop", Format::AlignTop); + writeVerticalAlignCell(xlsx, "F3:F7", "AlignVCenter", Format::AlignVCenter); + writeVerticalAlignCell(xlsx, "H3:H7", "AlignBottom", Format::AlignBottom); + + //Border + writeBorderStyleCell(xlsx, "B13", "BorderMedium", Format::BorderMedium); + writeBorderStyleCell(xlsx, "B15", "BorderDashed", Format::BorderDashed); + writeBorderStyleCell(xlsx, "B17", "BorderDotted", Format::BorderDotted); + writeBorderStyleCell(xlsx, "B19", "BorderThick", Format::BorderThick); + writeBorderStyleCell(xlsx, "B21", "BorderDouble", Format::BorderDouble); + writeBorderStyleCell(xlsx, "B23", "BorderDashDot", Format::BorderDashDot); + + //Fill + writeSolidFillCell(xlsx, "D13", Qt::red); + writeSolidFillCell(xlsx, "D15", Qt::blue); + writeSolidFillCell(xlsx, "D17", Qt::yellow); + writeSolidFillCell(xlsx, "D19", Qt::magenta); + writeSolidFillCell(xlsx, "D21", Qt::green); + writeSolidFillCell(xlsx, "D23", Qt::gray); + writePatternFillCell(xlsx, "F13", Format::PatternMediumGray, Qt::red); + writePatternFillCell(xlsx, "F15", Format::PatternDarkHorizontal, Qt::blue); + writePatternFillCell(xlsx, "F17", Format::PatternDarkVertical, Qt::yellow); + writePatternFillCell(xlsx, "F19", Format::PatternDarkDown, Qt::magenta); + writePatternFillCell(xlsx, "F21", Format::PatternLightVertical, Qt::green); + writePatternFillCell(xlsx, "F23", Format::PatternLightTrellis, Qt::gray); + + writeBorderAndFontColorCell(xlsx, "H13", "Qt::red", Qt::red); + writeBorderAndFontColorCell(xlsx, "H15", "Qt::blue", Qt::blue); + writeBorderAndFontColorCell(xlsx, "H17", "Qt::yellow", Qt::yellow); + writeBorderAndFontColorCell(xlsx, "H19", "Qt::magenta", Qt::magenta); + writeBorderAndFontColorCell(xlsx, "H21", "Qt::green", Qt::green); + writeBorderAndFontColorCell(xlsx, "H23", "Qt::gray", Qt::gray); + + //--------------------------------------------------------------- + //Create the second sheet. + xlsx.addSheet("Fonts"); + + xlsx.write("B3", "Normal"); + Format font_bold; + font_bold.setFontBold(true); + xlsx.write("B4", "Bold", font_bold); + Format font_italic; + font_italic.setFontItalic(true); + xlsx.write("B5", "Italic", font_italic); + Format font_underline; + font_underline.setFontUnderline(Format::FontUnderlineSingle); + xlsx.write("B6", "Underline", font_underline); + Format font_strikeout; + font_strikeout.setFontStrikeOut(true); + xlsx.write("B7", "StrikeOut", font_strikeout); + + writeFontNameCell(xlsx, "D3", "Arial"); + writeFontNameCell(xlsx, "D4", "Arial Black"); + writeFontNameCell(xlsx, "D5", "Comic Sans MS"); + writeFontNameCell(xlsx, "D6", "Courier New"); + writeFontNameCell(xlsx, "D7", "Impact"); + writeFontNameCell(xlsx, "D8", "Times New Roman"); + writeFontNameCell(xlsx, "D9", "Verdana"); + + writeFontSizeCell(xlsx, "G3", 10); + writeFontSizeCell(xlsx, "G4", 12); + writeFontSizeCell(xlsx, "G5", 14); + writeFontSizeCell(xlsx, "G6", 16); + writeFontSizeCell(xlsx, "G7", 18); + writeFontSizeCell(xlsx, "G8", 20); + writeFontSizeCell(xlsx, "G9", 25); + + Format font_vertical; + font_vertical.setRotation(255); + font_vertical.setFontSize(16); + xlsx.write("J3", "vertical", font_vertical); + xlsx.mergeCells("J3:J9"); + + //--------------------------------------------------------------- + //Create the third sheet. + xlsx.addSheet("Formulas"); + xlsx.setColumnWidth(1, 2, 40); + Format rAlign; + rAlign.setHorizontalAlignment(Format::AlignRight); + Format lAlign; + lAlign.setHorizontalAlignment(Format::AlignLeft); + xlsx.write("B3", 40, lAlign); + xlsx.write("B4", 30, lAlign); + xlsx.write("B5", 50, lAlign); + xlsx.write("A7", "SUM(B3:B5)=", rAlign); + xlsx.write("B7", "=SUM(B3:B5)", lAlign); + xlsx.write("A8", "AVERAGE(B3:B5)=", rAlign); + xlsx.write("B8", "=AVERAGE(B3:B5)", lAlign); + xlsx.write("A9", "MAX(B3:B5)=", rAlign); + xlsx.write("B9", "=MAX(B3:B5)", lAlign); + xlsx.write("A10", "MIN(B3:B5)=", rAlign); + xlsx.write("B10", "=MIN(B3:B5)", lAlign); + xlsx.write("A11", "COUNT(B3:B5)=", rAlign); + xlsx.write("B11", "=COUNT(B3:B5)", lAlign); + + xlsx.write("A13", "IF(B7>100,\"large\",\"small\")=", rAlign); + xlsx.write("B13", "=IF(B7>100,\"large\",\"small\")", lAlign); + + xlsx.write("A15", "SQRT(25)=", rAlign); + xlsx.write("B15", "=SQRT(25)", lAlign); + xlsx.write("A16", "RAND()=", rAlign); + xlsx.write("B16", "=RAND()", lAlign); + xlsx.write("A17", "2*PI()=", rAlign); + xlsx.write("B17", "=2*PI()", lAlign); + + xlsx.write("A19", "UPPER(\"qtxlsx\")=", rAlign); + xlsx.write("B19", "=UPPER(\"qtxlsx\")", lAlign); + xlsx.write("A20", "LEFT(\"ubuntu\",3)=", rAlign); + xlsx.write("B20", "=LEFT(\"ubuntu\",3)", lAlign); + xlsx.write("A21", "LEN(\"Hello Qt!\")=", rAlign); + xlsx.write("B21", "=LEN(\"Hello Qt!\")", lAlign); + + Format dateFormat; + dateFormat.setHorizontalAlignment(Format::AlignLeft); + dateFormat.setNumberFormat("yyyy-mm-dd"); + xlsx.write("A23", "DATE(2013,8,13)=", rAlign); + xlsx.write("B23", "=DATE(2013,8,13)", dateFormat); + xlsx.write("A24", "DAY(B23)=", rAlign); + xlsx.write("B24", "=DAY(B23)", lAlign); + xlsx.write("A25", "MONTH(B23)=", rAlign); + xlsx.write("B25", "=MONTH(B23)", lAlign); + xlsx.write("A26", "YEAR(B23)=", rAlign); + xlsx.write("B26", "=YEAR(B23)", lAlign); + xlsx.write("A27", "DAYS360(B23,TODAY())=", rAlign); + xlsx.write("B27", "=DAYS360(B23,TODAY())", lAlign); + + xlsx.write("A29", "B3+100*(2-COS(0)))=", rAlign); + xlsx.write("B29", "=B3+100*(2-COS(0))", lAlign); + xlsx.write("A30", "ISNUMBER(B29)=", rAlign); + xlsx.write("B30", "=ISNUMBER(B29)", lAlign); + xlsx.write("A31", "AND(1,0)=", rAlign); + xlsx.write("B31", "=AND(1,0)", lAlign); + + xlsx.write("A33", "HYPERLINK(\"http://qt-project.org\")=", rAlign); + xlsx.write("B33", "=HYPERLINK(\"http://qt-project.org\")", lAlign); + + //--------------------------------------------------------------- + //Create the fourth sheet. + xlsx.addSheet("NumFormats"); + xlsx.setColumnWidth(2, 40); + writeInternalNumFormatsCell(xlsx, 4, 2.5681, 2); + writeInternalNumFormatsCell(xlsx, 5, 2500000, 3); + writeInternalNumFormatsCell(xlsx, 6, -500, 5); + writeInternalNumFormatsCell(xlsx, 7, -0.25, 9); + writeInternalNumFormatsCell(xlsx, 8, 890, 11); + writeInternalNumFormatsCell(xlsx, 9, 0.75, 12); + writeInternalNumFormatsCell(xlsx, 10, 41499, 14); + writeInternalNumFormatsCell(xlsx, 11, 41499, 17); + + writeCustomNumFormatsCell(xlsx, 13, 20.5627, "#.###"); + writeCustomNumFormatsCell(xlsx, 14, 4.8, "#.00"); + writeCustomNumFormatsCell(xlsx, 15, 1.23, "0.00 \"RMB\""); + writeCustomNumFormatsCell(xlsx, 16, 60, "[Red][<=100];[Green][>100]"); + + //--------------------------------------------------------------- + //Create the fifth sheet. + xlsx.addSheet("Merging"); + Format centerAlign; + centerAlign.setHorizontalAlignment(Format::AlignHCenter); + centerAlign.setVerticalAlignment(Format::AlignVCenter); + xlsx.write("B4", "Hello Qt!"); + xlsx.mergeCells("B4:F6", centerAlign); + xlsx.write("B8", 1); + xlsx.mergeCells("B8:C21", centerAlign); + xlsx.write("E8", 2); + xlsx.mergeCells("E8:F21", centerAlign); + + //--------------------------------------------------------------- + //Create the fifth sheet. + xlsx.addSheet("Grouping"); + qsrand(QDateTime::currentMSecsSinceEpoch()); + for (int row=2; row<31; ++row) { + for (int col=1; col<=10; ++col) + xlsx.write(row, col, qrand() % 100); + } + xlsx.groupRows(4, 7); + xlsx.groupRows(11, 26, false); + xlsx.groupRows(15, 17, false); + xlsx.groupRows(20, 22, false); + xlsx.setColumnWidth(1, 10, 10.0); + xlsx.groupColumns(1, 2); + xlsx.groupColumns(5, 8, false); + + xlsx.saveAs("Book1.xlsx"); + + //Make sure that read/write works well. + Document xlsx2("Book1.xlsx"); + xlsx2.saveAs("Book2.xlsx"); + + return 0; +} diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/documentproperty/doc/images/doc_property.png b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/documentproperty/doc/images/doc_property.png new file mode 100644 index 0000000000000000000000000000000000000000..bd449c6571d33fbce73da24e93db4f738faa1382 GIT binary patch literal 32276 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 Q+m56xuP#?9V;1=T0Oq?DI{*Lx literal 0 HcmV?d00001 diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/documentproperty/doc/src/documentproperty.qdoc b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/documentproperty/doc/src/documentproperty.qdoc new file mode 100644 index 0000000..d4f7671 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/documentproperty/doc/src/documentproperty.qdoc @@ -0,0 +1,11 @@ +/*! + \example documentproperty + \title Document Properties Example + \brief This is a simplest xlsx examples. + + \image doc_property.png + + \ingroup qtxlsx-examples + + This example demonstrates how to set the document properties. +*/ diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/documentproperty/documentproperty.pro b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/documentproperty/documentproperty.pro new file mode 100644 index 0000000..39c74d5 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/documentproperty/documentproperty.pro @@ -0,0 +1,10 @@ +TARGET = ducumentproperty + +#include(../../../src/xlsx/qtxlsx.pri) +QT+=xlsx + +CONFIG += console +CONFIG -= app_bundle + +SOURCES += main.cpp + diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/documentproperty/main.cpp b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/documentproperty/main.cpp new file mode 100644 index 0000000..1cb3f89 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/documentproperty/main.cpp @@ -0,0 +1,20 @@ +#include +#include "xlsxdocument.h" + +int main() +{ + QXlsx::Document xlsx; + xlsx.write("A1", "View the properties through:"); + xlsx.write("A2", "Office Button -> Prepare -> Properties option in Excel"); + + xlsx.setDocumentProperty("title", "This is an example spreadsheet"); + xlsx.setDocumentProperty("subject", "With document properties"); + xlsx.setDocumentProperty("creator", "Debao Zhang"); + xlsx.setDocumentProperty("company", "HMICN"); + xlsx.setDocumentProperty("category", "Example spreadsheets"); + xlsx.setDocumentProperty("keywords", "Sample, Example, Properties"); + xlsx.setDocumentProperty("description", "Created with Qt Xlsx"); + + xlsx.saveAs("Test.xlsx"); + return 0; +} diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/extractdata/doc/src/extractdata.qdoc b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/extractdata/doc/src/extractdata.qdoc new file mode 100644 index 0000000..563cd59 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/extractdata/doc/src/extractdata.qdoc @@ -0,0 +1,16 @@ +/*! + \example extractdata + \title Extract Data Example + \brief This is a simplest Qt Xlsx example. + \ingroup qtxlsx-examples + + This example demonstrates how to extract data form existing + .xlsx file with Qt Xlsx Library. So lets see how this is achieved. + + This creates a new instance of the all important Document + class which gives you access to the Excel workbook and worksheets. + \snippet extractdata/main.cpp 0 + + Extracts data from current worksheet. + \snippet extractdata/main.cpp 1 +*/ diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/extractdata/extractdata.pro b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/extractdata/extractdata.pro new file mode 100644 index 0000000..6a4bf4d --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/extractdata/extractdata.pro @@ -0,0 +1,9 @@ +TARGET = extractdata + +#include(../../../src/xlsx/qtxlsx.pri) +QT+=xlsx + +CONFIG += console +CONFIG -= app_bundle + +SOURCES += main.cpp diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/extractdata/main.cpp b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/extractdata/main.cpp new file mode 100644 index 0000000..041aa5d --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/extractdata/main.cpp @@ -0,0 +1,41 @@ +#include +#include "xlsxdocument.h" + +int main() +{ + { + //Create a new .xlsx file. + QXlsx::Document xlsx; + xlsx.write("A1", "Hello Qt!"); + xlsx.write("A2", 12345); + xlsx.write("A3", "=44+33"); + xlsx.write("A4", true); + xlsx.write("A5", "http://qt-project.org"); + xlsx.write("A6", QDate(2013, 12, 27)); + xlsx.write("A7", QTime(6, 30)); + xlsx.saveAs("Book1.xlsx"); + } + + //![0] + QXlsx::Document xlsx("Book1.xlsx"); + //![0] + + //![1] + qDebug()<value(); + } + //![2] + + return 0; +} diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/formulas/doc/src/formulas.qdoc b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/formulas/doc/src/formulas.qdoc new file mode 100644 index 0000000..a91850c --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/formulas/doc/src/formulas.qdoc @@ -0,0 +1,24 @@ +/*! + \example formulas + \title Formulas Example + \brief This is a simplest Qt Xlsx example. + \ingroup qtxlsx-examples + + This example demonstrates how to create a new + .xlsx file containing formulas + with Qt Xlsx Library. So lets see how this is achieved. + + This creates a new instance of the all important Document + class which gives you access to the Excel workbook and worksheets. + \snippet formulas/main.cpp 0 + + A default worksheet have been created by Document. Let's start + by adding some basic formulas. + \snippet formulas/main.cpp 1 + + Then add one array formula. + \snippet formulas/main.cpp 2 + + Now save the file and all its components. + \snippet formulas/main.cpp 3 +*/ diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/formulas/formulas.pro b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/formulas/formulas.pro new file mode 100644 index 0000000..10d2978 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/formulas/formulas.pro @@ -0,0 +1,9 @@ +TARGET = hello + +#include(../../../src/xlsx/qtxlsx.pri) +QT+=xlsx + +CONFIG += console +CONFIG -= app_bundle + +SOURCES += main.cpp diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/formulas/main.cpp b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/formulas/main.cpp new file mode 100644 index 0000000..c824af3 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/formulas/main.cpp @@ -0,0 +1,92 @@ +#include +#include "xlsxdocument.h" +#include "xlsxformat.h" +#include "xlsxworksheet.h" +#include "xlsxcellformula.h" + +QTXLSX_USE_NAMESPACE + +int main() +{ + //![0] + Document xlsx; + //![0] + + //![1] + xlsx.setColumnWidth(1, 2, 40); + Format rAlign; + rAlign.setHorizontalAlignment(Format::AlignRight); + Format lAlign; + lAlign.setHorizontalAlignment(Format::AlignLeft); + xlsx.write("B3", 40, lAlign); + xlsx.write("B4", 30, lAlign); + xlsx.write("B5", 50, lAlign); + xlsx.write("A7", "SUM(B3:B5)=", rAlign); + xlsx.write("B7", "=SUM(B3:B5)", lAlign); + xlsx.write("A8", "AVERAGE(B3:B5)=", rAlign); + xlsx.write("B8", "=AVERAGE(B3:B5)", lAlign); + xlsx.write("A9", "MAX(B3:B5)=", rAlign); + xlsx.write("B9", "=MAX(B3:B5)", lAlign); + xlsx.write("A10", "MIN(B3:B5)=", rAlign); + xlsx.write("B10", "=MIN(B3:B5)", lAlign); + xlsx.write("A11", "COUNT(B3:B5)=", rAlign); + xlsx.write("B11", "=COUNT(B3:B5)", lAlign); + + xlsx.write("A13", "IF(B7>100,\"large\",\"small\")=", rAlign); + xlsx.write("B13", "=IF(B7>100,\"large\",\"small\")", lAlign); + + xlsx.write("A15", "SQRT(25)=", rAlign); + xlsx.write("B15", "=SQRT(25)", lAlign); + xlsx.write("A16", "RAND()=", rAlign); + xlsx.write("B16", "=RAND()", lAlign); + xlsx.write("A17", "2*PI()=", rAlign); + xlsx.write("B17", "=2*PI()", lAlign); + + xlsx.write("A19", "UPPER(\"qtxlsx\")=", rAlign); + xlsx.write("B19", "=UPPER(\"qtxlsx\")", lAlign); + xlsx.write("A20", "LEFT(\"ubuntu\",3)=", rAlign); + xlsx.write("B20", "=LEFT(\"ubuntu\",3)", lAlign); + xlsx.write("A21", "LEN(\"Hello Qt!\")=", rAlign); + xlsx.write("B21", "=LEN(\"Hello Qt!\")", lAlign); + //![1] + + //![2] + xlsx.addSheet("ArrayFormula"); + Worksheet *sheet = xlsx.currentWorksheet(); + + for (int row=2; row<20; ++row) { + sheet->write(row, 2, row*2); //B2:B19 + sheet->write(row, 3, row*3); //C2:C19 + } + sheet->writeFormula("D2", CellFormula("B2:B19+C2:C19", "D2:D19", CellFormula::ArrayType)); + sheet->writeFormula("E2", CellFormula("=CONCATENATE(\"The total is \",D2:D19,\" units\")", "E2:E19", CellFormula::ArrayType)); + //![2] + + //![21] + xlsx.addSheet("SharedFormula"); + sheet = xlsx.currentWorksheet(); + + for (int row=2; row<20; ++row) { + sheet->write(row, 2, row*2); //B2:B19 + sheet->write(row, 3, row*3); //C2:C19 + } + sheet->writeFormula("D2", CellFormula("=B2+C2", "D2:D19", CellFormula::SharedType)); + sheet->writeFormula("E2", CellFormula("=CONCATENATE(\"The total is \",D2,\" units\")", "E2:E19", CellFormula::SharedType)); + + //![21] + + //![3] + xlsx.save(); + //![3] + + //Make sure that read/write works well. + Document xlsx2("Book1.xlsx"); + Worksheet *sharedFormulaSheet = dynamic_cast(xlsx2.sheet("SharedFormula")); + for (int row=2; row<20; ++row) { + qDebug()<read(row, 4); + } + + xlsx2.saveAs("Book2.xlsx"); + + return 0; +} diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/hello/doc/images/hello.png b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/hello/doc/images/hello.png new file mode 100644 index 0000000000000000000000000000000000000000..294bba5caaa2a4265b493d7ddd409d2caadd2540 GIT binary patch literal 15311 zcmZX*by$>9w?0fuHzM8O&<*0yokN3wG!hb$(%s!4F*HMi64H%;beD8D4Bg-8dCz-Y z=lA_HwfD34nicoD*V@k$p{gQ_g-(hN2M32GFDIoA2L~Sm`@DpT0DGmh(3^+7!8@zV zO2Ac(lJCR5AX$nli^IWvkHdI0L56*&Hj`6VhJ*8DgoE=BhJ(9@{p7y~2j|KO2X|l$ z2Pc#c2S@xRt62>Q2lrlCUP@fk-SF7Q+J#KVt@r}uJerlHl=wk~`EN`%uY_Cq{NitF$G_DVft7c@md5-;I%^XvPKh zIs@@=1H`H=FdO%t9PC@0A8~0*(s1P~MZI+d*2Zy!VDmT;-oP_Z!$l*t2A4#x0d(cB zu$69fcbh9~b^i`U`%B>Nk)(%e5p`+Qq$>>1xL^*Ob-_g7L{N}~n@3C4L;_hW^ZaKn zH=gcVsrCi$>u5L`IJ#V3B!3}d_p)W~7-TwsnBZ@*0+7LF``Hre%e8XcydQIf=dVS_ z9@*l?mCj`UU9x6`^yd(u4HintxeVeFjb(3{=bjf5;iIf4YhF@k=z zD;$y`qtqT2)ger6uMORpRFO9V^S^qz&wgtjhgY!o=HzatS=%Y~%qEb}mepQaaHD-o6 ze_3YfM3!H=coW2Hr5(&vDMw15NW1vK5|IGzRUy&`)H6Z%Yic}E0BZy)@;525+|Tkg z58Meg1>-WEBN|wqOv=yDPNTUSzCR`HzVtV$W=3Yp4z4j(#j~nOa|xLfiM~H+*7dHo zWi&QZEy?N`o9%*DTn??aR%97@caqWvu()EBh!H%)9Y={K`Z%?AJE*Z34}Xcrg8oen4gH}O+IFdH0xow#cOtbHY_Fp;v+4#h7xQD(1xsml#t58O|l zkc@V&il@xfujHIaGvVvh_(}FI6rW(JTlJ>8+oNg$&9XRyyPY(=)SJoCN>{8H9+kD@ zvHlGD0G@^#08{!C_iLgck7R|hv7x-dL5OQNBA*f!(y{P}B7heZsF=tNXR#va0&mGkZk;c<%C$%8#_CS2-LHm+fus07&O>sf5#lBT6we z0_t;2F)9eZclrds#|G0{aRrhu@Ey4-7X)-`ROO-4+<)Z#oqvkx*ywKarY%Vjj)V1p z-s*F}0P5@)BO4lKngLTwk*t+3Pxa%qy8T4>T_RPV>&k`VIJ#4d zi)96Fb2Ggg>KM^zd<_Pnz$Z#ztp_!F zC`<_`Cy6dS8(m~Lz1&}P0Poh2&ZhSYkD2tJ&-yc8e7v7O1bxIw^P;vK0%5CQZKcft z+3Y^p+N%i4EaXJaxW_i%3sWiP;36fcH0~V6X)Ax`MSh^AjX>d3(b@<#LoSLQ5N8se zJr4P@K06^Ln*|!r%`?E_)FjG9$rPc$Wt1`pZOjy=4EAI&j{H7@N__=3e_a2tn_0XZ zmYXD~aOqFvf`HM;m&v<}k>`B-NTa}X@2(YQKuAweA-<=9GC^o#P~d14=tT1!4DH<{ z-HI>vM`qvh4A_rH!z*NgE2GiblDd!Tc7}{0l8O|1BVB)VA7;o8TJ?KJ5dot6@@&7; zVSC53R@#C7;4o&xJ+Wk>ij#^czx=sbm{0WGg()*%_11?EhZ{@BY+qxg zWrV-yst{8N5BR%HAb#z6;-OfJ9oVBi@g?9=aly-ziEUUzl|jTded&uEI+GVCgeszT zX?*47(Zh0S&SK{_KX^Ek%%=~8*y<%6chgL#tHA>dW+Z!@Q6KpcK_96R&UjxV*BC1z z71O?Dv=$fdU;$dEp)WL(ZqcwS|Du+X3(L@A{lezfmMeC7s(=y)meZv(B7}QKh;*dz z`h}7u8Bg%bRjIRQC}5nU`A1llCEd9-k^rba!_o?x)BZfxsqtbqV}u#2I|0@lle_8H zc_vBK6kU4S^;jPJWGEO=SZpLnS-8EUS;xWu^N;I!GDO2!WaIJUu~NuqSB>v$LzTZ~ zR&5vw!!hclwZW=UXyE+l20>)DF4^6vL6xtVQgX(7%_jv?f>R1}kl5n5LRJAv?ix>b zw*6XJep7QnYaBk}Z+65u4AN!cc(1Yf1pHouUB53B5g3lXG4DdEh@`~JQmI=N4q+qy6-i_T=bI0zr>@JIf^!N_bPEg>i_N1Zn`CBXY%r)0LO< z@g5tIR_j3$x;@zDH0NT#)=QMekMtSR6!Xr(_JM>JkWyu=f4vhvTx}TVNm637o2|7D znx&ua7cx@%Bk!xNIu%j@G;R6{bn=VryHInc+30RdUAR^^6~3|+$GWHENOropA=or{ z%djHwXPnh-{fCgDZqvYNJ{)@?;fc|g-H3o`hkye1Q>nP230fZ;A;ZPNPK`LbD#y!~ zo+LM;a`)pe&JjZs-85`n8fkU4$L3~gTMdd~Np8em6Q=$gc9IR15)w_Xis%vjE5yYnW!AJY5>fWc2K){c&d^SW-;AX?ful#!a4ZDOQ}$ zOV6w*N|~PDi`la7+-=42r;Vxnd;7`pnVLVZzzX%bqX*L%VsB@p^quiub32lDJ@pC_ zEAEHd8?l3(unrTo1HT&luKnO>&tcxPec$~wyD&QWO70c%VC5-EDtS)JxgewU3;`K> z!6n-Fc4|>}avN(yBCu-_vWu+_Hd9yA$4C@g>vr{xlRuKY@q0I&vIYH;R3bWXHz3he`QF8Su)k>KH>i;;`CYEely zpPPE;CRBWMqLAd!ZP&Ap@VE(?Ku=-yeuQZh`o-)t4&wgR*Tp%YcRBA(H6i{GF`2BV zY(%@CNwtckp5K7dO=B10v)$gVYDDzMIy=l1qzi^85?=!DUT)X4zf_ zCRif6VF35e>6~$U5lgP0i1J$>Ewj0lis~_QTvM0~7wC@DFF312WWUCq`HmMs{S(D2 z*Lz-4SMtgD`lQdg0-!71-2@kcxJ!B@_XCi~%O>5|*pxEG46lrJ5x^S2353pmlg051 zVi>Jem$K@YXq3m57}^-{j|4qN`Da30dM@NV!*=AXxnhYl>;HHql6l<>7Ll#?t;nmm z$3uBLI6La<6h6+G?D1kB@GV!$law8#ij>jVoBbnxqO@x}fHu1owjO8CxJzA#eoO%t z#S5bVL+ zvBNEW{0_Z=|0GKehT8!Q5B(*NlXzb)G;@4b*yt{N{=*Ryalc$7dtAPgn?s_>{$JjR z%ej;T%VW$%Cg>RdmQ`g$0AEcHxPV?<#{6r`{YVQ5Fl0KZP+f2YVWgFwW?a;+L74!E z{GvW|)px7`;G;VPiFW;Ge}6bm{4@L-0t}E^&Pv3RA`yI;^NySLGWc*I0y(DgUOc`i z0g&}kkuHJZTS)bvFb^Af6~sJwzMIR_#``0ayic}Ho;IG?gO^8-__)Iw5=`Qpm$^dS zyKml_fzf4BlGh33n7J7hr_3m_vxHRIO!0LSd4IRq0azP{ z{op&2_erbfTFO$|59_~tt6SB(a%bhC`}yZx=J7);xV4jrc?ZA%0+qy`y=&n0IA9pV zIFPc_5S_eFF_;kR{X||PyF7f@5PevQP2c<+@jEp3@@Qjg`teWxqTx`w<9MFZhbIsB z+hPhsvmPK(__xh!t~?=gvaqu(|=8Zh`${`Y%kmv&z<$4UFBA4}K>2X?r*j-ZJ0X!3= zcyg6&IYoxY$Y@p2bqZ@plYVxEP(+LZD+DsEHB*uk^_MJkGAeYhwhzWSLQDAV7usx& zb#|+kJ8&P2KiL@!%q+LfjOb7~>)( z7?02oP3@a>X=DoQd6?h3 zviBYw%6^cc$Pa4a*m&A~{FRq#?_BgNeTg$3LaCWyyW;q!>Vdj!tmmiwJfX+>C!6`^ zks+Nbj0aO59?fA5ZYBB&_FSRi#4hV0q3ttI1>Vs-J3*fJuhM+ya%^~PP|_1WSZZZ> zKkhFM-8gAitbDosV;6pGVv;$B$^`;=#7elfYR7BpW&ov^vrU#uKR_QeBpBcRIcU0q z*1nRyXCiu?QK)^zqTF!&zRkKn0nyR{4F?up@z%Jk6eY2sB7=-MpDqc}y2npi^`{YR ztvcr3sy4;Hd$=$D#;*c6=5IXOT311m4JeEHPy~wod_*=S^oA%>B9b4Ziy5fXA<6s; zCFf$U!DC#o3)qX4zF(z>;rtn1qR?@H=H07%K8yg(yr0!!%W*4HtJ&uYiJ+~z=711Q zEdCX)xYS5z&&ee(*fn@C{GujCSgC%{8`1b5d=taP>jZ{;cmsn=RUrgJcV@A)40qlC zDR>DGvK}-9cn&S%_nYpDnEaO}716o7JwmiUq!?5WGq#}X9!^eGLz z)+$k6+-L}$!#GdwjB#&26nRS-KOHm~0Ef0wincpENsy&uHA6V3`0SYgWH9#Parhv>4x#<|xGVB=>0cf64uE~rN%<=73%jQ{Zl zEAHJ^!pqanXQ&_o2lp28{l16A{nilmE zdwGMA+Hs>^-Gz;sxzhQ`A%mAgvh*_RDwR%yKtuRxJCf*0L0bJhBO^r23OM7C882?E z=TCge9@Kfq8bquo#BI(bX*kT9Dq}dj|MLsD|S$ zm$VCG3oy|AOgarfU=6e;3x;%9*? z7P#qD-0pey9s_IG1_SYFwtV@tjIiDInIwyUY)h+1uV1Ks0BX%!@m=Alh5XXE_l0dE z82C@R$M`M`J_--@BpMD6{5&n$(AM-RP^gl{=ny2Duvg>mz}IILP8s%>K2xIAsm@W1 zW7oZZL$wozX=v3n5dT-kc;s4MnC4Z|%-c#l?lj*QooO1j6_w8o6Ow{luNDy4;HdTk z7qPR9(r*IDvRH^o{_geZwIUry2`O7bQAS$lx3NBr%>0v~8y_Q;%BISx0cKwC0VgK1 zp0Pwcd&zOYf2L8z-!4Tna>j$Y9yZ6RLvn#`MhF)otS&j0 znf9Ey5{8!n#5V79Rknu}8w%mLNT3p~2|NG~Xuh2YlFNNU(2y#Jp5d9Av5gY=-hElE z3~Bcnzz&|g)=dLw7SkrRn;b6G2jk&vb<85x4tZ{B<{ z^bMOn^iPMhN(2*0(fW^BCUhbXDh*zB1BnXd&xOB~Z+UPa`(~vPUiL1Sg7L%18lbUo zA~|hlh4feqa~KzzoR+^8Iob%7Zs4ygVRIQ=|7R{r3}o#!htbXQppT1S+XRMFaf1i- znmU0MJCXsOqzM=wp<>d76EtXqw^sV3<1~BHdN*;uheLvpU0AW`W;PYUlr=U;pdz#- zT-vQ1&v^A9azMiVXuCT}D1x99a=VF^Wprm5{Uz?!`*myzK5vQv$6D!(eznbetn2TC z6A=L1hek8=;R#C$2Jj~nl6|fPPi20|j<)>v&oi^SqGyD(6o5lOT{NvCOO^#fFY&O6 zwJcA{9t+3vHER&8Eg z-cNP2ahDJG6=pRJ=Wvm|9rFdN zgcWT15o=i8TKWC+PdACd11M>-KcFhrBo_s}dLdTN-GAjR)RkV%6)bz^V+IDPI<-AEfT0frkGijr-u~D~*&XAh1(x~hNChY|p>0u2y6ceeUN3Fnr#3_4oR@1w}8 z(bFNl$_u&rFne_%r9)nuus@=)J@WRpGGy=GaJjDxiJlg@_g?)qnSKCJYr*#H!ujJs zCO+X0u*8|iQ$58CM`~$M4L-?X8P=GWqqBgnHY{z@fuNezUFJ2I*I4tHJL{C2#^0J- za*OF8`E1HFS%#D9nsZZjr--$UWAp}0U1 zJtH~V?kf)jBb{*}heYnt`;;)v$GtNIAyYX6@QlI#yl7ZsJ_#dBu1?ukrk zW>Enld;o&>k=L3zl6QU8fTu-0?7OIqhEDl0-pD4xMO&*QavX4TJ^GFJU3B1^Ns}~Z zBm<6j6Tg5&xOH5hgqn?ucho$r#zD+YhT^&)HHUQk=S>k0aN1h`JL;_n_JQog-7rG2 zzp$LNsy%pxP72CnV_p~VfRzA#8w!^te{&Dte{)ar-5(Q2YVOKlj^Z=V-$v;}{Mb8y zglNk;vrGiRkC1NH<01wPs#=iGbnejgxgMf#x5{>%`nf? zVK#%K_Mg*Gf401eV>A4E`%1P+rt2yZV;@;G9kSJ*b%Hncur}A3hWe$=TYN~gIUVvC zRFJH8)|wUwer$lntXZswg75ITC-ZH(Vg%ep^8e=SOwr1-)*Ggb04j_*ma{ig!bnMw z;MIuO6SH`C7)^=D*t1uv_WPb))-%1^T%_U7cHT<-H>o1#R3rV9|3 zc=_-cV5o#-CC&?zjOsD>ToX4(w9f$k?jBb~JCNWb5O^vrNlYkdz;S1SgAK}K5&2gA zAoqm}G{`e{cE^e{`V7tA@4oWJ=|tI}*$lVV}(8{E*SwpQg? z2@S`!YvYZ18R216iNJ#6_Eii->T%z#!{CPNro&ozkIwbHZ)UT)(gk?BopYlO+<;Ls zP?p`eyFzaP^s!rG!x+5;77y?tbEiR@o_7@L)rh8GD7soF(OD~wV6U&M|KYZdATrjD z0JwYXB6vUQ??E3b5`yn00B_E*J%e@TP(=JC&zPa_uLnTW5H6A*)6L@YVqhJjyTh=* zX8qnjE(5da<5drk0nPb07G~71^@Fr6OfnWkco-PW!Cxf14|B;!^s^_k!PITkMtw$j z-0#!vCoFkVfGGafqziu%ScHqYopU}Z3=5jrylOh6Fo^e4aopX5h%Y!XOuWzwjdtli z1QPhBqncnj?jGh~sKuRmoFFu$$STI{LgQXl(J@J3U&s1>AOp4lKwEqh06hTRE=GF3 z5DH0-=lgp$#0yK@%Tw$KqH2Jp!@ht`u_9PhX7!x<5v-8B;}xl=d~}=~i1O6t8T(>0 zyj8>dn{gpE>e(INQkWjs()TNn`hsa=Y8X3oNIALNY@hN1%=7F8GKfBluK^Yjn73v%x`{PltSsRDScpOHcSCw~gLl81z=_}$7^)8{$seXjJc$Z~YL>QNW3>pT%U-7H@2+UGTS-%1 zdOPQQBD;a8z>sIBoaEC7tEn_se&=k?I^V^1OlQ9JtKrM$AGx9Zg_r?p{1uMSS8;Fs zEeC%o#Y7Ri-v$zassQZd-T^hQwhjIw)!(Q?>mUv&BMIMaM(u!Z?9v5nqG~4nAm|kh z3uf)z$_X*NAd1nacIpBWp=#dsW6Fc`E9uVqPtg#dIg}NYe|-n_Um~%jrZfxh?}Z&= z!@+l)CpRj-%c($cTxNQC!BmR7eX(TF6nDpLH0=HkO=H{v_|X7-$$_VRX2h6^u;^EV zxrpeFOPu@4s}7WQDVYCb=si#L0k^5hi=qQz3>y~YeJ}`d{+q~R=QO(d4HRJP1qPL) z{8m7QZ4r=TDf2A)m{(tFC?6+m!9yZ)FsJLvh2rjHH=2>$_BBrr50 z6TwHc`LQ-&{~se0`7a|=^Ee1{wQQvSZ;FQXL1Ep{((QYlG%8QDXK@S>$?CKBFi)Q- z&V}WfVsbg97yM%4T-hJvHv#}5a~S>8a(Xz-PEq0 zw(13YDE#(*Z4)(SnI{L3#DO&_gpghyL|Vb!|1Tvh6dltrD2uFz4SX*$!NUC8&p-}? z!F#X&X-=Y_%Iy$LM^7Pzz)e{70ZSv_5WNkPfue=EL4Qg7V}n9f+N!(F5ma=58jj&_ z!MOGi>c8rK(A^d}PIUKjik>CwQ5OH92*)*`G*0>(DkntS+#m?leb@5syz~y2Nboyi zKPh({W)o5~`kLv>@vr!#D@e|``C$mTk;PM9A(6hR$St(O$-J+a#fZ{-?K3UB(>n1@rBZ5c-jhuTw z6z@O2fK{D4_f2HwmQfL*cOvWLIha3`l!TZlMh!Q|e~;++C`+y151Zb_K=ekYXqdwx zJ3B_fB}!w>@@4r$^5~qJBW=fL_QQ*>PNyYl7b{aqq|_l)HjZYLZ6^leI1<3s%I=thbJ}qm zIVUT6#l9;I9=zSrh5ibgz|Aoy44u+SDstPKmgxYJCT8 z{bTK=5?qqH7!I<$NZX!A|_FlSUb)i!|b{TFIfLMNHY>ci9;d`7iPOQ?m zS4>!`=k}Xcl1pnD6kNQLJF@jAq?LtLqQ|J#G!PM+&i8Yr&}u4&&Gpg~Lo?YlaZ6He ztogpd8XpAAZ>R0C{G7b#7($H*SkmA?$d5BsqFP;FebD(Cp~t<)HXtAaVWyKpIVlXX zmbHstV@hdyyhRdx6`!2I1X-p}nGhUIjtpko^89^fdpa;*=h|!1pmM;r`7v}N6}+yX z{1O=+RncH>SveXZci^V-wIoXHU)#hNd~n27=XTJHrQO!YC^0H!RKNJ^+bL}*x4!H; z)Y;aQS;_+){JUFP3x2EA<%(W;jXs$2fQUdNY>_UA5j}#@N*Ea;9OqAS{PsYcO9Ln2 z!`WB$B#YQiDopb1v-s($U-H`UiJsnW!mWoqH=PguBPKso_J+-}QM?pyzL-52%eU?K zU@Wxda4n4ojZa%w2Fo*5O_*O-X2$B(@0r(Hc1E6#r=L$9K2hXN)H1p9 zlz$$CNfuZujS3>tDot`O`!S@CZX+Z;&`xKW*}^*f6;D!&mn_5U{*`Ush=x-&Byx#@ zH{c@X{}+JMBQl=A4-X@3Rf&-m@9l9EcOFsn-L!)Vx-7H#A7o2aS zn|pfys;RVDcFMW|GmI02Y~ojz|Cw0|`CRj-YpSBZ)qteAz9|!Fyb$UXG8^U80J)xg zmzR84PdRyu;q+(HS??Yn_L_=Z(EtpC9$5Pfm9+HGwf*K2m%;$?NgO;W#Cq3}RkF<(S0?Y;pH+an-uYRBM_SmZOMK+Y?fIt6J?Q zIh+27Ub47Mc80Q5!=^ZEY%^M70kA8(FpUTLa>}T)5ki(I@P@&hc;=S~Yh#jOO0our zM8oNOczaDb9Vc;drqG8?=5jq-jU%o_(L})T`p{q@b zZfNssZnpegE=8{Lr{ZUK{j`_4=KJBdWOwCPN!O&IDuo8E0pc*UQoTwC|Y%zz3uX@p~XHJT+ zib@Qexa&w8aOU(>`mlx5yY@^<5J=x=WH$LLuUXgAZU=N0N3VI$?BMq};$H{Pct zkTxJJxwfh7TmW-50`fwwuXT?qxO@$l zGQyPmUig`+@MI}1mwfh(4B?Fod)GSqE3{>=S1t}mP`Th(CJbK=arurh{+F4i?vsFT zm{;@wBk(Y(%?Op1(v5uQmRf0hgd;?nn46*I{$cB^OASivmu z)k#1JdWP0=S(=&IKwhF5;NE+46)=7iGwh5EM_&{rVhoCI$O%`i_LWRY$Ipgth|$vE zox4d?E$Fmt$sW!CKb(1;XZTVR!tNu;@ylGE5WQ%$4@^!8o0Jv82;;RDK})AE^JIB1 zBOXis&T0Ni$o*{X`RU>2cAKNpQ={t_(%6SPz%5sNg}cWG(Sj@E_h<*o0PS52a4oPoUb-pbiPoOZd#kF^_G zY9AWhyJEzjkZO_Cg%#0L!pL-sVbn}2S%SWgw`y}yTiI=1HzzA?UXa6j zyQKz)_B#~bt}PWq9oM-xs8*?({M3NArK4I}=G$qX%*)kzE~ttun1lzFypzwj(~JT? zDX!96hhUlnt@3l1*`0pq@D*M_2}ER}AHX%AS;w@QXFYCA_q%bLe{jSo6)vmveA(vQ zGq`rryw&)TQ*<$&hFRa3ZqcF8A_E^e<7JWNe9EWg?b+trIWcp(N1DE0Ke~rvnIN{r z$!kXL(pxlp(xiv_+fe;%XVhp1caTGXVV+`aVEof5q$FbDMx}2YcO;QR}&5uoVX_r2zYKp|dgL(QPgN&{5CuP zL+mT~#6a`i-JGD#je&Q=up9||H@A`6jlFyQenB{t<{Ft2Gp;pT! zcJ83~;ED$$KeKAzQS20*=dwl=pd;EuwHdw|6^A;WGs!gCx+GM)Bc*LOX6{m)LdXp2;y$>$*sXPTrWO;5 z1?}E(YR1F>Z=pb=&#Hbkc<4$A0uq>NREKpMpuO7)U2f z#eAP<-M0ZY^R~yS+YX^m8_`Vl!C`(E(4v?VCE>7np_|kB!|%-ZeVI5nmU;qJh0&5- zkvo^xZBJ1I-_XV~pob5W%xq)R4ZvgFcDGis_u$oNbJm}O&vo`Sjf40Pg>J{+c{$Hh z`y{LpAZRA7-`BO}m)s53aRn={MYq!a+L86(=G?x=L7ec8 zuM2v>)bH73kfk!)?MgK_K{%hIUaGF$@rtE1dC%%SYnA~=%M{%;aq}~AnZi|^Z+*sJ z2w%Zn>zCb{pghDp0?oL9vPNp+e>{pU)}4Hl^uY^mokdKf<+vHIr(`WyL#D4c=|LGs zN>T*qX7 z>gk$fC|vevsu&MqJ)fX&sQ|F?VtEuwcONp%;|-V!=3LSBtF7<>wp*c^Z>}Smbs&B{PlbI-Do|vy2aS@d{-+6~;z zpt4FMyz8LKn2PLNMA?r^y2P`P?T&rluUD<-#sbJJ8B=u`>r}q(&5hzY`UNbrmpJp; zR8>poUCr5N&+CiFRoAgNv-YPyl}o30x|>)03_P%v8a@KBo9WGew&J@rm3@9}`9Xu* zt1<3RxyB(#dWotAN8jz?ijw=V+N5?BSo7242j`uN9#29nc+k9+a0o z2G+gYXw5u16o@n{k_L{}JA)lZed?{`>oJuYKW6z9*3Vlu5#oZ_TF1H3XH}~#lJ$1; zYxv)fzdlR0`j4xsJ)I2`L!8QmWIBBEnULLW^7oI7f3r~6bOs2QqV*G^9?4@Z_4^kZ zgV15si42AuWc2b5hQW;K z%!+fL3lsU{{VQ3&j$`ct`yaUr*q>jo0op>WB*zYoesxXc%7!CQ^{T6Ur4o!FVy@+(U z>pngaGYID2yvVbl)nk@zO-kwKskj zZ77-AC^;tWxGrgK`bxeyj`)O*hCd0R{ZmFogZKP%W=UM#nOT}Hy6OtIdz$~?{7>5W z`rFM^MWe7bCq126wfc?hx_)Wv>Q;iQ-$QB%(y{%J0&VYCp;gbw7iC07I$bo(c5DyL zk(Q4b0JhnQckCgE6Xz#=gw6~zpL7CB(8PfZix_bxYuMjxYsp5pbm|sjfqT^3Nr=|5 zvwIU8IAUvhIQ*lsGV36<*dB1Q#rUix$@J9~qGbKeWk8)9iFUOiR)(;a#Wy2SMoLJfX$t73_hxJQ!m>$gCER)@8@r7Oii z&(9Vts#g~j%tsa@l(>z&?v57wgg%SrV>iN)LZ3^9Td(B~c9H;GpfUodr74>cWVVLM z*zZfF7HFkK=YTWJQhfIvO&5vT1$`2-IMI7SC?yPs15X%m?{QHEL@T3&ooXBX%$qHZ z(O2@Yg!fdbvm)Olg?{nOCZSdyDt|oAIPTD|r65IJ_qwA%`xYZYqjVxKt~t$*J~^VH zwTum~UJqTao3`(tQ8p13E=PQtu2o}6BG)Ri7G2g18D7U7Cva)T$umhZP4ytuZ8K1? zBO%Y+M29;kG?>NHR|E876CKG&_m>+pAk({2>xCel6M|kp8X^^PAknV6tl0=W+KPJ& zo#j1L7Q%tvwNxq1`obg3d0K(ck+ju)o+N9SX6!h7xXbF7;PQ{ByJYaK0_6?dbmW(i zP+1FbL0vz+Y8anO`wbLA|WfSe(dvCR{Q`Y>W zPG?nlNbFv|H^!T~8azc4q9uRgI4-M>DrrxgrlB9&zuQQN3U+EA-*-9S&n8`t5;K6q z$Ip=_3WP{`okxmM6W+^O3dj(r+Pu11orss%2JGl~ZT&ArFzrKU2P2ei&{A~3G-4Z4 zmlS!KL*d@|Fj+hK$*f>ymXFi=4fvq;-ADsqbDYosV&&44qPKYx1v24sz4(wR(Jf;l zc1A7w0Nk0*Hg%V!A|j$ePYgYqpFV0dV{a)D($}J(4i@e>odT5xG3iX{*%3G!z{7#y z;n4`etha4Q3_gc@M{~OvioA#q8)R|;5BQ%h1+v)Q``~llsT5W3e?t%#jWYSD)U{2? zN!TiKzehK2`%@`NTZAN#y8;GJEQL>Y`8#@LJ3ZMqD$8s(0!yKc#j@G81S+?E!{k{i z4UU$Ut7kvYLpqjIzufy0y=9@d<&N&{ri|B_GnB+C3VC&Yi)Z5E6XvvKQ&0fjWq1SO z?Mfp1X4k0^fGtMJA!1=dk-6+*sP$*M<9$^s;acgtq2+~@O<2iUsGXh}%_D;L$VQH* zJ%IdIf7^9q3<5@;g@(?z=b}|j-aG{jc|Aa(eez5f{<_Q!_3{_{z9y{)D)3X){bi8M zb}weaQPY0vDSC54yl`YBLEt%Y_m&7@^x%w46O2o8bto?h5U~d2q+`X5pe(lhZB!t* z+gya?=gVAF9i|kripGmLC}#Pn(H*!l52|l{s;wV`z@l}6A=%H?XLXw46_t~TMHW~R*&uXY>quX<{VW_XrR>bIRq)!45=fZ&f z055l=0yVK&T>^{jCl`XRESwy=JKFrssFQpqT1a@HSp~|m2#Y17$0d+qIL}_0P zrz$dB9V4bu&HQ^V)Cv`jjwVrW4R8tX`L8SV_wiD(r?x*YuaYqiv1ScC{=lBNg_D<7 Lk*bm~4*dTBzYy=D literal 0 HcmV?d00001 diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/hello/doc/src/hello.qdoc b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/hello/doc/src/hello.qdoc new file mode 100644 index 0000000..008947b --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/hello/doc/src/hello.qdoc @@ -0,0 +1,22 @@ +/*! + \example hello + \title Hello QtXlsx Example + \brief This is a simplest Qt Xlsx example. + \ingroup qtxlsx-examples + + This example demonstrates how to create a new + .xlsx file containing some basic data and calculations + with Qt Xlsx Library. So lets see how this is achieved. + \image hello.png + + This creates a new instance of the all important Document + class which gives you access to the Excel workbook and worksheets. + \snippet hello/main.cpp 0 + + A default worksheet have been created by Document. Let's start + by adding some basic data. + \snippet hello/main.cpp 1 + + Now save the file and all its components. + \snippet hello/main.cpp 2 +*/ diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/hello/hello.pro b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/hello/hello.pro new file mode 100644 index 0000000..10d2978 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/hello/hello.pro @@ -0,0 +1,9 @@ +TARGET = hello + +#include(../../../src/xlsx/qtxlsx.pri) +QT+=xlsx + +CONFIG += console +CONFIG -= app_bundle + +SOURCES += main.cpp diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/hello/main.cpp b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/hello/main.cpp new file mode 100644 index 0000000..54a5a2d --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/hello/main.cpp @@ -0,0 +1,25 @@ +#include +#include "xlsxdocument.h" + +int main() +{ + //![0] + QXlsx::Document xlsx; + //![0] + + //![1] + xlsx.write("A1", "Hello Qt!"); + xlsx.write("A2", 12345); + xlsx.write("A3", "=44+33"); + xlsx.write("A4", true); + xlsx.write("A5", "http://qt-project.org"); + xlsx.write("A6", QDate(2013, 12, 27)); + xlsx.write("A7", QTime(6, 30)); + //![1] + + //![2] + xlsx.save(); + //![2] + + return 0; +} diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/hyperlinks/hyperlinks.pro b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/hyperlinks/hyperlinks.pro new file mode 100644 index 0000000..c64e480 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/hyperlinks/hyperlinks.pro @@ -0,0 +1,9 @@ +TARGET = hyperlinks + +#include(../../../src/xlsx/qtxlsx.pri) +QT+=xlsx + +CONFIG += console +CONFIG -= app_bundle + +SOURCES += main.cpp diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/hyperlinks/main.cpp b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/hyperlinks/main.cpp new file mode 100644 index 0000000..74333cc --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/hyperlinks/main.cpp @@ -0,0 +1,25 @@ +#include +#include "xlsxdocument.h" + +int main() +{ + //![0] + QXlsx::Document xlsx; + //![0] + + //![1] + xlsx.write("A1", "http://qt-project.org"); + xlsx.write("A2", "http://qt-project.org/wiki#0f68b904e33d9ac04605aecc958bcf52"); + xlsx.write("A3", "mailto:info@qt-project.org"); + xlsx.write("A4", "file:///C:/User/test/abc.txt"); + //![1] + + //![2] + xlsx.save(); + //![2] + + QXlsx::Document xlsx2("Book1.xlsx"); + xlsx2.saveAs("Book2.xlsx"); + + return 0; +} diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/image/image.pro b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/image/image.pro new file mode 100644 index 0000000..4b708c0 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/image/image.pro @@ -0,0 +1,9 @@ +TARGET = image + +#include(../../../src/xlsx/qtxlsx.pri) +QT += xlsx + +CONFIG += console +CONFIG -= app_bundle + +SOURCES += main.cpp diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/image/main.cpp b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/image/main.cpp new file mode 100644 index 0000000..7dcf9c4 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/image/main.cpp @@ -0,0 +1,19 @@ +#include +#include "xlsxdocument.h" + +int main(int argc, char** argv) +{ + QGuiApplication(argc, argv); + + QXlsx::Document xlsx; + QImage image(40, 30, QImage::Format_RGB32); + image.fill(Qt::green); + for (int i=0; i<10; ++i) + xlsx.insertImage(10*i, 5, image); + xlsx.saveAs("Book1.xlsx"); + + QXlsx::Document xlsx2("Book1.xlsx"); + xlsx2.saveAs("Book2.xlsx"); + + return 0; +} diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/mergecells/doc/images/xlsx-mergecells.png b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/mergecells/doc/images/xlsx-mergecells.png new file mode 100644 index 0000000000000000000000000000000000000000..fdd266b231b063dcf350ea34a169d93ab1dcc7fc GIT binary patch literal 30545 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 P>XZmsxwHP(O|$h_3p%5JbQADDneX-nsa`1y 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 literal 0 HcmV?d00001 diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/mergecells/doc/src/mergecells.qdoc b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/mergecells/doc/src/mergecells.qdoc new file mode 100644 index 0000000..3198cc3 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/mergecells/doc/src/mergecells.qdoc @@ -0,0 +1,19 @@ +/*! + \example mergecells + \title Merge Cells Example + \brief Demonstrates how to merge cells + \ingroup qtxlsx-examples + + This example demonstrates how to generate a + simplest .xlsx file which contians merged cells with + Qt Xlsx Library. + + \image xlsx-mergecells.png + + Create an format which will be applied to the merged cells: + \snippet mergecells/main.cpp 0 + + Merge cells. + \snippet mergecells/main.cpp 1 + +*/ diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/mergecells/main.cpp b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/mergecells/main.cpp new file mode 100644 index 0000000..28e5e9d --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/mergecells/main.cpp @@ -0,0 +1,26 @@ +#include "xlsxdocument.h" +#include "xlsxformat.h" + +QTXLSX_USE_NAMESPACE + +int main() +{ + Document xlsx; + //![0] + Format format; + format.setHorizontalAlignment(Format::AlignHCenter); + format.setVerticalAlignment(Format::AlignVCenter); + //![0] + //![1] + xlsx.write("B4", "Hello Qt!"); + xlsx.mergeCells("B4:F6", format); + xlsx.write("B8", 1); + xlsx.mergeCells("B8:C21", format); + xlsx.write("E8", 2); + xlsx.mergeCells("E8:F21", format); + //![1] + xlsx.save(); + + return 0; +} + diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/mergecells/mergecells.pro b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/mergecells/mergecells.pro new file mode 100644 index 0000000..8ceb295 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/mergecells/mergecells.pro @@ -0,0 +1,9 @@ +TARGET = mergecells + +#include(../../../src/xlsx/qtxlsx.pri) +QT += xlsx + +CONFIG += console +CONFIG -= app_bundle + +SOURCES += main.cpp diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/numberformat/main.cpp b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/numberformat/main.cpp new file mode 100644 index 0000000..1fb4b9a --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/numberformat/main.cpp @@ -0,0 +1,52 @@ +#include +#include "xlsxdocument.h" +#include "xlsxformat.h" + +int main(int argc, char** argv) +{ + QGuiApplication(argc, argv); + + QXlsx::Document xlsx; + xlsx.setColumnWidth(1, 4, 20.0); + + QXlsx::Format header; + header.setFontBold(true); + header.setFontSize(20); + + //Custom number formats + QStringList numFormats; + numFormats<<"Qt #" + <<"yyyy-mmm-dd" + <<"$ #,##0.00" + <<"[red]0.00"; + xlsx.write(1, 1, "Raw data", header); + xlsx.write(1, 2, "Format", header); + xlsx.write(1, 3, "Shown value", header); + for (int i=0; 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 +#include "xlsxdocument.h" +#include "xlsxrichstring.h" +#include "xlsxworkbook.h" +#include "xlsxformat.h" + +int main() +{ + //![0] + QXlsx::Document xlsx; + //![0] + + //![1] + QXlsx::Format blue; + blue.setFontColor(Qt::blue); + QXlsx::Format red; + red.setFontColor(Qt::red); + red.setFontSize(15); + QXlsx::Format bold; + bold.setFontBold(true); + + QXlsx::RichString rich; + rich.addFragment("Hello ", blue); + rich.addFragment("Qt ", red); + rich.addFragment("Xlsx", bold); + xlsx.write("B2", rich); + + xlsx.workbook()->setHtmlToRichStringEnabled(true); + xlsx.write("B4", "Hello Qt Xlsx"); + + xlsx.write("B6", "Qt Xlsx"); + + //![1] + + //![2] + xlsx.saveAs("Test1.xlsx"); + //![2] + + QXlsx::Document("Test1.xlsx"); + xlsx.saveAs("Test2.xlsx"); + + return 0; +} diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/richtext/richtext.pro b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/richtext/richtext.pro new file mode 100644 index 0000000..10d2978 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/richtext/richtext.pro @@ -0,0 +1,9 @@ +TARGET = hello + +#include(../../../src/xlsx/qtxlsx.pri) +QT+=xlsx + +CONFIG += console +CONFIG -= app_bundle + +SOURCES += main.cpp diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/rowcolumn/main.cpp b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/rowcolumn/main.cpp new file mode 100644 index 0000000..b485d27 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/rowcolumn/main.cpp @@ -0,0 +1,38 @@ +#include +#include "xlsxdocument.h" +#include "xlsxformat.h" + +int main() +{ + QXlsx::Document xlsx; + xlsx.write(1, 2, "Row:0, Col:2 ==> (C1)"); + + //Set the height of the first row to 50.0(points) + xlsx.setRowHeight(1, 50.0); + + //Set the width of the third column to 40.0(chars) + xlsx.setColumnWidth(3, 3, 40.0); + + //Set style for the row 11th. + QXlsx::Format format1; + format1.setFontBold(true); + format1.setFontColor(QColor(Qt::blue)); + format1.setFontSize(20); + xlsx.write(11, 1, "Hello Row Style"); + xlsx.write(11, 6, "Blue Color"); + xlsx.setRowFormat(11, format1); + xlsx.setRowHeight(11, 41); + + //Set style for the col [9th, 16th) + QXlsx::Format format2; + format2.setFontBold(true); + format2.setFontColor(QColor(Qt::magenta)); + for (int row=12; row<=30; row++) + for (int col=9; col<=15; col++) + xlsx.write(row, col, row+col); + xlsx.setColumnWidth(9, 16, 5.0); + xlsx.setColumnFormat(9, 16, format2); + + xlsx.save(); + return 0; +} diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/rowcolumn/rowcolumn.pro b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/rowcolumn/rowcolumn.pro new file mode 100644 index 0000000..4b708c0 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/rowcolumn/rowcolumn.pro @@ -0,0 +1,9 @@ +TARGET = image + +#include(../../../src/xlsx/qtxlsx.pri) +QT += xlsx + +CONFIG += console +CONFIG -= app_bundle + +SOURCES += main.cpp diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/style/doc/src/style.qdoc b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/style/doc/src/style.qdoc new file mode 100644 index 0000000..c24bb7b --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/style/doc/src/style.qdoc @@ -0,0 +1,10 @@ +/*! + \title Qt Xlsx Examples - Style + \example style + \title Xlsx Style Example + \brief This is a simplest xlsx examples. + \ingroup qtxlsx-examples + + This example demonstrates how to generate a + .xlsx file with Qt Xlsx Library. +*/ diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/style/main.cpp b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/style/main.cpp new file mode 100644 index 0000000..ae99412 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/style/main.cpp @@ -0,0 +1,48 @@ +#include +#include "xlsxdocument.h" +#include "xlsxformat.h" + +int main() +{ + QXlsx::Document xlsx; + QXlsx::Format format1; + format1.setFontColor(QColor(Qt::red)); + format1.setFontSize(15); + format1.setHorizontalAlignment(QXlsx::Format::AlignHCenter); + format1.setBorderStyle(QXlsx::Format::BorderDashDotDot); + xlsx.write("A1", "Hello Qt!", format1); + xlsx.write("B3", 12345, format1); + + QXlsx::Format format2; + format2.setFontBold(true); + format2.setFontUnderline(QXlsx::Format::FontUnderlineDouble); + format2.setFillPattern(QXlsx::Format::PatternLightUp); + xlsx.write("C5", "=44+33", format2); + xlsx.write("D7", true, format2); + + QXlsx::Format format3; + format3.setFontBold(true); + format3.setFontColor(QColor(Qt::blue)); + format3.setFontSize(20); + xlsx.write(11, 1, "Hello Row Style"); + xlsx.write(11, 6, "Blue Color"); + xlsx.setRowFormat(11, 41, format3); + + QXlsx::Format format4; + format4.setFontBold(true); + format4.setFontColor(QColor(Qt::magenta)); + for (int row=21; row<=40; row++) + for (int col=9; col<16; col++) + xlsx.write(row, col, row+col); + xlsx.setColumnFormat(9, 16, format4); + + xlsx.write("A5", QDate(2013, 8, 29)); + + QXlsx::Format format6; + format6.setPatternBackgroundColor(QColor(Qt::green)); + xlsx.write("A6", "Background color: green", format6); + + xlsx.saveAs("book1.xlsx"); + + return 0; +} diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/style/style.pro b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/style/style.pro new file mode 100644 index 0000000..3fbdcd6 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/style/style.pro @@ -0,0 +1,9 @@ +TARGET = style + +#include(../../../src/xlsx/qtxlsx.pri) +QT += xlsx + +CONFIG += console +CONFIG -= app_bundle + +SOURCES += main.cpp diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/worksheetoperations/doc/src/worksheetoperations.qdoc b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/worksheetoperations/doc/src/worksheetoperations.qdoc new file mode 100644 index 0000000..87dab42 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/worksheetoperations/doc/src/worksheetoperations.qdoc @@ -0,0 +1,8 @@ +/*! + \example worksheetoperations + \title Worksheet Operations Example + \brief Copy, delete, move worksheet + \ingroup qtxlsx-examples + + This example demonstrates how to copy, delete, move worksheet. +*/ diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/worksheetoperations/main.cpp b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/worksheetoperations/main.cpp new file mode 100644 index 0000000..d0c23a2 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/worksheetoperations/main.cpp @@ -0,0 +1,53 @@ +#include +#include "xlsxdocument.h" +#include "xlsxabstractsheet.h" + +QTXLSX_USE_NAMESPACE + +int main() +{ + //![Create a xlsx file] + Document xlsx; + + for (int i=1; i<20; ++i) { + for (int j=1; j<15; ++j) + xlsx.write(i, j, QString("R %1 C %2").arg(i).arg(j)); + } + xlsx.addSheet(); + xlsx.write(2, 2, "Hello Qt Xlsx"); + xlsx.addSheet(); + xlsx.write(3, 3, "This will be deleted..."); + + xlsx.addSheet("HiddenSheet"); + xlsx.currentSheet()->setHidden(true); + xlsx.write("A1", "This sheet is hidden."); + + xlsx.addSheet("VeryHiddenSheet"); + xlsx.sheet("VeryHiddenSheet")->setSheetState(AbstractSheet::SS_VeryHidden); + xlsx.write("A1", "This sheet is very hidden."); + + xlsx.save();//Default name is "Book1.xlsx" + //![Create a xlsx file] + + Document xlsx2("Book1.xlsx"); + //![add_copy_move_delete] + xlsx2.renameSheet("Sheet1", "TheFirstSheet"); + + xlsx2.copySheet("TheFirstSheet", "CopyOfTheFirst"); + + xlsx2.selectSheet("CopyOfTheFirst"); + xlsx2.write(25, 2, "On the Copy Sheet"); + + xlsx2.deleteSheet("Sheet3"); + + xlsx2.moveSheet("Sheet2", 0); + //![add_copy_move_delete] + + //![show_hidden_sheets] + xlsx2.sheet("HiddenSheet")->setVisible(true); + xlsx2.sheet("VeryHiddenSheet")->setVisible(true); + //![show_hidden_sheets] + + xlsx2.saveAs("Book2.xlsx"); + return 0; +} diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/worksheetoperations/worksheetoperations.pro b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/worksheetoperations/worksheetoperations.pro new file mode 100644 index 0000000..ce90d1c --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/worksheetoperations/worksheetoperations.pro @@ -0,0 +1,9 @@ +TARGET = worksheetoperations + +#include(../../../src/xlsx/qtxlsx.pri) +QT+=xlsx + +CONFIG += console +CONFIG -= app_bundle + +SOURCES += main.cpp diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/xlsx.pro b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/xlsx.pro new file mode 100644 index 0000000..7af77f8 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/xlsx.pro @@ -0,0 +1,23 @@ +TEMPLATE = subdirs +SUBDIRS = hello \ + extractdata \ + style \ + documentproperty \ + image \ + mergecells \ + rowcolumn \ + numberformat \ + datavalidation \ + definename \ + formulas \ + richtext \ + conditionalformatting \ + worksheetoperations \ + hyperlinks \ + chart \ + chartsheet \ + calendar \ + demo + +qtHaveModule(widgets): SUBDIRS += xlsxwidget + diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/xlsxwidget/main.cpp b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/xlsxwidget/main.cpp new file mode 100644 index 0000000..845774a --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/xlsxwidget/main.cpp @@ -0,0 +1,41 @@ +#include +#include "xlsxdocument.h" +#include "xlsxworksheet.h" +#include "xlsxcellrange.h" +#include "xlsxsheetmodel.h" + +using namespace QXlsx; + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + //![0] + QString filePath = QFileDialog::getOpenFileName(0, "Open xlsx file", QString(), "*.xlsx"); + if (filePath.isEmpty()) + return -1; + //![0] + + //![1] + QTabWidget tabWidget; + tabWidget.setWindowTitle(filePath + " - Qt Xlsx Demo"); + tabWidget.setTabPosition(QTabWidget::South); + //![1] + + //![2] + Document xlsx(filePath); + foreach (QString sheetName, xlsx.sheetNames()) { + Worksheet *sheet = dynamic_cast(xlsx.sheet(sheetName)); + if (sheet) { + QTableView *view = new QTableView(&tabWidget); + view->setModel(new SheetModel(sheet, view)); + foreach (CellRange range, sheet->mergedCells()) + view->setSpan(range.firstRow()-1, range.firstColumn()-1, range.rowCount(), range.columnCount()); + tabWidget.addTab(view, sheetName); + } + } + //![2] + + tabWidget.show(); + return app.exec(); +} diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/xlsxwidget/xlsxsheetmodel.cpp b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/xlsxwidget/xlsxsheetmodel.cpp new file mode 100644 index 0000000..d2142c6 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/xlsxwidget/xlsxsheetmodel.cpp @@ -0,0 +1,205 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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 "xlsxsheetmodel.h" +#include "xlsxsheetmodel_p.h" +#include "xlsxworksheet.h" + +#include + +QT_BEGIN_NAMESPACE_XLSX + +SheetModelPrivate::SheetModelPrivate(SheetModel *p) + :q_ptr(p) +{ + +} + +/*! + * \class SheetModel + * + * Helper class for gui applicaiton user + * + * \note SheetModel indices start from 0, while Worksheet + * column/row indices start from 1. + */ + +/*! + * Creates a model object with the given \a sheet and \a parent. + */ +SheetModel::SheetModel(Worksheet *sheet, QObject *parent) + :QAbstractTableModel(parent), d_ptr(new SheetModelPrivate(this)) +{ + d_ptr->sheet = sheet; +} + +/*! + * Destroys the model. + */ +SheetModel::~SheetModel() +{ + delete d_ptr; +} + +int SheetModel::rowCount(const QModelIndex &/*parent*/) const +{ + Q_D(const SheetModel); + return d->sheet->dimension().lastRow(); +} + + +int SheetModel::columnCount(const QModelIndex &/*parent*/) const +{ + Q_D(const SheetModel); + return d->sheet->dimension().lastColumn(); +} + +Qt::ItemFlags SheetModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return Qt::NoItemFlags; + return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable; +} + +QVariant SheetModel::data(const QModelIndex &index, int role) const +{ + Q_D(const SheetModel); + + if (!index.isValid()) + return QVariant(); + + Cell *cell = d->sheet->cellAt(index.row()+1, index.column()+1); + if (!cell) + return QVariant(); + QVariant userFriendlyValue = d->sheet->read(index.row()+1, index.column()+1); + + if (role == Qt::DisplayRole) { + if (cell->isDateTime()) + return userFriendlyValue; + return cell->value(); + } else if (role == Qt::EditRole) { + return userFriendlyValue; + } else if (role == Qt::TextAlignmentRole) { + Qt::Alignment align; + switch (cell->format().horizontalAlignment()) { + case Format::AlignLeft: + align |= Qt::AlignLeft; + break; + case Format::AlignRight: + align |= Qt::AlignRight; + break; + case Format::AlignHCenter: + align |= Qt::AlignHCenter; + break; + case Format::AlignHJustify: + align |= Qt::AlignJustify; + break; + default: + break; + } + switch (cell->format().verticalAlignment()) { + case Format::AlignTop: + align |= Qt::AlignTop; + break; + case Format::AlignBottom: + align |= Qt::AlignBottom; + break; + case Format::AlignVCenter: + align |= Qt::AlignVCenter; + break; + default: + break; + } + return QVariant(align); + } else if (role == Qt::FontRole) { + if (cell->format().hasFontData()) + return cell->format().font(); + } else if (role == Qt::ForegroundRole) { + if (cell->format().fontColor().isValid()) + return QBrush(cell->format().fontColor()); + } else if (role == Qt::BackgroundRole) { + if (cell->format().patternBackgroundColor().isValid()) + return QBrush(cell->format().patternBackgroundColor()); + } + + return QVariant(); +} + +/* + * Copy from xlsxutility.cpp, so this example don't depend on the xlsx-private + * This function should be removed once this class moved to the xlsx library. + */ +static QString col_to_name(int col_num) +{ + QString col_str; + + int remainder; + while (col_num) { + remainder = col_num % 26; + if (remainder == 0) + remainder = 26; + col_str.prepend(QChar('A'+remainder-1)); + col_num = (col_num - 1) / 26; + } + + return col_str; +} + +QVariant SheetModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (role == Qt::DisplayRole) { + if (orientation == Qt::Horizontal) + return col_to_name(section + 1); + else + return QString::number(section + 1); + } + return QVariant(); +} + +bool SheetModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + Q_D(const SheetModel); + + if (!index.isValid()) + return false; + + if (role == Qt::EditRole) { + if (d->sheet->write(index.row()+1, index.column()+1, value) == 0) + return true; + } + + return false; +} + +/*! + * Returns the sheet object. + */ +Worksheet *SheetModel::sheet() const +{ + Q_D(const SheetModel); + return d->sheet; +} + +QT_END_NAMESPACE_XLSX diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/xlsxwidget/xlsxsheetmodel.h b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/xlsxwidget/xlsxsheetmodel.h new file mode 100644 index 0000000..b500ff3 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/xlsxwidget/xlsxsheetmodel.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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. +** +****************************************************************************/ + +#ifndef QXLSX_XLSXSHEETMODEL_H +#define QXLSX_XLSXSHEETMODEL_H + +#include "xlsxglobal.h" +#include + +QT_BEGIN_NAMESPACE_XLSX + +class Worksheet; +class SheetModelPrivate; + +class SheetModel : public QAbstractTableModel +{ + Q_OBJECT + Q_DECLARE_PRIVATE(SheetModel) +public: + explicit SheetModel(Worksheet *sheet, QObject *parent = 0); + ~SheetModel(); + + int rowCount(const QModelIndex &parent = QModelIndex()) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + Qt::ItemFlags flags(const QModelIndex & index) const; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); + + Worksheet *sheet() const; +signals: + +public slots: + +private: + SheetModelPrivate * const d_ptr; +}; + +QT_END_NAMESPACE_XLSX + +#endif // QXLSX_XLSXSHEETMODEL_H diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/xlsxwidget/xlsxsheetmodel_p.h b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/xlsxwidget/xlsxsheetmodel_p.h new file mode 100644 index 0000000..fe69674 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/xlsxwidget/xlsxsheetmodel_p.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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. +** +****************************************************************************/ + +#ifndef XLSXSHEETMODEL_P_H +#define XLSXSHEETMODEL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt Xlsx API. It exists for the convenience +// of the Qt Xlsx. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// + +#include "xlsxsheetmodel.h" + +QT_BEGIN_NAMESPACE_XLSX + +class SheetModelPrivate +{ + Q_DECLARE_PUBLIC(SheetModel) +public: + SheetModelPrivate(SheetModel *p); + + Worksheet *sheet; + SheetModel *q_ptr; +}; + +QT_END_NAMESPACE_XLSX + +#endif // XLSXSHEETMODEL_P_H diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/xlsxwidget/xlsxwidget.pro b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/xlsxwidget/xlsxwidget.pro new file mode 100644 index 0000000..f303abc --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/examples/xlsx/xlsxwidget/xlsxwidget.pro @@ -0,0 +1,12 @@ +TARGET = xlsxwidget +QT += widgets + +#include(../../../src/xlsx/qtxlsx.pri) +QT+= xlsx + +SOURCES += main.cpp \ + xlsxsheetmodel.cpp + +HEADERS += \ + xlsxsheetmodel.h \ + xlsxsheetmodel_p.h diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/qtxlsx.pro b/src/thirdparty/QtXlsxWriter-0.3.0/qtxlsx.pro new file mode 100644 index 0000000..58c33f2 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/qtxlsx.pro @@ -0,0 +1 @@ +load(qt_parts) diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/src.pro b/src/thirdparty/QtXlsxWriter-0.3.0/src/src.pro new file mode 100644 index 0000000..07d244c --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/src.pro @@ -0,0 +1,3 @@ +TEMPLATE = subdirs + +SUBDIRS = xlsx diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/doc/qtxlsx.qdocconf b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/doc/qtxlsx.qdocconf new file mode 100644 index 0000000..ef11181 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/doc/qtxlsx.qdocconf @@ -0,0 +1,75 @@ +include($QT_INSTALL_DOCS/global/qt-html-templates-offline.qdocconf) +include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf) + +project = QtXlsx +description = Qt Xlsx Reference Documentation +url = http://qtxlsx.debao.me +version = $QT_VERSION + +qhp.projects = QtXlsx + +qhp.QtXlsx.file = qtxlsx.qhp +qhp.QtXlsx.namespace = me.debao.qtxlsx.$QT_VERSION_TAG +qhp.QtXlsx.virtualFolder = qtxlsx +qhp.QtXlsx.indexTitle = Qt Xlsx +qhp.QtXlsx.indexRoot = + +qhp.QtXlsx.filterAttributes = qtxlsx $QT_VERSION qtrefdoc +qhp.QtXlsx.customFilters.Qt.name = QtXlsx $QT_VERSION +qhp.QtXlsx.customFilters.Qt.filterAttributes = qtxlsx $QT_VERSION +qhp.QtXlsx.subprojects = overviews classes qmltypes examples +qhp.QtXlsx.subprojects.overviews.title = Overview +qhp.QtXlsx.subprojects.overviews.indexTitle = Qt Xlsx +qhp.QtXlsx.subprojects.overviews.selectors = fake:page,group,module +qhp.QtXlsx.subprojects.classes.title = C++ Classes +qhp.QtXlsx.subprojects.classes.indexTitle = Qt Xlsx C++ Classes +qhp.QtXlsx.subprojects.classes.selectors = class fake:headerfile +qhp.QtXlsx.subprojects.classes.sortPages = true +qhp.QtXlsx.subprojects.examples.title = Examples +qhp.QtXlsx.subprojects.examples.indexTitle = Qt Xlsx Examples +qhp.QtXlsx.subprojects.examples.selectors = fake:example + +tagfile = ../../../doc/qtxlsx/qtxlsx.tags + +headerdirs += .. + +sourcedirs += .. + +exampledirs += ../../../examples/xlsx \ + snippets/ + +# Specify the install path under QT_INSTALL_EXAMPLES +examplesinstallpath = xlsx + +imagedirs += images + +depends += qtcore qtdoc qtgui + +HTML.footer = \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + "\n" \ + "

\n" \ diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/doc/snippets/doc_src_qtxlsx.cpp b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/doc/snippets/doc_src_qtxlsx.cpp new file mode 100644 index 0000000..eab3ac2 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/doc/snippets/doc_src_qtxlsx.cpp @@ -0,0 +1,8 @@ + +//! [0] +#include +//! [0] + +//! [1] +#include +//! [1] diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/doc/snippets/doc_src_qtxlsx.pro b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/doc/snippets/doc_src_qtxlsx.pro new file mode 100644 index 0000000..b2789f7 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/doc/snippets/doc_src_qtxlsx.pro @@ -0,0 +1,3 @@ +#! [1] +QT += xlsx +#! [1] diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/doc/src/examples.qdoc b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/doc/src/examples.qdoc new file mode 100644 index 0000000..6defee7 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/doc/src/examples.qdoc @@ -0,0 +1,8 @@ +/*! + \group qtxlsx-examples + \title Qt Xlsx Examples + \brief Examples for the Qt Xlsx module + \ingroup all-examples + + Qt Xlsx comes with the following examples: +*/ diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/doc/src/qtxlsx-index.qdoc b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/doc/src/qtxlsx-index.qdoc new file mode 100644 index 0000000..8ef7b48 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/doc/src/qtxlsx-index.qdoc @@ -0,0 +1,72 @@ +/**************************************************************************** +** Copyright (c) 2013 Debao Zhang +** 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. +** +****************************************************************************/ + +/*! + \title Qt Xlsx + \page index.html + \brief Qt Xlsx provides functionality for handling .xlsx files. + + The \l{Qt Xlsx C++ Classes}{Qt Xlsx Module} provides a set of classes to read and write Excel files. It doesn't require + Microsoft Excel and can be used in any platform that Qt5 supported. The library can be used to + + \list + \li \l{Hello QtXlsx Example}{Generate a new .xlsx file from scratch} + \li \l{Extract Data Example}{Extract data from an existing .xlsx file} + \li Edit an existing .xlsx file + \endlist + + \image xlsx_demo.gif + + \table + \row + \li Source code: \li \l{https://github.com/dbzhang800/QtXlsxWriter} + \row + \li Issures: \li \l{https://github.com/dbzhang800/QtXlsxWriter/issues} + \row + \li License: \li MIT + \endtable + + \section1 Getting Started + + To include the definitions of the module's classes, using the following directive: + + \code + #include + \endcode + + To link against the module, add this line to your qmake .pro file: + + \code + QT += xlsx + \endcode + + More information can be found in \l{Qt Xlsx Build} page. + + \section1 Related information + \list + \li \l{Qt Xlsx C++ Classes} + \li \l{Qt Xlsx Examples} + \endlist +*/ diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/doc/src/qtxlsx.qdoc b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/doc/src/qtxlsx.qdoc new file mode 100644 index 0000000..cdc70f1 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/doc/src/qtxlsx.qdoc @@ -0,0 +1,36 @@ +/**************************************************************************** +** Copyright (c) 2013 Debao Zhang +** 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. +** +****************************************************************************/ + +/*! + \module QtXlsx + \title Qt Xlsx C++ Classes + \ingroup modules + + \brief The Qt Xlsx module provides functionality for handling .xlsx files. + + .xlsx is a zipped, XML-based file format developed by Microsoft for + representing spreadsheets. +*/ + diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/doc/src/usage.qdoc b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/doc/src/usage.qdoc new file mode 100644 index 0000000..fabbe9b --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/doc/src/usage.qdoc @@ -0,0 +1,83 @@ +/*! + \page building + \title Qt Xlsx Build + + \note QZipWriter and QZipReader which live in gui-private is used in + this library. For linux user, if your Qt is installed through package + manager tools such "apt-get", make sure that you have installed the Qt5 + develop package *qtbase5-private-dev* ; + if you Qt is built from source by yourself, + or download from qt-project.org directly, nothing need to do. + + \section1 Usage(1): Use Xlsx as Qt5's addon module + + 1. Download the source code from \l {https://github.com/dbzhang800/QtXlsxWriter/archive/master.zip} {github.com}. + + 2. Put the source code in any directory you like. At the toplevel directory run + + \note Perl is needed in this step. + + \code + qmake + make + make install + \endcode + + The library, the header files, and others will be installed to your system. + + 3. Add following line to your qmake's project file: + + \code + QT += xlsx + \endcode + + 4. Then, using Qt Xlsx in your code + + \code + #include "xlsxdocument.h" + int main() + { + QXlsx::Document xlsx; + xlsx.write("A1", "Hello Qt!"); + xlsx.saveAs("Test.xlsx"); + return 0; + } + \endcode + + \section1 Usage(2): Use source code directly + + The package contains a qtxlsx.pri file that allows you to integrate + the component into applications that use qmake for the build step. + + 1. Download the source code from \l {https://github.com/dbzhang800/QtXlsxWriter/archive/master.zip} {github.com} + + 2. Put the source code in any directory you like. For example, 3rdparty: + + \code + |-- project.pro + |-- .... + |-- 3rdparty\ + | |-- qtxlsx\ + | | + \endcode + + 3. Add following line to your qmake project file: + + \code + include(3rdparty/qtxlsx/src/xlsx/qtxlsx.pri) + \endcode + + \note If you like, you can copy all files from *src/xlsx* to your application's source path. Then add following line to your project file: + + \code + include(qtxlsx.pri) + \endcode + + \note If you do not use qmake, you need to define the following macro manually + + \code + XLSX_NO_LIB + \endcode + + 4. Then, using Qt Xlsx in your code +*/ diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/qtxlsx.pri b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/qtxlsx.pri new file mode 100644 index 0000000..a781146 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/qtxlsx.pri @@ -0,0 +1,84 @@ +INCLUDEPATH += $$PWD +DEPENDPATH += $$PWD + +QT += core gui gui-private +!build_xlsx_lib:DEFINES += XLSX_NO_LIB + +HEADERS += $$PWD/xlsxdocpropscore_p.h \ + $$PWD/xlsxdocpropsapp_p.h \ + $$PWD/xlsxrelationships_p.h \ + $$PWD/xlsxutility_p.h \ + $$PWD/xlsxsharedstrings_p.h \ + $$PWD/xlsxcontenttypes_p.h \ + $$PWD/xlsxtheme_p.h \ + $$PWD/xlsxformat.h \ + $$PWD/xlsxworkbook.h \ + $$PWD/xlsxstyles_p.h \ + $$PWD/xlsxabstractsheet.h \ + $$PWD/xlsxabstractsheet_p.h \ + $$PWD/xlsxworksheet.h \ + $$PWD/xlsxworksheet_p.h \ + $$PWD/xlsxchartsheet.h \ + $$PWD/xlsxchartsheet_p.h \ + $$PWD/xlsxzipwriter_p.h \ + $$PWD/xlsxworkbook_p.h \ + $$PWD/xlsxformat_p.h \ + $$PWD/xlsxglobal.h \ + $$PWD/xlsxdrawing_p.h \ + $$PWD/xlsxzipreader_p.h \ + $$PWD/xlsxdocument.h \ + $$PWD/xlsxdocument_p.h \ + $$PWD/xlsxcell.h \ + $$PWD/xlsxcell_p.h \ + $$PWD/xlsxdatavalidation.h \ + $$PWD/xlsxdatavalidation_p.h \ + $$PWD/xlsxcellreference.h \ + $$PWD/xlsxcellrange.h \ + $$PWD/xlsxrichstring_p.h \ + $$PWD/xlsxrichstring.h \ + $$PWD/xlsxconditionalformatting.h \ + $$PWD/xlsxconditionalformatting_p.h \ + $$PWD/xlsxcolor_p.h \ + $$PWD/xlsxnumformatparser_p.h \ + $$PWD/xlsxdrawinganchor_p.h \ + $$PWD/xlsxmediafile_p.h \ + $$PWD/xlsxabstractooxmlfile.h \ + $$PWD/xlsxabstractooxmlfile_p.h \ + $$PWD/xlsxchart.h \ + $$PWD/xlsxchart_p.h \ + $$PWD/xlsxsimpleooxmlfile_p.h \ + $$PWD/xlsxcellformula.h \ + $$PWD/xlsxcellformula_p.h + +SOURCES += $$PWD/xlsxdocpropscore.cpp \ + $$PWD/xlsxdocpropsapp.cpp \ + $$PWD/xlsxrelationships.cpp \ + $$PWD/xlsxutility.cpp \ + $$PWD/xlsxsharedstrings.cpp \ + $$PWD/xlsxcontenttypes.cpp \ + $$PWD/xlsxtheme.cpp \ + $$PWD/xlsxformat.cpp \ + $$PWD/xlsxstyles.cpp \ + $$PWD/xlsxworkbook.cpp \ + $$PWD/xlsxabstractsheet.cpp \ + $$PWD/xlsxworksheet.cpp \ + $$PWD/xlsxchartsheet.cpp \ + $$PWD/xlsxzipwriter.cpp \ + $$PWD/xlsxdrawing.cpp \ + $$PWD/xlsxzipreader.cpp \ + $$PWD/xlsxdocument.cpp \ + $$PWD/xlsxcell.cpp \ + $$PWD/xlsxdatavalidation.cpp \ + $$PWD/xlsxcellreference.cpp \ + $$PWD/xlsxcellrange.cpp \ + $$PWD/xlsxrichstring.cpp \ + $$PWD/xlsxconditionalformatting.cpp \ + $$PWD/xlsxcolor.cpp \ + $$PWD/xlsxnumformatparser.cpp \ + $$PWD/xlsxdrawinganchor.cpp \ + $$PWD/xlsxmediafile.cpp \ + $$PWD/xlsxabstractooxmlfile.cpp \ + $$PWD/xlsxchart.cpp \ + $$PWD/xlsxsimpleooxmlfile.cpp \ + $$PWD/xlsxcellformula.cpp + diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsx.pro b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsx.pro new file mode 100644 index 0000000..1449014 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsx.pro @@ -0,0 +1,16 @@ +TARGET = QtXlsx + +QMAKE_DOCS = $$PWD/doc/qtxlsx.qdocconf + +load(qt_module) + +CONFIG += build_xlsx_lib +include(qtxlsx.pri) + +#Define this macro if you want to run tests, so more AIPs will get exported. +#DEFINES += XLSX_TEST + +QMAKE_TARGET_COMPANY = "Debao Zhang" +QMAKE_TARGET_COPYRIGHT = "Copyright (C) 2013-2014 Debao Zhang " +QMAKE_TARGET_DESCRIPTION = ".Xlsx file wirter for Qt5" + diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxabstractooxmlfile.cpp b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxabstractooxmlfile.cpp new file mode 100644 index 0000000..36d15a0 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxabstractooxmlfile.cpp @@ -0,0 +1,119 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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 "xlsxabstractooxmlfile.h" +#include "xlsxabstractooxmlfile_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE_XLSX + +AbstractOOXmlFilePrivate::AbstractOOXmlFilePrivate(AbstractOOXmlFile *q, AbstractOOXmlFile::CreateFlag flag=AbstractOOXmlFile::F_NewFromScratch) + :relationships(new Relationships), flag(flag), q_ptr(q) +{ + +} + +AbstractOOXmlFilePrivate::~AbstractOOXmlFilePrivate() +{ + +} + +/*! + * \internal + * + * \class AbstractOOXmlFile + * + * Base class of all the ooxml part file. + */ + +AbstractOOXmlFile::AbstractOOXmlFile(CreateFlag flag) + :d_ptr(new AbstractOOXmlFilePrivate(this, flag)) +{ +} + +AbstractOOXmlFile::AbstractOOXmlFile(AbstractOOXmlFilePrivate *d) + :d_ptr(d) +{ + +} + +AbstractOOXmlFile::~AbstractOOXmlFile() +{ + if (d_ptr->relationships) + delete d_ptr->relationships; + delete d_ptr; +} + +QByteArray AbstractOOXmlFile::saveToXmlData() const +{ + QByteArray data; + QBuffer buffer(&data); + buffer.open(QIODevice::WriteOnly); + saveToXmlFile(&buffer); + + return data; +} + +bool AbstractOOXmlFile::loadFromXmlData(const QByteArray &data) +{ + QBuffer buffer; + buffer.setData(data); + buffer.open(QIODevice::ReadOnly); + + return loadFromXmlFile(&buffer); +} + +/*! + * \internal + */ +void AbstractOOXmlFile::setFilePath(const QString path) +{ + Q_D(AbstractOOXmlFile); + d->filePathInPackage = path; +} + +/*! + * \internal + */ +QString AbstractOOXmlFile::filePath() const +{ + Q_D(const AbstractOOXmlFile); + return d->filePathInPackage; +} + + +/*! + * \internal + */ +Relationships *AbstractOOXmlFile::relationships() const +{ + Q_D(const AbstractOOXmlFile); + return d->relationships; +} + + +QT_END_NAMESPACE_XLSX diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxabstractooxmlfile.h b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxabstractooxmlfile.h new file mode 100644 index 0000000..a5a791c --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxabstractooxmlfile.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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. +** +****************************************************************************/ + +#ifndef QXLSX_XLSXABSTRACTOOXMLFILE_H +#define QXLSX_XLSXABSTRACTOOXMLFILE_H + +#include "xlsxglobal.h" + +class QIODevice; +class QByteArray; + +QT_BEGIN_NAMESPACE_XLSX +class Relationships; +class AbstractOOXmlFilePrivate; + +class Q_XLSX_EXPORT AbstractOOXmlFile +{ + Q_DECLARE_PRIVATE(AbstractOOXmlFile) +public: + enum CreateFlag + { + F_NewFromScratch, + F_LoadFromExists + }; + + virtual ~AbstractOOXmlFile(); + + virtual void saveToXmlFile(QIODevice *device) const = 0; + virtual bool loadFromXmlFile(QIODevice *device) = 0; + + virtual QByteArray saveToXmlData() const; + virtual bool loadFromXmlData(const QByteArray &data); + + Relationships *relationships() const; + + void setFilePath(const QString path); + QString filePath() const; + +protected: + AbstractOOXmlFile(CreateFlag flag); + AbstractOOXmlFile(AbstractOOXmlFilePrivate *d); + + AbstractOOXmlFilePrivate *d_ptr; +}; + +QT_END_NAMESPACE_XLSX + +#endif // QXLSX_XLSXABSTRACTOOXMLFILE_H diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxabstractooxmlfile_p.h b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxabstractooxmlfile_p.h new file mode 100644 index 0000000..a1a2e60 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxabstractooxmlfile_p.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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. +** +****************************************************************************/ + +#ifndef XLSXOOXMLFILE_P_H +#define XLSXOOXMLFILE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt Xlsx API. It exists for the convenience +// of the Qt Xlsx. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// + +#include "xlsxabstractooxmlfile.h" +#include "xlsxrelationships_p.h" + +#include + +QT_BEGIN_NAMESPACE_XLSX + +class XLSX_AUTOTEST_EXPORT AbstractOOXmlFilePrivate +{ + Q_DECLARE_PUBLIC(AbstractOOXmlFile) + +public: + AbstractOOXmlFilePrivate(AbstractOOXmlFile *q, AbstractOOXmlFile::CreateFlag flag); + virtual ~AbstractOOXmlFilePrivate(); + + QString filePathInPackage;//such as "xl/worksheets/sheet1.xml" + //used when load the .xlsx file + Relationships *relationships; + AbstractOOXmlFile::CreateFlag flag; + AbstractOOXmlFile *q_ptr; +}; + +QT_END_NAMESPACE_XLSX + +#endif // XLSXOOXMLFILE_P_H diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxabstractsheet.cpp b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxabstractsheet.cpp new file mode 100644 index 0000000..2cf6eee --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxabstractsheet.cpp @@ -0,0 +1,206 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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 "xlsxabstractsheet.h" +#include "xlsxabstractsheet_p.h" +#include "xlsxworkbook.h" + +QT_BEGIN_NAMESPACE_XLSX + +AbstractSheetPrivate::AbstractSheetPrivate(AbstractSheet *p, AbstractSheet::CreateFlag flag) + : AbstractOOXmlFilePrivate(p, flag) +{ + type = AbstractSheet::ST_WorkSheet; + sheetState = AbstractSheet::SS_Visible; +} + +AbstractSheetPrivate::~AbstractSheetPrivate() +{ +} + +/*! + \class AbstractSheet + \inmodule QtXlsx + \brief Base class for worksheet, chartsheet, etc. +*/ + +/*! + \enum AbstractSheet::SheetType + + \value ST_WorkSheet + \value ST_ChartSheet + \omitvalue ST_DialogSheet + \omitvalue ST_MacroSheet +*/ + +/*! + \enum AbstractSheet::SheetState + + \value SS_Visible + \value SS_Hidden + \value SS_VeryHidden User cann't make a veryHidden sheet visible in normal way. +*/ + +/*! + \fn AbstractSheet::copy(const QString &distName, int distId) const + + Copies the current sheet to a sheet called \a distName with \a distId. + Returns the new sheet. + */ + +/*! + * \internal + */ +AbstractSheet::AbstractSheet(const QString &name, int id, Workbook *workbook, AbstractSheetPrivate *d) : + AbstractOOXmlFile(d) +{ + d_func()->name = name; + d_func()->id = id; + d_func()->workbook = workbook; +} + + +/*! + * Returns the name of the sheet. + */ +QString AbstractSheet::sheetName() const +{ + Q_D(const AbstractSheet); + return d->name; +} + +/*! + * \internal + */ +void AbstractSheet::setSheetName(const QString &sheetName) +{ + Q_D(AbstractSheet); + d->name = sheetName; +} + +/*! + * Returns the type of the sheet. + */ +AbstractSheet::SheetType AbstractSheet::sheetType() const +{ + Q_D(const AbstractSheet); + return d->type; +} + +/*! + * \internal + */ +void AbstractSheet::setSheetType(SheetType type) +{ + Q_D(AbstractSheet); + d->type = type; +} + +/*! + * Returns the state of the sheet. + * + * \sa isHidden(), isVisible(), setSheetState() + */ +AbstractSheet::SheetState AbstractSheet::sheetState() const +{ + Q_D(const AbstractSheet); + return d->sheetState; +} + +/*! + * Set the state of the sheet to \a state. + */ +void AbstractSheet::setSheetState(SheetState state) +{ + Q_D(AbstractSheet); + d->sheetState = state; +} + +/*! + * Returns true if the sheet is not visible, otherwise false will be returned. + * + * \sa sheetState(), setHidden() + */ +bool AbstractSheet::isHidden() const +{ + Q_D(const AbstractSheet); + return d->sheetState != SS_Visible; +} + +/*! + * Returns true if the sheet is visible. + */ +bool AbstractSheet::isVisible() const +{ + return !isHidden(); +} + +/*! + * Make the sheet hiden or visible based on \a hidden. + */ +void AbstractSheet::setHidden(bool hidden) +{ + Q_D(AbstractSheet); + if (hidden == isHidden()) + return; + + d->sheetState = hidden ? SS_Hidden : SS_Visible; +} + +/*! + * Convenience function, equivalent to setHidden(! \a visible). + */ +void AbstractSheet::setVisible(bool visible) +{ + setHidden(!visible); +} + +/*! + * \internal + */ +int AbstractSheet::sheetId() const +{ + Q_D(const AbstractSheet); + return d->id; +} + +/*! + * \internal + */ +Drawing *AbstractSheet::drawing() const +{ + Q_D(const AbstractSheet); + return d->drawing.data(); +} + +/*! + * Return the workbook + */ +Workbook *AbstractSheet::workbook() const +{ + Q_D(const AbstractSheet); + return d->workbook; +} + +QT_END_NAMESPACE_XLSX diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxabstractsheet.h b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxabstractsheet.h new file mode 100644 index 0000000..7aa416d --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxabstractsheet.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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. +** +****************************************************************************/ +#ifndef XLSXABSTRACTSHEET_H +#define XLSXABSTRACTSHEET_H + +#include "xlsxabstractooxmlfile.h" +#include +#include + +QT_BEGIN_NAMESPACE_XLSX +class Workbook; +class Drawing; +class AbstractSheetPrivate; +class Q_XLSX_EXPORT AbstractSheet : public AbstractOOXmlFile +{ + Q_DECLARE_PRIVATE(AbstractSheet) +public: + enum SheetType { + ST_WorkSheet, + ST_ChartSheet, + ST_DialogSheet, + ST_MacroSheet + }; + + enum SheetState { + SS_Visible, + SS_Hidden, + SS_VeryHidden + }; + + QString sheetName() const; + SheetType sheetType() const; + SheetState sheetState() const; + void setSheetState(SheetState ss); + bool isHidden() const; + bool isVisible() const; + void setHidden(bool hidden); + void setVisible(bool visible); + + Workbook *workbook() const; + +protected: + friend class Workbook; + AbstractSheet(const QString &sheetName, int sheetId, Workbook *book, AbstractSheetPrivate *d); + virtual AbstractSheet *copy(const QString &distName, int distId) const = 0; + void setSheetName(const QString &sheetName); + void setSheetType(SheetType type); + int sheetId() const; + + Drawing *drawing() const; +}; + +QT_END_NAMESPACE_XLSX +#endif // XLSXABSTRACTSHEET_H diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxabstractsheet_p.h b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxabstractsheet_p.h new file mode 100644 index 0000000..7d0f344 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxabstractsheet_p.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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. +** +****************************************************************************/ +#ifndef XLSXABSTRACTSHEET_P_H +#define XLSXABSTRACTSHEET_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt Xlsx API. It exists for the convenience +// of the Qt Xlsx. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// + +#include "xlsxglobal.h" +#include "xlsxabstractsheet.h" +#include "xlsxabstractooxmlfile_p.h" + +#include + +namespace QXlsx { + +class XLSX_AUTOTEST_EXPORT AbstractSheetPrivate : public AbstractOOXmlFilePrivate +{ + Q_DECLARE_PUBLIC(AbstractSheet) +public: + AbstractSheetPrivate(AbstractSheet *p, AbstractSheet::CreateFlag flag); + ~AbstractSheetPrivate(); + + Workbook *workbook; + QSharedPointer drawing; + + QString name; + int id; + AbstractSheet::SheetState sheetState; + AbstractSheet::SheetType type; +}; + +} +#endif // XLSXABSTRACTSHEET_P_H diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcell.cpp b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcell.cpp new file mode 100644 index 0000000..fcaf7a6 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcell.cpp @@ -0,0 +1,178 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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 "xlsxcell.h" +#include "xlsxcell_p.h" +#include "xlsxformat.h" +#include "xlsxformat_p.h" +#include "xlsxutility_p.h" +#include "xlsxworksheet.h" +#include "xlsxworkbook.h" +#include + +QT_BEGIN_NAMESPACE_XLSX + +CellPrivate::CellPrivate(Cell *p) : + q_ptr(p) +{ + +} + +CellPrivate::CellPrivate(const CellPrivate * const cp) + : value(cp->value), formula(cp->formula), cellType(cp->cellType) + , format(cp->format), richString(cp->richString), parent(cp->parent) +{ + +} + +/*! + \class Cell + \inmodule QtXlsx + \brief The Cell class provides a API that is used to handle the worksheet cell. + +*/ + +/*! + \enum Cell::CellType + \value BooleanType Boolean type + \value NumberType Number type, can be blank or used with forumula + \value ErrorType Error type + \value SharedStringType Shared string type + \value StringType String type, can be used with forumula + \value InlineStringType Inline string type + */ + +/*! + * \internal + * Created by Worksheet only. + */ +Cell::Cell(const QVariant &data, CellType type, const Format &format, Worksheet *parent) : + d_ptr(new CellPrivate(this)) +{ + d_ptr->value = data; + d_ptr->cellType = type; + d_ptr->format = format; + d_ptr->parent = parent; +} + +/*! + * \internal + */ +Cell::Cell(const Cell * const cell): + d_ptr(new CellPrivate(cell->d_ptr)) +{ + d_ptr->q_ptr = this; +} + +/*! + * Destroys the Cell and cleans up. + */ +Cell::~Cell() +{ + delete d_ptr; +} + +/*! + * Return the dataType of this Cell + */ +Cell::CellType Cell::cellType() const +{ + Q_D(const Cell); + return d->cellType; +} + +/*! + * Return the data content of this Cell + */ +QVariant Cell::value() const +{ + Q_D(const Cell); + return d->value; +} + +/*! + * Return the style used by this Cell. If no style used, 0 will be returned. + */ +Format Cell::format() const +{ + Q_D(const Cell); + return d->format; +} + +/*! + * Returns true if the cell has one formula. + */ +bool Cell::hasFormula() const +{ + Q_D(const Cell); + return d->formula.isValid(); +} + +/*! + * Return the formula contents if the dataType is Formula + */ +CellFormula Cell::formula() const +{ + Q_D(const Cell); + return d->formula; +} + +/*! + * Returns whether the value is probably a dateTime or not + */ +bool Cell::isDateTime() const +{ + Q_D(const Cell); + if (d->cellType == NumberType && d->value.toDouble() >=0 + && d->format.isValid() && d->format.isDateTimeFormat()) { + return true; + } + return false; +} + +/*! + * Return the data time value. + */ +QDateTime Cell::dateTime() const +{ + Q_D(const Cell); + if (!isDateTime()) + return QDateTime(); + return datetimeFromNumber(d->value.toDouble(), d->parent->workbook()->isDate1904()); +} + +/*! + * Returns whether the cell is probably a rich string or not + */ +bool Cell::isRichString() const +{ + Q_D(const Cell); + if (d->cellType != SharedStringType && d->cellType != InlineStringType + && d->cellType != StringType) + return false; + + return d->richString.isRichString(); +} + +QT_END_NAMESPACE_XLSX diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcell.h b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcell.h new file mode 100644 index 0000000..7aec8ce --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcell.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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. +** +****************************************************************************/ +#ifndef QXLSX_XLSXCELL_H +#define QXLSX_XLSXCELL_H + +#include "xlsxglobal.h" +#include "xlsxformat.h" +#include + +QT_BEGIN_NAMESPACE_XLSX + +class Worksheet; +class Format; +class CellFormula; +class CellPrivate; +class WorksheetPrivate; + +class Q_XLSX_EXPORT Cell +{ + Q_DECLARE_PRIVATE(Cell) +public: + enum CellType { + BooleanType, //t="b" + NumberType, //t="n" (default) + ErrorType, //t="e" + SharedStringType, //t="s" + StringType, //t="str" + InlineStringType //t="inlineStr" + }; + + CellType cellType() const; + QVariant value() const; + Format format() const; + + bool hasFormula() const; + CellFormula formula() const; + + bool isDateTime() const; + QDateTime dateTime() const; + + bool isRichString() const; + + ~Cell(); +private: + friend class Worksheet; + friend class WorksheetPrivate; + + Cell(const QVariant &data=QVariant(), CellType type=NumberType, const Format &format=Format(), Worksheet *parent=0); + Cell(const Cell * const cell); + CellPrivate * const d_ptr; +}; + +QT_END_NAMESPACE_XLSX + +#endif // QXLSX_XLSXCELL_H diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcell_p.h b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcell_p.h new file mode 100644 index 0000000..b537ff2 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcell_p.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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. +** +****************************************************************************/ +#ifndef XLSXCELL_P_H +#define XLSXCELL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt Xlsx API. It exists for the convenience +// of the Qt Xlsx. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// + +#include "xlsxglobal.h" +#include "xlsxcell.h" +#include "xlsxcellrange.h" +#include "xlsxrichstring.h" +#include "xlsxcellformula.h" +#include +#include + +QT_BEGIN_NAMESPACE_XLSX + +class CellPrivate +{ + Q_DECLARE_PUBLIC(Cell) +public: + CellPrivate(Cell *p); + CellPrivate(const CellPrivate * const cp); + + QVariant value; + CellFormula formula; + Cell::CellType cellType; + Format format; + + RichString richString; + + Worksheet *parent; + Cell *q_ptr; +}; + +QT_END_NAMESPACE_XLSX + +#endif // XLSXCELL_P_H diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcellformula.cpp b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcellformula.cpp new file mode 100644 index 0000000..858d347 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcellformula.cpp @@ -0,0 +1,259 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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 "xlsxcellformula.h" +#include "xlsxcellformula_p.h" +#include "xlsxutility_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE_XLSX + +CellFormulaPrivate::CellFormulaPrivate(const QString &formula_, const CellRange &ref_, CellFormula::FormulaType type_) + :formula(formula_), type(type_), reference(ref_), ca(false), si(0) +{ + //Remove the formula '=' sign if exists + if (formula.startsWith(QLatin1String("="))) + formula.remove(0,1); + else if (formula.startsWith(QLatin1String("{=")) && formula.endsWith(QLatin1String("}"))) + formula = formula.mid(2, formula.length()-3); +} + +CellFormulaPrivate::CellFormulaPrivate(const CellFormulaPrivate &other) + : QSharedData(other) + , formula(other.formula), type(other.type), reference(other.reference) + , ca(other.ca), si(other.si) +{ + +} + +CellFormulaPrivate::~CellFormulaPrivate() +{ + +} + +/*! + \class CellFormula + \inmodule QtXlsx + \brief The CellFormula class provides a API that is used to handle the cell formula. + +*/ + +/*! + \enum CellFormula::FormulaType + \value NormalType + \value ArrayType + \value DataTableType + \value SharedType +*/ + +/*! + * Creates a new formula. + */ +CellFormula::CellFormula() +{ + //The d pointer is initialized with a null pointer +} + +/*! + * Creates a new formula with the given \a formula and \a type. + */ +CellFormula::CellFormula(const char *formula, FormulaType type) + :d(new CellFormulaPrivate(QString::fromLatin1(formula), CellRange(), type)) +{ + +} + +/*! + * Creates a new formula with the given \a formula and \a type. + */ +CellFormula::CellFormula(const QString &formula, FormulaType type) + :d(new CellFormulaPrivate(formula, CellRange(), type)) +{ + +} + +/*! + * Creates a new formula with the given \a formula, \a ref and \a type. + */ +CellFormula::CellFormula(const QString &formula, const CellRange &ref, FormulaType type) + :d(new CellFormulaPrivate(formula, ref, type)) +{ + +} + +/*! + Creates a new formula with the same attributes as the \a other formula. + */ +CellFormula::CellFormula(const CellFormula &other) + :d(other.d) +{ +} + +/*! + Assigns the \a other formula to this formula, and returns a + reference to this formula. + */ +CellFormula &CellFormula::operator =(const CellFormula &other) +{ + d = other.d; + return *this; +} + +/*! + * Destroys this formula. + */ +CellFormula::~CellFormula() +{ + +} + +/*! + * Returns the type of the formula. + */ +CellFormula::FormulaType CellFormula::formulaType() const +{ + return d ? d->type : NormalType; +} + +/*! + * Returns the contents of the formula. + */ +QString CellFormula::formulaText() const +{ + return d ? d->formula : QString(); +} + +/*! + * Returns the reference cells of the formula. For normal formula, + * this will return an invalid CellRange object. + */ +CellRange CellFormula::reference() const +{ + return d ? d->reference : CellRange(); +} + +/*! + * Returns whether the formula is valid. + */ +bool CellFormula::isValid() const +{ + return d; +} + +/*! + * Returns the shared index for shared formula. + */ +int CellFormula::sharedIndex() const +{ + return d && d->type == SharedType ? d->si : -1; +} + +/*! + * \internal + */ +bool CellFormula::saveToXml(QXmlStreamWriter &writer) const +{ + writer.writeStartElement(QStringLiteral("f")); + QString t; + switch (d->type) { + case CellFormula::ArrayType: + t = QStringLiteral("array"); + break; + case CellFormula::SharedType: + t = QStringLiteral("shared"); + break; + default: + break; + } + if (!t.isEmpty()) + writer.writeAttribute(QStringLiteral("t"), t); + if (d->reference.isValid()) + writer.writeAttribute(QStringLiteral("ref"), d->reference.toString()); + if (d->ca) + writer.writeAttribute(QStringLiteral("ca"), QStringLiteral("1")); + if (d->type == CellFormula::SharedType) + writer.writeAttribute(QStringLiteral("si"), QString::number(d->si)); + + if (!d->formula.isEmpty()) + writer.writeCharacters(d->formula); + + writer.writeEndElement(); //f + + return true; +} + +/*! + * \internal + */ +bool CellFormula::loadFromXml(QXmlStreamReader &reader) +{ + Q_ASSERT(reader.name() == QLatin1String("f")); + if (!d) + d = new CellFormulaPrivate(QString(), CellRange(), NormalType); + + QXmlStreamAttributes attributes = reader.attributes(); + QString typeString = attributes.value(QLatin1String("t")).toString(); + if (typeString == QLatin1String("array")) + d->type = ArrayType; + else if (typeString == QLatin1String("shared")) + d->type = SharedType; + else + d->type = NormalType; + + if (attributes.hasAttribute(QLatin1String("ref"))) { + QString refString = attributes.value(QLatin1String("ref")).toString(); + d->reference = CellRange(refString); + } + + QString ca = attributes.value(QLatin1String("si")).toString(); + d->ca = parseXsdBoolean(ca, false); + + if (attributes.hasAttribute(QLatin1String("si"))) + d->si = attributes.value(QLatin1String("si")).toString().toInt(); + + d->formula = reader.readElementText(); + return true; +} + +/*! + * \internal + */ +bool CellFormula::operator ==(const CellFormula &formula) const +{ + return d->formula == formula.d->formula && d->type == formula.d->type + && d->si ==formula.d->si; +} + +/*! + * \internal + */ +bool CellFormula::operator !=(const CellFormula &formula) const +{ + return d->formula != formula.d->formula || d->type != formula.d->type + || d->si !=formula.d->si; +} + +QT_END_NAMESPACE_XLSX diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcellformula.h b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcellformula.h new file mode 100644 index 0000000..0d4679b --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcellformula.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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. +** +****************************************************************************/ +#ifndef QXLSX_XLSXCELLFORMULA_H +#define QXLSX_XLSXCELLFORMULA_H + +#include "xlsxglobal.h" +#include + +class QXmlStreamWriter; +class QXmlStreamReader; + +QT_BEGIN_NAMESPACE_XLSX + +class CellFormulaPrivate; +class CellRange; +class Worksheet; +class WorksheetPrivate; + +class Q_XLSX_EXPORT CellFormula +{ +public: + enum FormulaType { + NormalType, + ArrayType, + DataTableType, + SharedType + }; + + CellFormula(); + CellFormula(const char *formula, FormulaType type=NormalType); + CellFormula(const QString &formula, FormulaType type=NormalType); + CellFormula(const QString &formula, const CellRange &ref, FormulaType type); + CellFormula(const CellFormula &other); + ~CellFormula(); + CellFormula &operator =(const CellFormula &other); + bool isValid() const; + + FormulaType formulaType() const; + QString formulaText() const; + CellRange reference() const; + int sharedIndex() const; + + bool operator == (const CellFormula &formula) const; + bool operator != (const CellFormula &formula) const; + + bool saveToXml(QXmlStreamWriter &writer) const; + bool loadFromXml(QXmlStreamReader &reader); +private: + friend class Worksheet; + friend class WorksheetPrivate; + QExplicitlySharedDataPointer d; +}; + +QT_END_NAMESPACE_XLSX + +#endif // QXLSX_XLSXCELLFORMULA_H diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcellformula_p.h b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcellformula_p.h new file mode 100644 index 0000000..6aeddc9 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcellformula_p.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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. +** +****************************************************************************/ +#ifndef XLSXCELLFORMULA_P_H +#define XLSXCELLFORMULA_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt Xlsx API. It exists for the convenience +// of the Qt Xlsx. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// + +#include "xlsxglobal.h" +#include "xlsxcellformula.h" +#include "xlsxcellrange.h" + +#include +#include + +QT_BEGIN_NAMESPACE_XLSX + +class CellFormulaPrivate : public QSharedData +{ +public: + CellFormulaPrivate(const QString &formula, const CellRange &reference, CellFormula::FormulaType type); + CellFormulaPrivate(const CellFormulaPrivate &other); + ~CellFormulaPrivate(); + + QString formula; //formula contents + CellFormula::FormulaType type; + CellRange reference; + bool ca; //Calculate Cell + int si; //Shared group index +}; + +QT_END_NAMESPACE_XLSX + +#endif // XLSXCELLFORMULA_P_H diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcellrange.cpp b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcellrange.cpp new file mode 100644 index 0000000..6251ab7 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcellrange.cpp @@ -0,0 +1,147 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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 "xlsxcellrange.h" +#include "xlsxcellreference.h" +#include +#include +#include + +QT_BEGIN_NAMESPACE_XLSX + +/*! + \class CellRange + \brief For a range "A1:B2" or single cell "A1" + \inmodule QtXlsx + + The CellRange class stores the top left and bottom + right rows and columns of a range in a worksheet. +*/ + +/*! + Constructs an range, i.e. a range + whose rowCount() and columnCount() are 0. +*/ +CellRange::CellRange() + : top(-1), left(-1), bottom(-2), right(-2) +{ +} + +/*! + Constructs the range from the given \a top, \a + left, \a bottom and \a right rows and columns. + + \sa topRow(), leftColumn(), bottomRow(), rightColumn() +*/ +CellRange::CellRange(int top, int left, int bottom, int right) + : top(top), left(left), bottom(bottom), right(right) +{ +} + +CellRange::CellRange(const CellReference &topLeft, const CellReference &bottomRight) + : top(topLeft.row()), left(topLeft.column()) + , bottom(bottomRight.row()), right(bottomRight.column()) +{ +} + +/*! + \overload + Constructs the range form the given \a range string. +*/ +CellRange::CellRange(const QString &range) +{ + init(range); +} + +/*! + \overload + Constructs the range form the given \a range string. +*/ +CellRange::CellRange(const char *range) +{ + init(QString::fromLatin1(range)); +} + +void CellRange::init(const QString &range) +{ + QStringList rs = range.split(QLatin1Char(':')); + if (rs.size() == 2) { + CellReference start(rs[0]); + CellReference end(rs[1]); + top = start.row(); + left = start.column(); + bottom = end.row(); + right = end.column(); + } else { + CellReference p(rs[0]); + top = p.row(); + left = p.column(); + bottom = p.row(); + right = p.column(); + } +} + +/*! + Constructs a the range by copying the given \a + other range. +*/ +CellRange::CellRange(const CellRange &other) + : top(other.top), left(other.left), bottom(other.bottom), right(other.right) +{ +} + +/*! + Destroys the range. +*/ +CellRange::~CellRange() +{ +} + +/*! + Convert the range to string notation, such as "A1:B5". +*/ +QString CellRange::toString(bool row_abs, bool col_abs) const +{ + if (!isValid()) + return QString(); + + if (left == right && top == bottom) { + //Single cell + return CellReference(top, left).toString(row_abs, col_abs); + } + + QString cell_1 = CellReference(top, left).toString(row_abs, col_abs); + QString cell_2 = CellReference(bottom, right).toString(row_abs, col_abs); + return cell_1 + QLatin1String(":") + cell_2; +} + +/*! + * Returns true if the Range is valid. + */ +bool CellRange::isValid() const +{ + return left <= right && top <= bottom; +} + +QT_END_NAMESPACE_XLSX diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcellrange.h b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcellrange.h new file mode 100644 index 0000000..5a510b0 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcellrange.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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. +** +****************************************************************************/ +#ifndef QXLSX_XLSXCELLRANGE_H +#define QXLSX_XLSXCELLRANGE_H +#include "xlsxglobal.h" +#include "xlsxcellreference.h" + +QT_BEGIN_NAMESPACE_XLSX + +class Q_XLSX_EXPORT CellRange +{ +public: + CellRange(); + CellRange(int firstRow, int firstColumn, int lastRow, int lastColumn); + CellRange(const CellReference &topLeft, const CellReference &bottomRight); + CellRange(const QString &range); + CellRange(const char *range); + CellRange(const CellRange &other); + ~CellRange(); + + QString toString(bool row_abs=false, bool col_abs=false) const; + bool isValid() const; + inline void setFirstRow(int row) { top = row; } + inline void setLastRow(int row) { bottom = row; } + inline void setFirstColumn(int col) { left = col; } + inline void setLastColumn(int col) { right = col; } + inline int firstRow() const { return top; } + inline int lastRow() const { return bottom; } + inline int firstColumn() const { return left; } + inline int lastColumn() const { return right; } + inline int rowCount() const { return bottom - top + 1; } + inline int columnCount() const { return right - left + 1; } + inline CellReference topLeft() const { return CellReference(top, left); } + inline CellReference topRight() const { return CellReference(top, right); } + inline CellReference bottomLeft() const { return CellReference(bottom, left); } + inline CellReference bottomRight() const { return CellReference(bottom, right); } + + inline bool operator ==(const CellRange &other) const + { + return top==other.top && bottom==other.bottom + && left == other.left && right == other.right; + } + inline bool operator !=(const CellRange &other) const + { + return top!=other.top || bottom!=other.bottom + || left != other.left || right != other.right; + } +private: + void init(const QString &range); + int top, left, bottom, right; +}; + +QT_END_NAMESPACE_XLSX + +Q_DECLARE_TYPEINFO(QXlsx::CellRange, Q_MOVABLE_TYPE); + +#endif // QXLSX_XLSXCELLRANGE_H diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcellreference.cpp b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcellreference.cpp new file mode 100644 index 0000000..e7cf5da --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcellreference.cpp @@ -0,0 +1,174 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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 "xlsxcellreference.h" +#include +#include +#include + +QT_BEGIN_NAMESPACE_XLSX + +namespace { + +int intPow(int x, int p) +{ + if (p == 0) return 1; + if (p == 1) return x; + + int tmp = intPow(x, p/2); + if (p%2 == 0) return tmp * tmp; + else return x * tmp * tmp; +} + +QString col_to_name(int col_num) +{ + static QMap col_cache; + + if (!col_cache.contains(col_num)) { + QString col_str; + int remainder; + while (col_num) { + remainder = col_num % 26; + if (remainder == 0) + remainder = 26; + col_str.prepend(QChar('A'+remainder-1)); + col_num = (col_num - 1) / 26; + } + col_cache.insert(col_num, col_str); + } + + return col_cache[col_num]; +} + +int col_from_name(const QString &col_str) +{ + int col = 0; + int expn = 0; + for (int i=col_str.size()-1; i>-1; --i) { + col += (col_str[i].unicode() - 'A' + 1) * intPow(26, expn); + expn++; + } + + return col; +} +} //namespace + +/*! + \class CellReference + \brief For one single cell such as "A1" + \inmodule QtXlsx + + The CellReference class stores the cell location in a worksheet. +*/ + +/*! + Constructs an invalid Cell Reference +*/ +CellReference::CellReference() + : _row(-1), _column(-1) +{ +} + +/*! + Constructs the Reference from the given \a row, and \a column. +*/ +CellReference::CellReference(int row, int column) + : _row(row), _column(column) +{ +} + +/*! + \overload + Constructs the Reference form the given \a cell string. +*/ +CellReference::CellReference(const QString &cell) +{ + init(cell); +} + +/*! + \overload + Constructs the Reference form the given \a cell string. +*/ +CellReference::CellReference(const char *cell) +{ + init(QString::fromLatin1(cell)); +} + +void CellReference::init(const QString &cell_str) +{ + static QRegularExpression re(QStringLiteral("^\\$?([A-Z]{1,3})\\$?(\\d+)$")); + QRegularExpressionMatch match = re.match(cell_str); + if (match.hasMatch()) { + const QString col_str = match.captured(1); + const QString row_str = match.captured(2); + _row = row_str.toInt(); + _column = col_from_name(col_str); + } +} + +/*! + Constructs a Reference by copying the given \a + other Reference. +*/ +CellReference::CellReference(const CellReference &other) + : _row(other._row), _column(other._column) +{ +} + +/*! + Destroys the Reference. +*/ +CellReference::~CellReference() +{ +} + +/*! + Convert the Reference to string notation, such as "A1" or "$A$1". + If current object is invalid, an empty string will be returned. +*/ +QString CellReference::toString(bool row_abs, bool col_abs) const +{ + if (!isValid()) + return QString(); + + QString cell_str; + if (col_abs) + cell_str.append(QLatin1Char('$')); + cell_str.append(col_to_name(_column)); + if (row_abs) + cell_str.append(QLatin1Char('$')); + cell_str.append(QString::number(_row)); + return cell_str; +} + +/*! + * Returns true if the Reference is valid. + */ +bool CellReference::isValid() const +{ + return _row > 0 && _column > 0; +} + +QT_END_NAMESPACE_XLSX diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcellreference.h b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcellreference.h new file mode 100644 index 0000000..6a917c2 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcellreference.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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. +** +****************************************************************************/ +#ifndef QXLSX_XLSXCELLREFERENCE_H +#define QXLSX_XLSXCELLREFERENCE_H +#include "xlsxglobal.h" + +QT_BEGIN_NAMESPACE_XLSX + +class Q_XLSX_EXPORT CellReference +{ +public: + CellReference(); + CellReference(int row, int column); + CellReference(const QString &cell); + CellReference(const char *cell); + CellReference(const CellReference &other); + ~CellReference(); + + QString toString(bool row_abs=false, bool col_abs=false) const; + static CellReference fromString(const QString &cell); + bool isValid() const; + inline void setRow(int row) { _row = row; } + inline void setColumn(int col) { _column = col; } + inline int row() const { return _row; } + inline int column() const { return _column; } + + inline bool operator ==(const CellReference &other) const + { + return _row==other._row && _column==other._column; + } + inline bool operator !=(const CellReference &other) const + { + return _row!=other._row || _column!=other._column; + } +private: + void init(const QString &cell); + int _row, _column; +}; + +QT_END_NAMESPACE_XLSX + +Q_DECLARE_TYPEINFO(QXlsx::CellReference, Q_MOVABLE_TYPE); + +#endif // QXLSX_XLSXCELLREFERENCE_H diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxchart.cpp b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxchart.cpp new file mode 100644 index 0000000..a69f5c2 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxchart.cpp @@ -0,0 +1,645 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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 +#include +#include +#include + +QT_BEGIN_NAMESPACE_XLSX + +ChartPrivate::ChartPrivate(Chart *q, Chart::CreateFlag flag) + :AbstractOOXmlFilePrivate(q, flag), chartType(static_cast(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 series = QSharedPointer(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 series = QSharedPointer(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 series = QSharedPointer(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: "< series = QSharedPointer(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(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))); + } + + //Note: Bar3D have 2~3 axes + Q_ASSERT(axisList.size()==2 || (axisList.size()==3 && chartType==Chart::CT_Bar3D)); + + 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))); + } + + 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_Val, XlsxAxis::Bottom, 0, 1))); + const_cast(this)->axisList.append(QSharedPointer(new XlsxAxis(XlsxAxis::T_Val, XlsxAxis::Left, 1, 0))); + } + + 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))); + } + + //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; iaxDataSource_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(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; itype) { + 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 diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxchart.h b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxchart.h new file mode 100644 index 0000000..fcd8e2d --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxchart.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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. +** +****************************************************************************/ + +#ifndef QXLSX_CHART_H +#define QXLSX_CHART_H + +#include "xlsxabstractooxmlfile.h" + +#include + +class QXmlStreamReader; +class QXmlStreamWriter; + +QT_BEGIN_NAMESPACE_XLSX + +class AbstractSheet; +class Worksheet; +class ChartPrivate; +class CellRange; +class DrawingAnchor; + +class Q_XLSX_EXPORT Chart : public AbstractOOXmlFile +{ + Q_DECLARE_PRIVATE(Chart) + +public: + enum ChartType { + CT_Area = 1, //Zero is internally used for unknown types + CT_Area3D, + CT_Line, + CT_Line3D, + CT_Stock, + CT_Radar, + CT_Scatter, + CT_Pie, + CT_Pie3D, + CT_Doughnut, + CT_Bar, + CT_Bar3D, + CT_OfPie, + CT_Surface, + CT_Surface3D, + CT_Bubble + }; + + ~Chart(); + + void addSeries(const CellRange &range, AbstractSheet *sheet=0); + void setChartType(ChartType type); + void setChartStyle(int id); + + void saveToXmlFile(QIODevice *device) const; + bool loadFromXmlFile(QIODevice *device); + +private: + friend class AbstractSheet; + friend class Worksheet; + friend class Chartsheet; + friend class DrawingAnchor; + + Chart(AbstractSheet *parent, CreateFlag flag); +}; + +QT_END_NAMESPACE_XLSX + +#endif // QXLSX_CHART_H + diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxchart_p.h b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxchart_p.h new file mode 100644 index 0000000..4fcd0fb --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxchart_p.h @@ -0,0 +1,125 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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. +** +****************************************************************************/ + +#ifndef QXLSX_CHART_P_H +#define QXLSX_CHART_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt Xlsx API. It exists for the convenience +// of the Qt Xlsx. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// + +#include "xlsxabstractooxmlfile_p.h" +#include "xlsxchart.h" + +#include + +class QXmlStreamReader; +class QXmlStreamWriter; + +namespace QXlsx { + +class XlsxSeries +{ +public: + //At present, we care about number cell ranges only! + QString numberDataSource_numRef; //yval, val + QString axDataSource_numRef; //xval, cat +}; + +class XlsxAxis +{ +public: + enum Type + { + T_Cat, + T_Val, + T_Date, + T_Ser + }; + + enum Pos + { + Left, + Right, + Top, + Bottom + }; + + XlsxAxis(){} + + XlsxAxis(Type t, Pos p, int id, int crossId) + :type(t), axisPos(p), axisId(id), crossAx(crossId) + { + } + + Type type; + Pos axisPos; //l,r,b,t + int axisId; + int crossAx; +}; + +class ChartPrivate : public AbstractOOXmlFilePrivate +{ + Q_DECLARE_PUBLIC(Chart) + +public: + ChartPrivate(Chart *q, Chart::CreateFlag flag); + ~ChartPrivate(); + + bool loadXmlChart(QXmlStreamReader &reader); + bool loadXmlPlotArea(QXmlStreamReader &reader); + bool loadXmlXxxChart(QXmlStreamReader &reader); + bool loadXmlSer(QXmlStreamReader &reader); + QString loadXmlNumRef(QXmlStreamReader &reader); + bool loadXmlAxis(QXmlStreamReader &reader); + + void saveXmlChart(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; + + Chart::ChartType chartType; + + QList > seriesList; + QList > axisList; + + AbstractSheet *sheet; +}; + +} // namespace QXlsx + +#endif // QXLSX_CHART_P_H diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxchartsheet.cpp b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxchartsheet.cpp new file mode 100644 index 0000000..5cf477c --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxchartsheet.cpp @@ -0,0 +1,159 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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 "xlsxchartsheet.h" +#include "xlsxchartsheet_p.h" +#include "xlsxworkbook.h" +#include "xlsxutility_p.h" +#include "xlsxdrawing_p.h" +#include "xlsxdrawinganchor_p.h" +#include "xlsxchart.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE_XLSX + +ChartsheetPrivate::ChartsheetPrivate(Chartsheet *p, Chartsheet::CreateFlag flag) + : AbstractSheetPrivate(p, flag), chart(0) +{ + +} + +ChartsheetPrivate::~ChartsheetPrivate() +{ +} + +/*! + \class Chartsheet + \inmodule QtXlsx + \brief Represent one chartsheet in the workbook. +*/ + +/*! + * \internal + */ +Chartsheet::Chartsheet(const QString &name, int id, Workbook *workbook, CreateFlag flag) + :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(); + } +} + +/*! + * \internal + * + * Make a copy of this sheet. + */ + +Chartsheet *Chartsheet::copy(const QString &distName, int distId) const +{ + //:Todo + Q_UNUSED(distName) + Q_UNUSED(distId) + return 0; +} + +/*! + * Destroys this workssheet. + */ +Chartsheet::~Chartsheet() +{ +} + +/*! + * Returns the chart object of the sheet. + */ +Chart *Chartsheet::chart() +{ + Q_D(Chartsheet); + + return d->chart; +} + +void Chartsheet::saveToXmlFile(QIODevice *device) const +{ + Q_D(const Chartsheet); + d->relationships->clear(); + + QXmlStreamWriter writer(device); + + writer.writeStartDocument(QStringLiteral("1.0"), true); + writer.writeDefaultNamespace(QStringLiteral("http://schemas.openxmlformats.org/spreadsheetml/2006/main")); + writer.writeNamespace(QStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), QStringLiteral("r")); + writer.writeStartElement(QStringLiteral("chartsheet")); + + writer.writeStartElement(QStringLiteral("sheetViews")); + writer.writeEmptyElement(QStringLiteral("sheetView")); + writer.writeAttribute(QStringLiteral("workbookViewId"), QString::number(0)); + writer.writeAttribute(QStringLiteral("zoomToFit"), QStringLiteral("1")); + writer.writeEndElement(); //sheetViews + + int idx = d->workbook->drawings().indexOf(d->drawing.data()); + d->relationships->addWorksheetRelationship(QStringLiteral("/drawing"), QStringLiteral("../drawings/drawing%1.xml").arg(idx+1)); + + writer.writeEmptyElement(QStringLiteral("drawing")); + writer.writeAttribute(QStringLiteral("r:id"), QStringLiteral("rId%1").arg(d->relationships->count())); + + writer.writeEndElement();//chartsheet + writer.writeEndDocument(); +} + +bool Chartsheet::loadFromXmlFile(QIODevice *device) +{ + Q_D(Chartsheet); + + QXmlStreamReader reader(device); + while (!reader.atEnd()) { + reader.readNextStartElement(); + if (reader.tokenType() == QXmlStreamReader::StartElement) { + if (reader.name() == QLatin1String("drawing")) { + QString rId = reader.attributes().value(QStringLiteral("r:id")).toString(); + QString name = d->relationships->getRelationshipById(rId).target; + QString path = QDir::cleanPath(splitPath(filePath())[0] + QLatin1String("/") + name); + d->drawing = QSharedPointer(new Drawing(this, F_LoadFromExists)); + d->drawing->setFilePath(path); + } + } + } + + return true; +} + +QT_END_NAMESPACE_XLSX diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxchartsheet.h b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxchartsheet.h new file mode 100644 index 0000000..6c5ee98 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxchartsheet.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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. +** +****************************************************************************/ +#ifndef XLSXCHARTSHEET_H +#define XLSXCHARTSHEET_H + +#include "xlsxabstractsheet.h" +#include +#include + +QT_BEGIN_NAMESPACE_XLSX +class Workbook; +class DocumentPrivate; +class ChartsheetPrivate; +class Chart; +class Q_XLSX_EXPORT Chartsheet : public AbstractSheet +{ + Q_DECLARE_PRIVATE(Chartsheet) +public: + + ~Chartsheet(); + Chart *chart(); + +private: + friend class DocumentPrivate; + friend class Workbook; + Chartsheet(const QString &sheetName, int sheetId, Workbook *book, CreateFlag flag); + Chartsheet *copy(const QString &distName, int distId) const; + + void saveToXmlFile(QIODevice *device) const; + bool loadFromXmlFile(QIODevice *device); +}; + +QT_END_NAMESPACE_XLSX +#endif // XLSXCHARTSHEET_H diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxchartsheet_p.h b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxchartsheet_p.h new file mode 100644 index 0000000..817da88 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxchartsheet_p.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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. +** +****************************************************************************/ +#ifndef XLSXCHARTSHEET_P_H +#define XLSXCHARTSHEET_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt Xlsx API. It exists for the convenience +// of the Qt Xlsx. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// + +#include "xlsxglobal.h" +#include "xlsxchartsheet.h" +#include "xlsxabstractsheet_p.h" + +namespace QXlsx { + +class XLSX_AUTOTEST_EXPORT ChartsheetPrivate : public AbstractSheetPrivate +{ + Q_DECLARE_PUBLIC(Chartsheet) +public: + ChartsheetPrivate(Chartsheet *p, Chartsheet::CreateFlag flag); + ~ChartsheetPrivate(); + + Chart *chart; +}; + +} +#endif // XLSXCHARTSHEET_P_H diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcolor.cpp b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcolor.cpp new file mode 100644 index 0000000..b1ed463 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcolor.cpp @@ -0,0 +1,198 @@ +#include "xlsxcolor_p.h" +#include "xlsxstyles_p.h" +#include "xlsxutility_p.h" + +#include +#include +#include +#include + +namespace QXlsx { + + +XlsxColor::XlsxColor(const QColor &color) +{ + if (color.isValid()) + val.setValue(color); +} + +XlsxColor::XlsxColor(const QString &theme, const QString &tint) + :val(QStringList()<() && val.value().isValid()) + return true; + return false; +} + +bool XlsxColor::isIndexedColor() const +{ + return val.userType() == QMetaType::Int; +} + +bool XlsxColor::isThemeColor() const +{ + return val.userType() == QMetaType::QStringList; +} + +bool XlsxColor::isInvalid() const +{ + return !val.isValid(); +} + +QColor XlsxColor::rgbColor() const +{ + if (isRgbColor()) + return val.value(); + return QColor(); +} + +int XlsxColor::indexedColor() const +{ + if (isIndexedColor()) + return val.toInt(); + return -1; +} + +QStringList XlsxColor::themeColor() const +{ + if (isThemeColor()) + return val.toStringList(); + return QStringList(); +} + +bool XlsxColor::saveToXml(QXmlStreamWriter &writer, const QString &node) const +{ + if (!node.isEmpty()) + writer.writeEmptyElement(node); //color, bgColor, fgColor + else + writer.writeEmptyElement(QStringLiteral("color")); + + if (val.userType() == qMetaTypeId()) { + writer.writeAttribute(QStringLiteral("rgb"), XlsxColor::toARGBString(val.value())); + } else if (val.userType() == QMetaType::QStringList) { + QStringList themes = val.toStringList(); + writer.writeAttribute(QStringLiteral("theme"), themes[0]); + if (!themes[1].isEmpty()) + writer.writeAttribute(QStringLiteral("tint"), themes[1]); + } else if (val.userType() == QMetaType::Int) { + writer.writeAttribute(QStringLiteral("indexed"), val.toString()); + } else { + writer.writeAttribute(QStringLiteral("auto"), QStringLiteral("1")); + } + + return true; +} + +bool XlsxColor::loadFromXml(QXmlStreamReader &reader) +{ + QXmlStreamAttributes attributes = reader.attributes(); + + if (attributes.hasAttribute(QLatin1String("rgb"))) { + QString colorString = attributes.value(QLatin1String("rgb")).toString(); + val.setValue(fromARGBString(colorString)); + } else if (attributes.hasAttribute(QLatin1String("indexed"))) { + int index = attributes.value(QLatin1String("indexed")).toString().toInt(); + val.setValue(index); + } else if (attributes.hasAttribute(QLatin1String("theme"))) { + QString theme = attributes.value(QLatin1String("theme")).toString(); + QString tint = attributes.value(QLatin1String("tint")).toString(); + val.setValue(QStringList()<(), this); +} + + +QColor XlsxColor::fromARGBString(const QString &c) +{ + Q_ASSERT(c.length() == 8); + QColor color; + color.setAlpha(c.mid(0, 2).toInt(0, 16)); + color.setRed(c.mid(2, 2).toInt(0, 16)); + color.setGreen(c.mid(4, 2).toInt(0, 16)); + color.setBlue(c.mid(6, 2).toInt(0, 16)); + return color; +} + +QString XlsxColor::toARGBString(const QColor &c) +{ + QString color; + color.sprintf("%02X%02X%02X%02X", c.alpha(), c.red(), c.green(), c.blue()); + return color; +} + +#if !defined(QT_NO_DATASTREAM) +QDataStream &operator<<(QDataStream &s, const XlsxColor &color) +{ + if (color.isInvalid()) + s<<0; + else if (color.isRgbColor()) + s<<1<>(QDataStream &s, XlsxColor &color) +{ + int marker(4); + s>>marker; + if (marker == 0) { + color = XlsxColor(); + } else if (marker == 1) { + QColor c; + s>>c; + color = XlsxColor(c); + } else if (marker == 2) { + int indexed; + s>>indexed; + color = XlsxColor(indexed); + } else if (marker == 3) { + QStringList list; + s>>list; + color = XlsxColor(list[0], list[1]); + } + + return s; +} + +#endif + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug dbg, const XlsxColor &c) +{ + if (c.isInvalid()) + dbg.nospace() << "XlsxColor(invalid)"; + else if (c.isRgbColor()) + dbg.nospace() << c.rgbColor(); + else if (c.isIndexedColor()) + dbg.nospace() << "XlsxColor(indexed," << c.indexedColor() << ")"; + else if (c.isThemeColor()) + dbg.nospace() << "XlsxColor(theme," << c.themeColor().join(QLatin1Char(':')) << ")"; + + return dbg.space(); +} + +#endif + +} // namespace QXlsx diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcolor_p.h b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcolor_p.h new file mode 100644 index 0000000..eff1b0b --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcolor_p.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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. +** +****************************************************************************/ + +#ifndef QXLSX_XLSXCOLOR_P_H +#define QXLSX_XLSXCOLOR_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt Xlsx API. It exists for the convenience +// of the Qt Xlsx. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// + +#include "xlsxglobal.h" +#include +#include + +class QXmlStreamWriter; +class QXmlStreamReader; + +namespace QXlsx { + +class Styles; + +class Q_XLSX_EXPORT XlsxColor +{ +public: + explicit XlsxColor(const QColor &color = QColor()); + explicit XlsxColor(const QString &theme, const QString &tint=QString()); + explicit XlsxColor (int index); + + bool isThemeColor() const; + bool isIndexedColor() const; + bool isRgbColor() const; + bool isInvalid() const; + + QColor rgbColor() const; + int indexedColor() const; + QStringList themeColor() const; + + operator QVariant() const; + + static QColor fromARGBString(const QString &c); + static QString toARGBString(const QColor &c); + + bool saveToXml(QXmlStreamWriter &writer, const QString &node=QString()) const; + bool loadFromXml(QXmlStreamReader &reader); + +private: + QVariant val; +}; + +#if !defined(QT_NO_DATASTREAM) +Q_XLSX_EXPORT QDataStream &operator<<(QDataStream &, const XlsxColor &); +Q_XLSX_EXPORT QDataStream &operator>>(QDataStream &, XlsxColor &); +#endif + +#ifndef QT_NO_DEBUG_STREAM +Q_XLSX_EXPORT QDebug operator<<(QDebug dbg, const XlsxColor &c); +#endif + +} // namespace QXlsx + +Q_DECLARE_METATYPE(QXlsx::XlsxColor) + +#endif // QXLSX_XLSXCOLOR_P_H diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxconditionalformatting.cpp b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxconditionalformatting.cpp new file mode 100644 index 0000000..03561fe --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxconditionalformatting.cpp @@ -0,0 +1,735 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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 "xlsxconditionalformatting.h" +#include "xlsxconditionalformatting_p.h" +#include "xlsxworksheet.h" +#include "xlsxcellrange.h" +#include "xlsxstyles_p.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE_XLSX + +ConditionalFormattingPrivate::ConditionalFormattingPrivate() +{ + +} + +ConditionalFormattingPrivate::ConditionalFormattingPrivate(const ConditionalFormattingPrivate &other) + :QSharedData(other) +{ + +} + +ConditionalFormattingPrivate::~ConditionalFormattingPrivate() +{ + +} + +void ConditionalFormattingPrivate::writeCfVo(QXmlStreamWriter &writer, const XlsxCfVoData &cfvo) const +{ + writer.writeEmptyElement(QStringLiteral("cfvo")); + QString type; + switch(cfvo.type) { + case ConditionalFormatting::VOT_Formula: type=QStringLiteral("formula"); break; + case ConditionalFormatting::VOT_Max: type=QStringLiteral("max"); break; + case ConditionalFormatting::VOT_Min: type=QStringLiteral("min"); break; + case ConditionalFormatting::VOT_Num: type=QStringLiteral("num"); break; + case ConditionalFormatting::VOT_Percent: type=QStringLiteral("percent"); break; + case ConditionalFormatting::VOT_Percentile: type=QStringLiteral("percentile"); break; + default: break; + } + writer.writeAttribute(QStringLiteral("type"), type); + writer.writeAttribute(QStringLiteral("val"), cfvo.value); + if (!cfvo.gte) + writer.writeAttribute(QStringLiteral("gte"), QStringLiteral("0")); +} + +/*! + * \class ConditionalFormatting + * \brief Conditional formatting for single cell or ranges + * \inmodule QtXlsx + * + * The conditional formatting can be applied to a single cell or ranges of cells. + */ + + +/*! + \enum ConditionalFormatting::HighlightRuleType + + \value Highlight_LessThan + \value Highlight_LessThanOrEqual + \value Highlight_Equal + \value Highlight_NotEqual + \value Highlight_GreaterThanOrEqual + \value Highlight_GreaterThan + \value Highlight_Between + \value Highlight_NotBetween + + \value Highlight_ContainsText + \value Highlight_NotContainsText + \value Highlight_BeginsWith + \value Highlight_EndsWith + + \value Highlight_TimePeriod + + \value Highlight_Duplicate + \value Highlight_Unique + + \value Highlight_Blanks + \value Highlight_NoBlanks + \value Highlight_Errors + \value Highlight_NoErrors + + \value Highlight_Top + \value Highlight_TopPercent + \value Highlight_Bottom + \value Highlight_BottomPercent + + \value Highlight_AboveAverage + \value Highlight_AboveOrEqualAverage + \value Highlight_BelowAverage + \value Highlight_BelowOrEqualAverage + \value Highlight_AboveStdDev1 + \value Highlight_AboveStdDev2 + \value Highlight_AboveStdDev3 + \value Highlight_BelowStdDev1 + \value Highlight_BelowStdDev2 + \value Highlight_BelowStdDev3 + + \value Highlight_Expression +*/ + +/*! + \enum ConditionalFormatting::ValueObjectType + + \value VOT_Formula + \value VOT_Max + \value VOT_Min + \value VOT_Num + \value VOT_Percent + \value VOT_Percentile +*/ + +/*! + Construct a conditional formatting object +*/ +ConditionalFormatting::ConditionalFormatting() + :d(new ConditionalFormattingPrivate()) +{ + +} + +/*! + Constructs a copy of \a other. +*/ +ConditionalFormatting::ConditionalFormatting(const ConditionalFormatting &other) + :d(other.d) +{ + +} + +/*! + Assigns \a other to this conditional formatting and returns a reference to + this conditional formatting. + */ +ConditionalFormatting &ConditionalFormatting::operator=(const ConditionalFormatting &other) +{ + this->d = other.d; + return *this; +} + + +/*! + * Destroy the object. + */ +ConditionalFormatting::~ConditionalFormatting() +{ +} + +/*! + * Add a hightlight rule with the given \a type, \a formula1, \a formula2, + * \a format and \a stopIfTrue. + * Return false if failed. + */ +bool ConditionalFormatting::addHighlightCellsRule(HighlightRuleType type, const QString &formula1, const QString &formula2, const Format &format, bool stopIfTrue) +{ + if (format.isEmpty()) + return false; + + bool skipFormula = false; + + QSharedPointer cfRule(new XlsxCfRuleData); + if (type >= Highlight_LessThan && type <= Highlight_NotBetween) { + cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("cellIs"); + QString op; + switch (type) { + case Highlight_Between: op = QStringLiteral("between"); break; + case Highlight_Equal: op = QStringLiteral("equal"); break; + case Highlight_GreaterThan: op = QStringLiteral("greaterThan"); break; + case Highlight_GreaterThanOrEqual: op = QStringLiteral("greaterThanOrEqual"); break; + case Highlight_LessThan: op = QStringLiteral("lessThan"); break; + case Highlight_LessThanOrEqual: op = QStringLiteral("lessThanOrEqual"); break; + case Highlight_NotBetween: op = QStringLiteral("notBetween"); break; + case Highlight_NotEqual: op = QStringLiteral("notEqual"); break; + default: break; + } + cfRule->attrs[XlsxCfRuleData::A_operator] = op; + } else if (type >= Highlight_ContainsText && type <= Highlight_EndsWith) { + if (type == Highlight_ContainsText) { + cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("containsText"); + cfRule->attrs[XlsxCfRuleData::A_operator] = QStringLiteral("containsText"); + cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("NOT(ISERROR(SEARCH(\"%1\",%2)))").arg(formula1); + } else if (type == Highlight_NotContainsText) { + cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("notContainsText"); + cfRule->attrs[XlsxCfRuleData::A_operator] = QStringLiteral("notContains"); + cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("ISERROR(SEARCH(\"%2\",%1))").arg(formula1); + } else if (type == Highlight_BeginsWith) { + cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("beginsWith"); + cfRule->attrs[XlsxCfRuleData::A_operator] = QStringLiteral("beginsWith"); + cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("LEFT(%2,LEN(\"%1\"))=\"%1\"").arg(formula1); + } else { + cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("endsWith"); + cfRule->attrs[XlsxCfRuleData::A_operator] = QStringLiteral("endsWith"); + cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("RIGHT(%2,LEN(\"%1\"))=\"%1\"").arg(formula1); + } + cfRule->attrs[XlsxCfRuleData::A_text] = formula1; + skipFormula = true; + } else if (type == Highlight_TimePeriod) { + cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("timePeriod"); + //:Todo + return false; + } else if (type == Highlight_Duplicate) { + cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("duplicateValues"); + } else if (type == Highlight_Unique) { + cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("uniqueValues"); + } else if (type == Highlight_Errors) { + cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("containsErrors"); + cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("ISERROR(%1)"); + skipFormula = true; + } else if (type == Highlight_NoErrors) { + cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("notContainsErrors"); + cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("NOT(ISERROR(%1))"); + skipFormula = true; + } else if (type == Highlight_Blanks) { + cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("containsBlanks"); + cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("LEN(TRIM(%1))=0"); + skipFormula = true; + } else if (type == Highlight_NoBlanks) { + cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("notContainsBlanks"); + cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("LEN(TRIM(%1))>0"); + skipFormula = true; + } else if (type >= Highlight_Top && type <= Highlight_BottomPercent) { + cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("top10"); + if (type == Highlight_Bottom || type == Highlight_BottomPercent) + cfRule->attrs[XlsxCfRuleData::A_bottom] = QStringLiteral("1"); + if (type == Highlight_TopPercent || type == Highlight_BottomPercent) + cfRule->attrs[XlsxCfRuleData::A_percent] = QStringLiteral("1"); + cfRule->attrs[XlsxCfRuleData::A_rank] = !formula1.isEmpty() ? formula1 : QStringLiteral("10"); + skipFormula = true; + } else if (type >= Highlight_AboveAverage && type <= Highlight_BelowStdDev3) { + cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("aboveAverage"); + if (type >= Highlight_BelowAverage && type <= Highlight_BelowStdDev3) + cfRule->attrs[XlsxCfRuleData::A_aboveAverage] = QStringLiteral("0"); + if (type == Highlight_AboveOrEqualAverage || type == Highlight_BelowOrEqualAverage) + cfRule->attrs[XlsxCfRuleData::A_equalAverage] = QStringLiteral("1"); + if (type == Highlight_AboveStdDev1 || type == Highlight_BelowStdDev1) + cfRule->attrs[XlsxCfRuleData::A_stdDev] = QStringLiteral("1"); + else if (type == Highlight_AboveStdDev2 || type == Highlight_BelowStdDev2) + cfRule->attrs[XlsxCfRuleData::A_stdDev] = QStringLiteral("2"); + else if (type == Highlight_AboveStdDev3 || type == Highlight_BelowStdDev3) + cfRule->attrs[XlsxCfRuleData::A_stdDev] = QStringLiteral("3"); + } else if (type == Highlight_Expression){ + cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("expression"); + } else { + return false; + } + + cfRule->dxfFormat = format; + if (stopIfTrue) + cfRule->attrs[XlsxCfRuleData::A_stopIfTrue] = true; + if (!skipFormula) { + if (!formula1.isEmpty()) + cfRule->attrs[XlsxCfRuleData::A_formula1] = formula1.startsWith(QLatin1String("=")) ? formula1.mid(1) : formula1; + if (!formula2.isEmpty()) + cfRule->attrs[XlsxCfRuleData::A_formula2] = formula2.startsWith(QLatin1String("=")) ? formula2.mid(1) : formula2; + } + d->cfRules.append(cfRule); + return true; +} + +/*! + * \overload + * + * Add a hightlight rule with the given \a type \a format and \a stopIfTrue. + */ +bool ConditionalFormatting::addHighlightCellsRule(HighlightRuleType type, const Format &format, bool stopIfTrue) +{ + if ((type >= Highlight_AboveAverage && type <= Highlight_BelowStdDev3) + || (type >= Highlight_Duplicate && type <= Highlight_NoErrors)) { + return addHighlightCellsRule(type, QString(), QString(), format, stopIfTrue); + } + + return false; +} + +/*! + * \overload + * + * Add a hightlight rule with the given \a type, \a formula, \a format and \a stopIfTrue. + * Return false if failed. + */ +bool ConditionalFormatting::addHighlightCellsRule(HighlightRuleType type, const QString &formula, const Format &format, bool stopIfTrue) +{ + if (type == Highlight_Between || type == Highlight_NotBetween) + return false; + + return addHighlightCellsRule(type, formula, QString(), format, stopIfTrue); +} + +/*! + * Add a dataBar rule with the given \a color, \a type1, \a val1 + * , \a type2, \a val2, \a showData and \a stopIfTrue. + * Return false if failed. + */ +bool ConditionalFormatting::addDataBarRule(const QColor &color, ValueObjectType type1, const QString &val1, ValueObjectType type2, const QString &val2, bool showData, bool stopIfTrue) +{ + QSharedPointer cfRule(new XlsxCfRuleData); + + cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("dataBar"); + cfRule->attrs[XlsxCfRuleData::A_color1] = XlsxColor(color); + if (stopIfTrue) + cfRule->attrs[XlsxCfRuleData::A_stopIfTrue] = true; + if (!showData) + cfRule->attrs[XlsxCfRuleData::A_hideData] = true; + + XlsxCfVoData cfvo1(type1, val1); + XlsxCfVoData cfvo2(type2, val2); + cfRule->attrs[XlsxCfRuleData::A_cfvo1] = QVariant::fromValue(cfvo1); + cfRule->attrs[XlsxCfRuleData::A_cfvo2] = QVariant::fromValue(cfvo2); + + d->cfRules.append(cfRule); + return true; +} + +/*! + * \overload + * Add a dataBar rule with the given \a color, \a showData and \a stopIfTrue. + */ +bool ConditionalFormatting::addDataBarRule(const QColor &color, bool showData, bool stopIfTrue) +{ + return addDataBarRule(color, VOT_Min, QStringLiteral("0"), VOT_Max, QStringLiteral("0"), showData, stopIfTrue); +} + +/*! + * Add a colorScale rule with the given \a minColor, \a maxColor and \a stopIfTrue. + * Return false if failed. + */ +bool ConditionalFormatting::add2ColorScaleRule(const QColor &minColor, const QColor &maxColor, bool stopIfTrue) +{ + ValueObjectType type1 = VOT_Min; + ValueObjectType type2 = VOT_Max; + QString val1 = QStringLiteral("0"); + QString val2 = QStringLiteral("0"); + + QSharedPointer cfRule(new XlsxCfRuleData); + + cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("colorScale"); + cfRule->attrs[XlsxCfRuleData::A_color1] = XlsxColor(minColor); + cfRule->attrs[XlsxCfRuleData::A_color2] = XlsxColor(maxColor); + if (stopIfTrue) + cfRule->attrs[XlsxCfRuleData::A_stopIfTrue] = true; + + XlsxCfVoData cfvo1(type1, val1); + XlsxCfVoData cfvo2(type2, val2); + cfRule->attrs[XlsxCfRuleData::A_cfvo1] = QVariant::fromValue(cfvo1); + cfRule->attrs[XlsxCfRuleData::A_cfvo2] = QVariant::fromValue(cfvo2); + + d->cfRules.append(cfRule); + return true; +} + +/*! + * Add a colorScale rule with the given \a minColor, \a midColor, \a maxColor and \a stopIfTrue. + * Return false if failed. + */ +bool ConditionalFormatting::add3ColorScaleRule(const QColor &minColor, const QColor &midColor, const QColor &maxColor, bool stopIfTrue) +{ + ValueObjectType type1 = VOT_Min; + ValueObjectType type2 = VOT_Percent; + ValueObjectType type3 = VOT_Max; + QString val1 = QStringLiteral("0"); + QString val2 = QStringLiteral("50"); + QString val3 = QStringLiteral("0"); + + QSharedPointer cfRule(new XlsxCfRuleData); + + cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("colorScale"); + cfRule->attrs[XlsxCfRuleData::A_color1] = XlsxColor(minColor); + cfRule->attrs[XlsxCfRuleData::A_color2] = XlsxColor(midColor); + cfRule->attrs[XlsxCfRuleData::A_color3] = XlsxColor(maxColor); + + if (stopIfTrue) + cfRule->attrs[XlsxCfRuleData::A_stopIfTrue] = true; + + XlsxCfVoData cfvo1(type1, val1); + XlsxCfVoData cfvo2(type2, val2); + XlsxCfVoData cfvo3(type3, val3); + cfRule->attrs[XlsxCfRuleData::A_cfvo1] = QVariant::fromValue(cfvo1); + cfRule->attrs[XlsxCfRuleData::A_cfvo2] = QVariant::fromValue(cfvo2); + cfRule->attrs[XlsxCfRuleData::A_cfvo3] = QVariant::fromValue(cfvo3); + + d->cfRules.append(cfRule); + return true; +} + +/*! + Returns the ranges on which the validation will be applied. + */ +QList ConditionalFormatting::ranges() const +{ + return d->ranges; +} + +/*! + Add the \a cell on which the conditional formatting will apply to. + */ +void ConditionalFormatting::addCell(const CellReference &cell) +{ + d->ranges.append(CellRange(cell, cell)); +} + +/*! + \overload + Add the cell(\a row, \a col) on which the conditional formatting will apply to. + */ +void ConditionalFormatting::addCell(int row, int col) +{ + d->ranges.append(CellRange(row, col, row, col)); +} + +/*! + \overload + Add the range(\a firstRow, \a firstCol, \a lastRow, \a lastCol) on + which the conditional formatting will apply to. + */ +void ConditionalFormatting::addRange(int firstRow, int firstCol, int lastRow, int lastCol) +{ + d->ranges.append(CellRange(firstRow, firstCol, lastRow, lastCol)); +} + +/*! + Add the \a range on which the conditional formatting will apply to. + */ +void ConditionalFormatting::addRange(const CellRange &range) +{ + d->ranges.append(range); +} + +bool ConditionalFormattingPrivate::readCfRule(QXmlStreamReader &reader, XlsxCfRuleData *rule, Styles *styles) +{ + Q_ASSERT(reader.name() == QLatin1String("cfRule")); + QXmlStreamAttributes attrs = reader.attributes(); + if (attrs.hasAttribute(QLatin1String("type"))) + rule->attrs[XlsxCfRuleData::A_type] = attrs.value(QLatin1String("type")).toString(); + if (attrs.hasAttribute(QLatin1String("dxfId"))) { + int id = attrs.value(QLatin1String("dxfId")).toString().toInt(); + if (styles) + rule->dxfFormat = styles->dxfFormat(id); + else + rule->dxfFormat.setDxfIndex(id); + } + rule->priority = attrs.value(QLatin1String("priority")).toString().toInt(); + if (attrs.value(QLatin1String("stopIfTrue")) == QLatin1String("1")) { + //default is false + rule->attrs[XlsxCfRuleData::A_stopIfTrue] = QLatin1String("1"); + } + if (attrs.value(QLatin1String("aboveAverage")) == QLatin1String("0")) { + //default is true + rule->attrs[XlsxCfRuleData::A_aboveAverage] = QLatin1String("0"); + } + if (attrs.value(QLatin1String("percent")) == QLatin1String("1")) { + //default is false + rule->attrs[XlsxCfRuleData::A_percent] = QLatin1String("1"); + } + if (attrs.value(QLatin1String("bottom")) == QLatin1String("1")) { + //default is false + rule->attrs[XlsxCfRuleData::A_bottom] = QLatin1String("1"); + } + if (attrs.hasAttribute(QLatin1String("operator"))) + rule->attrs[XlsxCfRuleData::A_operator] = attrs.value(QLatin1String("operator")).toString(); + + if (attrs.hasAttribute(QLatin1String("text"))) + rule->attrs[XlsxCfRuleData::A_text] = attrs.value(QLatin1String("text")).toString(); + + if (attrs.hasAttribute(QLatin1String("timePeriod"))) + rule->attrs[XlsxCfRuleData::A_timePeriod] = attrs.value(QLatin1String("timePeriod")).toString(); + + if (attrs.hasAttribute(QLatin1String("rank"))) + rule->attrs[XlsxCfRuleData::A_rank] = attrs.value(QLatin1String("rank")).toString(); + + if (attrs.hasAttribute(QLatin1String("stdDev"))) + rule->attrs[XlsxCfRuleData::A_stdDev] = attrs.value(QLatin1String("stdDev")).toString(); + + if (attrs.value(QLatin1String("equalAverage")) == QLatin1String("1")) { + //default is false + rule->attrs[XlsxCfRuleData::A_equalAverage] = QLatin1String("1"); + } + + while (!reader.atEnd()) { + reader.readNextStartElement(); + if (reader.tokenType() == QXmlStreamReader::StartElement) { + if (reader.name() == QLatin1String("formula")) { + QString f = reader.readElementText(); + if (!rule->attrs.contains(XlsxCfRuleData::A_formula1)) + rule->attrs[XlsxCfRuleData::A_formula1] = f; + else if (!rule->attrs.contains(XlsxCfRuleData::A_formula2)) + rule->attrs[XlsxCfRuleData::A_formula2] = f; + else if (!rule->attrs.contains(XlsxCfRuleData::A_formula3)) + rule->attrs[XlsxCfRuleData::A_formula3] = f; + } else if (reader.name() == QLatin1String("dataBar")) { + readCfDataBar(reader, rule); + } else if (reader.name() == QLatin1String("colorScale")) { + readCfColorScale(reader, rule); + } + } + if (reader.tokenType() == QXmlStreamReader::EndElement + && reader.name() == QStringLiteral("conditionalFormatting")) { + break; + } + } + return true; +} + +bool ConditionalFormattingPrivate::readCfDataBar(QXmlStreamReader &reader, XlsxCfRuleData *rule) +{ + Q_ASSERT(reader.name() == QLatin1String("dataBar")); + QXmlStreamAttributes attrs = reader.attributes(); + if (attrs.value(QLatin1String("showValue")) == QLatin1String("0")) + rule->attrs[XlsxCfRuleData::A_hideData] = QStringLiteral("1"); + + while (!reader.atEnd()) { + reader.readNextStartElement(); + if (reader.tokenType() == QXmlStreamReader::StartElement) { + if (reader.name() == QLatin1String("cfvo")) { + XlsxCfVoData data; + readCfVo(reader, data); + if (!rule->attrs.contains(XlsxCfRuleData::A_cfvo1)) + rule->attrs[XlsxCfRuleData::A_cfvo1] = QVariant::fromValue(data); + else + rule->attrs[XlsxCfRuleData::A_cfvo2] = QVariant::fromValue(data); + } else if (reader.name() == QLatin1String("color")) { + XlsxColor color; + color.loadFromXml(reader); + rule->attrs[XlsxCfRuleData::A_color1] = color; + } + } + if (reader.tokenType() == QXmlStreamReader::EndElement + && reader.name() == QStringLiteral("dataBar")) { + break; + } + } + + return true; +} + +bool ConditionalFormattingPrivate::readCfColorScale(QXmlStreamReader &reader, XlsxCfRuleData *rule) +{ + Q_ASSERT(reader.name() == QLatin1String("colorScale")); + + while (!reader.atEnd()) { + reader.readNextStartElement(); + if (reader.tokenType() == QXmlStreamReader::StartElement) { + if (reader.name() == QLatin1String("cfvo")) { + XlsxCfVoData data; + readCfVo(reader, data); + if (!rule->attrs.contains(XlsxCfRuleData::A_cfvo1)) + rule->attrs[XlsxCfRuleData::A_cfvo1] = QVariant::fromValue(data); + else if (!rule->attrs.contains(XlsxCfRuleData::A_cfvo2)) + rule->attrs[XlsxCfRuleData::A_cfvo2] = QVariant::fromValue(data); + else + rule->attrs[XlsxCfRuleData::A_cfvo2] = QVariant::fromValue(data); + } else if (reader.name() == QLatin1String("color")) { + XlsxColor color; + color.loadFromXml(reader); + if (!rule->attrs.contains(XlsxCfRuleData::A_color1)) + rule->attrs[XlsxCfRuleData::A_color1] = color; + else if (!rule->attrs.contains(XlsxCfRuleData::A_color2)) + rule->attrs[XlsxCfRuleData::A_color2] = color; + else + rule->attrs[XlsxCfRuleData::A_color3] = color; + } + } + if (reader.tokenType() == QXmlStreamReader::EndElement + && reader.name() == QStringLiteral("colorScale")) { + break; + } + } + + return true; +} + +bool ConditionalFormattingPrivate::readCfVo(QXmlStreamReader &reader, XlsxCfVoData &cfvo) +{ + Q_ASSERT(reader.name() == QStringLiteral("cfvo")); + + QXmlStreamAttributes attrs = reader.attributes(); + + QString type = attrs.value(QLatin1String("type")).toString(); + ConditionalFormatting::ValueObjectType t; + if (type == QLatin1String("formula")) + t = ConditionalFormatting::VOT_Formula; + else if (type == QLatin1String("max")) + t = ConditionalFormatting::VOT_Max; + else if (type == QLatin1String("min")) + t = ConditionalFormatting::VOT_Min; + else if (type == QLatin1String("num")) + t = ConditionalFormatting::VOT_Num; + else if (type == QLatin1String("percent")) + t = ConditionalFormatting::VOT_Percent; + else //if (type == QLatin1String("percentile")) + t = ConditionalFormatting::VOT_Percentile; + + cfvo.type = t; + cfvo.value = attrs.value(QLatin1String("val")).toString(); + if (attrs.value(QLatin1String("gte")) == QLatin1String("0")) { + //default is true + cfvo.gte = false; + } + return true; +} + +bool ConditionalFormatting::loadFromXml(QXmlStreamReader &reader, Styles *styles) +{ + Q_ASSERT(reader.name() == QStringLiteral("conditionalFormatting")); + + d->ranges.clear(); + d->cfRules.clear(); + QXmlStreamAttributes attrs = reader.attributes(); + QString sqref = attrs.value(QLatin1String("sqref")).toString(); + foreach (QString range, sqref.split(QLatin1Char(' '))) + this->addRange(range); + + while (!reader.atEnd()) { + reader.readNextStartElement(); + if (reader.tokenType() == QXmlStreamReader::StartElement) { + if (reader.name() == QLatin1String("cfRule")) { + QSharedPointer cfRule(new XlsxCfRuleData); + d->readCfRule(reader, cfRule.data(), styles); + d->cfRules.append(cfRule); + } + } + if (reader.tokenType() == QXmlStreamReader::EndElement + && reader.name() == QStringLiteral("conditionalFormatting")) { + break; + } + } + + + return true; +} + +bool ConditionalFormatting::saveToXml(QXmlStreamWriter &writer) const +{ + writer.writeStartElement(QStringLiteral("conditionalFormatting")); + QStringList sqref; + foreach (CellRange range, ranges()) + sqref.append(range.toString()); + writer.writeAttribute(QStringLiteral("sqref"), sqref.join(QLatin1Char(' '))); + + for (int i=0; icfRules.size(); ++i) { + const QSharedPointer &rule = d->cfRules[i]; + writer.writeStartElement(QStringLiteral("cfRule")); + writer.writeAttribute(QStringLiteral("type"), rule->attrs[XlsxCfRuleData::A_type].toString()); + if (rule->dxfFormat.dxfIndexValid()) + writer.writeAttribute(QStringLiteral("dxfId"), QString::number(rule->dxfFormat.dxfIndex())); + writer.writeAttribute(QStringLiteral("priority"), QString::number(rule->priority)); + if (rule->attrs.contains(XlsxCfRuleData::A_stopIfTrue)) + writer.writeAttribute(QStringLiteral("stopIfTrue"), rule->attrs[XlsxCfRuleData::A_stopIfTrue].toString()); + if (rule->attrs.contains(XlsxCfRuleData::A_aboveAverage)) + writer.writeAttribute(QStringLiteral("aboveAverage"), rule->attrs[XlsxCfRuleData::A_aboveAverage].toString()); + if (rule->attrs.contains(XlsxCfRuleData::A_percent)) + writer.writeAttribute(QStringLiteral("percent"), rule->attrs[XlsxCfRuleData::A_percent].toString()); + if (rule->attrs.contains(XlsxCfRuleData::A_bottom)) + writer.writeAttribute(QStringLiteral("bottom"), rule->attrs[XlsxCfRuleData::A_bottom].toString()); + if (rule->attrs.contains(XlsxCfRuleData::A_operator)) + writer.writeAttribute(QStringLiteral("operator"), rule->attrs[XlsxCfRuleData::A_operator].toString()); + if (rule->attrs.contains(XlsxCfRuleData::A_text)) + writer.writeAttribute(QStringLiteral("text"), rule->attrs[XlsxCfRuleData::A_text].toString()); + if (rule->attrs.contains(XlsxCfRuleData::A_timePeriod)) + writer.writeAttribute(QStringLiteral("timePeriod"), rule->attrs[XlsxCfRuleData::A_timePeriod].toString()); + if (rule->attrs.contains(XlsxCfRuleData::A_rank)) + writer.writeAttribute(QStringLiteral("rank"), rule->attrs[XlsxCfRuleData::A_rank].toString()); + if (rule->attrs.contains(XlsxCfRuleData::A_stdDev)) + writer.writeAttribute(QStringLiteral("stdDev"), rule->attrs[XlsxCfRuleData::A_stdDev].toString()); + if (rule->attrs.contains(XlsxCfRuleData::A_equalAverage)) + writer.writeAttribute(QStringLiteral("equalAverage"), rule->attrs[XlsxCfRuleData::A_equalAverage].toString()); + + if (rule->attrs[XlsxCfRuleData::A_type] == QLatin1String("dataBar")) { + writer.writeStartElement(QStringLiteral("dataBar")); + if (rule->attrs.contains(XlsxCfRuleData::A_hideData)) + writer.writeAttribute(QStringLiteral("showValue"), QStringLiteral("0")); + d->writeCfVo(writer, rule->attrs[XlsxCfRuleData::A_cfvo1].value()); + d->writeCfVo(writer, rule->attrs[XlsxCfRuleData::A_cfvo2].value()); + rule->attrs[XlsxCfRuleData::A_color1].value().saveToXml(writer); + writer.writeEndElement();//dataBar + } else if (rule->attrs[XlsxCfRuleData::A_type] == QLatin1String("colorScale")) { + writer.writeStartElement(QStringLiteral("colorScale")); + d->writeCfVo(writer, rule->attrs[XlsxCfRuleData::A_cfvo1].value()); + d->writeCfVo(writer, rule->attrs[XlsxCfRuleData::A_cfvo2].value()); + if (rule->attrs.contains(XlsxCfRuleData::A_cfvo3)) + d->writeCfVo(writer, rule->attrs[XlsxCfRuleData::A_cfvo3].value()); + + rule->attrs[XlsxCfRuleData::A_color1].value().saveToXml(writer); + rule->attrs[XlsxCfRuleData::A_color2].value().saveToXml(writer); + if (rule->attrs.contains(XlsxCfRuleData::A_color3)) + rule->attrs[XlsxCfRuleData::A_color3].value().saveToXml(writer); + + writer.writeEndElement();//colorScale + } + + + if (rule->attrs.contains(XlsxCfRuleData::A_formula1_temp)) { + QString startCell = ranges()[0].toString().split(QLatin1Char(':'))[0]; + writer.writeTextElement(QStringLiteral("formula"), rule->attrs[XlsxCfRuleData::A_formula1_temp].toString().arg(startCell)); + } else if (rule->attrs.contains(XlsxCfRuleData::A_formula1)) { + writer.writeTextElement(QStringLiteral("formula"), rule->attrs[XlsxCfRuleData::A_formula1].toString()); + } + if (rule->attrs.contains(XlsxCfRuleData::A_formula2)) + writer.writeTextElement(QStringLiteral("formula"), rule->attrs[XlsxCfRuleData::A_formula2].toString()); + if (rule->attrs.contains(XlsxCfRuleData::A_formula3)) + writer.writeTextElement(QStringLiteral("formula"), rule->attrs[XlsxCfRuleData::A_formula3].toString()); + + writer.writeEndElement(); //cfRule + } + + writer.writeEndElement(); //conditionalFormatting + return true; +} + +QT_END_NAMESPACE_XLSX diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxconditionalformatting.h b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxconditionalformatting.h new file mode 100644 index 0000000..45378f7 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxconditionalformatting.h @@ -0,0 +1,135 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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. +** +****************************************************************************/ +#ifndef QXLSX_XLSXCONDITIONALFORMATTING_H +#define QXLSX_XLSXCONDITIONALFORMATTING_H + +#include "xlsxglobal.h" +#include "xlsxcellrange.h" +#include "xlsxcellreference.h" +#include +#include +#include + +class QXmlStreamReader; +class QXmlStreamWriter; +class QColor; +class ConditionalFormattingTest; + +QT_BEGIN_NAMESPACE_XLSX + +class Format; +class Worksheet; +class Styles; + +class ConditionalFormattingPrivate; +class Q_XLSX_EXPORT ConditionalFormatting +{ +public: + enum HighlightRuleType { + Highlight_LessThan, + Highlight_LessThanOrEqual, + Highlight_Equal, + Highlight_NotEqual, + Highlight_GreaterThanOrEqual, + Highlight_GreaterThan, + Highlight_Between, + Highlight_NotBetween, + + Highlight_ContainsText, + Highlight_NotContainsText, + Highlight_BeginsWith, + Highlight_EndsWith, + + Highlight_TimePeriod, + + Highlight_Duplicate, + Highlight_Unique, + Highlight_Blanks, + Highlight_NoBlanks, + Highlight_Errors, + Highlight_NoErrors, + + Highlight_Top, + Highlight_TopPercent, + Highlight_Bottom, + Highlight_BottomPercent, + + Highlight_AboveAverage, + Highlight_AboveOrEqualAverage, + Highlight_AboveStdDev1, + Highlight_AboveStdDev2, + Highlight_AboveStdDev3, + Highlight_BelowAverage, + Highlight_BelowOrEqualAverage, + Highlight_BelowStdDev1, + Highlight_BelowStdDev2, + Highlight_BelowStdDev3, + + Highlight_Expression + }; + + enum ValueObjectType + { + VOT_Formula, + VOT_Max, + VOT_Min, + VOT_Num, + VOT_Percent, + VOT_Percentile + }; + + ConditionalFormatting(); + ConditionalFormatting(const ConditionalFormatting &other); + ~ConditionalFormatting(); + + bool addHighlightCellsRule(HighlightRuleType type, const Format &format, bool stopIfTrue=false); + bool addHighlightCellsRule(HighlightRuleType type, const QString &formula1, const Format &format, bool stopIfTrue=false); + bool addHighlightCellsRule(HighlightRuleType type, const QString &formula1, const QString &formula2, const Format &format, bool stopIfTrue=false); + bool addDataBarRule(const QColor &color, bool showData=true, bool stopIfTrue=false); + bool addDataBarRule(const QColor &color, ValueObjectType type1, const QString &val1, ValueObjectType type2, const QString &val2, bool showData=true, bool stopIfTrue=false); + bool add2ColorScaleRule(const QColor &minColor, const QColor &maxColor, bool stopIfTrue=false); + bool add3ColorScaleRule(const QColor &minColor, const QColor &midColor, const QColor &maxColor, bool stopIfTrue=false); + + QList ranges() const; + + void addCell(const CellReference &cell); + void addCell(int row, int col); + void addRange(int firstRow, int firstCol, int lastRow, int lastCol); + void addRange(const CellRange &range); + + //needed by QSharedDataPointer!! + ConditionalFormatting &operator=(const ConditionalFormatting &other); + +private: + friend class Worksheet; + friend class ::ConditionalFormattingTest; + bool saveToXml(QXmlStreamWriter &writer) const; + bool loadFromXml(QXmlStreamReader &reader, Styles *styles=0); + QSharedDataPointer d; +}; + +QT_END_NAMESPACE_XLSX + +#endif // QXLSX_XLSXCONDITIONALFORMATTING_H diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxconditionalformatting_p.h b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxconditionalformatting_p.h new file mode 100644 index 0000000..ff71e5b --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxconditionalformatting_p.h @@ -0,0 +1,131 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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. +** +****************************************************************************/ + +#ifndef XLSXCONDITIONALFORMATTING_P_H +#define XLSXCONDITIONALFORMATTING_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt Xlsx API. It exists for the convenience +// of the Qt Xlsx. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// + +#include "xlsxconditionalformatting.h" +#include "xlsxformat.h" +#include "xlsxcolor_p.h" +#include +#include +#include + +QT_BEGIN_NAMESPACE_XLSX + +class XlsxCfVoData +{ +public: + XlsxCfVoData() + :gte(true) + { + } + + XlsxCfVoData(ConditionalFormatting::ValueObjectType type, const QString &value, bool gte=true) + :type(type), value(value), gte(gte) + { + } + + ConditionalFormatting::ValueObjectType type; + QString value; + bool gte; +}; + +class XlsxCfRuleData +{ +public: + enum Attribute { + A_type, + A_dxfId, + //A_priority, + A_stopIfTrue, + A_aboveAverage, + A_percent, + A_bottom, + A_operator, + A_text, + A_timePeriod, + A_rank, + A_stdDev, + A_equalAverage, + + A_dxfFormat, + A_formula1, + A_formula2, + A_formula3, + A_formula1_temp, + + A_color1, + A_color2, + A_color3, + + A_cfvo1, + A_cfvo2, + A_cfvo3, + + A_hideData + }; + + XlsxCfRuleData() + :priority(1) + {} + + int priority; + Format dxfFormat; + QMap attrs; +}; + +class ConditionalFormattingPrivate : public QSharedData +{ +public: + ConditionalFormattingPrivate(); + ConditionalFormattingPrivate(const ConditionalFormattingPrivate &other); + ~ConditionalFormattingPrivate(); + + void writeCfVo(QXmlStreamWriter &writer, const XlsxCfVoData& cfvo) const; + bool readCfVo(QXmlStreamReader &reader, XlsxCfVoData& cfvo); + bool readCfRule(QXmlStreamReader &reader, XlsxCfRuleData *cfRule, Styles *styles); + bool readCfDataBar(QXmlStreamReader &reader, XlsxCfRuleData *cfRule); + bool readCfColorScale(QXmlStreamReader &reader, XlsxCfRuleData *cfRule); + + QList >cfRules; + QList ranges; +}; + +QT_END_NAMESPACE_XLSX + +Q_DECLARE_METATYPE(QXlsx::XlsxCfVoData) +#endif // XLSXCONDITIONALFORMATTING_P_H diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcontenttypes.cpp b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcontenttypes.cpp new file mode 100644 index 0000000..8a500ac --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxcontenttypes.cpp @@ -0,0 +1,205 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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 "xlsxcontenttypes_p.h" +#include +#include +#include +#include +#include +#include + +namespace QXlsx { + +ContentTypes::ContentTypes(CreateFlag flag) + :AbstractOOXmlFile(flag) +{ + m_package_prefix = QStringLiteral("application/vnd.openxmlformats-package."); + m_document_prefix = QStringLiteral("application/vnd.openxmlformats-officedocument."); + + m_defaults.insert(QStringLiteral("rels"), m_package_prefix + QStringLiteral("relationships+xml")); + m_defaults.insert(QStringLiteral("xml"), QStringLiteral("application/xml")); +} + +void ContentTypes::addDefault(const QString &key, const QString &value) +{ + m_defaults.insert(key, value); +} + +void ContentTypes::addOverride(const QString &key, const QString &value) +{ + m_overrides.insert(key, value); +} + +void ContentTypes::addDocPropApp() +{ + addOverride(QStringLiteral("/docProps/app.xml"), m_document_prefix + QStringLiteral("extended-properties+xml")); +} + +void ContentTypes::addDocPropCore() +{ + addOverride(QStringLiteral("/docProps/core.xml"), m_package_prefix + QStringLiteral("core-properties+xml")); +} + +void ContentTypes::addStyles() +{ + addOverride(QStringLiteral("/xl/styles.xml"), m_document_prefix + QStringLiteral("spreadsheetml.styles+xml")); +} + +void ContentTypes::addTheme() +{ + addOverride(QStringLiteral("/xl/theme/theme1.xml"), m_document_prefix + QStringLiteral("theme+xml")); +} + +void ContentTypes::addWorkbook() +{ + addOverride(QStringLiteral("/xl/workbook.xml"), m_document_prefix + QStringLiteral("spreadsheetml.sheet.main+xml")); +} + +void ContentTypes::addWorksheetName(const QString &name) +{ + addOverride(QStringLiteral("/xl/worksheets/%1.xml").arg(name), m_document_prefix + QStringLiteral("spreadsheetml.worksheet+xml")); +} + +void ContentTypes::addChartsheetName(const QString &name) +{ + addOverride(QStringLiteral("/xl/chartsheets/%1.xml").arg(name), m_document_prefix + QStringLiteral("spreadsheetml.chartsheet+xml")); +} + +void ContentTypes::addDrawingName(const QString &name) +{ + addOverride(QStringLiteral("/xl/drawings/%1.xml").arg(name), m_document_prefix + QStringLiteral("drawing+xml")); +} + +void ContentTypes::addChartName(const QString &name) +{ + addOverride(QStringLiteral("/xl/charts/%1.xml").arg(name), m_document_prefix + QStringLiteral("drawingml.chart+xml")); +} + +void ContentTypes::addCommentName(const QString &name) +{ + addOverride(QStringLiteral("/xl/%1.xml").arg(name), m_document_prefix + QStringLiteral("spreadsheetml.comments+xml")); +} + +void ContentTypes::addTableName(const QString &name) +{ + addOverride(QStringLiteral("/xl/tables/%1.xml").arg(name), m_document_prefix + QStringLiteral("spreadsheetml.table+xml")); +} + +void ContentTypes::addExternalLinkName(const QString &name) +{ + addOverride(QStringLiteral("/xl/externalLinks/%1.xml").arg(name), m_document_prefix + QStringLiteral("spreadsheetml.externalLink+xml")); +} + +void ContentTypes::addSharedString() +{ + addOverride(QStringLiteral("/xl/sharedStrings.xml"), m_document_prefix + QStringLiteral("spreadsheetml.sharedStrings+xml")); +} + +void ContentTypes::addVmlName() +{ + addOverride(QStringLiteral("vml"), m_document_prefix + QStringLiteral("vmlDrawing")); +} + +void ContentTypes::addCalcChain() +{ + addOverride(QStringLiteral("/xl/calcChain.xml"), m_document_prefix + QStringLiteral("spreadsheetml.calcChain+xml")); +} + +void ContentTypes::addVbaProject() +{ + //:TODO + addOverride(QStringLiteral("bin"), QStringLiteral("application/vnd.ms-office.vbaProject")); +} + +void ContentTypes::clearOverrides() +{ + m_overrides.clear(); +} + +void ContentTypes::saveToXmlFile(QIODevice *device) const +{ + QXmlStreamWriter writer(device); + + writer.writeStartDocument(QStringLiteral("1.0"), true); + writer.writeStartElement(QStringLiteral("Types")); + writer.writeAttribute(QStringLiteral("xmlns"), QStringLiteral("http://schemas.openxmlformats.org/package/2006/content-types")); + + { + QMapIterator it(m_defaults); + while (it.hasNext()) { + it.next(); + writer.writeStartElement(QStringLiteral("Default")); + writer.writeAttribute(QStringLiteral("Extension"), it.key()); + writer.writeAttribute(QStringLiteral("ContentType"), it.value()); + writer.writeEndElement();//Default + } + } + + { + QMapIterator it(m_overrides); + while (it.hasNext()) { + it.next(); + writer.writeStartElement(QStringLiteral("Override")); + writer.writeAttribute(QStringLiteral("PartName"), it.key()); + writer.writeAttribute(QStringLiteral("ContentType"), it.value()); + writer.writeEndElement(); //Override + } + } + + writer.writeEndElement();//Types + writer.writeEndDocument(); + +} + +bool ContentTypes::loadFromXmlFile(QIODevice *device) +{ + m_defaults.clear(); + m_overrides.clear(); + + QXmlStreamReader reader(device); + while (!reader.atEnd()) { + QXmlStreamReader::TokenType token = reader.readNext(); + if (token == QXmlStreamReader::StartElement) { + if (reader.name() == QLatin1String("Default")) { + QXmlStreamAttributes attrs = reader.attributes(); + QString extension = attrs.value(QLatin1String("Extension")).toString(); + QString type = attrs.value(QLatin1String("ContentType")).toString(); + m_defaults.insert(extension, type); + } else if (reader.name() == QLatin1String("Override")) { + QXmlStreamAttributes attrs = reader.attributes(); + QString partName = attrs.value(QLatin1String("PartName")).toString(); + QString type = attrs.value(QLatin1String("ContentType")).toString(); + m_overrides.insert(partName, type); + } + } + + if (reader.hasError()) { + qDebug()< +** 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. +** +****************************************************************************/ +#ifndef XLSXCONTENTTYPES_H +#define XLSXCONTENTTYPES_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt Xlsx API. It exists for the convenience +// of the Qt Xlsx. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// + +#include "xlsxabstractooxmlfile.h" + +#include +#include +#include + +class QIODevice; + +namespace QXlsx { + +class ContentTypes : public AbstractOOXmlFile +{ +public: + ContentTypes(CreateFlag flag); + + void addDefault(const QString &key, const QString &value); + void addOverride(const QString &key, const QString &value); + + //Convenient funcation for addOverride() + void addDocPropCore(); + void addDocPropApp(); + void addStyles(); + void addTheme(); + void addWorkbook(); + void addWorksheetName(const QString &name); + void addChartsheetName(const QString &name); + void addChartName(const QString &name); + void addDrawingName(const QString &name); + void addCommentName(const QString &name); + void addTableName(const QString &name); + void addExternalLinkName(const QString &name); + void addSharedString(); + void addVmlName(); + void addCalcChain(); + void addVbaProject(); + + void clearOverrides(); + + void saveToXmlFile(QIODevice *device) const; + bool loadFromXmlFile(QIODevice *device); +private: + QMap m_defaults; + QMap m_overrides; + + QString m_package_prefix; + QString m_document_prefix; +}; + +} +#endif // XLSXCONTENTTYPES_H diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdatavalidation.cpp b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdatavalidation.cpp new file mode 100644 index 0000000..c538c72 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdatavalidation.cpp @@ -0,0 +1,552 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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 "xlsxdatavalidation.h" +#include "xlsxdatavalidation_p.h" +#include "xlsxworksheet.h" +#include "xlsxcellrange.h" + +#include +#include + +QT_BEGIN_NAMESPACE_XLSX + +DataValidationPrivate::DataValidationPrivate() + :validationType(DataValidation::None), validationOperator(DataValidation::Between) + , errorStyle(DataValidation::Stop), allowBlank(false), isPromptMessageVisible(true) + , isErrorMessageVisible(true) +{ + +} + +DataValidationPrivate::DataValidationPrivate(DataValidation::ValidationType type, DataValidation::ValidationOperator op, const QString &formula1, const QString &formula2, bool allowBlank) + :validationType(type), validationOperator(op) + , errorStyle(DataValidation::Stop), allowBlank(allowBlank), isPromptMessageVisible(true) + , isErrorMessageVisible(true), formula1(formula1), formula2(formula2) +{ + +} + +DataValidationPrivate::DataValidationPrivate(const DataValidationPrivate &other) + :QSharedData(other) + , validationType(DataValidation::None), validationOperator(DataValidation::Between) + , errorStyle(DataValidation::Stop), allowBlank(false), isPromptMessageVisible(true) + , isErrorMessageVisible(true) +{ + +} + +DataValidationPrivate::~DataValidationPrivate() +{ + +} + +/*! + * \class DataValidation + * \brief Data validation for single cell or a range + * \inmodule QtXlsx + * + * The data validation can be applied to a single cell or a range of cells. + */ + +/*! + * \enum DataValidation::ValidationType + * + * The enum type defines the type of data that you wish to validate. + * + * \value None the type of data is unrestricted. This is the same as not applying a data validation. + * \value Whole restricts the cell to integer values. Means "Whole number"? + * \value Decimal restricts the cell to decimal values. + * \value List restricts the cell to a set of user specified values. + * \value Date restricts the cell to date values. + * \value Time restricts the cell to time values. + * \value TextLength restricts the cell data based on an integer string length. + * \value Custom restricts the cell based on an external Excel formula that returns a true/false value. + */ + +/*! + * \enum DataValidation::ValidationOperator + * + * The enum type defines the criteria by which the data in the + * cell is validated + * + * \value Between + * \value NotBetween + * \value Equal + * \value NotEqual + * \value LessThan + * \value LessThanOrEqual + * \value GreaterThan + * \value GreaterThanOrEqual + */ + +/*! + * \enum DataValidation::ErrorStyle + * + * The enum type defines the type of error dialog that + * is displayed. + * + * \value Stop + * \value Warning + * \value Information + */ + +/*! + * Construct a data validation object with the given \a type, \a op, \a formula1 + * \a formula2, and \a allowBlank. + */ +DataValidation::DataValidation(ValidationType type, ValidationOperator op, const QString &formula1, const QString &formula2, bool allowBlank) + :d(new DataValidationPrivate(type, op, formula1, formula2, allowBlank)) +{ + +} + +/*! + Construct a data validation object +*/ +DataValidation::DataValidation() + :d(new DataValidationPrivate()) +{ + +} + +/*! + Constructs a copy of \a other. +*/ +DataValidation::DataValidation(const DataValidation &other) + :d(other.d) +{ + +} + +/*! + Assigns \a other to this validation and returns a reference to this validation. + */ +DataValidation &DataValidation::operator=(const DataValidation &other) +{ + this->d = other.d; + return *this; +} + + +/*! + * Destroy the object. + */ +DataValidation::~DataValidation() +{ +} + +/*! + Returns the validation type. + */ +DataValidation::ValidationType DataValidation::validationType() const +{ + return d->validationType; +} + +/*! + Returns the validation operator. + */ +DataValidation::ValidationOperator DataValidation::validationOperator() const +{ + return d->validationOperator; +} + +/*! + Returns the validation error style. + */ +DataValidation::ErrorStyle DataValidation::errorStyle() const +{ + return d->errorStyle; +} + +/*! + Returns the formula1. + */ +QString DataValidation::formula1() const +{ + return d->formula1; +} + +/*! + Returns the formula2. + */ +QString DataValidation::formula2() const +{ + return d->formula2; +} + +/*! + Returns whether blank is allowed. + */ +bool DataValidation::allowBlank() const +{ + return d->allowBlank; +} + +/*! + Returns the error message. + */ +QString DataValidation::errorMessage() const +{ + return d->errorMessage; +} + +/*! + Returns the error message title. + */ +QString DataValidation::errorMessageTitle() const +{ + return d->errorMessageTitle; +} + +/*! + Returns the prompt message. + */ +QString DataValidation::promptMessage() const +{ + return d->promptMessage; +} + +/*! + Returns the prompt message title. + */ +QString DataValidation::promptMessageTitle() const +{ + return d->promptMessageTitle; +} + +/*! + Returns the whether prompt message is shown. + */ +bool DataValidation::isPromptMessageVisible() const +{ + return d->isPromptMessageVisible; +} + +/*! + Returns the whether error message is shown. + */ +bool DataValidation::isErrorMessageVisible() const +{ + return d->isErrorMessageVisible; +} + +/*! + Returns the ranges on which the validation will be applied. + */ +QList DataValidation::ranges() const +{ + return d->ranges; +} + +/*! + Sets the validation type to \a type. + */ +void DataValidation::setValidationType(DataValidation::ValidationType type) +{ + d->validationType = type; +} + +/*! + Sets the validation operator to \a op. + */ +void DataValidation::setValidationOperator(DataValidation::ValidationOperator op) +{ + d->validationOperator = op; +} + +/*! + Sets the error style to \a es. + */ +void DataValidation::setErrorStyle(DataValidation::ErrorStyle es) +{ + d->errorStyle = es; +} + +/*! + Sets the formula1 to \a formula. + */ +void DataValidation::setFormula1(const QString &formula) +{ + if (formula.startsWith(QLatin1Char('='))) + d->formula1 = formula.mid(1); + else + d->formula1 = formula; +} + +/*! + Sets the formulas to \a formula. + */ +void DataValidation::setFormula2(const QString &formula) +{ + if (formula.startsWith(QLatin1Char('='))) + d->formula2 = formula.mid(1); + else + d->formula2 = formula; +} + +/*! + Sets the error message to \a error with title \a title. + */ +void DataValidation::setErrorMessage(const QString &error, const QString &title) +{ + d->errorMessage = error; + d->errorMessageTitle = title; +} + +/*! + Sets the prompt message to \a prompt with title \a title. + */ +void DataValidation::setPromptMessage(const QString &prompt, const QString &title) +{ + d->promptMessage = prompt; + d->promptMessageTitle = title; +} + +/*! + Enable/disabe blank allow based on \a enable. + */ +void DataValidation::setAllowBlank(bool enable) +{ + d->allowBlank = enable; +} + +/*! + Enable/disabe prompt message visible based on \a visible. + */ +void DataValidation::setPromptMessageVisible(bool visible) +{ + d->isPromptMessageVisible = visible; +} + +/*! + Enable/disabe error message visible based on \a visible. + */ +void DataValidation::setErrorMessageVisible(bool visible) +{ + d->isErrorMessageVisible = visible; +} + +/*! + Add the \a cell on which the DataValidation will apply to. + */ +void DataValidation::addCell(const CellReference &cell) +{ + d->ranges.append(CellRange(cell, cell)); +} + +/*! + \overload + Add the cell(\a row, \a col) on which the DataValidation will apply to. + */ +void DataValidation::addCell(int row, int col) +{ + d->ranges.append(CellRange(row, col, row, col)); +} + +/*! + \overload + Add the range(\a firstRow, \a firstCol, \a lastRow, \a lastCol) on + which the DataValidation will apply to. + */ +void DataValidation::addRange(int firstRow, int firstCol, int lastRow, int lastCol) +{ + d->ranges.append(CellRange(firstRow, firstCol, lastRow, lastCol)); +} + +/*! + Add the \a range on which the DataValidation will apply to. + */ +void DataValidation::addRange(const CellRange &range) +{ + d->ranges.append(range); +} + +/*! + * \internal + */ +bool DataValidation::saveToXml(QXmlStreamWriter &writer) const +{ + static QMap typeMap; + static QMap opMap; + static QMap esMap; + if (typeMap.isEmpty()) { + typeMap.insert(DataValidation::None, QStringLiteral("none")); + typeMap.insert(DataValidation::Whole, QStringLiteral("whole")); + typeMap.insert(DataValidation::Decimal, QStringLiteral("decimal")); + typeMap.insert(DataValidation::List, QStringLiteral("list")); + typeMap.insert(DataValidation::Date, QStringLiteral("date")); + typeMap.insert(DataValidation::Time, QStringLiteral("time")); + typeMap.insert(DataValidation::TextLength, QStringLiteral("textLength")); + typeMap.insert(DataValidation::Custom, QStringLiteral("custom")); + + opMap.insert(DataValidation::Between, QStringLiteral("between")); + opMap.insert(DataValidation::NotBetween, QStringLiteral("notBetween")); + opMap.insert(DataValidation::Equal, QStringLiteral("equal")); + opMap.insert(DataValidation::NotEqual, QStringLiteral("notEqual")); + opMap.insert(DataValidation::LessThan, QStringLiteral("lessThan")); + opMap.insert(DataValidation::LessThanOrEqual, QStringLiteral("lessThanOrEqual")); + opMap.insert(DataValidation::GreaterThan, QStringLiteral("greaterThan")); + opMap.insert(DataValidation::GreaterThanOrEqual, QStringLiteral("greaterThanOrEqual")); + + esMap.insert(DataValidation::Stop, QStringLiteral("stop")); + esMap.insert(DataValidation::Warning, QStringLiteral("warning")); + esMap.insert(DataValidation::Information, QStringLiteral("information")); + } + + writer.writeStartElement(QStringLiteral("dataValidation")); + if (validationType() != DataValidation::None) + writer.writeAttribute(QStringLiteral("type"), typeMap[validationType()]); + if (errorStyle() != DataValidation::Stop) + writer.writeAttribute(QStringLiteral("errorStyle"), esMap[errorStyle()]); + if (validationOperator() != DataValidation::Between) + writer.writeAttribute(QStringLiteral("operator"), opMap[validationOperator()]); + if (allowBlank()) + writer.writeAttribute(QStringLiteral("allowBlank"), QStringLiteral("1")); + // if (dropDownVisible()) + // writer.writeAttribute(QStringLiteral("showDropDown"), QStringLiteral("1")); + if (isPromptMessageVisible()) + writer.writeAttribute(QStringLiteral("showInputMessage"), QStringLiteral("1")); + if (isErrorMessageVisible()) + writer.writeAttribute(QStringLiteral("showErrorMessage"), QStringLiteral("1")); + if (!errorMessageTitle().isEmpty()) + writer.writeAttribute(QStringLiteral("errorTitle"), errorMessageTitle()); + if (!errorMessage().isEmpty()) + writer.writeAttribute(QStringLiteral("error"), errorMessage()); + if (!promptMessageTitle().isEmpty()) + writer.writeAttribute(QStringLiteral("promptTitle"), promptMessageTitle()); + if (!promptMessage().isEmpty()) + writer.writeAttribute(QStringLiteral("prompt"), promptMessage()); + + QStringList sqref; + foreach (CellRange range, ranges()) + sqref.append(range.toString()); + writer.writeAttribute(QStringLiteral("sqref"), sqref.join(QLatin1Char(' '))); + + if (!formula1().isEmpty()) + writer.writeTextElement(QStringLiteral("formula1"), formula1()); + if (!formula2().isEmpty()) + writer.writeTextElement(QStringLiteral("formula2"), formula2()); + + writer.writeEndElement(); //dataValidation + + return true; +} + +/*! + * \internal + */ +DataValidation DataValidation::loadFromXml(QXmlStreamReader &reader) +{ + Q_ASSERT(reader.name() == QLatin1String("dataValidation")); + + static QMap typeMap; + static QMap opMap; + static QMap esMap; + if (typeMap.isEmpty()) { + typeMap.insert(QStringLiteral("none"), DataValidation::None); + typeMap.insert(QStringLiteral("whole"), DataValidation::Whole); + typeMap.insert(QStringLiteral("decimal"), DataValidation::Decimal); + typeMap.insert(QStringLiteral("list"), DataValidation::List); + typeMap.insert(QStringLiteral("date"), DataValidation::Date); + typeMap.insert(QStringLiteral("time"), DataValidation::Time); + typeMap.insert(QStringLiteral("textLength"), DataValidation::TextLength); + typeMap.insert(QStringLiteral("custom"), DataValidation::Custom); + + opMap.insert(QStringLiteral("between"), DataValidation::Between); + opMap.insert(QStringLiteral("notBetween"), DataValidation::NotBetween); + opMap.insert(QStringLiteral("equal"), DataValidation::Equal); + opMap.insert(QStringLiteral("notEqual"), DataValidation::NotEqual); + opMap.insert(QStringLiteral("lessThan"), DataValidation::LessThan); + opMap.insert(QStringLiteral("lessThanOrEqual"), DataValidation::LessThanOrEqual); + opMap.insert(QStringLiteral("greaterThan"), DataValidation::GreaterThan); + opMap.insert(QStringLiteral("greaterThanOrEqual"), DataValidation::GreaterThanOrEqual); + + esMap.insert(QStringLiteral("stop"), DataValidation::Stop); + esMap.insert(QStringLiteral("warning"), DataValidation::Warning); + esMap.insert(QStringLiteral("information"), DataValidation::Information); + } + + DataValidation validation; + QXmlStreamAttributes attrs = reader.attributes(); + + QString sqref = attrs.value(QLatin1String("sqref")).toString(); + foreach (QString range, sqref.split(QLatin1Char(' '))) + validation.addRange(range); + + if (attrs.hasAttribute(QLatin1String("type"))) { + QString t = attrs.value(QLatin1String("type")).toString(); + validation.setValidationType(typeMap.contains(t) ? typeMap[t] : DataValidation::None); + } + if (attrs.hasAttribute(QLatin1String("errorStyle"))) { + QString es = attrs.value(QLatin1String("errorStyle")).toString(); + validation.setErrorStyle(esMap.contains(es) ? esMap[es] : DataValidation::Stop); + } + if (attrs.hasAttribute(QLatin1String("operator"))) { + QString op = attrs.value(QLatin1String("operator")).toString(); + validation.setValidationOperator(opMap.contains(op) ? opMap[op] : DataValidation::Between); + } + if (attrs.hasAttribute(QLatin1String("allowBlank"))) { + validation.setAllowBlank(true); + } else { + validation.setAllowBlank(false); + } + if (attrs.hasAttribute(QLatin1String("showInputMessage"))) { + validation.setPromptMessageVisible(true); + } else { + validation.setPromptMessageVisible(false); + } + if (attrs.hasAttribute(QLatin1String("showErrorMessage"))) { + validation.setErrorMessageVisible(true); + } else { + validation.setErrorMessageVisible(false); + } + + QString et = attrs.value(QLatin1String("errorTitle")).toString(); + QString e = attrs.value(QLatin1String("error")).toString(); + if (!e.isEmpty() || !et.isEmpty()) + validation.setErrorMessage(e, et); + + QString pt = attrs.value(QLatin1String("promptTitle")).toString(); + QString p = attrs.value(QLatin1String("prompt")).toString(); + if (!p.isEmpty() || !pt.isEmpty()) + validation.setPromptMessage(p, pt); + + //find the end + while(!(reader.name() == QLatin1String("dataValidation") && reader.tokenType() == QXmlStreamReader::EndElement)) { + reader.readNextStartElement(); + if (reader.tokenType() == QXmlStreamReader::StartElement) { + if (reader.name() == QLatin1String("formula1")) { + validation.setFormula1(reader.readElementText()); + } else if (reader.name() == QLatin1String("formula2")) { + validation.setFormula2(reader.readElementText()); + } + } + } + return validation; +} + +QT_END_NAMESPACE_XLSX diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdatavalidation.h b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdatavalidation.h new file mode 100644 index 0000000..3a19079 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdatavalidation.h @@ -0,0 +1,123 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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. +** +****************************************************************************/ +#ifndef QXLSX_XLSXDATAVALIDATION_H +#define QXLSX_XLSXDATAVALIDATION_H + +#include "xlsxglobal.h" +#include +#include +#include + +class QXmlStreamReader; +class QXmlStreamWriter; + +QT_BEGIN_NAMESPACE_XLSX + +class Worksheet; +class CellRange; +class CellReference; + +class DataValidationPrivate; +class Q_XLSX_EXPORT DataValidation +{ +public: + enum ValidationType + { + None, + Whole, + Decimal, + List, + Date, + Time, + TextLength, + Custom + }; + + enum ValidationOperator + { + Between, + NotBetween, + Equal, + NotEqual, + LessThan, + LessThanOrEqual, + GreaterThan, + GreaterThanOrEqual + }; + + enum ErrorStyle + { + Stop, + Warning, + Information + }; + + DataValidation(); + DataValidation(ValidationType type, ValidationOperator op=Between, const QString &formula1=QString() + , const QString &formula2=QString(), bool allowBlank=false); + DataValidation(const DataValidation &other); + ~DataValidation(); + + ValidationType validationType() const; + ValidationOperator validationOperator() const; + ErrorStyle errorStyle() const; + QString formula1() const; + QString formula2() const; + bool allowBlank() const; + QString errorMessage() const; + QString errorMessageTitle() const; + QString promptMessage() const; + QString promptMessageTitle() const; + bool isPromptMessageVisible() const; + bool isErrorMessageVisible() const; + QList ranges() const; + + void setValidationType(ValidationType type); + void setValidationOperator(ValidationOperator op); + void setErrorStyle(ErrorStyle es); + void setFormula1(const QString &formula); + void setFormula2(const QString &formula); + void setErrorMessage(const QString &error, const QString &title=QString()); + void setPromptMessage(const QString &prompt, const QString &title=QString()); + void setAllowBlank(bool enable); + void setPromptMessageVisible(bool visible); + void setErrorMessageVisible(bool visible); + + void addCell(const CellReference &cell); + void addCell(int row, int col); + void addRange(int firstRow, int firstCol, int lastRow, int lastCol); + void addRange(const CellRange &range); + + DataValidation &operator=(const DataValidation &other); + + bool saveToXml(QXmlStreamWriter &writer) const; + static DataValidation loadFromXml(QXmlStreamReader &reader); +private: + QSharedDataPointer d; +}; + +QT_END_NAMESPACE_XLSX + +#endif // QXLSX_XLSXDATAVALIDATION_H diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdatavalidation_p.h b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdatavalidation_p.h new file mode 100644 index 0000000..236bb3d --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdatavalidation_p.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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. +** +****************************************************************************/ + +#ifndef XLSXDATAVALIDATION_P_H +#define XLSXDATAVALIDATION_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt Xlsx API. It exists for the convenience +// of the Qt Xlsx. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// + +#include "xlsxdatavalidation.h" +#include + +QT_BEGIN_NAMESPACE_XLSX + +class Q_XLSX_EXPORT DataValidationPrivate : public QSharedData +{ +public: + DataValidationPrivate(); + DataValidationPrivate(DataValidation::ValidationType type, DataValidation::ValidationOperator op, const QString &formula1, const QString &formula2, bool allowBlank); + DataValidationPrivate(const DataValidationPrivate &other); + ~DataValidationPrivate(); + + DataValidation::ValidationType validationType; + DataValidation::ValidationOperator validationOperator; + DataValidation::ErrorStyle errorStyle; + bool allowBlank; + bool isPromptMessageVisible; + bool isErrorMessageVisible; + QString formula1; + QString formula2; + QString errorMessage; + QString errorMessageTitle; + QString promptMessage; + QString promptMessageTitle; + QList ranges; +}; + +QT_END_NAMESPACE_XLSX +#endif // XLSXDATAVALIDATION_P_H diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdocpropsapp.cpp b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdocpropsapp.cpp new file mode 100644 index 0000000..49ad9b2 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdocpropsapp.cpp @@ -0,0 +1,157 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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 "xlsxdocpropsapp_p.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace QXlsx { + +DocPropsApp::DocPropsApp(CreateFlag flag) + :AbstractOOXmlFile(flag) +{ +} + +void DocPropsApp::addPartTitle(const QString &title) +{ + m_titlesOfPartsList.append(title); +} + +void DocPropsApp::addHeadingPair(const QString &name, int value) +{ + m_headingPairsList.append(qMakePair(name, value)); +} + +bool DocPropsApp::setProperty(const QString &name, const QString &value) +{ + static QStringList validKeys; + if (validKeys.isEmpty()) { + validKeys << QStringLiteral("manager") << QStringLiteral("company"); + } + + if (!validKeys.contains(name)) + return false; + + if (value.isEmpty()) + m_properties.remove(name); + else + m_properties[name] = value; + + return true; +} + +QString DocPropsApp::property(const QString &name) const +{ + if (m_properties.contains(name)) + return m_properties[name]; + + return QString(); +} + +QStringList DocPropsApp::propertyNames() const +{ + return m_properties.keys(); +} + +void DocPropsApp::saveToXmlFile(QIODevice *device) const +{ + QXmlStreamWriter writer(device); + QString vt = QStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"); + + writer.writeStartDocument(QStringLiteral("1.0"), true); + writer.writeStartElement(QStringLiteral("Properties")); + writer.writeDefaultNamespace(QStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/extended-properties")); + writer.writeNamespace(vt, QStringLiteral("vt")); + writer.writeTextElement(QStringLiteral("Application"), QStringLiteral("Microsoft Excel")); + writer.writeTextElement(QStringLiteral("DocSecurity"), QStringLiteral("0")); + writer.writeTextElement(QStringLiteral("ScaleCrop"), QStringLiteral("false")); + + writer.writeStartElement(QStringLiteral("HeadingPairs")); + writer.writeStartElement(vt, QStringLiteral("vector")); + writer.writeAttribute(QStringLiteral("size"), QString::number(m_headingPairsList.size()*2)); + writer.writeAttribute(QStringLiteral("baseType"), QStringLiteral("variant")); + typedef QPair PairType; //Make foreach happy + foreach (PairType pair, m_headingPairsList) { + writer.writeStartElement(vt, QStringLiteral("variant")); + writer.writeTextElement(vt, QStringLiteral("lpstr"), pair.first); + writer.writeEndElement(); //vt:variant + writer.writeStartElement(vt, QStringLiteral("variant")); + writer.writeTextElement(vt, QStringLiteral("i4"), QString::number(pair.second)); + writer.writeEndElement(); //vt:variant + } + writer.writeEndElement();//vt:vector + writer.writeEndElement();//HeadingPairs + + writer.writeStartElement(QStringLiteral("TitlesOfParts")); + writer.writeStartElement(vt, QStringLiteral("vector")); + writer.writeAttribute(QStringLiteral("size"), QString::number(m_titlesOfPartsList.size())); + writer.writeAttribute(QStringLiteral("baseType"), QStringLiteral("lpstr")); + foreach (QString title, m_titlesOfPartsList) + writer.writeTextElement(vt, QStringLiteral("lpstr"), title); + writer.writeEndElement();//vt:vector + writer.writeEndElement();//TitlesOfParts + + if (m_properties.contains(QStringLiteral("manager"))) + writer.writeTextElement(QStringLiteral("Manager"), m_properties[QStringLiteral("manager")]); + //Not like "manager", "company" always exists for Excel generated file. + writer.writeTextElement(QStringLiteral("Company"), m_properties.contains(QStringLiteral("company")) ? m_properties[QStringLiteral("company")]: QString()); + writer.writeTextElement(QStringLiteral("LinksUpToDate"), QStringLiteral("false")); + writer.writeTextElement(QStringLiteral("SharedDoc"), QStringLiteral("false")); + writer.writeTextElement(QStringLiteral("HyperlinksChanged"), QStringLiteral("false")); + writer.writeTextElement(QStringLiteral("AppVersion"), QStringLiteral("12.0000")); + + writer.writeEndElement(); //Properties + writer.writeEndDocument(); +} + +bool DocPropsApp::loadFromXmlFile(QIODevice *device) +{ + QXmlStreamReader reader(device); + while (!reader.atEnd()) { + QXmlStreamReader::TokenType token = reader.readNext(); + if (token == QXmlStreamReader::StartElement) { + if (reader.name() == QLatin1String("Properties")) + continue; + + if (reader.name() == QStringLiteral("Manager")) { + setProperty(QStringLiteral("manager"), reader.readElementText()); + } else if (reader.name() == QStringLiteral("Company")) { + setProperty(QStringLiteral("company"), reader.readElementText()); + } + } + + if (reader.hasError()) { + qDebug("Error when read doc props app file."); + } + } + return true; +} + +} //namespace diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdocpropsapp_p.h b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdocpropsapp_p.h new file mode 100644 index 0000000..433731e --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdocpropsapp_p.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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. +** +****************************************************************************/ +#ifndef XLSXDOCPROPSAPP_H +#define XLSXDOCPROPSAPP_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt Xlsx API. It exists for the convenience +// of the Qt Xlsx. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// + +#include "xlsxglobal.h" +#include "xlsxabstractooxmlfile.h" +#include +#include +#include +#include + +class QIODevice; + +namespace QXlsx { + +class XLSX_AUTOTEST_EXPORT DocPropsApp : public AbstractOOXmlFile +{ +public: + DocPropsApp(CreateFlag flag); + + void addPartTitle(const QString &title); + void addHeadingPair(const QString &name, int value); + + bool setProperty(const QString &name, const QString &value); + QString property(const QString &name) const; + QStringList propertyNames() const; + + void saveToXmlFile(QIODevice *device) const; + bool loadFromXmlFile(QIODevice *device); + +private: + QStringList m_titlesOfPartsList; + QList > m_headingPairsList; + QMap m_properties; +}; + +} +#endif // XLSXDOCPROPSAPP_H diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdocpropscore.cpp b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdocpropscore.cpp new file mode 100644 index 0000000..7e955f8 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdocpropscore.cpp @@ -0,0 +1,168 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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 "xlsxdocpropscore_p.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace QXlsx { + +DocPropsCore::DocPropsCore(CreateFlag flag) + :AbstractOOXmlFile(flag) +{ +} + +bool DocPropsCore::setProperty(const QString &name, const QString &value) +{ + static QStringList validKeys; + if (validKeys.isEmpty()) { + validKeys << QStringLiteral("title") << QStringLiteral("subject") + << QStringLiteral("keywords") << QStringLiteral("description") + << QStringLiteral("category") << QStringLiteral("status") + << QStringLiteral("created") << QStringLiteral("creator"); + } + + if (!validKeys.contains(name)) + return false; + + if (value.isEmpty()) + m_properties.remove(name); + else + m_properties[name] = value; + + return true; +} + +QString DocPropsCore::property(const QString &name) const +{ + if (m_properties.contains(name)) + return m_properties[name]; + + return QString(); +} + +QStringList DocPropsCore::propertyNames() const +{ + return m_properties.keys(); +} + +void DocPropsCore::saveToXmlFile(QIODevice *device) const +{ + QXmlStreamWriter writer(device); + const QString cp = QStringLiteral("http://schemas.openxmlformats.org/package/2006/metadata/core-properties"); + const QString dc = QStringLiteral("http://purl.org/dc/elements/1.1/"); + const QString dcterms = QStringLiteral("http://purl.org/dc/terms/"); + const QString dcmitype = QStringLiteral("http://purl.org/dc/dcmitype/"); + const QString xsi = QStringLiteral("http://www.w3.org/2001/XMLSchema-instance"); + writer.writeStartDocument(QStringLiteral("1.0"), true); + writer.writeStartElement(QStringLiteral("cp:coreProperties")); + writer.writeNamespace(cp, QStringLiteral("cp")); + writer.writeNamespace(dc, QStringLiteral("dc")); + writer.writeNamespace(dcterms, QStringLiteral("dcterms")); + writer.writeNamespace(dcmitype, QStringLiteral("dcmitype")); + writer.writeNamespace(xsi, QStringLiteral("xsi")); + + if (m_properties.contains(QStringLiteral("title"))) + writer.writeTextElement(dc, QStringLiteral("title"), m_properties[QStringLiteral("title")]); + + if (m_properties.contains(QStringLiteral("subject"))) + writer.writeTextElement(dc, QStringLiteral("subject"), m_properties[QStringLiteral("subject")]); + + writer.writeTextElement(dc, QStringLiteral("creator"), m_properties.contains(QStringLiteral("creator")) ? m_properties[QStringLiteral("creator")] : QStringLiteral("Qt Xlsx Library")); + + if (m_properties.contains(QStringLiteral("keywords"))) + writer.writeTextElement(cp, QStringLiteral("keywords"), m_properties[QStringLiteral("keywords")]); + + if (m_properties.contains(QStringLiteral("description"))) + writer.writeTextElement(dc, QStringLiteral("description"), m_properties[QStringLiteral("description")]); + + writer.writeTextElement(cp, QStringLiteral("lastModifiedBy"), m_properties.contains(QStringLiteral("creator")) ? m_properties[QStringLiteral("creator")] : QStringLiteral("Qt Xlsx Library")); + + writer.writeStartElement(dcterms, QStringLiteral("created")); + writer.writeAttribute(xsi, QStringLiteral("type"), QStringLiteral("dcterms:W3CDTF")); + writer.writeCharacters(m_properties.contains(QStringLiteral("created")) ? m_properties[QStringLiteral("created")] : QDateTime::currentDateTime().toString(Qt::ISODate)); + writer.writeEndElement();//dcterms:created + + writer.writeStartElement(dcterms, QStringLiteral("modified")); + writer.writeAttribute(xsi, QStringLiteral("type"), QStringLiteral("dcterms:W3CDTF")); + writer.writeCharacters(QDateTime::currentDateTime().toString(Qt::ISODate)); + writer.writeEndElement();//dcterms:created + + if (m_properties.contains(QStringLiteral("category"))) + writer.writeTextElement(cp, QStringLiteral("category"), m_properties[QStringLiteral("category")]); + + if (m_properties.contains(QStringLiteral("status"))) + writer.writeTextElement(cp, QStringLiteral("contentStatus"), m_properties[QStringLiteral("status")]); + + writer.writeEndElement(); //cp:coreProperties + writer.writeEndDocument(); +} + +bool DocPropsCore::loadFromXmlFile(QIODevice *device) +{ + QXmlStreamReader reader(device); + + const QString cp = QStringLiteral("http://schemas.openxmlformats.org/package/2006/metadata/core-properties"); + const QString dc = QStringLiteral("http://purl.org/dc/elements/1.1/"); + const QString dcterms = QStringLiteral("http://purl.org/dc/terms/"); + + while (!reader.atEnd()) { + QXmlStreamReader::TokenType token = reader.readNext(); + if (token == QXmlStreamReader::StartElement) { + const QStringRef nsUri = reader.namespaceUri(); + const QStringRef name = reader.name(); + if (name == QStringLiteral("subject") && nsUri == dc) { + setProperty(QStringLiteral("subject"), reader.readElementText()); + } else if (name == QStringLiteral("title") && nsUri == dc) { + setProperty(QStringLiteral("title"), reader.readElementText()); + } else if (name == QStringLiteral("creator") && nsUri == dc) { + setProperty(QStringLiteral("creator"), reader.readElementText()); + } else if (name == QStringLiteral("description") && nsUri == dc) { + setProperty(QStringLiteral("description"), reader.readElementText()); + } else if (name == QStringLiteral("keywords") && nsUri == cp) { + setProperty(QStringLiteral("keywords"), reader.readElementText()); + } else if (name == QStringLiteral("created") && nsUri == dcterms) { + setProperty(QStringLiteral("created"), reader.readElementText()); + } else if (name == QStringLiteral("category") && nsUri == cp) { + setProperty(QStringLiteral("category"), reader.readElementText()); + } else if (name == QStringLiteral("contentStatus") && nsUri == cp) { + setProperty(QStringLiteral("status"), reader.readElementText()); + } + } + + if (reader.hasError()) { + qDebug()<<"Error when read doc props core file."< +** 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. +** +****************************************************************************/ +#ifndef XLSXDOCPROPSCORE_H +#define XLSXDOCPROPSCORE_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt Xlsx API. It exists for the convenience +// of the Qt Xlsx. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// + +#include "xlsxglobal.h" +#include "xlsxabstractooxmlfile.h" +#include +#include + +class QIODevice; + +namespace QXlsx { + +class XLSX_AUTOTEST_EXPORT DocPropsCore : public AbstractOOXmlFile +{ +public: + explicit DocPropsCore(CreateFlag flag); + + bool setProperty(const QString &name, const QString &value); + QString property(const QString &name) const; + QStringList propertyNames() const; + + void saveToXmlFile(QIODevice *device) const; + bool loadFromXmlFile(QIODevice *device); + +private: + QMap m_properties; +}; + +} +#endif // XLSXDOCPROPSCORE_H diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdocument.cpp b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdocument.cpp new file mode 100644 index 0000000..314e789 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdocument.cpp @@ -0,0 +1,1046 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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 "xlsxdocument.h" +#include "xlsxdocument_p.h" +#include "xlsxworkbook.h" +#include "xlsxworksheet.h" +#include "xlsxcontenttypes_p.h" +#include "xlsxrelationships_p.h" +#include "xlsxstyles_p.h" +#include "xlsxtheme_p.h" +#include "xlsxdocpropsapp_p.h" +#include "xlsxdocpropscore_p.h" +#include "xlsxsharedstrings_p.h" +#include "xlsxutility_p.h" +#include "xlsxworkbook_p.h" +#include "xlsxdrawing_p.h" +#include "xlsxmediafile_p.h" +#include "xlsxchart.h" +#include "xlsxzipreader_p.h" +#include "xlsxzipwriter_p.h" + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE_XLSX + +/* + From Wikipedia: The Open Packaging Conventions (OPC) is a + container-file technology initially created by Microsoft to store + a combination of XML and non-XML files that together form a single + entity such as an Open XML Paper Specification (OpenXPS) + document. http://en.wikipedia.org/wiki/Open_Packaging_Conventions. + + At its simplest an Excel XLSX file contains the following elements: + + ____ [Content_Types].xml + | + |____ docProps + | |____ app.xml + | |____ core.xml + | + |____ xl + | |____ workbook.xml + | |____ worksheets + | | |____ sheet1.xml + | | + | |____ styles.xml + | | + | |____ theme + | | |____ theme1.xml + | | + | |_____rels + | |____ workbook.xml.rels + | + |_____rels + |____ .rels + + The Packager class coordinates the classes that represent the + elements of the package and writes them into the XLSX file. +*/ + +DocumentPrivate::DocumentPrivate(Document *p) : + q_ptr(p), defaultPackageName(QStringLiteral("Book1.xlsx")) +{ +} + +void DocumentPrivate::init() +{ + if (contentTypes.isNull()) + contentTypes = QSharedPointer(new ContentTypes(ContentTypes::F_NewFromScratch)); + + if (workbook.isNull()) + workbook = QSharedPointer(new Workbook(Workbook::F_NewFromScratch)); +} + +bool DocumentPrivate::loadPackage(QIODevice *device) +{ + Q_Q(Document); + ZipReader zipReader(device); + QStringList filePaths = zipReader.filePaths(); + + //Load the Content_Types file + if (!filePaths.contains(QLatin1String("[Content_Types].xml"))) + return false; + contentTypes = QSharedPointer(new ContentTypes(ContentTypes::F_LoadFromExists)); + contentTypes->loadFromXmlData(zipReader.fileData(QStringLiteral("[Content_Types].xml"))); + + //Load root rels file + if (!filePaths.contains(QLatin1String("_rels/.rels"))) + return false; + Relationships rootRels; + rootRels.loadFromXmlData(zipReader.fileData(QStringLiteral("_rels/.rels"))); + + //load core property + QList rels_core = rootRels.packageRelationships(QStringLiteral("/metadata/core-properties")); + if (!rels_core.isEmpty()) { + //Get the core property file name if it exists. + //In normal case, this should be "docProps/core.xml" + QString docPropsCore_Name = rels_core[0].target; + + DocPropsCore props(DocPropsCore::F_LoadFromExists); + props.loadFromXmlData(zipReader.fileData(docPropsCore_Name)); + foreach (QString name, props.propertyNames()) + q->setDocumentProperty(name, props.property(name)); + } + + //load app property + QList rels_app = rootRels.documentRelationships(QStringLiteral("/extended-properties")); + if (!rels_app.isEmpty()) { + //Get the app property file name if it exists. + //In normal case, this should be "docProps/app.xml" + QString docPropsApp_Name = rels_app[0].target; + + DocPropsApp props(DocPropsApp::F_LoadFromExists); + props.loadFromXmlData(zipReader.fileData(docPropsApp_Name)); + foreach (QString name, props.propertyNames()) + q->setDocumentProperty(name, props.property(name)); + } + + //load workbook now, Get the workbook file path from the root rels file + //In normal case, this should be "xl/workbook.xml" + workbook = QSharedPointer(new Workbook(Workbook::F_LoadFromExists)); + QList rels_xl = rootRels.documentRelationships(QStringLiteral("/officeDocument")); + if (rels_xl.isEmpty()) + return false; + QString xlworkbook_Path = rels_xl[0].target; + QString xlworkbook_Dir = splitPath(xlworkbook_Path)[0]; + workbook->relationships()->loadFromXmlData(zipReader.fileData(getRelFilePath(xlworkbook_Path))); + workbook->setFilePath(xlworkbook_Path); + workbook->loadFromXmlData(zipReader.fileData(xlworkbook_Path)); + + //load styles + QList rels_styles = workbook->relationships()->documentRelationships(QStringLiteral("/styles")); + if (!rels_styles.isEmpty()) { + //In normal case this should be styles.xml which in xl + QString name = rels_styles[0].target; + QString path = xlworkbook_Dir + QLatin1String("/") + name; + QSharedPointer styles (new Styles(Styles::F_LoadFromExists)); + styles->loadFromXmlData(zipReader.fileData(path)); + workbook->d_func()->styles = styles; + } + + //load sharedStrings + QList rels_sharedStrings = workbook->relationships()->documentRelationships(QStringLiteral("/sharedStrings")); + if (!rels_sharedStrings.isEmpty()) { + //In normal case this should be sharedStrings.xml which in xl + QString name = rels_sharedStrings[0].target; + QString path = xlworkbook_Dir + QLatin1String("/") + name; + workbook->d_func()->sharedStrings->loadFromXmlData(zipReader.fileData(path)); + } + + //load theme + QList rels_theme = workbook->relationships()->documentRelationships(QStringLiteral("/theme")); + if (!rels_theme.isEmpty()) { + //In normal case this should be theme/theme1.xml which in xl + QString name = rels_theme[0].target; + QString path = xlworkbook_Dir + QLatin1String("/") + name; + workbook->theme()->loadFromXmlData(zipReader.fileData(path)); + } + + //load sheets + for (int i=0; isheetCount(); ++i) { + AbstractSheet *sheet = workbook->sheet(i); + QString rel_path = getRelFilePath(sheet->filePath()); + //If the .rel file exists, load it. + if (zipReader.filePaths().contains(rel_path)) + sheet->relationships()->loadFromXmlData(zipReader.fileData(rel_path)); + sheet->loadFromXmlData(zipReader.fileData(sheet->filePath())); + } + + //load external links + for (int i=0; id_func()->externalLinks.count(); ++i) { + SimpleOOXmlFile *link = workbook->d_func()->externalLinks[i].data(); + QString rel_path = getRelFilePath(link->filePath()); + //If the .rel file exists, load it. + if (zipReader.filePaths().contains(rel_path)) + link->relationships()->loadFromXmlData(zipReader.fileData(rel_path)); + link->loadFromXmlData(zipReader.fileData(link->filePath())); + } + + //load drawings + for (int i=0; idrawings().size(); ++i) { + Drawing *drawing = workbook->drawings()[i]; + QString rel_path = getRelFilePath(drawing->filePath()); + if (zipReader.filePaths().contains(rel_path)) + drawing->relationships()->loadFromXmlData(zipReader.fileData(rel_path)); + drawing->loadFromXmlData(zipReader.fileData(drawing->filePath())); + } + + //load charts + QList > chartFileToLoad = workbook->chartFiles(); + for (int i=0; i cf = chartFileToLoad[i]; + cf->loadFromXmlData(zipReader.fileData(cf->filePath())); + } + + //load media files + QList > mediaFileToLoad = workbook->mediaFiles(); + for (int i=0; i mf = mediaFileToLoad[i]; + const QString path = mf->fileName(); + const QString suffix = path.mid(path.lastIndexOf(QLatin1Char('.'))+1); + mf->set(zipReader.fileData(path), suffix); + } + + return true; +} + +bool DocumentPrivate::savePackage(QIODevice *device) const +{ + Q_Q(const Document); + ZipWriter zipWriter(device); + if (zipWriter.error()) + return false; + + contentTypes->clearOverrides(); + + DocPropsApp docPropsApp(DocPropsApp::F_NewFromScratch); + DocPropsCore docPropsCore(DocPropsCore::F_NewFromScratch); + + // 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 + for (int i=0; id_func()->externalLinks.count(); ++i) { + SimpleOOXmlFile *link = workbook->d_func()->externalLinks[i].data(); + contentTypes->addExternalLinkName(QStringLiteral("externalLink%1").arg(i+1)); + + zipWriter.addFile(QStringLiteral("xl/externalLinks/externalLink%1.xml").arg(i+1), link->saveToXmlData()); + Relationships *rel = link->relationships(); + if (!rel->isEmpty()) + zipWriter.addFile(QStringLiteral("xl/externalLinks/_rels/externalLink%1.xml.rels").arg(i+1), rel->saveToXmlData()); + } + + // save workbook xml file + contentTypes->addWorkbook(); + zipWriter.addFile(QStringLiteral("xl/workbook.xml"), workbook->saveToXmlData()); + zipWriter.addFile(QStringLiteral("xl/_rels/workbook.xml.rels"), workbook->relationships()->saveToXmlData()); + + // save drawing xml files + for (int i=0; idrawings().size(); ++i) { + contentTypes->addDrawingName(QStringLiteral("drawing%1").arg(i+1)); + + Drawing *drawing = workbook->drawings()[i]; + zipWriter.addFile(QStringLiteral("xl/drawings/drawing%1.xml").arg(i+1), drawing->saveToXmlData()); + if (!drawing->relationships()->isEmpty()) + zipWriter.addFile(QStringLiteral("xl/drawings/_rels/drawing%1.xml.rels").arg(i+1), drawing->relationships()->saveToXmlData()); + } + + // save docProps app/core xml file + foreach (QString name, q->documentPropertyNames()) { + docPropsApp.setProperty(name, q->documentProperty(name)); + docPropsCore.setProperty(name, q->documentProperty(name)); + } + contentTypes->addDocPropApp(); + contentTypes->addDocPropCore(); + zipWriter.addFile(QStringLiteral("docProps/app.xml"), docPropsApp.saveToXmlData()); + zipWriter.addFile(QStringLiteral("docProps/core.xml"), docPropsCore.saveToXmlData()); + + // save sharedStrings xml file + if (!workbook->sharedStrings()->isEmpty()) { + contentTypes->addSharedString(); + zipWriter.addFile(QStringLiteral("xl/sharedStrings.xml"), workbook->sharedStrings()->saveToXmlData()); + } + + // save styles xml file + contentTypes->addStyles(); + zipWriter.addFile(QStringLiteral("xl/styles.xml"), workbook->styles()->saveToXmlData()); + + // save theme xml file + contentTypes->addTheme(); + zipWriter.addFile(QStringLiteral("xl/theme/theme1.xml"), workbook->theme()->saveToXmlData()); + + // save chart xml files + for (int i=0; ichartFiles().size(); ++i) { + contentTypes->addChartName(QStringLiteral("chart%1").arg(i+1)); + QSharedPointer cf = workbook->chartFiles()[i]; + zipWriter.addFile(QStringLiteral("xl/charts/chart%1.xml").arg(i+1), cf->saveToXmlData()); + } + + // save image files + for (int i=0; imediaFiles().size(); ++i) { + QSharedPointer mf = workbook->mediaFiles()[i]; + if (!mf->mimeType().isEmpty()) + contentTypes->addDefault(mf->suffix(), mf->mimeType()); + + zipWriter.addFile(QStringLiteral("xl/media/image%1.%2").arg(i+1).arg(mf->suffix()), mf->contents()); + } + + // save root .rels xml file + Relationships rootrels; + rootrels.addDocumentRelationship(QStringLiteral("/officeDocument"), QStringLiteral("xl/workbook.xml")); + rootrels.addPackageRelationship(QStringLiteral("/metadata/core-properties"), QStringLiteral("docProps/core.xml")); + rootrels.addDocumentRelationship(QStringLiteral("/extended-properties"), QStringLiteral("docProps/app.xml")); + zipWriter.addFile(QStringLiteral("_rels/.rels"), rootrels.saveToXmlData()); + + // save content types xml file + zipWriter.addFile(QStringLiteral("[Content_Types].xml"), contentTypes->saveToXmlData()); + + zipWriter.close(); + return true; +} + + +/*! + \class Document + \inmodule QtXlsx + \brief The Document class provides a API that is used to handle the contents of .xlsx files. + +*/ + +/*! + * Creates a new empty xlsx document. + * The \a parent argument is passed to QObject's constructor. + */ +Document::Document(QObject *parent) : + QObject(parent), d_ptr(new DocumentPrivate(this)) +{ + d_ptr->init(); +} + +/*! + * \overload + * Try to open an existing xlsx document named \a name. + * The \a parent argument is passed to QObject's constructor. + */ +Document::Document(const QString &name, QObject *parent) : + QObject(parent), d_ptr(new DocumentPrivate(this)) +{ + d_ptr->packageName = name; + if (QFile::exists(name)) { + QFile xlsx(name); + if (xlsx.open(QFile::ReadOnly)) + d_ptr->loadPackage(&xlsx); + } + d_ptr->init(); +} + +/*! + * \overload + * Try to open an existing xlsx document from \a device. + * The \a parent argument is passed to QObject's constructor. + */ +Document::Document(QIODevice *device, QObject *parent) : + QObject(parent), d_ptr(new DocumentPrivate(this)) +{ + if (device && device->isReadable()) + d_ptr->loadPackage(device); + d_ptr->init(); +} + +/*! + \overload + + Write \a value to cell \a row_column with the given \a format. + */ +bool Document::write(const CellReference &row_column, const QVariant &value, const Format &format) +{ + if (Worksheet *sheet = currentWorksheet()) + return sheet->write(row_column, value, format); + return false; +} + +/*! + * Write \a value to cell (\a row, \a col) with the \a format. + * Returns true on success. + */ +bool Document::write(int row, int col, const QVariant &value, const Format &format) +{ + if (Worksheet *sheet = currentWorksheet()) + return sheet->write(row, col, value, format); + return false; +} + +/*! + \overload + Returns the contents of the cell \a cell. + + \sa cellAt() +*/ +QVariant Document::read(const CellReference &cell) const +{ + if (Worksheet *sheet = currentWorksheet()) + return sheet->read(cell); + return QVariant(); +} + +/*! + Returns the contents of the cell (\a row, \a col). + + \sa cellAt() + */ +QVariant Document::read(int row, int col) const +{ + if (Worksheet *sheet = currentWorksheet()) + return sheet->read(row, col); + return QVariant(); +} + +/*! + * Insert an \a image to current active worksheet at the position \a row, \a column + * Returns ture if success. + */ +bool Document::insertImage(int row, int column, const QImage &image) +{ + if (Worksheet *sheet = currentWorksheet()) + return sheet->insertImage(row, column, image); + return false; +} + +/*! + * Creates an chart with the given \a size and insert it to the current + * active worksheet at the position \a row, \a col. + * The chart will be returned. + */ +Chart *Document::insertChart(int row, int col, const QSize &size) +{ + if (Worksheet *sheet = currentWorksheet()) + return sheet->insertChart(row, col, size); + return 0; +} + +/*! + Merge a \a range of cells. The first cell should contain the data and the others should + be blank. All cells will be applied the same style if a valid \a format is given. + Returns true on success. + + \note All cells except the top-left one will be cleared. + */ +bool Document::mergeCells(const CellRange &range, const Format &format) +{ + if (Worksheet *sheet = currentWorksheet()) + return sheet->mergeCells(range, format); + return false; +} + +/*! + Unmerge the cells in the \a range. + Returns true on success. +*/ +bool Document::unmergeCells(const CellRange &range) +{ + if (Worksheet *sheet = currentWorksheet()) + return sheet->unmergeCells(range); + return false; +} + +/*! + Sets width in characters of columns with the given \a range and \a width. + Returns true on success. + */ +bool Document::setColumnWidth(const CellRange &range, double width) +{ + if (Worksheet *sheet = currentWorksheet()) + return sheet->setColumnWidth(range, width); + return false; +} + +/*! + Sets format property of columns with the gien \a range and \a format. + Returns true on success. + */ +bool Document::setColumnFormat(const CellRange &range, const Format &format) +{ + if (Worksheet *sheet = currentWorksheet()) + return sheet->setColumnFormat(range, format); + return false; +} + +/*! + Sets hidden property of columns \a range to \a hidden. Columns are 1-indexed. + Hidden columns are not visible. + Returns true on success. + */ +bool Document::setColumnHidden(const CellRange &range, bool hidden) +{ + if (Worksheet *sheet = currentWorksheet()) + return sheet->setColumnWidth(range, hidden); + return false; +} + +/*! + Sets width in characters \a column to \a width. Columns are 1-indexed. + Returns true on success. + */ +bool Document::setColumnWidth(int column, double width) +{ + return setColumnWidth(column,column,width); +} + +/*! + Sets format property \a column to \a format. Columns are 1-indexed. + Returns true on success. + */ +bool Document::setColumnFormat(int column, const Format &format) +{ + return setColumnFormat(column,column,format); +} + +/*! + Sets hidden property of a \a column. Columns are 1-indexed. + Returns true on success. + */ +bool Document::setColumnHidden(int column, bool hidden) +{ + return setColumnHidden(column,column,hidden); +} + +/*! + Sets width in characters for columns [\a colFirst, \a colLast]. Columns are 1-indexed. + Returns true on success. + */ +bool Document::setColumnWidth(int colFirst, int colLast, double width) +{ + if (Worksheet *sheet = currentWorksheet()) + return sheet->setColumnWidth(colFirst, colLast, width); + return false; +} + +/*! + Sets format property of columns [\a colFirst, \a colLast] to \a format. + Columns are 1-indexed. + Returns true on success. + */ +bool Document::setColumnFormat(int colFirst, int colLast, const Format &format) +{ + if (Worksheet *sheet = currentWorksheet()) + return sheet->setColumnFormat(colFirst, colLast, format); + return false; +} + + +/*! + Sets hidden property of columns [\a colFirst, \a colLast] to \a hidden. + Columns are 1-indexed. + Returns true on success. + */ +bool Document::setColumnHidden(int colFirst, int colLast, bool hidden) +{ + if (Worksheet *sheet = currentWorksheet()) + return sheet->setColumnHidden(colFirst, colLast, hidden); + return false; +} + +/*! + Returns width of the \a column in characters of the normal font. + Columns are 1-indexed. + Returns true on success. + */ +double Document::columnWidth(int column) +{ + if (Worksheet *sheet = currentWorksheet()) + return sheet->columnWidth(column); + return 0.0; +} + +/*! + Returns formatting of the \a column. Columns are 1-indexed. + */ +Format Document::columnFormat(int column) +{ + if (Worksheet *sheet = currentWorksheet()) + return sheet->columnFormat(column); + return Format(); +} + +/*! + Returns true if \a column is hidden. Columns are 1-indexed. + */ +bool Document::isColumnHidden(int column) +{ + if (Worksheet *sheet = currentWorksheet()) + return sheet->isColumnHidden(column); + return false; +} + +/*! + Sets the \a format of the \a row. + Rows are 1-indexed. + + Returns true if success. +*/ +bool Document::setRowFormat(int row, const Format &format) +{ + return setRowFormat(row,row, format); +} + +/*! + Sets the \a format of the rows including and between \a rowFirst and \a rowLast. + Rows are 1-indexed. + + Returns true if success. +*/ +bool Document::setRowFormat(int rowFirst, int rowLast, const Format &format) +{ + if (Worksheet *sheet = currentWorksheet()) + return sheet->setRowFormat(rowFirst, rowLast, format); + return false; +} + +/*! + Sets the \a hidden property of the row \a row. + Rows are 1-indexed. If hidden is true rows will not be visible. + + Returns true if success. +*/ +bool Document::setRowHidden(int row, bool hidden) +{ + return setRowHidden(row,row,hidden); +} + +/*! + Sets the \a hidden property of the rows including and between \a rowFirst and \a rowLast. + Rows are 1-indexed. If hidden is true rows will not be visible. + + Returns true if success. +*/ +bool Document::setRowHidden(int rowFirst, int rowLast, bool hidden) +{ + if (Worksheet *sheet = currentWorksheet()) + return sheet->setRowHidden(rowFirst, rowLast, hidden); + return false; +} + +/*! + Sets the \a height of the row \a row. + Row height measured in point size. + Rows are 1-indexed. + + Returns true if success. +*/ +bool Document::setRowHeight(int row, double height) +{ + return setRowHeight(row,row,height); +} + +/*! + Sets the \a height of the rows including and between \a rowFirst and \a rowLast. + Row height measured in point size. + Rows are 1-indexed. + + Returns true if success. +*/ +bool Document::setRowHeight(int rowFirst, int rowLast, double height) +{ + if (Worksheet *sheet = currentWorksheet()) + return sheet->setRowHeight(rowFirst, rowLast, height); + return false; +} + +/*! + Returns height of \a row in points. +*/ +double Document::rowHeight(int row) +{ + if (Worksheet *sheet = currentWorksheet()) + return sheet->rowHeight(row); + return 0.0; +} + +/*! + Returns format of \a row. +*/ +Format Document::rowFormat(int row) +{ + if (Worksheet *sheet = currentWorksheet()) + return sheet->rowFormat(row); + return Format(); +} + +/*! + Returns true if \a row is hidden. +*/ +bool Document::isRowHidden(int row) +{ + if (Worksheet *sheet = currentWorksheet()) + return sheet->isRowHidden(row); + return false; +} + +/*! + Groups rows from \a rowFirst to \a rowLast with the given \a collapsed. + Returns false if error occurs. + */ +bool Document::groupRows(int rowFirst, int rowLast, bool collapsed) +{ + if (Worksheet *sheet = currentWorksheet()) + return sheet->groupRows(rowFirst, rowLast, collapsed); + return false; +} + +/*! + Groups columns from \a colFirst to \a colLast with the given \a collapsed. + Returns false if error occurs. + */ +bool Document::groupColumns(int colFirst, int colLast, bool collapsed) +{ + if (Worksheet *sheet = currentWorksheet()) + return sheet->groupColumns(colFirst, colLast, collapsed); + return false; +} + +/*! + * Add a data \a validation rule for current worksheet. Returns true if successful. + */ +bool Document::addDataValidation(const DataValidation &validation) +{ + if (Worksheet *sheet = currentWorksheet()) + return sheet->addDataValidation(validation); + return false; +} + +/*! + * Add a conditional formatting \a cf for current worksheet. Returns true if successful. + */ +bool Document::addConditionalFormatting(const ConditionalFormatting &cf) +{ + if (Worksheet *sheet = currentWorksheet()) + return sheet->addConditionalFormatting(cf); + return false; +} + +/*! + * \overload + * Returns the cell at the position \a pos. If there is no cell at + * the specified position, the function returns 0. + * + * \sa read() + */ +Cell *Document::cellAt(const CellReference &pos) const +{ + if (Worksheet *sheet = currentWorksheet()) + return sheet->cellAt(pos); + return 0; +} + +/*! + * Returns the cell at the given \a row and \a col. If there + * is no cell at the specified position, the function returns 0. + * + * \sa read() + */ +Cell *Document::cellAt(int row, int col) const +{ + if (Worksheet *sheet = currentWorksheet()) + return sheet->cellAt(row, col); + return 0; +} + +/*! + * \brief Create a defined name in the workbook with the given \a name, \a formula, \a comment + * and \a scope. + * + * \param name The defined name. + * \param formula The cell or range that the defined name refers to. + * \param scope The name of one worksheet, or empty which means golbal scope. + * \return Return false if the name invalid. + */ +bool Document::defineName(const QString &name, const QString &formula, const QString &comment, const QString &scope) +{ + Q_D(Document); + + return d->workbook->defineName(name, formula, comment, scope); +} + +/*! + Return the range that contains cell data. + */ +CellRange Document::dimension() const +{ + if (Worksheet *sheet = currentWorksheet()) + return sheet->dimension(); + return CellRange(); +} + +/*! + * Returns the value of the document's \a key property. + */ +QString Document::documentProperty(const QString &key) const +{ + Q_D(const Document); + if (d->documentProperties.contains(key)) + return d->documentProperties[key]; + else + return QString(); +} + +/*! + Set the document properties such as Title, Author etc. + + The method can be used to set the document properties of the Excel + file created by Qt Xlsx. These properties are visible when you use the + Office Button -> Prepare -> Properties option in Excel and are also + available to external applications that read or index windows files. + + The \a property \a key that can be set are: + + \list + \li title + \li subject + \li creator + \li manager + \li company + \li category + \li keywords + \li description + \li status + \endlist +*/ +void Document::setDocumentProperty(const QString &key, const QString &property) +{ + Q_D(Document); + d->documentProperties[key] = property; +} + +/*! + * Returns the names of all properties that were addedusing setDocumentProperty(). + */ +QStringList Document::documentPropertyNames() const +{ + Q_D(const Document); + return d->documentProperties.keys(); +} + +/*! + * Return the internal Workbook object. + */ +Workbook *Document::workbook() const +{ + Q_D(const Document); + return d->workbook.data(); +} + +/*! + * Returns the sheet object named \a sheetName. + */ +AbstractSheet *Document::sheet(const QString &sheetName) const +{ + Q_D(const Document); + return d->workbook->sheet(sheetNames().indexOf(sheetName)); +} + +/*! + * Creates and append an sheet with the given \a name and \a type. + * Return true if success. + */ +bool Document::addSheet(const QString &name, AbstractSheet::SheetType type) +{ + Q_D(Document); + return d->workbook->addSheet(name, type); +} + +/*! + * Creates and inserts an document with the given \a name and \a type at the \a index. + * Returns false if the \a name already used. + */ +bool Document::insertSheet(int index, const QString &name, AbstractSheet::SheetType type) +{ + Q_D(Document); + return d->workbook->insertSheet(index, name, type); +} + +/*! + Rename the worksheet from \a oldName to \a newName. + Returns true if the success. + */ +bool Document::renameSheet(const QString &oldName, const QString &newName) +{ + Q_D(Document); + if (oldName == newName) + return false; + return d->workbook->renameSheet(sheetNames().indexOf(oldName), newName); +} + +/*! + Make a copy of the worksheet \a srcName with the new name \a distName. + Returns true if the success. + */ +bool Document::copySheet(const QString &srcName, const QString &distName) +{ + Q_D(Document); + if (srcName == distName) + return false; + return d->workbook->copySheet(sheetNames().indexOf(srcName), distName); +} + +/*! + Move the worksheet \a srcName to the new pos \a distIndex. + Returns true if the success. + */ +bool Document::moveSheet(const QString &srcName, int distIndex) +{ + Q_D(Document); + return d->workbook->moveSheet(sheetNames().indexOf(srcName), distIndex); +} + +/*! + Delete the worksheet \a name. + Returns true if current sheet was deleted successfully. + */ +bool Document::deleteSheet(const QString &name) +{ + Q_D(Document); + return d->workbook->deleteSheet(sheetNames().indexOf(name)); +} + +/*! + * \brief Return pointer of current sheet. + */ +AbstractSheet *Document::currentSheet() const +{ + Q_D(const Document); + + return d->workbook->activeSheet(); +} + +/*! + * \brief Return pointer of current worksheet. + * If the type of sheet is not AbstractSheet::ST_WorkSheet, then 0 will be returned. + */ +Worksheet *Document::currentWorksheet() const +{ + AbstractSheet *st = currentSheet(); + if (st && st->sheetType() == AbstractSheet::ST_WorkSheet) + return static_cast(st); + else + return 0; +} + +/*! + * \brief Set worksheet named \a name to be active sheet. + * Returns true if success. + */ +bool Document::selectSheet(const QString &name) +{ + Q_D(Document); + return d->workbook->setActiveSheet(sheetNames().indexOf(name)); +} + +/*! + * Returns the names of worksheets contained in current document. + */ +QStringList Document::sheetNames() const +{ + Q_D(const Document); + return d->workbook->worksheetNames(); +} + +/*! + * Save current document to the filesystem. If no name specified when + * the document constructed, a default name "book1.xlsx" will be used. + * Returns true if saved successfully. + */ +bool Document::save() const +{ + Q_D(const Document); + QString name = d->packageName.isEmpty() ? d->defaultPackageName : d->packageName; + + return saveAs(name); +} + +/*! + * Saves the document to the file with the given \a name. + * Returns true if saved successfully. + */ +bool Document::saveAs(const QString &name) const +{ + QFile file(name); + if (file.open(QIODevice::WriteOnly)) + return saveAs(&file); + return false; +} + +/*! + * \overload + * This function writes a document to the given \a device. + * + * \warning The \a device will be closed when this function returned. + */ +bool Document::saveAs(QIODevice *device) const +{ + Q_D(const Document); + return d->savePackage(device); +} + +/*! + * Destroys the document and cleans up. + */ +Document::~Document() +{ + delete d_ptr; +} + +QT_END_NAMESPACE_XLSX diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdocument.h b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdocument.h new file mode 100644 index 0000000..7f1113d --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdocument.h @@ -0,0 +1,133 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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. +** +****************************************************************************/ + +#ifndef QXLSX_XLSXDOCUMENT_H +#define QXLSX_XLSXDOCUMENT_H + +#include "xlsxglobal.h" +#include "xlsxformat.h" +#include "xlsxworksheet.h" +#include +#include +class QIODevice; +class QImage; + +QT_BEGIN_NAMESPACE_XLSX + +class Workbook; +class Cell; +class CellRange; +class DataValidation; +class ConditionalFormatting; +class Chart; +class CellReference; + +class DocumentPrivate; +class Q_XLSX_EXPORT Document : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(Document) + +public: + explicit Document(QObject *parent = 0); + Document(const QString &xlsxName, QObject *parent=0); + Document(QIODevice *device, QObject *parent=0); + ~Document(); + + bool write(const CellReference &cell, const QVariant &value, const Format &format=Format()); + bool write(int row, int col, const QVariant &value, const Format &format=Format()); + QVariant read(const CellReference &cell) const; + QVariant read(int row, int col) const; + bool insertImage(int row, int col, const QImage &image); + Chart *insertChart(int row, int col, const QSize &size); + bool mergeCells(const CellRange &range, const Format &format=Format()); + bool unmergeCells(const CellRange &range); + + bool setColumnWidth(const CellRange &range, double width); + bool setColumnFormat(const CellRange &range, const Format &format); + bool setColumnHidden(const CellRange &range, bool hidden); + bool setColumnWidth(int column, double width); + bool setColumnFormat(int column, const Format &format); + bool setColumnHidden(int column, bool hidden); + bool setColumnWidth(int colFirst, int colLast, double width); + bool setColumnFormat(int colFirst, int colLast, const Format &format); + bool setColumnHidden(int colFirst, int colLast, bool hidden); + double columnWidth(int column); + Format columnFormat(int column); + bool isColumnHidden(int column); + + bool setRowHeight(int row, double height); + bool setRowFormat(int row, const Format &format); + bool setRowHidden(int row, bool hidden); + bool setRowHeight(int rowFirst, int rowLast, double height); + bool setRowFormat(int rowFirst, int rowLast, const Format &format); + bool setRowHidden(int rowFirst, int rowLast, bool hidden); + + double rowHeight(int row); + Format rowFormat(int row); + bool isRowHidden(int row); + + bool groupRows(int rowFirst, int rowLast, bool collapsed = true); + bool groupColumns(int colFirst, int colLast, bool collapsed = true); + bool addDataValidation(const DataValidation &validation); + bool addConditionalFormatting(const ConditionalFormatting &cf); + + Cell *cellAt(const CellReference &cell) const; + Cell *cellAt(int row, int col) const; + + bool defineName(const QString &name, const QString &formula, const QString &comment=QString(), const QString &scope=QString()); + + CellRange dimension() const; + + QString documentProperty(const QString &name) const; + void setDocumentProperty(const QString &name, const QString &property); + QStringList documentPropertyNames() const; + + QStringList sheetNames() const; + bool addSheet(const QString &name = QString(), AbstractSheet::SheetType type = AbstractSheet::ST_WorkSheet); + bool insertSheet(int index, const QString &name = QString(), AbstractSheet::SheetType type = AbstractSheet::ST_WorkSheet); + bool selectSheet(const QString &name); + bool renameSheet(const QString &oldName, const QString &newName); + bool copySheet(const QString &srcName, const QString &distName = QString()); + bool moveSheet(const QString &srcName, int distIndex); + bool deleteSheet(const QString &name); + + Workbook *workbook() const; + AbstractSheet *sheet(const QString &sheetName) const; + AbstractSheet *currentSheet() const; + Worksheet *currentWorksheet() const; + + bool save() const; + bool saveAs(const QString &xlsXname) const; + bool saveAs(QIODevice *device) const; + +private: + Q_DISABLE_COPY(Document) + DocumentPrivate * const d_ptr; +}; + +QT_END_NAMESPACE_XLSX + +#endif // QXLSX_XLSXDOCUMENT_H diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdocument_p.h b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdocument_p.h new file mode 100644 index 0000000..736a678 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdocument_p.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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. +** +****************************************************************************/ + +#ifndef XLSXDOCUMENT_P_H +#define XLSXDOCUMENT_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt Xlsx API. It exists for the convenience +// of the Qt Xlsx. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// + +#include "xlsxdocument.h" +#include "xlsxworkbook.h" +#include "xlsxcontenttypes_p.h" + +#include + +namespace QXlsx { + +class DocumentPrivate +{ + Q_DECLARE_PUBLIC(Document) +public: + DocumentPrivate(Document *p); + void init(); + + bool loadPackage(QIODevice *device); + bool savePackage(QIODevice *device) const; + + Document *q_ptr; + const QString defaultPackageName; //default name when package name not specified + QString packageName; //name of the .xlsx file + + QMap documentProperties; //core, app and custom properties + QSharedPointer workbook; + QSharedPointer contentTypes; +}; + +} + +#endif // XLSXDOCUMENT_P_H diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdrawing.cpp b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdrawing.cpp new file mode 100644 index 0000000..ae7d2d7 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdrawing.cpp @@ -0,0 +1,87 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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 "xlsxdrawing_p.h" +#include "xlsxdrawinganchor_p.h" +#include "xlsxabstractsheet.h" + +#include +#include +#include + +namespace QXlsx { + +Drawing::Drawing(AbstractSheet *sheet, CreateFlag flag) + :AbstractOOXmlFile(flag), sheet(sheet) +{ + workbook = sheet->workbook(); +} + +Drawing::~Drawing() +{ + qDeleteAll(anchors); +} + +void Drawing::saveToXmlFile(QIODevice *device) const +{ + relationships()->clear(); + + QXmlStreamWriter writer(device); + + writer.writeStartDocument(QStringLiteral("1.0"), true); + writer.writeStartElement(QStringLiteral("xdr:wsDr")); + writer.writeAttribute(QStringLiteral("xmlns:xdr"), QStringLiteral("http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing")); + writer.writeAttribute(QStringLiteral("xmlns:a"), QStringLiteral("http://schemas.openxmlformats.org/drawingml/2006/main")); + + foreach (DrawingAnchor *anchor, anchors) + anchor->saveToXml(writer); + + writer.writeEndElement();//xdr:wsDr + writer.writeEndDocument(); +} + +bool Drawing::loadFromXmlFile(QIODevice *device) +{ + QXmlStreamReader reader(device); + while (!reader.atEnd()) { + reader.readNextStartElement(); + if (reader.tokenType() == QXmlStreamReader::StartElement) { + if (reader.name() == QLatin1String("absoluteAnchor")) { + DrawingAbsoluteAnchor * anchor = new DrawingAbsoluteAnchor(this); + anchor->loadFromXml(reader); + } else if (reader.name() == QLatin1String("oneCellAnchor")) { + DrawingOneCellAnchor * anchor = new DrawingOneCellAnchor(this); + anchor->loadFromXml(reader); + } else if (reader.name() == QLatin1String("twoCellAnchor")) { + DrawingTwoCellAnchor * anchor = new DrawingTwoCellAnchor(this); + anchor->loadFromXml(reader); + } + } + } + + return true; +} + +} // namespace QXlsx diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdrawing_p.h b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdrawing_p.h new file mode 100644 index 0000000..3afad4d --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdrawing_p.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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. +** +****************************************************************************/ + +#ifndef QXLSX_DRAWING_H +#define QXLSX_DRAWING_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt Xlsx API. It exists for the convenience +// of the Qt Xlsx. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// + +#include "xlsxrelationships_p.h" +#include "xlsxabstractooxmlfile.h" + +#include +#include +#include + +class QIODevice; +class QXmlStreamWriter; + +namespace QXlsx { + +class DrawingAnchor; +class Workbook; +class AbstractSheet; +class MediaFile; + +class Drawing : public AbstractOOXmlFile +{ +public: + Drawing(AbstractSheet *sheet, CreateFlag flag); + ~Drawing(); + void saveToXmlFile(QIODevice *device) const; + bool loadFromXmlFile(QIODevice *device); + + AbstractSheet *sheet; + Workbook *workbook; + QList anchors; +}; + +} // namespace QXlsx + +#endif // QXLSX_DRAWING_H diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdrawinganchor.cpp b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdrawinganchor.cpp new file mode 100644 index 0000000..be12dc0 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdrawinganchor.cpp @@ -0,0 +1,529 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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 "xlsxdrawinganchor_p.h" +#include "xlsxdrawing_p.h" +#include "xlsxmediafile_p.h" +#include "xlsxchart.h" +#include "xlsxworkbook.h" +#include "xlsxutility_p.h" + +#include +#include +#include +#include + +namespace QXlsx { + +/* + The vertices that define the position of a graphical object + within the worksheet in pixels. + + +------------+------------+ + | A | B | + +-----+------------+------------+ + | |(x1,y1) | | + | 1 |(A1)._______|______ | + | | | | | + | | | | | + +-----+----| OBJECT |-----+ + | | | | | + | 2 | |______________. | + | | | (B2)| + | | | (x2,y2)| + +---- +------------+------------+ + + Example of an object that covers some of the area from cell A1 to B2. + + Based on the width and height of the object we need to calculate 8 vars: + + col_start, row_start, col_end, row_end, x1, y1, x2, y2. + + We also calculate the absolute x and y position of the top left vertex of + the object. This is required for images. + + The width and height of the cells that the object occupies can be + variable and have to be taken into account. +*/ + +//anchor + +DrawingAnchor::DrawingAnchor(Drawing *drawing, ObjectType objectType) + :m_drawing(drawing), m_objectType(objectType) +{ + m_drawing->anchors.append(this); + m_id = m_drawing->anchors.size();//must be unique in one drawing{x}.xml file. +} + +DrawingAnchor::~DrawingAnchor() +{ + +} + +void DrawingAnchor::setObjectPicture(const QImage &img) +{ + QByteArray ba; + QBuffer buffer(&ba); + buffer.open(QIODevice::WriteOnly); + img.save(&buffer, "PNG"); + + m_pictureFile = QSharedPointer(new MediaFile(ba, QStringLiteral("png"), QStringLiteral("image/png"))); + m_drawing->workbook->addMediaFile(m_pictureFile); + + m_objectType = Picture; +} + +void DrawingAnchor::setObjectGraphicFrame(QSharedPointer chart) +{ + m_chartFile = chart; + m_drawing->workbook->addChartFile(chart); + + m_objectType = GraphicFrame; +} + +QPoint DrawingAnchor::loadXmlPos(QXmlStreamReader &reader) +{ + Q_ASSERT(reader.name() == QLatin1String("pos")); + + QPoint pos; + QXmlStreamAttributes attrs = reader.attributes(); + pos.setX(attrs.value(QLatin1String("x")).toString().toInt()); + pos.setY(attrs.value(QLatin1String("y")).toString().toInt()); + return pos; +} + +QSize DrawingAnchor::loadXmlExt(QXmlStreamReader &reader) +{ + Q_ASSERT(reader.name() == QLatin1String("ext")); + + QSize size; + QXmlStreamAttributes attrs = reader.attributes(); + size.setWidth(attrs.value(QLatin1String("cx")).toString().toInt()); + size.setHeight(attrs.value(QLatin1String("cy")).toString().toInt()); + return size; +} + +XlsxMarker DrawingAnchor::loadXmlMarker(QXmlStreamReader &reader, const QString &node) +{ + Q_ASSERT(reader.name() == node); + + int col = 0; + int colOffset = 0; + int row = 0; + int rowOffset = 0; + while (!reader.atEnd()) { + reader.readNextStartElement(); + if (reader.tokenType() == QXmlStreamReader::StartElement) { + if (reader.name() == QLatin1String("col")) { + col = reader.readElementText().toInt(); + } else if (reader.name() == QLatin1String("colOff")) { + colOffset = reader.readElementText().toInt(); + } else if (reader.name() == QLatin1String("row")) { + row = reader.readElementText().toInt(); + } else if (reader.name() == QLatin1String("rowOff")) { + rowOffset = reader.readElementText().toInt(); + } + } else if (reader.tokenType() == QXmlStreamReader::EndElement + && reader.name() == node) { + break; + } + } + + return XlsxMarker(row, col, rowOffset, colOffset); +} + +void DrawingAnchor::loadXmlObject(QXmlStreamReader &reader) +{ + if (reader.name() == QLatin1String("sp")) { + //Shape + m_objectType = Shape; + loadXmlObjectShape(reader); + } else if (reader.name() == QLatin1String("grpSp")) { + //Group Shape + m_objectType = GroupShape; + loadXmlObjectGroupShape(reader); + } else if (reader.name() == QLatin1String("graphicFrame")) { + //Graphic Frame + m_objectType = GraphicFrame; + loadXmlObjectGraphicFrame(reader); + } else if (reader.name() == QLatin1String("cxnSp")) { + //Connection Shape + m_objectType = ConnectionShape; + loadXmlObjectConnectionShape(reader); + } else if (reader.name() == QLatin1String("pic")) { + //Picture + m_objectType = Picture; + loadXmlObjectPicture(reader); + } +} + +void DrawingAnchor::loadXmlObjectConnectionShape(QXmlStreamReader &reader) +{ + Q_UNUSED(reader) +} + +void DrawingAnchor::loadXmlObjectGraphicFrame(QXmlStreamReader &reader) +{ + Q_ASSERT(reader.name() == QLatin1String("graphicFrame")); + + while (!reader.atEnd()) { + reader.readNextStartElement(); + if (reader.tokenType() == QXmlStreamReader::StartElement) { + if (reader.name() == QLatin1String("chart")) { + QString rId = reader.attributes().value(QLatin1String("r:id")).toString(); + QString name = m_drawing->relationships()->getRelationshipById(rId).target; + QString path = QDir::cleanPath(splitPath(m_drawing->filePath())[0] + QLatin1String("/") + name); + + bool exist = false; + QList > cfs = m_drawing->workbook->chartFiles(); + for (int i=0; ifilePath() == path) { + //already exist + exist = true; + m_chartFile = cfs[i]; + } + } + if (!exist) { + m_chartFile = QSharedPointer (new Chart(m_drawing->sheet, Chart::F_LoadFromExists)); + m_chartFile->setFilePath(path); + m_drawing->workbook->addChartFile(m_chartFile); + } + } + } else if (reader.tokenType() == QXmlStreamReader::EndElement + && reader.name() == QLatin1String("graphicFrame")) { + break; + } + } + + return; +} + +void DrawingAnchor::loadXmlObjectGroupShape(QXmlStreamReader &reader) +{ + Q_UNUSED(reader) +} + +void DrawingAnchor::loadXmlObjectPicture(QXmlStreamReader &reader) +{ + Q_ASSERT(reader.name() == QLatin1String("pic")); + + while (!reader.atEnd()) { + reader.readNextStartElement(); + if (reader.tokenType() == QXmlStreamReader::StartElement) { + if (reader.name() == QLatin1String("blip")) { + QString rId = reader.attributes().value(QLatin1String("r:embed")).toString(); + QString name = m_drawing->relationships()->getRelationshipById(rId).target; + QString path = QDir::cleanPath(splitPath(m_drawing->filePath())[0] + QLatin1String("/") + name); + + bool exist = false; + QList > mfs = m_drawing->workbook->mediaFiles(); + for (int i=0; ifileName() == path) { + //already exist + exist = true; + m_pictureFile = mfs[i]; + } + } + if (!exist) { + m_pictureFile = QSharedPointer (new MediaFile(path)); + m_drawing->workbook->addMediaFile(m_pictureFile, true); + } + } + } else if (reader.tokenType() == QXmlStreamReader::EndElement + && reader.name() == QLatin1String("pic")) { + break; + } + } + + return; +} + +void DrawingAnchor::loadXmlObjectShape(QXmlStreamReader &reader) +{ + Q_UNUSED(reader) +} + +void DrawingAnchor::saveXmlPos(QXmlStreamWriter &writer, const QPoint &pos) const +{ + writer.writeEmptyElement(QStringLiteral("xdr:pos")); + writer.writeAttribute(QStringLiteral("x"), QString::number(pos.x())); + writer.writeAttribute(QStringLiteral("y"), QString::number(pos.y())); +} + +void DrawingAnchor::saveXmlExt(QXmlStreamWriter &writer, const QSize &ext) const +{ + writer.writeStartElement(QStringLiteral("xdr:ext")); + writer.writeAttribute(QStringLiteral("cx"), QString::number(ext.width())); + writer.writeAttribute(QStringLiteral("cy"), QString::number(ext.height())); + writer.writeEndElement(); //xdr:ext +} + +void DrawingAnchor::saveXmlMarker(QXmlStreamWriter &writer, const XlsxMarker &marker, const QString &node) const +{ + writer.writeStartElement(node); //xdr:from or xdr:to + writer.writeTextElement(QStringLiteral("xdr:col"), QString::number(marker.col())); + writer.writeTextElement(QStringLiteral("xdr:colOff"), QString::number(marker.colOff())); + writer.writeTextElement(QStringLiteral("xdr:row"), QString::number(marker.row())); + writer.writeTextElement(QStringLiteral("xdr:rowOff"), QString::number(marker.rowOff())); + writer.writeEndElement(); +} + +void DrawingAnchor::saveXmlObject(QXmlStreamWriter &writer) const +{ + if (m_objectType == Picture) + saveXmlObjectPicture(writer); + else if (m_objectType == ConnectionShape) + saveXmlObjectConnectionShape(writer); + else if (m_objectType == GraphicFrame) + saveXmlObjectGraphicFrame(writer); + else if (m_objectType == GroupShape) + saveXmlObjectGroupShape(writer); + else if (m_objectType == Shape) + saveXmlObjectShape(writer); +} + +void DrawingAnchor::saveXmlObjectConnectionShape(QXmlStreamWriter &writer) const +{ + Q_UNUSED(writer) +} + +void DrawingAnchor::saveXmlObjectGraphicFrame(QXmlStreamWriter &writer) const +{ + writer.writeStartElement(QStringLiteral("xdr:graphicFrame")); + writer.writeAttribute(QStringLiteral("macro"), QString()); + + writer.writeStartElement(QStringLiteral("xdr:nvGraphicFramePr")); + writer.writeEmptyElement(QStringLiteral("xdr:cNvPr")); + writer.writeAttribute(QStringLiteral("id"), QString::number(m_id)); + writer.writeAttribute(QStringLiteral("name"),QStringLiteral("Chart %1").arg(m_id)); + writer.writeEmptyElement(QStringLiteral("xdr:cNvGraphicFramePr")); + writer.writeEndElement();//xdr:nvGraphicFramePr + + writer.writeStartElement(QStringLiteral("xdr:xfrm")); + writer.writeEndElement(); //xdr:xfrm + + writer.writeStartElement(QStringLiteral("a:graphic")); + writer.writeStartElement(QStringLiteral("a:graphicData")); + writer.writeAttribute(QStringLiteral("uri"), QStringLiteral("http://schemas.openxmlformats.org/drawingml/2006/chart")); + + int idx = m_drawing->workbook->chartFiles().indexOf(m_chartFile); + m_drawing->relationships()->addDocumentRelationship(QStringLiteral("/chart"), QStringLiteral("../charts/chart%1.xml").arg(idx+1)); + + writer.writeEmptyElement(QStringLiteral("c:chart")); + writer.writeAttribute(QStringLiteral("xmlns:c"), QStringLiteral("http://schemas.openxmlformats.org/drawingml/2006/chart")); + writer.writeAttribute(QStringLiteral("xmlns:r"), QStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/relationships")); + writer.writeAttribute(QStringLiteral("r:id"), QStringLiteral("rId%1").arg(m_drawing->relationships()->count())); + + writer.writeEndElement(); //a:graphicData + writer.writeEndElement(); //a:graphic + writer.writeEndElement(); //xdr:graphicFrame +} + +void DrawingAnchor::saveXmlObjectGroupShape(QXmlStreamWriter &writer) const +{ + Q_UNUSED(writer) +} + +void DrawingAnchor::saveXmlObjectPicture(QXmlStreamWriter &writer) const +{ + Q_ASSERT(m_objectType == Picture && !m_pictureFile.isNull()); + + writer.writeStartElement(QStringLiteral("xdr:pic")); + + writer.writeStartElement(QStringLiteral("xdr:nvPicPr")); + writer.writeEmptyElement(QStringLiteral("xdr:cNvPr")); + writer.writeAttribute(QStringLiteral("id"), QString::number(m_id)); + writer.writeAttribute(QStringLiteral("name"), QStringLiteral("Picture %1").arg(m_id)); + + writer.writeStartElement(QStringLiteral("xdr:cNvPicPr")); + writer.writeEmptyElement(QStringLiteral("a:picLocks")); + writer.writeAttribute(QStringLiteral("noChangeAspect"), QStringLiteral("1")); + writer.writeEndElement(); //xdr:cNvPicPr + + writer.writeEndElement(); //xdr:nvPicPr + + m_drawing->relationships()->addDocumentRelationship(QStringLiteral("/image"), QStringLiteral("../media/image%1.%2") + .arg(m_pictureFile->index()+1) + .arg(m_pictureFile->suffix())); + + writer.writeStartElement(QStringLiteral("xdr:blipFill")); + writer.writeEmptyElement(QStringLiteral("a:blip")); + writer.writeAttribute(QStringLiteral("xmlns:r"), QStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/relationships")); + writer.writeAttribute(QStringLiteral("r:embed"), QStringLiteral("rId%1").arg(m_drawing->relationships()->count())); + writer.writeStartElement(QStringLiteral("a:stretch")); + writer.writeEmptyElement(QStringLiteral("a:fillRect")); + writer.writeEndElement(); //a:stretch + writer.writeEndElement();//xdr:blipFill + + writer.writeStartElement(QStringLiteral("xdr:spPr")); + + writer.writeStartElement(QStringLiteral("a:prstGeom")); + writer.writeAttribute(QStringLiteral("prst"), QStringLiteral("rect")); + writer.writeEmptyElement(QStringLiteral("a:avLst")); + writer.writeEndElement(); //a:prstGeom + + writer.writeEndElement(); //xdr:spPr + + writer.writeEndElement(); //xdr:pic +} + +void DrawingAnchor::saveXmlObjectShape(QXmlStreamWriter &writer) const +{ + Q_UNUSED(writer) +} + +//absolute anchor + +DrawingAbsoluteAnchor::DrawingAbsoluteAnchor(Drawing *drawing, ObjectType objectType) + :DrawingAnchor(drawing, objectType) +{ + +} + +bool DrawingAbsoluteAnchor::loadFromXml(QXmlStreamReader &reader) +{ + Q_ASSERT(reader.name() == QLatin1String("absoluteAnchor")); + + while (!reader.atEnd()) { + reader.readNextStartElement(); + if (reader.tokenType() == QXmlStreamReader::StartElement) { + if (reader.name() == QLatin1String("pos")) { + pos = loadXmlPos(reader); + } else if (reader.name() == QLatin1String("ext")) { + ext = loadXmlExt(reader); + } else { + loadXmlObject(reader); + } + } else if (reader.tokenType() == QXmlStreamReader::EndElement + && reader.name() == QLatin1String("absoluteAnchor")) { + break; + } + } + return true; +} + +void DrawingAbsoluteAnchor::saveToXml(QXmlStreamWriter &writer) const +{ + writer.writeStartElement(QStringLiteral("xdr:absoluteAnchor")); + saveXmlPos(writer, pos); + saveXmlExt(writer, ext); + + saveXmlObject(writer); + + writer.writeEmptyElement(QStringLiteral("xdr:clientData")); + writer.writeEndElement(); //xdr:absoluteAnchor +} + +//one cell anchor + +DrawingOneCellAnchor::DrawingOneCellAnchor(Drawing *drawing, ObjectType objectType) + :DrawingAnchor(drawing, objectType) +{ + +} + +bool DrawingOneCellAnchor::loadFromXml(QXmlStreamReader &reader) +{ + Q_ASSERT(reader.name() == QLatin1String("oneCellAnchor")); + while (!reader.atEnd()) { + reader.readNextStartElement(); + if (reader.tokenType() == QXmlStreamReader::StartElement) { + if (reader.name() == QLatin1String("from")) { + from = loadXmlMarker(reader, QLatin1String("from")); + } else if (reader.name() == QLatin1String("ext")) { + ext = loadXmlExt(reader); + } else { + loadXmlObject(reader); + } + } else if (reader.tokenType() == QXmlStreamReader::EndElement + && reader.name() == QLatin1String("oneCellAnchor")) { + break; + } + } + return true; +} + +void DrawingOneCellAnchor::saveToXml(QXmlStreamWriter &writer) const +{ + writer.writeStartElement(QStringLiteral("xdr:oneCellAnchor")); + + saveXmlMarker(writer, from, QStringLiteral("xdr:from")); + saveXmlExt(writer, ext); + + saveXmlObject(writer); + + writer.writeEmptyElement(QStringLiteral("xdr:clientData")); + writer.writeEndElement(); //xdr:oneCellAnchor +} + +/* + Two cell anchor + + This class specifies a two cell anchor placeholder for a group + , a shape, or a drawing element. It moves with + cells and its extents are in EMU units. +*/ +DrawingTwoCellAnchor::DrawingTwoCellAnchor(Drawing *drawing, ObjectType objectType) + :DrawingAnchor(drawing, objectType) +{ + +} + +bool DrawingTwoCellAnchor::loadFromXml(QXmlStreamReader &reader) +{ + Q_ASSERT(reader.name() == QLatin1String("twoCellAnchor")); + while (!reader.atEnd()) { + reader.readNextStartElement(); + if (reader.tokenType() == QXmlStreamReader::StartElement) { + if (reader.name() == QLatin1String("from")) { + from = loadXmlMarker(reader, QLatin1String("from")); + } else if (reader.name() == QLatin1String("to")) { + to = loadXmlMarker(reader, QLatin1String("to")); + } else { + loadXmlObject(reader); + } + } else if (reader.tokenType() == QXmlStreamReader::EndElement + && reader.name() == QLatin1String("twoCellAnchor")) { + break; + } + } + return true; +} + +void DrawingTwoCellAnchor::saveToXml(QXmlStreamWriter &writer) const +{ + writer.writeStartElement(QStringLiteral("xdr:twoCellAnchor")); + writer.writeAttribute(QStringLiteral("editAs"), QStringLiteral("oneCell")); + + saveXmlMarker(writer, from, QStringLiteral("xdr:from")); + saveXmlMarker(writer, to, QStringLiteral("xdr:to")); + + saveXmlObject(writer); + + writer.writeEmptyElement(QStringLiteral("xdr:clientData")); + writer.writeEndElement(); //xdr:twoCellAnchor +} + +} // namespace QXlsx diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdrawinganchor_p.h b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdrawinganchor_p.h new file mode 100644 index 0000000..2f38a91 --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxdrawinganchor_p.h @@ -0,0 +1,151 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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. +** +****************************************************************************/ + +#ifndef QXLSX_XLSXDRAWINGANCHOR_P_H +#define QXLSX_XLSXDRAWINGANCHOR_P_H + +#include "xlsxglobal.h" + +#include +#include +#include +#include + +class QXmlStreamReader; +class QXmlStreamWriter; + +namespace QXlsx { + +class Drawing; +class MediaFile; +class Chart; + +//Helper class +struct XlsxMarker +{ + XlsxMarker(){} + XlsxMarker(int row, int column, int rowOffset, int colOffset) + :cell(QPoint(row, column)), offset(rowOffset, colOffset) + { + + } + + int row() const {return cell.x();} + int col() const {return cell.y();} + int rowOff() const {return offset.width();} + int colOff() const {return offset.height();} + + QPoint cell; + QSize offset; +}; + +class DrawingAnchor +{ +public: + enum ObjectType { + GraphicFrame, + Shape, + GroupShape, + ConnectionShape, + Picture, + Unknown + }; + + DrawingAnchor(Drawing *drawing, ObjectType objectType); + virtual ~DrawingAnchor(); + void setObjectPicture(const QImage &img); + void setObjectGraphicFrame(QSharedPointer chart); + + virtual bool loadFromXml(QXmlStreamReader &reader) = 0; + virtual void saveToXml(QXmlStreamWriter &writer) const = 0; + +protected: + QPoint loadXmlPos(QXmlStreamReader &reader); + QSize loadXmlExt(QXmlStreamReader &reader); + XlsxMarker loadXmlMarker(QXmlStreamReader &reader, const QString &node); + void loadXmlObject(QXmlStreamReader &reader); + void loadXmlObjectShape(QXmlStreamReader &reader); + void loadXmlObjectGroupShape(QXmlStreamReader &reader); + void loadXmlObjectGraphicFrame(QXmlStreamReader &reader); + void loadXmlObjectConnectionShape(QXmlStreamReader &reader); + void loadXmlObjectPicture(QXmlStreamReader &reader); + + void saveXmlPos(QXmlStreamWriter &writer, const QPoint &pos) const; + void saveXmlExt(QXmlStreamWriter &writer, const QSize &ext) const; + void saveXmlMarker(QXmlStreamWriter &writer, const XlsxMarker &marker, const QString &node) const; + void saveXmlObject(QXmlStreamWriter &writer) const; + void saveXmlObjectShape(QXmlStreamWriter &writer) const; + void saveXmlObjectGroupShape(QXmlStreamWriter &writer) const; + void saveXmlObjectGraphicFrame(QXmlStreamWriter &writer) const; + void saveXmlObjectConnectionShape(QXmlStreamWriter &writer) const; + void saveXmlObjectPicture(QXmlStreamWriter &writer) const; + + Drawing *m_drawing; + ObjectType m_objectType; + QSharedPointer m_pictureFile; + QSharedPointer m_chartFile; + + int m_id; +}; + +class DrawingAbsoluteAnchor : public DrawingAnchor +{ +public: + DrawingAbsoluteAnchor(Drawing *drawing, ObjectType objectType=Unknown); + + QPoint pos; + QSize ext; + + bool loadFromXml(QXmlStreamReader &reader); + void saveToXml(QXmlStreamWriter &writer) const; +}; + +class DrawingOneCellAnchor : public DrawingAnchor +{ +public: + DrawingOneCellAnchor(Drawing *drawing, ObjectType objectType=Unknown); + + XlsxMarker from; + QSize ext; + + bool loadFromXml(QXmlStreamReader &reader); + void saveToXml(QXmlStreamWriter &writer) const; +}; + +class DrawingTwoCellAnchor : public DrawingAnchor +{ +public: + DrawingTwoCellAnchor(Drawing *drawing, ObjectType objectType=Unknown); + + XlsxMarker from; + XlsxMarker to; + + bool loadFromXml(QXmlStreamReader &reader); + void saveToXml(QXmlStreamWriter &writer) const; +}; + +} // namespace QXlsx + +#endif // QXLSX_XLSXDRAWINGANCHOR_P_H diff --git a/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxformat.cpp b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxformat.cpp new file mode 100644 index 0000000..074184f --- /dev/null +++ b/src/thirdparty/QtXlsxWriter-0.3.0/src/xlsx/xlsxformat.cpp @@ -0,0 +1,1432 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** 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 "xlsxformat.h" +#include "xlsxformat_p.h" +#include "xlsxcolor_p.h" +#include "xlsxnumformatparser_p.h" +#include +#include + +QT_BEGIN_NAMESPACE_XLSX + +FormatPrivate::FormatPrivate() + : dirty(true) + , font_dirty(true), font_index_valid(false), font_index(0) + , fill_dirty(true), fill_index_valid(false), fill_index(0) + , border_dirty(true), border_index_valid(false), border_index(0) + , xf_index(-1), xf_indexValid(false) + , is_dxf_fomat(false), dxf_index(-1), dxf_indexValid(false) + , theme(0) +{ +} + +FormatPrivate::FormatPrivate(const FormatPrivate &other) + : QSharedData(other) + , dirty(other.dirty), formatKey(other.formatKey) + , font_dirty(other.font_dirty), font_index_valid(other.font_index_valid), font_key(other.font_key), font_index(other.font_index) + , fill_dirty(other.fill_dirty), fill_index_valid(other.fill_index_valid), fill_key(other.fill_key), fill_index(other.fill_index) + , border_dirty(other.border_dirty), border_index_valid(other.border_index_valid), border_key(other.border_key), border_index(other.border_index) + , xf_index(other.xf_index), xf_indexValid(other.xf_indexValid) + , is_dxf_fomat(other.is_dxf_fomat), dxf_index(other.dxf_index), dxf_indexValid(other.dxf_indexValid) + , theme(other.theme) + , properties(other.properties) +{ + +} + +FormatPrivate::~FormatPrivate() +{ + +} + +/*! + * \class Format + * \inmodule QtXlsx + * \brief Providing the methods and properties that are available for formatting cells in Excel. + */ + +/*! + * \enum Format::FontScript + * + * The enum type defines the type of font script. + * + * \value FontScriptNormal normal + * \value FontScriptSuper super script + * \value FontScriptSub sub script + */ + + +/*! + * \enum Format::FontUnderline + * + * The enum type defines the type of font underline. + * + * \value FontUnderlineNone + * \value FontUnderlineSingle + * \value FontUnderlineDouble + * \value FontUnderlineSingleAccounting + * \value FontUnderlineDoubleAccounting + */ + +/*! + * \enum Format::HorizontalAlignment + * + * The enum type defines the type of horizontal alignment. + * + * \value AlignHGeneral + * \value AlignLeft + * \value AlignHCenter + * \value AlignRight + * \value AlignHFill + * \value AlignHJustify + * \value AlignHMerge + * \value AlignHDistributed + */ + +/*! + * \enum Format::VerticalAlignment + * + * The enum type defines the type of vertical alignment. + * + * \value AlignTop, + * \value AlignVCenter, + * \value AlignBottom, + * \value AlignVJustify, + * \value AlignVDistributed + */ + +/*! + * \enum Format::BorderStyle + * + * The enum type defines the type of font underline. + * + * \value BorderNone + * \value BorderThin + * \value BorderMedium + * \value BorderDashed + * \value BorderDotted + * \value BorderThick + * \value BorderDouble + * \value BorderHair + * \value BorderMediumDashed + * \value BorderDashDot + * \value BorderMediumDashDot + * \value BorderDashDotDot + * \value BorderMediumDashDotDot + * \value BorderSlantDashDot +*/ + +/*! + * \enum Format::DiagonalBorderType + * + * The enum type defines the type of diagonal border. + * + * \value DiagonalBorderNone + * \value DiagonalBorderDown + * \value DiagonalBorderUp + * \value DiagnoalBorderBoth + */ + +/*! + * \enum Format::FillPattern + * + * The enum type defines the type of fill. + * + * \value PatternNone + * \value PatternSolid + * \value PatternMediumGray + * \value PatternDarkGray + * \value PatternLightGray + * \value PatternDarkHorizontal + * \value PatternDarkVertical + * \value PatternDarkDown + * \value PatternDarkUp + * \value PatternDarkGrid + * \value PatternDarkTrellis + * \value PatternLightHorizontal + * \value PatternLightVertical + * \value PatternLightDown + * \value PatternLightUp + * \value PatternLightTrellis + * \value PatternGray125 + * \value PatternGray0625 + * \value PatternLightGrid + */ + +/*! + * Creates a new invalid format. + */ +Format::Format() +{ + //The d pointer is initialized with a null pointer +} + +/*! + Creates a new format with the same attributes as the \a other format. + */ +Format::Format(const Format &other) + :d(other.d) +{ + +} + +/*! + Assigns the \a other format to this format, and returns a + reference to this format. + */ +Format &Format::operator =(const Format &other) +{ + d = other.d; + return *this; +} + +/*! + * Destroys this format. + */ +Format::~Format() +{ +} + +/*! + * Returns the number format identifier. + */ +int Format::numberFormatIndex() const +{ + return intProperty(FormatPrivate::P_NumFmt_Id, 0); +} + +/*! + * Set the number format identifier. The \a format + * must be a valid built-in number format identifier + * or the identifier of a custom number format. + */ +void Format::setNumberFormatIndex(int format) +{ + setProperty(FormatPrivate::P_NumFmt_Id, format); + clearProperty(FormatPrivate::P_NumFmt_FormatCode); +} + +/*! + * Returns the number format string. + * \note for built-in number formats, this may + * return an empty string. + */ +QString Format::numberFormat() const +{ + return stringProperty(FormatPrivate::P_NumFmt_FormatCode); +} + +/*! + * Set number \a format. + * http://office.microsoft.com/en-001/excel-help/create-a-custom-number-format-HP010342372.aspx + */ +void Format::setNumberFormat(const QString &format) +{ + if (format.isEmpty()) + return; + setProperty(FormatPrivate::P_NumFmt_FormatCode, format); + clearProperty(FormatPrivate::P_NumFmt_Id); //numFmt id must be re-generated. +} + +/*! + * Returns whether the number format is probably a dateTime or not + */ +bool Format::isDateTimeFormat() const +{ + if (hasProperty(FormatPrivate::P_NumFmt_FormatCode)) { + //Custom numFmt, so + //Gauss from the number string + return NumFormatParser::isDateTime(numberFormat()); + } else if (hasProperty(FormatPrivate::P_NumFmt_Id)){ + //Non-custom numFmt + int idx = numberFormatIndex(); + + //Is built-in date time number id? + if ((idx >= 14 && idx <= 22) || (idx >= 45 && idx <= 47)) + return true; + + if ((idx >= 27 && idx <= 36) || (idx >= 50 && idx <= 58)) //Used in CHS\CHT\JPN\KOR + return true; + } + + return false; +} + +/*! + \internal + Set a custom num \a format with the given \a id. + */ +void Format::setNumberFormat(int id, const QString &format) +{ + setProperty(FormatPrivate::P_NumFmt_Id, id); + setProperty(FormatPrivate::P_NumFmt_FormatCode, format); +} + +/*! + \internal + Called by styles to fix the numFmt + */ +void Format::fixNumberFormat(int id, const QString &format) +{ + setProperty(FormatPrivate::P_NumFmt_Id, id, 0, false); + setProperty(FormatPrivate::P_NumFmt_FormatCode, format, QString(), false); +} + +/*! + \internal + Return true if the format has number format. + */ +bool Format::hasNumFmtData() const +{ + if (!d) + return false; + + if (hasProperty(FormatPrivate::P_NumFmt_Id) + || hasProperty(FormatPrivate::P_NumFmt_FormatCode)) { + return true; + } + return false; +} + +/*! + * Return the size of the font in points. + */ +int Format::fontSize() const +{ + return intProperty(FormatPrivate::P_Font_Size); +} + +/*! + * Set the \a size of the font in points. + */ +void Format::setFontSize(int size) +{ + setProperty(FormatPrivate::P_Font_Size, size, 0); +} + +/*! + * Return whether the font is italic. + */ +bool Format::fontItalic() const +{ + return boolProperty(FormatPrivate::P_Font_Italic); +} + +/*! + * Turn on/off the italic font based on \a italic. + */ +void Format::setFontItalic(bool italic) +{ + setProperty(FormatPrivate::P_Font_Italic, italic, false); +} + +/*! + * Return whether the font is strikeout. + */ +bool Format::fontStrikeOut() const +{ + return boolProperty(FormatPrivate::P_Font_StrikeOut); +} + +/*! + * Turn on/off the strikeOut font based on \a strikeOut. + */ +void Format::setFontStrikeOut(bool strikeOut) +{ + setProperty(FormatPrivate::P_Font_StrikeOut, strikeOut, false); +} + +/*! + * Return the color of the font. + */ +QColor Format::fontColor() const +{ + if (hasProperty(FormatPrivate::P_Font_Color)) + return colorProperty(FormatPrivate::P_Font_Color); + return QColor(); +} + +/*! + * Set the \a color of the font. + */ +void Format::setFontColor(const QColor &color) +{ + setProperty(FormatPrivate::P_Font_Color, XlsxColor(color), XlsxColor()); +} + +/*! + * Return whether the font is bold. + */ +bool Format::fontBold() const +{ + return boolProperty(FormatPrivate::P_Font_Bold); +} + +/*! + * Turn on/off the bold font based on the given \a bold. + */ +void Format::setFontBold(bool bold) +{ + setProperty(FormatPrivate::P_Font_Bold, bold, false); +} + +/*! + * Return the script style of the font. + */ +Format::FontScript Format::fontScript() const +{ + return static_cast(intProperty(FormatPrivate::P_Font_Script)); +} + +/*! + * Set the script style of the font to \a script. + */ +void Format::setFontScript(FontScript script) +{ + setProperty(FormatPrivate::P_Font_Script, script, FontScriptNormal); +} + +/*! + * Return the underline style of the font. + */ +Format::FontUnderline Format::fontUnderline() const +{ + return static_cast(intProperty(FormatPrivate::P_Font_Underline)); +} + +/*! + * Set the underline style of the font to \a underline. + */ +void Format::setFontUnderline(FontUnderline underline) +{ + setProperty(FormatPrivate::P_Font_Underline, underline, FontUnderlineNone); +} + +/*! + * Return whether the font is outline. + */ +bool Format::fontOutline() const +{ + return boolProperty(FormatPrivate::P_Font_Outline); +} + +/*! + * Turn on/off the outline font based on \a outline. + */ +void Format::setFontOutline(bool outline) +{ + setProperty(FormatPrivate::P_Font_Outline, outline, false); +} + +/*! + * Return the name of the font. + */ +QString Format::fontName() const +{ + return stringProperty(FormatPrivate::P_Font_Name, QStringLiteral("Calibri")); +} + +/*! + * Set the name of the font to \a name. + */ +void Format::setFontName(const QString &name) +{ + setProperty(FormatPrivate::P_Font_Name, name, QStringLiteral("Calibri")); +} + +/*! + * Returns a QFont object based on font data contained in the format. + */ +QFont Format::font() const +{ + QFont font; + font.setFamily(fontName()); + if (fontSize() > 0) + font.setPointSize(fontSize()); + font.setBold(fontBold()); + font.setItalic(fontItalic()); + font.setUnderline(fontUnderline()!=FontUnderlineNone); + font.setStrikeOut(fontStrikeOut()); + return font; +} + +/*! + * Set the format properties from the given \a font. + */ +void Format::setFont(const QFont &font) +{ + setFontName(font.family()); + if (font.pointSize() > 0) + setFontSize(font.pointSize()); + setFontBold(font.bold()); + setFontItalic(font.italic()); + setFontUnderline(font.underline() ? FontUnderlineSingle : FontUnderlineNone); + setFontStrikeOut(font.strikeOut()); +} + +/*! + * \internal + * When the format has font data, when need to assign a valid index for it. + * The index value is depend on the order in styles.xml + */ +bool Format::fontIndexValid() const +{ + if (!hasFontData()) + return false; + return d->font_index_valid; +} + +/*! + * \internal + */ +int Format::fontIndex() const +{ + if (fontIndexValid()) + return d->font_index; + + return 0; +} + +/*! + * \internal + */ +void Format::setFontIndex(int index) +{ + d->font_index = index; + d->font_index_valid = true; +} + +/*! + * \internal + */ +QByteArray Format::fontKey() const +{ + if (isEmpty()) + return QByteArray(); + + if (d->font_dirty) { + QByteArray key; + QDataStream stream(&key, QIODevice::WriteOnly); + for (int i=FormatPrivate::P_Font_STARTID; iproperties.contains(i)) + stream << i << d->properties[i]; + }; + + const_cast(this)->d->font_key = key; + const_cast(this)->d->font_dirty = false; + } + + return d->font_key; +} + +/*! + \internal + Return true if the format has font format, otherwise return false. + */ +bool Format::hasFontData() const +{ + if (!d) + return false; + + for (int i=FormatPrivate::P_Font_STARTID; i(intProperty(FormatPrivate::P_Alignment_AlignH, AlignHGeneral)); +} + +/*! + * Set the horizontal alignment with the given \a align. + */ +void Format::setHorizontalAlignment(HorizontalAlignment align) +{ + if (hasProperty(FormatPrivate::P_Alignment_Indent) + &&(align != AlignHGeneral && align != AlignLeft && align != AlignRight && align != AlignHDistributed)) { + clearProperty(FormatPrivate::P_Alignment_Indent); + } + + if (hasProperty(FormatPrivate::P_Alignment_ShinkToFit) + && (align == AlignHFill || align == AlignHJustify || align == AlignHDistributed)) { + clearProperty(FormatPrivate::P_Alignment_ShinkToFit); + } + + setProperty(FormatPrivate::P_Alignment_AlignH, align, AlignHGeneral); +} + +/*! + * Return the vertical alignment. + */ +Format::VerticalAlignment Format::verticalAlignment() const +{ + return static_cast(intProperty(FormatPrivate::P_Alignment_AlignV, AlignBottom)); +} + +/*! + * Set the vertical alignment with the given \a align. + */ +void Format::setVerticalAlignment(VerticalAlignment align) +{ + setProperty(FormatPrivate::P_Alignment_AlignV, align, AlignBottom); +} + +/*! + * Return whether the cell text is wrapped. + */ +bool Format::textWrap() const +{ + return boolProperty(FormatPrivate::P_Alignment_Wrap); +} + +/*! + * Enable the text wrap if \a wrap is true. + */ +void Format::setTextWarp(bool wrap) +{ + if (wrap && hasProperty(FormatPrivate::P_Alignment_ShinkToFit)) + clearProperty(FormatPrivate::P_Alignment_ShinkToFit); + + setProperty(FormatPrivate::P_Alignment_Wrap, wrap, false); +} + +/*! + * Return the text rotation. + */ +int Format::rotation() const +{ + return intProperty(FormatPrivate::P_Alignment_Rotation); +} + +/*! + * Set the text roation with the given \a rotation. Must be in the range [0, 180] or 255. + */ +void Format::setRotation(int rotation) +{ + setProperty(FormatPrivate::P_Alignment_Rotation, rotation, 0); +} + +/*! + * Return the text indentation level. + */ +int Format::indent() const +{ + return intProperty(FormatPrivate::P_Alignment_Indent); +} + +/*! + * Set the text indentation level with the given \a indent. Must be less than or equal to 15. + */ +void Format::setIndent(int indent) +{ + if (indent && hasProperty(FormatPrivate::P_Alignment_AlignH)) { + HorizontalAlignment hl = horizontalAlignment(); + + if (hl != AlignHGeneral && hl != AlignLeft && hl!= AlignRight && hl!= AlignHJustify) { + setHorizontalAlignment(AlignLeft); + } + } + + setProperty(FormatPrivate::P_Alignment_Indent, indent, 0); +} + +/*! + * Return whether the cell is shrink to fit. + */ +bool Format::shrinkToFit() const +{ + return boolProperty(FormatPrivate::P_Alignment_ShinkToFit); +} + +/*! + * Turn on/off shrink to fit base on \a shink. + */ +void Format::setShrinkToFit(bool shink) +{ + if (shink && hasProperty(FormatPrivate::P_Alignment_Wrap)) + clearProperty(FormatPrivate::P_Alignment_Wrap); + + if (shink && hasProperty(FormatPrivate::P_Alignment_AlignH)) { + HorizontalAlignment hl = horizontalAlignment(); + if (hl == AlignHFill || hl == AlignHJustify || hl == AlignHDistributed) + setHorizontalAlignment(AlignLeft); + } + + setProperty(FormatPrivate::P_Alignment_ShinkToFit, shink, false); +} + +/*! + * \internal + */ +bool Format::hasAlignmentData() const +{ + if (!d) + return false; + + for (int i=FormatPrivate::P_Alignment_STARTID; i(intProperty(FormatPrivate::P_Border_LeftStyle)); +} + +/*! + * Sets the left border style to \a style + */ +void Format::setLeftBorderStyle(BorderStyle style) +{ + setProperty(FormatPrivate::P_Border_LeftStyle, style, BorderNone); +} + +/*! + * Returns the left border color + */ +QColor Format::leftBorderColor() const +{ + return colorProperty(FormatPrivate::P_Border_LeftColor); +} + +/*! + Sets the left border color to the given \a color +*/ +void Format::setLeftBorderColor(const QColor &color) +{ + setProperty(FormatPrivate::P_Border_LeftColor, XlsxColor(color), XlsxColor()); +} + +/*! + Returns the right border style. +*/ +Format::BorderStyle Format::rightBorderStyle() const +{ + return static_cast(intProperty(FormatPrivate::P_Border_RightStyle)); +} + +/*! + Sets the right border style to the given \a style. +*/ +void Format::setRightBorderStyle(BorderStyle style) +{ + setProperty(FormatPrivate::P_Border_RightStyle, style, BorderNone); +} + +/*! + Returns the right border color. +*/ +QColor Format::rightBorderColor() const +{ + return colorProperty(FormatPrivate::P_Border_RightColor); +} + +/*! + Sets the right border color to the given \a color +*/ +void Format::setRightBorderColor(const QColor &color) +{ + setProperty(FormatPrivate::P_Border_RightColor, XlsxColor(color), XlsxColor()); +} + +/*! + Returns the top border style. +*/ +Format::BorderStyle Format::topBorderStyle() const +{ + return static_cast(intProperty(FormatPrivate::P_Border_TopStyle)); +} + +/*! + Sets the top border style to the given \a style. +*/ +void Format::setTopBorderStyle(BorderStyle style) +{ + setProperty(FormatPrivate::P_Border_TopStyle, style, BorderNone); +} + +/*! + Returns the top border color. +*/ +QColor Format::topBorderColor() const +{ + return colorProperty(FormatPrivate::P_Border_TopColor); +} + +/*! + Sets the top border color to the given \a color. +*/ +void Format::setTopBorderColor(const QColor &color) +{ + setProperty(FormatPrivate::P_Border_TopColor, XlsxColor(color), XlsxColor()); +} + +/*! + Returns the bottom border style. +*/ +Format::BorderStyle Format::bottomBorderStyle() const +{ + return static_cast(intProperty(FormatPrivate::P_Border_BottomStyle)); +} + +/*! + Sets the bottom border style to the given \a style. +*/ +void Format::setBottomBorderStyle(BorderStyle style) +{ + setProperty(FormatPrivate::P_Border_BottomStyle, style, BorderNone); +} + +/*! + Returns the bottom border color. +*/ +QColor Format::bottomBorderColor() const +{ + return colorProperty(FormatPrivate::P_Border_BottomColor); +} + +/*! + Sets the bottom border color to the given \a color. +*/ +void Format::setBottomBorderColor(const QColor &color) +{ + setProperty(FormatPrivate::P_Border_BottomColor, XlsxColor(color), XlsxColor()); +} + +/*! + Return the diagonla border style. +*/ +Format::BorderStyle Format::diagonalBorderStyle() const +{ + return static_cast(intProperty(FormatPrivate::P_Border_DiagonalStyle)); +} + +/*! + Sets the diagonal border style to the given \a style. +*/ +void Format::setDiagonalBorderStyle(BorderStyle style) +{ + setProperty(FormatPrivate::P_Border_DiagonalStyle, style, BorderNone); +} + +/*! + Returns the diagonal border type. +*/ +Format::DiagonalBorderType Format::diagonalBorderType() const +{ + return static_cast(intProperty(FormatPrivate::P_Border_DiagonalType)); +} + +/*! + Sets the diagonal border type to the given \a style +*/ +void Format::setDiagonalBorderType(DiagonalBorderType style) +{ + setProperty(FormatPrivate::P_Border_DiagonalType, style, DiagonalBorderNone); +} + +/*! + Returns the diagonal border color. +*/ +QColor Format::diagonalBorderColor() const +{ + return colorProperty(FormatPrivate::P_Border_DiagonalColor); +} + +/*! + Sets the diagonal border color to the given \a color +*/ +void Format::setDiagonalBorderColor(const QColor &color) +{ + setProperty(FormatPrivate::P_Border_DiagonalColor, XlsxColor(color), XlsxColor()); +} + +/*! + \internal + Returns whether this format has been set valid border index. +*/ +bool Format::borderIndexValid() const +{ + if (!hasBorderData()) + return false; + return d->border_index_valid; +} + +/*! + \internal + Returns the border index. +*/ +int Format::borderIndex() const +{ + if (borderIndexValid()) + return d->border_index; + return 0; +} + +/*! + * \internal + */ +void Format::setBorderIndex(int index) +{ + d->border_index = index; + d->border_index_valid = true; +} + +/*! \internal + */ +QByteArray Format::borderKey() const +{ + if (isEmpty()) + return QByteArray(); + + if (d->border_dirty) { + QByteArray key; + QDataStream stream(&key, QIODevice::WriteOnly); + for (int i=FormatPrivate::P_Border_STARTID; iproperties.contains(i)) + stream << i << d->properties[i]; + }; + + const_cast(this)->d->border_key = key; + const_cast(this)->d->border_dirty = false; + } + + return d->border_key; +} + +/*! + \internal + Return true if the format has border format, otherwise return false. + */ +bool Format::hasBorderData() const +{ + if (!d) + return false; + + for (int i=FormatPrivate::P_Border_STARTID; i(intProperty(FormatPrivate::P_Fill_Pattern, PatternNone)); +} + +/*! + Sets the fill pattern to the given \a pattern. +*/ +void Format::setFillPattern(FillPattern pattern) +{ + setProperty(FormatPrivate::P_Fill_Pattern, pattern, PatternNone); +} + +/*! + Returns the foreground color of the pattern. +*/ +QColor Format::patternForegroundColor() const +{ + return colorProperty(FormatPrivate::P_Fill_FgColor); +} + +/*! + Sets the foreground color of the pattern with the given \a color. +*/ +void Format::setPatternForegroundColor(const QColor &color) +{ + if (color.isValid() && !hasProperty(FormatPrivate::P_Fill_Pattern)) + setFillPattern(PatternSolid); + setProperty(FormatPrivate::P_Fill_FgColor, XlsxColor(color), XlsxColor()); +} + +/*! + Returns the background color of the pattern. +*/ +QColor Format::patternBackgroundColor() const +{ + return colorProperty(FormatPrivate::P_Fill_BgColor); +} + +/*! + Sets the background color of the pattern with the given \a color. +*/ +void Format::setPatternBackgroundColor(const QColor &color) +{ + if (color.isValid() && !hasProperty(FormatPrivate::P_Fill_Pattern)) + setFillPattern(PatternSolid); + setProperty(FormatPrivate::P_Fill_BgColor, XlsxColor(color), XlsxColor()); +} + +/*! + * \internal + */ +bool Format::fillIndexValid() const +{ + if (!hasFillData()) + return false; + return d->fill_index_valid; +} + +/*! + * \internal + */ +int Format::fillIndex() const +{ + if (fillIndexValid()) + return d->fill_index; + return 0; +} + +/*! + * \internal + */ +void Format::setFillIndex(int index) +{ + d->fill_index = index; + d->fill_index_valid = true; +} + +/*! + * \internal + */ +QByteArray Format::fillKey() const +{ + if (isEmpty()) + return QByteArray(); + + if (d->fill_dirty) { + QByteArray key; + QDataStream stream(&key, QIODevice::WriteOnly); + for (int i=FormatPrivate::P_Fill_STARTID; iproperties.contains(i)) + stream << i << d->properties[i]; + }; + + const_cast(this)->d->fill_key = key; + const_cast(this)->d->fill_dirty = false; + } + + return d->fill_key; +} + +/*! + \internal + Return true if the format has fill format, otherwise return false. + */ +bool Format::hasFillData() const +{ + if (!d) + return false; + + for (int i=FormatPrivate::P_Fill_STARTID; i
\n" \ + "
\n" \ + "
\n" \ + "

\n" \ + " © 2013-2014 Debao Zhang. \n" \ + " Documentation contributions included herein are the copyrights of\n" \ + " their respective owners.

\n" \ + "

\n" \ + " The documentation provided herein is licensed under the terms of the\n" \ + " GNU Free Documentation\n" \ + " License version 1.3 as published by the Free Software Foundation.

\n" \ + "

\n" \ + " Documentation sources may be obtained from \n" \ + " github.com/dbzhang800.

\n" \ + "

\n" \ + " Qt and their respective logos are trademarks of Digia Plc \n" \ + " in Finland and/or other countries worldwide. All other trademarks are property\n" \ + " of their respective owners. Privacy Policy

\n" \ + "
\n" \ + "
\n" \ + "

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 z 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�ngtez!*bLl_XS{^f+{K67{2+edv2Yr#2nosy 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