diff --git a/examples/xlsx/hello/main.cpp b/examples/xlsx/hello/main.cpp index dd6997e..3830893 100755 --- a/examples/xlsx/hello/main.cpp +++ b/examples/xlsx/hello/main.cpp @@ -31,7 +31,7 @@ int main() xlsx.write(1, 1, 200); xlsx.write(2, 1, 300); xlsx.write(3, 1, 400); - xlsx.write(4, 1, "=SUM(B1:B4)"); +// xlsx.write(4, 1, "=SUM(B1:B4)"); xlsx.saveAs(DATA_PATH"Test.xlsx"); return 0; diff --git a/src/xlsx/xlsxpackage.cpp b/src/xlsx/xlsxpackage.cpp index 085aaa7..a3da444 100644 --- a/src/xlsx/xlsxpackage.cpp +++ b/src/xlsx/xlsxpackage.cpp @@ -283,11 +283,7 @@ void Package::writeDocPropsCoreFile(ZipWriter &zipWriter) void Package::writeSharedStringsFile(ZipWriter &zipWriter) { - QByteArray data; - QBuffer buffer(&data); - buffer.open(QIODevice::WriteOnly); - m_workbook->sharedStrings()->saveToXmlFile(&buffer); - zipWriter.addFile(QStringLiteral("xl/sharedStrings.xml"), data); + zipWriter.addFile(QStringLiteral("xl/sharedStrings.xml"), m_workbook->sharedStrings()->saveToXmlData()); } void Package::writeStylesFiles(ZipWriter &zipWriter) diff --git a/src/xlsx/xlsxsharedstrings.cpp b/src/xlsx/xlsxsharedstrings.cpp index cfbc38c..d463278 100755 --- a/src/xlsx/xlsxsharedstrings.cpp +++ b/src/xlsx/xlsxsharedstrings.cpp @@ -24,15 +24,16 @@ ****************************************************************************/ #include "xlsxsharedstrings_p.h" #include "xlsxxmlwriter_p.h" +#include "xlsxxmlreader_p.h" #include #include #include #include +#include namespace QXlsx { -SharedStrings::SharedStrings(QObject *parent) : - QObject(parent) +SharedStrings::SharedStrings() { m_stringCount = 0; } @@ -46,23 +47,49 @@ int SharedStrings::addSharedString(const QString &string) { m_stringCount += 1; - if (m_stringTable.contains(string)) - return m_stringTable[string]; + if (m_stringTable.contains(string)) { + XlsxSharedStringInfo &item = m_stringTable[string]; + item.count += 1; + return item.index; + } int index = m_stringTable.size(); - m_stringTable[string] = index; + m_stringTable[string] = XlsxSharedStringInfo(index); m_stringList.append(string); return index; } +void SharedStrings::removeSharedString(const QString &string) +{ + if (!m_stringTable.contains(string)) + return; + + m_stringCount -= 1; + + XlsxSharedStringInfo &item = m_stringTable[string]; + item.count -= 1; + + if (item.count <= 0) { + for (int i=item.index+1; i= 0) + return m_stringList[index]; + return QString(); } QStringList SharedStrings::getSharedStrings() const @@ -99,4 +126,56 @@ void SharedStrings::saveToXmlFile(QIODevice *device) const writer.writeEndDocument(); } +QByteArray SharedStrings::saveToXmlData() const +{ + QByteArray data; + QBuffer buffer(&data); + buffer.open(QIODevice::WriteOnly); + saveToXmlFile(&buffer); + + return data; +} + +QSharedPointer SharedStrings::loadFromXmlFile(QIODevice *device) +{ + QSharedPointer sst(new SharedStrings); + + XmlStreamReader reader(device); + int count = 0; + while(!reader.atEnd()) { + QXmlStreamReader::TokenType token = reader.readNext(); + if (token == QXmlStreamReader::StartElement) { + if (reader.name() == QLatin1String("sst")) { + QXmlStreamAttributes attributes = reader.attributes(); + count = attributes.value(QLatin1String("uniqueCount")).toInt(); + } else if (reader.name() == QLatin1String("si")) { + if (reader.readNextStartElement()) { + if (reader.name() == QLatin1String("t")) { + QXmlStreamAttributes attributes = reader.attributes(); + QString string = reader.readElementText(); + + sst->m_stringTable[string] = XlsxSharedStringInfo(sst->m_stringTable.size(), 0); + sst->m_stringList.append(string); + } + } + } + } + } + + if (sst->m_stringTable.size() != count) { + qDebug("Error: Shared string count"); + } + + return sst; +} + +QSharedPointer SharedStrings::loadFromXmlData(const QByteArray &data) +{ + QBuffer buffer; + buffer.setData(data); + buffer.open(QIODevice::ReadOnly); + + return loadFromXmlFile(&buffer); +} + } //namespace diff --git a/src/xlsx/xlsxsharedstrings_p.h b/src/xlsx/xlsxsharedstrings_p.h index 8d92707..7d4b5cf 100755 --- a/src/xlsx/xlsxsharedstrings_p.h +++ b/src/xlsx/xlsxsharedstrings_p.h @@ -25,31 +25,47 @@ #ifndef XLSXSHAREDSTRINGS_H #define XLSXSHAREDSTRINGS_H -#include +#include "xlsxglobal.h" #include #include +#include class QIODevice; namespace QXlsx { -class SharedStrings : public QObject +class XlsxSharedStringInfo { - Q_OBJECT public: - explicit SharedStrings(QObject *parent = 0); + XlsxSharedStringInfo(int index=0, int count = 1) : + index(index), count(count) + { + } + + int index; + int count; +}; + +class XLSX_AUTOTEST_EXPORT SharedStrings +{ +public: + SharedStrings(); int count() const; -public slots: int addSharedString(const QString &string); + void removeSharedString(const QString &string); + int getSharedStringIndex(const QString &string) const; QString getSharedString(int index) const; QStringList getSharedStrings() const; void saveToXmlFile(QIODevice *device) const; + QByteArray saveToXmlData() const; + static QSharedPointer loadFromXmlFile(QIODevice *device); + static QSharedPointer loadFromXmlData(const QByteArray &data); private: - QHash m_stringTable; //for fast lookup + QHash m_stringTable; //for fast lookup QStringList m_stringList; int m_stringCount; }; diff --git a/src/xlsx/xlsxworkbook.cpp b/src/xlsx/xlsxworkbook.cpp index 2be82f3..ed6cd07 100755 --- a/src/xlsx/xlsxworkbook.cpp +++ b/src/xlsx/xlsxworkbook.cpp @@ -40,7 +40,7 @@ namespace QXlsx { WorkbookPrivate::WorkbookPrivate(Workbook *q) : q_ptr(q) { - sharedStrings = new SharedStrings(q); + sharedStrings = QSharedPointer (new SharedStrings); styles = new Styles(q); x_window = 240; @@ -176,7 +176,7 @@ QList Workbook::worksheets() const SharedStrings *Workbook::sharedStrings() { Q_D(Workbook); - return d->sharedStrings; + return d->sharedStrings.data(); } Styles *Workbook::styles() diff --git a/src/xlsx/xlsxworkbook_p.h b/src/xlsx/xlsxworkbook_p.h index 2405ea1..6d81d96 100644 --- a/src/xlsx/xlsxworkbook_p.h +++ b/src/xlsx/xlsxworkbook_p.h @@ -25,6 +25,7 @@ #ifndef XLSXWORKBOOK_P_H #define XLSXWORKBOOK_P_H #include "xlsxworkbook.h" +#include namespace QXlsx { @@ -36,7 +37,7 @@ public: Workbook *q_ptr; - SharedStrings *sharedStrings; + QSharedPointer sharedStrings; QList worksheets; Styles *styles; QList images; diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index b8a58f4..b86ac2b 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -6,4 +6,5 @@ SUBDIRS=\ relationships \ propscore \ propsapp \ - readdocument + readdocument \ + sharedstrings diff --git a/tests/auto/sharedstrings/sharedstrings.pro b/tests/auto/sharedstrings/sharedstrings.pro new file mode 100644 index 0000000..10503b2 --- /dev/null +++ b/tests/auto/sharedstrings/sharedstrings.pro @@ -0,0 +1,13 @@ +QT += testlib xlsx xlsx-private +CONFIG += testcase +DEFINES += XLSX_TEST + +TARGET = tst_sharedstringstest +CONFIG += console +CONFIG -= app_bundle + +TEMPLATE = app + + +SOURCES += tst_sharedstringstest.cpp +DEFINES += SRCDIR=\\\"$$PWD/\\\" diff --git a/tests/auto/sharedstrings/tst_sharedstringstest.cpp b/tests/auto/sharedstrings/tst_sharedstringstest.cpp new file mode 100644 index 0000000..ac3aa79 --- /dev/null +++ b/tests/auto/sharedstrings/tst_sharedstringstest.cpp @@ -0,0 +1,103 @@ +#include "private/xlsxsharedstrings_p.h" +#include +#include +#include + +class SharedStringsTest : public QObject +{ + Q_OBJECT + +public: + SharedStringsTest(); + +private Q_SLOTS: + void testAddSharedString(); + void testRemoveSharedString(); + + void testLoadXmlData(); + +}; + +SharedStringsTest::SharedStringsTest() +{ +} + +void SharedStringsTest::testAddSharedString() +{ + QXlsx::SharedStrings sst; + sst.addSharedString("Hello Qt!"); + sst.addSharedString("Xlsx Writer"); + sst.addSharedString("Hello World"); + sst.addSharedString("Hello Qt!"); + + QByteArray xmlData = sst.saveToXmlData(); + QXmlStreamReader reader(xmlData); + + int count = 0; + int uniqueCount = 0; + while(!reader.atEnd()) { + QXmlStreamReader::TokenType token = reader.readNext(); + if (token == QXmlStreamReader::StartElement) { + if (reader.name() == QLatin1String("sst")) { + QXmlStreamAttributes attributes = reader.attributes(); + count = attributes.value("count").toInt(); + uniqueCount = attributes.value("uniqueCount").toInt(); + } + } + } + + QCOMPARE(count, 4); + QCOMPARE(uniqueCount, 3); +} + +void SharedStringsTest::testRemoveSharedString() +{ + QXlsx::SharedStrings sst; + sst.addSharedString("Hello Qt!"); + sst.addSharedString("Xlsx Writer"); + sst.addSharedString("Hello World"); + sst.addSharedString("Hello Qt!"); + sst.addSharedString("Hello Qt!"); + + sst.removeSharedString("Hello World"); + sst.removeSharedString("Hello Qt!"); + sst.removeSharedString("Non exists"); + + QByteArray xmlData = sst.saveToXmlData(); + QXmlStreamReader reader(xmlData); + + int count = 0; + int uniqueCount = 0; + while(!reader.atEnd()) { + QXmlStreamReader::TokenType token = reader.readNext(); + if (token == QXmlStreamReader::StartElement) { + if (reader.name() == QLatin1String("sst")) { + QXmlStreamAttributes attributes = reader.attributes(); + count = attributes.value("count").toInt(); + uniqueCount = attributes.value("uniqueCount").toInt(); + } + } + } + + QCOMPARE(count, 3); + QCOMPARE(uniqueCount, 2); +} + +void SharedStringsTest::testLoadXmlData() +{ + QXlsx::SharedStrings sst; + sst.addSharedString("Hello Qt!"); + sst.addSharedString("Xlsx Writer"); + sst.addSharedString("Hello World"); + sst.addSharedString("Hello Qt!"); + QByteArray xmlData = sst.saveToXmlData(); + + QSharedPointer sst2 = QXlsx::SharedStrings::loadFromXmlData(xmlData); + + QCOMPARE(sst2->getSharedString(0), QStringLiteral("Hello Qt!")); + QCOMPARE(sst2->getSharedString(2), QStringLiteral("Hello World")); +} + +QTEST_APPLESS_MAIN(SharedStringsTest) + +#include "tst_sharedstringstest.moc"