commit 4ec93ecb4118830e65dea5ddf46a9cafdd420403 Author: Debao Zhang Date: Fri Aug 23 23:12:46 2013 +0800 Long live QtXlsxWriter! diff --git a/.gitignore b/.gitignore new file mode 100755 index 0000000..37f30c0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,43 @@ +syntax: glob +*.pro.user* +*.autosave +*.app +*.moc +*.prl +Makefile* +doc/html/ +*.framework/ +*.xcodeproj/ +debug/ +release/ +qtc-gdbmacros/ +*.rej +*.orig +*.obj +*.swp +*.dll +*.exp +*.ilk +*.pdb +*.lib +Thumbs.db +moc_*.cpp +qrc_*.cpp +*.o +*.so.* +*.so +*.pdb +ui_*.h +*~ +.qmake.cache +lib/* +*.orig +*.exe +*.vcproj +*.vcproj.*.user +*_resource.rc +*.sln +*.idb +*.ncb +*.suo + diff --git a/examples/examples.pro b/examples/examples.pro new file mode 100755 index 0000000..bf12ebe --- /dev/null +++ b/examples/examples.pro @@ -0,0 +1,3 @@ +TEMPLATE = subdirs +SUBDIRS = hello + diff --git a/examples/hello/hello.pro b/examples/hello/hello.pro new file mode 100755 index 0000000..75736ae --- /dev/null +++ b/examples/hello/hello.pro @@ -0,0 +1,5 @@ +TARGET = hello + +include(../../src/qtxlsxwriter.pri) + +SOURCES += main.cpp diff --git a/examples/hello/main.cpp b/examples/hello/main.cpp new file mode 100755 index 0000000..f167a72 --- /dev/null +++ b/examples/hello/main.cpp @@ -0,0 +1,16 @@ +#include +#include "xlsxworkbook.h" +#include "xlsxworksheet.h" + +int main(int argc, char* argv[]) +{ +#ifdef Q_OS_MAC + QXlsx::Workbook workbook("../../../Test.xlsx"); +#else + QXlsx::Workbook workbook("Test.xlsx"); +#endif + QXlsx::Worksheet *sheet = workbook.addWorksheet(); + sheet->write("A1", "Hello Qt!"); + workbook.close(); + return 0; +} diff --git a/qtxlsxwriter.pro b/qtxlsxwriter.pro new file mode 100755 index 0000000..e69de29 diff --git a/src/qtxlsxwriter.pri b/src/qtxlsxwriter.pri new file mode 100755 index 0000000..85ec140 --- /dev/null +++ b/src/qtxlsxwriter.pri @@ -0,0 +1,32 @@ +INCLUDEPATH += $$PWD +DEPENDPATH += $$PWD + +QT += core gui gui-private + +HEADERS += $$PWD/xlsxdocprops_p.h \ + $$PWD/xlsxrelationships_p.h \ + $$PWD/xlsxutility_p.h \ + $$PWD/xlsxsharedstrings_p.h \ + $$PWD/xmlstreamwriter_p.h \ + $$PWD/xlsxcontenttypes_p.h \ + $$PWD/xlsxtheme_p.h \ + $$PWD/xlsxformat.h \ + $$PWD/xlsxworkbook.h \ + $$PWD/xlsxstyles_p.h \ + $$PWD/xlsxworksheet.h \ + $$PWD/zipwriter_p.h \ + $$PWD/xlsxpackage_p.h + +SOURCES += $$PWD/xlsxdocprops.cpp \ + $$PWD/xlsxrelationships.cpp \ + $$PWD/xlsxutility.cpp \ + $$PWD/xlsxsharedstrings.cpp \ + $$PWD/xmlstreamwriter.cpp \ + $$PWD/xlsxcontenttypes.cpp \ + $$PWD/xlsxtheme.cpp \ + $$PWD/xlsxformat.cpp \ + $$PWD/xlsxstyles.cpp \ + $$PWD/xlsxworkbook.cpp \ + $$PWD/xlsxworksheet.cpp \ + $$PWD/zipwriter.cpp \ + $$PWD/xlsxpackage.cpp diff --git a/src/qxlsxwriter.cpp b/src/qxlsxwriter.cpp new file mode 100755 index 0000000..f8b50f6 --- /dev/null +++ b/src/qxlsxwriter.cpp @@ -0,0 +1,6 @@ +#include "qxlsxwriter.h" + +QXlsxWriter::QXlsxWriter(QObject *parent) : + QObject(parent) +{ +} diff --git a/src/qxlsxwriter.h b/src/qxlsxwriter.h new file mode 100755 index 0000000..f75bdc2 --- /dev/null +++ b/src/qxlsxwriter.h @@ -0,0 +1,23 @@ +#ifndef QXLSXWRITER_H +#define QXLSXWRITER_H + +#include + +class QXlsxWriter : public QObject +{ + Q_OBJECT +public: + explicit QXlsxWriter(QObject *parent = 0); + +// void worksheets(); + +signals: + +public slots: +// void addWorksheet(QString name); +// void addFormat(); +// void addChart(); +// void setProperties(); +}; + +#endif // QXLSXWRITER_H diff --git a/src/xlsxcontenttypes.cpp b/src/xlsxcontenttypes.cpp new file mode 100755 index 0000000..dfe27c6 --- /dev/null +++ b/src/xlsxcontenttypes.cpp @@ -0,0 +1,144 @@ +/**************************************************************************** +** 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. +** +****************************************************************************/ +#include "xlsxcontenttypes_p.h" +#include "xmlstreamwriter_p.h" +#include +#include + +namespace QXlsx { + +ContentTypes::ContentTypes() +{ + m_package_prefix = "application/vnd.openxmlformats-package."; + m_document_prefix = "application/vnd.openxmlformats-officedocument."; + + m_defaults.insert("rels", m_package_prefix + "relationships+xml"); + m_defaults.insert("xml", "application/xml"); + + m_overrides.insert("/docProps/app.xml", m_document_prefix + "extended-properties+xml"); + m_overrides.insert("/docProps/core.xml", m_package_prefix + "core-properties+xml"); + m_overrides.insert("/xl/styles.xml", m_document_prefix + "spreadsheetml.styles+xml"); + m_overrides.insert("/xl/theme/theme1.xml", m_document_prefix + "theme+xml"); + m_overrides.insert("/xl/workbook.xml", m_document_prefix + "spreadsheetml.sheet.main+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::addWorksheetName(const QString &name) +{ + addOverride(QString("/xl/worksheets/%1.xml").arg(name), m_document_prefix + "spreadsheetml.worksheet+xml"); +} + +void ContentTypes::addChartsheetName(const QString &name) +{ + addOverride(QString("/xl/chartsheets/%1.xml").arg(name), m_document_prefix + "spreadsheetml.chartsheet+xml"); +} + +void ContentTypes::addChartName(const QString &name) +{ + addOverride(QString("/xl/charts/%1.xml").arg(name), m_document_prefix + "drawingml.chart+xml"); +} + +void ContentTypes::addCommentName(const QString &name) +{ + addOverride(QString("/xl/%1.xml").arg(name), m_document_prefix + "spreadsheetml.comments+xml"); +} + +void ContentTypes::addImageTypes(const QStringList &imageTypes) +{ + foreach (QString type, imageTypes) + addOverride(type, "image/" + type); +} + +void ContentTypes::addTableName(const QString &name) +{ + addOverride(QString("/xl/tables/%1.xml").arg(name), m_document_prefix + "spreadsheetml.table+xml"); +} + +void ContentTypes::addSharedString() +{ + addOverride("/xl/sharedStrings.xml", m_document_prefix + "spreadsheetml.sharedStrings+xml"); +} + +void ContentTypes::addVmlName() +{ + addOverride("vml", m_document_prefix + "vmlDrawing"); +} + +void ContentTypes::addCalcChain() +{ + addOverride("/xl/calcChain.xml", m_document_prefix + "spreadsheetml.calcChain+xml"); +} + +void ContentTypes::addVbaProject() +{ + //:TODO + addOverride("bin", "application/vnd.ms-office.vbaProject"); +} + +void ContentTypes::saveToXmlFile(QIODevice *device) +{ + XmlStreamWriter writer(device); + + writer.writeStartDocument("1.0", true); + writer.writeStartElement("Types"); + writer.writeAttribute("xmlns", "http://schemas.openxmlformats.org/package/2006/content-types"); + + { + QMapIterator it(m_defaults); + while(it.hasNext()) { + it.next(); + writer.writeStartElement("Default"); + writer.writeAttribute("Extension", it.key()); + writer.writeAttribute("ContentType", it.value()); + writer.writeEndElement();//Default + } + } + + { + QMapIterator it(m_overrides); + while(it.hasNext()) { + it.next(); + writer.writeStartElement("Override"); + writer.writeAttribute("PartName", it.key()); + writer.writeAttribute("ContentType", it.value()); + writer.writeEndElement(); //Override + } + } + + writer.writeEndElement();//Types + writer.writeEndDocument(); + +} + +} //namespace QXlsx diff --git a/src/xlsxcontenttypes_p.h b/src/xlsxcontenttypes_p.h new file mode 100755 index 0000000..6e0bd26 --- /dev/null +++ b/src/xlsxcontenttypes_p.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** 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. +** +****************************************************************************/ +#ifndef XLSXCONTENTTYPES_H +#define XLSXCONTENTTYPES_H + +#include +#include +#include + +class QIODevice; + +namespace QXlsx { + +class ContentTypes +{ +public: + ContentTypes(); + + void addDefault(const QString &key, const QString &value); + void addOverride(const QString &key, const QString &value); + + //Convenient funcation for addOverride() + void addWorksheetName(const QString &name); + void addChartsheetName(const QString &name); + void addChartName(const QString &name); + void addDrawingName(const QString &name); + void addCommentName(const QString &name); + void addImageTypes(const QStringList &imageTypes); + void addTableName(const QString &name); + void addSharedString(); + void addVmlName(); + void addCalcChain(); + void addVbaProject(); + + void saveToXmlFile(QIODevice *device); + +private: + QMap m_defaults; + QMap m_overrides; + + QString m_package_prefix; + QString m_document_prefix; +}; + +} +#endif // XLSXCONTENTTYPES_H diff --git a/src/xlsxdocprops.cpp b/src/xlsxdocprops.cpp new file mode 100755 index 0000000..922ab81 --- /dev/null +++ b/src/xlsxdocprops.cpp @@ -0,0 +1,129 @@ +/**************************************************************************** +** 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. +** +****************************************************************************/ +#include "xlsxdocprops_p.h" +#include "xmlstreamwriter_p.h" + +#include +#include +#include +namespace QXlsx { + +DocProps::DocProps(QObject *parent) : + QObject(parent) +{ +} + +void DocProps::addPartTitle(const QString &title) +{ + m_titlesOfPartsList.append(title); +} + +void DocProps::addHeadingPair(const QString &name, int value) +{ + m_headingPairsList.append(qMakePair(name, value)); +} + + +void DocProps::saveToXmlFile_App(QIODevice *device) +{ + XmlStreamWriter writer(device); + + writer.writeStartDocument("1.0", true); + writer.writeStartElement("Properties"); + writer.writeAttribute("xmlns", "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties"); + writer.writeAttribute("xmlns:vt", "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"); + writer.writeTextElement("Application", "Microsoft Excel"); + writer.writeTextElement("DocSecurity", "0"); + writer.writeTextElement("ScaleCrop", "false"); + + writer.writeStartElement("HeadingPairs"); + writer.writeStartElement("vt:vector"); + writer.writeAttribute("size", QString::number(m_headingPairsList.size()*2)); + writer.writeAttribute("baseType", "variant"); + typedef QPair PairType; //Make foreach happy + foreach (PairType pair, m_headingPairsList) { + writer.writeStartElement("vt:variant"); + writer.writeTextElement("vt:lpstr", pair.first); + writer.writeEndElement(); //vt:variant + writer.writeStartElement("vt:variant"); + writer.writeTextElement("vt:i4", QString::number(pair.second)); + writer.writeEndElement(); //vt:variant + } + writer.writeEndElement();//vt:vector + writer.writeEndElement();//HeadingPairs + + writer.writeStartElement("TitlesOfParts"); + writer.writeStartElement("vt:vector"); + writer.writeAttribute("size", QString::number(m_titlesOfPartsList.size())); + writer.writeAttribute("baseType", "lpstr"); + foreach (QString title, m_titlesOfPartsList) + writer.writeTextElement("vt:lpstr", title); + writer.writeEndElement();//vt:vector + writer.writeEndElement();//TitlesOfParts + + writer.writeTextElement("Company", ""); + writer.writeTextElement("LinksUpToDate", "false"); + writer.writeTextElement("SharedDoc", "false"); + writer.writeTextElement("HyperlinksChanged", "false"); + writer.writeTextElement("AppVersion", "12.0000"); + writer.writeEndElement(); //Properties + writer.writeEndDocument(); +} + +void DocProps::saveToXmlFile_Core(QIODevice *device) +{ + XmlStreamWriter writer(device); + + writer.writeStartDocument("1.0", true); + writer.writeStartElement("cp:coreProperties"); + writer.writeAttribute("xmlns:cp", "http://schemas.openxmlformats.org/package/2006/metadata/core-properties"); + writer.writeAttribute("xmlns:dc", "http://purl.org/dc/elements/1.1/"); + writer.writeAttribute("xmlns:dcterms", "http://purl.org/dc/terms/"); + writer.writeAttribute("xmlns:dcmitype", "http://purl.org/dc/dcmitype/"); + writer.writeAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); + writer.writeTextElement("dc:title", ""); + writer.writeTextElement("dc:subject", ""); + writer.writeTextElement("dc:creator", "QXlsxWriter"); + writer.writeTextElement("cp:keywords", ""); + writer.writeTextElement("dc:description", ""); + writer.writeTextElement("cp:lastModifiedBy", ""); + + writer.writeStartElement("dcterms:created"); + writer.writeAttribute("xsi:type", "dcterms:W3CDTF"); + writer.writeCharacters(QDateTime::currentDateTime().toString(Qt::ISODate)); + writer.writeEndElement();//dcterms:created + + writer.writeStartElement("dcterms:modified"); + writer.writeAttribute("xsi:type", "dcterms:W3CDTF"); + writer.writeCharacters(QDateTime::currentDateTime().toString(Qt::ISODate)); + writer.writeEndElement();//dcterms:created + + writer.writeTextElement("cp", "category", ""); + writer.writeTextElement("cp", "contentStatus", ""); + writer.writeEndElement(); //cp:coreProperties + writer.writeEndDocument(); +} + +} //namespace diff --git a/src/xlsxdocprops_p.h b/src/xlsxdocprops_p.h new file mode 100755 index 0000000..6592caf --- /dev/null +++ b/src/xlsxdocprops_p.h @@ -0,0 +1,57 @@ +/**************************************************************************** +** 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. +** +****************************************************************************/ +#ifndef XLSXDOCPROPS_H +#define XLSXDOCPROPS_H + +#include +#include +#include +#include + +class QIODevice; + +namespace QXlsx { + +class DocProps : public QObject +{ + Q_OBJECT +public: + explicit DocProps(QObject *parent = 0); + +signals: + +public slots: + void addPartTitle(const QString &title); + void addHeadingPair(const QString &name, int value); + void saveToXmlFile_App(QIODevice *device); + void saveToXmlFile_Core(QIODevice *device); + +private: + QStringList m_titlesOfPartsList; + QList > m_headingPairsList; +}; + +} +#endif // XLSXDOCPROPS_H diff --git a/src/xlsxformat.cpp b/src/xlsxformat.cpp new file mode 100755 index 0000000..a08cca1 --- /dev/null +++ b/src/xlsxformat.cpp @@ -0,0 +1,123 @@ +/**************************************************************************** +** 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. +** +****************************************************************************/ +#include "xlsxformat.h" + +namespace QXlsx { + +Format::Format(QObject *parent) : + QObject(parent) +{ + m_is_dxf_fomat = false; + + m_xf_index = 0; + m_dxf_index = 0; + + m_num_format_index = 0; + + m_has_font = false; + m_font_index = 0; + m_font_family = 2; + m_font_scheme = "minor"; + + m_font.setFamily("Calibri"); + m_font.setPointSize(11); + + m_theme = 0; + m_color_indexed = 0; + + m_has_fill = false; + m_fill_index = 0; + + m_has_borders = false; + m_border_index = false; +} + +bool Format::isDxfFormat() const +{ + return m_is_dxf_fomat; +} + +void Format::setFont(const QFont &font) +{ + m_font = font; +} + +void Format::setForegroundColor(const QColor &color) +{ + m_fg_color = color; +} + +void Format::setBackgroundColor(const QColor &color) +{ + m_bg_color = color; +} + +QString Format::fontName() const +{ + return m_font.family(); +} + +bool Format::bold() const +{ + return m_font.weight() == QFont::Bold; +} + +bool Format::italic() const +{ + return m_font.italic(); +} + +bool Format::fontOutline() const +{ + return false; +} + +bool Format::fontShadow() const +{ + return false; +} + +bool Format::fontStrikout() const +{ + return m_font.strikeOut(); +} + +bool Format::fontUnderline() const +{ + return m_font.underline(); +} + +QColor Format::fontColor() const +{ + return m_font_color; +} + +int Format::fontSize() const +{ + return m_font.pointSize(); +} + + +} // namespace QXlsx diff --git a/src/xlsxformat.h b/src/xlsxformat.h new file mode 100755 index 0000000..51e2702 --- /dev/null +++ b/src/xlsxformat.h @@ -0,0 +1,107 @@ +/**************************************************************************** +** 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. +** +****************************************************************************/ +#ifndef QXLSX_FORMAT_H +#define QXLSX_FORMAT_H + +#include +#include +#include + +namespace QXlsx { + +class Styles; + +class Format : public QObject +{ + Q_OBJECT +public: + void setFont(const QFont &font); + void setForegroundColor(const QColor &color); + void setBackgroundColor(const QColor &color); + +private: + friend class Styles; + explicit Format(QObject *parent = 0); + + bool isDxfFormat() const; + + //num + int numFormatIndex() const {return m_num_format_index;} + + //fonts + bool hasFont() const {return m_has_font;} + int fontIndex() const {return m_font_index;} + QString fontName() const; + bool bold() const; + bool italic() const; + bool fontStrikout() const; + bool fontOutline() const; + bool fontShadow() const; + bool fontUnderline() const; + QColor fontColor() const; + int fontSize() const; + int fontFamily() const{return m_font_family;} + int theme() const {return m_theme;} + int colorIndexed() const {return m_color_indexed;} + QString fontScheme() const {return m_font_scheme;} + void setHasFont(bool has) {m_has_font=has;} + + //fills + bool hasFill() const {return m_has_fill;} + int fillIndex() const {return m_fill_index;} + + //borders + bool hasBorders() const {return m_has_borders;} + void setHasBorder(bool has) {m_has_borders=has;} + int borderIndex() const {return m_border_index;} + + bool m_is_dxf_fomat; + + int m_xf_index; + int m_dxf_index; + + int m_num_format_index; + + bool m_has_font; + int m_font_index; + QFont m_font; + int m_font_family; + QString m_font_scheme; + QColor m_font_color; + QColor m_bg_color; + QColor m_fg_color; + int m_theme; + int m_color_indexed; + + bool m_has_fill; + int m_fill_index; + + bool m_has_borders; + int m_border_index; +}; + +} // namespace QXlsx + +#endif // QXLSX_FORMAT_H diff --git a/src/xlsxpackage.cpp b/src/xlsxpackage.cpp new file mode 100644 index 0000000..6998c22 --- /dev/null +++ b/src/xlsxpackage.cpp @@ -0,0 +1,274 @@ +/**************************************************************************** +** 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. +** +****************************************************************************/ +#include "xlsxpackage_p.h" +#include "xlsxworkbook.h" +#include "xlsxworksheet.h" +#include "xlsxcontenttypes_p.h" +#include "xlsxsharedstrings_p.h" +#include "xlsxdocprops_p.h" +#include "xlsxtheme_p.h" +#include "xlsxstyles_p.h" +#include "xlsxrelationships_p.h" +#include "zipwriter_p.h" +#include +#include + +namespace QXlsx { + +/* + 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. +*/ + +Package::Package(Workbook *workbook) : + m_workbook(workbook) +{ + m_worksheet_count = 0; + m_chartsheet_count = 0; + foreach (Worksheet *sheet, m_workbook->worksheets()) { + if (sheet->isChartsheet()) + m_chartsheet_count += 1; + else + m_worksheet_count += 1; + } +} + +bool Package::createPackage(const QString &packageName) +{ + QString fileName = packageName.isEmpty() ? m_workbook->fileName() : packageName; + ZipWriter zipWriter(fileName); + + writeWorksheetFiles(zipWriter); +// writeChartsheetFiles(zipWriter); + writeWorkbookFile(zipWriter); +// writeChartFiles(zipWriter); +// writeDrawingFiles(zipWriter); +// writeVmlFiles(zipWriter); +// writeCommentFiles(zipWriter); +// writeTableFiles(zipWriter); + writeSharedStringsFile(zipWriter); + writeDocPropsFiles(zipWriter); + writeContentTypesFiles(zipWriter); + writeStylesFiles(zipWriter); + writeThemeFile(zipWriter); + writeRootRelsFile(zipWriter); + writeWorkbookRelsFile(zipWriter); + writeWorksheetRelsFile(zipWriter); +// writeChartsheetRelsFile(zipWriter); +// writeImageFiles(zipWriter); +// writeVbaProjectFiles(zipWriter); + + zipWriter.close(); + return true; +} + +void Package::writeWorksheetFiles(ZipWriter &zipWriter) +{ + int index = 1; + foreach (Worksheet *sheet, m_workbook->worksheets()) { + if (sheet->isChartsheet()) + continue; + + QByteArray data; + QBuffer buffer(&data); + buffer.open(QIODevice::WriteOnly); + sheet->saveToXmlFile(&buffer); + zipWriter.addFile(QString("xl/worksheets/sheet%1.xml").arg(index), data); + index += 1; + } +} + +void Package::writeWorkbookFile(ZipWriter &zipWriter) +{ + QByteArray data; + QBuffer buffer(&data); + buffer.open(QIODevice::WriteOnly); + m_workbook->saveToXmlFile(&buffer); + zipWriter.addFile("xl/workbook.xml", data); +} + +void Package::writeContentTypesFiles(ZipWriter &zipWriter) +{ + ContentTypes content; + + int worksheet_index = 1; + foreach (Worksheet *sheet, m_workbook->worksheets()) { + if (sheet->isChartsheet()) { + + } else { + content.addWorksheetName(QString("sheet%1").arg(worksheet_index)); + worksheet_index += 1; + } + } + + if (m_workbook->sharedStrings()->count()) + content.addSharedString(); + + QByteArray data; + QBuffer buffer(&data); + buffer.open(QIODevice::WriteOnly); + content.saveToXmlFile(&buffer); + zipWriter.addFile("[Content_Types].xml", data); +} + +void Package::writeDocPropsFiles(ZipWriter &zipWriter) +{ + DocProps props; + + if (m_worksheet_count) + props.addHeadingPair("Worksheets", m_worksheet_count); + if (m_chartsheet_count) + props.addHeadingPair("Chartsheets", m_chartsheet_count); + + //Add worksheet parts + foreach (Worksheet *sheet, m_workbook->worksheets()){ + if (!sheet->isChartsheet()) + props.addPartTitle(sheet->name()); + } + + //Add the chartsheet parts + foreach (Worksheet *sheet, m_workbook->worksheets()){ + if (sheet->isChartsheet()) + props.addPartTitle(sheet->name()); + } + + QByteArray data1; + QBuffer buffer1(&data1); + buffer1.open(QIODevice::WriteOnly); + props.saveToXmlFile_App(&buffer1); + zipWriter.addFile("docProps/app.xml", data1); + + QByteArray data2; + QBuffer buffer2(&data2); + buffer2.open(QIODevice::WriteOnly); + props.saveToXmlFile_Core(&buffer2); + zipWriter.addFile("docProps/core.xml", data2); +} + +void Package::writeSharedStringsFile(ZipWriter &zipWriter) +{ + QByteArray data; + QBuffer buffer(&data); + buffer.open(QIODevice::WriteOnly); + m_workbook->sharedStrings()->saveToXmlFile(&buffer); + zipWriter.addFile("xl/sharedStrings.xml", data); +} + +void Package::writeStylesFiles(ZipWriter &zipWriter) +{ + QByteArray data; + QBuffer buffer(&data); + buffer.open(QIODevice::WriteOnly); + m_workbook->styles()->saveToXmlFile(&buffer); + zipWriter.addFile("xl/styles.xml", data); +} + +void Package::writeThemeFile(ZipWriter &zipWriter) +{ + QByteArray data; + QBuffer buffer(&data); + buffer.open(QIODevice::WriteOnly); + Theme().saveToXmlFile(&buffer); + zipWriter.addFile("xl/theme/theme1.xml", data); +} + +void Package::writeRootRelsFile(ZipWriter &zipWriter) +{ + Relationships rels; + rels.addDocumentRelationship("/officeDocument", "xl/workbook.xml"); + rels.addPackageRelationship("/metadata/core-properties", "docProps/core.xml"); + rels.addDocumentRelationship("/extended-properties", "docProps/app.xml"); + + QByteArray data; + QBuffer buffer(&data); + buffer.open(QIODevice::WriteOnly); + rels.saveToXmlFile(&buffer); + zipWriter.addFile("_rels/.rels", data); +} + +void Package::writeWorkbookRelsFile(ZipWriter &zipWriter) +{ + Relationships rels; + + int worksheet_index = 1; + int chartsheet_index = 1; + foreach (Worksheet *sheet, m_workbook->worksheets()) { + if (sheet->isChartsheet()) { + rels.addDocumentRelationship("/chartsheet", QString("chartsheets/sheet%1.xml").arg(chartsheet_index)); + chartsheet_index += 1; + } else { + rels.addDocumentRelationship("/worksheet", QString("worksheets/sheet%1.xml").arg(worksheet_index)); + worksheet_index += 1; + } + } + + rels.addDocumentRelationship("/theme", "theme/theme1.xml"); + rels.addDocumentRelationship("/styles", "styles.xml"); + + if (m_workbook->sharedStrings()->count()) + rels.addDocumentRelationship("/sharedStrings", "sharedStrings.xml"); + + QByteArray data; + QBuffer buffer(&data); + buffer.open(QIODevice::WriteOnly); + rels.saveToXmlFile(&buffer); + zipWriter.addFile("xl/_rels/workbook.xml.rels", data); +} + +void Package::writeWorksheetRelsFile(ZipWriter &zipWriter) +{ + +} +} // namespace QXlsx diff --git a/src/xlsxpackage_p.h b/src/xlsxpackage_p.h new file mode 100644 index 0000000..75e86f5 --- /dev/null +++ b/src/xlsxpackage_p.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** 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. +** +****************************************************************************/ +#ifndef QXLSX_PACKAGE_H +#define QXLSX_PACKAGE_H + +#include + +namespace QXlsx { + +class Workbook; +class ZipWriter; + +class Package +{ +public: + Package(Workbook *workbook); + + bool createPackage(const QString &packageName=QString()); + +private: + void writeWorksheetFiles(ZipWriter &zipWriter); +// void writeChartsheetFiles(ZipWriter &zipWriter); + void writeWorkbookFile(ZipWriter &zipWriter); +// void writeChartFiles(ZipWriter &zipWriter); +// void writeDrawingFiles(ZipWriter &zipWriter); +// void writeVmlFiles(ZipWriter &zipWriter); +// void writeCommentFiles(ZipWriter &zipWriter); +// void writeTableFiles(ZipWriter &zipWriter); + void writeSharedStringsFile(ZipWriter &zipWriter); + void writeDocPropsFiles(ZipWriter &zipWriter); + void writeContentTypesFiles(ZipWriter &zipWriter); + void writeStylesFiles(ZipWriter &zipWriter); + void writeThemeFile(ZipWriter &zipWriter); + void writeRootRelsFile(ZipWriter &zipWriter); + void writeWorkbookRelsFile(ZipWriter &zipWriter); + void writeWorksheetRelsFile(ZipWriter &zipWriter); +// void writeChartsheetRelsFile(ZipWriter &zipWriter); +// void writeImageFiles(ZipWriter &zipWriter); +// void writeVbaProjectFiles(ZipWriter &zipWriter); + + Workbook * m_workbook; + int m_worksheet_count; + int m_chartsheet_count; +}; + +} // namespace QXlsx + +#endif // QXLSX_PACKAGE_H diff --git a/src/xlsxrelationships.cpp b/src/xlsxrelationships.cpp new file mode 100755 index 0000000..7259cb4 --- /dev/null +++ b/src/xlsxrelationships.cpp @@ -0,0 +1,92 @@ +/**************************************************************************** +** 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. +** +****************************************************************************/ +#include "xlsxrelationships_p.h" +#include "xmlstreamwriter_p.h" +#include +#include + +namespace QXlsx { + +Relationships::Relationships(QObject *parent) : + QObject(parent) +{ +} + +void Relationships::addDocumentRelationship(const QString &relativeType, const QString &target) +{ + QString type = "http://schemas.openxmlformats.org/officeDocument/2006/relationships" + relativeType; + addRelationship(type, target); +} + +void Relationships::addMsPackageRelationship(const QString &relativeType, const QString &target) +{ + QString type = "http://schemas.microsoft.com/office/2006/relationships" + relativeType; + addRelationship(type, target); +} + +void Relationships::addPackageRelationship(const QString &relativeType, const QString &target) +{ + QString type = "http://schemas.openxmlformats.org/package/2006/relationships" + relativeType; + addRelationship(type, target); +} + +void Relationships::addWorksheetRelationship(const QString &relativeType, const QString &target, const QString &targetMode) +{ + QString type = "http://schemas.openxmlformats.org/officeDocument/2006/relationships" + relativeType; + addRelationship(type, target, targetMode); +} + +void Relationships::addRelationship(const QString &type, const QString &target, const QString &targetMode) +{ + XlsxRelationship relation; + relation.id = QString("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) +{ + XmlStreamWriter writer(device); + + writer.writeStartDocument("1.0", true); + writer.writeStartElement("Relationships"); + writer.writeAttribute("xmlns", "http://schemas.openxmlformats.org/package/2006/relationships"); + foreach (XlsxRelationship relation, m_relationships) { + writer.writeStartElement("Relationship"); + writer.writeAttribute("Id", relation.id); + writer.writeAttribute("Type", relation.type); + writer.writeAttribute("Target", relation.target); + if (!relation.targetMode.isNull()) + writer.writeAttribute("TargetMode", relation.targetMode); + writer.writeEndElement(); + } + writer.writeEndElement();//Relationships + writer.writeEndDocument(); +} + +} //namespace diff --git a/src/xlsxrelationships_p.h b/src/xlsxrelationships_p.h new file mode 100755 index 0000000..6c80a82 --- /dev/null +++ b/src/xlsxrelationships_p.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** 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. +** +****************************************************************************/ +#ifndef XLSXRELATIONSHIPS_H +#define XLSXRELATIONSHIPS_H + +#include +#include +class QIODevice; + +namespace QXlsx { + +struct XlsxRelationship +{ + QString id; + QString type; + QString target; + QString targetMode; +}; + +class Relationships : public QObject +{ + Q_OBJECT +public: + explicit Relationships(QObject *parent = 0); + +signals: + +public slots: + void addDocumentRelationship(const QString &relativeType, const QString &target); + void addPackageRelationship(const QString &relativeType, const QString &target); + void addMsPackageRelationship(const QString &relativeType, const QString &target); + void addWorksheetRelationship(const QString &relativeType, const QString &target, const QString &targetMode=QString()); + + void saveToXmlFile(QIODevice *device); +private: + void addRelationship(const QString &type, const QString &target, const QString &targetMode=QString()); + QList m_relationships; +}; + +} +#endif // XLSXRELATIONSHIPS_H diff --git a/src/xlsxsharedstrings.cpp b/src/xlsxsharedstrings.cpp new file mode 100755 index 0000000..dfc95c5 --- /dev/null +++ b/src/xlsxsharedstrings.cpp @@ -0,0 +1,102 @@ +/**************************************************************************** +** 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. +** +****************************************************************************/ +#include "xlsxsharedstrings_p.h" +#include "xmlstreamwriter_p.h" +#include +#include +#include +#include + +namespace QXlsx { + +SharedStrings::SharedStrings(QObject *parent) : + QObject(parent) +{ + m_stringCount = 0; +} + +int SharedStrings::count() const +{ + return m_stringCount; +} + +int SharedStrings::addSharedString(const QString &string) +{ + m_stringCount += 1; + + if (m_stringTable.contains(string)) + return m_stringTable[string]; + + int index = m_stringTable.size(); + m_stringTable[string] = index; + m_stringList.append(string); + return index; +} + +int SharedStrings::getSharedStringIndex(const QString &string) const +{ + return m_stringTable[string]; +} + +QString SharedStrings::getSharedString(int index) const +{ + return m_stringList[index]; +} + +QStringList SharedStrings::getSharedStrings() const +{ + return m_stringList; +} + +void SharedStrings::saveToXmlFile(QIODevice *device) const +{ + XmlStreamWriter writer(device); + + writer.writeStartDocument("1.0", true); + writer.writeStartElement("sst"); + writer.writeAttribute("xmlns", "http://schemas.openxmlformats.org/spreadsheetml/2006/main"); + writer.writeAttribute("count", QString::number(m_stringCount)); + writer.writeAttribute("uniqueCount", QString::number(m_stringTable.size())); + + foreach (QString string, m_stringList) { + writer.writeStartElement("si"); + if (string.contains(QRegularExpression("^")) || string.contains(QRegularExpression("$"))) { + //Rich text string, +// writer.writeCharacters(string); + } else { + writer.writeStartElement("t"); + if (string.contains(QRegularExpression("^\\s")) || string.contains(QRegularExpression("\\s$"))) + writer.writeAttribute("xml:space", "preserve"); + writer.writeCharacters(string); + writer.writeEndElement();//t + } + writer.writeEndElement();//si + } + + writer.writeEndElement(); //sst + writer.writeEndDocument(); +} + +} //namespace diff --git a/src/xlsxsharedstrings_p.h b/src/xlsxsharedstrings_p.h new file mode 100755 index 0000000..8d92707 --- /dev/null +++ b/src/xlsxsharedstrings_p.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** 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. +** +****************************************************************************/ +#ifndef XLSXSHAREDSTRINGS_H +#define XLSXSHAREDSTRINGS_H + +#include +#include +#include + +class QIODevice; + +namespace QXlsx { + +class SharedStrings : public QObject +{ + Q_OBJECT +public: + explicit SharedStrings(QObject *parent = 0); + int count() const; + +public slots: + int addSharedString(const QString &string); + int getSharedStringIndex(const QString &string) const; + QString getSharedString(int index) const; + QStringList getSharedStrings() const; + + void saveToXmlFile(QIODevice *device) const; + +private: + QHash m_stringTable; //for fast lookup + QStringList m_stringList; + int m_stringCount; +}; + +} +#endif // XLSXSHAREDSTRINGS_H diff --git a/src/xlsxstyles.cpp b/src/xlsxstyles.cpp new file mode 100755 index 0000000..3dfb5ea --- /dev/null +++ b/src/xlsxstyles.cpp @@ -0,0 +1,240 @@ +/**************************************************************************** +** 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. +** +****************************************************************************/ +#include "xlsxstyles_p.h" +#include "xlsxformat.h" +#include "xmlstreamwriter_p.h" +#include + +namespace QXlsx { + + +Styles::Styles(QObject *parent) : + QObject(parent) +{ + m_fill_count = 2; //Starts from 2 + m_borders_count = 1; + m_font_count = 1; + + //Add the default cell format + Format *format = addFormat(); + format->setHasFont(true); + format->setHasBorder(true); +} + +Format *Styles::addFormat() +{ + Format *format = new Format(this); + m_formats.append(format); + return format; +} + +void Styles::saveToXmlFile(QIODevice *device) +{ + //Todo + m_xf_formats = m_formats; + + XmlStreamWriter writer(device); + + writer.writeStartDocument("1.0", true); + writer.writeStartElement("styleSheet"); + writer.writeAttribute("xmlns", "http://schemas.openxmlformats.org/spreadsheetml/2006/main"); + +// writer.writeStartElement("numFmts"); +// writer.writeEndElement();//numFmts + + writeFonts(writer); + writeFills(writer); + writeBorders(writer); + + writer.writeStartElement("cellStyleXfs"); + writer.writeAttribute("count", "1"); + writer.writeStartElement("xf"); + writer.writeAttribute("numFmtId", "0"); + writer.writeAttribute("fontId", "0"); + writer.writeAttribute("fillId", "0"); + writer.writeAttribute("borderId", "0"); + writer.writeEndElement();//xf + writer.writeEndElement();//cellStyleXfs + + writeCellXfs(writer); + + writer.writeStartElement("cellStyles"); + writer.writeAttribute("count", "1"); + writer.writeStartElement("cellStyle"); + writer.writeAttribute("name", "Normal"); + writer.writeAttribute("xfId", "0"); + writer.writeAttribute("builtinId", "0"); + writer.writeEndElement();//cellStyle + writer.writeEndElement();//cellStyles + + writeDxfs(writer); + + writer.writeStartElement("tableStyles"); + writer.writeAttribute("count", "0"); + writer.writeAttribute("defaultTableStyle", "TableStyleMedium9"); + writer.writeAttribute("defaultPivotStyle", "PivotStyleLight16"); + writer.writeEndElement();//tableStyles + + writer.writeEndElement();//styleSheet + writer.writeEndDocument(); +} + +void Styles::writeFonts(XmlStreamWriter &writer) +{ + + writer.writeStartElement("fonts"); + writer.writeAttribute("count", QString::number(m_font_count)); + foreach (Format *format, m_xf_formats) { + if (format->hasFont()) { + writer.writeStartElement("font"); + if (format->bold()) + writer.writeEmptyElement("b"); + if (format->italic()) + writer.writeEmptyElement("i"); + if (format->fontStrikout()) + writer.writeEmptyElement("strike"); + if (format->fontOutline()) + writer.writeEmptyElement("outline"); + if (format->fontShadow()) + writer.writeEmptyElement("shadow"); + if (format->fontUnderline()) //More option + writer.writeEmptyElement("u"); + if (!format->isDxfFormat()) { + writer.writeEmptyElement("sz"); + writer.writeAttribute("val", QString::number(format->fontSize())); + } + + //font color + if (format->theme()) { + writer.writeEmptyElement("color"); + writer.writeAttribute("theme", QString::number(format->theme())); + } else if (format->colorIndexed()) { + writer.writeEmptyElement("color"); + writer.writeAttribute("indexed", QString::number(format->colorIndexed())); + } else if (format->fontColor().isValid()) { + writer.writeEmptyElement("color"); + QString color = format->fontColor().name(); + writer.writeAttribute("rgb", "FF"+color.mid(1));//remove # + } else if (!format->isDxfFormat()) { + writer.writeEmptyElement("color"); + writer.writeAttribute("theme", "1"); + } + + if (!format->isDxfFormat()) { + writer.writeEmptyElement("name"); + writer.writeAttribute("val", format->fontName()); + writer.writeEmptyElement("family"); + writer.writeAttribute("val", QString::number(format->fontFamily())); + if (format->fontName() == "Calibri") { + writer.writeEmptyElement("scheme"); + writer.writeAttribute("val", format->fontScheme()); + } + } + + writer.writeEndElement(); //font + } + } + writer.writeEndElement();//fonts +} + +void Styles::writeFills(XmlStreamWriter &writer) +{ + writer.writeStartElement("fills"); + writer.writeAttribute("count", QString::number(m_fill_count)); + writer.writeStartElement("fill"); + writer.writeEmptyElement("patternFill"); + writer.writeAttribute("patternType", "none"); + writer.writeEndElement();//fill + writer.writeStartElement("fill"); + writer.writeEmptyElement("patternFill"); + writer.writeAttribute("patternType", "gray125"); + writer.writeEndElement();//fill + foreach (Format *format, m_xf_formats) { + if (format->hasFill()) { + //:TODO + } + } + writer.writeEndElement(); //fills +} + +void Styles::writeBorders(XmlStreamWriter &writer) +{ + writer.writeStartElement("borders"); + writer.writeAttribute("count", QString::number(m_borders_count)); + foreach (Format *format, m_xf_formats) { + if (format->hasBorders()) { + writer.writeStartElement("border"); + writer.writeEmptyElement("left"); + writer.writeEmptyElement("right"); + writer.writeEmptyElement("top"); + writer.writeEmptyElement("bottom"); + if (!format->isDxfFormat()) { + writer.writeEmptyElement("diagonal"); + } + writer.writeEndElement();//border + } + } + writer.writeEndElement();//borders +} + +void Styles::writeCellXfs(XmlStreamWriter &writer) +{ + writer.writeStartElement("cellXfs"); + writer.writeAttribute("count", QString::number(m_xf_formats.size())); + foreach (Format *format, m_xf_formats) { + int num_fmt_id = format->numFormatIndex(); + int font_id = format->fontIndex(); + int fill_id = format->fillIndex(); + int border_id = format->borderIndex(); + int xf_id = 0; + writer.writeStartElement("xf"); + writer.writeAttribute("numFmtId", QString::number(num_fmt_id)); + writer.writeAttribute("fontId", QString::number(font_id)); + writer.writeAttribute("fillId", QString::number(fill_id)); + writer.writeAttribute("borderId", QString::number(border_id)); + writer.writeAttribute("xfId", QString::number(xf_id)); + if (format->numFormatIndex() > 0) + writer.writeAttribute("applyNumberFormat", "1"); + if (format->fontIndex() > 0) + writer.writeAttribute("applyFont", "1"); + if (format->fillIndex() > 0) + writer.writeAttribute("applyBorder", "1"); + writer.writeEndElement();//xf + } + writer.writeEndElement();//cellXfs +} + +void Styles::writeDxfs(XmlStreamWriter &writer) +{ + writer.writeStartElement("dxfs"); + writer.writeAttribute("count", QString::number(m_dxf_formats.size())); + foreach (Format *format, m_dxf_formats) { + writer.writeStartElement("dxf"); + writer.writeEndElement();//dxf + } + writer.writeEndElement(); //dxfs +} + +} //namespace QXlsx diff --git a/src/xlsxstyles_p.h b/src/xlsxstyles_p.h new file mode 100755 index 0000000..4642509 --- /dev/null +++ b/src/xlsxstyles_p.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** 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. +** +****************************************************************************/ +#ifndef XLSXSTYLES_H +#define XLSXSTYLES_H + +#include + +class QIODevice; + +namespace QXlsx { + +class Format; +class XmlStreamWriter; + +class Styles : public QObject +{ +public: + explicit Styles(QObject *parent=0); + Format *addFormat(); + + void saveToXmlFile(QIODevice *device); + +private: + void writeFonts(XmlStreamWriter &writer); + void writeFills(XmlStreamWriter &writer); + void writeBorders(XmlStreamWriter &writer); + void writeCellXfs(XmlStreamWriter &writer); + void writeDxfs(XmlStreamWriter &writer); + + + QList m_formats; + QList m_xf_formats; + QList m_dxf_formats; + + int m_font_count; + int m_fill_count; + int m_borders_count; +}; + +} +#endif // XLSXSTYLES_H diff --git a/src/xlsxtheme.cpp b/src/xlsxtheme.cpp new file mode 100755 index 0000000..a26e83f --- /dev/null +++ b/src/xlsxtheme.cpp @@ -0,0 +1,43 @@ +/**************************************************************************** +** 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. +** +****************************************************************************/ +#include "xlsxtheme_p.h" +#include + +namespace QXlsx { + +const char *contents = + "\x0a" + ; + +Theme::Theme() +{ +} + +void Theme::saveToXmlFile(QIODevice *device) +{ + device->write(contents); +} + +} diff --git a/src/xlsxtheme_p.h b/src/xlsxtheme_p.h new file mode 100755 index 0000000..f9f87b8 --- /dev/null +++ b/src/xlsxtheme_p.h @@ -0,0 +1,42 @@ +/**************************************************************************** +** 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. +** +****************************************************************************/ +#ifndef XLSXTHEME_H +#define XLSXTHEME_H + +#include +class QIODevice; + +namespace QXlsx { + +class Theme +{ +public: + Theme(); + + void saveToXmlFile(QIODevice *device); +}; + +} +#endif // XLSXTHEME_H diff --git a/src/xlsxutility.cpp b/src/xlsxutility.cpp new file mode 100755 index 0000000..c98d880 --- /dev/null +++ b/src/xlsxutility.cpp @@ -0,0 +1,111 @@ +/**************************************************************************** +** 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. +** +****************************************************************************/ +#include "xlsxutility_p.h" + +#include +#include +#include +#include + +namespace QXlsx { + +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; +} + +QPoint xl_cell_to_rowcol(const QString &cell_str) +{ + if (cell_str.isEmpty()) + return QPoint(0, 0); + QRegularExpression re("^([A-Z]{1,3})(\\d+)$"); + QRegularExpressionMatch match = re.match(cell_str); + if (match.hasMatch()) { + QString col_str = match.captured(1); + QString row_str = match.captured(2); + 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++; + } + + col--; + int row = row_str.toInt() - 1; + return QPoint(row, col); + } else { + return QPoint(-1, -1); //... + } +} + +QString xl_col_to_name(int col_num) +{ + col_num += 1; //Change to 1-index + QString col_str; + + int remainder; + while (col_num) { + remainder = col_num % 26; + if (remainder == 0) + remainder = 26; + col_str.prepend(QChar('A'+remainder-1)); + col_num = (col_num - 1) / 26; + } + + return col_str; +} + +QString xl_rowcol_to_cell(int row, int col, bool row_abs, bool col_abs) +{ + row += 1; //Change to 1-index + QString cell_str; + if (col_abs) + cell_str.append("$"); + cell_str.append(xl_col_to_name(col)); + if (row_abs) + cell_str.append("$"); + cell_str.append(QString::number(row)); + return cell_str; +} + +QString xl_rowcol_to_cell_fast(int row, int col) +{ + static QMap col_cache; + QString col_str; + if (col_cache.contains(col)) { + col_str = col_cache[col]; + } else { + col_str = xl_col_to_name(col); + col_cache[col] = col_str; + } + return col_str + QString::number(row+1); +} + +} //namespace QXlsx diff --git a/src/xlsxutility_p.h b/src/xlsxutility_p.h new file mode 100755 index 0000000..b7b9e2f --- /dev/null +++ b/src/xlsxutility_p.h @@ -0,0 +1,39 @@ +/**************************************************************************** +** 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. +** +****************************************************************************/ +#ifndef XLSXUTILITY_H +#define XLSXUTILITY_H + +class QPoint; +class QString; + +namespace QXlsx { + +int intPow(int x, int p); +QPoint xl_cell_to_rowcol(const QString &cell_str); +QString xl_col_to_name(int col_num); +QString xl_rowcol_to_cell(int row, int col, bool row_abs=false, bool col_abs=false); +QString xl_rowcol_to_cell_fast(int row, int col); +} //QXlsx +#endif // XLSXUTILITY_H diff --git a/src/xlsxworkbook.cpp b/src/xlsxworkbook.cpp new file mode 100755 index 0000000..88fec55 --- /dev/null +++ b/src/xlsxworkbook.cpp @@ -0,0 +1,234 @@ +/**************************************************************************** +** 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. +** +****************************************************************************/ +#include "xlsxworkbook.h" +#include "xlsxsharedstrings_p.h" +#include "xlsxworksheet.h" +#include "xlsxstyles_p.h" +#include "xlsxformat.h" +#include "xlsxpackage_p.h" +#include "xmlstreamwriter_p.h" + +namespace QXlsx { + +Workbook::Workbook(const QString &name, QObject *parent) : + QObject(parent), m_fileName(name) +{ + m_sharedStrings = new SharedStrings(this); + m_styles = new Styles(this); + + + m_x_window = 240; + m_y_window = 15; + m_window_width = 16095; + m_window_height = 9660; + + m_optimization_enabled = false; + m_strings_to_numbers_enabled = false; + m_activesheet = 0; + m_firstsheet = 0; + m_table_count = 0; + m_closed = false; +} + +Workbook::~Workbook() +{ + close(); +} + +void Workbook::close() +{ + if (m_closed) + return; + + m_closed = true; + saveWorkbook(); +} + +void Workbook::saveWorkbook() +{ + //Add a default worksheet if non have been added. + if (m_worksheets.size() == 0) + addWorksheet(); + + //Ensure that at least one worksheet has been selected. + if (m_activesheet == 0) { + m_worksheets[0]->setHidden(false); + m_worksheets[0]->setSelected(true); + } + + //Set the active sheet + foreach (Worksheet *sheet, m_worksheets) { + if (sheet->index() == m_activesheet) + sheet->setActived(true); + } + + + //Create the package based on current workbook + Package package(this); + package.createPackage(); +} + +QString Workbook::fileName() const +{ + return m_fileName; +} + +/*! + Reduces the amount of data stored in memory so + that large files can be written efficiently + + Note, in this mode a row of data is written and + then discarded when a cell in a new row is added + via one of the worksheet write_() methods. As such + data should be written in sequential row order once + this mode is on. + + It is used to optimise speed and reduce memory usage. + However, these design goals meant that it wasn’t easy + to implement features that many users requested such as + writing formatting and data separately. + + This feature is disabled by default. + */ +void Workbook::setOptimizationEnabled(bool enable) +{ + m_optimization_enabled = enable; +} + +bool Workbook::isOptimizationEnabled() const +{ + return m_optimization_enabled; +} + +/* + Enable the worksheet.write() method to convert strings + to numbers, where possible, using float() in order to avoid + an Excel warning about “Numbers Stored as Text”. + + The default is false + */ +void Workbook::setStringsToNumbersEnabled(bool enable) +{ + m_strings_to_numbers_enabled = enable; +} + +bool Workbook::isStringsToNumbersEnabled() const +{ + return m_strings_to_numbers_enabled; +} + +void Workbook::defineName(const QString &name, const QString &formula) +{ + +} + +Worksheet *Workbook::addWorksheet(const QString &name) +{ + QString worksheetName = name; + int index = m_worksheets.size()+1; + if (name.isEmpty()) + worksheetName = QString("Sheet%1").arg(index); + + Worksheet *sheet = new Worksheet(worksheetName, index, this); + m_worksheets.append(sheet); + return sheet; +} + +Format *Workbook::addFormat() +{ + return m_styles->addFormat(); +} + +QList Workbook::worksheets() const +{ + return m_worksheets; +} + +SharedStrings *Workbook::sharedStrings() +{ + return m_sharedStrings; +} + +Styles *Workbook::styles() +{ + return m_styles; +} + +void Workbook::saveToXmlFile(QIODevice *device) +{ + XmlStreamWriter writer(device); + + writer.writeStartDocument("1.0", true); + writer.writeStartElement("workbook"); + writer.writeAttribute("xmlns", "http://schemas.openxmlformats.org/spreadsheetml/2006/main"); + writer.writeAttribute("xmlns:r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships"); + + writer.writeEmptyElement("fileVersion"); + writer.writeAttribute("appName", "xl"); + writer.writeAttribute("lastEdited", "4"); + writer.writeAttribute("lowestEdited", "4"); + writer.writeAttribute("rupBuild", "4505"); +// writer.writeAttribute("codeName", "{37E998C4-C9E5-D4B9-71C8-EB1FF731991C}"); + + writer.writeEmptyElement("workbookPr"); + writer.writeAttribute("defaultThemeVersion", "124226"); + + writer.writeStartElement("bookViews"); + writer.writeEmptyElement("workbookView"); + writer.writeAttribute("xWindow", QString::number(m_x_window)); + writer.writeAttribute("yWindow", QString::number(m_y_window)); + writer.writeAttribute("windowWidth", QString::number(m_window_width)); + writer.writeAttribute("windowHeight", QString::number(m_window_height)); + //Store the firstSheet when it isn't the default + if (m_firstsheet > 0) + writer.writeAttribute("firstSheet", QString::number(m_firstsheet + 1)); + //Store the activeTab when it isn't the first sheet + if (m_activesheet > 0) + writer.writeAttribute("activeTab", QString::number(m_activesheet)); + writer.writeEndElement();//bookviews + + writer.writeStartElement("sheets"); + foreach (Worksheet *sheet, m_worksheets) { + writer.writeEmptyElement("sheet"); + writer.writeAttribute("name", sheet->name()); + writer.writeAttribute("sheetId", QString::number(sheet->index())); + if (sheet->isHidden()) + writer.writeAttribute("state", "hidden"); + writer.writeAttribute("r:id", QString("rId%1").arg(sheet->index())); + } + writer.writeEndElement();//sheets + +// writer.writeStartElement("definedNames"); +// writer.writeEndElement();//definedNames + + writer.writeStartElement("calcPr"); + writer.writeAttribute("calcId", "124519"); + writer.writeEndElement(); //calcPr + + writer.writeEndElement();//workbook + writer.writeEndDocument(); +} + +} //namespace diff --git a/src/xlsxworkbook.h b/src/xlsxworkbook.h new file mode 100755 index 0000000..eb89351 --- /dev/null +++ b/src/xlsxworkbook.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** 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. +** +****************************************************************************/ +#ifndef XLSXWORKBOOK_H +#define XLSXWORKBOOK_H + +#include +#include +class QIODevice; + +namespace QXlsx { + +class Worksheet; +class Format; +class SharedStrings; +class Styles; +class Package; + +class Workbook : public QObject +{ + Q_OBJECT +public: + Workbook(const QString &name, QObject *parent=0); + ~Workbook(); + + Worksheet *addWorksheet(const QString &name = QString()); + Format *addFormat(); +// void addChart(); + void defineName(const QString &name, const QString &formula); + void setOptimizationEnabled(bool enable=true); + void setStringsToNumbersEnabled(bool enable=true); + + void close(); + +private: + friend class Package; + friend class Worksheet; + + QList worksheets() const; + SharedStrings *sharedStrings(); + Styles *styles(); + QString fileName() const; + bool isOptimizationEnabled() const; + bool isStringsToNumbersEnabled() const; + void saveToXmlFile(QIODevice *device); + void saveWorkbook(); + + QString m_fileName; + bool m_closed; + + SharedStrings *m_sharedStrings; + QList m_worksheets; + Styles *m_styles; + bool m_optimization_enabled; //constant_memory + bool m_strings_to_numbers_enabled; + + int m_x_window; + int m_y_window; + int m_window_width; + int m_window_height; + + int m_activesheet; + int m_firstsheet; + int m_table_count; +}; + +} //QXlsx + +#endif // XLSXWORKBOOK_H diff --git a/src/xlsxworksheet.cpp b/src/xlsxworksheet.cpp new file mode 100755 index 0000000..7ffd448 --- /dev/null +++ b/src/xlsxworksheet.cpp @@ -0,0 +1,479 @@ +/**************************************************************************** +** 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. +** +****************************************************************************/ +#include "xlsxworksheet.h" +#include "xlsxworkbook.h" +#include "xlsxutility_p.h" +#include "xlsxsharedstrings_p.h" +#include "xmlstreamwriter_p.h" + +#include +#include +#include +#include + +#include + +namespace QXlsx { + +/*! + * \brief Worksheet::Worksheet + * \param name Name of the worksheet + * \param index Index of the worksheet in the workbook + * \param parent + */ +Worksheet::Worksheet(const QString &name, int index, Workbook *parent) : + QObject(parent), m_workbook(parent), m_name(name), m_index(index) +{ + m_xls_rowmax = 1048576; + m_xls_colmax = 16384; + m_xls_strmax = 32767; + m_dim_rowmin = INT32_MAX; + m_dim_rowmax = INT32_MIN; + m_dim_colmin = INT32_MAX; + m_dim_colmax = INT32_MIN; + + m_previous_row = 0; + + m_outline_row_level = 0; + m_outline_col_level = 0; + + m_default_row_height = 15; + m_default_row_zeroed = false; + + m_hidden = false; + m_selected = false; + m_actived = false; + m_right_to_left = false; + m_show_zeros = true; +} + +bool Worksheet::isChartsheet() const +{ + return false; +} + +QString Worksheet::name() const +{ + return m_name; +} + +int Worksheet::index() const +{ + return m_index; +} + +bool Worksheet::isHidden() const +{ + return m_hidden; +} + +bool Worksheet::isSelected() const +{ + return m_selected; +} + +bool Worksheet::isActived() const +{ + return m_actived; +} + +void Worksheet::setHidden(bool hidden) +{ + m_hidden = hidden; +} + +void Worksheet::setSelected(bool select) +{ + m_selected = select; +} + +void Worksheet::setActived(bool act) +{ + m_actived = act; +} + +void Worksheet::setRightToLeft(bool enable) +{ + m_right_to_left = enable; +} + +void Worksheet::setZeroValuesHidden(bool enable) +{ + m_show_zeros = !enable; +} + +int Worksheet::write(int row, int column, const QVariant &value) +{ + bool ok; + int ret = 0; + + if (value.isNull()) { //blank + ret = writeBlank(row, column); + } else if (value.type() == QMetaType::Bool) { //Bool + ret = writeBool(row,column, value.toBool()); + } else if (value.toDateTime().isValid()) { //DateTime + + } else if (value.toDouble(&ok), ok) { //Number + if (!m_workbook->isStringsToNumbersEnabled() && value.type() == QMetaType::QString) { + //Don't convert string to number if the flag not enabled. + ret = writeString(row, column, value.toString()); + } else { + ret = writeNumber(row, column, value.toDouble()); + } + } else if (value.type() == QMetaType::QUrl) { //url + + } else if (value.type() == QMetaType::QString) { //string + QString token = value.toString(); + if (token.startsWith("=")) { + ret = writeFormula(row, column, token); + } else if (token.startsWith("{") && token.endsWith("}")) { + + } else { + ret = writeString(row, column, token); + } + } else { //Wrong type + + return -1; + } + + return ret; +} + +//convert the "A1" notation to row/column notation +int Worksheet::write(const QString row_column, const QVariant &value) +{ + QPoint pos = xl_cell_to_rowcol(row_column); + if (pos == QPoint(-1, -1)) { + return -1; + } + return write(pos.x(), pos.y(), value); +} + +int Worksheet::writeString(int row, int column, const QString &value) +{ + int error = 0; + QString content = value; + if (checkDimensions(row, column)) + return -1; + + if (value.size() > m_xls_strmax) { + content = value.left(m_xls_strmax); + error = -2; + } + + SharedStrings *sharedStrings = m_workbook->sharedStrings(); + int index = sharedStrings->addSharedString(content); + + m_table[row][column] = XlsxCellData(index, XlsxCellData::String); + return error; +} + +int Worksheet::writeNumber(int row, int column, double value) +{ + if (checkDimensions(row, column)) + return -1; + + m_table[row][column] = XlsxCellData(value, XlsxCellData::Number); + return 0; +} + +int Worksheet::writeFormula(int row, int column, const QString &content, double result) +{ + int error = 0; + QString formula = content; + if (checkDimensions(row, column)) + return -1; + + //Remove the formula '=' sign if exists + if (formula.startsWith("=")) + formula.remove(0,1); + + XlsxCellData data(result, XlsxCellData::Formula); + data.formula = formula; + m_table[row][column] = data; + + return error; +} + +int Worksheet::writeBlank(int row, int column) +{ + if (checkDimensions(row, column)) + return -1; + + m_table[row][column] = XlsxCellData(QVariant(), XlsxCellData::Blank); + return 0; +} + +int Worksheet::writeBool(int row, int column, bool value) +{ + if (checkDimensions(row, column)) + return -1; + + m_table[row][column] = XlsxCellData(value, XlsxCellData::Boolean); + return 0; +} + +/* + Check that row and col are valid and store the max and min + values for use in other methods/elements. The ignore_row / + ignore_col flags is used to indicate that we wish to perform + the dimension check without storing the value. The ignore + flags are use by setRow() and dataValidate. +*/ +int Worksheet::checkDimensions(int row, int col, bool ignore_row, bool ignore_col) +{ + if (row >= m_xls_rowmax || col >= m_xls_colmax) + return -1; + +// // In optimization mode we don't change dimensions for rows +// // that are already written. +// if (!ignore_row && !ignore_col && m_optimization == 1) { +// if (row < m_previous_row) +// return -1; +// } + + if (!ignore_row) { + if (row < m_dim_rowmin) m_dim_rowmin = row; + if (row > m_dim_rowmax) m_dim_rowmax = row; + } + if (!ignore_col) { + if (col < m_dim_colmin) m_dim_colmin = col; + if (col > m_dim_colmax) m_dim_colmax = col; + } + + return 0; +} + +void Worksheet::saveToXmlFile(QIODevice *device) +{ + XmlStreamWriter writer(device); + + writer.writeStartDocument("1.0", true); + writer.writeStartElement("worksheet"); + writer.writeAttribute("xmlns", "http://schemas.openxmlformats.org/spreadsheetml/2006/main"); + writer.writeAttribute("xmlns:r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships"); + + //for Excel 2010 + // writer.writeAttribute("xmlns:mc", "http://schemas.openxmlformats.org/markup-compatibility/2006"); + // writer.writeAttribute("xmlns:x14ac", "http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac"); + // writer.writeAttribute("mc:Ignorable", "x14ac"); + + writer.writeStartElement("dimension"); + writer.writeAttribute("ref", generateDimensionString()); + writer.writeEndElement();//dimension + + writer.writeStartElement("sheetViews"); + writer.writeStartElement("sheetView"); + if (!m_show_zeros) + writer.writeAttribute("showZeros", "0"); + if (m_right_to_left) + writer.writeAttribute("rightToLeft", "1"); + if (m_selected) + writer.writeAttribute("tabSelected", "1"); + writer.writeAttribute("workbookViewId", "0"); + writer.writeEndElement();//sheetView + writer.writeEndElement();//sheetViews + + writer.writeStartElement("sheetFormatPr"); + writer.writeAttribute("defaultRowHeight", QString::number(m_default_row_height)); + if (m_default_row_height != 15) + writer.writeAttribute("customHeight", "1"); + if (m_default_row_zeroed) + writer.writeAttribute("zeroHeight", "1"); + if (m_outline_row_level) + writer.writeAttribute("outlineLevelRow", QString::number(m_outline_row_level)); + if (m_outline_col_level) + writer.writeAttribute("outlineLevelCol", QString::number(m_outline_col_level)); + //for Excel 2010 + // writer.writeAttribute("x14ac:dyDescent", "0.25"); + writer.writeEndElement();//sheetFormatPr + + writer.writeStartElement("sheetData"); + if (m_dim_rowmax == INT32_MIN) { + //If the max dimensions are equal to INT32_MIN, then there is no data to write + } else { + writeSheetData(writer); + } + writer.writeEndElement();//sheetData + + writer.writeEndElement();//worksheet + writer.writeEndDocument(); +} + +QString Worksheet::generateDimensionString() +{ + if (m_dim_rowmax == INT32_MIN && m_dim_colmax == INT32_MIN) { + //If the max dimensions are equal to INT32_MIN, then no dimension have been set + //and we use the default "A1" + return "A1"; + } + + if (m_dim_rowmax == INT32_MIN) { + //row dimensions aren't set but the column dimensions are set + if (m_dim_colmin == m_dim_colmax) { + //The dimensions are a single cell and not a range + return xl_rowcol_to_cell(0, m_dim_colmin); + } else { + const QString cell_1 = xl_rowcol_to_cell(0, m_dim_colmin); + const QString cell_2 = xl_rowcol_to_cell(0, m_dim_colmax); + return cell_1 + ":" + cell_2; + } + } + + if (m_dim_rowmin == m_dim_rowmax && m_dim_colmin == m_dim_colmax) { + //Single cell + return xl_rowcol_to_cell(m_dim_rowmin, m_dim_rowmin); + } + + QString cell_1 = xl_rowcol_to_cell(m_dim_rowmin, m_dim_colmin); + QString cell_2 = xl_rowcol_to_cell(m_dim_rowmax, m_dim_colmax); + return cell_1 + ":" + cell_2; +} + +void Worksheet::writeSheetData(XmlStreamWriter &writer) +{ + calculateSpans(); + for (int row_num = m_dim_rowmin; row_num <= m_dim_rowmax; row_num++) { + if (!(m_table.contains(row_num) || m_comments.contains(row_num))) { + //Only process rows with cell data / comments / formatting + continue; + } + + int span_index = row_num / 16; + QString span; + if (m_row_spans.contains(span_index)) + span = m_row_spans[span_index]; + + if (m_table.contains(row_num)) { + writer.writeStartElement("row"); + writer.writeAttribute("r", QString::number(row_num + 1)); + if (!span.isEmpty()) + writer.writeAttribute("spans", span); + for (int col_num = m_dim_colmin; col_num <= m_dim_colmax; col_num++) { + if (m_table[row_num].contains(col_num)) { + writeCellData(writer, row_num, col_num, m_table[row_num][col_num]); + } + } + writer.writeEndElement(); //row + } else if (m_comments.contains(row_num)){ + + } else { + + } + + } +} + +void Worksheet::writeCellData(XmlStreamWriter &writer, int row, int col, const XlsxCellData &data) +{ + //This is the innermost loop so efficiency is important. + QString cell_range = xl_rowcol_to_cell_fast(row, col); + + writer.writeStartElement("c"); + writer.writeAttribute("r", cell_range); + //Style used by the cell, row /col + // writer.writeAttribute("s", QString::number("")); + + if (data.dataType == XlsxCellData::String) { + //data.data: Index of the string in sharedStringTable + writer.writeAttribute("t", "s"); + writer.writeTextElement("v", data.value.toString()); + } else if (data.dataType == XlsxCellData::Number){ + writer.writeTextElement("v", data.value.toString()); + } else if (data.dataType == XlsxCellData::Formula) { + bool ok = true; + data.formula.toDouble(&ok); + if (!ok) //is string + writer.writeAttribute("t", "str"); + writer.writeTextElement("f", data.formula); + writer.writeTextElement("v", data.value.toString()); + } else if (data.dataType == XlsxCellData::ArrayFormula) { + + } else if (data.dataType == XlsxCellData::Boolean) { + writer.writeAttribute("t", "b"); + writer.writeTextElement("v", data.value.toBool() ? "True" : "False"); + } else if (data.dataType == XlsxCellData::Blank) { + //Ok, empty here. + } + writer.writeEndElement(); //c +} + +/* + Calculate the "spans" attribute of the tag. This is an + XLSX optimisation and isn't strictly required. However, it + makes comparing files easier. The span is the same for each + block of 16 rows. + */ +void Worksheet::calculateSpans() +{ + m_row_spans.clear(); + int span_min = INT32_MAX; + int span_max = INT32_MIN; + + for (int row_num = m_dim_rowmin; row_num <= m_dim_rowmax; row_num++) { + if (m_table.contains(row_num)) { + for (int col_num = m_dim_colmin; col_num <= m_dim_colmax; col_num++) { + if (m_table[row_num].contains(col_num)) { + if (span_max == INT32_MIN) { + span_min = col_num; + span_max = col_num; + } else { + if (col_num < span_min) + span_min = col_num; + if (col_num > span_max) + span_max = col_num; + } + } + } + } + if (m_comments.contains(row_num)) { + for (int col_num = m_dim_colmin; col_num <= m_dim_colmax; col_num++) { + if (m_comments[row_num].contains(col_num)) { + if (span_max == INT32_MIN) { + span_min = col_num; + span_max = col_num; + } else { + if (col_num < span_min) + span_min = col_num; + if (col_num > span_max) + span_max = col_num; + } + } + } + } + + if ((row_num + 1)%16 == 0 || row_num == m_dim_rowmax) { + int span_index = row_num / 16; + if (span_max != INT32_MIN) { + span_min += 1; + span_max += 1; + m_row_spans[span_index] = QString("%1:%2").arg(span_min).arg(span_max); + span_max = INT32_MIN; + } + } + } +} + +} //namespace diff --git a/src/xlsxworksheet.h b/src/xlsxworksheet.h new file mode 100755 index 0000000..db8b266 --- /dev/null +++ b/src/xlsxworksheet.h @@ -0,0 +1,131 @@ +/**************************************************************************** +** 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. +** +****************************************************************************/ +#ifndef XLSXWORKSHEET_H +#define XLSXWORKSHEET_H + +#include +#include +#include +#include +class QIODevice; + +namespace QXlsx { +class Package; +class Workbook; +class XmlStreamWriter; +class Format; + +struct XlsxCellData +{ + enum CellDataType { + Blank, + String, + Number, + Formula, + ArrayFormula, + Boolean + }; + XlsxCellData(const QVariant &data=QVariant(), CellDataType type=Blank) : + value(data), dataType(type), format(0) + { + + } + + QVariant value; + QString formula; + CellDataType dataType; + Format *format; +}; + +class Worksheet : public QObject +{ + Q_OBJECT +public: + int write(const QString row_column, const QVariant &value); + int write(int row, int column, const QVariant &value); + int writeString(int row, int column, const QString &value); + int writeNumber(int row, int column, double value); + int writeFormula(int row, int column, const QString &formula, double result=0); + int writeBlank(int row, int column); + int writeBool(int row, int column, bool value); + + void setRightToLeft(bool enable); + void setZeroValuesHidden(bool enable); + +private: + friend class Package; + friend class Workbook; + explicit Worksheet(const QString &sheetName, int sheetIndex, Workbook *parent=0); + virtual bool isChartsheet() const; + QString name() const; + int index() const; + bool isHidden() const; + bool isSelected() const; + bool isActived() const; + void setHidden(bool hidden); + void setSelected(bool select); + void setActived(bool act); + void saveToXmlFile(QIODevice *device); + int checkDimensions(int row, int col, bool ignore_row=false, bool ignore_col=false); + QString generateDimensionString(); + void writeSheetData(XmlStreamWriter &writer); + void writeCellData(XmlStreamWriter &writer, int row, int col, const XlsxCellData &data); + void calculateSpans(); + + Workbook *m_workbook; + QMap > m_table; + QMap > m_comments; + + int m_xls_rowmax; + int m_xls_colmax; + int m_xls_strmax; + int m_dim_rowmin; + int m_dim_rowmax; + int m_dim_colmin; + int m_dim_colmax; + int m_previous_row; + + QMap m_row_spans; + + int m_outline_row_level; + int m_outline_col_level; + + int m_default_row_height; + bool m_default_row_zeroed; + + QString m_name; + int m_index; + bool m_hidden; + bool m_selected; + bool m_actived; + bool m_right_to_left; + bool m_show_zeros; +}; + +} //QXlsx + +Q_DECLARE_TYPEINFO(QXlsx::XlsxCellData, Q_MOVABLE_TYPE); + +#endif // XLSXWORKSHEET_H diff --git a/src/xmlstreamwriter.cpp b/src/xmlstreamwriter.cpp new file mode 100755 index 0000000..ff7efc5 --- /dev/null +++ b/src/xmlstreamwriter.cpp @@ -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. +** +****************************************************************************/ +#include "xmlstreamwriter_p.h" +#include + +namespace QXlsx { + +XmlStreamWriter::XmlStreamWriter(QIODevice *device) : + QXmlStreamWriter(device) +{ + +} + +} diff --git a/src/xmlstreamwriter_p.h b/src/xmlstreamwriter_p.h new file mode 100755 index 0000000..c8dd41b --- /dev/null +++ b/src/xmlstreamwriter_p.h @@ -0,0 +1,41 @@ +/**************************************************************************** +** 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. +** +****************************************************************************/ +#ifndef XMLSTEAMWRITER_H +#define XMLSTEAMWRITER_H + +#include + +class QIODevice; + +namespace QXlsx { + +class XmlStreamWriter : public QXmlStreamWriter +{ +public: + explicit XmlStreamWriter(QIODevice *device); +}; + +} +#endif // XMLSTEAMWRITER_H diff --git a/src/zipwriter.cpp b/src/zipwriter.cpp new file mode 100644 index 0000000..3e20f4a --- /dev/null +++ b/src/zipwriter.cpp @@ -0,0 +1,59 @@ +/**************************************************************************** +** 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. +** +****************************************************************************/ +#include "zipwriter_p.h" +#include +#include + +namespace QXlsx { + +ZipWriter::ZipWriter(const QString &filePath, QObject *parent) : + QObject(parent) +{ + m_writer = new QZipWriter(filePath, QIODevice::WriteOnly); + m_writer->setCompressionPolicy(QZipWriter::NeverCompress); +} + +ZipWriter::~ZipWriter() +{ + delete m_writer; +} + +void ZipWriter::addFile(const QString &filePath, QIODevice *device) +{ + m_writer->addFile(filePath, device); +} + +void ZipWriter::addFile(const QString &filePath, const QByteArray &data) +{ + qDebug()<addFile(filePath, data); +} + +void ZipWriter::close() +{ + m_writer->close(); +} + +} // namespace QXlsx diff --git a/src/zipwriter_p.h b/src/zipwriter_p.h new file mode 100644 index 0000000..550a237 --- /dev/null +++ b/src/zipwriter_p.h @@ -0,0 +1,51 @@ +/**************************************************************************** +** 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. +** +****************************************************************************/ +#ifndef QXLSX_ZIPWRITER_H +#define QXLSX_ZIPWRITER_H + +#include +class QIODevice; +class QZipWriter; + +namespace QXlsx { + +class ZipWriter : public QObject +{ + Q_OBJECT +public: + explicit ZipWriter(const QString &filePath, QObject *parent = 0); + ~ZipWriter(); + + void addFile(const QString &filePath, QIODevice *device); + void addFile(const QString &filePath, const QByteArray &data); + void close(); + +private: + QZipWriter *m_writer; +}; + +} // namespace QXlsx + +#endif // QXLSX_ZIPWRITER_H