diff --git a/platform/src/public/pub_excel/excellib.cpp b/platform/src/public/pub_excel/excellib.cpp
new file mode 100644
index 00000000..a3f32678
--- /dev/null
+++ b/platform/src/public/pub_excel/excellib.cpp
@@ -0,0 +1,6 @@
+#include "excellib.h"
+
+
+ExcelLib::ExcelLib()
+{
+}
diff --git a/platform/src/public/pub_excel/pub_excel.pro b/platform/src/public/pub_excel/pub_excel.pro
new file mode 100644
index 00000000..6fb50d7e
--- /dev/null
+++ b/platform/src/public/pub_excel/pub_excel.pro
@@ -0,0 +1,51 @@
+#-------------------------------------------------
+#
+# Project created by QtCreator 2018-02-09T13:26:54
+#此处仅仅是简单将QtXlsx库封装
+#-------------------------------------------------
+
+QT -= gui
+QT += core gui-private
+
+TARGET = pub_excel
+TEMPLATE = lib
+
+
+DEFINES += QT_BUILD_XLSX_LIB
+include($$PWD/xlsx/qtxlsx.pri)
+
+exists($$PWD/../../common.pri) {
+ include($$PWD/../../common.pri)
+}else {
+ error("FATAL error: connot find common.pri")
+}
+
+
+DEFINES += EXCELLIB_LIBRARY
+
+# The following define makes your compiler emit warnings if you use
+# any feature of Qt which has been marked as deprecated (the exact warnings
+# depend on your compiler). Please consult the documentation of the
+# deprecated API in order to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+# You can also make your code fail to compile if you use deprecated APIs.
+# In order to do so, uncomment the following line.
+# You can also select to disable deprecated APIs only up to a certain version of Qt.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
+
+INCLUDEPATH += $$PWD/../../include/public/pub_excel/xlsx \
+ $$PWD/../../include/public/pub_excel
+
+
+SOURCES += \
+ excellib.cpp
+
+HEADERS += \
+ $$PWD/../../include/public/pub_excel/excellib.h \
+ $$PWD/../../include/public/pub_excel/excellib_global.h
+
+unix {
+ target.path = /usr/lib
+ INSTALLS += target
+}
diff --git a/platform/src/public/pub_excel/xlsx/doc/qtxlsx.qdocconf b/platform/src/public/pub_excel/xlsx/doc/qtxlsx.qdocconf
new file mode 100644
index 00000000..ef111818
--- /dev/null
+++ b/platform/src/public/pub_excel/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/platform/src/public/pub_excel/xlsx/doc/snippets/doc_src_qtxlsx.cpp b/platform/src/public/pub_excel/xlsx/doc/snippets/doc_src_qtxlsx.cpp
new file mode 100644
index 00000000..eab3ac21
--- /dev/null
+++ b/platform/src/public/pub_excel/xlsx/doc/snippets/doc_src_qtxlsx.cpp
@@ -0,0 +1,8 @@
+
+//! [0]
+#include
+//! [0]
+
+//! [1]
+#include
+//! [1]
diff --git a/platform/src/public/pub_excel/xlsx/doc/snippets/doc_src_qtxlsx.pro b/platform/src/public/pub_excel/xlsx/doc/snippets/doc_src_qtxlsx.pro
new file mode 100644
index 00000000..b2789f71
--- /dev/null
+++ b/platform/src/public/pub_excel/xlsx/doc/snippets/doc_src_qtxlsx.pro
@@ -0,0 +1,3 @@
+#! [1]
+QT += xlsx
+#! [1]
diff --git a/platform/src/public/pub_excel/xlsx/doc/src/examples.qdoc b/platform/src/public/pub_excel/xlsx/doc/src/examples.qdoc
new file mode 100644
index 00000000..6defee73
--- /dev/null
+++ b/platform/src/public/pub_excel/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/platform/src/public/pub_excel/xlsx/doc/src/qtxlsx-index.qdoc b/platform/src/public/pub_excel/xlsx/doc/src/qtxlsx-index.qdoc
new file mode 100644
index 00000000..8ef7b482
--- /dev/null
+++ b/platform/src/public/pub_excel/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/platform/src/public/pub_excel/xlsx/doc/src/qtxlsx.qdoc b/platform/src/public/pub_excel/xlsx/doc/src/qtxlsx.qdoc
new file mode 100644
index 00000000..cdc70f18
--- /dev/null
+++ b/platform/src/public/pub_excel/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/platform/src/public/pub_excel/xlsx/doc/src/usage.qdoc b/platform/src/public/pub_excel/xlsx/doc/src/usage.qdoc
new file mode 100644
index 00000000..fabbe9ba
--- /dev/null
+++ b/platform/src/public/pub_excel/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/platform/src/public/pub_excel/xlsx/qtxlsx.pri b/platform/src/public/pub_excel/xlsx/qtxlsx.pri
new file mode 100644
index 00000000..6113f2bd
--- /dev/null
+++ b/platform/src/public/pub_excel/xlsx/qtxlsx.pri
@@ -0,0 +1,86 @@
+INCLUDEPATH += $$PWD
+DEPENDPATH += $$PWD
+
+QT += core gui gui-private
+#!build_xlsx_lib:DEFINES += XLSX_NO_LIB
+
+
+
+HEADERS += $$PWD/../../../include/public/pub_excel/xlsx/xlsxdocpropscore_p.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxdocpropsapp_p.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxrelationships_p.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxutility_p.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxsharedstrings_p.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxcontenttypes_p.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxtheme_p.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxformat.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxworkbook.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxstyles_p.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxabstractsheet.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxabstractsheet_p.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxworksheet.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxworksheet_p.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxchartsheet.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxchartsheet_p.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxzipwriter_p.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxworkbook_p.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxformat_p.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxglobal.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxdrawing_p.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxzipreader_p.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxdocument.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxdocument_p.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxcell.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxcell_p.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxdatavalidation.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxdatavalidation_p.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxcellreference.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxcellrange.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxrichstring_p.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxrichstring.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxconditionalformatting.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxconditionalformatting_p.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxcolor_p.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxnumformatparser_p.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxdrawinganchor_p.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxmediafile_p.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxabstractooxmlfile.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxabstractooxmlfile_p.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxchart.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxchart_p.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxsimpleooxmlfile_p.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/xlsxcellformula.h \
+ $$PWD/../../../include/public/pub_excel/xlsx/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/platform/src/public/pub_excel/xlsx/xlsx.pro b/platform/src/public/pub_excel/xlsx/xlsx.pro
new file mode 100644
index 00000000..ea0810b9
--- /dev/null
+++ b/platform/src/public/pub_excel/xlsx/xlsx.pro
@@ -0,0 +1,17 @@
+TARGET = QtXlsx
+TEMPLATE = lib
+
+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/platform/src/public/pub_excel/xlsx/xlsxabstractooxmlfile.cpp b/platform/src/public/pub_excel/xlsx/xlsxabstractooxmlfile.cpp
new file mode 100644
index 00000000..36d15a02
--- /dev/null
+++ b/platform/src/public/pub_excel/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/platform/src/public/pub_excel/xlsx/xlsxabstractsheet.cpp b/platform/src/public/pub_excel/xlsx/xlsxabstractsheet.cpp
new file mode 100644
index 00000000..2cf6eeeb
--- /dev/null
+++ b/platform/src/public/pub_excel/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/platform/src/public/pub_excel/xlsx/xlsxcell.cpp b/platform/src/public/pub_excel/xlsx/xlsxcell.cpp
new file mode 100644
index 00000000..fcaf7a6b
--- /dev/null
+++ b/platform/src/public/pub_excel/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/platform/src/public/pub_excel/xlsx/xlsxcellformula.cpp b/platform/src/public/pub_excel/xlsx/xlsxcellformula.cpp
new file mode 100644
index 00000000..858d3479
--- /dev/null
+++ b/platform/src/public/pub_excel/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/platform/src/public/pub_excel/xlsx/xlsxcellrange.cpp b/platform/src/public/pub_excel/xlsx/xlsxcellrange.cpp
new file mode 100644
index 00000000..6251ab7a
--- /dev/null
+++ b/platform/src/public/pub_excel/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/platform/src/public/pub_excel/xlsx/xlsxcellreference.cpp b/platform/src/public/pub_excel/xlsx/xlsxcellreference.cpp
new file mode 100644
index 00000000..e7cf5da9
--- /dev/null
+++ b/platform/src/public/pub_excel/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/platform/src/public/pub_excel/xlsx/xlsxchart.cpp b/platform/src/public/pub_excel/xlsx/xlsxchart.cpp
new file mode 100644
index 00000000..a69f5c25
--- /dev/null
+++ b/platform/src/public/pub_excel/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/platform/src/public/pub_excel/xlsx/xlsxchartsheet.cpp b/platform/src/public/pub_excel/xlsx/xlsxchartsheet.cpp
new file mode 100644
index 00000000..5cf477c9
--- /dev/null
+++ b/platform/src/public/pub_excel/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/platform/src/public/pub_excel/xlsx/xlsxcolor.cpp b/platform/src/public/pub_excel/xlsx/xlsxcolor.cpp
new file mode 100644
index 00000000..b1ed4639
--- /dev/null
+++ b/platform/src/public/pub_excel/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/platform/src/public/pub_excel/xlsx/xlsxconditionalformatting.cpp b/platform/src/public/pub_excel/xlsx/xlsxconditionalformatting.cpp
new file mode 100644
index 00000000..03561fe6
--- /dev/null
+++ b/platform/src/public/pub_excel/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/platform/src/public/pub_excel/xlsx/xlsxcontenttypes.cpp b/platform/src/public/pub_excel/xlsx/xlsxcontenttypes.cpp
new file mode 100644
index 00000000..8a500ac9
--- /dev/null
+++ b/platform/src/public/pub_excel/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.
+**
+****************************************************************************/
+
+#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/platform/src/public/pub_excel/xlsx/xlsxdocpropsapp.cpp b/platform/src/public/pub_excel/xlsx/xlsxdocpropsapp.cpp
new file mode 100644
index 00000000..49ad9b29
--- /dev/null
+++ b/platform/src/public/pub_excel/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/platform/src/public/pub_excel/xlsx/xlsxdocpropscore.cpp b/platform/src/public/pub_excel/xlsx/xlsxdocpropscore.cpp
new file mode 100644
index 00000000..7e955f8d
--- /dev/null
+++ b/platform/src/public/pub_excel/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.
+**
+****************************************************************************/
+
+#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/platform/src/public/pub_excel/xlsx/xlsxdrawing.cpp b/platform/src/public/pub_excel/xlsx/xlsxdrawing.cpp
new file mode 100644
index 00000000..ae7d2d7b
--- /dev/null
+++ b/platform/src/public/pub_excel/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/platform/src/public/pub_excel/xlsx/xlsxdrawinganchor.cpp b/platform/src/public/pub_excel/xlsx/xlsxdrawinganchor.cpp
new file mode 100644
index 00000000..be12dc03
--- /dev/null
+++ b/platform/src/public/pub_excel/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/platform/src/public/pub_excel/xlsx/xlsxformat.cpp b/platform/src/public/pub_excel/xlsx/xlsxformat.cpp
new file mode 100644
index 00000000..074184f7
--- /dev/null
+++ b/platform/src/public/pub_excel/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 it(modifier.d->properties);
+ while(it.hasNext()) {
+ it.next();
+ setProperty(it.key(), it.value());
+ }
+}
+
+/*!
+ Returns true if the format is valid; otherwise returns false.
+ */
+bool Format::isValid() const
+{
+ if (d)
+ return true;
+ return false;
+}
+
+/*!
+ Returns true if the format is empty; otherwise returns false.
+ */
+bool Format::isEmpty() const
+{
+ if (!d)
+ return true;
+ return d->properties.isEmpty();
+}
+
+/*!
+ * \internal
+ */
+QByteArray Format::formatKey() const
+{
+ if (isEmpty())
+ return QByteArray();
+
+ if (d->dirty) {
+ QByteArray key;
+ QDataStream stream(&key, QIODevice::WriteOnly);
+
+ QMapIterator i(d->properties);
+ while (i.hasNext()) {
+ i.next();
+ stream<formatKey = key;
+ d->dirty = false;
+ }
+
+ return d->formatKey;
+}
+
+/*!
+ * \internal
+ * Called by QXlsx::Styles or some unittests.
+ */
+void Format::setXfIndex(int index)
+{
+ if (!d)
+ d = new FormatPrivate;
+ d->xf_index = index;
+ d->xf_indexValid = true;
+}
+
+/*!
+ * \internal
+ */
+int Format::xfIndex() const
+{
+ if (!d)
+ return -1;
+ return d->xf_index;
+}
+
+/*!
+ * \internal
+ */
+bool Format::xfIndexValid() const
+{
+ if (!d)
+ return false;
+ return d->xf_indexValid;
+}
+
+/*!
+ * \internal
+ * Called by QXlsx::Styles or some unittests.
+ */
+void Format::setDxfIndex(int index)
+{
+ if (!d)
+ d = new FormatPrivate;
+ d->dxf_index = index;
+ d->dxf_indexValid = true;
+}
+
+/*!
+ * \internal
+ * Returns the index in the styles dxfs.
+ */
+int Format::dxfIndex() const
+{
+ if (!d)
+ return -1;
+ return d->dxf_index;
+}
+
+/*!
+ * \internal
+ * Returns whether the dxf index is valid or not.
+ */
+bool Format::dxfIndexValid() const
+{
+ if (!d)
+ return false;
+ return d->dxf_indexValid;
+}
+
+/*!
+ Returns ture if the \a format is equal to this format.
+*/
+bool Format::operator ==(const Format &format) const
+{
+ return this->formatKey() == format.formatKey();
+}
+
+/*!
+ Returns ture if the \a format is not equal to this format.
+*/
+bool Format::operator !=(const Format &format) const
+{
+ return this->formatKey() != format.formatKey();
+}
+
+int Format::theme() const
+{
+ return d->theme;
+}
+
+/*!
+ * \internal
+ */
+QVariant Format::property(int propertyId, const QVariant &defaultValue) const
+{
+ if (d && d->properties.contains(propertyId))
+ return d->properties[propertyId];
+ return defaultValue;
+}
+
+/*!
+ * \internal
+ */
+void Format::setProperty(int propertyId, const QVariant &value, const QVariant &clearValue, bool detach)
+{
+ if (!d)
+ d = new FormatPrivate;
+
+ if (value != clearValue) {
+ if (d->properties.contains(propertyId) && d->properties[propertyId] == value)
+ return;
+ if (detach)
+ d.detach();
+ d->properties[propertyId] = value;
+ } else {
+ if (!d->properties.contains(propertyId))
+ return;
+ if (detach)
+ d.detach();
+ d->properties.remove(propertyId);
+ }
+
+ d->dirty = true;
+ d->xf_indexValid = false;
+ d->dxf_indexValid = false;
+
+ if (propertyId >= FormatPrivate::P_Font_STARTID && propertyId < FormatPrivate::P_Font_ENDID) {
+ d->font_dirty = true;
+ d->font_index_valid = false;
+ } else if (propertyId >= FormatPrivate::P_Border_STARTID && propertyId < FormatPrivate::P_Border_ENDID) {
+ d->border_dirty = true;
+ d->border_index_valid = false;
+ } else if (propertyId >= FormatPrivate::P_Fill_STARTID && propertyId < FormatPrivate::P_Fill_ENDID) {
+ d->fill_dirty = true;
+ d->fill_index_valid = false;
+ }
+}
+
+/*!
+ * \internal
+ */
+void Format::clearProperty(int propertyId)
+{
+ setProperty(propertyId, QVariant());
+}
+
+/*!
+ * \internal
+ */
+bool Format::hasProperty(int propertyId) const
+{
+ if (!d)
+ return false;
+ return d->properties.contains(propertyId);
+}
+
+/*!
+ * \internal
+ */
+bool Format::boolProperty(int propertyId, bool defaultValue) const
+{
+ if (!hasProperty(propertyId))
+ return defaultValue;
+
+ const QVariant prop = d->properties[propertyId];
+ if (prop.userType() != QMetaType::Bool)
+ return defaultValue;
+ return prop.toBool();
+}
+
+/*!
+ * \internal
+ */
+int Format::intProperty(int propertyId, int defaultValue) const
+{
+ if (!hasProperty(propertyId))
+ return defaultValue;
+
+ const QVariant prop = d->properties[propertyId];
+ if (prop.userType() != QMetaType::Int)
+ return defaultValue;
+ return prop.toInt();
+}
+
+/*!
+ * \internal
+ */
+double Format::doubleProperty(int propertyId, double defaultValue) const
+{
+ if (!hasProperty(propertyId))
+ return defaultValue;
+
+ const QVariant prop = d->properties[propertyId];
+ if (prop.userType() != QMetaType::Double && prop.userType() != QMetaType::Float)
+ return defaultValue;
+ return prop.toDouble();
+}
+
+/*!
+ * \internal
+ */
+QString Format::stringProperty(int propertyId, const QString &defaultValue) const
+{
+ if (!hasProperty(propertyId))
+ return defaultValue;
+
+ const QVariant prop = d->properties[propertyId];
+ if (prop.userType() != QMetaType::QString)
+ return defaultValue;
+ return prop.toString();
+}
+
+/*!
+ * \internal
+ */
+QColor Format::colorProperty(int propertyId, const QColor &defaultValue) const
+{
+ if (!hasProperty(propertyId))
+ return defaultValue;
+
+ const QVariant prop = d->properties[propertyId];
+ if (prop.userType() != qMetaTypeId())
+ return defaultValue;
+ return qvariant_cast(prop).rgbColor();
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const Format &f)
+{
+ dbg.nospace() << "QXlsx::Format(" << f.d->properties << ")";
+ return dbg.space();
+}
+#endif
+
+QT_END_NAMESPACE_XLSX
diff --git a/platform/src/public/pub_excel/xlsx/xlsxmediafile.cpp b/platform/src/public/pub_excel/xlsx/xlsxmediafile.cpp
new file mode 100644
index 00000000..39fbc03d
--- /dev/null
+++ b/platform/src/public/pub_excel/xlsx/xlsxmediafile.cpp
@@ -0,0 +1,99 @@
+/****************************************************************************
+** 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 "xlsxmediafile_p.h"
+#include
+
+namespace QXlsx {
+
+MediaFile::MediaFile(const QByteArray &bytes, const QString &suffix, const QString &mimeType)
+ : m_contents(bytes), m_suffix(suffix), m_mimeType(mimeType)
+ , m_index(0), m_indexValid(false)
+{
+ m_hashKey = QCryptographicHash::hash(m_contents, QCryptographicHash::Md5);
+}
+
+MediaFile::MediaFile(const QString &fileName)
+ :m_fileName(fileName), m_index(0), m_indexValid(false)
+{
+
+}
+
+void MediaFile::set(const QByteArray &bytes, const QString &suffix, const QString &mimeType)
+{
+ m_contents = bytes;
+ m_suffix = suffix;
+ m_mimeType = mimeType;
+ m_hashKey = QCryptographicHash::hash(m_contents, QCryptographicHash::Md5);
+ m_indexValid = false;
+}
+
+void MediaFile::setFileName(const QString &name)
+{
+ m_fileName = name;
+}
+
+QString MediaFile::fileName() const
+{
+ return m_fileName;
+}
+
+QString MediaFile::suffix() const
+{
+ return m_suffix;
+}
+
+QString MediaFile::mimeType() const
+{
+ return m_mimeType;
+}
+
+QByteArray MediaFile::contents() const
+{
+ return m_contents;
+}
+
+int MediaFile::index() const
+{
+ return m_index;
+}
+
+bool MediaFile::isIndexValid() const
+{
+ return m_indexValid;
+}
+
+void MediaFile::setIndex(int idx)
+{
+ m_index = idx;
+ m_indexValid = true;
+}
+
+QByteArray MediaFile::hashKey() const
+{
+ return m_hashKey;
+}
+
+} // namespace QXlsx
diff --git a/platform/src/public/pub_excel/xlsx/xlsxnumformatparser.cpp b/platform/src/public/pub_excel/xlsx/xlsxnumformatparser.cpp
new file mode 100644
index 00000000..6e2a686a
--- /dev/null
+++ b/platform/src/public/pub_excel/xlsx/xlsxnumformatparser.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+** 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 "xlsxnumformatparser_p.h"
+
+#include
+
+namespace QXlsx {
+
+bool NumFormatParser::isDateTime(const QString &formatCode)
+{
+ for (int i = 0; i < formatCode.length(); ++i) {
+ const QChar &c = formatCode[i];
+
+ switch (c.unicode()) {
+ case '[':
+ // [h], [m], [s] are valid format for time
+ if (i < formatCode.length()-2 && formatCode[i+2] == QLatin1Char(']')) {
+ const QChar cc = formatCode[i+1].toLower();
+ if (cc == QLatin1Char('h') || cc == QLatin1Char('m') || cc == QLatin1Char('s'))
+ return true;
+ i+=2;
+ break;
+ } else {
+ // condition or color: don't care, ignore
+ while (i < formatCode.length() && formatCode[i] != QLatin1Char(']'))
+ ++i;
+ break;
+ }
+
+ // quoted plain text block: don't care, ignore
+ case '"':
+ while (i < formatCode.length()-1 && formatCode[++i] != QLatin1Char('"'))
+ ;
+ break;
+
+ // escaped char: don't care, ignore
+ case '\\':
+ if (i < formatCode.length() - 1)
+ ++i;
+ break;
+
+ // date/time can only be positive number,
+ // so only the first section of the format make sense.
+ case ';':
+ return false;
+ break;
+
+ // days
+ case 'D':
+ case 'd':
+ // years
+ case 'Y':
+ case 'y':
+ // hours
+ case 'H':
+ case 'h':
+ // seconds
+ case 'S':
+ case 's':
+ // minutes or months, depending on context
+ case 'M':
+ case 'm':
+ return true;
+
+ default:
+ break;
+ }
+ }
+ return false;
+}
+
+} // namespace QXlsx
diff --git a/platform/src/public/pub_excel/xlsx/xlsxrelationships.cpp b/platform/src/public/pub_excel/xlsx/xlsxrelationships.cpp
new file mode 100644
index 00000000..26161822
--- /dev/null
+++ b/platform/src/public/pub_excel/xlsx/xlsxrelationships.cpp
@@ -0,0 +1,189 @@
+/****************************************************************************
+** 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 "xlsxrelationships_p.h"
+#include
+#include
+#include
+#include
+#include
+
+namespace QXlsx {
+
+const QString schema_doc = QStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/relationships");
+const QString schema_msPackage = QStringLiteral("http://schemas.microsoft.com/office/2006/relationships");
+const QString schema_package = QStringLiteral("http://schemas.openxmlformats.org/package/2006/relationships");
+//const QString schema_worksheet = QStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/relationships");
+Relationships::Relationships()
+{
+}
+
+QList Relationships::documentRelationships(const QString &relativeType) const
+{
+ return relationships(schema_doc + relativeType);
+}
+
+void Relationships::addDocumentRelationship(const QString &relativeType, const QString &target)
+{
+ addRelationship(schema_doc + relativeType, target);
+}
+
+QList Relationships::msPackageRelationships(const QString &relativeType) const
+{
+ return relationships(schema_msPackage + relativeType);
+}
+
+void Relationships::addMsPackageRelationship(const QString &relativeType, const QString &target)
+{
+ addRelationship(schema_msPackage + relativeType, target);
+}
+
+QList Relationships::packageRelationships(const QString &relativeType) const
+{
+ return relationships(schema_package + relativeType);
+}
+
+void Relationships::addPackageRelationship(const QString &relativeType, const QString &target)
+{
+ addRelationship(schema_package + relativeType, target);
+}
+
+QList Relationships::worksheetRelationships(const QString &relativeType) const
+{
+ return relationships(schema_doc + relativeType);
+}
+
+void Relationships::addWorksheetRelationship(const QString &relativeType, const QString &target, const QString &targetMode)
+{
+ addRelationship(schema_doc + relativeType, target, targetMode);
+}
+
+QList Relationships::relationships(const QString &type) const
+{
+ QList res;
+ foreach (XlsxRelationship ship, m_relationships) {
+ if (ship.type == type)
+ res.append(ship);
+ }
+ return res;
+}
+
+void Relationships::addRelationship(const QString &type, const QString &target, const QString &targetMode)
+{
+ XlsxRelationship relation;
+ relation.id = QStringLiteral("rId%1").arg(m_relationships.size()+1);
+ relation.type = type;
+ relation.target = target;
+ relation.targetMode = targetMode;
+
+ m_relationships.append(relation);
+}
+
+void Relationships::saveToXmlFile(QIODevice *device) const
+{
+ QXmlStreamWriter writer(device);
+
+ writer.writeStartDocument(QStringLiteral("1.0"), true);
+ writer.writeStartElement(QStringLiteral("Relationships"));
+ writer.writeAttribute(QStringLiteral("xmlns"), QStringLiteral("http://schemas.openxmlformats.org/package/2006/relationships"));
+ foreach (XlsxRelationship relation, m_relationships) {
+ writer.writeStartElement(QStringLiteral("Relationship"));
+ writer.writeAttribute(QStringLiteral("Id"), relation.id);
+ writer.writeAttribute(QStringLiteral("Type"), relation.type);
+ writer.writeAttribute(QStringLiteral("Target"), relation.target);
+ if (!relation.targetMode.isNull())
+ writer.writeAttribute(QStringLiteral("TargetMode"), relation.targetMode);
+ writer.writeEndElement();
+ }
+ writer.writeEndElement();//Relationships
+ writer.writeEndDocument();
+}
+
+QByteArray Relationships::saveToXmlData() const
+{
+ QByteArray data;
+ QBuffer buffer(&data);
+ buffer.open(QIODevice::WriteOnly);
+ saveToXmlFile(&buffer);
+
+ return data;
+}
+
+bool Relationships::loadFromXmlFile(QIODevice *device)
+{
+ clear();
+ QXmlStreamReader reader(device);
+ while (!reader.atEnd()) {
+ QXmlStreamReader::TokenType token = reader.readNext();
+ if (token == QXmlStreamReader::StartElement) {
+ if (reader.name() == QStringLiteral("Relationship")) {
+ QXmlStreamAttributes attributes = reader.attributes();
+ XlsxRelationship relationship;
+ relationship.id = attributes.value(QLatin1String("Id")).toString();
+ relationship.type = attributes.value(QLatin1String("Type")).toString();
+ relationship.target = attributes.value(QLatin1String("Target")).toString();
+ relationship.targetMode = attributes.value(QLatin1String("TargetMode")).toString();
+ m_relationships.append(relationship);
+ }
+ }
+
+ if (reader.hasError())
+ return false;
+ }
+ return true;
+}
+
+bool Relationships::loadFromXmlData(const QByteArray &data)
+{
+ QBuffer buffer;
+ buffer.setData(data);
+ buffer.open(QIODevice::ReadOnly);
+ return loadFromXmlFile(&buffer);
+}
+
+XlsxRelationship Relationships::getRelationshipById(const QString &id) const
+{
+ foreach (XlsxRelationship ship, m_relationships) {
+ if (ship.id == id)
+ return ship;
+ }
+ return XlsxRelationship();
+}
+
+void Relationships::clear()
+{
+ m_relationships.clear();
+}
+
+int Relationships::count() const
+{
+ return m_relationships.count();
+}
+
+bool Relationships::isEmpty() const
+{
+ return m_relationships.isEmpty();
+}
+
+} //namespace
diff --git a/platform/src/public/pub_excel/xlsx/xlsxrichstring.cpp b/platform/src/public/pub_excel/xlsx/xlsxrichstring.cpp
new file mode 100644
index 00000000..4d025948
--- /dev/null
+++ b/platform/src/public/pub_excel/xlsx/xlsxrichstring.cpp
@@ -0,0 +1,343 @@
+/****************************************************************************
+** 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 "xlsxrichstring.h"
+#include "xlsxrichstring_p.h"
+#include "xlsxformat_p.h"
+#include
+#include
+#include
+
+QT_BEGIN_NAMESPACE_XLSX
+
+RichStringPrivate::RichStringPrivate()
+ :_dirty(true)
+{
+
+}
+
+RichStringPrivate::RichStringPrivate(const RichStringPrivate &other)
+ :QSharedData(other), fragmentTexts(other.fragmentTexts)
+ ,fragmentFormats(other.fragmentFormats)
+ , _idKey(other.idKey()), _dirty(other._dirty)
+{
+
+}
+
+RichStringPrivate::~RichStringPrivate()
+{
+
+}
+
+/*!
+ \class RichString
+ \inmodule QtXlsx
+ \brief This class add support for the rich text string of the cell.
+*/
+
+/*!
+ Constructs a null string.
+ */
+RichString::RichString()
+ :d(new RichStringPrivate)
+{
+}
+
+/*!
+ Constructs a plain string with the given \a text.
+*/
+RichString::RichString(const QString text)
+ :d(new RichStringPrivate)
+{
+ addFragment(text, Format());
+}
+
+/*!
+ Constructs a copy of \a other.
+ */
+RichString::RichString(const RichString &other)
+ :d(other.d)
+{
+
+}
+
+/*!
+ Destructs the string.
+ */
+RichString::~RichString()
+{
+
+}
+
+/*!
+ Assigns \a other to this string and returns a reference to this string
+ */
+RichString &RichString::operator =(const RichString &other)
+{
+ this->d = other.d;
+ return *this;
+}
+
+/*!
+ Returns the rich string as a QVariant
+*/
+RichString::operator QVariant() const
+{
+ return QVariant(qMetaTypeId(), this);
+}
+
+/*!
+ Returns true if this is rich text string.
+ */
+bool RichString::isRichString() const
+{
+ if (fragmentCount() > 1) //Is this enough??
+ return true;
+ return false;
+}
+
+/*!
+ Returns true is this is an Null string.
+ */
+bool RichString::isNull() const
+{
+ return d->fragmentTexts.size() == 0;
+}
+
+/*!
+ Returns true is this is an empty string.
+ */
+bool RichString::isEmtpy() const
+{
+ foreach (const QString str, d->fragmentTexts) {
+ if (!str.isEmpty())
+ return false;
+ }
+
+ return true;
+}
+
+/*!
+ Converts to plain text string.
+*/
+QString RichString::toPlainString() const
+{
+ if (isEmtpy())
+ return QString();
+ if (d->fragmentTexts.size() == 1)
+ return d->fragmentTexts[0];
+
+ return d->fragmentTexts.join(QString());
+}
+
+/*!
+ Converts to html string
+*/
+QString RichString::toHtml() const
+{
+ //: Todo
+ return QString();
+}
+
+/*!
+ Replaces the entire contents of the document
+ with the given HTML-formatted text in the \a text string
+*/
+void RichString::setHtml(const QString &text)
+{
+ QTextDocument doc;
+ doc.setHtml(text);
+ QTextBlock block = doc.firstBlock();
+ QTextBlock::iterator it;
+ for (it = block.begin(); !(it.atEnd()); ++it) {
+ QTextFragment textFragment = it.fragment();
+ if (textFragment.isValid()) {
+ Format fmt;
+ fmt.setFont(textFragment.charFormat().font());
+ fmt.setFontColor(textFragment.charFormat().foreground().color());
+ addFragment(textFragment.text(), fmt);
+ }
+ }
+}
+
+/*!
+ Returns fragment count.
+ */
+int RichString::fragmentCount() const
+{
+ return d->fragmentTexts.size();
+}
+
+/*!
+ Appends a fragment with the given \a text and \a format.
+ */
+void RichString::addFragment(const QString &text, const Format &format)
+{
+ d->fragmentTexts.append(text);
+ d->fragmentFormats.append(format);
+ d->_dirty = true;
+}
+
+/*!
+ Returns fragment text at the position \a index.
+ */
+QString RichString::fragmentText(int index) const
+{
+ if (index < 0 || index >= fragmentCount())
+ return QString();
+
+ return d->fragmentTexts[index];
+}
+
+/*!
+ Returns fragment format at the position \a index.
+ */
+Format RichString::fragmentFormat(int index) const
+{
+ if (index < 0 || index >= fragmentCount())
+ return Format();
+
+ return d->fragmentFormats[index];
+}
+
+/*!
+ * \internal
+ */
+QByteArray RichStringPrivate::idKey() const
+{
+ if (_dirty) {
+ RichStringPrivate *rs = const_cast(this);
+ QByteArray bytes;
+ if (fragmentTexts.size() == 1) {
+ bytes = fragmentTexts[0].toUtf8();
+ } else {
+ //Generate a hash value base on QByteArray ?
+ bytes.append("@@QtXlsxRichString=");
+ for (int i=0; i_idKey = bytes;
+ rs->_dirty = false;
+ }
+
+ return _idKey;
+}
+
+/*!
+ Returns true if this string \a rs1 is equal to string \a rs2;
+ otherwise returns false.
+ */
+bool operator==(const RichString &rs1, const RichString &rs2)
+{
+ if (rs1.fragmentCount() != rs2.fragmentCount())
+ return false;
+
+ return rs1.d->idKey() == rs2.d->idKey();
+}
+
+/*!
+ Returns true if this string \a rs1 is not equal to string \a rs2;
+ otherwise returns false.
+ */
+bool operator!=(const RichString &rs1, const RichString &rs2)
+{
+ if (rs1.fragmentCount() != rs2.fragmentCount())
+ return true;
+
+ return rs1.d->idKey() != rs2.d->idKey();
+}
+
+/*!
+ * \internal
+ */
+bool operator<(const RichString &rs1, const RichString &rs2)
+{
+ return rs1.d->idKey() < rs2.d->idKey();
+}
+
+/*!
+ \overload
+ Returns true if this string \a rs1 is equal to string \a rs2;
+ otherwise returns false.
+ */
+bool operator ==(const RichString &rs1, const QString &rs2)
+{
+ if (rs1.fragmentCount() == 1 && rs1.fragmentText(0) == rs2) //format == 0
+ return true;
+
+ return false;
+}
+
+/*!
+ \overload
+ Returns true if this string \a rs1 is not equal to string \a rs2;
+ otherwise returns false.
+ */
+bool operator !=(const RichString &rs1, const QString &rs2)
+{
+ if (rs1.fragmentCount() == 1 && rs1.fragmentText(0) == rs2) //format == 0
+ return false;
+
+ return true;
+}
+
+/*!
+ \overload
+ Returns true if this string \a rs1 is equal to string \a rs2;
+ otherwise returns false.
+ */
+bool operator ==(const QString &rs1, const RichString &rs2)
+{
+ return rs2 == rs1;
+}
+
+/*!
+ \overload
+ Returns true if this string \a rs1 is not equal to string \a rs2;
+ otherwise returns false.
+ */
+bool operator !=(const QString &rs1, const RichString &rs2)
+{
+ return rs2 != rs1;
+}
+
+uint qHash(const RichString &rs, uint seed) Q_DECL_NOTHROW
+{
+ return qHash(rs.d->idKey(), seed);
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const RichString &rs)
+{
+ dbg.nospace() << "QXlsx::RichString(" << rs.d->fragmentTexts << ")";
+ return dbg.space();
+}
+#endif
+
+QT_END_NAMESPACE_XLSX
diff --git a/platform/src/public/pub_excel/xlsx/xlsxsharedstrings.cpp b/platform/src/public/pub_excel/xlsx/xlsxsharedstrings.cpp
new file mode 100644
index 00000000..129d0a1c
--- /dev/null
+++ b/platform/src/public/pub_excel/xlsx/xlsxsharedstrings.cpp
@@ -0,0 +1,400 @@
+/****************************************************************************
+** 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 "xlsxrichstring.h"
+#include "xlsxsharedstrings_p.h"
+#include "xlsxutility_p.h"
+#include "xlsxformat_p.h"
+#include "xlsxcolor_p.h"
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace QXlsx {
+
+/*
+ * Note that, when we open an existing .xlsx file (broken file?),
+ * duplicated string items may exist in the shared string table.
+ *
+ * In such case, the size of stringList will larger than stringTable.
+ * Duplicated items can be removed once we loaded all the worksheets.
+ */
+
+SharedStrings::SharedStrings(CreateFlag flag)
+ :AbstractOOXmlFile(flag)
+{
+ m_stringCount = 0;
+}
+
+int SharedStrings::count() const
+{
+ return m_stringCount;
+}
+
+bool SharedStrings::isEmpty() const
+{
+ return m_stringList.isEmpty();
+}
+
+int SharedStrings::addSharedString(const QString &string)
+{
+ return addSharedString(RichString(string));
+}
+
+int SharedStrings::addSharedString(const RichString &string)
+{
+ m_stringCount += 1;
+
+ if (m_stringTable.contains(string)) {
+ XlsxSharedStringInfo &item = m_stringTable[string];
+ item.count += 1;
+ return item.index;
+ }
+
+ int index = m_stringList.size();
+ m_stringTable[string] = XlsxSharedStringInfo(index);
+ m_stringList.append(string);
+ return index;
+}
+
+void SharedStrings::incRefByStringIndex(int idx)
+{
+ if (idx <0 || idx >= m_stringList.size()) {
+ qDebug("SharedStrings: invlid index");
+ return;
+ }
+
+ addSharedString(m_stringList[idx]);
+}
+
+/*
+ * Broken, don't use.
+ */
+void SharedStrings::removeSharedString(const QString &string)
+{
+ removeSharedString(RichString(string));
+}
+
+/*
+ * Broken, don't use.
+ */
+void SharedStrings::removeSharedString(const RichString &string)
+{
+ if (!m_stringTable.contains(string))
+ return;
+
+ m_stringCount -= 1;
+
+ XlsxSharedStringInfo &item = m_stringTable[string];
+ item.count -= 1;
+
+ if (item.count <= 0) {
+ for (int i=item.index+1; i= 0)
+ return m_stringList[index];
+ return RichString();
+}
+
+QList SharedStrings::getSharedStrings() const
+{
+ return m_stringList;
+}
+
+void SharedStrings::writeRichStringPart_rPr(QXmlStreamWriter &writer, const Format &format) const
+{
+ if (!format.hasFontData())
+ return;
+
+ if (format.fontBold())
+ writer.writeEmptyElement(QStringLiteral("b"));
+ if (format.fontItalic())
+ writer.writeEmptyElement(QStringLiteral("i"));
+ if (format.fontStrikeOut())
+ writer.writeEmptyElement(QStringLiteral("strike"));
+ if (format.fontOutline())
+ writer.writeEmptyElement(QStringLiteral("outline"));
+ if (format.boolProperty(FormatPrivate::P_Font_Shadow))
+ writer.writeEmptyElement(QStringLiteral("shadow"));
+ if (format.hasProperty(FormatPrivate::P_Font_Underline)) {
+ Format::FontUnderline u = format.fontUnderline();
+ if (u != Format::FontUnderlineNone) {
+ writer.writeEmptyElement(QStringLiteral("u"));
+ if (u== Format::FontUnderlineDouble)
+ writer.writeAttribute(QStringLiteral("val"), QStringLiteral("double"));
+ else if (u == Format::FontUnderlineSingleAccounting)
+ writer.writeAttribute(QStringLiteral("val"), QStringLiteral("singleAccounting"));
+ else if (u == Format::FontUnderlineDoubleAccounting)
+ writer.writeAttribute(QStringLiteral("val"), QStringLiteral("doubleAccounting"));
+ }
+ }
+ if (format.hasProperty(FormatPrivate::P_Font_Script)) {
+ Format::FontScript s = format.fontScript();
+ if (s != Format::FontScriptNormal) {
+ writer.writeEmptyElement(QStringLiteral("vertAlign"));
+ if (s == Format::FontScriptSuper)
+ writer.writeAttribute(QStringLiteral("val"), QStringLiteral("superscript"));
+ else
+ writer.writeAttribute(QStringLiteral("val"), QStringLiteral("subscript"));
+ }
+ }
+
+ if (format.hasProperty(FormatPrivate::P_Font_Size)) {
+ writer.writeEmptyElement(QStringLiteral("sz"));
+ writer.writeAttribute(QStringLiteral("val"), QString::number(format.fontSize()));
+ }
+
+ if (format.hasProperty(FormatPrivate::P_Font_Color)) {
+ XlsxColor color = format.property(FormatPrivate::P_Font_Color).value();
+ color.saveToXml(writer);
+ }
+
+ if (!format.fontName().isEmpty()) {
+ writer.writeEmptyElement(QStringLiteral("rFont"));
+ writer.writeAttribute(QStringLiteral("val"), format.fontName());
+ }
+ if (format.hasProperty(FormatPrivate::P_Font_Family)) {
+ writer.writeEmptyElement(QStringLiteral("family"));
+ writer.writeAttribute(QStringLiteral("val"), QString::number(format.intProperty(FormatPrivate::P_Font_Family)));
+ }
+
+ if (format.hasProperty(FormatPrivate::P_Font_Scheme)) {
+ writer.writeEmptyElement(QStringLiteral("scheme"));
+ writer.writeAttribute(QStringLiteral("val"), format.stringProperty(FormatPrivate::P_Font_Scheme));
+ }
+}
+
+void SharedStrings::saveToXmlFile(QIODevice *device) const
+{
+ QXmlStreamWriter writer(device);
+
+ if (m_stringList.size() != m_stringTable.size()) {
+ //Duplicated string items exist in m_stringList
+ //Clean up can not be done here, as the indices
+ //have been used when we save the worksheets part.
+ }
+
+ writer.writeStartDocument(QStringLiteral("1.0"), true);
+ writer.writeStartElement(QStringLiteral("sst"));
+ writer.writeAttribute(QStringLiteral("xmlns"), QStringLiteral("http://schemas.openxmlformats.org/spreadsheetml/2006/main"));
+ writer.writeAttribute(QStringLiteral("count"), QString::number(m_stringCount));
+ writer.writeAttribute(QStringLiteral("uniqueCount"), QString::number(m_stringList.size()));
+
+ foreach (RichString string, m_stringList) {
+ writer.writeStartElement(QStringLiteral("si"));
+ if (string.isRichString()) {
+ //Rich text string
+ for (int i=0; i
+** 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 "xlsxsimpleooxmlfile_p.h"
+#include