Improve Document::read() support for shared formula
This commit is contained in:
+41
-27
@@ -159,62 +159,76 @@ bool isSpaceReserveNeeded(const QString &s)
|
|||||||
*/
|
*/
|
||||||
QString convertSharedFormula(const QString &rootFormula, const CellReference &rootCell, const CellReference &cell)
|
QString convertSharedFormula(const QString &rootFormula, const CellReference &rootCell, const CellReference &cell)
|
||||||
{
|
{
|
||||||
//Find all the "[A-Z]+[0-9]+" patterns in the rootFormula.
|
//Find all the "$?[A-Z]+$?[0-9]+" patterns in the rootFormula.
|
||||||
QList<QPair<QString, bool> > segments;
|
QList<QPair<QString, int> > segments;
|
||||||
|
|
||||||
QString segment;
|
QString segment;
|
||||||
bool inQuote = false;
|
bool inQuote = false;
|
||||||
int cellFlag = 0; //-1, 0, 1, 2 ==> Invalid, Empty, A-Z ready, A1 ready
|
enum RefState{INVALID, PRE_AZ, AZ, PRE_09, _09};
|
||||||
|
RefState refState = INVALID;
|
||||||
|
int refFlag = 0; // 0x00, 0x01, 0x02, 0x03 ==> A1, $A1, A$1, $A$1
|
||||||
foreach (QChar ch, rootFormula) {
|
foreach (QChar ch, rootFormula) {
|
||||||
if (inQuote) {
|
if (inQuote) {
|
||||||
segment.append(ch);
|
segment.append(ch);
|
||||||
if (ch == QLatin1Char('"')) {
|
if (ch == QLatin1Char('"'))
|
||||||
segments.append(qMakePair(segment, false));
|
|
||||||
segment = QString();
|
|
||||||
inQuote = false;
|
inQuote = false;
|
||||||
cellFlag = 0;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (ch == QLatin1Char('"')) {
|
if (ch == QLatin1Char('"')) {
|
||||||
segments.append(qMakePair(segment, false));
|
|
||||||
segment = QString(ch);
|
|
||||||
inQuote = true;
|
inQuote = true;
|
||||||
|
refState = INVALID;
|
||||||
|
segment.append(ch);
|
||||||
|
} else if (ch == QLatin1Char('$')) {
|
||||||
|
if (refState == AZ) {
|
||||||
|
segment.append(ch);
|
||||||
|
refState = PRE_09;
|
||||||
|
refFlag |= 0x02;
|
||||||
|
} else {
|
||||||
|
segments.append(qMakePair(segment, refState==_09 ? refFlag : -1));
|
||||||
|
segment = QString(ch); //Start new segment.
|
||||||
|
refState = PRE_AZ;
|
||||||
|
refFlag = 0x01;
|
||||||
|
}
|
||||||
} else if (ch >= QLatin1Char('A') && ch <=QLatin1Char('Z')) {
|
} else if (ch >= QLatin1Char('A') && ch <=QLatin1Char('Z')) {
|
||||||
if (cellFlag == 0 || cellFlag == 1) {
|
if (refState == PRE_AZ || refState == AZ) {
|
||||||
segment.append(ch);
|
segment.append(ch);
|
||||||
} else {
|
} else {
|
||||||
segments.append(qMakePair(segment, (cellFlag == 2)));
|
segments.append(qMakePair(segment, refState==_09 ? refFlag : -1));
|
||||||
segment = QString(ch); //start new "A1" segment
|
segment = QString(ch); //Start new segment.
|
||||||
|
refFlag = 0x00;
|
||||||
}
|
}
|
||||||
cellFlag = 1;
|
refState = AZ;
|
||||||
} else if (ch >= QLatin1Char('0') && ch <=QLatin1Char('9')) {
|
} else if (ch >= QLatin1Char('0') && ch <=QLatin1Char('9')) {
|
||||||
segment.append(ch);
|
segment.append(ch);
|
||||||
if (cellFlag == 1)
|
|
||||||
cellFlag = 2;
|
if (refState == AZ || refState == PRE_09 || refState == _09)
|
||||||
|
refState = _09;
|
||||||
|
else
|
||||||
|
refState = INVALID;
|
||||||
} else {
|
} else {
|
||||||
if (cellFlag == 2) {
|
if (refState == _09) {
|
||||||
segments.append(qMakePair(segment, true)); //find one "A1" segment
|
segments.append(qMakePair(segment, refFlag));
|
||||||
segment = QString(ch);
|
segment = QString(ch); //Start new segment.
|
||||||
} else {
|
} else {
|
||||||
segment.append(ch);
|
segment.append(ch);
|
||||||
}
|
}
|
||||||
cellFlag = -1;
|
refState = INVALID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!segment.isEmpty())
|
if (!segment.isEmpty())
|
||||||
segments.append(qMakePair(segment, (cellFlag == 2)));
|
segments.append(qMakePair(segment, refState==_09 ? refFlag : -1));
|
||||||
|
|
||||||
//Replace "A1" segment with proper one.
|
//Replace "A1", "$A1", "A$1" segment with proper one.
|
||||||
QStringList result;
|
QStringList result;
|
||||||
typedef QPair<QString, bool> PairType;
|
typedef QPair<QString, int> PairType;
|
||||||
foreach (PairType p, segments) {
|
foreach (PairType p, segments) {
|
||||||
if (p.second) {
|
//qDebug()<<p.first<<p.second;
|
||||||
|
if (p.second != -1 && p.second != 3) {
|
||||||
CellReference oldRef(p.first);
|
CellReference oldRef(p.first);
|
||||||
CellReference newRef(oldRef.row()-rootCell.row()+cell.row(),
|
int row = p.second & 0x02 ? oldRef.row() : oldRef.row()-rootCell.row()+cell.row();
|
||||||
oldRef.column()-rootCell.column()+cell.column());
|
int col = p.second & 0x01 ? oldRef.column() : oldRef.column()-rootCell.column()+cell.column();
|
||||||
result.append(newRef.toString());
|
result.append(CellReference(row, col).toString(p.second & 0x02, p.second & 0x01));
|
||||||
} else {
|
} else {
|
||||||
result.append(p.first);
|
result.append(p.first);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -165,6 +165,15 @@ void UtilityTest::test_convertSharedFormula_data()
|
|||||||
|
|
||||||
QTest::newRow("[C4]") << QString("A1*B8")<<QString("C1")<<QString("C4")<<QString("A4*B11");
|
QTest::newRow("[C4]") << QString("A1*B8")<<QString("C1")<<QString("C4")<<QString("A4*B11");
|
||||||
QTest::newRow("[C4]") << QString("TAN(A1+B2*B3)+COS(A1-B2)")<<QString("C1")<<QString("C4")<<QString("TAN(A4+B5*B6)+COS(A4-B5)");
|
QTest::newRow("[C4]") << QString("TAN(A1+B2*B3)+COS(A1-B2)")<<QString("C1")<<QString("C4")<<QString("TAN(A4+B5*B6)+COS(A4-B5)");
|
||||||
|
|
||||||
|
QTest::newRow("[Mixed B2]") << QString("$A1*A$1")<<QString("B1")<<QString("B2")<<QString("$A2*A$1");
|
||||||
|
QTest::newRow("[Mixed C1]") << QString("$A1*A$1")<<QString("B1")<<QString("C1")<<QString("$A1*B$1");
|
||||||
|
QTest::newRow("[Mixed D9]") << QString("$A1*A$1")<<QString("B1")<<QString("D9")<<QString("$A9*C$1");
|
||||||
|
QTest::newRow("[Mixed C4]") << QString("TAN(A1+B2*$B3)+COS(A1-B$2)")<<QString("C1")<<QString("C4")<<QString("TAN(A4+B5*$B6)+COS(A4-B$2)");
|
||||||
|
|
||||||
|
QTest::newRow("[Absolute C4]") << QString("A1*$B$8")<<QString("C1")<<QString("C4")<<QString("A4*$B$8");
|
||||||
|
|
||||||
|
QTest::newRow("[Quote]") << QString("=CONCATENATE(\"The B1 $B1 \",B1,\" units\")")<<QString("C1")<<QString("D2")<<QString("=CONCATENATE(\"The B1 $B1 \",C2,\" units\")");
|
||||||
}
|
}
|
||||||
|
|
||||||
void UtilityTest::test_convertSharedFormula()
|
void UtilityTest::test_convertSharedFormula()
|
||||||
|
|||||||
@@ -90,7 +90,6 @@ void WorksheetTest::testSetColumn()
|
|||||||
|
|
||||||
QByteArray xmldata = sheet.saveToXmlData();
|
QByteArray xmldata = sheet.saveToXmlData();
|
||||||
|
|
||||||
qDebug()<<xmldata;
|
|
||||||
QVERIFY(xmldata.contains("<col min=\"1\" max=\"3\"")); //"A:C"
|
QVERIFY(xmldata.contains("<col min=\"1\" max=\"3\"")); //"A:C"
|
||||||
QVERIFY(xmldata.contains("<col min=\"4\" max=\"5\"")); //"D:E"
|
QVERIFY(xmldata.contains("<col min=\"4\" max=\"5\"")); //"D:E"
|
||||||
QVERIFY(xmldata.contains("<col min=\"6\" max=\"6\"")); //"F:F"
|
QVERIFY(xmldata.contains("<col min=\"6\" max=\"6\"")); //"F:F"
|
||||||
@@ -110,13 +109,14 @@ void WorksheetTest::testWriteCells()
|
|||||||
sheet.writeFormula(5, 2, "44+33", QXlsx::Format(), 77);
|
sheet.writeFormula(5, 2, "44+33", QXlsx::Format(), 77);
|
||||||
|
|
||||||
QByteArray xmldata = sheet.saveToXmlData();
|
QByteArray xmldata = sheet.saveToXmlData();
|
||||||
|
qDebug()<<xmldata;
|
||||||
|
|
||||||
QVERIFY2(xmldata.contains("<c r=\"A1\"><v>123</v></c>"), "numeric");
|
QVERIFY2(xmldata.contains("<c r=\"A1\"><v>123</v></c>"), "numeric");
|
||||||
QVERIFY2(xmldata.contains("<c r=\"A2\" t=\"s\"><v>0</v></c>"), "string");
|
QVERIFY2(xmldata.contains("<c r=\"A2\" t=\"s\"><v>0</v></c>"), "string");
|
||||||
QVERIFY2(xmldata.contains("<c r=\"A3\" t=\"inlineStr\"><is><t>Hello inline</t></is></c>"), "inline string");
|
QVERIFY2(xmldata.contains("<c r=\"A3\" t=\"inlineStr\"><is><t>Hello inline</t></is></c>"), "inline string");
|
||||||
QVERIFY2(xmldata.contains("<c r=\"A4\" t=\"b\"><v>1</v></c>"), "boolean");
|
QVERIFY2(xmldata.contains("<c r=\"A4\" t=\"b\"><v>1</v></c>"), "boolean");
|
||||||
QVERIFY2(xmldata.contains("<c r=\"A5\"><f>44+33</f><v>0</v></c>"), "formula");
|
QVERIFY2(xmldata.contains("<c r=\"A5\"><f ca=\"1\">44+33</f><v>0</v></c>"), "formula");
|
||||||
QVERIFY2(xmldata.contains("<c r=\"B5\"><f>44+33</f><v>77</v></c>"), "formula");
|
QVERIFY2(xmldata.contains("<c r=\"B5\"><f ca=\"1\">44+33</f><v>77</v></c>"), "formula");
|
||||||
|
|
||||||
QCOMPARE(sheet.d_func()->sharedStrings()->getSharedString(0).toPlainString(), QStringLiteral("Hello"));
|
QCOMPARE(sheet.d_func()->sharedStrings()->getSharedString(0).toPlainString(), QStringLiteral("Hello"));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user