Browse Source

Fix numFmt: don't assume that all custom numFmtId starts from 164

master
Debao Zhang 11 years ago
parent
commit
8feb738e9f
  1. 56
      src/xlsx/xlsxstyles.cpp
  2. 4
      src/xlsx/xlsxstyles_p.h
  3. 13
      tests/auto/styles/tst_stylestest.cpp

56
src/xlsx/xlsxstyles.cpp

@ -35,9 +35,15 @@
namespace QXlsx { namespace QXlsx {
/*
When loading from existing .xlsx file. we should create a clean styles object.
otherwise, default formats should be added.
*/
Styles::Styles(bool createEmpty) Styles::Styles(bool createEmpty)
{ {
//!Fix me. Should the custom num fmt Id starts with 164 or 176 or others??
m_nextCustomNumFmtId = 176;
if (!createEmpty) { if (!createEmpty) {
//Add default Format //Add default Format
addFormat(createFormat()); addFormat(createFormat());
@ -85,10 +91,10 @@ void Styles::addFormat(Format *format)
m_builtinNumFmtsHash.insert(QStringLiteral("0.00"), 2); m_builtinNumFmtsHash.insert(QStringLiteral("0.00"), 2);
m_builtinNumFmtsHash.insert(QStringLiteral("#,##0"), 3); m_builtinNumFmtsHash.insert(QStringLiteral("#,##0"), 3);
m_builtinNumFmtsHash.insert(QStringLiteral("#,##0.00"), 4); m_builtinNumFmtsHash.insert(QStringLiteral("#,##0.00"), 4);
m_builtinNumFmtsHash.insert(QStringLiteral("($#,##0_);($#,##0)"), 5); // m_builtinNumFmtsHash.insert(QStringLiteral("($#,##0_);($#,##0)"), 5);
m_builtinNumFmtsHash.insert(QStringLiteral("($#,##0_);[Red]($#,##0)"), 6); // m_builtinNumFmtsHash.insert(QStringLiteral("($#,##0_);[Red]($#,##0)"), 6);
m_builtinNumFmtsHash.insert(QStringLiteral("($#,##0.00_);($#,##0.00)"), 7); // m_builtinNumFmtsHash.insert(QStringLiteral("($#,##0.00_);($#,##0.00)"), 7);
m_builtinNumFmtsHash.insert(QStringLiteral("($#,##0.00_);[Red]($#,##0.00)"), 8); // m_builtinNumFmtsHash.insert(QStringLiteral("($#,##0.00_);[Red]($#,##0.00)"), 8);
m_builtinNumFmtsHash.insert(QStringLiteral("0%"), 9); m_builtinNumFmtsHash.insert(QStringLiteral("0%"), 9);
m_builtinNumFmtsHash.insert(QStringLiteral("0.00%"), 10); m_builtinNumFmtsHash.insert(QStringLiteral("0.00%"), 10);
m_builtinNumFmtsHash.insert(QStringLiteral("0.00E+00"), 11); m_builtinNumFmtsHash.insert(QStringLiteral("0.00E+00"), 11);
@ -108,10 +114,10 @@ void Styles::addFormat(Format *format)
m_builtinNumFmtsHash.insert(QStringLiteral("(#,##0_);[Red](#,##0)"), 38); m_builtinNumFmtsHash.insert(QStringLiteral("(#,##0_);[Red](#,##0)"), 38);
m_builtinNumFmtsHash.insert(QStringLiteral("(#,##0.00_);(#,##0.00)"), 39); m_builtinNumFmtsHash.insert(QStringLiteral("(#,##0.00_);(#,##0.00)"), 39);
m_builtinNumFmtsHash.insert(QStringLiteral("(#,##0.00_);[Red](#,##0.00)"), 40); m_builtinNumFmtsHash.insert(QStringLiteral("(#,##0.00_);[Red](#,##0.00)"), 40);
m_builtinNumFmtsHash.insert(QStringLiteral("_(* #,##0_);_(* (#,##0);_(* \"-\"_);_(_)"), 41); // m_builtinNumFmtsHash.insert(QStringLiteral("_(* #,##0_);_(* (#,##0);_(* \"-\"_);_(_)"), 41);
m_builtinNumFmtsHash.insert(QStringLiteral("_($* #,##0_);_($* (#,##0);_($* \"-\"_);_(_)"), 42); // m_builtinNumFmtsHash.insert(QStringLiteral("_($* #,##0_);_($* (#,##0);_($* \"-\"_);_(_)"), 42);
m_builtinNumFmtsHash.insert(QStringLiteral("_(* #,##0.00_);_(* (#,##0.00);_(* \"-\"??_);_(_)"), 43); // m_builtinNumFmtsHash.insert(QStringLiteral("_(* #,##0.00_);_(* (#,##0.00);_(* \"-\"??_);_(_)"), 43);
m_builtinNumFmtsHash.insert(QStringLiteral("_($* #,##0.00_);_($* (#,##0.00);_($* \"-\"??_);_(_)"), 44); // m_builtinNumFmtsHash.insert(QStringLiteral("_($* #,##0.00_);_($* (#,##0.00);_($* \"-\"??_);_(_)"), 44);
m_builtinNumFmtsHash.insert(QStringLiteral("mm:ss"), 45); m_builtinNumFmtsHash.insert(QStringLiteral("mm:ss"), 45);
m_builtinNumFmtsHash.insert(QStringLiteral("[h]:mm:ss"), 46); m_builtinNumFmtsHash.insert(QStringLiteral("[h]:mm:ss"), 46);
m_builtinNumFmtsHash.insert(QStringLiteral("mm:ss.0"), 47); m_builtinNumFmtsHash.insert(QStringLiteral("mm:ss.0"), 47);
@ -125,12 +131,14 @@ void Styles::addFormat(Format *format)
} else if (m_customNumFmtsHash.contains(str)) { } else if (m_customNumFmtsHash.contains(str)) {
format->setNumFmt(m_customNumFmtsHash[str]->formatIndex, str); format->setNumFmt(m_customNumFmtsHash[str]->formatIndex, str);
} else { } else {
int idx = 164 + m_customNumFmts.size(); //Assign a new fmt Id.
format->setNumFmt(idx, str); format->setNumFmt(m_nextCustomNumFmtId, str);
QSharedPointer<NumberData> fmt(new NumberData(format->d_func()->numberData)); QSharedPointer<NumberData> fmt(new NumberData(format->d_func()->numberData));
m_customNumFmts.append(fmt); m_customNumFmtIdMap.insert(m_nextCustomNumFmtId, fmt);
m_customNumFmtsHash.insert(str, fmt); m_customNumFmtsHash.insert(str, fmt);
m_nextCustomNumFmtId += 1;
} }
} }
@ -249,15 +257,18 @@ void Styles::saveToXmlFile(QIODevice *device)
void Styles::writeNumFmts(XmlStreamWriter &writer) void Styles::writeNumFmts(XmlStreamWriter &writer)
{ {
if (m_customNumFmts.size() == 0) if (m_customNumFmtIdMap.size() == 0)
return; return;
writer.writeStartElement(QStringLiteral("numFmts")); writer.writeStartElement(QStringLiteral("numFmts"));
writer.writeAttribute(QStringLiteral("count"), QString::number(m_customNumFmts.count())); writer.writeAttribute(QStringLiteral("count"), QString::number(m_customNumFmtIdMap.count()));
for (int i=0; i<m_customNumFmts.size(); ++i) {
QMapIterator<int, QSharedPointer<NumberData> > it(m_customNumFmtIdMap);
while(it.hasNext()) {
it.next();
writer.writeEmptyElement(QStringLiteral("numFmt")); writer.writeEmptyElement(QStringLiteral("numFmt"));
writer.writeAttribute(QStringLiteral("numFmtId"), QString::number(164 + i)); writer.writeAttribute(QStringLiteral("numFmtId"), QString::number(it.value()->formatIndex));
writer.writeAttribute(QStringLiteral("formatCode"), m_customNumFmts[i]->formatString); writer.writeAttribute(QStringLiteral("formatCode"), it.value()->formatString);
} }
writer.writeEndElement();//numFmts writer.writeEndElement();//numFmts
} }
@ -546,7 +557,9 @@ bool Styles::readNumFmts(XmlStreamReader &reader)
QSharedPointer<NumberData> fmt (new NumberData); QSharedPointer<NumberData> fmt (new NumberData);
fmt->formatIndex = attributes.value(QLatin1String("numFmtId")).toInt(); fmt->formatIndex = attributes.value(QLatin1String("numFmtId")).toInt();
fmt->formatString = attributes.value(QLatin1String("formatCode")).toString(); fmt->formatString = attributes.value(QLatin1String("formatCode")).toString();
m_customNumFmts.append(fmt); if (fmt->formatIndex >= m_nextCustomNumFmtId)
m_nextCustomNumFmtId = fmt->formatIndex + 1;
m_customNumFmtIdMap.insert(fmt->formatIndex, fmt);
m_customNumFmtsHash.insert(fmt->formatString, fmt); m_customNumFmtsHash.insert(fmt->formatString, fmt);
while (!(reader.name() == QLatin1String("numFmt") && reader.tokenType() == QXmlStreamReader::EndElement)) while (!(reader.name() == QLatin1String("numFmt") && reader.tokenType() == QXmlStreamReader::EndElement))
@ -829,11 +842,10 @@ bool Styles::readCellXfs(XmlStreamReader &reader)
if (xfAttrs.hasAttribute(QLatin1String("applyNumberFormat"))) { if (xfAttrs.hasAttribute(QLatin1String("applyNumberFormat"))) {
int numFmtIndex = xfAttrs.value(QLatin1String("numFmtId")).toInt(); int numFmtIndex = xfAttrs.value(QLatin1String("numFmtId")).toInt();
if (numFmtIndex < 164) { if (!m_customNumFmtIdMap.contains(numFmtIndex))
format->setNumberFormatIndex(numFmtIndex); format->setNumberFormatIndex(numFmtIndex);
} else { else
format->d_func()->numberData = *m_customNumFmts[numFmtIndex-164]; format->d_func()->numberData = *m_customNumFmtIdMap[numFmtIndex];
}
} }
if (xfAttrs.hasAttribute(QLatin1String("applyFont"))) { if (xfAttrs.hasAttribute(QLatin1String("applyFont"))) {

4
src/xlsx/xlsxstyles_p.h

@ -30,6 +30,7 @@
#include <QSharedPointer> #include <QSharedPointer>
#include <QHash> #include <QHash>
#include <QList> #include <QList>
#include <QMap>
#include <QStringList> #include <QStringList>
class QIODevice; class QIODevice;
@ -82,8 +83,9 @@ private:
bool readCellXfs(XmlStreamReader &reader); bool readCellXfs(XmlStreamReader &reader);
QHash<QString, int> m_builtinNumFmtsHash; QHash<QString, int> m_builtinNumFmtsHash;
QList<QSharedPointer<NumberData> > m_customNumFmts; QMap<int, QSharedPointer<NumberData> > m_customNumFmtIdMap;
QHash<QString, QSharedPointer<NumberData> > m_customNumFmtsHash; QHash<QString, QSharedPointer<NumberData> > m_customNumFmtsHash;
int m_nextCustomNumFmtId;
QList<QSharedPointer<FontData> > m_fontsList; //Keep a copy of unique fonts QList<QSharedPointer<FontData> > m_fontsList; //Keep a copy of unique fonts
QList<QSharedPointer<FillData> > m_fillsList; //Keep a copy of unique fills QList<QSharedPointer<FillData> > m_fillsList; //Keep a copy of unique fills
QList<QSharedPointer<BorderData> > m_bordersList; //Keep a copy of unique borders QList<QSharedPointer<BorderData> > m_bordersList; //Keep a copy of unique borders

13
tests/auto/styles/tst_stylestest.cpp

@ -64,7 +64,7 @@ void StylesTest::testAddFormat2()
format2->setNumberFormat("aaaaa h:mm:ss AM/PM"); //custom format2->setNumberFormat("aaaaa h:mm:ss AM/PM"); //custom
styles.addFormat(format2); styles.addFormat(format2);
QCOMPARE(format2->numberFormatIndex(), 164); QCOMPARE(format2->numberFormatIndex(), 176);
} }
// For a solid fill, Excel reverses the role of foreground and background colours // For a solid fill, Excel reverses the role of foreground and background colours
@ -141,12 +141,11 @@ void StylesTest::testReadNumFmts()
reader.readNextStartElement();//So current node is numFmts reader.readNextStartElement();//So current node is numFmts
styles.readNumFmts(reader); styles.readNumFmts(reader);
QCOMPARE(styles.m_customNumFmts.size(), 2); QCOMPARE(styles.m_customNumFmtIdMap.size(), 2);
QCOMPARE(styles.m_customNumFmts[0]->formatIndex, 164); QVERIFY(styles.m_customNumFmtIdMap.contains(164));
QCOMPARE(styles.m_customNumFmts[0]->formatString, QStringLiteral("yyyy-mm-ddThh:mm:ss")); QCOMPARE(styles.m_customNumFmtIdMap[164]->formatString, QStringLiteral("yyyy-mm-ddThh:mm:ss"));
QCOMPARE(styles.m_customNumFmts[1]->formatIndex, 165); QVERIFY(styles.m_customNumFmtIdMap.contains(165));
QCOMPARE(styles.m_customNumFmts[1]->formatString, QStringLiteral("dd/mm/yyyy")); QCOMPARE(styles.m_customNumFmtIdMap[165]->formatString, QStringLiteral("dd/mm/yyyy"));
} }
QTEST_APPLESS_MAIN(StylesTest) QTEST_APPLESS_MAIN(StylesTest)

Loading…
Cancel
Save