From 31270604c6637cb4775f5e81321cbdaf312d2530 Mon Sep 17 00:00:00 2001 From: Debao Zhang Date: Tue, 22 Oct 2013 13:37:49 +0800 Subject: [PATCH] Can read .xlsx files with border styles now --- examples/xlsx/readwrite/main.cpp | 1 + src/xlsx/xlsxstyles.cpp | 111 ++++++++++++++++++++++++++- src/xlsx/xlsxstyles_p.h | 3 + tests/auto/styles/tst_stylestest.cpp | 16 +++- 4 files changed, 127 insertions(+), 4 deletions(-) diff --git a/examples/xlsx/readwrite/main.cpp b/examples/xlsx/readwrite/main.cpp index 1c5b98f..c12bc32 100644 --- a/examples/xlsx/readwrite/main.cpp +++ b/examples/xlsx/readwrite/main.cpp @@ -12,6 +12,7 @@ int main() QXlsx::Format *format = xlsx.createFormat(); format->setFontColor(QColor(Qt::blue)); format->setFontSize(15); + format->setBorderStyle(QXlsx::Format::BorderDashDotDot); format->setPatternBackgroundColor(QColor(Qt::gray)); xlsx.write("A1", "Hello Qt!", format); xlsx.write("A2", 500); diff --git a/src/xlsx/xlsxstyles.cpp b/src/xlsx/xlsxstyles.cpp index 1c7429a..1cd6941 100755 --- a/src/xlsx/xlsxstyles.cpp +++ b/src/xlsx/xlsxstyles.cpp @@ -704,7 +704,107 @@ bool Styles::readFill(XmlStreamReader &reader) bool Styles::readBorders(XmlStreamReader &reader) { - return false; + Q_ASSERT(reader.name() == QLatin1String("borders")); + + QXmlStreamAttributes attributes = reader.attributes(); + int count = attributes.value(QLatin1String("count")).toInt(); + for (int i=0; i border(new BorderData); + + QXmlStreamAttributes attributes = reader.attributes(); + bool isUp = attributes.hasAttribute(QLatin1String("diagonalUp")); + bool isDown = attributes.hasAttribute(QLatin1String("diagonalUp")); + if (isUp && isDown) + border->diagonalType = Format::DiagnoalBorderBoth; + else if (isUp) + border->diagonalType = Format::DiagonalBorderUp; + else if (isDown) + border->diagonalType = Format::DiagonalBorderDown; + + while((reader.readNextStartElement(), true)) { //read until border endelement + if (reader.tokenType() == QXmlStreamReader::StartElement) { + if (reader.name() == QLatin1String("left")) + readSubBorder(reader, reader.name().toString(), border->left, border->leftColor); + else if (reader.name() == QLatin1String("right")) + readSubBorder(reader, reader.name().toString(), border->right, border->rightColor); + else if (reader.name() == QLatin1String("top")) + readSubBorder(reader, reader.name().toString(), border->top, border->topColor); + else if (reader.name() == QLatin1String("bottom")) + readSubBorder(reader, reader.name().toString(), border->bottom, border->bottomColor); + else if (reader.name() == QLatin1String("diagonal")) + readSubBorder(reader, reader.name().toString(), border->diagonal, border->diagonalColor); + } + + if (reader.tokenType() == QXmlStreamReader::EndElement && reader.name() == QLatin1String("border")) + break; + } + + m_bordersList.append(border); + m_bordersHash.insert(border->key(), border); + border->setIndex(m_bordersList.size()-1);//first call key(), then setIndex() + + return true; +} + +bool Styles::readSubBorder(XmlStreamReader &reader, const QString &name, Format::BorderStyle &style, QColor &color) +{ + Q_ASSERT(reader.name() == name); + + static QMap stylesStringsMap; + if (stylesStringsMap.isEmpty()) { + stylesStringsMap[QStringLiteral("none")] = Format::BorderNone; + stylesStringsMap[QStringLiteral("thin")] = Format::BorderThin; + stylesStringsMap[QStringLiteral("medium")] = Format::BorderMedium; + stylesStringsMap[QStringLiteral("dashed")] = Format::BorderDashed; + stylesStringsMap[QStringLiteral("dotted")] = Format::BorderDotted; + stylesStringsMap[QStringLiteral("thick")] = Format::BorderThick; + stylesStringsMap[QStringLiteral("double")] = Format::BorderDouble; + stylesStringsMap[QStringLiteral("hair")] = Format::BorderHair; + stylesStringsMap[QStringLiteral("mediumDashed")] = Format::BorderMediumDashed; + stylesStringsMap[QStringLiteral("dashDot")] = Format::BorderDashDot; + stylesStringsMap[QStringLiteral("mediumDashDot")] = Format::BorderMediumDashDot; + stylesStringsMap[QStringLiteral("dashDotDot")] = Format::BorderDashDotDot; + stylesStringsMap[QStringLiteral("mediumDashDotDot")] = Format::BorderMediumDashDotDot; + stylesStringsMap[QStringLiteral("slantDashDot")] = Format::BorderSlantDashDot; + } + + QXmlStreamAttributes attributes = reader.attributes(); + if (attributes.hasAttribute(QLatin1String("style"))) { + QString styleString = attributes.value(QLatin1String("style")).toString(); + if (stylesStringsMap.contains(styleString)) { + //get style + style = stylesStringsMap[styleString]; + while((reader.readNextStartElement(),true)) { + if (reader.tokenType() == QXmlStreamReader::StartElement) { + if (reader.name() == QLatin1String("color")) { + QXmlStreamAttributes colorAttrs = reader.attributes(); + if (colorAttrs.hasAttribute(QLatin1String("rgb"))) { + QString colorString = colorAttrs.value(QLatin1String("rgb")).toString(); + //get color + color = fromARGBString(colorString); + } + } + + } else if (reader.tokenType() == QXmlStreamReader::EndElement) { + if (reader.name() == name) + break; + } + } + } + } + + return true; } bool Styles::readCellXfs(XmlStreamReader &reader) @@ -750,6 +850,15 @@ bool Styles::readCellXfs(XmlStreamReader &reader) } } + if (xfAttrs.hasAttribute(QLatin1String("applyBorder"))) { + int id = xfAttrs.value(QLatin1String("borderId")).toInt(); + if (id >= m_bordersList.size()) { + qDebug("Error read styles.xml, cellXfs borderId"); + } else { + format->d_func()->borderData = *m_bordersList[id]; + } + } + addFormat(format); //Find the endElement of xf diff --git a/src/xlsx/xlsxstyles_p.h b/src/xlsx/xlsxstyles_p.h index f969dee..c8b99ba 100755 --- a/src/xlsx/xlsxstyles_p.h +++ b/src/xlsx/xlsxstyles_p.h @@ -26,6 +26,7 @@ #define XLSXSTYLES_H #include "xlsxglobal.h" +#include "xlsxformat.h" #include #include #include @@ -76,6 +77,8 @@ private: bool readFills(XmlStreamReader &reader); bool readFill(XmlStreamReader &reader); bool readBorders(XmlStreamReader &reader); + bool readBorder(XmlStreamReader &reader); + bool readSubBorder(XmlStreamReader &reader, const QString &name, Format::BorderStyle &style, QColor &color); bool readCellXfs(XmlStreamReader &reader); QHash m_builtinNumFmtsHash; diff --git a/tests/auto/styles/tst_stylestest.cpp b/tests/auto/styles/tst_stylestest.cpp index 4d92d2e..795829a 100644 --- a/tests/auto/styles/tst_stylestest.cpp +++ b/tests/auto/styles/tst_stylestest.cpp @@ -20,7 +20,7 @@ private Q_SLOTS: void testReadFonts(); void testReadFills(); - void testReaderBorders(); + void testReadBorders(); }; StylesTest::StylesTest() @@ -105,7 +105,7 @@ void StylesTest::testReadFills() ""; QXlsx::Styles styles(true); QXlsx::XmlStreamReader reader(xmlData); - reader.readNextStartElement();//So current node is fonts + reader.readNextStartElement();//So current node is fills styles.readFills(reader); QCOMPARE(styles.m_fillsList.size(), 4); @@ -113,9 +113,19 @@ void StylesTest::testReadFills() QCOMPARE(styles.m_fillsList[3]->bgColor, QColor(Qt::gray));//for solid pattern, bg vs. fg color! } -void StylesTest::testReaderBorders() +void StylesTest::testReadBorders() { + QByteArray xmlData ="" + "" + "" + ""; + + QXlsx::Styles styles(true); + QXlsx::XmlStreamReader reader(xmlData); + reader.readNextStartElement();//So current node is borders + styles.readBorders(reader); + QCOMPARE(styles.m_bordersList.size(), 2); } QTEST_APPLESS_MAIN(StylesTest)