From aa885e4377e1266b44a4a89b9b4d42dac5e140f5 Mon Sep 17 00:00:00 2001 From: Debao Zhang Date: Wed, 26 Feb 2014 11:41:38 +0800 Subject: [PATCH] Don't lost externalLinks information when edit exists file --- src/xlsx/qtxlsx.pri | 7 +++-- src/xlsx/xlsxcontenttypes.cpp | 5 +++ src/xlsx/xlsxcontenttypes_p.h | 1 + src/xlsx/xlsxdocument.cpp | 21 +++++++++++++ src/xlsx/xlsxexternallink.cpp | 55 ++++++++++++++++++++++++++++++++ src/xlsx/xlsxexternallink_p.h | 59 +++++++++++++++++++++++++++++++++++ src/xlsx/xlsxworkbook.cpp | 33 +++++++++++++++----- src/xlsx/xlsxworkbook_p.h | 2 ++ 8 files changed, 173 insertions(+), 10 deletions(-) create mode 100644 src/xlsx/xlsxexternallink.cpp create mode 100644 src/xlsx/xlsxexternallink_p.h diff --git a/src/xlsx/qtxlsx.pri b/src/xlsx/qtxlsx.pri index c5cb396..a3e8bfe 100755 --- a/src/xlsx/qtxlsx.pri +++ b/src/xlsx/qtxlsx.pri @@ -42,7 +42,8 @@ HEADERS += $$PWD/xlsxdocpropscore_p.h \ $$PWD/xlsxooxmlfile.h \ $$PWD/xlsxooxmlfile_p.h \ $$PWD/xlsxchart.h \ - $$PWD/xlsxchart_p.h + $$PWD/xlsxchart_p.h \ + $$PWD/xlsxexternallink_p.h SOURCES += $$PWD/xlsxdocpropscore.cpp \ $$PWD/xlsxdocpropsapp.cpp \ @@ -70,4 +71,6 @@ SOURCES += $$PWD/xlsxdocpropscore.cpp \ $$PWD/xlsxdrawinganchor.cpp \ $$PWD/xlsxmediafile.cpp \ $$PWD/xlsxooxmlfile.cpp \ - $$PWD/xlsxchart.cpp + $$PWD/xlsxchart.cpp \ + $$PWD/xlsxexternallink.cpp + diff --git a/src/xlsx/xlsxcontenttypes.cpp b/src/xlsx/xlsxcontenttypes.cpp index e5e16bf..0546ce0 100755 --- a/src/xlsx/xlsxcontenttypes.cpp +++ b/src/xlsx/xlsxcontenttypes.cpp @@ -106,6 +106,11 @@ void ContentTypes::addTableName(const QString &name) addOverride(QStringLiteral("/xl/tables/%1.xml").arg(name), m_document_prefix + QStringLiteral("spreadsheetml.table+xml")); } +void ContentTypes::addExternalLinkName(const QString &name) +{ + addOverride(QStringLiteral("/xl/externalLinks/%1.xml").arg(name), m_document_prefix + QStringLiteral("spreadsheetml.externalLink+xml")); +} + void ContentTypes::addSharedString() { addOverride(QStringLiteral("/xl/sharedStrings.xml"), m_document_prefix + QStringLiteral("spreadsheetml.sharedStrings+xml")); diff --git a/src/xlsx/xlsxcontenttypes_p.h b/src/xlsx/xlsxcontenttypes_p.h index 8d99231..3b1ff55 100755 --- a/src/xlsx/xlsxcontenttypes_p.h +++ b/src/xlsx/xlsxcontenttypes_p.h @@ -66,6 +66,7 @@ public: void addDrawingName(const QString &name); void addCommentName(const QString &name); void addTableName(const QString &name); + void addExternalLinkName(const QString &name); void addSharedString(); void addVmlName(); void addCalcChain(); diff --git a/src/xlsx/xlsxdocument.cpp b/src/xlsx/xlsxdocument.cpp index e3cc110..af71a23 100644 --- a/src/xlsx/xlsxdocument.cpp +++ b/src/xlsx/xlsxdocument.cpp @@ -189,6 +189,16 @@ bool DocumentPrivate::loadPackage(QIODevice *device) sheet->loadFromXmlData(zipReader.fileData(sheet->filePath())); } + //load external links + for (int i=0; id_func()->externalLinks.count(); ++i) { + ExternalLinK *link = workbook->d_func()->externalLinks[i].data(); + QString rel_path = getRelFilePath(link->filePath()); + //If the .rel file exists, load it. + if (zipReader.filePaths().contains(rel_path)) + link->relationships()->loadFromXmlData(zipReader.fileData(rel_path)); + link->loadFromXmlData(zipReader.fileData(link->filePath())); + } + //load drawings for (int i=0; idrawings().size(); ++i) { Drawing *drawing = workbook->drawings()[i]; @@ -243,6 +253,17 @@ bool DocumentPrivate::savePackage(QIODevice *device) const } } + // save external links xml files + for (int i=0; id_func()->externalLinks.count(); ++i) { + ExternalLinK *link = workbook->d_func()->externalLinks[i].data(); + contentTypes.addExternalLinkName(QStringLiteral("externalLink%1").arg(i+1)); + + zipWriter.addFile(QStringLiteral("xl/externalLinks/externalLink%1.xml").arg(i+1), link->saveToXmlData()); + Relationships *rel = link->relationships(); + if (!rel->isEmpty()) + zipWriter.addFile(QStringLiteral("xl/externalLinks/_rels/externalLink%1.xml.rels").arg(i+1), rel->saveToXmlData()); + } + // save workbook xml file contentTypes.addWorkbook(); zipWriter.addFile(QStringLiteral("xl/workbook.xml"), workbook->saveToXmlData()); diff --git a/src/xlsx/xlsxexternallink.cpp b/src/xlsx/xlsxexternallink.cpp new file mode 100644 index 0000000..fa2020d --- /dev/null +++ b/src/xlsx/xlsxexternallink.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** All right reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ +#include "xlsxexternallink_p.h" +#include + +namespace QXlsx { +ExternalLinK::ExternalLinK() +{ +} + +void ExternalLinK::saveToXmlFile(QIODevice *device) const +{ + device->write(xmlData); +} + +QByteArray ExternalLinK::saveToXmlData() const +{ + return xmlData; +} + +bool ExternalLinK::loadFromXmlData(const QByteArray &data) +{ + xmlData = data; + return true; +} + +bool ExternalLinK::loadFromXmlFile(QIODevice *device) +{ + xmlData = device->readAll(); + return true; +} + +} diff --git a/src/xlsx/xlsxexternallink_p.h b/src/xlsx/xlsxexternallink_p.h new file mode 100644 index 0000000..29f9ed8 --- /dev/null +++ b/src/xlsx/xlsxexternallink_p.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** Copyright (c) 2013-2014 Debao Zhang +** All right reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ +#ifndef XLSXEXTERNALLINK_H +#define XLSXEXTERNALLINK_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt Xlsx API. It exists for the convenience +// of the Qt Xlsx. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// +#include "xlsxooxmlfile.h" + +#include +class QIODevice; + +namespace QXlsx { + +class ExternalLinK : public OOXmlFile +{ +public: + ExternalLinK(); + + void saveToXmlFile(QIODevice *device) const; + QByteArray saveToXmlData() const; + bool loadFromXmlData(const QByteArray &data); + bool loadFromXmlFile(QIODevice *device); + + QByteArray xmlData; +}; + +} +#endif // XLSXEXTERNALLINK_H diff --git a/src/xlsx/xlsxworkbook.cpp b/src/xlsx/xlsxworkbook.cpp index 29409f6..7b18ff4 100755 --- a/src/xlsx/xlsxworkbook.cpp +++ b/src/xlsx/xlsxworkbook.cpp @@ -389,13 +389,6 @@ void Workbook::saveToXmlFile(QIODevice *device) const Q_D(const Workbook); d->relationships->clear(); - for (int i=0; irelationships->addDocumentRelationship(QStringLiteral("/worksheet"), QStringLiteral("worksheets/sheet%1.xml").arg(i+1)); - d->relationships->addDocumentRelationship(QStringLiteral("/theme"), QStringLiteral("theme/theme1.xml")); - d->relationships->addDocumentRelationship(QStringLiteral("/styles"), QStringLiteral("styles.xml")); - if (!sharedStrings()->isEmpty()) - d->relationships->addDocumentRelationship(QStringLiteral("/sharedStrings"), QStringLiteral("sharedStrings.xml")); - QXmlStreamWriter writer(device); writer.writeStartDocument(QStringLiteral("1.0"), true); @@ -438,10 +431,20 @@ void Workbook::saveToXmlFile(QIODevice *device) const writer.writeAttribute(QStringLiteral("sheetId"), QString::number(sheet->sheetId())); if (sheet->isHidden()) writer.writeAttribute(QStringLiteral("state"), QStringLiteral("hidden")); - writer.writeAttribute(QStringLiteral("r:id"), QStringLiteral("rId%1").arg(i+1)); + + d->relationships->addDocumentRelationship(QStringLiteral("/worksheet"), QStringLiteral("worksheets/sheet%1.xml").arg(i+1)); + writer.writeAttribute(QStringLiteral("r:id"), QStringLiteral("rId%1").arg(d->relationships->count())); } writer.writeEndElement();//sheets + writer.writeStartElement(QStringLiteral("externalReferences")); + for (int i=0; iexternalLinks.size(); ++i) { + writer.writeEmptyElement(QStringLiteral("externalReference")); + d->relationships->addDocumentRelationship(QStringLiteral("/externalLink"), QStringLiteral("externalLinks/externalLink%1.xml").arg(i+1)); + writer.writeAttribute(QStringLiteral("r:id"), QStringLiteral("rId%1").arg(d->relationships->count())); + } + writer.writeEndElement();//externalReferences + if (!d->definedNamesList.isEmpty()) { writer.writeStartElement(QStringLiteral("definedNames")); foreach (XlsxDefineNameData data, d->definedNamesList) { @@ -470,6 +473,11 @@ void Workbook::saveToXmlFile(QIODevice *device) const writer.writeEndElement();//workbook writer.writeEndDocument(); + + d->relationships->addDocumentRelationship(QStringLiteral("/theme"), QStringLiteral("theme/theme1.xml")); + d->relationships->addDocumentRelationship(QStringLiteral("/styles"), QStringLiteral("styles.xml")); + if (!sharedStrings()->isEmpty()) + d->relationships->addDocumentRelationship(QStringLiteral("/sharedStrings"), QStringLiteral("sharedStrings.xml")); } bool Workbook::loadFromXmlFile(QIODevice *device) @@ -530,6 +538,15 @@ bool Workbook::loadFromXmlFile(QIODevice *device) } } } + } else if (reader.name() == QLatin1String("externalReference")) { + QXmlStreamAttributes attributes = reader.attributes(); + const QString rId = attributes.value(QLatin1String("r:id")).toString(); + XlsxRelationship relationship = d->relationships->getRelationshipById(rId); + + QSharedPointer link(new ExternalLinK); + const QString fullPath = QDir::cleanPath(splitPath(filePath())[0] +QLatin1String("/")+ relationship.target); + link->setFilePath(fullPath); + d->externalLinks.append(link); } else if (reader.name() == QLatin1String("definedName")) { QXmlStreamAttributes attrs = reader.attributes(); XlsxDefineNameData data; diff --git a/src/xlsx/xlsxworkbook_p.h b/src/xlsx/xlsxworkbook_p.h index 7850fa9..5b299c4 100644 --- a/src/xlsx/xlsxworkbook_p.h +++ b/src/xlsx/xlsxworkbook_p.h @@ -39,6 +39,7 @@ #include "xlsxworkbook.h" #include "xlsxooxmlfile_p.h" #include "xlsxtheme_p.h" +#include "xlsxexternallink_p.h" #include "xlsxrelationships_p.h" #include @@ -72,6 +73,7 @@ public: QSharedPointer sharedStrings; QList > sheets; + QList > externalLinks; QStringList sheetNames; QSharedPointer styles; QSharedPointer theme;