From 23c04a546e2be8ac5f50c1a52f70584f7cf4f45f Mon Sep 17 00:00:00 2001 From: Debao Zhang Date: Tue, 22 Oct 2013 17:29:24 +0800 Subject: [PATCH] Can read .xlsx files with cols and rows info --- src/xlsx/xlsxworksheet.cpp | 86 ++++++++++++++++++++------ src/xlsx/xlsxworksheet_p.h | 11 ++-- tests/auto/worksheet/tst_worksheet.cpp | 37 +++++++++++ 3 files changed, 110 insertions(+), 24 deletions(-) diff --git a/src/xlsx/xlsxworksheet.cpp b/src/xlsx/xlsxworksheet.cpp index adb056c..a074423 100755 --- a/src/xlsx/xlsxworksheet.cpp +++ b/src/xlsx/xlsxworksheet.cpp @@ -75,12 +75,6 @@ WorksheetPrivate::WorksheetPrivate(Worksheet *p) : WorksheetPrivate::~WorksheetPrivate() { - foreach (XlsxRowInfo *row, rowsInfo) - delete row; - - foreach (XlsxColumnInfo *col, colsInfo) - delete col; - if (drawing) delete drawing; } @@ -621,7 +615,8 @@ void Worksheet::saveToXmlFile(QIODevice *device) if (!d->colsInfo.isEmpty()) { writer.writeStartElement(QStringLiteral("cols")); - foreach (XlsxColumnInfo *col_info, d->colsInfo) { + for (int i=0; icolsInfo.size(); ++i) { + QSharedPointer col_info = d->colsInfo[i]; writer.writeStartElement(QStringLiteral("col")); writer.writeAttribute(QStringLiteral("min"), QString::number(col_info->column_min + 1)); writer.writeAttribute(QStringLiteral("max"), QString::number(col_info->column_max)); @@ -675,7 +670,7 @@ void WorksheetPrivate::writeSheetData(XmlStreamWriter &writer) writer.writeAttribute(QStringLiteral("spans"), span); if (rowsInfo.contains(row_num)) { - XlsxRowInfo *rowInfo = rowsInfo[row_num]; + QSharedPointer rowInfo = rowsInfo[row_num]; if (rowInfo->format) { writer.writeAttribute(QStringLiteral("s"), QString::number(rowInfo->format->xfIndex())); writer.writeAttribute(QStringLiteral("customFormat"), QStringLiteral("1")); @@ -836,13 +831,7 @@ bool Worksheet::setRow(int row, double height, Format *format, bool hidden) 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); - } + d->rowsInfo[row] = QSharedPointer(new XlsxRowInfo(height, format, hidden)); d->workbook->styles()->addFormat(format); return true; } @@ -867,10 +856,10 @@ bool Worksheet::setColumn(int colFirst, int colLast, double width, Format *forma if (d->checkDimensions(0, colFirst, ignore_row, ignore_col)) return false; - XlsxColumnInfo *info = new XlsxColumnInfo(colFirst, colLast, width, format, hidden); + QSharedPointer info(new XlsxColumnInfo(colFirst, colLast, width, format, hidden)); d->colsInfo.append(info); - for (int col=colFirst; col<=colLast; ++col) + for (int col=colFirst; colcolsInfoHelper[col] = info; d->workbook->styles()->addFormat(format); @@ -1084,7 +1073,29 @@ void WorksheetPrivate::readSheetData(XmlStreamReader &reader) reader.readNextStartElement(); if (reader.tokenType() == QXmlStreamReader::StartElement) { - if (reader.name() == QLatin1String("c")) { + if (reader.name() == QLatin1String("row")) { + QXmlStreamAttributes attributes = reader.attributes(); + + if (attributes.hasAttribute(QLatin1String("customFormat")) + || attributes.hasAttribute(QLatin1String("customHeight")) + || attributes.hasAttribute(QLatin1String("hidden"))) { + + QSharedPointer info(new XlsxRowInfo); + if (attributes.hasAttribute(QLatin1String("customFormat")) && attributes.hasAttribute(QLatin1String("s"))) { + int idx = attributes.value(QLatin1String("s")).toInt(); + info->format = workbook->styles()->xfFormat(idx); + } + if (attributes.hasAttribute(QLatin1String("customHeight")) && attributes.hasAttribute(QLatin1String("ht"))) { + info->height = attributes.value(QLatin1String("ht")).toDouble(); + } + if (attributes.hasAttribute(QLatin1String("hidden"))) + info->hidden = true; + + int row = attributes.value(QLatin1String("r")).toInt(); + rowsInfo[row] = info; + } + + } else if (reader.name() == QLatin1String("c")) { QXmlStreamAttributes attributes = reader.attributes(); QString r = attributes.value(QLatin1String("r")).toString(); QPoint pos = xl_cell_to_rowcol(r); @@ -1124,6 +1135,43 @@ void WorksheetPrivate::readSheetData(XmlStreamReader &reader) } } +void WorksheetPrivate::readColumnsInfo(XmlStreamReader &reader) +{ + Q_ASSERT(reader.name() == QLatin1String("cols")); + + while(!(reader.name() == QLatin1String("cols") && reader.tokenType() == QXmlStreamReader::EndElement)) { + reader.readNextStartElement(); + if (reader.tokenType() == QXmlStreamReader::StartElement) { + if (reader.name() == QLatin1String("col")) { + QSharedPointer info(new XlsxColumnInfo); + + QXmlStreamAttributes colAttrs = reader.attributes(); + int min = colAttrs.value(QLatin1String("min")).toInt(); + int max = colAttrs.value(QLatin1String("max")).toInt(); + info->column_min = min - 1; + info->column_max = max; + + if (colAttrs.hasAttribute(QLatin1String("customWidth"))) { + double width = colAttrs.value(QLatin1String("width")).toDouble(); + info->width = width; + } + + if (colAttrs.hasAttribute(QLatin1String("hidden"))) + info->hidden = true; + + if (colAttrs.hasAttribute(QLatin1String("style"))) { + int idx = colAttrs.value(QLatin1String("style")).toInt(); + info->format = workbook->styles()->xfFormat(idx); + } + + colsInfo.append(info); + for (int col=min; colreadColumnsInfo(reader); } else if (reader.name() == QLatin1String("sheetData")) { d->readSheetData(reader); } diff --git a/src/xlsx/xlsxworksheet_p.h b/src/xlsx/xlsxworksheet_p.h index 485d759..a8849d7 100644 --- a/src/xlsx/xlsxworksheet_p.h +++ b/src/xlsx/xlsxworksheet_p.h @@ -152,7 +152,7 @@ struct XlsxObjectPositionData struct XlsxRowInfo { - XlsxRowInfo(double height, Format *format, bool hidden) : + XlsxRowInfo(double height=0, Format *format=0, bool hidden=false) : height(height), format(format), hidden(hidden) { @@ -165,7 +165,7 @@ struct XlsxRowInfo struct XlsxColumnInfo { - XlsxColumnInfo(int column_min, int column_max, double width, Format *format, bool hidden) : + XlsxColumnInfo(int column_min=0, int column_max=1, double width=0, Format *format=0, bool hidden=false) : column_min(column_min), column_max(column_max), width(width), format(format), hidden(hidden) { @@ -197,6 +197,7 @@ public: XlsxObjectPositionData pixelsToEMUs(const XlsxObjectPositionData &data); void readSheetData(XmlStreamReader &reader); + void readColumnsInfo(XmlStreamReader &reader); Workbook *workbook; Drawing *drawing; @@ -207,9 +208,9 @@ public: QStringList externUrlList; QStringList externDrawingList; QList imageList; - QMap rowsInfo; - QList colsInfo; - QMap colsInfoHelper;//Not owns the XlsxColumnInfo + QMap > rowsInfo; + QList > colsInfo; + QMap > colsInfoHelper; QList > drawingLinks; int xls_rowmax; diff --git a/tests/auto/worksheet/tst_worksheet.cpp b/tests/auto/worksheet/tst_worksheet.cpp index f263076..2a4aeea 100644 --- a/tests/auto/worksheet/tst_worksheet.cpp +++ b/tests/auto/worksheet/tst_worksheet.cpp @@ -18,6 +18,8 @@ private Q_SLOTS: void testUnMerge(); void testReadSheetData(); + void testReadColsInfo(); + void testReadRowsInfo(); }; WorksheetTest::WorksheetTest() @@ -74,6 +76,41 @@ void WorksheetTest::testReadSheetData() QCOMPARE(sheet.d_ptr->cellTable.size(), 2); } +void WorksheetTest::testReadColsInfo() +{ + const QByteArray xmlData = "" + "" + ""; + QXlsx::XmlStreamReader reader(xmlData); + reader.readNextStartElement();//current node is cols + + QXlsx::Worksheet sheet("", 0); + sheet.d_ptr->readColumnsInfo(reader); + + QCOMPARE(sheet.d_ptr->colsInfo.size(), 1); + QCOMPARE(sheet.d_ptr->colsInfo[0]->width, 5.0); +} + +void WorksheetTest::testReadRowsInfo() +{ + const QByteArray xmlData = "" + "" + "0" + "" + "" + "12345" + "" + ""; + QXlsx::XmlStreamReader reader(xmlData); + reader.readNextStartElement();//current node is sheetData + + QXlsx::Worksheet sheet("", 0); + sheet.d_ptr->readSheetData(reader); + + QCOMPARE(sheet.d_ptr->rowsInfo.size(), 1); + QCOMPARE(sheet.d_ptr->rowsInfo[3]->height, 40.0); +} + QTEST_APPLESS_MAIN(WorksheetTest) #include "tst_worksheet.moc"