From 7748184ba15db29f764766ff982d5c106f7dae4f Mon Sep 17 00:00:00 2001 From: Debao Zhang Date: Fri, 13 Sep 2013 16:03:43 +0800 Subject: [PATCH] wip: Add read function for workbook --- src/xlsx/xlsxdocument.cpp | 2 +- src/xlsx/xlsxpackage.cpp | 21 +++++---- src/xlsx/xlsxrelationships.cpp | 9 ++++ src/xlsx/xlsxrelationships_p.h | 1 + src/xlsx/xlsxworkbook.cpp | 47 ++++++++++++++----- src/xlsx/xlsxworkbook.h | 3 +- src/xlsx/xlsxworkbook_p.h | 5 +- src/xlsx/xlsxworksheet.cpp | 85 +++++++++++++++++++++++++++------- src/xlsx/xlsxworksheet.h | 3 +- src/xlsx/xlsxworksheet_p.h | 5 +- 10 files changed, 137 insertions(+), 44 deletions(-) diff --git a/src/xlsx/xlsxdocument.cpp b/src/xlsx/xlsxdocument.cpp index db57d52..0e5289b 100644 --- a/src/xlsx/xlsxdocument.cpp +++ b/src/xlsx/xlsxdocument.cpp @@ -168,7 +168,7 @@ Worksheet *Document::activedWorksheet() const if (d->workbook->worksheets().size() == 0) return 0; - return d->workbook->worksheets().at(d->workbook->activedWorksheet()); + return d->workbook->worksheets().at(d->workbook->activedWorksheet()).data(); } int Document::activedWorksheetIndex() const diff --git a/src/xlsx/xlsxpackage.cpp b/src/xlsx/xlsxpackage.cpp index b0d278f..f697059 100644 --- a/src/xlsx/xlsxpackage.cpp +++ b/src/xlsx/xlsxpackage.cpp @@ -75,6 +75,7 @@ namespace QXlsx { The Packager class coordinates the classes that represent the elements of the package and writes them into the XLSX file. */ +typedef QSharedPointer WorksheetPtrType; Package::Package(Document *document) : m_document(document) @@ -82,7 +83,7 @@ Package::Package(Document *document) : m_workbook = m_document->workbook(); m_worksheet_count = 0; m_chartsheet_count = 0; - foreach (Worksheet *sheet, m_workbook->worksheets()) { + foreach (WorksheetPtrType sheet, m_workbook->worksheets()) { if (sheet->isChartsheet()) m_chartsheet_count += 1; else @@ -174,7 +175,7 @@ bool Package::createPackage(QIODevice *package) void Package::writeWorksheetFiles(ZipWriter &zipWriter) { int index = 1; - foreach (Worksheet *sheet, m_workbook->worksheets()) { + foreach (WorksheetPtrType sheet, m_workbook->worksheets()) { if (sheet->isChartsheet()) continue; @@ -206,7 +207,7 @@ void Package::writeContentTypesFile(ZipWriter &zipWriter) ContentTypes content; int worksheet_index = 1; - foreach (Worksheet *sheet, m_workbook->worksheets()) { + foreach (WorksheetPtrType sheet, m_workbook->worksheets()) { if (sheet->isChartsheet()) { } else { @@ -247,15 +248,15 @@ void Package::writeDocPropsAppFile(ZipWriter &zipWriter) props.addHeadingPair(QStringLiteral("Chartsheets"), m_chartsheet_count); //Add worksheet parts - foreach (Worksheet *sheet, m_workbook->worksheets()){ + foreach (WorksheetPtrType sheet, m_workbook->worksheets()){ if (!sheet->isChartsheet()) - props.addPartTitle(sheet->name()); + props.addPartTitle(sheet->sheetName()); } //Add the chartsheet parts - foreach (Worksheet *sheet, m_workbook->worksheets()){ + foreach (WorksheetPtrType sheet, m_workbook->worksheets()){ if (sheet->isChartsheet()) - props.addPartTitle(sheet->name()); + props.addPartTitle(sheet->sheetName()); } zipWriter.addFile(QStringLiteral("docProps/app.xml"), props.saveToXmlData()); @@ -306,7 +307,7 @@ void Package::writeWorkbookRelsFile(ZipWriter &zipWriter) int worksheet_index = 1; int chartsheet_index = 1; - foreach (Worksheet *sheet, m_workbook->worksheets()) { + foreach (WorksheetPtrType sheet, m_workbook->worksheets()) { if (sheet->isChartsheet()) { rels.addDocumentRelationship(QStringLiteral("/chartsheet"), QStringLiteral("chartsheets/sheet%1.xml").arg(chartsheet_index)); chartsheet_index += 1; @@ -328,7 +329,7 @@ void Package::writeWorkbookRelsFile(ZipWriter &zipWriter) void Package::writeWorksheetRelsFiles(ZipWriter &zipWriter) { int index = 1; - foreach (Worksheet *sheet, m_workbook->worksheets()) { + foreach (WorksheetPtrType sheet, m_workbook->worksheets()) { if (sheet->isChartsheet()) continue; Relationships rels; @@ -346,7 +347,7 @@ void Package::writeWorksheetRelsFiles(ZipWriter &zipWriter) void Package::writeDrawingRelsFiles(ZipWriter &zipWriter) { int index = 1; - foreach (Worksheet *sheet, m_workbook->worksheets()) { + foreach (WorksheetPtrType sheet, m_workbook->worksheets()) { if (sheet->drawingLinks().size() == 0) continue; Relationships rels; diff --git a/src/xlsx/xlsxrelationships.cpp b/src/xlsx/xlsxrelationships.cpp index 422a87e..4908b60 100755 --- a/src/xlsx/xlsxrelationships.cpp +++ b/src/xlsx/xlsxrelationships.cpp @@ -164,4 +164,13 @@ Relationships Relationships::loadFromXmlData(const QByteArray &data) return loadFromXmlFile(&buffer); } +XlsxRelationship Relationships::getRelationshipById(const QString &id) const +{ + foreach (XlsxRelationship ship, m_relationships) { + if (ship.id == id) + return ship; + } + return XlsxRelationship(); +} + } //namespace diff --git a/src/xlsx/xlsxrelationships_p.h b/src/xlsx/xlsxrelationships_p.h index 89816c3..c2a6625 100755 --- a/src/xlsx/xlsxrelationships_p.h +++ b/src/xlsx/xlsxrelationships_p.h @@ -59,6 +59,7 @@ public: QByteArray saveToXmlData(); static Relationships loadFromXmlFile(QIODevice *device); static Relationships loadFromXmlData(const QByteArray &data); + XlsxRelationship getRelationshipById(const QString &id) const; private: QList relationships(const QString &type) const; diff --git a/src/xlsx/xlsxworkbook.cpp b/src/xlsx/xlsxworkbook.cpp index f51f1b2..5d5a887 100755 --- a/src/xlsx/xlsxworkbook.cpp +++ b/src/xlsx/xlsxworkbook.cpp @@ -30,6 +30,7 @@ #include "xlsxformat.h" #include "xlsxpackage_p.h" #include "xlsxxmlwriter_p.h" +#include "xlsxxmlreader_p.h" #include "xlsxworksheet_p.h" #include @@ -63,7 +64,6 @@ Workbook::Workbook() : Workbook::~Workbook() { - qDeleteAll(d_ptr->worksheets); delete d_ptr; } @@ -123,9 +123,10 @@ Worksheet *Workbook::insertWorkSheet(int index, const QString &name) QString worksheetName = name; if (!name.isEmpty()) { //If user given an already in-use name, we should not continue any more! - foreach (Worksheet *sheet, d->worksheets) { - if (sheet->name() == name) + for (int i=0; iworksheets.size(); ++i) { + if (d->worksheets[i]->sheetName() == name) { return 0; + } } } else { bool exists; @@ -133,15 +134,15 @@ Worksheet *Workbook::insertWorkSheet(int index, const QString &name) ++lastIndex; exists = false; worksheetName = QStringLiteral("Sheet%1").arg(lastIndex+1); - foreach (Worksheet *sheet, d->worksheets) { - if (sheet->name() == worksheetName) + for (int i=0; iworksheets.size(); ++i) { + if (d->worksheets[i]->sheetName() == worksheetName) exists = true; } } while (exists); } Worksheet *sheet = new Worksheet(worksheetName, this); - d->worksheets.insert(index, sheet); + d->worksheets.insert(index, QSharedPointer(sheet)); d->activesheet = index; return sheet; } @@ -168,7 +169,7 @@ Format *Workbook::createFormat() return d->styles->createFormat(); } -QList Workbook::worksheets() const +QList > Workbook::worksheets() const { Q_D(const Workbook); return d->worksheets; @@ -206,7 +207,8 @@ void Workbook::prepareDrawings() d->images.clear(); d->drawings.clear(); - foreach (Worksheet *sheet, d->worksheets) { + for (int i=0; iworksheets.size(); ++i) { + QSharedPointer sheet = d->worksheets[i]; if (sheet->images().isEmpty()) //No drawing (such as Image, ...) continue; @@ -262,9 +264,9 @@ void Workbook::saveToXmlFile(QIODevice *device) writer.writeStartElement(QStringLiteral("sheets")); for (int i=0; iworksheets.size(); ++i) { - Worksheet *sheet = d->worksheets[i]; + QSharedPointer sheet = d->worksheets[i]; writer.writeEmptyElement(QStringLiteral("sheet")); - writer.writeAttribute(QStringLiteral("name"), sheet->name()); + writer.writeAttribute(QStringLiteral("name"), sheet->sheetName()); writer.writeAttribute(QStringLiteral("sheetId"), QString::number(i+1)); if (sheet->isHidden()) writer.writeAttribute(QStringLiteral("state"), QStringLiteral("hidden")); @@ -295,8 +297,21 @@ QByteArray Workbook::saveToXmlData() QSharedPointer Workbook::loadFromXmlFile(QIODevice *device) { - - return QSharedPointer(new Workbook); + Workbook *book = new Workbook; + + XmlStreamReader reader(device); + while(!reader.atEnd()) { + QXmlStreamReader::TokenType token = reader.readNext(); + if (token == QXmlStreamReader::StartElement) { + if (reader.name() == QLatin1String("sheet")) { + QXmlStreamAttributes attributes = reader.attributes(); + QString sheetName = attributes.value(QLatin1String("name")).toString(); + QString rId = attributes.value(QLatin1String("r:id")).toString(); + book->d_func()->sheetNameIdPairList.append(QPair(sheetName, rId)); + } + } + } + return QSharedPointer(book); } QSharedPointer Workbook::loadFromXmlData(const QByteArray &data) @@ -308,4 +323,12 @@ QSharedPointer Workbook::loadFromXmlData(const QByteArray &data) return loadFromXmlFile(&buffer); } +void Workbook::addWorksheet(const QString &name, QSharedPointer sheet) +{ + Q_D(Workbook); + + sheet->setSheetName(name); + d->worksheets.append(sheet); +} + } //namespace diff --git a/src/xlsx/xlsxworkbook.h b/src/xlsx/xlsxworkbook.h index 742ee42..365a888 100755 --- a/src/xlsx/xlsxworkbook.h +++ b/src/xlsx/xlsxworkbook.h @@ -50,7 +50,7 @@ class Q_XLSX_EXPORT Workbook public: ~Workbook(); - QList worksheets() const; + QList > worksheets() const; Worksheet *addWorksheet(const QString &name = QString()); Worksheet *insertWorkSheet(int index, const QString &name = QString()); int activedWorksheet() const; @@ -76,6 +76,7 @@ private: QByteArray saveToXmlData(); static QSharedPointer loadFromXmlFile(QIODevice *device); static QSharedPointer loadFromXmlData(const QByteArray &data); + void addWorksheet(const QString &name, QSharedPointer sheet); SharedStrings *sharedStrings(); Styles *styles(); diff --git a/src/xlsx/xlsxworkbook_p.h b/src/xlsx/xlsxworkbook_p.h index dceee14..5571c8a 100644 --- a/src/xlsx/xlsxworkbook_p.h +++ b/src/xlsx/xlsxworkbook_p.h @@ -26,6 +26,7 @@ #define XLSXWORKBOOK_P_H #include "xlsxworkbook.h" #include +#include namespace QXlsx { @@ -38,11 +39,13 @@ public: Workbook *q_ptr; QSharedPointer sharedStrings; - QList worksheets; + QList > worksheets; QSharedPointer styles; QList images; QList drawings; + QList > sheetNameIdPairList;//Data from xml file + bool strings_to_numbers_enabled; bool date1904; diff --git a/src/xlsx/xlsxworksheet.cpp b/src/xlsx/xlsxworksheet.cpp index 4e035e0..741d79e 100755 --- a/src/xlsx/xlsxworksheet.cpp +++ b/src/xlsx/xlsxworksheet.cpp @@ -29,6 +29,7 @@ #include "xlsxutility_p.h" #include "xlsxsharedstrings_p.h" #include "xlsxxmlwriter_p.h" +#include "xlsxxmlreader_p.h" #include "xlsxdrawing_p.h" #include "xlsxstyles_p.h" @@ -74,12 +75,6 @@ WorksheetPrivate::WorksheetPrivate(Worksheet *p) : WorksheetPrivate::~WorksheetPrivate() { - typedef QMap RowMap; - foreach (RowMap row, cellTable) { - foreach (XlsxCellData *item, row) - delete item; - } - foreach (XlsxRowInfo *row, rowsInfo) delete row; @@ -224,12 +219,18 @@ bool Worksheet::isChartsheet() const return false; } -QString Worksheet::name() const +QString Worksheet::sheetName() const { Q_D(const Worksheet); return d->name; } +void Worksheet::setSheetName(const QString &sheetName) +{ + Q_D(Worksheet); + d->name = sheetName; +} + bool Worksheet::isHidden() const { Q_D(const Worksheet); @@ -354,7 +355,7 @@ int Worksheet::writeString(int row, int column, const QString &value, Format *fo SharedStrings *sharedStrings = d->workbook->sharedStrings(); int index = sharedStrings->addSharedString(content); - d->cellTable[row][column] = new XlsxCellData(index, XlsxCellData::String, format); + d->cellTable[row][column] = QSharedPointer(new XlsxCellData(index, XlsxCellData::String, format)); d->workbook->styles()->addFormat(format); return error; } @@ -365,7 +366,7 @@ int Worksheet::writeNumber(int row, int column, double value, Format *format) if (d->checkDimensions(row, column)) return -1; - d->cellTable[row][column] = new XlsxCellData(value, XlsxCellData::Number, format); + d->cellTable[row][column] = QSharedPointer(new XlsxCellData(value, XlsxCellData::Number, format)); d->workbook->styles()->addFormat(format); return 0; } @@ -384,7 +385,7 @@ int Worksheet::writeFormula(int row, int column, const QString &content, Format XlsxCellData *data = new XlsxCellData(result, XlsxCellData::Formula, format); data->formula = formula; - d->cellTable[row][column] = data; + d->cellTable[row][column] = QSharedPointer(data); d->workbook->styles()->addFormat(format); return error; @@ -396,7 +397,7 @@ int Worksheet::writeBlank(int row, int column, Format *format) if (d->checkDimensions(row, column)) return -1; - d->cellTable[row][column] = new XlsxCellData(QVariant(), XlsxCellData::Blank, format); + d->cellTable[row][column] = QSharedPointer(new XlsxCellData(QVariant(), XlsxCellData::Blank, format)); d->workbook->styles()->addFormat(format); return 0; @@ -408,7 +409,7 @@ int Worksheet::writeBool(int row, int column, bool value, Format *format) if (d->checkDimensions(row, column)) return -1; - d->cellTable[row][column] = new XlsxCellData(value, XlsxCellData::Boolean, format); + d->cellTable[row][column] = QSharedPointer(new XlsxCellData(value, XlsxCellData::Boolean, format)); d->workbook->styles()->addFormat(format); return 0; @@ -420,7 +421,7 @@ int Worksheet::writeDateTime(int row, int column, const QDateTime &dt, Format *f if (d->checkDimensions(row, column)) return -1; - d->cellTable[row][column] = new XlsxCellData(dt, XlsxCellData::DateTime, format); + d->cellTable[row][column] = QSharedPointer(new XlsxCellData(dt, XlsxCellData::DateTime, format)); d->workbook->styles()->addFormat(format); return 0; @@ -482,7 +483,7 @@ int Worksheet::writeUrl(int row, int column, const QUrl &url, Format *format, co //Write the hyperlink string as normal string. SharedStrings *sharedStrings = d->workbook->sharedStrings(); int index = sharedStrings->addSharedString(urlString); - d->cellTable[row][column] = new XlsxCellData(index, XlsxCellData::String, format); + d->cellTable[row][column] = QSharedPointer(new XlsxCellData(index, XlsxCellData::String, format)); //Store the hyperlink data in sa separate table d->urlTable[row][column] = new XlsxUrlData(link_type, urlString, locationString, tip); @@ -695,7 +696,7 @@ void WorksheetPrivate::writeSheetData(XmlStreamWriter &writer) } } -void WorksheetPrivate::writeCellData(XmlStreamWriter &writer, int row, int col, XlsxCellData *cell) +void WorksheetPrivate::writeCellData(XmlStreamWriter &writer, int row, int col, QSharedPointer cell) { //This is the innermost loop so efficiency is important. QString cell_range = xl_rowcol_to_cell_fast(row, col); @@ -1068,7 +1069,59 @@ QByteArray Worksheet::saveToXmlData() QSharedPointer Worksheet::loadFromXmlFile(QIODevice *device) { - return QSharedPointer(new Worksheet(QString())); + Worksheet *sheet = new Worksheet(QStringLiteral("Sheet9999")); + + XmlStreamReader reader(device); + while(!reader.atEnd()) { + QXmlStreamReader::TokenType token = reader.readNext(); + if (token == QXmlStreamReader::StartElement) { + if (reader.name() == QLatin1String("dimension")) { + QXmlStreamAttributes attributes = reader.attributes(); + QStringList range = attributes.value(QLatin1String("ref")).toString().split(QLatin1Char(':')); + if (range.size() == 2) { + QPoint start = xl_cell_to_rowcol(range[0]); + QPoint end = xl_cell_to_rowcol(range[1]); + sheet->d_func()->dim_rowmin = start.x(); + sheet->d_func()->dim_colmin = start.y(); + sheet->d_func()->dim_rowmax = end.x(); + sheet->d_func()->dim_colmax = end.y(); + } else { + QPoint p = xl_cell_to_rowcol(range[0]); + sheet->d_func()->dim_rowmin = p.x(); + sheet->d_func()->dim_colmin = p.y(); + sheet->d_func()->dim_rowmax = p.x(); + sheet->d_func()->dim_colmax = p.y(); + } + } else if (reader.name() == QLatin1String("c")) { + QXmlStreamAttributes attributes = reader.attributes(); + QString r = attributes.value(QLatin1String("r")).toString(); + QPoint pos = xl_cell_to_rowcol(r); + + if (attributes.hasAttribute(QLatin1String("t"))) { + QString type = attributes.value(QLatin1String("t")).toString(); + if (type == QLatin1String("s")) { + //string type + reader.readNextStartElement(); + if (reader.name() == QLatin1String("v")) { + QString value = reader.readElementText(); + XlsxCellData *data = new XlsxCellData(value ,XlsxCellData::String); + sheet->d_func()->cellTable[pos.x()][pos.y()] = QSharedPointer(data); + } + } + } else { + //number type + reader.readNextStartElement(); + if (reader.name() == QLatin1String("v")) { + QString value = reader.readElementText(); + XlsxCellData *data = new XlsxCellData(value ,XlsxCellData::Number); + sheet->d_func()->cellTable[pos.x()][pos.y()] = QSharedPointer(data); + } + } + } + } + } + + return QSharedPointer (sheet); } QSharedPointer Worksheet::loadFromXmlData(const QByteArray &data) diff --git a/src/xlsx/xlsxworksheet.h b/src/xlsx/xlsxworksheet.h index 4acde49..db6be3c 100755 --- a/src/xlsx/xlsxworksheet.h +++ b/src/xlsx/xlsxworksheet.h @@ -84,7 +84,8 @@ private: Worksheet(const QString &sheetName, Workbook *book=0); virtual bool isChartsheet() const; - QString name() const; + QString sheetName() const; + void setSheetName(const QString &sheetName); bool isHidden() const; bool isSelected() const; void setHidden(bool hidden); diff --git a/src/xlsx/xlsxworksheet_p.h b/src/xlsx/xlsxworksheet_p.h index 80ffa1e..28e3d1e 100644 --- a/src/xlsx/xlsxworksheet_p.h +++ b/src/xlsx/xlsxworksheet_p.h @@ -27,6 +27,7 @@ #include "xlsxworksheet.h" #include +#include namespace QXlsx { @@ -182,7 +183,7 @@ public: QString generateDimensionString(); void calculateSpans(); void writeSheetData(XmlStreamWriter &writer); - void writeCellData(XmlStreamWriter &writer, int row, int col, XlsxCellData *cell); + void writeCellData(XmlStreamWriter &writer, int row, int col, QSharedPointer cell); void writeMergeCells(XmlStreamWriter &writer); void writeHyperlinks(XmlStreamWriter &writer); void writeDrawings(XmlStreamWriter &writer); @@ -193,7 +194,7 @@ public: Workbook *workbook; Drawing *drawing; - QMap > cellTable; + QMap > > cellTable; QMap > comments; QMap > urlTable; QList merges;