Refactor: Follow Qt5 module's file directories style

Xlsx Shared library can be used now
This commit is contained in:
Debao Zhang
2013-08-29 17:14:27 +08:00
parent a563809f77
commit 929db3d481
47 changed files with 95 additions and 47 deletions
+37
View File
@@ -0,0 +1,37 @@
INCLUDEPATH += $$PWD
DEPENDPATH += $$PWD
QT += core gui gui-private
!build_xlsx_lib:DEFINES += XLSX_NO_LIB
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 \
$$PWD/xlsxworkbook_p.h \
$$PWD/xlsxworksheet_p.h \
$$PWD/xlsxformat_p.h \
$$PWD/xlsxglobal.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
+13
View File
@@ -0,0 +1,13 @@
TARGET = QtXlsx
#QMAKE_DOCS = $$PWD/doc/qtxlsx.qdocconf
load(qt_module)
CONFIG += build_xlsx_lib
include(qtxlsx.pri)
QMAKE_TARGET_COMPANY = "Debao Zhang"
QMAKE_TARGET_COPYRIGHT = "Copyright (C) 2013 Debao Zhang <hello@debao.me>"
QMAKE_TARGET_DESCRIPTION = ".Xlsx file wirter for Qt5"
+144
View File
@@ -0,0 +1,144 @@
/****************************************************************************
** Copyright (c) 2013 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "xlsxcontenttypes_p.h"
#include "xmlstreamwriter_p.h"
#include <QFile>
#include <QMapIterator>
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<QString, QString> 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<QString, QString> 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
+68
View File
@@ -0,0 +1,68 @@
/****************************************************************************
** Copyright (c) 2013 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef XLSXCONTENTTYPES_H
#define XLSXCONTENTTYPES_H
#include <QString>
#include <QStringList>
#include <QMap>
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<QString, QString> m_defaults;
QMap<QString, QString> m_overrides;
QString m_package_prefix;
QString m_document_prefix;
};
}
#endif // XLSXCONTENTTYPES_H
+129
View File
@@ -0,0 +1,129 @@
/****************************************************************************
** Copyright (c) 2013 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "xlsxdocprops_p.h"
#include "xmlstreamwriter_p.h"
#include <QDir>
#include <QFile>
#include <QDateTime>
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<QString,int> 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
+57
View File
@@ -0,0 +1,57 @@
/****************************************************************************
** Copyright (c) 2013 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef XLSXDOCPROPS_H
#define XLSXDOCPROPS_H
#include <QObject>
#include <QList>
#include <QPair>
#include <QStringList>
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<QPair<QString, int> > m_headingPairsList;
};
}
#endif // XLSXDOCPROPS_H
+829
View File
@@ -0,0 +1,829 @@
/****************************************************************************
** Copyright (c) 2013 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "xlsxformat.h"
#include "xlsxformat_p.h"
#include <QDataStream>
#include <QDebug>
namespace QXlsx {
QList<Format *> FormatPrivate::s_xfFormats;
QList<Format *> FormatPrivate::s_dxfFormats;
FormatPrivate::FormatPrivate(Format *p) :
q_ptr(p)
{
dirty = true;
is_dxf_fomat = false;
xf_index = -1;
dxf_index = -1;
theme = 0;
color_indexed = 0;
}
Format::Format() :
d_ptr(new FormatPrivate(this))
{
}
Format::~Format()
{
delete d_ptr;
}
int Format::numberFormat() const
{
Q_D(const Format);
return d->numberData.formatIndex;
}
void Format::setNumberFormat(int format)
{
Q_D(Format);
d->dirty = true;
d->numberData.formatIndex = format;
}
int Format::fontSize() const
{
Q_D(const Format);
return d->fontData.size;
}
void Format::setFontSize(int size)
{
Q_D(Format);
d->fontData.size = size;
d->fontData._dirty = true;
}
bool Format::fontItalic() const
{
Q_D(const Format);
return d->fontData.italic;
}
void Format::setFontItalic(bool italic)
{
Q_D(Format);
d->fontData.italic = italic;
d->fontData._dirty = true;
}
bool Format::fontStrikeOut() const
{
Q_D(const Format);
return d->fontData.strikeOut;
}
void Format::setFontStrikeOut(bool strikeOut)
{
Q_D(Format);
d->fontData.strikeOut = strikeOut;
d->fontData._dirty = true;
}
QColor Format::fontColor() const
{
Q_D(const Format);
return d->fontData.color;
}
void Format::setFontColor(const QColor &color)
{
Q_D(Format);
d->fontData.color = color;
d->fontData._dirty = true;
}
bool Format::fontBold() const
{
Q_D(const Format);
return d->fontData.bold;
}
void Format::setFontBold(bool bold)
{
Q_D(Format);
d->fontData.bold = bold;
d->fontData._dirty = true;
}
Format::FontScript Format::fontScript() const
{
Q_D(const Format);
return d->fontData.scirpt;
}
void Format::setFontScript(FontScript script)
{
Q_D(Format);
d->fontData.scirpt = script;
d->fontData._dirty = true;
}
Format::FontUnderline Format::fontUnderline() const
{
Q_D(const Format);
return d->fontData.underline;
}
void Format::setFontUnderline(FontUnderline underline)
{
Q_D(Format);
d->fontData.underline = underline;
d->fontData._dirty = true;
}
bool Format::fontOutline() const
{
Q_D(const Format);
return d->fontData.outline;
}
void Format::setFontOutline(bool outline)
{
Q_D(Format);
d->fontData.outline = outline;
d->fontData._dirty = true;
}
QString Format::fontName() const
{
Q_D(const Format);
return d->fontData.name;
}
void Format::setFontName(const QString &name)
{
Q_D(Format);
d->fontData.name = name;
d->fontData._dirty = true;
}
bool Format::hasFont() const
{
Q_D(const Format);
return !d->fontData._redundant;
}
void Format::setFontRedundant(bool redundant)
{
Q_D(Format);
d->fontData._redundant = redundant;
}
int Format::fontIndex() const
{
Q_D(const Format);
return d->fontData._index;
}
void Format::setFontIndex(int index)
{
Q_D(Format);
d->fontData._index = index;
}
int Format::fontFamily() const
{
Q_D(const Format);
return d->fontData.family;
}
bool Format::fontShadow() const
{
Q_D(const Format);
return d->fontData.shadow;
}
QString Format::fontScheme() const
{
Q_D(const Format);
return d->fontData.scheme;
}
/* Internal
*/
QByteArray Format::fontKey() const
{
Q_D(const Format);
if (d->fontData._dirty) {
QByteArray key;
QDataStream stream(&key, QIODevice::WriteOnly);
stream<<d->fontData.bold<<d->fontData.charset<<d->fontData.color<<d->fontData.condense
<<d->fontData.extend<<d->fontData.family<<d->fontData.italic<<d->fontData.name
<<d->fontData.outline<<d->fontData.scheme<<d->fontData.scirpt<<d->fontData.shadow
<<d->fontData.size<<d->fontData.strikeOut<<d->fontData.underline;
const_cast<FormatPrivate*>(d)->fontData._key = key;
const_cast<FormatPrivate*>(d)->fontData._dirty = false;
const_cast<FormatPrivate*>(d)->dirty = true; //Make sure formatKey() will be re-generated.
}
return d->fontData._key;
}
Format::HorizontalAlignment Format::horizontalAlignment() const
{
Q_D(const Format);
return d->alignmentData.alignH;
}
void Format::setHorizontalAlignment(HorizontalAlignment align)
{
Q_D(Format);
if (d->alignmentData.indent &&(align != AlignHGeneral && align != AlignLeft &&
align != AlignRight && align != AlignHDistributed)) {
d->alignmentData.indent = 0;
}
if (d->alignmentData.shinkToFit && (align == AlignHFill || align == AlignHJustify
|| align == AlignHDistributed)) {
d->alignmentData.shinkToFit = false;
}
d->alignmentData.alignH = align;
d->dirty = true;
}
Format::VerticalAlignment Format::verticalAlignment() const
{
Q_D(const Format);
return d->alignmentData.alignV;
}
void Format::setVerticalAlignment(VerticalAlignment align)
{
Q_D(Format);
d->alignmentData.alignV = align;
d->dirty = true;
}
bool Format::textWrap() const
{
Q_D(const Format);
return d->alignmentData.wrap;
}
void Format::setTextWarp(bool wrap)
{
Q_D(Format);
if (wrap && d->alignmentData.shinkToFit)
d->alignmentData.shinkToFit = false;
d->alignmentData.wrap = wrap;
d->dirty = true;
}
int Format::rotation() const
{
Q_D(const Format);
return d->alignmentData.rotation;
}
void Format::setRotation(int rotation)
{
Q_D(Format);
d->alignmentData.rotation = rotation;
d->dirty = true;
}
int Format::indent() const
{
Q_D(const Format);
return d->alignmentData.indent;
}
void Format::setIndent(int indent)
{
Q_D(Format);
if (indent && (d->alignmentData.alignH != AlignHGeneral
&& d->alignmentData.alignH != AlignLeft
&& d->alignmentData.alignH != AlignRight
&& d->alignmentData.alignH != AlignHJustify)) {
d->alignmentData.alignH = AlignLeft;
}
d->alignmentData.indent = indent;
d->dirty = true;
}
bool Format::shrinkToFit() const
{
Q_D(const Format);
return d->alignmentData.shinkToFit;
}
void Format::setShrinkToFit(bool shink)
{
Q_D(Format);
if (shink && d->alignmentData.wrap)
d->alignmentData.wrap = false;
if (shink && (d->alignmentData.alignH == AlignHFill
|| d->alignmentData.alignH == AlignHJustify
|| d->alignmentData.alignH == AlignHDistributed)) {
d->alignmentData.alignH = AlignLeft;
}
d->alignmentData.shinkToFit = shink;
d->dirty = true;
}
bool Format::alignmentChanged() const
{
Q_D(const Format);
return d->alignmentData.alignH != AlignHGeneral
|| d->alignmentData.alignV != AlignBottom
|| d->alignmentData.indent != 0
|| d->alignmentData.wrap
|| d->alignmentData.rotation != 0
|| d->alignmentData.shinkToFit;
}
QString Format::horizontalAlignmentString() const
{
Q_D(const Format);
QString alignH;
switch (d->alignmentData.alignH) {
case Format::AlignLeft:
alignH = "left";
break;
case Format::AlignHCenter:
alignH = "center";
break;
case Format::AlignRight:
alignH = "right";
break;
case Format::AlignHFill:
alignH = "fill";
break;
case Format::AlignHJustify:
alignH = "justify";
break;
case Format::AlignHMerge:
alignH = "centerContinuous";
break;
case Format::AlignHDistributed:
alignH = "distributed";
break;
default:
break;
}
return alignH;
}
QString Format::verticalAlignmentString() const
{
Q_D(const Format);
QString align;
switch (d->alignmentData.alignV) {
case AlignTop:
align = "top";
break;
case AlignVCenter:
align = "center";
break;
case AlignVJustify:
align = "justify";
break;
case AlignVDistributed:
align = "distributed";
break;
default:
break;
}
return align;
}
void Format::setBorderStyle(BorderStyle style)
{
setLeftBorderStyle(style);
setRightBorderStyle(style);
setBottomBorderStyle(style);
setTopBorderStyle(style);
}
void Format::setBorderColor(const QColor &color)
{
setLeftBorderColor(color);
setRightBorderColor(color);
setTopBorderColor(color);
setBottomBorderColor(color);
}
Format::BorderStyle Format::leftBorderStyle() const
{
Q_D(const Format);
return d->borderData.left;
}
void Format::setLeftBorderStyle(BorderStyle style)
{
Q_D(Format);
d->borderData.left = style;
d->borderData._dirty = true;
}
QColor Format::leftBorderColor() const
{
Q_D(const Format);
return d->borderData.leftColor;
}
void Format::setLeftBorderColor(const QColor &color)
{
Q_D(Format);
d->borderData.leftColor = color;
d->borderData._dirty = true;
}
Format::BorderStyle Format::rightBorderStyle() const
{
Q_D(const Format);
return d->borderData.right;
}
void Format::setRightBorderStyle(BorderStyle style)
{
Q_D(Format);
d->borderData.right = style;
d->borderData._dirty = true;
}
QColor Format::rightBorderColor() const
{
Q_D(const Format);
return d->borderData.rightColor;
}
void Format::setRightBorderColor(const QColor &color)
{
Q_D(Format);
d->borderData.rightColor = color;
d->borderData._dirty = true;
}
Format::BorderStyle Format::topBorderStyle() const
{
Q_D(const Format);
return d->borderData.top;
}
void Format::setTopBorderStyle(BorderStyle style)
{
Q_D(Format);
d->borderData.top = style;
d->borderData._dirty = true;
}
QColor Format::topBorderColor() const
{
Q_D(const Format);
return d->borderData.topColor;
}
void Format::setTopBorderColor(const QColor &color)
{
Q_D(Format);
d->borderData.topColor = color;
d->borderData._dirty = true;
}
Format::BorderStyle Format::bottomBorderStyle() const
{
Q_D(const Format);
return d->borderData.bottom;
}
void Format::setBottomBorderStyle(BorderStyle style)
{
Q_D(Format);
d->borderData.bottom = style;
d->borderData._dirty = true;
}
QColor Format::bottomBorderColor() const
{
Q_D(const Format);
return d->borderData.bottomColor;
}
void Format::setBottomBorderColor(const QColor &color)
{
Q_D(Format);
d->borderData.bottomColor = color;
d->borderData._dirty = true;
}
Format::BorderStyle Format::diagonalBorderStyle() const
{
Q_D(const Format);
return d->borderData.diagonal;
}
void Format::setDiagonalBorderStyle(BorderStyle style)
{
Q_D(Format);
d->borderData.diagonal = style;
d->borderData._dirty = true;
}
Format::DiagonalBorderType Format::diagonalBorderType() const
{
Q_D(const Format);
return d->borderData.diagonalType;
}
void Format::setDiagonalBorderType(DiagonalBorderType style)
{
Q_D(Format);
d->borderData.diagonalType = style;
d->borderData._dirty = true;
}
QColor Format::diagonalBorderColor() const
{
Q_D(const Format);
return d->borderData.diagonalColor;
}
void Format::setDiagonalBorderColor(const QColor &color)
{
Q_D(Format);
d->borderData.diagonalColor = color;
d->borderData._dirty = true;
}
bool Format::hasBorders() const
{
Q_D(const Format);
return !d->borderData._redundant;
}
void Format::setBorderRedundant(bool redundant)
{
Q_D(Format);
d->borderData._redundant = redundant;
}
int Format::borderIndex() const
{
Q_D(const Format);
return d->borderData._index;
}
void Format::setBorderIndex(int index)
{
Q_D(Format);
d->borderData._index = index;
}
/* Internal
*/
QByteArray Format::borderKey() const
{
Q_D(const Format);
if (d->borderData._dirty) {
QByteArray key;
QDataStream stream(&key, QIODevice::WriteOnly);
stream<<d->borderData.bottom<<d->borderData.bottomColor
<<d->borderData.diagonal<<d->borderData.diagonalColor<<d->borderData.diagonalType
<<d->borderData.left<<d->borderData.leftColor
<<d->borderData.right<<d->borderData.rightColor
<<d->borderData.top<<d->borderData.topColor;
const_cast<FormatPrivate*>(d)->borderData._key = key;
const_cast<FormatPrivate*>(d)->borderData._dirty = false;
const_cast<FormatPrivate*>(d)->dirty = true; //Make sure formatKey() will be re-generated.
}
return d->borderData._key;
}
Format::FillPattern Format::fillPattern() const
{
Q_D(const Format);
return d->fillData.pattern;
}
void Format::setFillPattern(FillPattern pattern)
{
Q_D(Format);
d->fillData.pattern = pattern;
d->fillData._dirty = true;
}
QColor Format::patternForegroundColor() const
{
Q_D(const Format);
return d->fillData.fgColor;
}
void Format::setPatternForegroundColor(const QColor &color)
{
Q_D(Format);
if (color.isValid() && d->fillData.pattern == PatternNone)
d->fillData.pattern = PatternSolid;
d->fillData.fgColor = color;
d->fillData._dirty = true;
}
QColor Format::patternBackgroundColor() const
{
Q_D(const Format);
return d->fillData.bgColor;
}
void Format::setPatternBackgroundColor(const QColor &color)
{
Q_D(Format);
if (color.isValid() && d->fillData.pattern == PatternNone)
d->fillData.pattern = PatternSolid;
d->fillData.bgColor = color;
d->fillData._dirty = true;
}
bool Format::hasFill() const
{
Q_D(const Format);
return !d->fillData._redundant;
}
void Format::setFillRedundant(bool redundant)
{
Q_D(Format);
d->fillData._redundant = redundant;
}
int Format::fillIndex() const
{
Q_D(const Format);
return d->fillData._index;
}
void Format::setFillIndex(int index)
{
Q_D(Format);
d->fillData._index = index;
}
/* Internal
*/
QByteArray Format::fillKey() const
{
Q_D(const Format);
if (d->fillData._dirty) {
QByteArray key;
QDataStream stream(&key, QIODevice::WriteOnly);
stream<<d->fillData.bgColor<<d->fillData.fgColor<<d->fillData.pattern;
const_cast<FormatPrivate*>(d)->fillData._key = key;
const_cast<FormatPrivate*>(d)->fillData._dirty = false;
const_cast<FormatPrivate*>(d)->dirty = true; //Make sure formatKey() will be re-generated.
}
return d->fillData._key;
}
bool Format::hidden() const
{
Q_D(const Format);
return d->protectionData.hidden;
}
void Format::setHidden(bool hidden)
{
Q_D(Format);
d->protectionData.hidden = hidden;
d->dirty = true;
}
bool Format::locked() const
{
Q_D(const Format);
return d->protectionData.locked;
}
void Format::setLocked(bool locked)
{
Q_D(Format);
d->protectionData.locked = locked;
d->dirty = true;
}
QByteArray Format::formatKey() const
{
Q_D(const Format);
if (d->dirty || d->fontData._dirty || d->borderData._dirty || d->fillData._dirty) {
QByteArray key;
QDataStream stream(&key, QIODevice::WriteOnly);
stream<<fontKey()<<borderKey()<<fillKey()
<<d->numberData.formatIndex
<<d->alignmentData.alignH<<d->alignmentData.alignV<<d->alignmentData.indent
<<d->alignmentData.rotation<<d->alignmentData.shinkToFit<<d->alignmentData.wrap
<<d->protectionData.hidden<<d->protectionData.locked;
const_cast<FormatPrivate*>(d)->formatKey = key;
const_cast<FormatPrivate*>(d)->dirty = false;
}
return d->formatKey;
}
bool Format::operator ==(const Format &format) const
{
return this->formatKey() == format.formatKey();
}
bool Format::operator !=(const Format &format) const
{
return this->formatKey() != format.formatKey();
}
/* Internal
*
* This function will be called when wirte the cell contents of worksheet to xml files.
* Depending on the order of the Format used instead of the Format created, we assign a
* index to it.
*/
int Format::xfIndex(bool generateIfNotValid)
{
Q_D(Format);
if (d->xf_index == -1 && generateIfNotValid) { //Generate a valid xf_index for this format
int index = -1;
for (int i=0; i<d->s_xfFormats.size(); ++i) {
if (*d->s_xfFormats[i] == *this) {
index = i;
break;
}
}
if (index != -1) {
d->xf_index = index;
} else {
d->xf_index = d->s_xfFormats.size();
d->s_xfFormats.append(this);
}
}
return d->xf_index;
}
void Format::clearExtraInfos()
{
Q_D(Format);
d->xf_index = -1;
d->dxf_index = -1;
d->s_xfFormats.clear();
d->s_dxfFormats.clear();
}
bool Format::isDxfFormat() const
{
Q_D(const Format);
return d->is_dxf_fomat;
}
int Format::theme() const
{
Q_D(const Format);
return d->theme;
}
int Format::colorIndexed() const
{
Q_D(const Format);
return d->color_indexed;
}
QList<Format *> Format::xfFormats()
{
return FormatPrivate::s_xfFormats;
}
QList<Format *> Format::dxfFormats()
{
return FormatPrivate::s_dxfFormats;
}
} // namespace QXlsx
+255
View File
@@ -0,0 +1,255 @@
/****************************************************************************
** Copyright (c) 2013 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef QXLSX_FORMAT_H
#define QXLSX_FORMAT_H
#include "xlsxglobal.h"
#include <QFont>
#include <QColor>
#include <QByteArray>
#include <QList>
namespace QXlsx {
class Styles;
class Worksheet;
class WorksheetPrivate;
class FormatPrivate;
class Q_XLSX_EXPORT Format
{
Q_DECLARE_PRIVATE(Format)
public:
enum FontScript
{
FontScriptNormal,
FontScriptSuper,
FontScriptSub
};
enum FontUnderline
{
FontUnderlineNone,
FontUnderlineSingle,
FontUnderlineDouble,
FontUnderlineSingleAccounting,
FontUnderlineDoubleAccounting
};
enum HorizontalAlignment
{
AlignHGeneral,
AlignLeft,
AlignHCenter,
AlignRight,
AlignHFill,
AlignHJustify,
AlignHMerge,
AlignHDistributed
};
enum VerticalAlignment
{
AlignTop,
AlignVCenter,
AlignBottom,
AlignVJustify,
AlignVDistributed
};
enum BorderStyle
{
BorderNone,
BorderThin,
BorderMedium,
BorderDashed,
BorderDotted,
BorderThick,
BorderDouble,
BorderHair,
BorderMediumDashed,
BorderDashDot,
BorderMediumDashDot,
BorderDashDotDot,
BorderMediumDashDotDot,
BorderSlantDashDot
};
enum DiagonalBorderType
{
DiagonalBorderNone,
DiagonalBorderDown,
DiagonalBorderUp,
DiagnoalBorderBoth
};
enum FillPattern
{
PatternNone,
PatternSolid,
PatternMediumGray,
PatternDarkGray,
PatternLightGray,
PatternDarkHorizontal,
PatternDarkVertical,
PatternDarkDown,
PatternDarkUp,
PatternDarkGrid,
PatternDarkTrellis,
PatternLightHorizontal,
PatternLightVertical,
PatternLightDown,
PatternLightUp,
PatternLightTrellis,
PatternGray125,
PatternGray0625
};
~Format();
int numberFormat() const;
void setNumberFormat(int format);
int fontSize() const;
void setFontSize(int size);
bool fontItalic() const;
void setFontItalic(bool italic);
bool fontStrikeOut() const;
void setFontStrikeOut(bool);
QColor fontColor() const;
void setFontColor(const QColor &);
bool fontBold() const;
void setFontBold(bool bold);
FontScript fontScript() const;
void setFontScript(FontScript);
FontUnderline fontUnderline() const;
void setFontUnderline(FontUnderline);
bool fontOutline() const;
void setFontOutline(bool outline);
QString fontName() const;
void setFontName(const QString &);
HorizontalAlignment horizontalAlignment() const;
void setHorizontalAlignment(HorizontalAlignment align);
VerticalAlignment verticalAlignment() const;
void setVerticalAlignment(VerticalAlignment align);
bool textWrap() const;
void setTextWarp(bool textWrap);
int rotation() const;
void setRotation(int rotation);
int indent() const;
void setIndent(int indent);
bool shrinkToFit() const;
void setShrinkToFit(bool shink);
void setBorderStyle(BorderStyle style);
void setBorderColor(const QColor &color);
BorderStyle leftBorderStyle() const;
void setLeftBorderStyle(BorderStyle style);
QColor leftBorderColor() const;
void setLeftBorderColor(const QColor &color);
BorderStyle rightBorderStyle() const;
void setRightBorderStyle(BorderStyle style);
QColor rightBorderColor() const;
void setRightBorderColor(const QColor &color);
BorderStyle topBorderStyle() const;
void setTopBorderStyle(BorderStyle style);
QColor topBorderColor() const;
void setTopBorderColor(const QColor &color);
BorderStyle bottomBorderStyle() const;
void setBottomBorderStyle(BorderStyle style);
QColor bottomBorderColor() const;
void setBottomBorderColor(const QColor &color);
BorderStyle diagonalBorderStyle() const;
void setDiagonalBorderStyle(BorderStyle style);
DiagonalBorderType diagonalBorderType() const;
void setDiagonalBorderType(DiagonalBorderType style);
QColor diagonalBorderColor() const;
void setDiagonalBorderColor(const QColor &color);
FillPattern fillPattern() const;
void setFillPattern(FillPattern pattern);
QColor patternForegroundColor() const;
void setPatternForegroundColor(const QColor &color);
QColor patternBackgroundColor() const;
void setPatternBackgroundColor(const QColor &color);
bool locked() const;
void setLocked(bool locked);
bool hidden() const;
void setHidden(bool hidden);
bool operator == (const Format &format) const;
bool operator != (const Format &format) const;
private:
friend class Styles;
friend class Worksheet;
friend class WorksheetPrivate;
Format();
bool hasFont() const;
void setFontRedundant(bool redundant);
int fontIndex() const;
void setFontIndex(int index);
QByteArray fontKey() const;
int fontFamily() const;
bool fontShadow() const;
QString fontScheme() const;
bool alignmentChanged() const;
QString horizontalAlignmentString() const;
QString verticalAlignmentString() const;
QByteArray borderKey() const;
bool hasBorders() const;
void setBorderRedundant(bool redundant);
int borderIndex() const;
void setBorderIndex(int index);
QByteArray fillKey() const;
bool hasFill() const;
void setFillRedundant(bool redundant);
int fillIndex() const;
void setFillIndex(int index);
QByteArray formatKey() const;
static QList<Format *> xfFormats();
static QList<Format *> dxfFormats();
int xfIndex(bool generateIfNotValid=true); //Generate index when first called.
void clearExtraInfos();
bool isDxfFormat() const;
int theme() const;
int colorIndexed() const;
FormatPrivate * const d_ptr;
};
} // namespace QXlsx
#endif // QXLSX_FORMAT_H
+172
View File
@@ -0,0 +1,172 @@
/****************************************************************************
** Copyright (c) 2013 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef XLSXFORMAT_P_H
#define XLSXFORMAT_P_H
#include "xlsxformat.h"
namespace QXlsx {
struct NumberData
{
NumberData() : formatIndex(0) {}
int formatIndex;
};
struct FontData
{
FontData() :
size(11), italic(false), strikeOut(false), color(QColor()), bold(false)
, scirpt(Format::FontScriptNormal), underline(Format::FontUnderlineNone)
, outline(false), shadow(false), name("Calibri"), family(2), charset(0)
, scheme("minor"), condense(0), extend(0)
, _dirty(true), _redundant(false), _index(-1)
{}
int size;
bool italic;
bool strikeOut;
QColor color;
bool bold;
Format::FontScript scirpt;
Format::FontUnderline underline;
bool outline;
bool shadow;
QString name;
int family;
int charset;
QString scheme;
int condense;
int extend;
//helper member
bool _dirty; //key re-generated is need.
QByteArray _key;
bool _redundant; //same font already used by some other Formats
int _index; //index in the Font list
};
struct AlignmentData
{
AlignmentData() :
alignH(Format::AlignHGeneral), alignV(Format::AlignBottom)
, wrap(false), rotation(0), indent(0), shinkToFit(false)
{}
Format::HorizontalAlignment alignH;
Format::VerticalAlignment alignV;
bool wrap;
int rotation;
int indent;
bool shinkToFit;
};
struct BorderData
{
BorderData() :
left(Format::BorderNone), right(Format::BorderNone), top(Format::BorderNone)
,bottom(Format::BorderNone), diagonal(Format::BorderNone)
,diagonalType(Format::DiagonalBorderNone)
,_dirty(true), _redundant(false), _index(-1)
{}
Format::BorderStyle left;
Format::BorderStyle right;
Format::BorderStyle top;
Format::BorderStyle bottom;
Format::BorderStyle diagonal;
QColor leftColor;
QColor rightColor;
QColor topColor;
QColor bottomColor;
QColor diagonalColor;
Format::DiagonalBorderType diagonalType;
//helper member
bool _dirty; //key re-generated is need.
QByteArray _key;
bool _redundant; //same border already used by some other Formats
int _index; //index in the border list
};
struct FillData {
FillData() :
pattern(Format::PatternNone)
,_dirty(true), _redundant(false), _index(-1)
{}
Format::FillPattern pattern;
QColor bgColor;
QColor fgColor;
//helper member
bool _dirty; //key re-generated is need.
QByteArray _key;
bool _redundant; //same border already used by some other Formats
int _index; //index in the border list
};
struct ProtectionData {
ProtectionData() :
locked(false), hidden(false)
{}
bool locked;
bool hidden;
};
class FormatPrivate
{
Q_DECLARE_PUBLIC(Format)
public:
FormatPrivate(Format *p);
NumberData numberData;
FontData fontData;
AlignmentData alignmentData;
BorderData borderData;
FillData fillData;
ProtectionData protectionData;
bool dirty; //The key re-generation is need.
QByteArray formatKey;
static QList<Format *> s_xfFormats;
int xf_index;
static QList<Format *> s_dxfFormats;
bool is_dxf_fomat;
int dxf_index;
int theme;
int color_indexed;
Format *q_ptr;
};
}
#endif // XLSXFORMAT_P_H
+43
View File
@@ -0,0 +1,43 @@
/****************************************************************************
** Copyright (c) 2013 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef XLSXGLOBAL_H
#define XLSXGLOBAL_H
#include <QtGlobal>
namespace QXlsx {
#if !defined(QT_STATIC) && !defined(XLSX_NO_LIB)
# if defined(QT_BUILD_XLSX_LIB)
# define Q_XLSX_EXPORT Q_DECL_EXPORT
# else
# define Q_XLSX_EXPORT Q_DECL_IMPORT
# endif
#else
# define Q_XLSX_EXPORT
#endif
}
#endif // XLSXGLOBAL_H
+275
View File
@@ -0,0 +1,275 @@
/****************************************************************************
** Copyright (c) 2013 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "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 <QBuffer>
#include <QDebug>
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)
{
ZipWriter zipWriter(packageName);
m_workbook->styles()->clearExtraFormatInfo(); //These info will be generated when write the worksheet data.
writeWorksheetFiles(zipWriter);
// writeChartsheetFiles(zipWriter);
writeWorkbookFile(zipWriter);
// writeChartFiles(zipWriter);
// writeDrawingFiles(zipWriter);
// writeVmlFiles(zipWriter);
// writeCommentFiles(zipWriter);
// writeTableFiles(zipWriter);
writeSharedStringsFile(zipWriter);
writeDocPropsFiles(zipWriter);
writeContentTypesFiles(zipWriter);
m_workbook->styles()->prepareStyles();
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
+70
View File
@@ -0,0 +1,70 @@
/****************************************************************************
** Copyright (c) 2013 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef QXLSX_PACKAGE_H
#define QXLSX_PACKAGE_H
#include <QString>
namespace QXlsx {
class Workbook;
class ZipWriter;
class Package
{
public:
Package(Workbook *workbook);
bool createPackage(const QString &packageName);
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
+92
View File
@@ -0,0 +1,92 @@
/****************************************************************************
** Copyright (c) 2013 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "xlsxrelationships_p.h"
#include "xmlstreamwriter_p.h"
#include <QDir>
#include <QFile>
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
+63
View File
@@ -0,0 +1,63 @@
/****************************************************************************
** Copyright (c) 2013 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef XLSXRELATIONSHIPS_H
#define XLSXRELATIONSHIPS_H
#include <QObject>
#include <QList>
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<XlsxRelationship> m_relationships;
};
}
#endif // XLSXRELATIONSHIPS_H
+102
View File
@@ -0,0 +1,102 @@
/****************************************************************************
** Copyright (c) 2013 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "xlsxsharedstrings_p.h"
#include "xmlstreamwriter_p.h"
#include <QDir>
#include <QFile>
#include <QRegularExpression>
#include <QDebug>
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("^<r>")) || string.contains(QRegularExpression("</r>$"))) {
//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
+58
View File
@@ -0,0 +1,58 @@
/****************************************************************************
** Copyright (c) 2013 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef XLSXSHAREDSTRINGS_H
#define XLSXSHAREDSTRINGS_H
#include <QObject>
#include <QHash>
#include <QStringList>
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<QString, int> m_stringTable; //for fast lookup
QStringList m_stringList;
int m_stringCount;
};
}
#endif // XLSXSHAREDSTRINGS_H
+447
View File
@@ -0,0 +1,447 @@
/****************************************************************************
** Copyright (c) 2013 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "xlsxstyles_p.h"
#include "xlsxformat.h"
#include "xmlstreamwriter_p.h"
#include <QFile>
#include <QMap>
#include <QDataStream>
#include <QDebug>
namespace QXlsx {
Styles::Styles(QObject *parent) :
QObject(parent)
{
m_fill_count = 0;
m_borders_count = 0;
m_font_count = 0;
}
Styles::~Styles()
{
qDeleteAll(m_formats);
}
Format *Styles::addFormat()
{
Format *format = new Format();
m_formats.append(format);
return format;
}
/*
* This function should be called after worksheet written finished,
* which means the order of the Formats used have been known to us.
*/
void Styles::prepareStyles()
{
m_xf_formats = Format::xfFormats();
m_dxf_formats = Format::dxfFormats();
if (m_xf_formats.isEmpty())
m_xf_formats.append(this->addFormat());
//fonts
QMap<QByteArray, int> fontsKeyCache;
foreach (Format *format, m_xf_formats) {
const QByteArray &key = format->fontKey();
if (fontsKeyCache.contains(key)) {
//Font has already been used.
format->setFontIndex(fontsKeyCache[key]);
format->setFontRedundant(true);
} else {
int index = fontsKeyCache.size();
fontsKeyCache[key] = index;
format->setFontIndex(index);
format->setFontRedundant(false);
}
}
m_font_count = fontsKeyCache.size();
//borders
QMap<QByteArray, int> bordersKeyCache;
foreach (Format *format, m_xf_formats) {
const QByteArray &key = format->borderKey();
if (bordersKeyCache.contains(key)) {
//Border has already been used.
format->setBorderIndex(bordersKeyCache[key]);
format->setBorderRedundant(true);
} else {
int index = bordersKeyCache.size();
bordersKeyCache[key] = index;
format->setBorderIndex(index);
format->setBorderRedundant(false);
}
}
m_borders_count = bordersKeyCache.size();
//fills
QMap<QByteArray, int> fillsKeyCache;
// The user defined fill properties start from 2 since there are 2
// default fills: patternType="none" and patternType="gray125".
{
QByteArray key;
QDataStream stream(&key, QIODevice::WriteOnly);
stream<<QColor()<<QColor()<<Format::PatternNone;
fillsKeyCache[key] = 0;
}
{
QByteArray key;
QDataStream stream(&key, QIODevice::WriteOnly);
stream<<QColor()<<QColor()<<Format::PatternGray125;
fillsKeyCache[key] = 1;
}
foreach (Format *format, m_xf_formats) {
const QByteArray &key = format->fillKey();
if (fillsKeyCache.contains(key)) {
//Border has already been used.
format->setFillIndex(fillsKeyCache[key]);
format->setFillRedundant(true);
} else {
int index = fillsKeyCache.size();
fillsKeyCache[key] = index;
format->setFillIndex(index);
format->setFillRedundant(false);
}
}
m_fill_count = fillsKeyCache.size();
}
void Styles::clearExtraFormatInfo()
{
foreach (Format *format, m_formats)
format->clearExtraInfos();
}
void Styles::saveToXmlFile(QIODevice *device)
{
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->fontBold())
writer.writeEmptyElement("b");
if (format->fontItalic())
writer.writeEmptyElement("i");
if (format->fontStrikeOut())
writer.writeEmptyElement("strike");
if (format->fontOutline())
writer.writeEmptyElement("outline");
if (format->fontShadow())
writer.writeEmptyElement("shadow");
if (format->fontUnderline() != Format::FontUnderlineNone) {
writer.writeEmptyElement("u");
if (format->fontUnderline() == Format::FontUnderlineDouble)
writer.writeAttribute("val", "double");
else if (format->fontUnderline() == Format::FontUnderlineSingleAccounting)
writer.writeAttribute("val", "singleAccounting");
else if (format->fontUnderline() == Format::FontUnderlineDoubleAccounting)
writer.writeAttribute("val", "doubleAccounting");
}
if (format->fontScript() != Format::FontScriptNormal) {
writer.writeEmptyElement("vertAligh");
if (format->fontScript() == Format::FontScriptSuper)
writer.writeAttribute("val", "superscript");
else
writer.writeAttribute("val", "subscript");
}
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));
//wirte two default fill first
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()) {
writeFill(writer, format);
}
}
writer.writeEndElement(); //fills
}
void Styles::writeFill(XmlStreamWriter &writer, Format *format)
{
static QMap<int, QString> patternStrings;
if (patternStrings.isEmpty()) {
patternStrings[Format::PatternNone] = "none";
patternStrings[Format::PatternSolid] = "solid";
patternStrings[Format::PatternMediumGray] = "mediumGray";
patternStrings[Format::PatternDarkGray] = "darkGray";
patternStrings[Format::PatternLightGray] = "lightGray";
patternStrings[Format::PatternDarkHorizontal] = "darkHorizontal";
patternStrings[Format::PatternDarkVertical] = "darkVertical";
patternStrings[Format::PatternDarkDown] = "darkDown";
patternStrings[Format::PatternDarkUp] = "darkUp";
patternStrings[Format::PatternDarkGrid] = "darkGrid";
patternStrings[Format::PatternDarkTrellis] = "darkTrellis";
patternStrings[Format::PatternLightHorizontal] = "lightHorizontal";
patternStrings[Format::PatternLightVertical] = "lightVertical";
patternStrings[Format::PatternLightDown] = "lightDown";
patternStrings[Format::PatternLightUp] = "lightUp";
patternStrings[Format::PatternLightTrellis] = "lightTrellis";
patternStrings[Format::PatternGray125] = "gray125";
patternStrings[Format::PatternGray0625] = "gray0625";
}
writer.writeStartElement("fill");
writer.writeStartElement("patternFill");
writer.writeAttribute("patternType", patternStrings[format->fillPattern()]);
if (format->patternForegroundColor().isValid()) {
writer.writeEmptyElement("fgColor");
writer.writeAttribute("rgb", "FF"+format->patternForegroundColor().name().mid(1));
}
if (format->patternBackgroundColor().isValid()) {
writer.writeEmptyElement("bgColor");
writer.writeAttribute("rgb", "FF"+format->patternBackgroundColor().name().mid(1));
}
writer.writeEndElement();//patternFill
writer.writeEndElement();//fill
}
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");
if (format->diagonalBorderType() == Format::DiagonalBorderUp) {
writer.writeAttribute("diagonalUp", "1");
} else if (format->diagonalBorderType() == Format::DiagonalBorderDown) {
writer.writeAttribute("diagonalDown", "1");
} else if (format->DiagnoalBorderBoth) {
writer.writeAttribute("diagonalUp", "1");
writer.writeAttribute("diagonalDown", "1");
}
writeSubBorder(writer, "left", format->leftBorderStyle(), format->leftBorderColor());
writeSubBorder(writer, "right", format->rightBorderStyle(), format->rightBorderColor());
writeSubBorder(writer, "top", format->topBorderStyle(), format->topBorderColor());
writeSubBorder(writer, "bottom", format->bottomBorderStyle(), format->bottomBorderColor());
if (!format->isDxfFormat()) {
writeSubBorder(writer, "diagonal", format->diagonalBorderStyle(), format->diagonalBorderColor());
}
writer.writeEndElement();//border
}
}
writer.writeEndElement();//borders
}
void Styles::writeSubBorder(XmlStreamWriter &writer, const QString &type, int style, const QColor &color)
{
if (style == Format::BorderNone) {
writer.writeEmptyElement(type);
return;
}
static QMap<int, QString> stylesString;
if (stylesString.isEmpty()) {
stylesString[Format::BorderNone] = "none";
stylesString[Format::BorderThin] = "thin";
stylesString[Format::BorderMedium] = "medium";
stylesString[Format::BorderDashed] = "dashed";
stylesString[Format::BorderDotted] = "dotted";
stylesString[Format::BorderThick] = "thick";
stylesString[Format::BorderDouble] = "double";
stylesString[Format::BorderHair] = "hair";
stylesString[Format::BorderMediumDashed] = "mediumDashed";
stylesString[Format::BorderDashDot] = "dashDot";
stylesString[Format::BorderMediumDashDot] = "mediumDashDot";
stylesString[Format::BorderDashDotDot] = "dashDotDot";
stylesString[Format::BorderMediumDashDotDot] = "mediumDashDotDot";
stylesString[Format::BorderSlantDashDot] = "slantDashDot";
}
writer.writeStartElement(type);
writer.writeAttribute("style", stylesString[style]);
writer.writeEmptyElement("color");
if (color.isValid())
writer.writeAttribute("rgb", "FF"+color.name().mid(1)); //remove #
else
writer.writeAttribute("auto", "1");
writer.writeEndElement();//type
}
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->numberFormat();
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->numberFormat() > 0)
writer.writeAttribute("applyNumberFormat", "1");
if (format->fontIndex() > 0)
writer.writeAttribute("applyFont", "1");
if (format->borderIndex() > 0)
writer.writeAttribute("applyBorder", "1");
if (format->fillIndex() > 0)
writer.writeAttribute("applyFill", "1");
if (format->alignmentChanged())
writer.writeAttribute("applyAlignment", "1");
if (format->alignmentChanged()) {
writer.writeEmptyElement("alignment");
QString alignH = format->horizontalAlignmentString();
if (!alignH.isEmpty())
writer.writeAttribute("horizontal", alignH);
QString alignV = format->verticalAlignmentString();
if (!alignV.isEmpty())
writer.writeAttribute("vertical", alignV);
if (format->indent())
writer.writeAttribute("indent", QString::number(format->indent()));
if (format->textWrap())
writer.writeAttribute("wrapText", "1");
if (format->shrinkToFit())
writer.writeAttribute("shrinkToFit", "1");
if (format->shrinkToFit())
writer.writeAttribute("shrinkToFit", "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
+67
View File
@@ -0,0 +1,67 @@
/****************************************************************************
** Copyright (c) 2013 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef XLSXSTYLES_H
#define XLSXSTYLES_H
#include <QObject>
class QIODevice;
namespace QXlsx {
class Format;
class XmlStreamWriter;
class Styles : public QObject
{
public:
explicit Styles(QObject *parent=0);
~Styles();
Format *addFormat();
void prepareStyles();
void clearExtraFormatInfo();
void saveToXmlFile(QIODevice *device);
private:
void writeFonts(XmlStreamWriter &writer);
void writeFills(XmlStreamWriter &writer);
void writeFill(XmlStreamWriter &writer, Format *format);
void writeBorders(XmlStreamWriter &writer);
void writeSubBorder(XmlStreamWriter &writer, const QString &type, int style, const QColor &color);
void writeCellXfs(XmlStreamWriter &writer);
void writeDxfs(XmlStreamWriter &writer);
QList<Format *> m_formats;
QList<Format *> m_xf_formats;
QList<Format *> m_dxf_formats;
int m_font_count;
int m_fill_count;
int m_borders_count;
};
}
#endif // XLSXSTYLES_H
+43
View File
File diff suppressed because one or more lines are too long
+42
View File
@@ -0,0 +1,42 @@
/****************************************************************************
** Copyright (c) 2013 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef XLSXTHEME_H
#define XLSXTHEME_H
#include <QString>
class QIODevice;
namespace QXlsx {
class Theme
{
public:
Theme();
void saveToXmlFile(QIODevice *device);
};
}
#endif // XLSXTHEME_H
+111
View File
@@ -0,0 +1,111 @@
/****************************************************************************
** Copyright (c) 2013 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "xlsxutility_p.h"
#include <QString>
#include <QPoint>
#include <QRegularExpression>
#include <QMap>
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<int, QString> 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
+39
View File
@@ -0,0 +1,39 @@
/****************************************************************************
** Copyright (c) 2013 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#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
+229
View File
@@ -0,0 +1,229 @@
/****************************************************************************
** Copyright (c) 2013 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "xlsxworkbook.h"
#include "xlsxworkbook_p.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 {
WorkbookPrivate::WorkbookPrivate(Workbook *q) :
q_ptr(q)
{
sharedStrings = new SharedStrings(q);
styles = new Styles(q);
x_window = 240;
y_window = 15;
window_width = 16095;
window_height = 9660;
strings_to_numbers_enabled = false;
date1904 = false;
activesheet = 0;
firstsheet = 0;
table_count = 0;
}
Workbook::Workbook(QObject *parent) :
QObject(parent), d_ptr(new WorkbookPrivate(this))
{
}
Workbook::~Workbook()
{
delete d_ptr;
}
void Workbook::save(const QString &name)
{
Q_D(Workbook);
//Add a default worksheet if non have been added.
if (d->worksheets.size() == 0)
addWorksheet();
//Ensure that at least one worksheet has been selected.
if (d->activesheet == 0) {
d->worksheets[0]->setHidden(false);
d->worksheets[0]->setSelected(true);
}
//Set the active sheet
foreach (Worksheet *sheet, d->worksheets) {
if (sheet->index() == d->activesheet)
sheet->setActived(true);
}
//Create the package based on current workbook
Package package(this);
package.createPackage(name);
}
bool Workbook::isDate1904() const
{
Q_D(const Workbook);
return d->date1904;
}
/*
Excel for Windows uses a default epoch of 1900 and Excel
for Mac uses an epoch of 1904. However, Excel on either
platform will convert automatically between one system
and the other. QtXlsxWriter stores dates in the 1900 format
by default.
*/
void Workbook::setDate1904(bool date1904)
{
Q_D(Workbook);
d->date1904 = date1904;
}
/*
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)
{
Q_D(Workbook);
d->strings_to_numbers_enabled = enable;
}
bool Workbook::isStringsToNumbersEnabled() const
{
Q_D(const Workbook);
return d->strings_to_numbers_enabled;
}
void Workbook::defineName(const QString &name, const QString &formula)
{
}
Worksheet *Workbook::addWorksheet(const QString &name)
{
Q_D(Workbook);
QString worksheetName = name;
int index = d->worksheets.size()+1;
if (name.isEmpty())
worksheetName = QString("Sheet%1").arg(index);
Worksheet *sheet = new Worksheet(worksheetName, index, this);
d->worksheets.append(sheet);
return sheet;
}
Format *Workbook::addFormat()
{
Q_D(Workbook);
return d->styles->addFormat();
}
QList<Worksheet *> Workbook::worksheets() const
{
Q_D(const Workbook);
return d->worksheets;
}
SharedStrings *Workbook::sharedStrings()
{
Q_D(Workbook);
return d->sharedStrings;
}
Styles *Workbook::styles()
{
Q_D(Workbook);
return d->styles;
}
void Workbook::saveToXmlFile(QIODevice *device)
{
Q_D(Workbook);
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");
if (d->date1904)
writer.writeAttribute("date1904", "1");
writer.writeAttribute("defaultThemeVersion", "124226");
writer.writeStartElement("bookViews");
writer.writeEmptyElement("workbookView");
writer.writeAttribute("xWindow", QString::number(d->x_window));
writer.writeAttribute("yWindow", QString::number(d->y_window));
writer.writeAttribute("windowWidth", QString::number(d->window_width));
writer.writeAttribute("windowHeight", QString::number(d->window_height));
//Store the firstSheet when it isn't the default
if (d->firstsheet > 0)
writer.writeAttribute("firstSheet", QString::number(d->firstsheet + 1));
//Store the activeTab when it isn't the first sheet
if (d->activesheet > 0)
writer.writeAttribute("activeTab", QString::number(d->activesheet));
writer.writeEndElement();//bookviews
writer.writeStartElement("sheets");
foreach (Worksheet *sheet, d->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
+75
View File
@@ -0,0 +1,75 @@
/****************************************************************************
** Copyright (c) 2013 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef XLSXWORKBOOK_H
#define XLSXWORKBOOK_H
#include "xlsxglobal.h"
#include <QObject>
#include <QList>
class QIODevice;
namespace QXlsx {
class Worksheet;
class Format;
class SharedStrings;
class Styles;
class Package;
class WorkbookPrivate;
class Q_XLSX_EXPORT Workbook : public QObject
{
Q_OBJECT
Q_DECLARE_PRIVATE(Workbook)
public:
Workbook(QObject *parent=0);
~Workbook();
QList<Worksheet *> worksheets() const;
Worksheet *addWorksheet(const QString &name = QString());
Format *addFormat();
// void addChart();
void defineName(const QString &name, const QString &formula);
bool isDate1904() const;
void setDate1904(bool date1904);
bool isStringsToNumbersEnabled() const;
void setStringsToNumbersEnabled(bool enable=true);
void save(const QString &name);
private:
friend class Package;
friend class Worksheet;
SharedStrings *sharedStrings();
Styles *styles();
void saveToXmlFile(QIODevice *device);
WorkbookPrivate * const d_ptr;
};
} //QXlsx
#endif // XLSXWORKBOOK_H
+58
View File
@@ -0,0 +1,58 @@
/****************************************************************************
** Copyright (c) 2013 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef XLSXWORKBOOK_P_H
#define XLSXWORKBOOK_P_H
#include "xlsxworkbook.h"
namespace QXlsx {
class WorkbookPrivate
{
Q_DECLARE_PUBLIC(Workbook)
public:
WorkbookPrivate(Workbook *q);
Workbook *q_ptr;
SharedStrings *sharedStrings;
QList<Worksheet *> worksheets;
Styles *styles;
bool strings_to_numbers_enabled;
bool date1904;
int x_window;
int y_window;
int window_width;
int window_height;
int activesheet;
int firstsheet;
int table_count;
};
}
#endif // XLSXWORKBOOK_P_H
+632
View File
@@ -0,0 +1,632 @@
/****************************************************************************
** Copyright (c) 2013 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "xlsxworksheet.h"
#include "xlsxworksheet_p.h"
#include "xlsxworkbook.h"
#include "xlsxformat.h"
#include "xlsxutility_p.h"
#include "xlsxsharedstrings_p.h"
#include "xmlstreamwriter_p.h"
#include <QVariant>
#include <QDateTime>
#include <QPoint>
#include <QFile>
#include <QDebug>
#include <stdint.h>
namespace QXlsx {
WorksheetPrivate::WorksheetPrivate(Worksheet *p) :
q_ptr(p)
{
xls_rowmax = 1048576;
xls_colmax = 16384;
xls_strmax = 32767;
dim_rowmin = INT32_MAX;
dim_rowmax = INT32_MIN;
dim_colmin = INT32_MAX;
dim_colmax = INT32_MIN;
previous_row = 0;
outline_row_level = 0;
outline_col_level = 0;
default_row_height = 15;
default_row_zeroed = false;
hidden = false;
selected = false;
actived = false;
right_to_left = false;
show_zeros = true;
}
WorksheetPrivate::~WorksheetPrivate()
{
typedef QMap<int, XlsxCellData *> RowMap;
foreach (RowMap row, cellTable) {
foreach (XlsxCellData *item, row)
delete item;
}
foreach (XlsxRowInfo *row, rowsInfo)
delete row;
foreach (XlsxColumnInfo *col, colsInfo)
delete col;
}
/*
Calculate the "spans" attribute of the <row> 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 WorksheetPrivate::calculateSpans()
{
row_spans.clear();
int span_min = INT32_MAX;
int span_max = INT32_MIN;
for (int row_num = dim_rowmin; row_num <= dim_rowmax; row_num++) {
if (cellTable.contains(row_num)) {
for (int col_num = dim_colmin; col_num <= dim_colmax; col_num++) {
if (cellTable[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 (comments.contains(row_num)) {
for (int col_num = dim_colmin; col_num <= dim_colmax; col_num++) {
if (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 == dim_rowmax) {
int span_index = row_num / 16;
if (span_max != INT32_MIN) {
span_min += 1;
span_max += 1;
row_spans[span_index] = QString("%1:%2").arg(span_min).arg(span_max);
span_max = INT32_MIN;
}
}
}
}
QString WorksheetPrivate::generateDimensionString()
{
if (dim_rowmax == INT32_MIN && 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 (dim_rowmax == INT32_MIN) {
//row dimensions aren't set but the column dimensions are set
if (dim_colmin == dim_colmax) {
//The dimensions are a single cell and not a range
return xl_rowcol_to_cell(0, dim_colmin);
} else {
const QString cell_1 = xl_rowcol_to_cell(0, dim_colmin);
const QString cell_2 = xl_rowcol_to_cell(0, dim_colmax);
return cell_1 + ":" + cell_2;
}
}
if (dim_rowmin == dim_rowmax && dim_colmin == dim_colmax) {
//Single cell
return xl_rowcol_to_cell(dim_rowmin, dim_rowmin);
}
QString cell_1 = xl_rowcol_to_cell(dim_rowmin, dim_colmin);
QString cell_2 = xl_rowcol_to_cell(dim_rowmax, dim_colmax);
return cell_1 + ":" + cell_2;
}
/*
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 WorksheetPrivate::checkDimensions(int row, int col, bool ignore_row, bool ignore_col)
{
if (row >= xls_rowmax || col >= xls_colmax)
return -1;
if (!ignore_row) {
if (row < dim_rowmin) dim_rowmin = row;
if (row > dim_rowmax) dim_rowmax = row;
}
if (!ignore_col) {
if (col < dim_colmin) dim_colmin = col;
if (col > dim_colmax) dim_colmax = col;
}
return 0;
}
/*!
* \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), d_ptr(new WorksheetPrivate(this))
{
d_ptr->name = name;
d_ptr->index = index;
d_ptr->workbook = parent;
}
Worksheet::~Worksheet()
{
delete d_ptr;
}
bool Worksheet::isChartsheet() const
{
return false;
}
QString Worksheet::name() const
{
Q_D(const Worksheet);
return d->name;
}
int Worksheet::index() const
{
Q_D(const Worksheet);
return d->index;
}
bool Worksheet::isHidden() const
{
Q_D(const Worksheet);
return d->hidden;
}
bool Worksheet::isSelected() const
{
Q_D(const Worksheet);
return d->selected;
}
bool Worksheet::isActived() const
{
Q_D(const Worksheet);
return d->actived;
}
void Worksheet::setHidden(bool hidden)
{
Q_D(Worksheet);
d->hidden = hidden;
}
void Worksheet::setSelected(bool select)
{
Q_D(Worksheet);
d->selected = select;
}
void Worksheet::setActived(bool act)
{
Q_D(Worksheet);
d->actived = act;
}
void Worksheet::setRightToLeft(bool enable)
{
Q_D(Worksheet);
d->right_to_left = enable;
}
void Worksheet::setZeroValuesHidden(bool enable)
{
Q_D(Worksheet);
d->show_zeros = !enable;
}
int Worksheet::write(int row, int column, const QVariant &value, Format *format)
{
Q_D(Worksheet);
bool ok;
int ret = 0;
if (d->checkDimensions(row, column))
return -1;
if (value.isNull()) { //blank
ret = writeBlank(row, column, format);
} else if (value.type() == QMetaType::Bool) { //Bool
ret = writeBool(row,column, value.toBool(), format);
} else if (value.toDateTime().isValid()) { //DateTime
ret = writeDateTime(row, column, value.toDateTime(), format);
} else if (value.toDouble(&ok), ok) { //Number
if (!d->workbook->isStringsToNumbersEnabled() && value.type() == QMetaType::QString) {
//Don't convert string to number if the flag not enabled.
ret = writeString(row, column, value.toString(), format);
} else {
ret = writeNumber(row, column, value.toDouble(), format);
}
} 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, format);
} else if (token.startsWith("{") && token.endsWith("}")) {
} else {
ret = writeString(row, column, token, format);
}
} 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, Format *format)
{
QPoint pos = xl_cell_to_rowcol(row_column);
if (pos == QPoint(-1, -1)) {
return -1;
}
return write(pos.x(), pos.y(), value, format);
}
int Worksheet::writeString(int row, int column, const QString &value, Format *format)
{
Q_D(Worksheet);
int error = 0;
QString content = value;
if (d->checkDimensions(row, column))
return -1;
if (value.size() > d->xls_strmax) {
content = value.left(d->xls_strmax);
error = -2;
}
SharedStrings *sharedStrings = d->workbook->sharedStrings();
int index = sharedStrings->addSharedString(content);
d->cellTable[row][column] = new XlsxCellData(index, XlsxCellData::String, format);
return error;
}
int Worksheet::writeNumber(int row, int column, double value, Format *format)
{
Q_D(Worksheet);
if (d->checkDimensions(row, column))
return -1;
d->cellTable[row][column] = new XlsxCellData(value, XlsxCellData::Number, format);
return 0;
}
int Worksheet::writeFormula(int row, int column, const QString &content, Format *format, double result)
{
Q_D(Worksheet);
int error = 0;
QString formula = content;
if (d->checkDimensions(row, column))
return -1;
//Remove the formula '=' sign if exists
if (formula.startsWith("="))
formula.remove(0,1);
XlsxCellData *data = new XlsxCellData(result, XlsxCellData::Formula, format);
data->formula = formula;
d->cellTable[row][column] = data;
return error;
}
int Worksheet::writeBlank(int row, int column, Format *format)
{
Q_D(Worksheet);
if (d->checkDimensions(row, column))
return -1;
d->cellTable[row][column] = new XlsxCellData(QVariant(), XlsxCellData::Blank, format);
return 0;
}
int Worksheet::writeBool(int row, int column, bool value, Format *format)
{
Q_D(Worksheet);
if (d->checkDimensions(row, column))
return -1;
d->cellTable[row][column] = new XlsxCellData(value, XlsxCellData::Boolean, format);
return 0;
}
int Worksheet::writeDateTime(int row, int column, const QDateTime &dt, Format *format)
{
Q_D(Worksheet);
if (d->checkDimensions(row, column))
return -1;
d->cellTable[row][column] = new XlsxCellData(dt, XlsxCellData::DateTime, format);
return 0;
}
void Worksheet::saveToXmlFile(QIODevice *device)
{
Q_D(Worksheet);
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", d->generateDimensionString());
writer.writeEndElement();//dimension
writer.writeStartElement("sheetViews");
writer.writeStartElement("sheetView");
if (!d->show_zeros)
writer.writeAttribute("showZeros", "0");
if (d->right_to_left)
writer.writeAttribute("rightToLeft", "1");
if (d->selected)
writer.writeAttribute("tabSelected", "1");
writer.writeAttribute("workbookViewId", "0");
writer.writeEndElement();//sheetView
writer.writeEndElement();//sheetViews
writer.writeStartElement("sheetFormatPr");
writer.writeAttribute("defaultRowHeight", QString::number(d->default_row_height));
if (d->default_row_height != 15)
writer.writeAttribute("customHeight", "1");
if (d->default_row_zeroed)
writer.writeAttribute("zeroHeight", "1");
if (d->outline_row_level)
writer.writeAttribute("outlineLevelRow", QString::number(d->outline_row_level));
if (d->outline_col_level)
writer.writeAttribute("outlineLevelCol", QString::number(d->outline_col_level));
//for Excel 2010
// writer.writeAttribute("x14ac:dyDescent", "0.25");
writer.writeEndElement();//sheetFormatPr
if (!d->colsInfo.isEmpty()) {
writer.writeStartElement("cols");
foreach (XlsxColumnInfo *col_info, d->colsInfo) {
writer.writeStartElement("col");
writer.writeAttribute("min", QString::number(col_info->column_min));
writer.writeAttribute("max", QString::number(col_info->column_max));
writer.writeAttribute("width", QString::number(col_info->width, 'g', 15));
if (col_info->format)
writer.writeAttribute("style", QString::number(col_info->format->xfIndex()));
if (col_info->hidden)
writer.writeAttribute("hidden", "1");
if (col_info->width)
writer.writeAttribute("customWidth", "1");
writer.writeEndElement();//col
}
writer.writeEndElement();//cols
}
writer.writeStartElement("sheetData");
if (d->dim_rowmax == INT32_MIN) {
//If the max dimensions are equal to INT32_MIN, then there is no data to write
} else {
d->writeSheetData(writer);
}
writer.writeEndElement();//sheetData
writer.writeEndElement();//worksheet
writer.writeEndDocument();
}
void WorksheetPrivate::writeSheetData(XmlStreamWriter &writer)
{
calculateSpans();
for (int row_num = dim_rowmin; row_num <= dim_rowmax; row_num++) {
if (!(cellTable.contains(row_num) || comments.contains(row_num) || rowsInfo.contains(row_num))) {
//Only process rows with cell data / comments / formatting
continue;
}
int span_index = row_num / 16;
QString span;
if (row_spans.contains(span_index))
span = row_spans[span_index];
if (cellTable.contains(row_num)) {
writer.writeStartElement("row");
writer.writeAttribute("r", QString::number(row_num + 1));
if (!span.isEmpty())
writer.writeAttribute("spans", span);
if (rowsInfo.contains(row_num)) {
XlsxRowInfo *rowInfo = rowsInfo[row_num];
if (rowInfo->format) {
writer.writeAttribute("s", QString::number(rowInfo->format->xfIndex()));
writer.writeAttribute("customFormat", "1");
}
if (rowInfo->height != 15) {
writer.writeAttribute("ht", QString::number(rowInfo->height));
writer.writeAttribute("customHeight", "1");
}
if (rowInfo->hidden)
writer.writeAttribute("hidden", "1");
}
for (int col_num = dim_colmin; col_num <= dim_colmax; col_num++) {
if (cellTable[row_num].contains(col_num)) {
writeCellData(writer, row_num, col_num, cellTable[row_num][col_num]);
}
}
writer.writeEndElement(); //row
} else if (comments.contains(row_num)){
} else {
}
}
}
void WorksheetPrivate::writeCellData(XmlStreamWriter &writer, int row, int col, XlsxCellData *cell)
{
//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 or col
if (cell->format)
writer.writeAttribute("s", QString::number(cell->format->xfIndex()));
else if (rowsInfo.contains(row) && rowsInfo[row]->format)
writer.writeAttribute("s", QString::number(rowsInfo[row]->format->xfIndex()));
else if (colsInfoHelper.contains(col) && colsInfoHelper[col]->format)
writer.writeAttribute("s", QString::number(colsInfoHelper[col]->format->xfIndex()));
if (cell->dataType == XlsxCellData::String) {
//cell->data: Index of the string in sharedStringTable
writer.writeAttribute("t", "s");
writer.writeTextElement("v", cell->value.toString());
} else if (cell->dataType == XlsxCellData::Number){
double value = cell->value.toDouble();
writer.writeTextElement("v", QString::number(value, 'g', 15));
} else if (cell->dataType == XlsxCellData::Formula) {
bool ok = true;
cell->formula.toDouble(&ok);
if (!ok) //is string
writer.writeAttribute("t", "str");
writer.writeTextElement("f", cell->formula);
writer.writeTextElement("v", cell->value.toString());
} else if (cell->dataType == XlsxCellData::ArrayFormula) {
} else if (cell->dataType == XlsxCellData::Boolean) {
writer.writeAttribute("t", "b");
writer.writeTextElement("v", cell->value.toBool() ? "1" : "0");
} else if (cell->dataType == XlsxCellData::Blank) {
//Ok, empty here.
} else if (cell->dataType == XlsxCellData::DateTime) {
QDateTime epoch(QDate(1899, 12, 31));
if (workbook->isDate1904())
epoch = QDateTime(QDate(1904, 1, 1));
qint64 delta = epoch.msecsTo(cell->value.toDateTime());
double excel_time = delta / (1000*60*60*24);
//Account for Excel erroneously treating 1900 as a leap year.
if (!workbook->isDate1904() && excel_time > 59)
excel_time += 1;
writer.writeTextElement("v", QString::number(excel_time, 'g', 15));
}
writer.writeEndElement(); //c
}
/*
Sets row height and format. Row height measured in point size. If format
equals 0 then format is ignored.
*/
bool Worksheet::setRow(int row, double height, Format *format, bool hidden)
{
Q_D(Worksheet);
int min_col = d->dim_colmax == INT32_MIN ? 0 : d->dim_colmin;
if (d->checkDimensions(row, min_col))
return false;
if (d->rowsInfo.contains(row)) {
d->rowsInfo[row]->height = height;
d->rowsInfo[row]->format = format;
d->rowsInfo[row]->hidden = hidden;
} else {
d->rowsInfo[row] = new XlsxRowInfo(height, format, hidden);
}
return true;
}
/*
Sets column width and format for all columns from colFirst to colLast. Column
width measured as the number of characters of the maximum digit width of the
numbers 0, 1, 2, ..., 9 as rendered in the normal style's font. If format
equals 0 then format is ignored.
*/
bool Worksheet::setColumn(int colFirst, int colLast, double width, Format *format, bool hidden)
{
Q_D(Worksheet);
bool ignore_row = true;
bool ignore_col = (format || (width && hidden)) ? false : true;
if (d->checkDimensions(0, colLast, ignore_row, ignore_col))
return false;
if (d->checkDimensions(0, colFirst, ignore_row, ignore_col))
return false;
XlsxColumnInfo *info = new XlsxColumnInfo(colFirst, colLast, width, format, hidden);
d->colsInfo.append(info);
for (int col=colFirst; col<=colLast; ++col)
d->colsInfoHelper[col] = info;
return true;
}
} //namespace
+85
View File
@@ -0,0 +1,85 @@
/****************************************************************************
** Copyright (c) 2013 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef XLSXWORKSHEET_H
#define XLSXWORKSHEET_H
#include "xlsxglobal.h"
#include <QObject>
#include <QStringList>
#include <QMap>
#include <QVariant>
class QIODevice;
class QDateTime;
namespace QXlsx {
class Package;
class Workbook;
class XmlStreamWriter;
class Format;
class WorksheetPrivate;
class Q_XLSX_EXPORT Worksheet : public QObject
{
Q_OBJECT
Q_DECLARE_PRIVATE(Worksheet)
public:
int write(const QString row_column, const QVariant &value, Format *format=0);
int write(int row, int column, const QVariant &value, Format *format=0);
int writeString(int row, int column, const QString &value, Format *format=0);
int writeNumber(int row, int column, double value, Format *format=0);
int writeFormula(int row, int column, const QString &formula, Format *format=0, double result=0);
int writeBlank(int row, int column, Format *format=0);
int writeBool(int row, int column, bool value, Format *format=0);
int writeDateTime(int row, int column, const QDateTime& dt, Format *format=0);
bool setRow(int row, double height, Format* format=0, bool hidden=false);
bool setColumn(int colFirst, int colLast, double width, Format* format=0, bool hidden=false);
void setRightToLeft(bool enable);
void setZeroValuesHidden(bool enable);
private:
friend class Package;
friend class Workbook;
Worksheet(const QString &sheetName, int sheetIndex, Workbook *parent=0);
~Worksheet();
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);
WorksheetPrivate * const d_ptr;
};
} //QXlsx
#endif // XLSXWORKSHEET_H
+129
View File
@@ -0,0 +1,129 @@
/****************************************************************************
** Copyright (c) 2013 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef XLSXWORKSHEET_P_H
#define XLSXWORKSHEET_P_H
#include "xlsxworksheet.h"
namespace QXlsx {
struct XlsxCellData
{
enum CellDataType {
Blank,
String,
Number,
Formula,
ArrayFormula,
Boolean,
DateTime
};
XlsxCellData(const QVariant &data=QVariant(), CellDataType type=Blank, Format *format=0) :
value(data), dataType(type), format(format)
{
}
QVariant value;
QString formula;
CellDataType dataType;
Format *format;
};
struct XlsxRowInfo
{
XlsxRowInfo(double height, Format *format, bool hidden) :
height(height), format(format), hidden(hidden)
{
}
double height;
Format *format;
bool hidden;
};
struct XlsxColumnInfo
{
XlsxColumnInfo(int column_min, int column_max, double width, Format *format, bool hidden) :
column_min(column_min), column_max(column_max), width(width), format(format), hidden(hidden)
{
}
int column_min;
int column_max;
double width;
Format *format;
bool hidden;
};
class WorksheetPrivate
{
Q_DECLARE_PUBLIC(Worksheet)
public:
WorksheetPrivate(Worksheet *p);
~WorksheetPrivate();
int checkDimensions(int row, int col, bool ignore_row=false, bool ignore_col=false);
QString generateDimensionString();
void calculateSpans();
void writeSheetData(XmlStreamWriter &writer);
void writeCellData(XmlStreamWriter &writer, int row, int col, XlsxCellData *cell);
Workbook *workbook;
QMap<int, QMap<int, XlsxCellData *> > cellTable;
QMap<int, QMap<int, QString> > comments;
QMap<int, XlsxRowInfo *> rowsInfo;
QList<XlsxColumnInfo *> colsInfo;
QMap<int, XlsxColumnInfo *> colsInfoHelper;//Not owns the XlsxColumnInfo
int xls_rowmax;
int xls_colmax;
int xls_strmax;
int dim_rowmin;
int dim_rowmax;
int dim_colmin;
int dim_colmax;
int previous_row;
QMap<int, QString> row_spans;
int outline_row_level;
int outline_col_level;
int default_row_height;
bool default_row_zeroed;
QString name;
int index;
bool hidden;
bool selected;
bool actived;
bool right_to_left;
bool show_zeros;
Worksheet *q_ptr;
};
}
#endif // XLSXWORKSHEET_P_H
+36
View File
@@ -0,0 +1,36 @@
/****************************************************************************
** Copyright (c) 2013 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "xmlstreamwriter_p.h"
#include <QIODevice>
namespace QXlsx {
XmlStreamWriter::XmlStreamWriter(QIODevice *device) :
QXmlStreamWriter(device)
{
}
}
+41
View File
@@ -0,0 +1,41 @@
/****************************************************************************
** Copyright (c) 2013 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef XMLSTEAMWRITER_H
#define XMLSTEAMWRITER_H
#include <QXmlStreamWriter>
class QIODevice;
namespace QXlsx {
class XmlStreamWriter : public QXmlStreamWriter
{
public:
explicit XmlStreamWriter(QIODevice *device);
};
}
#endif // XMLSTEAMWRITER_H
+58
View File
@@ -0,0 +1,58 @@
/****************************************************************************
** Copyright (c) 2013 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "zipwriter_p.h"
#include <QDebug>
#include <private/qzipwriter_p.h>
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)
{
m_writer->addFile(filePath, data);
}
void ZipWriter::close()
{
m_writer->close();
}
} // namespace QXlsx
+51
View File
@@ -0,0 +1,51 @@
/****************************************************************************
** Copyright (c) 2013 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef QXLSX_ZIPWRITER_H
#define QXLSX_ZIPWRITER_H
#include <QObject>
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