Browse Source

Code refactoring: Introduce new class CellFormula

master
Debao Zhang 11 years ago
parent
commit
4669640c27
  1. 5
      examples/xlsx/formulas/main.cpp
  2. 7
      src/xlsx/qtxlsx.pri
  3. 46
      src/xlsx/xlsxcell.cpp
  4. 25
      src/xlsx/xlsxcell.h
  5. 6
      src/xlsx/xlsxcell_p.h
  6. 249
      src/xlsx/xlsxcellformula.cpp
  7. 74
      src/xlsx/xlsxcellformula.h
  8. 63
      src/xlsx/xlsxcellformula_p.h
  9. 256
      src/xlsx/xlsxworksheet.cpp
  10. 5
      src/xlsx/xlsxworksheet.h
  11. 1
      src/xlsx/xlsxworksheet_p.h
  12. 47
      tests/auto/document/tst_documenttest.cpp
  13. 21
      tests/auto/worksheet/tst_worksheet.cpp

5
examples/xlsx/formulas/main.cpp

@ -2,6 +2,7 @@
#include "xlsxdocument.h" #include "xlsxdocument.h"
#include "xlsxformat.h" #include "xlsxformat.h"
#include "xlsxworksheet.h" #include "xlsxworksheet.h"
#include "xlsxcellformula.h"
QTXLSX_USE_NAMESPACE QTXLSX_USE_NAMESPACE
@ -58,8 +59,8 @@ int main()
sheet->write(row, 3, QString(row%5+1, 'X')); //C2:C19 sheet->write(row, 3, QString(row%5+1, 'X')); //C2:C19
sheet->write(row, 5, 100.0 - row); //E2:E19 sheet->write(row, 5, 100.0 - row); //E2:E19
} }
sheet->writeArrayFormula("C20", "{=SUM(IF((C2:C19=\"X\")*(B2:B19=\"X\"),1,0))}"); sheet->writeFormula("C20", CellFormula("SUM(IF((C2:C19=\"X\")*(B2:B19=\"X\"),1,0))", "C20", CellFormula::ArrayType));
sheet->writeArrayFormula("F2:F19", "{=E2:E19*10}"); sheet->writeFormula("F2", CellFormula("E2:E19*10", "F2:F19", CellFormula::ArrayType));
//![2] //![2]
//![3] //![3]

7
src/xlsx/qtxlsx.pri

@ -46,7 +46,9 @@ HEADERS += $$PWD/xlsxdocpropscore_p.h \
$$PWD/xlsxabstractooxmlfile_p.h \ $$PWD/xlsxabstractooxmlfile_p.h \
$$PWD/xlsxchart.h \ $$PWD/xlsxchart.h \
$$PWD/xlsxchart_p.h \ $$PWD/xlsxchart_p.h \
$$PWD/xlsxsimpleooxmlfile_p.h $$PWD/xlsxsimpleooxmlfile_p.h \
$$PWD/xlsxcellformula.h \
$$PWD/xlsxcellformula_p.h
SOURCES += $$PWD/xlsxdocpropscore.cpp \ SOURCES += $$PWD/xlsxdocpropscore.cpp \
$$PWD/xlsxdocpropsapp.cpp \ $$PWD/xlsxdocpropsapp.cpp \
@ -77,5 +79,6 @@ SOURCES += $$PWD/xlsxdocpropscore.cpp \
$$PWD/xlsxmediafile.cpp \ $$PWD/xlsxmediafile.cpp \
$$PWD/xlsxabstractooxmlfile.cpp \ $$PWD/xlsxabstractooxmlfile.cpp \
$$PWD/xlsxchart.cpp \ $$PWD/xlsxchart.cpp \
$$PWD/xlsxsimpleooxmlfile.cpp $$PWD/xlsxsimpleooxmlfile.cpp \
$$PWD/xlsxcellformula.cpp

46
src/xlsx/xlsxcell.cpp

@ -40,9 +40,8 @@ CellPrivate::CellPrivate(Cell *p) :
} }
CellPrivate::CellPrivate(const CellPrivate * const cp) CellPrivate::CellPrivate(const CellPrivate * const cp)
: value(cp->value), formula(cp->formula), dataType(cp->dataType) : value(cp->value), formula(cp->formula), cellType(cp->cellType)
, format(cp->format), range(cp->range), richString(cp->richString) , format(cp->format), richString(cp->richString), parent(cp->parent)
, parent(cp->parent)
{ {
} }
@ -55,27 +54,24 @@ CellPrivate::CellPrivate(const CellPrivate * const cp)
*/ */
/*! /*!
\enum Cell::DataType \enum Cell::CellType
\value BooleanType Boolean type
\value Blank, \value NumberType Number type, can be blank or used with forumula
\value String, \value ErrorType Error type
\value Numeric, \value SharedStringType Shared string type
\value Formula, \value StringType String type, can be used with forumula
\value Boolean, \value InlineStringType Inline string type
\value Error,
\value InlineString,
\value ArrayFormula
*/ */
/*! /*!
* \internal * \internal
* Created by Worksheet only. * Created by Worksheet only.
*/ */
Cell::Cell(const QVariant &data, DataType type, const Format &format, Worksheet *parent) : Cell::Cell(const QVariant &data, CellType type, const Format &format, Worksheet *parent) :
d_ptr(new CellPrivate(this)) d_ptr(new CellPrivate(this))
{ {
d_ptr->value = data; d_ptr->value = data;
d_ptr->dataType = type; d_ptr->cellType = type;
d_ptr->format = format; d_ptr->format = format;
d_ptr->parent = parent; d_ptr->parent = parent;
} }
@ -100,10 +96,10 @@ Cell::~Cell()
/*! /*!
* Return the dataType of this Cell * Return the dataType of this Cell
*/ */
Cell::DataType Cell::dataType() const Cell::CellType Cell::cellType() const
{ {
Q_D(const Cell); Q_D(const Cell);
return d->dataType; return d->cellType;
} }
/*! /*!
@ -124,10 +120,19 @@ Format Cell::format() const
return d->format; return d->format;
} }
/*!
* Returns true if the cell has one formula.
*/
bool Cell::hasFormula() const
{
Q_D(const Cell);
return d->formula.isValid();
}
/*! /*!
* Return the formula contents if the dataType is Formula * Return the formula contents if the dataType is Formula
*/ */
QString Cell::formula() const CellFormula Cell::formula() const
{ {
Q_D(const Cell); Q_D(const Cell);
return d->formula; return d->formula;
@ -139,7 +144,7 @@ QString Cell::formula() const
bool Cell::isDateTime() const bool Cell::isDateTime() const
{ {
Q_D(const Cell); Q_D(const Cell);
if (d->dataType == Numeric && d->value.toDouble() >=0 if (d->cellType == NumberType && d->value.toDouble() >=0
&& d->format.isValid() && d->format.isDateTimeFormat()) { && d->format.isValid() && d->format.isDateTimeFormat()) {
return true; return true;
} }
@ -163,7 +168,8 @@ QDateTime Cell::dateTime() const
bool Cell::isRichString() const bool Cell::isRichString() const
{ {
Q_D(const Cell); Q_D(const Cell);
if (d->dataType != String && d->dataType != InlineString) if (d->cellType != SharedStringType && d->cellType != InlineStringType
&& d->cellType != StringType)
return false; return false;
return d->richString.isRichString(); return d->richString.isRichString();

25
src/xlsx/xlsxcell.h

@ -33,6 +33,7 @@ QT_BEGIN_NAMESPACE_XLSX
class Worksheet; class Worksheet;
class Format; class Format;
class CellFormula;
class CellPrivate; class CellPrivate;
class WorksheetPrivate; class WorksheetPrivate;
@ -40,21 +41,21 @@ class Q_XLSX_EXPORT Cell
{ {
Q_DECLARE_PRIVATE(Cell) Q_DECLARE_PRIVATE(Cell)
public: public:
enum DataType { enum CellType {
Blank, BooleanType, //t="b"
String, NumberType, //t="n" (default)
Numeric, ErrorType, //t="e"
Formula, SharedStringType, //t="s"
Boolean, StringType, //t="str"
Error, InlineStringType //t="inlineStr"
InlineString,
ArrayFormula
}; };
DataType dataType() const; CellType cellType() const;
QVariant value() const; QVariant value() const;
Format format() const; Format format() const;
QString formula() const;
bool hasFormula() const;
CellFormula formula() const;
bool isDateTime() const; bool isDateTime() const;
QDateTime dateTime() const; QDateTime dateTime() const;
@ -66,7 +67,7 @@ private:
friend class Worksheet; friend class Worksheet;
friend class WorksheetPrivate; friend class WorksheetPrivate;
Cell(const QVariant &data=QVariant(), DataType type=Blank, const Format &format=Format(), Worksheet *parent=0); Cell(const QVariant &data=QVariant(), CellType type=NumberType, const Format &format=Format(), Worksheet *parent=0);
Cell(const Cell * const cell); Cell(const Cell * const cell);
CellPrivate * const d_ptr; CellPrivate * const d_ptr;
}; };

6
src/xlsx/xlsxcell_p.h

@ -40,6 +40,7 @@
#include "xlsxcell.h" #include "xlsxcell.h"
#include "xlsxcellrange.h" #include "xlsxcellrange.h"
#include "xlsxrichstring.h" #include "xlsxrichstring.h"
#include "xlsxcellformula.h"
#include <QList> #include <QList>
#include <QSharedPointer> #include <QSharedPointer>
@ -53,10 +54,9 @@ public:
CellPrivate(const CellPrivate * const cp); CellPrivate(const CellPrivate * const cp);
QVariant value; QVariant value;
QString formula; CellFormula formula;
Cell::DataType dataType; Cell::CellType cellType;
Format format; Format format;
CellRange range; //used for arrayFormula
RichString richString; RichString richString;

249
src/xlsx/xlsxcellformula.cpp

@ -0,0 +1,249 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#include "xlsxcellformula.h"
#include "xlsxcellformula_p.h"
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
QT_BEGIN_NAMESPACE_XLSX
CellFormulaPrivate::CellFormulaPrivate(const QString &formula_, const CellRange &ref_, CellFormula::FormulaType type_)
:formula(formula_), type(type_), reference(ref_), si(0)
{
//Remove the formula '=' sign if exists
if (formula.startsWith(QLatin1String("=")))
formula.remove(0,1);
else if (formula.startsWith(QLatin1String("{=")) && formula.endsWith(QLatin1String("}")))
formula = formula.mid(2, formula.length()-3);
}
CellFormulaPrivate::CellFormulaPrivate(const CellFormulaPrivate &other)
: QSharedData(other)
, formula(other.formula), type(other.type), reference(other.reference), si(other.si)
{
}
CellFormulaPrivate::~CellFormulaPrivate()
{
}
/*!
\class CellFormula
\inmodule QtXlsx
\brief The CellFormula class provides a API that is used to handle the cell formula.
*/
/*!
\enum CellFormula::FormulaType
\value NormalType
\value ArrayType
\value DataTableType
\value SharedType
*/
/*!
* Creates a new formula.
*/
CellFormula::CellFormula()
{
//The d pointer is initialized with a null pointer
}
/*!
* Creates a new formula with the given \a formula and \a type.
*/
CellFormula::CellFormula(const char *formula, FormulaType type)
:d(new CellFormulaPrivate(QString::fromLatin1(formula), CellRange(), type))
{
}
/*!
* Creates a new formula with the given \a formula and \a type.
*/
CellFormula::CellFormula(const QString &formula, FormulaType type)
:d(new CellFormulaPrivate(formula, CellRange(), type))
{
}
/*!
* Creates a new formula with the given \a formula, \a ref and \a type.
*/
CellFormula::CellFormula(const QString &formula, const CellRange &ref, FormulaType type)
:d(new CellFormulaPrivate(formula, ref, type))
{
}
/*!
Creates a new formula with the same attributes as the \a other formula.
*/
CellFormula::CellFormula(const CellFormula &other)
:d(other.d)
{
}
/*!
Assigns the \a other formula to this formula, and returns a
reference to this formula.
*/
CellFormula &CellFormula::operator =(const CellFormula &other)
{
d = other.d;
return *this;
}
/*!
* Destroys this formula.
*/
CellFormula::~CellFormula()
{
}
/*!
* Returns the type of the formula.
*/
CellFormula::FormulaType CellFormula::formulaType() const
{
return d ? d->type : NormalType;
}
/*!
* Returns the contents of the formula.
*/
QString CellFormula::formulaContent() const
{
return d ? d->formula : QString();
}
/*!
* Returns the reference cells of the formula. For normal formula,
* this will return an invalid CellRange object.
*/
CellRange CellFormula::reference() const
{
return d ? d->reference : CellRange();
}
/*!
* Returns whether the formula is valid.
*/
bool CellFormula::isValid() const
{
return d;
}
/*!
* Returns the shared index for shared formula.
*/
int CellFormula::sharedIndex() const
{
return d && d->type == SharedType ? d->si : -1;
}
/*!
* \internal
*/
bool CellFormula::saveToXml(QXmlStreamWriter &writer) const
{
writer.writeStartElement(QStringLiteral("f"));
QString t;
switch (d->type) {
case CellFormula::ArrayType:
t = QStringLiteral("array");
break;
case CellFormula::SharedType:
t = QStringLiteral("shared");
break;
default:
break;
}
if (!t.isEmpty())
writer.writeAttribute(QStringLiteral("t"), t);
if (d->reference.isValid())
writer.writeAttribute(QStringLiteral("ref"), d->reference.toString());
if (d->type == CellFormula::SharedType)
writer.writeAttribute(QStringLiteral("si"), QString::number(d->si));
writer.writeCharacters(d->formula);
writer.writeEndElement(); //f
return true;
}
/*!
* \internal
*/
bool CellFormula::loadFromXml(QXmlStreamReader &reader)
{
Q_ASSERT(reader.name() == QLatin1String("f"));
if (!d)
d = new CellFormulaPrivate(QString(), CellRange(), NormalType);
QXmlStreamAttributes attributes = reader.attributes();
QString typeString = attributes.value(QLatin1String("t")).toString();
if (typeString == QLatin1String("array"))
d->type = ArrayType;
else if (typeString == QLatin1String("shared"))
d->type = SharedType;
else
d->type = NormalType;
if (attributes.hasAttribute(QLatin1String("ref"))) {
QString refString = attributes.value(QLatin1String("ref")).toString();
d->reference = CellRange(refString);
} else if (attributes.hasAttribute(QLatin1String("si"))) {
d->si = attributes.value(QLatin1String("si")).toString().toInt();
}
d->formula = reader.readElementText();
return true;
}
/*!
* \internal
*/
bool CellFormula::operator ==(const CellFormula &formula) const
{
return d->formula == formula.d->formula && d->type == formula.d->type
&& d->si ==formula.d->si;
}
/*!
* \internal
*/
bool CellFormula::operator !=(const CellFormula &formula) const
{
return d->formula != formula.d->formula || d->type != formula.d->type
|| d->si !=formula.d->si;
}
QT_END_NAMESPACE_XLSX

74
src/xlsx/xlsxcellformula.h

@ -0,0 +1,74 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef QXLSX_XLSXCELLFORMULA_H
#define QXLSX_XLSXCELLFORMULA_H
#include "xlsxglobal.h"
#include <QExplicitlySharedDataPointer>
class QXmlStreamWriter;
class QXmlStreamReader;
QT_BEGIN_NAMESPACE_XLSX
class CellFormulaPrivate;
class CellRange;
class Q_XLSX_EXPORT CellFormula
{
public:
enum FormulaType {
NormalType,
ArrayType,
DataTableType,
SharedType
};
CellFormula();
CellFormula(const char *formula, FormulaType type=NormalType);
CellFormula(const QString &formula, FormulaType type=NormalType);
CellFormula(const QString &formula, const CellRange &ref, FormulaType type);
CellFormula(const CellFormula &other);
~CellFormula();
CellFormula &operator =(const CellFormula &other);
bool isValid() const;
FormulaType formulaType() const;
QString formulaContent() const;
CellRange reference() const;
int sharedIndex() const;
bool operator == (const CellFormula &formula) const;
bool operator != (const CellFormula &formula) const;
bool saveToXml(QXmlStreamWriter &writer) const;
bool loadFromXml(QXmlStreamReader &reader);
private:
QExplicitlySharedDataPointer<CellFormulaPrivate> d;
};
QT_END_NAMESPACE_XLSX
#endif // QXLSX_XLSXCELLFORMULA_H

63
src/xlsx/xlsxcellformula_p.h

@ -0,0 +1,63 @@
/****************************************************************************
** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
** All right reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
****************************************************************************/
#ifndef XLSXCELLFORMULA_P_H
#define XLSXCELLFORMULA_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt Xlsx API. It exists for the convenience
// of the Qt Xlsx. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
//
#include "xlsxglobal.h"
#include "xlsxcellformula.h"
#include "xlsxcellrange.h"
#include <QSharedData>
#include <QString>
QT_BEGIN_NAMESPACE_XLSX
class CellFormulaPrivate : public QSharedData
{
public:
CellFormulaPrivate(const QString &formula, const CellRange &reference, CellFormula::FormulaType type);
CellFormulaPrivate(const CellFormulaPrivate &other);
~CellFormulaPrivate();
QString formula; //formula contents
CellFormula::FormulaType type;
CellRange reference;
int si;
};
QT_END_NAMESPACE_XLSX
#endif // XLSXCELLFORMULA_P_H

256
src/xlsx/xlsxworksheet.cpp

@ -39,6 +39,8 @@
#include "xlsxconditionalformatting_p.h" #include "xlsxconditionalformatting_p.h"
#include "xlsxdrawinganchor_p.h" #include "xlsxdrawinganchor_p.h"
#include "xlsxchart.h" #include "xlsxchart.h"
#include "xlsxcellformula.h"
#include "xlsxcellformula_p.h"
#include <QVariant> #include <QVariant>
#include <QDateTime> #include <QDateTime>
@ -208,7 +210,7 @@ Worksheet *Worksheet::copy(const QString &distName, int distId) const
QSharedPointer<Cell> cell(new Cell(it2.value().data())); QSharedPointer<Cell> cell(new Cell(it2.value().data()));
cell->d_ptr->parent = sheet; cell->d_ptr->parent = sheet;
if (cell->dataType() == Cell::String) if (cell->cellType() == Cell::SharedStringType)
d->workbook->sharedStrings()->addSharedString(cell->d_ptr->richString); d->workbook->sharedStrings()->addSharedString(cell->d_ptr->richString);
sheet_d->cellTable[row][col] = cell; sheet_d->cellTable[row][col] = cell;
@ -437,10 +439,7 @@ bool Worksheet::write(int row, int column, const QVariant &value, const Format &
if (token.startsWith(QLatin1String("="))) { if (token.startsWith(QLatin1String("="))) {
//convert to formula //convert to formula
ret = writeFormula(row, column, token, format); ret = writeFormula(row, column, CellFormula(token), format);
} else if (token.startsWith(QLatin1String("{=")) && token.endsWith(QLatin1Char('}'))) {
//convert to array formula
ret = writeArrayFormula(CellRange(row, column, row, column), token, format);
} else if (d->workbook->isStringsToHyperlinksEnabled() && token.contains(d->urlPattern)) { } else if (d->workbook->isStringsToHyperlinksEnabled() && token.contains(d->urlPattern)) {
//convert to url //convert to url
ret = writeHyperlink(row, column, QUrl(token)); ret = writeHyperlink(row, column, QUrl(token));
@ -513,8 +512,8 @@ QVariant Worksheet::read(int row, int column) const
Cell *cell = cellAt(row, column); Cell *cell = cellAt(row, column);
if (!cell) if (!cell)
return QVariant(); return QVariant();
if (!cell->formula().isEmpty()) if (cell->hasFormula() && cell->formula().formulaType() == CellFormula::NormalType)
return QVariant(QLatin1String("=")+cell->formula()); return QVariant(QLatin1String("=")+cell->formula().formulaContent());
if (cell->isDateTime()) { if (cell->isDateTime()) {
double val = cell->value().toDouble(); double val = cell->value().toDouble();
QDateTime dt = cell->dateTime(); QDateTime dt = cell->dateTime();
@ -596,7 +595,7 @@ bool Worksheet::writeString(int row, int column, const RichString &value, const
if (value.fragmentCount() == 1 && value.fragmentFormat(0).isValid()) if (value.fragmentCount() == 1 && value.fragmentFormat(0).isValid())
fmt.mergeFormat(value.fragmentFormat(0)); fmt.mergeFormat(value.fragmentFormat(0));
d->workbook->styles()->addXfFormat(fmt); d->workbook->styles()->addXfFormat(fmt);
QSharedPointer<Cell> cell = QSharedPointer<Cell>(new Cell(value.toPlainString(), Cell::String, fmt, this)); QSharedPointer<Cell> cell = QSharedPointer<Cell>(new Cell(value.toPlainString(), Cell::SharedStringType, fmt, this));
cell->d_ptr->richString = value; cell->d_ptr->richString = value;
d->cellTable[row][column] = cell; d->cellTable[row][column] = cell;
return true; return true;
@ -664,7 +663,7 @@ bool Worksheet::writeInlineString(int row, int column, const QString &value, con
Format fmt = format.isValid() ? format : d->cellFormat(row, column); Format fmt = format.isValid() ? format : d->cellFormat(row, column);
d->workbook->styles()->addXfFormat(fmt); d->workbook->styles()->addXfFormat(fmt);
d->cellTable[row][column] = QSharedPointer<Cell>(new Cell(value, Cell::InlineString, fmt, this)); d->cellTable[row][column] = QSharedPointer<Cell>(new Cell(value, Cell::InlineStringType, fmt, this));
return true; return true;
} }
@ -691,7 +690,7 @@ bool Worksheet::writeNumeric(int row, int column, double value, const Format &fo
Format fmt = format.isValid() ? format : d->cellFormat(row, column); Format fmt = format.isValid() ? format : d->cellFormat(row, column);
d->workbook->styles()->addXfFormat(fmt); d->workbook->styles()->addXfFormat(fmt);
d->cellTable[row][column] = QSharedPointer<Cell>(new Cell(value, Cell::Numeric, fmt, this)); d->cellTable[row][column] = QSharedPointer<Cell>(new Cell(value, Cell::NumberType, fmt, this));
return true; return true;
} }
@ -699,7 +698,7 @@ bool Worksheet::writeNumeric(int row, int column, double value, const Format &fo
\overload \overload
Write \a formula to the cell \a row_column with the \a format and \a result. Write \a formula to the cell \a row_column with the \a format and \a result.
*/ */
bool Worksheet::writeFormula(const CellReference &row_column, const QString &formula, const Format &format, double result) bool Worksheet::writeFormula(const CellReference &row_column, const CellFormula &formula, const Format &format, double result)
{ {
if (!row_column.isValid()) if (!row_column.isValid())
return false; return false;
@ -710,58 +709,18 @@ bool Worksheet::writeFormula(const CellReference &row_column, const QString &for
/*! /*!
Write \a formula to the cell (\a row, \a column) with the \a format and \a result. Write \a formula to the cell (\a row, \a column) with the \a format and \a result.
*/ */
bool Worksheet::writeFormula(int row, int column, const QString &formula, const Format &format, double result) bool Worksheet::writeFormula(int row, int column, const CellFormula &formula, const Format &format, double result)
{ {
Q_D(Worksheet); Q_D(Worksheet);
QString _formula = formula;
if (d->checkDimensions(row, column)) if (d->checkDimensions(row, column))
return false; return false;
//Remove the formula '=' sign if exists
if (_formula.startsWith(QLatin1String("=")))
_formula.remove(0,1);
Format fmt = format.isValid() ? format : d->cellFormat(row, column); Format fmt = format.isValid() ? format : d->cellFormat(row, column);
d->workbook->styles()->addXfFormat(fmt); d->workbook->styles()->addXfFormat(fmt);
Cell *data = new Cell(result, Cell::Formula, fmt, this);
data->d_ptr->formula = _formula;
d->cellTable[row][column] = QSharedPointer<Cell>(data);
return true;
}
/*! QSharedPointer<Cell> data = QSharedPointer<Cell>(new Cell(result, Cell::NumberType, fmt, this));
Write \a formula to the \a range with the \a format data->d_ptr->formula = formula;
*/
bool Worksheet::writeArrayFormula(const CellRange &range, const QString &formula, const Format &format)
{
Q_D(Worksheet);
if (d->checkDimensions(range.firstRow(), range.firstColumn()))
return false;
if (d->checkDimensions(range.lastRow(), range.lastColumn()))
return false;
QString _formula = formula;
//Remove the formula "{=" and "}" sign if exists
if (_formula.startsWith(QLatin1String("{=")))
_formula.remove(0,2);
if (_formula.endsWith(QLatin1Char('}')))
_formula.chop(1);
for (int row=range.firstRow(); row<=range.lastRow(); ++row) {
for (int column=range.firstColumn(); column<=range.lastColumn(); ++column) {
Format _format = format.isValid() ? format : d->cellFormat(row, column);
d->workbook->styles()->addXfFormat(_format);
if (row == range.firstRow() && column == range.firstColumn()) {
QSharedPointer<Cell> data(new Cell(0, Cell::ArrayFormula, _format, this));
data->d_ptr->formula = _formula;
data->d_ptr->range = range;
d->cellTable[row][column] = data; d->cellTable[row][column] = data;
} else {
d->cellTable[row][column] = QSharedPointer<Cell>(new Cell(0, Cell::Numeric, _format, this));
}
}
}
return true; return true;
} }
@ -790,7 +749,8 @@ bool Worksheet::writeBlank(int row, int column, const Format &format)
Format fmt = format.isValid() ? format : d->cellFormat(row, column); Format fmt = format.isValid() ? format : d->cellFormat(row, column);
d->workbook->styles()->addXfFormat(fmt); d->workbook->styles()->addXfFormat(fmt);
d->cellTable[row][column] = QSharedPointer<Cell>(new Cell(QVariant(), Cell::Blank, fmt, this)); //Note: NumberType with an invalid QVariant value means blank.
d->cellTable[row][column] = QSharedPointer<Cell>(new Cell(QVariant(), Cell::NumberType, fmt, this));
return true; return true;
} }
@ -817,7 +777,7 @@ bool Worksheet::writeBool(int row, int column, bool value, const Format &format)
Format fmt = format.isValid() ? format : d->cellFormat(row, column); Format fmt = format.isValid() ? format : d->cellFormat(row, column);
d->workbook->styles()->addXfFormat(fmt); d->workbook->styles()->addXfFormat(fmt);
d->cellTable[row][column] = QSharedPointer<Cell>(new Cell(value, Cell::Boolean, fmt, this)); d->cellTable[row][column] = QSharedPointer<Cell>(new Cell(value, Cell::BooleanType, fmt, this));
return true; return true;
} }
@ -849,7 +809,7 @@ bool Worksheet::writeDateTime(int row, int column, const QDateTime &dt, const Fo
double value = datetimeToNumber(dt, d->workbook->isDate1904()); double value = datetimeToNumber(dt, d->workbook->isDate1904());
d->cellTable[row][column] = QSharedPointer<Cell>(new Cell(value, Cell::Numeric, fmt, this)); d->cellTable[row][column] = QSharedPointer<Cell>(new Cell(value, Cell::NumberType, fmt, this));
return true; return true;
} }
@ -880,7 +840,7 @@ bool Worksheet::writeTime(int row, int column, const QTime &t, const Format &for
fmt.setNumberFormat(QStringLiteral("hh:mm:ss")); fmt.setNumberFormat(QStringLiteral("hh:mm:ss"));
d->workbook->styles()->addXfFormat(fmt); d->workbook->styles()->addXfFormat(fmt);
d->cellTable[row][column] = QSharedPointer<Cell>(new Cell(timeToNumber(t), Cell::Numeric, fmt, this)); d->cellTable[row][column] = QSharedPointer<Cell>(new Cell(timeToNumber(t), Cell::NumberType, fmt, this));
return true; return true;
} }
@ -943,7 +903,7 @@ bool Worksheet::writeHyperlink(int row, int column, const QUrl &url, const Forma
//Write the hyperlink string as normal string. //Write the hyperlink string as normal string.
d->sharedStrings()->addSharedString(displayString); d->sharedStrings()->addSharedString(displayString);
d->cellTable[row][column] = QSharedPointer<Cell>(new Cell(displayString, Cell::String, fmt, this)); d->cellTable[row][column] = QSharedPointer<Cell>(new Cell(displayString, Cell::SharedStringType, fmt, this));
//Store the hyperlink data in a separate table //Store the hyperlink data in a separate table
d->urlTable[row][column] = QSharedPointer<XlsxHyperlinkData>(new XlsxHyperlinkData(XlsxHyperlinkData::External, urlString, locationString, QString(), tip)); d->urlTable[row][column] = QSharedPointer<XlsxHyperlinkData>(new XlsxHyperlinkData(XlsxHyperlinkData::External, urlString, locationString, QString(), tip));
@ -1275,7 +1235,7 @@ void WorksheetPrivate::saveXmlCellData(QXmlStreamWriter &writer, int row, int co
else if (colsInfoHelper.contains(col) && !colsInfoHelper[col]->format.isEmpty()) else if (colsInfoHelper.contains(col) && !colsInfoHelper[col]->format.isEmpty())
writer.writeAttribute(QStringLiteral("s"), QString::number(colsInfoHelper[col]->format.xfIndex())); writer.writeAttribute(QStringLiteral("s"), QString::number(colsInfoHelper[col]->format.xfIndex()));
if (cell->dataType() == Cell::String) { if (cell->cellType() == Cell::SharedStringType) {
int sst_idx; int sst_idx;
if (cell->isRichString()) if (cell->isRichString())
sst_idx = sharedStrings()->getSharedStringIndex(cell->d_ptr->richString); sst_idx = sharedStrings()->getSharedStringIndex(cell->d_ptr->richString);
@ -1284,7 +1244,7 @@ void WorksheetPrivate::saveXmlCellData(QXmlStreamWriter &writer, int row, int co
writer.writeAttribute(QStringLiteral("t"), QStringLiteral("s")); writer.writeAttribute(QStringLiteral("t"), QStringLiteral("s"));
writer.writeTextElement(QStringLiteral("v"), QString::number(sst_idx)); writer.writeTextElement(QStringLiteral("v"), QString::number(sst_idx));
} else if (cell->dataType() == Cell::InlineString) { } else if (cell->cellType() == Cell::InlineStringType) {
writer.writeAttribute(QStringLiteral("t"), QStringLiteral("inlineStr")); writer.writeAttribute(QStringLiteral("t"), QStringLiteral("inlineStr"));
writer.writeStartElement(QStringLiteral("is")); writer.writeStartElement(QStringLiteral("is"));
if (cell->isRichString()) { if (cell->isRichString()) {
@ -1313,28 +1273,21 @@ void WorksheetPrivate::saveXmlCellData(QXmlStreamWriter &writer, int row, int co
writer.writeEndElement(); // t writer.writeEndElement(); // t
} }
writer.writeEndElement();//is writer.writeEndElement();//is
} else if (cell->dataType() == Cell::Numeric){ } else if (cell->cellType() == Cell::NumberType){
if (cell->hasFormula())
cell->formula().saveToXml(writer);
if (cell->value().isValid()) {//note that, invalid value means 'v' is blank
double value = cell->value().toDouble(); double value = cell->value().toDouble();
writer.writeTextElement(QStringLiteral("v"), QString::number(value, 'g', 15)); writer.writeTextElement(QStringLiteral("v"), QString::number(value, 'g', 15));
} else if (cell->dataType() == Cell::Formula) { }
bool ok = true; } else if (cell->cellType() == Cell::StringType) {
cell->formula().toDouble(&ok);
if (!ok) //is string
writer.writeAttribute(QStringLiteral("t"), QStringLiteral("str")); writer.writeAttribute(QStringLiteral("t"), QStringLiteral("str"));
writer.writeTextElement(QStringLiteral("f"), cell->formula()); if (cell->hasFormula())
cell->formula().saveToXml(writer);
writer.writeTextElement(QStringLiteral("v"), cell->value().toString()); writer.writeTextElement(QStringLiteral("v"), cell->value().toString());
} else if (cell->dataType() == Cell::ArrayFormula) { } else if (cell->cellType() == Cell::BooleanType) {
writer.writeStartElement(QStringLiteral("f"));
writer.writeAttribute(QStringLiteral("t"), QStringLiteral("array"));
writer.writeAttribute(QStringLiteral("ref"), cell->d_ptr->range.toString());
writer.writeCharacters(cell->formula());
writer.writeEndElement(); //f
writer.writeTextElement(QStringLiteral("v"), cell->value().toString());
} else if (cell->dataType() == Cell::Boolean) {
writer.writeAttribute(QStringLiteral("t"), QStringLiteral("b")); writer.writeAttribute(QStringLiteral("t"), QStringLiteral("b"));
writer.writeTextElement(QStringLiteral("v"), cell->value().toBool() ? QStringLiteral("1") : QStringLiteral("0")); writer.writeTextElement(QStringLiteral("v"), cell->value().toBool() ? QStringLiteral("1") : QStringLiteral("0"));
} else if (cell->dataType() == Cell::Blank) {
//Ok, empty here.
} }
writer.writeEndElement(); //c writer.writeEndElement(); //c
} }
@ -1864,55 +1817,13 @@ int WorksheetPrivate::colPixelsSize(int col) const
return pixels; return pixels;
} }
QSharedPointer<Cell> WorksheetPrivate::loadXmlNumericCellData(QXmlStreamReader &reader)
{
Q_ASSERT(reader.name() == QLatin1String("c"));
QString v_str;
QString f_str;
QSharedPointer<Cell> cell;
while (!reader.atEnd() && !(reader.name() == QLatin1String("c") && reader.tokenType() == QXmlStreamReader::EndElement)) {
reader.readNextStartElement();
if (reader.tokenType() == QXmlStreamReader::StartElement) {
if (reader.name() == QLatin1String("v")) {
v_str = reader.readElementText();
} else if (reader.name() == QLatin1String("f")) {
QXmlStreamAttributes fAttrs = reader.attributes();
if (fAttrs.hasAttribute(QLatin1String("array"))) {
cell = QSharedPointer<Cell>(new Cell(0, Cell::ArrayFormula));
cell->d_ptr->range = CellRange(fAttrs.value(QLatin1String("ref")).toString());
} else {
cell = QSharedPointer<Cell>(new Cell(0, Cell::Formula));
}
f_str = reader.readElementText();
}
}
}
if (v_str.isEmpty() && f_str.isEmpty()) {
//blank type
return QSharedPointer<Cell>(new Cell(QVariant(), Cell::Blank));
} else if (f_str.isEmpty()) {
//numeric type
return QSharedPointer<Cell>(new Cell(v_str.toDouble(), Cell::Numeric));
} else {
//formula type
cell->d_ptr->value = v_str.toDouble();
cell->d_ptr->formula = f_str;
}
return cell;
}
void WorksheetPrivate::loadXmlSheetData(QXmlStreamReader &reader) void WorksheetPrivate::loadXmlSheetData(QXmlStreamReader &reader)
{ {
Q_Q(Worksheet); Q_Q(Worksheet);
Q_ASSERT(reader.name() == QLatin1String("sheetData")); Q_ASSERT(reader.name() == QLatin1String("sheetData"));
while (!reader.atEnd() && !(reader.name() == QLatin1String("sheetData") && reader.tokenType() == QXmlStreamReader::EndElement)) { while (!reader.atEnd() && !(reader.name() == QLatin1String("sheetData") && reader.tokenType() == QXmlStreamReader::EndElement)) {
reader.readNextStartElement(); if (reader.readNextStartElement()) {
if (reader.tokenType() == QXmlStreamReader::StartElement) {
if (reader.name() == QLatin1String("row")) { if (reader.name() == QLatin1String("row")) {
QXmlStreamAttributes attributes = reader.attributes(); QXmlStreamAttributes attributes = reader.attributes();
@ -1964,80 +1875,65 @@ void WorksheetPrivate::loadXmlSheetData(QXmlStreamReader &reader)
qDebug()<<QStringLiteral("<c s=\"%1\">Invalid style index: ").arg(idx)<<idx; qDebug()<<QStringLiteral("<c s=\"%1\">Invalid style index: ").arg(idx)<<idx;
} }
if (attributes.hasAttribute(QLatin1String("t"))) { // "t" == cell data type Cell::CellType cellType = Cell::NumberType;
QString type = attributes.value(QLatin1String("t")).toString(); if (attributes.hasAttribute(QLatin1String("t"))) {
if (type == QLatin1String("s")) { QString typeString = attributes.value(QLatin1String("t")).toString();
//string type if (typeString == QLatin1String("s"))
cellType = Cell::SharedStringType;
else if (typeString == QLatin1String("inlineStr"))
cellType = Cell::InlineStringType;
else if (typeString == QLatin1String("str"))
cellType = Cell::StringType;
else if (typeString == QLatin1String("b"))
cellType = Cell::BooleanType;
else if (typeString == QLatin1String("e"))
cellType = Cell::ErrorType;
else
cellType = Cell::NumberType;
}
QSharedPointer<Cell> cell(new Cell(QVariant() ,cellType, format, q));
while (!reader.atEnd() && !(reader.name() == QLatin1String("c") && reader.tokenType() == QXmlStreamReader::EndElement)) { while (!reader.atEnd() && !(reader.name() == QLatin1String("c") && reader.tokenType() == QXmlStreamReader::EndElement)) {
reader.readNextStartElement(); if (reader.readNextStartElement()) {
if (reader.name() == QLatin1String("v")) { if (reader.name() == QLatin1String("f")) {
int sst_idx = reader.readElementText().toInt(); cell->d_func()->formula.loadFromXml(reader);
} else if (reader.name() == QLatin1String("v")) {
QString value = reader.readElementText();
if (cellType == Cell::SharedStringType) {
int sst_idx = value.toInt();
sharedStrings()->incRefByStringIndex(sst_idx); sharedStrings()->incRefByStringIndex(sst_idx);
RichString rs = sharedStrings()->getSharedString(sst_idx); RichString rs = sharedStrings()->getSharedString(sst_idx);
QSharedPointer<Cell> data(new Cell(rs.toPlainString() ,Cell::String, format, q)); cell->d_func()->value = rs.toPlainString();
if (rs.isRichString()) if (rs.isRichString())
data->d_ptr->richString = rs; cell->d_func()->richString = rs;
cellTable[pos.row()][pos.column()] = QSharedPointer<Cell>(data); } else if (cellType == Cell::NumberType) {
} cell->d_func()->value = value.toDouble();
} } else if (cellType == Cell::BooleanType) {
} else if (type == QLatin1String("inlineStr")) { cell->d_func()->value = value.toInt() ? true : false;
//inline string type } else { //Cell::ErrorType and Cell::StringType
while (!reader.atEnd() && !(reader.name() == QLatin1String("c") && reader.tokenType() == QXmlStreamReader::EndElement)) { cell->d_func()->value = value;
reader.readNextStartElement(); }
if (reader.tokenType() == QXmlStreamReader::StartElement) { } else if (reader.name() == QLatin1String("is")) {
while (!reader.atEnd() && !(reader.name() == QLatin1String("is") && reader.tokenType() == QXmlStreamReader::EndElement)) {
if (reader.readNextStartElement()) {
//:Todo, add rich text read support //:Todo, add rich text read support
if (reader.name() == QLatin1String("t")) { if (reader.name() == QLatin1String("t")) {
QString value = reader.readElementText(); cell->d_func()->value = reader.readElementText();
QSharedPointer<Cell> data(new Cell(value, Cell::InlineString, format, q));
cellTable[pos.row()][pos.column()] = data;
} }
} }
} }
} else if (type == QLatin1String("b")) { } else if (reader.name() == QLatin1String("extLst")) {
//bool type //skip extLst element
reader.readNextStartElement(); while (!reader.atEnd() && !(reader.name() == QLatin1String("extLst")
if (reader.name() == QLatin1String("v")) { && reader.tokenType() == QXmlStreamReader::EndElement)) {
QString value = reader.readElementText();
QSharedPointer<Cell> data(new Cell(value.toInt() ? true : false, Cell::Boolean, format, q));
cellTable[pos.row()][pos.column()] = data;
}
} else if (type == QLatin1String("str")) {
//formula type
QSharedPointer<Cell> data = loadXmlNumericCellData(reader);
data->d_ptr->format = format;
data->d_ptr->parent = q;
cellTable[pos.row()][pos.column()] = data;
} else if (type == QLatin1String("e")) {
//error type, such as #DIV/0! #NULL! #REF! etc
QString v_str, f_str;
while (!reader.atEnd() && !(reader.name() == QLatin1String("c") && reader.tokenType() == QXmlStreamReader::EndElement)) {
reader.readNextStartElement(); reader.readNextStartElement();
if (reader.tokenType() == QXmlStreamReader::StartElement) {
if (reader.name() == QLatin1String("v"))
v_str = reader.readElementText();
else if (reader.name() == QLatin1String("f"))
f_str = reader.readElementText();
}
}
QSharedPointer<Cell> data(new Cell(v_str, Cell::Error, format, q));
if (!f_str.isEmpty())
data->d_ptr->formula = f_str;
cellTable[pos.row()][pos.column()] = data;
} else if (type == QLatin1String("n")) {
QSharedPointer<Cell> data = loadXmlNumericCellData(reader);
data->d_ptr->format = format;
data->d_ptr->parent = q;
cellTable[pos.row()][pos.column()] = data;
} }
} else {
//default is "n"
QSharedPointer<Cell> data = loadXmlNumericCellData(reader);
data->d_ptr->format = format;
data->d_ptr->parent = q;
cellTable[pos.row()][pos.column()] = data;
} }
} }
} }
cellTable[pos.row()][pos.column()] = cell;
}
}
} }
} }

5
src/xlsx/xlsxworksheet.h

@ -69,9 +69,8 @@ public:
bool writeInlineString(int row, int column, const QString &value, const Format &format=Format()); bool writeInlineString(int row, int column, const QString &value, const Format &format=Format());
bool writeNumeric(const CellReference &row_column, double value, const Format &format=Format()); bool writeNumeric(const CellReference &row_column, double value, const Format &format=Format());
bool writeNumeric(int row, int column, double value, const Format &format=Format()); bool writeNumeric(int row, int column, double value, const Format &format=Format());
bool writeFormula(const CellReference &row_column, const QString &formula, const Format &format=Format(), double result=0); bool writeFormula(const CellReference &row_column, const CellFormula &formula, const Format &format=Format(), double result=0);
bool writeFormula(int row, int column, const QString &formula, const Format &format=Format(), double result=0); bool writeFormula(int row, int column, const CellFormula &formula, const Format &format=Format(), double result=0);
bool writeArrayFormula(const CellRange &range, const QString &formula, const Format &format=Format());
bool writeBlank(const CellReference &row_column, const Format &format=Format()); bool writeBlank(const CellReference &row_column, const Format &format=Format());
bool writeBlank(int row, int column, const Format &format=Format()); bool writeBlank(int row, int column, const Format &format=Format());
bool writeBool(const CellReference &row_column, bool value, const Format &format=Format()); bool writeBool(const CellReference &row_column, bool value, const Format &format=Format());

1
src/xlsx/xlsxworksheet_p.h

@ -169,7 +169,6 @@ public:
int rowPixelsSize(int row) const; int rowPixelsSize(int row) const;
int colPixelsSize(int col) const; int colPixelsSize(int col) const;
QSharedPointer<Cell> loadXmlNumericCellData(QXmlStreamReader &reader);
void loadXmlSheetData(QXmlStreamReader &reader); void loadXmlSheetData(QXmlStreamReader &reader);
void loadXmlColumnsInfo(QXmlStreamReader &reader); void loadXmlColumnsInfo(QXmlStreamReader &reader);
void loadXmlMergeCells(QXmlStreamReader &reader); void loadXmlMergeCells(QXmlStreamReader &reader);

47
tests/auto/document/tst_documenttest.cpp

@ -1,6 +1,7 @@
#include "xlsxdocument.h" #include "xlsxdocument.h"
#include "xlsxcell.h" #include "xlsxcell.h"
#include "xlsxformat.h" #include "xlsxformat.h"
#include "xlsxcellformula.h"
#include <QString> #include <QString>
#include <QtTest> #include <QtTest>
@ -69,9 +70,9 @@ void DocumentTest::testReadWriteString()
device.open(QIODevice::ReadOnly); device.open(QIODevice::ReadOnly);
Document xlsx2(&device); Document xlsx2(&device);
QCOMPARE(xlsx2.cellAt("A1")->dataType(), Cell::String); QCOMPARE(xlsx2.cellAt("A1")->cellType(), Cell::SharedStringType);
QCOMPARE(xlsx2.cellAt("A1")->value().toString(), QString("Hello Qt!")); QCOMPARE(xlsx2.cellAt("A1")->value().toString(), QString("Hello Qt!"));
QCOMPARE(xlsx2.cellAt("A2")->dataType(), Cell::String); QCOMPARE(xlsx2.cellAt("A2")->cellType(), Cell::SharedStringType);
QCOMPARE(xlsx2.cellAt("A2")->value().toString(), QString("Hello Qt again!")); QCOMPARE(xlsx2.cellAt("A2")->value().toString(), QString("Hello Qt again!"));
Format format2 = xlsx2.cellAt("A2")->format(); Format format2 = xlsx2.cellAt("A2")->format();
QVERIFY(format2.isValid()); QVERIFY(format2.isValid());
@ -79,7 +80,7 @@ void DocumentTest::testReadWriteString()
// qDebug()<<format; // qDebug()<<format;
QCOMPARE(format2, format); QCOMPARE(format2, format);
QCOMPARE(xlsx2.cellAt("A3")->dataType(), Cell::String); QCOMPARE(xlsx2.cellAt("A3")->cellType(), Cell::SharedStringType);
QCOMPARE(xlsx2.cellAt("A3")->value().toString(), QString("12345")); QCOMPARE(xlsx2.cellAt("A3")->value().toString(), QString("12345"));
} }
@ -100,9 +101,9 @@ void DocumentTest::testReadWriteNumeric()
device.open(QIODevice::ReadOnly); device.open(QIODevice::ReadOnly);
Document xlsx2(&device); Document xlsx2(&device);
QCOMPARE(xlsx2.cellAt("A1")->dataType(), Cell::Numeric); QCOMPARE(xlsx2.cellAt("A1")->cellType(), Cell::NumberType);
QCOMPARE(xlsx2.cellAt("A1")->value().toDouble(), 123.0); QCOMPARE(xlsx2.cellAt("A1")->value().toDouble(), 123.0);
QCOMPARE(xlsx2.cellAt("A2")->dataType(), Cell::Numeric); QCOMPARE(xlsx2.cellAt("A2")->cellType(), Cell::NumberType);
QCOMPARE(xlsx2.cellAt("A2")->value().toDouble(), 12345.0); QCOMPARE(xlsx2.cellAt("A2")->value().toDouble(), 12345.0);
QVERIFY(xlsx2.cellAt("A2")->format().isValid()); QVERIFY(xlsx2.cellAt("A2")->format().isValid());
QCOMPARE(xlsx2.cellAt("A2")->format(), format); QCOMPARE(xlsx2.cellAt("A2")->format(), format);
@ -124,9 +125,9 @@ void DocumentTest::testReadWriteBool()
device.open(QIODevice::ReadOnly); device.open(QIODevice::ReadOnly);
Document xlsx2(&device); Document xlsx2(&device);
QCOMPARE(xlsx2.cellAt("A1")->dataType(), Cell::Boolean); QCOMPARE(xlsx2.cellAt("A1")->cellType(), Cell::BooleanType);
QCOMPARE(xlsx2.cellAt("A1")->value().toBool(), true); QCOMPARE(xlsx2.cellAt("A1")->value().toBool(), true);
QCOMPARE(xlsx2.cellAt("A2")->dataType(), Cell::Boolean); QCOMPARE(xlsx2.cellAt("A2")->cellType(), Cell::BooleanType);
QCOMPARE(xlsx2.cellAt("A2")->value().toBool(), false); QCOMPARE(xlsx2.cellAt("A2")->value().toBool(), false);
QVERIFY(xlsx2.cellAt("A2")->format().isValid()); QVERIFY(xlsx2.cellAt("A2")->format().isValid());
QCOMPARE(xlsx2.cellAt("A2")->format(), format); QCOMPARE(xlsx2.cellAt("A2")->format(), format);
@ -149,10 +150,10 @@ void DocumentTest::testReadWriteBlank()
device.open(QIODevice::ReadOnly); device.open(QIODevice::ReadOnly);
Document xlsx2(&device); Document xlsx2(&device);
QVERIFY(xlsx2.cellAt("A1")); QVERIFY(xlsx2.cellAt("A1"));
QCOMPARE(xlsx2.cellAt("A1")->dataType(), Cell::Blank); QCOMPARE(xlsx2.cellAt("A1")->cellType(), Cell::NumberType);
QVERIFY(!xlsx2.cellAt("A1")->value().isValid()); QVERIFY(!xlsx2.cellAt("A1")->value().isValid());
QVERIFY(xlsx2.cellAt("A2")); QVERIFY(xlsx2.cellAt("A2"));
QCOMPARE(xlsx2.cellAt("A2")->dataType(), Cell::Blank); QCOMPARE(xlsx2.cellAt("A2")->cellType(), Cell::NumberType);
QVERIFY(!xlsx2.cellAt("A2")->value().isValid()); QVERIFY(!xlsx2.cellAt("A2")->value().isValid());
QVERIFY(xlsx2.cellAt("A2")->format().isValid()); QVERIFY(xlsx2.cellAt("A2")->format().isValid());
QCOMPARE(xlsx2.cellAt("A2")->format(), format); QCOMPARE(xlsx2.cellAt("A2")->format(), format);
@ -175,12 +176,11 @@ void DocumentTest::testReadWriteFormula()
device.open(QIODevice::ReadOnly); device.open(QIODevice::ReadOnly);
Document xlsx2(&device); Document xlsx2(&device);
QCOMPARE(xlsx2.cellAt("A1")->dataType(), Cell::Formula); QCOMPARE(xlsx2.cellAt("A1")->cellType(), Cell::NumberType);
// QCOMPARE(xlsx2.cellAt("A1")->value().toDouble(), 0.0); QVERIFY(xlsx2.cellAt("A1")->hasFormula());
QCOMPARE(xlsx2.cellAt("A1")->formula(), QStringLiteral("11+22")); QCOMPARE(xlsx2.cellAt("A1")->formula(), CellFormula("11+22"));
QCOMPARE(xlsx2.cellAt("A2")->dataType(), Cell::Formula); QCOMPARE(xlsx2.cellAt("A2")->cellType(), Cell::NumberType);
// QCOMPARE(xlsx2.cellAt("A2")->value().toDouble(), 0.0); QCOMPARE(xlsx2.cellAt("A2")->formula(), CellFormula("22+33"));
QCOMPARE(xlsx2.cellAt("A2")->formula(), QStringLiteral("22+33"));
QVERIFY(xlsx2.cellAt("A2")->format().isValid()); QVERIFY(xlsx2.cellAt("A2")->format().isValid());
QCOMPARE(xlsx2.cellAt("A2")->format(), format); QCOMPARE(xlsx2.cellAt("A2")->format(), format);
} }
@ -211,17 +211,17 @@ void DocumentTest::testReadWriteDateTime()
device.open(QIODevice::ReadOnly); device.open(QIODevice::ReadOnly);
Document xlsx2(&device); Document xlsx2(&device);
QCOMPARE(xlsx2.cellAt("A1")->dataType(), Cell::Numeric); QCOMPARE(xlsx2.cellAt("A1")->cellType(), Cell::NumberType);
QCOMPARE(xlsx2.cellAt("A1")->isDateTime(), true); QCOMPARE(xlsx2.cellAt("A1")->isDateTime(), true);
QCOMPARE(xlsx2.cellAt("A1")->dateTime(), dt); QCOMPARE(xlsx2.cellAt("A1")->dateTime(), dt);
QVERIFY(xlsx2.read("A1").userType() == QMetaType::QDateTime); QVERIFY(xlsx2.read("A1").userType() == QMetaType::QDateTime);
QCOMPARE(xlsx2.cellAt("A2")->dataType(), Cell::Numeric); QCOMPARE(xlsx2.cellAt("A2")->cellType(), Cell::NumberType);
QCOMPARE(xlsx2.cellAt("A2")->isDateTime(), true); QCOMPARE(xlsx2.cellAt("A2")->isDateTime(), true);
QCOMPARE(xlsx2.cellAt("A2")->dateTime(), dt); QCOMPARE(xlsx2.cellAt("A2")->dateTime(), dt);
QVERIFY(xlsx2.read("A2").userType() == QMetaType::QDateTime); QVERIFY(xlsx2.read("A2").userType() == QMetaType::QDateTime);
QCOMPARE(xlsx2.cellAt("A3")->dataType(), Cell::Numeric); QCOMPARE(xlsx2.cellAt("A3")->cellType(), Cell::NumberType);
QVERIFY(xlsx2.cellAt("A3")->format().isValid()); QVERIFY(xlsx2.cellAt("A3")->format().isValid());
QCOMPARE(xlsx2.cellAt("A3")->isDateTime(), true); QCOMPARE(xlsx2.cellAt("A3")->isDateTime(), true);
QCOMPARE(xlsx2.cellAt("A3")->dateTime(), dt); QCOMPARE(xlsx2.cellAt("A3")->dateTime(), dt);
@ -259,16 +259,16 @@ void DocumentTest::testReadWriteDate()
device.open(QIODevice::ReadOnly); device.open(QIODevice::ReadOnly);
Document xlsx2(&device); Document xlsx2(&device);
QCOMPARE(xlsx2.cellAt("A1")->dataType(), Cell::Numeric); QCOMPARE(xlsx2.cellAt("A1")->cellType(), Cell::NumberType);
QCOMPARE(xlsx2.cellAt("A1")->isDateTime(), true); QCOMPARE(xlsx2.cellAt("A1")->isDateTime(), true);
QVERIFY(xlsx2.read("A1").userType() == QMetaType::QDate); QVERIFY(xlsx2.read("A1").userType() == QMetaType::QDate);
QCOMPARE(xlsx2.read("A1").toDate(), d); QCOMPARE(xlsx2.read("A1").toDate(), d);
QCOMPARE(xlsx2.cellAt("A2")->dataType(), Cell::Numeric); QCOMPARE(xlsx2.cellAt("A2")->cellType(), Cell::NumberType);
QCOMPARE(xlsx2.cellAt("A2")->isDateTime(), true); QCOMPARE(xlsx2.cellAt("A2")->isDateTime(), true);
QVERIFY(xlsx2.read("A2").userType() == QMetaType::QDate); QVERIFY(xlsx2.read("A2").userType() == QMetaType::QDate);
QCOMPARE(xlsx2.cellAt("A3")->dataType(), Cell::Numeric); QCOMPARE(xlsx2.cellAt("A3")->cellType(), Cell::NumberType);
QVERIFY(xlsx2.cellAt("A3")->format().isValid()); QVERIFY(xlsx2.cellAt("A3")->format().isValid());
QCOMPARE(xlsx2.cellAt("A3")->isDateTime(), true); QCOMPARE(xlsx2.cellAt("A3")->isDateTime(), true);
QCOMPARE(xlsx2.cellAt("A3")->format().numberFormat(), QString("dd/mm/yyyy")); QCOMPARE(xlsx2.cellAt("A3")->format().numberFormat(), QString("dd/mm/yyyy"));
@ -297,9 +297,10 @@ void DocumentTest::testReadWriteTime()
device.open(QIODevice::ReadOnly); device.open(QIODevice::ReadOnly);
Document xlsx2(&device); Document xlsx2(&device);
QCOMPARE(xlsx2.cellAt("A1")->dataType(), Cell::Blank); QCOMPARE(xlsx2.cellAt("A1")->cellType(), Cell::NumberType);
QVERIFY(!xlsx2.cellAt("A1")->value().isValid());
QCOMPARE(xlsx2.cellAt("A2")->dataType(), Cell::Numeric); QCOMPARE(xlsx2.cellAt("A2")->cellType(), Cell::NumberType);
QCOMPARE(xlsx2.cellAt("A2")->isDateTime(), true); QCOMPARE(xlsx2.cellAt("A2")->isDateTime(), true);
QVERIFY(xlsx2.read("A2").userType() == QMetaType::QTime); QVERIFY(xlsx2.read("A2").userType() == QMetaType::QTime);
QCOMPARE(xlsx2.read("A2").toTime(), QTime(1, 22)); QCOMPARE(xlsx2.read("A2").toTime(), QTime(1, 22));

21
tests/auto/worksheet/tst_worksheet.cpp

@ -9,6 +9,7 @@
#include "private/xlsxworksheet_p.h" #include "private/xlsxworksheet_p.h"
#include "private/xlsxsharedstrings_p.h" #include "private/xlsxsharedstrings_p.h"
#include "xlsxrichstring.h" #include "xlsxrichstring.h"
#include "xlsxcellformula.h"
class WorksheetTest : public QObject class WorksheetTest : public QObject
{ {
@ -114,8 +115,8 @@ void WorksheetTest::testWriteCells()
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\" t=\"str\"><f>44+33</f><v>0</v></c>"), "formula"); QVERIFY2(xmldata.contains("<c r=\"A5\"><f>44+33</f><v>0</v></c>"), "formula");
QVERIFY2(xmldata.contains("<c r=\"B5\" t=\"str\"><f>44+33</f><v>77</v></c>"), "formula"); QVERIFY2(xmldata.contains("<c r=\"B5\"><f>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"));
} }
@ -204,29 +205,29 @@ void WorksheetTest::testReadSheetData()
QCOMPARE(sheet.d_func()->cellTable.size(), 2); QCOMPARE(sheet.d_func()->cellTable.size(), 2);
//A1 //A1
QCOMPARE(sheet.cellAt("A1")->dataType(), QXlsx::Cell::String); QCOMPARE(sheet.cellAt("A1")->cellType(), QXlsx::Cell::SharedStringType);
QCOMPARE(sheet.cellAt("A1")->value().toString(), QStringLiteral("Hello")); QCOMPARE(sheet.cellAt("A1")->value().toString(), QStringLiteral("Hello"));
//B1 //B1
QCOMPARE(sheet.cellAt("B1")->dataType(), QXlsx::Cell::Formula); QCOMPARE(sheet.cellAt("B1")->cellType(), QXlsx::Cell::NumberType);
QCOMPARE(sheet.cellAt("B1")->value().toInt(), 77); QCOMPARE(sheet.cellAt("B1")->value().toInt(), 77);
QCOMPARE(sheet.cellAt("B1")->formula(), QStringLiteral("44+33")); QCOMPARE(sheet.cellAt("B1")->formula(), QXlsx::CellFormula("44+33"));
//C1 //C1
QCOMPARE(sheet.cellAt("C1")->dataType(), QXlsx::Cell::Formula); QCOMPARE(sheet.cellAt("C1")->cellType(), QXlsx::Cell::StringType);
QCOMPARE(sheet.cellAt("C1")->value().toInt(), 77); QCOMPARE(sheet.cellAt("C1")->value().toInt(), 77);
QCOMPARE(sheet.cellAt("C1")->formula(), QStringLiteral("44+33")); QCOMPARE(sheet.cellAt("C1")->formula(), QXlsx::CellFormula("44+33"));
//B3 //B3
QCOMPARE(sheet.cellAt("B3")->dataType(), QXlsx::Cell::Numeric); QCOMPARE(sheet.cellAt("B3")->cellType(), QXlsx::Cell::NumberType);
QCOMPARE(sheet.cellAt("B3")->value().toInt(), 12345); QCOMPARE(sheet.cellAt("B3")->value().toInt(), 12345);
//C3 //C3
QCOMPARE(sheet.cellAt("C3")->dataType(), QXlsx::Cell::InlineString); QCOMPARE(sheet.cellAt("C3")->cellType(), QXlsx::Cell::InlineStringType);
QCOMPARE(sheet.cellAt("C3")->value().toString(), QStringLiteral("inline test string")); QCOMPARE(sheet.cellAt("C3")->value().toString(), QStringLiteral("inline test string"));
//E3 //E3
QCOMPARE(sheet.cellAt("E3")->dataType(), QXlsx::Cell::Error); QCOMPARE(sheet.cellAt("E3")->cellType(), QXlsx::Cell::ErrorType);
QCOMPARE(sheet.cellAt("E3")->value().toString(), QStringLiteral("#DIV/0!")); QCOMPARE(sheet.cellAt("E3")->value().toString(), QStringLiteral("#DIV/0!"));
} }

Loading…
Cancel
Save