Fix numFmt: don't assume that all custom numFmtId starts from 164
This commit is contained in:
+34
-22
@@ -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"))) {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user