commit
060e7ea0b2
91 changed files with 20939 additions and 0 deletions
@ -0,0 +1 @@ |
|||||
|
*.pro.user |
@ -0,0 +1,44 @@ |
|||||
|
QT += gui |
||||
|
QT += xml |
||||
|
QT += xmlpatterns |
||||
|
|
||||
|
|
||||
|
TARGET = QXlsx |
||||
|
|
||||
|
QT += core |
||||
|
QT += gui-private |
||||
|
|
||||
|
CONFIG += c++11 console |
||||
|
CONFIG -= app_bundle |
||||
|
|
||||
|
# The following define makes your compiler emit warnings if you use |
||||
|
# any Qt feature that has been marked deprecated (the exact warnings |
||||
|
# depend on your compiler). Please consult the documentation of the |
||||
|
# deprecated API in order to know how to port your code away from it. |
||||
|
DEFINES += QT_DEPRECATED_WARNINGS |
||||
|
|
||||
|
# You can also make your code fail to compile if it uses deprecated APIs. |
||||
|
# In order to do so, uncomment the following line. |
||||
|
# You can also select to disable deprecated APIs only up to a certain version of Qt. |
||||
|
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
SOURCES += $$files(src/*.cpp, true) |
||||
|
SOURCES += main.cpp |
||||
|
HEADERS += $$files(include/QXlsx/*.h, true) |
||||
|
HEADERS += $$files(include/*.h, true) |
||||
|
|
||||
|
INCLUDEPATH += "$$PWD/include/" \ |
||||
|
INCLUDEPATH += "$$PWD/include/QXlsx" \ |
||||
|
$$PWD/.. |
||||
|
|
||||
|
# Default rules for deployment. |
||||
|
qnx: target.path = /tmp/$${TARGET}/bin |
||||
|
else: unix:!android: target.path = /opt/$${TARGET}/bin |
||||
|
!isEmpty(target.path): INSTALLS += target |
||||
|
|
||||
|
|
@ -0,0 +1,48 @@ |
|||||
|
//xlsxabstractooxmlfile.h
|
||||
|
|
||||
|
#ifndef QXLSX_XLSXABSTRACTOOXMLFILE_H |
||||
|
#define QXLSX_XLSXABSTRACTOOXMLFILE_H |
||||
|
|
||||
|
#include "xlsxglobal.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class Relationships; |
||||
|
|
||||
|
class AbstractOOXmlFilePrivate; |
||||
|
|
||||
|
class QXLSX_EXPORT AbstractOOXmlFile |
||||
|
{ |
||||
|
Q_DECLARE_PRIVATE(AbstractOOXmlFile) |
||||
|
|
||||
|
public: |
||||
|
enum CreateFlag |
||||
|
{ |
||||
|
F_NewFromScratch, |
||||
|
F_LoadFromExists |
||||
|
}; |
||||
|
|
||||
|
public: |
||||
|
virtual ~AbstractOOXmlFile(); |
||||
|
|
||||
|
virtual void saveToXmlFile(QIODevice* device) const = 0; |
||||
|
virtual bool loadFromXmlFile(QIODevice* device) = 0; |
||||
|
|
||||
|
virtual QByteArray saveToXmlData() const; |
||||
|
virtual bool loadFromXmlData(const QByteArray& data); |
||||
|
|
||||
|
Relationships* relationships() const; |
||||
|
|
||||
|
void setFilePath(const QString path); |
||||
|
QString filePath() const; |
||||
|
|
||||
|
protected: |
||||
|
AbstractOOXmlFile(CreateFlag flag); |
||||
|
AbstractOOXmlFile(AbstractOOXmlFilePrivate* d); |
||||
|
|
||||
|
AbstractOOXmlFilePrivate* d_ptr; |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
|
||||
|
#endif //QXLSX_XLSXABSTRACTOOXMLFILE_H
|
@ -0,0 +1,31 @@ |
|||||
|
// xlsxabstractooxmlfile_p.h
|
||||
|
|
||||
|
#ifndef XLSXOOXMLFILE_P_H |
||||
|
#define XLSXOOXMLFILE_P_H |
||||
|
|
||||
|
#include "xlsxglobal.h" |
||||
|
|
||||
|
#include "xlsxabstractooxmlfile.h" |
||||
|
#include "xlsxrelationships_p.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class AbstractOOXmlFilePrivate |
||||
|
{ |
||||
|
Q_DECLARE_PUBLIC(AbstractOOXmlFile) |
||||
|
|
||||
|
public: |
||||
|
AbstractOOXmlFilePrivate(AbstractOOXmlFile* q, AbstractOOXmlFile::CreateFlag flag); |
||||
|
virtual ~AbstractOOXmlFilePrivate(); |
||||
|
|
||||
|
public: |
||||
|
QString filePathInPackage; //such as "xl/worksheets/sheet1.xml"
|
||||
|
|
||||
|
Relationships *relationships; |
||||
|
AbstractOOXmlFile::CreateFlag flag; |
||||
|
AbstractOOXmlFile *q_ptr; |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
|
||||
|
#endif // XLSXOOXMLFILE_P_H
|
@ -0,0 +1,49 @@ |
|||||
|
// xlsxabstractsheet.h
|
||||
|
|
||||
|
#ifndef XLSXABSTRACTSHEET_H |
||||
|
#define XLSXABSTRACTSHEET_H |
||||
|
|
||||
|
#include "xlsxglobal.h" |
||||
|
#include "xlsxabstractooxmlfile.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class Workbook; |
||||
|
class Drawing; |
||||
|
class AbstractSheetPrivate; |
||||
|
|
||||
|
class QXLSX_EXPORT AbstractSheet : public AbstractOOXmlFile |
||||
|
{ |
||||
|
Q_DECLARE_PRIVATE(AbstractSheet) |
||||
|
|
||||
|
public: |
||||
|
Workbook *workbook() const; |
||||
|
|
||||
|
public: |
||||
|
// NOTE: If all Qt compiler supports C++1x, recommend to use a 'class enum'.
|
||||
|
enum SheetType { ST_WorkSheet, ST_ChartSheet, ST_DialogSheet, ST_MacroSheet }; |
||||
|
enum SheetState { SS_Visible,SS_Hidden, SS_VeryHidden }; |
||||
|
|
||||
|
public: |
||||
|
QString sheetName() const; |
||||
|
SheetType sheetType() const; |
||||
|
SheetState sheetState() const; |
||||
|
void setSheetState(SheetState ss); |
||||
|
bool isHidden() const; |
||||
|
bool isVisible() const; |
||||
|
void setHidden(bool hidden); |
||||
|
void setVisible(bool visible); |
||||
|
|
||||
|
protected: |
||||
|
friend class Workbook; |
||||
|
AbstractSheet(const QString &sheetName, int sheetId, Workbook *book, AbstractSheetPrivate *d); |
||||
|
virtual AbstractSheet *copy(const QString &distName, int distId) const = 0; |
||||
|
void setSheetName(const QString &sheetName); |
||||
|
void setSheetType(SheetType type); |
||||
|
int sheetId() const; |
||||
|
|
||||
|
Drawing *drawing() const; |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
#endif // XLSXABSTRACTSHEET_H
|
@ -0,0 +1,36 @@ |
|||||
|
// xlsxabstractsheet_p/h
|
||||
|
|
||||
|
#ifndef XLSXABSTRACTSHEET_P_H |
||||
|
#define XLSXABSTRACTSHEET_P_H |
||||
|
|
||||
|
#include <QString> |
||||
|
|
||||
|
#include <memory> |
||||
|
|
||||
|
#include "xlsxglobal.h" |
||||
|
|
||||
|
#include "xlsxabstractsheet.h" |
||||
|
#include "xlsxabstractooxmlfile_p.h" |
||||
|
#include "xlsxdrawing_p.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class AbstractSheetPrivate : public AbstractOOXmlFilePrivate |
||||
|
{ |
||||
|
Q_DECLARE_PUBLIC(AbstractSheet) |
||||
|
public: |
||||
|
AbstractSheetPrivate(AbstractSheet *p, AbstractSheet::CreateFlag flag); |
||||
|
~AbstractSheetPrivate(); |
||||
|
|
||||
|
Workbook *workbook; |
||||
|
std::shared_ptr<Drawing> drawing; |
||||
|
|
||||
|
QString name; |
||||
|
int id; |
||||
|
AbstractSheet::SheetState sheetState; |
||||
|
AbstractSheet::SheetType type; |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
|
||||
|
#endif // XLSXABSTRACTSHEET_P_H
|
@ -0,0 +1,82 @@ |
|||||
|
// xlsxcell.h
|
||||
|
|
||||
|
#ifndef QXLSX_XLSXCELL_H |
||||
|
#define QXLSX_XLSXCELL_H |
||||
|
|
||||
|
#include <cstdio> |
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QObject> |
||||
|
#include <QString> |
||||
|
#include <QVariant> |
||||
|
#include <QDate> |
||||
|
#include <QDateTime> |
||||
|
#include <QTime> |
||||
|
|
||||
|
#include "xlsxglobal.h" |
||||
|
#include "xlsxformat.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class Worksheet; |
||||
|
class Format; |
||||
|
class CellFormula; |
||||
|
class CellPrivate; |
||||
|
class WorksheetPrivate; |
||||
|
|
||||
|
class QXLSX_EXPORT Cell |
||||
|
{ |
||||
|
Q_DECLARE_PRIVATE(Cell) |
||||
|
|
||||
|
private: |
||||
|
friend class Worksheet; |
||||
|
friend class WorksheetPrivate; |
||||
|
|
||||
|
public: |
||||
|
enum CellType // See ECMA 376, 18.18.11. ST_CellType (Cell Type) for more information.
|
||||
|
{ |
||||
|
BooleanType, |
||||
|
DateType, |
||||
|
ErrorType, |
||||
|
InlineStringType, |
||||
|
NumberType, |
||||
|
SharedStringType, |
||||
|
StringType, |
||||
|
CustomType, // custom or un-defined cell type
|
||||
|
}; |
||||
|
|
||||
|
public: |
||||
|
Cell(const QVariant &data = QVariant(), |
||||
|
CellType type = NumberType, |
||||
|
const Format &format = Format(), |
||||
|
Worksheet *parent = nullptr, |
||||
|
qint32 styleIndex = (-1) ); |
||||
|
Cell(const Cell * const cell); |
||||
|
~Cell(); |
||||
|
|
||||
|
public: |
||||
|
CellPrivate * const d_ptr; // See D-pointer and Q-pointer of Qt, for more information.
|
||||
|
|
||||
|
public: |
||||
|
CellType cellType() const; |
||||
|
QVariant value() const; |
||||
|
QVariant readValue() const; |
||||
|
Format format() const; |
||||
|
|
||||
|
bool hasFormula() const; |
||||
|
CellFormula formula() const; |
||||
|
|
||||
|
bool isDateTime() const; |
||||
|
QVariant dateTime() const; // QDateTime, QDate, QTime
|
||||
|
|
||||
|
bool isRichString() const; |
||||
|
|
||||
|
qint32 styleNumber() const; |
||||
|
|
||||
|
static bool isDateType(CellType cellType, const Format &format); |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
|
||||
|
#endif // QXLSX_XLSXCELL_H
|
@ -0,0 +1,41 @@ |
|||||
|
// xlsxcell_p.h
|
||||
|
|
||||
|
#ifndef XLSXCELL_P_H |
||||
|
#define XLSXCELL_P_H |
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QObject> |
||||
|
#include <QList> |
||||
|
|
||||
|
#include "xlsxglobal.h" |
||||
|
#include "xlsxcell.h" |
||||
|
#include "xlsxcellrange.h" |
||||
|
#include "xlsxrichstring.h" |
||||
|
#include "xlsxcellformula.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class CellPrivate |
||||
|
{ |
||||
|
Q_DECLARE_PUBLIC(Cell) |
||||
|
public: |
||||
|
CellPrivate(Cell *p); |
||||
|
CellPrivate(const CellPrivate * const cp); |
||||
|
public: |
||||
|
Worksheet *parent; |
||||
|
Cell *q_ptr; |
||||
|
public: |
||||
|
Cell::CellType cellType; |
||||
|
QVariant value; |
||||
|
|
||||
|
CellFormula formula; |
||||
|
Format format; |
||||
|
|
||||
|
RichString richString; |
||||
|
|
||||
|
qint32 styleNumber; |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
|
||||
|
#endif // XLSXCELL_P_H
|
@ -0,0 +1,55 @@ |
|||||
|
// xlsxcellformula.h
|
||||
|
|
||||
|
#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 Worksheet; |
||||
|
class WorksheetPrivate; |
||||
|
|
||||
|
class QXLSX_EXPORT CellFormula |
||||
|
{ |
||||
|
public: |
||||
|
enum FormulaType { NormalType, ArrayType, DataTableType, SharedType }; |
||||
|
|
||||
|
public: |
||||
|
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(); |
||||
|
|
||||
|
public: |
||||
|
CellFormula &operator =(const CellFormula &other); |
||||
|
bool isValid() const; |
||||
|
|
||||
|
FormulaType formulaType() const; |
||||
|
QString formulaText() 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: |
||||
|
friend class Worksheet; |
||||
|
friend class WorksheetPrivate; |
||||
|
QExplicitlySharedDataPointer<CellFormulaPrivate> d; |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
|
||||
|
#endif // QXLSX_XLSXCELLFORMULA_H
|
@ -0,0 +1,31 @@ |
|||||
|
// xlsxcellformula_p.h
|
||||
|
|
||||
|
#ifndef XLSXCELLFORMULA_P_H |
||||
|
#define XLSXCELLFORMULA_P_H |
||||
|
|
||||
|
#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; |
||||
|
bool ca; //Calculate Cell
|
||||
|
int si; //Shared group index
|
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
|
||||
|
#endif // XLSXCELLFORMULA_P_H
|
@ -0,0 +1,33 @@ |
|||||
|
// xlsxcelllocation.h
|
||||
|
|
||||
|
#ifndef CELL_LOCATION_H |
||||
|
#define CELL_LOCATION_H |
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QObject> |
||||
|
#include <QString> |
||||
|
#include <QVector> |
||||
|
#include <QList> |
||||
|
#include <QMetaType> |
||||
|
|
||||
|
#include <memory> |
||||
|
|
||||
|
#include "xlsxglobal.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class Cell; |
||||
|
|
||||
|
class QXLSX_EXPORT CellLocation |
||||
|
{ |
||||
|
public: |
||||
|
CellLocation(); |
||||
|
|
||||
|
int col; |
||||
|
int row; |
||||
|
|
||||
|
std::shared_ptr<Cell> cell; |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
#endif |
@ -0,0 +1,73 @@ |
|||||
|
// xlsxcellrange.h
|
||||
|
|
||||
|
#ifndef QXLSX_XLSXCELLRANGE_H |
||||
|
#define QXLSX_XLSXCELLRANGE_H |
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QObject> |
||||
|
|
||||
|
#include "xlsxglobal.h" |
||||
|
#include "xlsxcellreference.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
// dev57
|
||||
|
class QXLSX_EXPORT CellRange |
||||
|
{ |
||||
|
public: |
||||
|
CellRange(); |
||||
|
CellRange(int firstRow, int firstColumn, int lastRow, int lastColumn); |
||||
|
CellRange(const CellReference &topLeft, const CellReference &bottomRight); |
||||
|
CellRange(const QString &range); |
||||
|
CellRange(const char *range); |
||||
|
CellRange(const CellRange &other); |
||||
|
~CellRange(); |
||||
|
|
||||
|
QString toString(bool row_abs=false, bool col_abs=false) const; |
||||
|
bool isValid() const; |
||||
|
inline void setFirstRow(int row) { top = row; } |
||||
|
inline void setLastRow(int row) { bottom = row; } |
||||
|
inline void setFirstColumn(int col) { left = col; } |
||||
|
inline void setLastColumn(int col) { right = col; } |
||||
|
inline int firstRow() const { return top; } |
||||
|
inline int lastRow() const { return bottom; } |
||||
|
inline int firstColumn() const { return left; } |
||||
|
inline int lastColumn() const { return right; } |
||||
|
inline int rowCount() const { return bottom - top + 1; } |
||||
|
inline int columnCount() const { return right - left + 1; } |
||||
|
inline CellReference topLeft() const { return CellReference(top, left); } |
||||
|
inline CellReference topRight() const { return CellReference(top, right); } |
||||
|
inline CellReference bottomLeft() const { return CellReference(bottom, left); } |
||||
|
inline CellReference bottomRight() const { return CellReference(bottom, right); } |
||||
|
|
||||
|
inline void operator =(const CellRange &other) |
||||
|
{ |
||||
|
top = other.top; |
||||
|
bottom = other.bottom; |
||||
|
left = other.left; |
||||
|
right = other.right; |
||||
|
} |
||||
|
inline bool operator ==(const CellRange &other) const |
||||
|
{ |
||||
|
return top==other.top && bottom==other.bottom |
||||
|
&& left == other.left && right == other.right; |
||||
|
} |
||||
|
inline bool operator !=(const CellRange &other) const |
||||
|
{ |
||||
|
return top!=other.top || bottom!=other.bottom |
||||
|
|| left != other.left || right != other.right; |
||||
|
} |
||||
|
private: |
||||
|
void init(const QString &range); |
||||
|
|
||||
|
int top; |
||||
|
int left; |
||||
|
int bottom; |
||||
|
int right; |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
|
||||
|
Q_DECLARE_TYPEINFO(QXlsx::CellRange, Q_MOVABLE_TYPE); |
||||
|
|
||||
|
#endif // QXLSX_XLSXCELLRANGE_H
|
@ -0,0 +1,47 @@ |
|||||
|
// xlsxcellreference.h
|
||||
|
|
||||
|
#ifndef QXLSX_XLSXCELLREFERENCE_H |
||||
|
#define QXLSX_XLSXCELLREFERENCE_H |
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
|
||||
|
#include "xlsxglobal.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class QXLSX_EXPORT CellReference |
||||
|
{ |
||||
|
public: |
||||
|
CellReference(); |
||||
|
CellReference(int row, int column); |
||||
|
CellReference(const QString &cell); |
||||
|
CellReference(const char *cell); |
||||
|
CellReference(const CellReference &other); |
||||
|
~CellReference(); |
||||
|
|
||||
|
QString toString(bool row_abs=false, bool col_abs=false) const; |
||||
|
static CellReference fromString(const QString &cell); |
||||
|
bool isValid() const; |
||||
|
inline void setRow(int row) { _row = row; } |
||||
|
inline void setColumn(int col) { _column = col; } |
||||
|
inline int row() const { return _row; } |
||||
|
inline int column() const { return _column; } |
||||
|
|
||||
|
inline bool operator ==(const CellReference &other) const |
||||
|
{ |
||||
|
return _row==other._row && _column==other._column; |
||||
|
} |
||||
|
inline bool operator !=(const CellReference &other) const |
||||
|
{ |
||||
|
return _row!=other._row || _column!=other._column; |
||||
|
} |
||||
|
private: |
||||
|
void init(const QString &cell); |
||||
|
int _row, _column; |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
|
||||
|
Q_DECLARE_TYPEINFO(QXlsx::CellReference, Q_MOVABLE_TYPE); |
||||
|
|
||||
|
#endif // QXLSX_XLSXCELLREFERENCE_H
|
@ -0,0 +1,58 @@ |
|||||
|
// xlsxchart.h
|
||||
|
|
||||
|
#ifndef QXLSX_CHART_H |
||||
|
#define QXLSX_CHART_H |
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QXmlStreamReader> |
||||
|
#include <QXmlStreamWriter> |
||||
|
|
||||
|
#include "xlsxabstractooxmlfile.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class AbstractSheet; |
||||
|
class Worksheet; |
||||
|
class ChartPrivate; |
||||
|
class CellRange; |
||||
|
class DrawingAnchor; |
||||
|
|
||||
|
class QXLSX_EXPORT Chart : public AbstractOOXmlFile |
||||
|
{ |
||||
|
Q_DECLARE_PRIVATE(Chart) |
||||
|
public: |
||||
|
enum ChartType { // 16 type of chart (ECMA 376)
|
||||
|
CT_NoStatementChart = 0, // Zero is internally used for unknown types
|
||||
|
CT_AreaChart, CT_Area3DChart, CT_LineChart, |
||||
|
CT_Line3DChart, CT_StockChart, CT_RadarChart, |
||||
|
CT_ScatterChart, CT_PieChart, CT_Pie3DChart, |
||||
|
CT_DoughnutChart, CT_BarChart, CT_Bar3DChart, |
||||
|
CT_OfPieChart, CT_SurfaceChart, CT_Surface3DChart, |
||||
|
CT_BubbleChart, |
||||
|
}; |
||||
|
enum ChartAxisPos { None = (-1), Left = 0, Right, Top, Bottom }; |
||||
|
private: |
||||
|
friend class AbstractSheet; |
||||
|
friend class Worksheet; |
||||
|
friend class Chartsheet; |
||||
|
friend class DrawingAnchor; |
||||
|
private: |
||||
|
Chart(AbstractSheet *parent, CreateFlag flag); |
||||
|
public: |
||||
|
~Chart(); |
||||
|
public: |
||||
|
void addSeries(const CellRange &range, AbstractSheet *sheet = NULL, bool headerH = false, bool headerV = false, bool swapHeaders = false); |
||||
|
void setChartType(ChartType type); |
||||
|
void setChartStyle(int id); |
||||
|
void setAxisTitle(Chart::ChartAxisPos pos, QString axisTitle); |
||||
|
void setChartTitle(QString strchartTitle); |
||||
|
void setChartLegend(Chart::ChartAxisPos legendPos, bool overlap = false); |
||||
|
void setGridlinesEnable(bool majorGridlinesEnable = false, bool minorGridlinesEnable = false); |
||||
|
public: |
||||
|
bool loadFromXmlFile(QIODevice *device) override; |
||||
|
void saveToXmlFile(QIODevice *device) const override; |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
|
||||
|
#endif // QXLSX_CHART_H
|
@ -0,0 +1,148 @@ |
|||||
|
// xlsxchart_p.h
|
||||
|
|
||||
|
#ifndef QXLSX_CHART_P_H |
||||
|
#define QXLSX_CHART_P_H |
||||
|
|
||||
|
#include <QObject> |
||||
|
#include <QString> |
||||
|
#include <QVector> |
||||
|
#include <QMap> |
||||
|
#include <QList> |
||||
|
#include <QXmlStreamReader> |
||||
|
#include <QXmlStreamWriter> |
||||
|
|
||||
|
#include <memory> |
||||
|
|
||||
|
#include "xlsxabstractooxmlfile_p.h" |
||||
|
#include "xlsxchart.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class XlsxSeries |
||||
|
{ |
||||
|
public: |
||||
|
//At present, we care about number cell ranges only!
|
||||
|
QString numberDataSource_numRef; // yval, val
|
||||
|
QString axDataSource_numRef; // xval, cat
|
||||
|
QString headerH_numRef; |
||||
|
QString headerV_numRef; |
||||
|
bool swapHeader = false; |
||||
|
}; |
||||
|
|
||||
|
class XlsxAxis |
||||
|
{ |
||||
|
public: |
||||
|
enum Type { T_None = (-1), T_Cat, T_Val, T_Date, T_Ser }; |
||||
|
enum AxisPos { None = (-1), Left, Right, Top, Bottom }; |
||||
|
public: |
||||
|
XlsxAxis(){} |
||||
|
|
||||
|
XlsxAxis( Type t, |
||||
|
XlsxAxis::AxisPos p, |
||||
|
int id, |
||||
|
int crossId, |
||||
|
QString axisTitle = QString()) |
||||
|
{ |
||||
|
type = t; |
||||
|
axisPos = p; |
||||
|
axisId = id; |
||||
|
crossAx = crossId; |
||||
|
|
||||
|
if ( !axisTitle.isEmpty() ) |
||||
|
{ |
||||
|
axisNames[ p ] = axisTitle; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public: |
||||
|
Type type; |
||||
|
XlsxAxis::AxisPos axisPos; |
||||
|
int axisId; |
||||
|
int crossAx; |
||||
|
QMap< XlsxAxis::AxisPos, QString > axisNames; |
||||
|
}; |
||||
|
|
||||
|
class ChartPrivate : public AbstractOOXmlFilePrivate |
||||
|
{ |
||||
|
Q_DECLARE_PUBLIC(Chart) |
||||
|
|
||||
|
public: |
||||
|
ChartPrivate(Chart *q, Chart::CreateFlag flag); |
||||
|
~ChartPrivate(); |
||||
|
|
||||
|
public: |
||||
|
bool loadXmlChart(QXmlStreamReader &reader); |
||||
|
bool loadXmlPlotArea(QXmlStreamReader &reader); |
||||
|
protected: |
||||
|
bool loadXmlPlotAreaElement(QXmlStreamReader &reader); |
||||
|
public: |
||||
|
bool loadXmlXxxChart(QXmlStreamReader &reader); |
||||
|
bool loadXmlSer(QXmlStreamReader &reader); |
||||
|
QString loadXmlNumRef(QXmlStreamReader &reader); |
||||
|
QString loadXmlStrRef(QXmlStreamReader &reader); |
||||
|
bool loadXmlChartTitle(QXmlStreamReader &reader); |
||||
|
bool loadXmlChartLegend(QXmlStreamReader &reader); |
||||
|
protected: |
||||
|
bool loadXmlChartTitleTx(QXmlStreamReader &reader); |
||||
|
bool loadXmlChartTitleTxRich(QXmlStreamReader &reader); |
||||
|
bool loadXmlChartTitleTxRichP(QXmlStreamReader &reader); |
||||
|
bool loadXmlChartTitleTxRichP_R(QXmlStreamReader &reader); |
||||
|
protected: |
||||
|
bool loadXmlAxisCatAx(QXmlStreamReader &reader); |
||||
|
bool loadXmlAxisDateAx(QXmlStreamReader &reader); |
||||
|
bool loadXmlAxisSerAx(QXmlStreamReader &reader); |
||||
|
bool loadXmlAxisValAx(QXmlStreamReader &reader); |
||||
|
bool loadXmlAxisEG_AxShared(QXmlStreamReader &reader, XlsxAxis* axis); |
||||
|
bool loadXmlAxisEG_AxShared_Scaling(QXmlStreamReader &reader, XlsxAxis* axis); |
||||
|
bool loadXmlAxisEG_AxShared_Title(QXmlStreamReader &reader, XlsxAxis* axis); |
||||
|
bool loadXmlAxisEG_AxShared_Title_Overlay(QXmlStreamReader &reader, XlsxAxis* axis); |
||||
|
bool loadXmlAxisEG_AxShared_Title_Tx(QXmlStreamReader &reader, XlsxAxis* axis); |
||||
|
bool loadXmlAxisEG_AxShared_Title_Tx_Rich(QXmlStreamReader &reader, XlsxAxis* axis); |
||||
|
bool loadXmlAxisEG_AxShared_Title_Tx_Rich_P(QXmlStreamReader &reader, XlsxAxis* axis); |
||||
|
bool loadXmlAxisEG_AxShared_Title_Tx_Rich_P_pPr(QXmlStreamReader &reader, XlsxAxis* axis); |
||||
|
bool loadXmlAxisEG_AxShared_Title_Tx_Rich_P_R(QXmlStreamReader &reader, XlsxAxis* axis); |
||||
|
|
||||
|
QString readSubTree(QXmlStreamReader &reader); |
||||
|
|
||||
|
public: |
||||
|
void saveXmlChart(QXmlStreamWriter &writer) const; |
||||
|
void saveXmlChartTitle(QXmlStreamWriter &writer) const; |
||||
|
void saveXmlPieChart(QXmlStreamWriter &writer) const; |
||||
|
void saveXmlBarChart(QXmlStreamWriter &writer) const; |
||||
|
void saveXmlLineChart(QXmlStreamWriter &writer) const; |
||||
|
void saveXmlScatterChart(QXmlStreamWriter &writer) const; |
||||
|
void saveXmlAreaChart(QXmlStreamWriter &writer) const; |
||||
|
void saveXmlDoughnutChart(QXmlStreamWriter &writer) const; |
||||
|
void saveXmlSer(QXmlStreamWriter &writer, XlsxSeries *ser, int id) const; |
||||
|
void saveXmlAxis(QXmlStreamWriter &writer) const; |
||||
|
void saveXmlChartLegend(QXmlStreamWriter &writer) const; |
||||
|
|
||||
|
protected: |
||||
|
void saveXmlAxisCatAx(QXmlStreamWriter &writer, XlsxAxis* axis) const; |
||||
|
void saveXmlAxisDateAx(QXmlStreamWriter &writer, XlsxAxis* axis) const; |
||||
|
void saveXmlAxisSerAx(QXmlStreamWriter &writer, XlsxAxis* axis) const; |
||||
|
void saveXmlAxisValAx(QXmlStreamWriter &writer, XlsxAxis* axis) const; |
||||
|
|
||||
|
void saveXmlAxisEG_AxShared(QXmlStreamWriter &writer, XlsxAxis* axis) const; |
||||
|
void saveXmlAxisEG_AxShared_Title(QXmlStreamWriter &writer, XlsxAxis* axis) const; |
||||
|
QString GetAxisPosString( XlsxAxis::AxisPos axisPos ) const; |
||||
|
QString GetAxisName(XlsxAxis* ptrXlsxAxis) const; |
||||
|
|
||||
|
public: |
||||
|
Chart::ChartType chartType; |
||||
|
QList< std::shared_ptr<XlsxSeries> > seriesList; |
||||
|
QList< std::shared_ptr<XlsxAxis> > axisList; |
||||
|
QMap< XlsxAxis::AxisPos, QString > axisNames; |
||||
|
QString chartTitle; |
||||
|
AbstractSheet* sheet; |
||||
|
Chart::ChartAxisPos legendPos; |
||||
|
bool legendOverlay; |
||||
|
bool majorGridlinesEnabled; |
||||
|
bool minorGridlinesEnabled; |
||||
|
|
||||
|
QString layout; // only for storing a readed file
|
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
|
||||
|
#endif // QXLSX_CHART_P_H
|
@ -0,0 +1,38 @@ |
|||||
|
// xlsxchartsheet.h
|
||||
|
|
||||
|
#ifndef XLSXCHARTSHEET_H |
||||
|
#define XLSXCHARTSHEET_H |
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QStringList> |
||||
|
|
||||
|
#include "xlsxabstractsheet.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class Workbook; |
||||
|
class DocumentPrivate; |
||||
|
class ChartsheetPrivate; |
||||
|
class Chart; |
||||
|
|
||||
|
class QXLSX_EXPORT Chartsheet : public AbstractSheet |
||||
|
{ |
||||
|
Q_DECLARE_PRIVATE(Chartsheet) |
||||
|
|
||||
|
public: |
||||
|
~Chartsheet(); |
||||
|
Chart *chart(); |
||||
|
|
||||
|
private: |
||||
|
friend class DocumentPrivate; |
||||
|
friend class Workbook; |
||||
|
|
||||
|
Chartsheet(const QString &sheetName, int sheetId, Workbook *book, CreateFlag flag); |
||||
|
Chartsheet *copy(const QString &distName, int distId) const override; |
||||
|
|
||||
|
void saveToXmlFile(QIODevice *device) const override; |
||||
|
bool loadFromXmlFile(QIODevice *device) override; |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
#endif // XLSXCHARTSHEET_H
|
@ -0,0 +1,25 @@ |
|||||
|
// xlsxchartsheet_p.h
|
||||
|
|
||||
|
#ifndef XLSXCHARTSHEET_P_H |
||||
|
#define XLSXCHARTSHEET_P_H |
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
|
||||
|
#include "xlsxglobal.h" |
||||
|
#include "xlsxchartsheet.h" |
||||
|
#include "xlsxabstractsheet_p.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class ChartsheetPrivate : public AbstractSheetPrivate |
||||
|
{ |
||||
|
Q_DECLARE_PUBLIC(Chartsheet) |
||||
|
public: |
||||
|
ChartsheetPrivate(Chartsheet *p, Chartsheet::CreateFlag flag); |
||||
|
~ChartsheetPrivate(); |
||||
|
|
||||
|
Chart *chart; |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
#endif // XLSXCHARTSHEET_P_H
|
@ -0,0 +1,59 @@ |
|||||
|
// xlsxcolor_p.h
|
||||
|
|
||||
|
#ifndef QXLSX_XLSXCOLOR_P_H |
||||
|
#define QXLSX_XLSXCOLOR_P_H |
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QVariant> |
||||
|
#include <QColor> |
||||
|
#include <QXmlStreamWriter> |
||||
|
#include <QXmlStreamReader> |
||||
|
|
||||
|
#include "xlsxglobal.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class Styles; |
||||
|
|
||||
|
class XlsxColor |
||||
|
{ |
||||
|
public: |
||||
|
explicit XlsxColor(const QColor &color = QColor()); |
||||
|
explicit XlsxColor(const QString &theme, const QString &tint=QString()); |
||||
|
explicit XlsxColor (int index); |
||||
|
|
||||
|
bool isThemeColor() const; |
||||
|
bool isIndexedColor() const; |
||||
|
bool isRgbColor() const; |
||||
|
bool isInvalid() const; |
||||
|
|
||||
|
QColor rgbColor() const; |
||||
|
int indexedColor() const; |
||||
|
QStringList themeColor() const; |
||||
|
|
||||
|
operator QVariant() const; |
||||
|
|
||||
|
static QColor fromARGBString(const QString &c); |
||||
|
static QString toARGBString(const QColor &c); |
||||
|
|
||||
|
bool saveToXml(QXmlStreamWriter &writer, const QString &node=QString()) const; |
||||
|
bool loadFromXml(QXmlStreamReader &reader); |
||||
|
|
||||
|
private: |
||||
|
QVariant val; |
||||
|
}; |
||||
|
|
||||
|
#if !defined(QT_NO_DATASTREAM) |
||||
|
QDataStream &operator<<(QDataStream &, const XlsxColor &); |
||||
|
QDataStream &operator>>(QDataStream &, XlsxColor &); |
||||
|
#endif |
||||
|
|
||||
|
#ifndef QT_NO_DEBUG_STREAM |
||||
|
QDebug operator<<(QDebug dbg, const XlsxColor &c); |
||||
|
#endif |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
|
||||
|
Q_DECLARE_METATYPE(QXlsx::XlsxColor) |
||||
|
|
||||
|
#endif // QXLSX_XLSXCOLOR_P_H
|
@ -0,0 +1,120 @@ |
|||||
|
// xlsxconditionalformatting.h
|
||||
|
|
||||
|
#ifndef QXLSX_XLSXCONDITIONALFORMATTING_H |
||||
|
#define QXLSX_XLSXCONDITIONALFORMATTING_H |
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QString> |
||||
|
#include <QList> |
||||
|
#include <QColor> |
||||
|
#include <QXmlStreamReader> |
||||
|
#include <QXmlStreamWriter> |
||||
|
#include <QSharedDataPointer> |
||||
|
|
||||
|
#include "xlsxglobal.h" |
||||
|
#include "xlsxcellrange.h" |
||||
|
#include "xlsxcellreference.h" |
||||
|
|
||||
|
class ConditionalFormattingTest; |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class Format; |
||||
|
class Worksheet; |
||||
|
class Styles; |
||||
|
class ConditionalFormattingPrivate; |
||||
|
|
||||
|
class QXLSX_EXPORT ConditionalFormatting |
||||
|
{ |
||||
|
public: |
||||
|
enum HighlightRuleType { |
||||
|
Highlight_LessThan, |
||||
|
Highlight_LessThanOrEqual, |
||||
|
Highlight_Equal, |
||||
|
Highlight_NotEqual, |
||||
|
Highlight_GreaterThanOrEqual, |
||||
|
Highlight_GreaterThan, |
||||
|
Highlight_Between, |
||||
|
Highlight_NotBetween, |
||||
|
|
||||
|
Highlight_ContainsText, |
||||
|
Highlight_NotContainsText, |
||||
|
Highlight_BeginsWith, |
||||
|
Highlight_EndsWith, |
||||
|
|
||||
|
Highlight_TimePeriod, |
||||
|
|
||||
|
Highlight_Duplicate, |
||||
|
Highlight_Unique, |
||||
|
Highlight_Blanks, |
||||
|
Highlight_NoBlanks, |
||||
|
Highlight_Errors, |
||||
|
Highlight_NoErrors, |
||||
|
|
||||
|
Highlight_Top, |
||||
|
Highlight_TopPercent, |
||||
|
Highlight_Bottom, |
||||
|
Highlight_BottomPercent, |
||||
|
|
||||
|
Highlight_AboveAverage, |
||||
|
Highlight_AboveOrEqualAverage, |
||||
|
Highlight_AboveStdDev1, |
||||
|
Highlight_AboveStdDev2, |
||||
|
Highlight_AboveStdDev3, |
||||
|
Highlight_BelowAverage, |
||||
|
Highlight_BelowOrEqualAverage, |
||||
|
Highlight_BelowStdDev1, |
||||
|
Highlight_BelowStdDev2, |
||||
|
Highlight_BelowStdDev3, |
||||
|
|
||||
|
Highlight_Expression |
||||
|
}; |
||||
|
|
||||
|
enum ValueObjectType |
||||
|
{ |
||||
|
VOT_Formula, |
||||
|
VOT_Max, |
||||
|
VOT_Min, |
||||
|
VOT_Num, |
||||
|
VOT_Percent, |
||||
|
VOT_Percentile |
||||
|
}; |
||||
|
|
||||
|
public: |
||||
|
ConditionalFormatting(); |
||||
|
ConditionalFormatting(const ConditionalFormatting &other); |
||||
|
~ConditionalFormatting(); |
||||
|
|
||||
|
public: |
||||
|
bool addHighlightCellsRule(HighlightRuleType type, const Format &format, bool stopIfTrue=false); |
||||
|
bool addHighlightCellsRule(HighlightRuleType type, const QString &formula1, const Format &format, bool stopIfTrue=false); |
||||
|
bool addHighlightCellsRule(HighlightRuleType type, const QString &formula1, const QString &formula2, const Format &format, bool stopIfTrue=false); |
||||
|
bool addDataBarRule(const QColor &color, bool showData=true, bool stopIfTrue=false); |
||||
|
bool addDataBarRule(const QColor &color, ValueObjectType type1, const QString &val1, ValueObjectType type2, const QString &val2, bool showData=true, bool stopIfTrue=false); |
||||
|
bool add2ColorScaleRule(const QColor &minColor, const QColor &maxColor, bool stopIfTrue=false); |
||||
|
bool add3ColorScaleRule(const QColor &minColor, const QColor &midColor, const QColor &maxColor, bool stopIfTrue=false); |
||||
|
|
||||
|
QList<CellRange> ranges() const; |
||||
|
|
||||
|
void addCell(const CellReference &cell); |
||||
|
void addCell(int row, int col); |
||||
|
void addRange(int firstRow, int firstCol, int lastRow, int lastCol); |
||||
|
void addRange(const CellRange &range); |
||||
|
|
||||
|
//needed by QSharedDataPointer!!
|
||||
|
ConditionalFormatting &operator=(const ConditionalFormatting &other); |
||||
|
|
||||
|
private: |
||||
|
friend class Worksheet; |
||||
|
friend class ::ConditionalFormattingTest; |
||||
|
|
||||
|
private: |
||||
|
bool saveToXml(QXmlStreamWriter &writer) const; |
||||
|
bool loadFromXml(QXmlStreamReader &reader, Styles* styles = NULL); |
||||
|
|
||||
|
QSharedDataPointer<ConditionalFormattingPrivate> d; |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
|
||||
|
#endif // QXLSX_XLSXCONDITIONALFORMATTING_H
|
@ -0,0 +1,99 @@ |
|||||
|
// xlsxconditionalformatting_p.h
|
||||
|
|
||||
|
#ifndef XLSXCONDITIONALFORMATTING_P_H |
||||
|
#define XLSXCONDITIONALFORMATTING_P_H |
||||
|
|
||||
|
#include <QSharedData> |
||||
|
#include <QMap> |
||||
|
|
||||
|
#include <memory> |
||||
|
|
||||
|
#include "xlsxconditionalformatting.h" |
||||
|
#include "xlsxformat.h" |
||||
|
#include "xlsxcolor_p.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class XlsxCfVoData |
||||
|
{ |
||||
|
public: |
||||
|
XlsxCfVoData() |
||||
|
:gte(true) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
XlsxCfVoData(ConditionalFormatting::ValueObjectType type, const QString &value, bool gte=true) |
||||
|
:type(type), value(value), gte(gte) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
ConditionalFormatting::ValueObjectType type; |
||||
|
QString value; |
||||
|
bool gte; |
||||
|
}; |
||||
|
|
||||
|
class XlsxCfRuleData |
||||
|
{ |
||||
|
public: |
||||
|
enum Attribute { |
||||
|
A_type, |
||||
|
A_dxfId, |
||||
|
//A_priority,
|
||||
|
A_stopIfTrue, |
||||
|
A_aboveAverage, |
||||
|
A_percent, |
||||
|
A_bottom, |
||||
|
A_operator, |
||||
|
A_text, |
||||
|
A_timePeriod, |
||||
|
A_rank, |
||||
|
A_stdDev, |
||||
|
A_equalAverage, |
||||
|
|
||||
|
A_dxfFormat, |
||||
|
A_formula1, |
||||
|
A_formula2, |
||||
|
A_formula3, |
||||
|
A_formula1_temp, |
||||
|
|
||||
|
A_color1, |
||||
|
A_color2, |
||||
|
A_color3, |
||||
|
|
||||
|
A_cfvo1, |
||||
|
A_cfvo2, |
||||
|
A_cfvo3, |
||||
|
|
||||
|
A_hideData |
||||
|
}; |
||||
|
|
||||
|
XlsxCfRuleData() |
||||
|
:priority(1) |
||||
|
{} |
||||
|
|
||||
|
int priority; |
||||
|
Format dxfFormat; |
||||
|
QMap<int, QVariant> attrs; |
||||
|
}; |
||||
|
|
||||
|
class ConditionalFormattingPrivate : public QSharedData |
||||
|
{ |
||||
|
public: |
||||
|
ConditionalFormattingPrivate(); |
||||
|
ConditionalFormattingPrivate(const ConditionalFormattingPrivate &other); |
||||
|
~ConditionalFormattingPrivate(); |
||||
|
|
||||
|
void writeCfVo(QXmlStreamWriter &writer, const XlsxCfVoData& cfvo) const; |
||||
|
bool readCfVo(QXmlStreamReader &reader, XlsxCfVoData& cfvo); |
||||
|
bool readCfRule(QXmlStreamReader &reader, XlsxCfRuleData *cfRule, Styles *styles); |
||||
|
bool readCfDataBar(QXmlStreamReader &reader, XlsxCfRuleData *cfRule); |
||||
|
bool readCfColorScale(QXmlStreamReader &reader, XlsxCfRuleData *cfRule); |
||||
|
|
||||
|
QList<std::shared_ptr<XlsxCfRuleData> >cfRules; |
||||
|
QList<CellRange> ranges; |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
|
||||
|
Q_DECLARE_METATYPE(QXlsx::XlsxCfVoData) |
||||
|
#endif // XLSXCONDITIONALFORMATTING_P_H
|
@ -0,0 +1,55 @@ |
|||||
|
// xlsxcontenttypes_p.h
|
||||
|
|
||||
|
#ifndef XLSXCONTENTTYPES_H |
||||
|
#define XLSXCONTENTTYPES_H |
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QString> |
||||
|
#include <QStringList> |
||||
|
#include <QMap> |
||||
|
#include <QIODevice> |
||||
|
|
||||
|
#include "xlsxabstractooxmlfile.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class ContentTypes : public AbstractOOXmlFile |
||||
|
{ |
||||
|
public: |
||||
|
ContentTypes(CreateFlag flag); |
||||
|
|
||||
|
void addDefault(const QString &key, const QString &value); |
||||
|
void addOverride(const QString &key, const QString &value); |
||||
|
|
||||
|
//Convenient funcation for addOverride()
|
||||
|
void addDocPropCore(); |
||||
|
void addDocPropApp(); |
||||
|
void addStyles(); |
||||
|
void addTheme(); |
||||
|
void addWorkbook(); |
||||
|
void addWorksheetName(const QString &name); |
||||
|
void addChartsheetName(const QString &name); |
||||
|
void addChartName(const QString &name); |
||||
|
void addDrawingName(const QString &name); |
||||
|
void addCommentName(const QString &name); |
||||
|
void addTableName(const QString &name); |
||||
|
void addExternalLinkName(const QString &name); |
||||
|
void addSharedString(); |
||||
|
void addVmlName(); |
||||
|
void addCalcChain(); |
||||
|
void addVbaProject(); |
||||
|
|
||||
|
void clearOverrides(); |
||||
|
|
||||
|
void saveToXmlFile(QIODevice *device) const override; |
||||
|
bool loadFromXmlFile(QIODevice *device) override; |
||||
|
private: |
||||
|
QMap<QString, QString> m_defaults; |
||||
|
QMap<QString, QString> m_overrides; |
||||
|
|
||||
|
QString m_package_prefix; |
||||
|
QString m_document_prefix; |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
#endif // XLSXCONTENTTYPES_H
|
@ -0,0 +1,105 @@ |
|||||
|
// xlsxvalidation.h
|
||||
|
|
||||
|
#ifndef QXLSX_XLSXDATAVALIDATION_H |
||||
|
#define QXLSX_XLSXDATAVALIDATION_H |
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QSharedDataPointer> |
||||
|
#include <QString> |
||||
|
#include <QList> |
||||
|
#include <QXmlStreamReader> |
||||
|
#include <QXmlStreamWriter> |
||||
|
|
||||
|
#include "xlsxglobal.h" |
||||
|
|
||||
|
class QXmlStreamReader; |
||||
|
class QXmlStreamWriter; |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class Worksheet; |
||||
|
class CellRange; |
||||
|
class CellReference; |
||||
|
|
||||
|
class DataValidationPrivate; |
||||
|
class QXLSX_EXPORT DataValidation |
||||
|
{ |
||||
|
public: |
||||
|
enum ValidationType |
||||
|
{ |
||||
|
None, |
||||
|
Whole, |
||||
|
Decimal, |
||||
|
List, |
||||
|
Date, |
||||
|
Time, |
||||
|
TextLength, |
||||
|
Custom |
||||
|
}; |
||||
|
|
||||
|
enum ValidationOperator |
||||
|
{ |
||||
|
Between, |
||||
|
NotBetween, |
||||
|
Equal, |
||||
|
NotEqual, |
||||
|
LessThan, |
||||
|
LessThanOrEqual, |
||||
|
GreaterThan, |
||||
|
GreaterThanOrEqual |
||||
|
}; |
||||
|
|
||||
|
enum ErrorStyle |
||||
|
{ |
||||
|
Stop, |
||||
|
Warning, |
||||
|
Information |
||||
|
}; |
||||
|
|
||||
|
DataValidation(); |
||||
|
DataValidation(ValidationType type, ValidationOperator op=Between, const QString &formula1=QString() |
||||
|
, const QString &formula2=QString(), bool allowBlank=false); |
||||
|
DataValidation(const DataValidation &other); |
||||
|
~DataValidation(); |
||||
|
|
||||
|
ValidationType validationType() const; |
||||
|
ValidationOperator validationOperator() const; |
||||
|
ErrorStyle errorStyle() const; |
||||
|
QString formula1() const; |
||||
|
QString formula2() const; |
||||
|
bool allowBlank() const; |
||||
|
QString errorMessage() const; |
||||
|
QString errorMessageTitle() const; |
||||
|
QString promptMessage() const; |
||||
|
QString promptMessageTitle() const; |
||||
|
bool isPromptMessageVisible() const; |
||||
|
bool isErrorMessageVisible() const; |
||||
|
QList<CellRange> ranges() const; |
||||
|
|
||||
|
void setValidationType(ValidationType type); |
||||
|
void setValidationOperator(ValidationOperator op); |
||||
|
void setErrorStyle(ErrorStyle es); |
||||
|
void setFormula1(const QString &formula); |
||||
|
void setFormula2(const QString &formula); |
||||
|
void setErrorMessage(const QString &error, const QString &title=QString()); |
||||
|
void setPromptMessage(const QString &prompt, const QString &title=QString()); |
||||
|
void setAllowBlank(bool enable); |
||||
|
void setPromptMessageVisible(bool visible); |
||||
|
void setErrorMessageVisible(bool visible); |
||||
|
|
||||
|
void addCell(const CellReference &cell); |
||||
|
void addCell(int row, int col); |
||||
|
void addRange(int firstRow, int firstCol, int lastRow, int lastCol); |
||||
|
void addRange(const CellRange &range); |
||||
|
|
||||
|
DataValidation &operator=(const DataValidation &other); |
||||
|
|
||||
|
bool saveToXml(QXmlStreamWriter &writer) const; |
||||
|
static DataValidation loadFromXml(QXmlStreamReader &reader); |
||||
|
private: |
||||
|
QSharedDataPointer<DataValidationPrivate> d; |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
|
||||
|
#endif // QXLSX_XLSXDATAVALIDATION_H
|
@ -0,0 +1,37 @@ |
|||||
|
// xlsxdatavalidation_p.h
|
||||
|
|
||||
|
#ifndef XLSXDATAVALIDATION_P_H |
||||
|
#define XLSXDATAVALIDATION_P_H |
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QSharedData> |
||||
|
|
||||
|
#include "xlsxdatavalidation.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class DataValidationPrivate : public QSharedData |
||||
|
{ |
||||
|
public: |
||||
|
DataValidationPrivate(); |
||||
|
DataValidationPrivate(DataValidation::ValidationType type, DataValidation::ValidationOperator op, const QString &formula1, const QString &formula2, bool allowBlank); |
||||
|
DataValidationPrivate(const DataValidationPrivate &other); |
||||
|
~DataValidationPrivate(); |
||||
|
|
||||
|
DataValidation::ValidationType validationType; |
||||
|
DataValidation::ValidationOperator validationOperator; |
||||
|
DataValidation::ErrorStyle errorStyle; |
||||
|
bool allowBlank; |
||||
|
bool isPromptMessageVisible; |
||||
|
bool isErrorMessageVisible; |
||||
|
QString formula1; |
||||
|
QString formula2; |
||||
|
QString errorMessage; |
||||
|
QString errorMessageTitle; |
||||
|
QString promptMessage; |
||||
|
QString promptMessageTitle; |
||||
|
QList<CellRange> ranges; |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
#endif // XLSXDATAVALIDATION_P_H
|
@ -0,0 +1,48 @@ |
|||||
|
// xlsxdatetype.h
|
||||
|
|
||||
|
#ifndef QXLSX_XLSXDATETYPE_H |
||||
|
#define QXLSX_XLSXDATETYPE_H |
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QObject> |
||||
|
#include <QString> |
||||
|
#include <QStringList> |
||||
|
#include <QDateTime> |
||||
|
#include <QDate> |
||||
|
#include <QTime> |
||||
|
|
||||
|
#include "xlsxglobal.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class QXLSX_EXPORT DateType |
||||
|
{ |
||||
|
public: |
||||
|
DateType(); |
||||
|
/*
|
||||
|
DateType(bool is1904 = false); |
||||
|
DateType(double d, bool is1904 = false); |
||||
|
DateType(QDateTime qdt, bool is1904 = false); |
||||
|
DateType(QDate qd, bool is1904 = false); |
||||
|
DateType(QTime qt, bool is1904 = false); |
||||
|
public: |
||||
|
enum currentDateType { DateAndTimeType, OnlyDateType, OnlyTimeType }; |
||||
|
public: |
||||
|
currentDateType getType(); |
||||
|
bool getValue(QDateTime* pQdt); |
||||
|
bool getValue(QDate* pQd); |
||||
|
bool getValue(QTime* pQt); |
||||
|
bool getValue(double* pD); |
||||
|
|
||||
|
protected: |
||||
|
|
||||
|
protected: |
||||
|
bool isSet; |
||||
|
double dValue; |
||||
|
bool is1904Type; |
||||
|
currentDateType dType; |
||||
|
*/ |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
#endif |
@ -0,0 +1,40 @@ |
|||||
|
// xlsxdocpropsapp_p.h
|
||||
|
|
||||
|
#ifndef XLSXDOCPROPSAPP_H |
||||
|
#define XLSXDOCPROPSAPP_H |
||||
|
|
||||
|
#include <QList> |
||||
|
#include <QStringList> |
||||
|
#include <QMap> |
||||
|
|
||||
|
#include "xlsxglobal.h" |
||||
|
#include "xlsxabstractooxmlfile.h" |
||||
|
|
||||
|
class QIODevice; |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class DocPropsApp : public AbstractOOXmlFile |
||||
|
{ |
||||
|
public: |
||||
|
DocPropsApp(CreateFlag flag); |
||||
|
|
||||
|
void addPartTitle(const QString &title); |
||||
|
void addHeadingPair(const QString &name, int value); |
||||
|
|
||||
|
bool setProperty(const QString &name, const QString &value); |
||||
|
QString property(const QString &name) const; |
||||
|
QStringList propertyNames() const; |
||||
|
|
||||
|
void saveToXmlFile(QIODevice *device) const override; |
||||
|
bool loadFromXmlFile(QIODevice *device) override; |
||||
|
|
||||
|
private: |
||||
|
QStringList m_titlesOfPartsList; |
||||
|
QList<std::pair<QString, int> > m_headingPairsList; |
||||
|
QMap<QString, QString> m_properties; |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
|
||||
|
#endif // XLSXDOCPROPSAPP_H
|
@ -0,0 +1,34 @@ |
|||||
|
// xlsxdocpropscore_p.h
|
||||
|
|
||||
|
#ifndef XLSXDOCPROPSCORE_H |
||||
|
#define XLSXDOCPROPSCORE_H |
||||
|
|
||||
|
#include "xlsxglobal.h" |
||||
|
#include "xlsxabstractooxmlfile.h" |
||||
|
|
||||
|
#include <QMap> |
||||
|
#include <QStringList> |
||||
|
|
||||
|
class QIODevice; |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class DocPropsCore : public AbstractOOXmlFile |
||||
|
{ |
||||
|
public: |
||||
|
explicit DocPropsCore(CreateFlag flag); |
||||
|
|
||||
|
bool setProperty(const QString &name, const QString &value); |
||||
|
QString property(const QString &name) const; |
||||
|
QStringList propertyNames() const; |
||||
|
|
||||
|
void saveToXmlFile(QIODevice *device) const override; |
||||
|
bool loadFromXmlFile(QIODevice *device) override; |
||||
|
|
||||
|
private: |
||||
|
QMap<QString, QString> m_properties; |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
|
||||
|
#endif // XLSXDOCPROPSCORE_H
|
@ -0,0 +1,143 @@ |
|||||
|
// xlsxdocument.h
|
||||
|
|
||||
|
#ifndef QXLSX_XLSXDOCUMENT_H |
||||
|
#define QXLSX_XLSXDOCUMENT_H |
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QObject> |
||||
|
#include <QVariant> |
||||
|
#include <QIODevice> |
||||
|
#include <QImage> |
||||
|
|
||||
|
#include "xlsxglobal.h" |
||||
|
#include "xlsxformat.h" |
||||
|
#include "xlsxworksheet.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class Workbook; |
||||
|
class Cell; |
||||
|
class CellRange; |
||||
|
class DataValidation; |
||||
|
class ConditionalFormatting; |
||||
|
class Chart; |
||||
|
class CellReference; |
||||
|
class DocumentPrivate; |
||||
|
|
||||
|
class QXLSX_EXPORT Document : public QObject |
||||
|
{ |
||||
|
Q_OBJECT |
||||
|
Q_DECLARE_PRIVATE(Document) // D-Pointer. Qt classes have a Q_DECLARE_PRIVATE
|
||||
|
// macro in the public class. The macro reads: qglobal.h
|
||||
|
public: |
||||
|
explicit Document(QObject *parent = nullptr); |
||||
|
Document(const QString& xlsxName, QObject* parent = nullptr); |
||||
|
Document(QIODevice* device, QObject* parent = nullptr); |
||||
|
~Document(); |
||||
|
|
||||
|
bool write(const CellReference &cell, const QVariant &value, const Format &format=Format()); |
||||
|
bool write(int row, int col, const QVariant &value, const Format &format=Format()); |
||||
|
|
||||
|
QVariant read(const CellReference &cell) const; |
||||
|
QVariant read(int row, int col) const; |
||||
|
|
||||
|
int insertImage(int row, int col, const QImage &image); |
||||
|
bool getImage(int imageIndex, QImage& img); |
||||
|
bool getImage(int row, int col, QImage& img); |
||||
|
uint getImageCount(); |
||||
|
|
||||
|
Chart *insertChart(int row, int col, const QSize &size); |
||||
|
|
||||
|
bool mergeCells(const CellRange &range, const Format &format=Format()); |
||||
|
bool unmergeCells(const CellRange &range); |
||||
|
|
||||
|
bool setColumnWidth(const CellRange &range, double width); |
||||
|
bool setColumnFormat(const CellRange &range, const Format &format); |
||||
|
bool setColumnHidden(const CellRange &range, bool hidden); |
||||
|
bool setColumnWidth(int column, double width); |
||||
|
bool setColumnFormat(int column, const Format &format); |
||||
|
bool setColumnHidden(int column, bool hidden); |
||||
|
bool setColumnWidth(int colFirst, int colLast, double width); |
||||
|
bool setColumnFormat(int colFirst, int colLast, const Format &format); |
||||
|
bool setColumnHidden(int colFirst, int colLast, bool hidden); |
||||
|
|
||||
|
double columnWidth(int column); |
||||
|
Format columnFormat(int column); |
||||
|
bool isColumnHidden(int column); |
||||
|
|
||||
|
bool setRowHeight(int row, double height); |
||||
|
bool setRowFormat(int row, const Format &format); |
||||
|
bool setRowHidden(int row, bool hidden); |
||||
|
bool setRowHeight(int rowFirst, int rowLast, double height); |
||||
|
bool setRowFormat(int rowFirst, int rowLast, const Format &format); |
||||
|
bool setRowHidden(int rowFirst, int rowLast, bool hidden); |
||||
|
|
||||
|
double rowHeight(int row); |
||||
|
Format rowFormat(int row); |
||||
|
bool isRowHidden(int row); |
||||
|
|
||||
|
bool groupRows(int rowFirst, int rowLast, bool collapsed = true); |
||||
|
bool groupColumns(int colFirst, int colLast, bool collapsed = true); |
||||
|
|
||||
|
bool addDataValidation(const DataValidation &validation); |
||||
|
bool addConditionalFormatting(const ConditionalFormatting &cf); |
||||
|
|
||||
|
Cell *cellAt(const CellReference &cell) const; |
||||
|
Cell *cellAt(int row, int col) const; |
||||
|
|
||||
|
bool defineName(const QString &name, const QString &formula, |
||||
|
const QString &comment=QString(), const QString &scope=QString()); |
||||
|
|
||||
|
CellRange dimension() const; |
||||
|
|
||||
|
QString documentProperty(const QString &name) const; |
||||
|
void setDocumentProperty(const QString &name, const QString &property); |
||||
|
QStringList documentPropertyNames() const; |
||||
|
|
||||
|
QStringList sheetNames() const; |
||||
|
bool addSheet(const QString &name = QString(), |
||||
|
AbstractSheet::SheetType type = AbstractSheet::ST_WorkSheet); |
||||
|
bool insertSheet(int index, const QString &name = QString(), |
||||
|
AbstractSheet::SheetType type = AbstractSheet::ST_WorkSheet); |
||||
|
bool selectSheet(const QString &name); |
||||
|
bool selectSheet(int index); |
||||
|
bool renameSheet(const QString &oldName, const QString &newName); |
||||
|
bool copySheet(const QString &srcName, const QString &distName = QString()); |
||||
|
bool moveSheet(const QString &srcName, int distIndex); |
||||
|
bool deleteSheet(const QString &name); |
||||
|
|
||||
|
Workbook *workbook() const; |
||||
|
AbstractSheet *sheet(const QString &sheetName) const; |
||||
|
AbstractSheet *currentSheet() const; |
||||
|
Worksheet *currentWorksheet() const; |
||||
|
|
||||
|
bool save() const; |
||||
|
bool saveAs(const QString &xlsXname) const; |
||||
|
bool saveAs(QIODevice *device) const; |
||||
|
|
||||
|
// copy style from one xlsx file to other
|
||||
|
static bool copyStyle(const QString &from, const QString &to); |
||||
|
|
||||
|
bool isLoadPackage() const; |
||||
|
bool load() const; // equals to isLoadPackage()
|
||||
|
|
||||
|
bool changeimage(int filenoinmidea,QString newfile); // add by liufeijin20181025
|
||||
|
|
||||
|
bool autosizeColumnWidth(const CellRange &range); |
||||
|
bool autosizeColumnWidth(int column); |
||||
|
bool autosizeColumnWidth(int colFirst, int colLast); |
||||
|
bool autosizeColumnWidth(void); |
||||
|
|
||||
|
private: |
||||
|
QMap<int, int> getMaximalColumnWidth(int firstRow=1, int lastRow=INT_MAX); |
||||
|
|
||||
|
|
||||
|
private: |
||||
|
Q_DISABLE_COPY(Document) // Disables the use of copy constructors and
|
||||
|
// assignment operators for the given Class.
|
||||
|
DocumentPrivate* const d_ptr; |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
|
||||
|
#endif // QXLSX_XLSXDOCUMENT_H
|
@ -0,0 +1,41 @@ |
|||||
|
// xlsxdocument_p.h
|
||||
|
|
||||
|
#ifndef XLSXDOCUMENT_P_H |
||||
|
#define XLSXDOCUMENT_P_H |
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QMap> |
||||
|
|
||||
|
#include "xlsxglobal.h" |
||||
|
#include "xlsxdocument.h" |
||||
|
#include "xlsxworkbook.h" |
||||
|
#include "xlsxcontenttypes_p.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class DocumentPrivate |
||||
|
{ |
||||
|
Q_DECLARE_PUBLIC(Document) |
||||
|
public: |
||||
|
DocumentPrivate(Document *p); |
||||
|
void init(); |
||||
|
|
||||
|
bool loadPackage(QIODevice *device); |
||||
|
bool savePackage(QIODevice *device) const; |
||||
|
|
||||
|
// copy style from one xlsx file to other
|
||||
|
static bool copyStyle(const QString &from, const QString &to); |
||||
|
|
||||
|
Document *q_ptr; |
||||
|
const QString defaultPackageName; //default name when package name not specified
|
||||
|
QString packageName; //name of the .xlsx file
|
||||
|
|
||||
|
QMap<QString, QString> documentProperties; //core, app and custom properties
|
||||
|
QSharedPointer<Workbook> workbook; |
||||
|
std::shared_ptr<ContentTypes> contentTypes; |
||||
|
bool isLoad; |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
|
||||
|
#endif // XLSXDOCUMENT_P_H
|
@ -0,0 +1,38 @@ |
|||||
|
// xlsxdrwaing_p.h
|
||||
|
|
||||
|
#ifndef QXLSX_DRAWING_H |
||||
|
#define QXLSX_DRAWING_H |
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QList> |
||||
|
#include <QString> |
||||
|
|
||||
|
#include "xlsxrelationships_p.h" |
||||
|
#include "xlsxabstractooxmlfile.h" |
||||
|
|
||||
|
class QIODevice; |
||||
|
class QXmlStreamWriter; |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class DrawingAnchor; |
||||
|
class Workbook; |
||||
|
class AbstractSheet; |
||||
|
class MediaFile; |
||||
|
|
||||
|
class Drawing : public AbstractOOXmlFile |
||||
|
{ |
||||
|
public: |
||||
|
Drawing(AbstractSheet *sheet, CreateFlag flag); |
||||
|
~Drawing(); |
||||
|
void saveToXmlFile(QIODevice *device) const override; |
||||
|
bool loadFromXmlFile(QIODevice *device) override; |
||||
|
|
||||
|
AbstractSheet *sheet; |
||||
|
Workbook *workbook; |
||||
|
QList<DrawingAnchor *> anchors; |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
|
||||
|
#endif // QXLSX_DRAWING_H
|
@ -0,0 +1,169 @@ |
|||||
|
// xlsxdrawinganchor_p.h
|
||||
|
|
||||
|
#ifndef QXLSX_XLSXDRAWINGANCHOR_P_H |
||||
|
#define QXLSX_XLSXDRAWINGANCHOR_P_H |
||||
|
|
||||
|
#include <QPoint> |
||||
|
#include <QSize> |
||||
|
#include <QString> |
||||
|
#include <QSharedPointer> |
||||
|
#include <QXmlStreamReader> |
||||
|
#include <QXmlStreamWriter> |
||||
|
|
||||
|
#include <memory> |
||||
|
|
||||
|
#include "xlsxglobal.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class Drawing; |
||||
|
class MediaFile; |
||||
|
class Chart; |
||||
|
|
||||
|
//Helper class
|
||||
|
struct XlsxMarker |
||||
|
{ |
||||
|
XlsxMarker(){} |
||||
|
XlsxMarker(int row, int column, int rowOffset, int colOffset) |
||||
|
:cell(QPoint(row, column)), offset(rowOffset, colOffset) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
int row() const {return cell.x();} |
||||
|
int col() const {return cell.y();} |
||||
|
int rowOff() const {return offset.width();} |
||||
|
int colOff() const {return offset.height();} |
||||
|
|
||||
|
QPoint cell; |
||||
|
QSize offset; |
||||
|
}; |
||||
|
|
||||
|
class DrawingAnchor |
||||
|
{ |
||||
|
public: |
||||
|
enum ObjectType { |
||||
|
GraphicFrame, |
||||
|
Shape, |
||||
|
GroupShape, |
||||
|
ConnectionShape, |
||||
|
Picture, |
||||
|
Unknown |
||||
|
}; |
||||
|
|
||||
|
DrawingAnchor(Drawing *drawing, ObjectType objectType); |
||||
|
virtual ~DrawingAnchor(); |
||||
|
|
||||
|
void setObjectPicture(const QImage &img); |
||||
|
bool getObjectPicture(QImage &img); |
||||
|
|
||||
|
void setObjectGraphicFrame(QSharedPointer<Chart> chart); |
||||
|
|
||||
|
virtual bool loadFromXml(QXmlStreamReader &reader) = 0; |
||||
|
virtual void saveToXml(QXmlStreamWriter &writer) const = 0; |
||||
|
|
||||
|
virtual int row() const; |
||||
|
virtual int col() const; |
||||
|
|
||||
|
protected: |
||||
|
QPoint loadXmlPos(QXmlStreamReader &reader); |
||||
|
QSize loadXmlExt(QXmlStreamReader &reader); |
||||
|
XlsxMarker loadXmlMarker(QXmlStreamReader &reader, const QString &node); |
||||
|
void loadXmlObject(QXmlStreamReader &reader); |
||||
|
void loadXmlObjectShape(QXmlStreamReader &reader); |
||||
|
void loadXmlObjectGroupShape(QXmlStreamReader &reader); |
||||
|
void loadXmlObjectGraphicFrame(QXmlStreamReader &reader); |
||||
|
void loadXmlObjectConnectionShape(QXmlStreamReader &reader); |
||||
|
void loadXmlObjectPicture(QXmlStreamReader &reader); |
||||
|
|
||||
|
void saveXmlPos(QXmlStreamWriter &writer, const QPoint &pos) const; |
||||
|
void saveXmlExt(QXmlStreamWriter &writer, const QSize &ext) const; |
||||
|
void saveXmlMarker(QXmlStreamWriter &writer, const XlsxMarker &marker, const QString &node) const; |
||||
|
void saveXmlObject(QXmlStreamWriter &writer) const; |
||||
|
void saveXmlObjectShape(QXmlStreamWriter &writer) const; |
||||
|
void saveXmlObjectGroupShape(QXmlStreamWriter &writer) const; |
||||
|
void saveXmlObjectGraphicFrame(QXmlStreamWriter &writer) const; |
||||
|
void saveXmlObjectConnectionShape(QXmlStreamWriter &writer) const; |
||||
|
void saveXmlObjectPicture(QXmlStreamWriter &writer) const; |
||||
|
|
||||
|
Drawing *m_drawing; |
||||
|
ObjectType m_objectType; |
||||
|
std::shared_ptr<MediaFile> m_pictureFile; |
||||
|
QSharedPointer<Chart> m_chartFile; |
||||
|
|
||||
|
int m_id; |
||||
|
public: |
||||
|
int getm_id(); |
||||
|
|
||||
|
protected: |
||||
|
|
||||
|
// liufeij {{
|
||||
|
void setObjectShape(const QImage &img); // liufeij
|
||||
|
|
||||
|
QString editASName; |
||||
|
// below only for twocellanchor shape
|
||||
|
QPoint posTA; // for shape liufeij 20181024
|
||||
|
QSize extTA; // for shape liufeij 20181024
|
||||
|
int rotWithShapeTA; //// for shape liufeij 20181024
|
||||
|
int dpiTA; //// for shape liufeij 20181024
|
||||
|
QString sp_textlink,sp_macro,sp_blip_cstate,sp_blip_rembed; |
||||
|
|
||||
|
// BELOW only for cxnSp shape
|
||||
|
QString cxnSp_filpV,cxnSp_macro; |
||||
|
// belwo for cxnsp and sp
|
||||
|
QString xsp_cNvPR_name,xsp_cNvPR_id; //x measns shape and cxnSp together using
|
||||
|
QString xbwMode; // same as above
|
||||
|
QString xIn_algn,xIn_cmpd,xIn_cap,xIn_w; //cxnSp only need xIn_w
|
||||
|
QString xprstGeom_prst; |
||||
|
QString x_headEnd_w,x_headEnd_len,x_headEnd_tyep; |
||||
|
QString x_tailEnd_w,x_tailEnd_len,x_tailEnd_tyep; |
||||
|
QString Style_inref_idx,style_fillref_idx,style_effectref_idx,style_forntref_idx; |
||||
|
QString Style_inref_val,style_fillref_val,style_effectref_val,style_forntref_val; |
||||
|
// liufeij }}
|
||||
|
}; |
||||
|
|
||||
|
class DrawingAbsoluteAnchor : public DrawingAnchor |
||||
|
{ |
||||
|
public: |
||||
|
DrawingAbsoluteAnchor(Drawing *drawing, ObjectType objectType=Unknown); |
||||
|
|
||||
|
QPoint pos; |
||||
|
QSize ext; |
||||
|
|
||||
|
bool loadFromXml(QXmlStreamReader &reader) override; |
||||
|
void saveToXml(QXmlStreamWriter &writer) const override; |
||||
|
}; |
||||
|
|
||||
|
class DrawingOneCellAnchor : public DrawingAnchor |
||||
|
{ |
||||
|
public: |
||||
|
DrawingOneCellAnchor(Drawing *drawing, ObjectType objectType=Unknown); |
||||
|
|
||||
|
XlsxMarker from; |
||||
|
QSize ext; |
||||
|
|
||||
|
int row() const override; |
||||
|
int col() const override; |
||||
|
|
||||
|
bool loadFromXml(QXmlStreamReader &reader) override; |
||||
|
void saveToXml(QXmlStreamWriter &writer) const override; |
||||
|
}; |
||||
|
|
||||
|
class DrawingTwoCellAnchor : public DrawingAnchor |
||||
|
{ |
||||
|
public: |
||||
|
DrawingTwoCellAnchor(Drawing *drawing, ObjectType objectType=Unknown); |
||||
|
|
||||
|
XlsxMarker from; |
||||
|
XlsxMarker to; |
||||
|
|
||||
|
int row() const override; |
||||
|
int col() const override; |
||||
|
|
||||
|
bool loadFromXml(QXmlStreamReader &reader) override; |
||||
|
void saveToXml(QXmlStreamWriter &writer) const override; |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
|
||||
|
#endif // QXLSX_XLSXDRAWINGANCHOR_P_H
|
@ -0,0 +1,262 @@ |
|||||
|
// xlsxformat.h
|
||||
|
|
||||
|
#ifndef QXLSX_FORMAT_H |
||||
|
#define QXLSX_FORMAT_H |
||||
|
|
||||
|
#include <QFont> |
||||
|
#include <QColor> |
||||
|
#include <QByteArray> |
||||
|
#include <QList> |
||||
|
#include <QExplicitlySharedDataPointer> |
||||
|
#include <QVariant> |
||||
|
|
||||
|
#include "xlsxglobal.h" |
||||
|
|
||||
|
class FormatTest; |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class Styles; |
||||
|
class Worksheet; |
||||
|
class WorksheetPrivate; |
||||
|
class RichStringPrivate; |
||||
|
class SharedStrings; |
||||
|
|
||||
|
class FormatPrivate; |
||||
|
|
||||
|
class QXLSX_EXPORT Format |
||||
|
{ |
||||
|
public: |
||||
|
enum FontScript |
||||
|
{ |
||||
|
FontScriptNormal, |
||||
|
FontScriptSuper, |
||||
|
FontScriptSub |
||||
|
}; |
||||
|
|
||||
|
enum FontUnderline |
||||
|
{ |
||||
|
FontUnderlineNone, |
||||
|
FontUnderlineSingle, |
||||
|
FontUnderlineDouble, |
||||
|
FontUnderlineSingleAccounting, |
||||
|
FontUnderlineDoubleAccounting |
||||
|
}; |
||||
|
|
||||
|
enum HorizontalAlignment |
||||
|
{ |
||||
|
AlignHGeneral, |
||||
|
AlignLeft, |
||||
|
AlignHCenter, |
||||
|
AlignRight, |
||||
|
AlignHFill, |
||||
|
AlignHJustify, |
||||
|
AlignHMerge, |
||||
|
AlignHDistributed |
||||
|
}; |
||||
|
|
||||
|
enum VerticalAlignment |
||||
|
{ |
||||
|
AlignTop, |
||||
|
AlignVCenter, |
||||
|
AlignBottom, |
||||
|
AlignVJustify, |
||||
|
AlignVDistributed |
||||
|
}; |
||||
|
|
||||
|
enum BorderStyle |
||||
|
{ |
||||
|
BorderNone, |
||||
|
BorderThin, |
||||
|
BorderMedium, |
||||
|
BorderDashed, |
||||
|
BorderDotted, |
||||
|
BorderThick, |
||||
|
BorderDouble, |
||||
|
BorderHair, |
||||
|
BorderMediumDashed, |
||||
|
BorderDashDot, |
||||
|
BorderMediumDashDot, |
||||
|
BorderDashDotDot, |
||||
|
BorderMediumDashDotDot, |
||||
|
BorderSlantDashDot |
||||
|
}; |
||||
|
|
||||
|
enum DiagonalBorderType |
||||
|
{ |
||||
|
DiagonalBorderNone, |
||||
|
DiagonalBorderDown, |
||||
|
DiagonalBorderUp, |
||||
|
DiagnoalBorderBoth |
||||
|
}; |
||||
|
|
||||
|
enum FillPattern |
||||
|
{ |
||||
|
PatternNone, |
||||
|
PatternSolid, |
||||
|
PatternMediumGray, |
||||
|
PatternDarkGray, |
||||
|
PatternLightGray, |
||||
|
PatternDarkHorizontal, |
||||
|
PatternDarkVertical, |
||||
|
PatternDarkDown, |
||||
|
PatternDarkUp, |
||||
|
PatternDarkGrid, |
||||
|
PatternDarkTrellis, |
||||
|
PatternLightHorizontal, |
||||
|
PatternLightVertical, |
||||
|
PatternLightDown, |
||||
|
PatternLightUp, |
||||
|
PatternLightTrellis, |
||||
|
PatternGray125, |
||||
|
PatternGray0625, |
||||
|
PatternLightGrid |
||||
|
}; |
||||
|
|
||||
|
Format(); |
||||
|
Format(const Format &other); |
||||
|
Format &operator=(const Format &rhs); |
||||
|
~Format(); |
||||
|
|
||||
|
int numberFormatIndex() const; |
||||
|
void setNumberFormatIndex(int format); |
||||
|
QString numberFormat() const; |
||||
|
void setNumberFormat(const QString &format); |
||||
|
void setNumberFormat(int id, const QString &format); |
||||
|
bool isDateTimeFormat() const; |
||||
|
|
||||
|
int fontSize() const; |
||||
|
void setFontSize(int size); |
||||
|
bool fontItalic() const; |
||||
|
void setFontItalic(bool italic); |
||||
|
bool fontStrikeOut() const; |
||||
|
void setFontStrikeOut(bool); |
||||
|
QColor fontColor() const; |
||||
|
void setFontColor(const QColor &); |
||||
|
bool fontBold() const; |
||||
|
void setFontBold(bool bold); |
||||
|
FontScript fontScript() const; |
||||
|
void setFontScript(FontScript); |
||||
|
FontUnderline fontUnderline() const; |
||||
|
void setFontUnderline(FontUnderline); |
||||
|
bool fontOutline() const; |
||||
|
void setFontOutline(bool outline); |
||||
|
QString fontName() const; |
||||
|
void setFontName(const QString &); |
||||
|
QFont font() const; |
||||
|
void setFont(const QFont &font); |
||||
|
|
||||
|
HorizontalAlignment horizontalAlignment() const; |
||||
|
void setHorizontalAlignment(HorizontalAlignment align); |
||||
|
VerticalAlignment verticalAlignment() const; |
||||
|
void setVerticalAlignment(VerticalAlignment align); |
||||
|
bool textWrap() const; |
||||
|
void setTextWrap(bool textWrap); |
||||
|
int rotation() const; |
||||
|
void setRotation(int rotation); |
||||
|
int indent() const; |
||||
|
void setIndent(int indent); |
||||
|
bool shrinkToFit() const; |
||||
|
void setShrinkToFit(bool shink); |
||||
|
|
||||
|
void setBorderStyle(BorderStyle style); |
||||
|
void setBorderColor(const QColor &color); |
||||
|
BorderStyle leftBorderStyle() const; |
||||
|
void setLeftBorderStyle(BorderStyle style); |
||||
|
QColor leftBorderColor() const; |
||||
|
void setLeftBorderColor(const QColor &color); |
||||
|
BorderStyle rightBorderStyle() const; |
||||
|
void setRightBorderStyle(BorderStyle style); |
||||
|
QColor rightBorderColor() const; |
||||
|
void setRightBorderColor(const QColor &color); |
||||
|
BorderStyle topBorderStyle() const; |
||||
|
void setTopBorderStyle(BorderStyle style); |
||||
|
QColor topBorderColor() const; |
||||
|
void setTopBorderColor(const QColor &color); |
||||
|
BorderStyle bottomBorderStyle() const; |
||||
|
void setBottomBorderStyle(BorderStyle style); |
||||
|
QColor bottomBorderColor() const; |
||||
|
void setBottomBorderColor(const QColor &color); |
||||
|
BorderStyle diagonalBorderStyle() const; |
||||
|
void setDiagonalBorderStyle(BorderStyle style); |
||||
|
DiagonalBorderType diagonalBorderType() const; |
||||
|
void setDiagonalBorderType(DiagonalBorderType style); |
||||
|
QColor diagonalBorderColor() const; |
||||
|
void setDiagonalBorderColor(const QColor &color); |
||||
|
|
||||
|
FillPattern fillPattern() const; |
||||
|
void setFillPattern(FillPattern pattern); |
||||
|
QColor patternForegroundColor() const; |
||||
|
void setPatternForegroundColor(const QColor &color); |
||||
|
QColor patternBackgroundColor() const; |
||||
|
void setPatternBackgroundColor(const QColor &color); |
||||
|
|
||||
|
bool locked() const; |
||||
|
void setLocked(bool locked); |
||||
|
bool hidden() const; |
||||
|
void setHidden(bool hidden); |
||||
|
|
||||
|
void mergeFormat(const Format &modifier); |
||||
|
bool isValid() const; |
||||
|
bool isEmpty() const; |
||||
|
|
||||
|
bool operator == (const Format &format) const; |
||||
|
bool operator != (const Format &format) const; |
||||
|
|
||||
|
QVariant property(int propertyId, const QVariant &defaultValue=QVariant()) const; |
||||
|
void setProperty(int propertyId, const QVariant &value, const QVariant &clearValue=QVariant(), bool detach=true); |
||||
|
void clearProperty(int propertyId); |
||||
|
bool hasProperty(int propertyId) const; |
||||
|
|
||||
|
bool boolProperty(int propertyId, bool defaultValue=false) const; |
||||
|
int intProperty(int propertyId, int defaultValue=0) const; |
||||
|
double doubleProperty(int propertyId, double defaultValue = 0.0) const; |
||||
|
QString stringProperty(int propertyId, const QString &defaultValue = QString()) const; |
||||
|
QColor colorProperty(int propertyId, const QColor &defaultValue = QColor()) const; |
||||
|
|
||||
|
bool hasNumFmtData() const; |
||||
|
bool hasFontData() const; |
||||
|
bool hasFillData() const; |
||||
|
bool hasBorderData() const; |
||||
|
bool hasAlignmentData() const; |
||||
|
bool hasProtectionData() const; |
||||
|
|
||||
|
bool fontIndexValid() const; |
||||
|
int fontIndex() const; |
||||
|
QByteArray fontKey() const; |
||||
|
bool borderIndexValid() const; |
||||
|
QByteArray borderKey() const; |
||||
|
int borderIndex() const; |
||||
|
bool fillIndexValid() const; |
||||
|
QByteArray fillKey() const; |
||||
|
int fillIndex() const; |
||||
|
|
||||
|
QByteArray formatKey() const; |
||||
|
bool xfIndexValid() const; |
||||
|
int xfIndex() const; |
||||
|
bool dxfIndexValid() const; |
||||
|
int dxfIndex() const; |
||||
|
|
||||
|
void fixNumberFormat(int id, const QString &format); |
||||
|
void setFontIndex(int index); |
||||
|
void setBorderIndex(int index); |
||||
|
void setFillIndex(int index); |
||||
|
void setXfIndex(int index); |
||||
|
void setDxfIndex(int index); |
||||
|
private: |
||||
|
friend class Styles; |
||||
|
friend class ::FormatTest; |
||||
|
friend QDebug operator<<(QDebug, const Format &f); |
||||
|
|
||||
|
int theme() const; |
||||
|
|
||||
|
QExplicitlySharedDataPointer<FormatPrivate> d; |
||||
|
}; |
||||
|
|
||||
|
#ifndef QT_NO_DEBUG_STREAM |
||||
|
QDebug operator<<(QDebug dbg, const Format &f); |
||||
|
#endif |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
|
||||
|
#endif // QXLSX_FORMAT_H
|
@ -0,0 +1,130 @@ |
|||||
|
// xlsxformat_p.h
|
||||
|
#ifndef XLSXFORMAT_P_H |
||||
|
#define XLSXFORMAT_P_H |
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QSharedData> |
||||
|
#include <QMap> |
||||
|
#include <QSet> |
||||
|
|
||||
|
#include "xlsxformat.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class FormatPrivate : public QSharedData |
||||
|
{ |
||||
|
public: |
||||
|
enum FormatType |
||||
|
{ |
||||
|
FT_Invalid = 0, |
||||
|
FT_NumFmt = 0x01, |
||||
|
FT_Font = 0x02, |
||||
|
FT_Alignment = 0x04, |
||||
|
FT_Border = 0x08, |
||||
|
FT_Fill = 0x10, |
||||
|
FT_Protection = 0x20 |
||||
|
}; |
||||
|
|
||||
|
enum Property { |
||||
|
P_STARTID, |
||||
|
|
||||
|
//numFmt
|
||||
|
P_NumFmt_Id, |
||||
|
P_NumFmt_FormatCode, |
||||
|
|
||||
|
//font
|
||||
|
P_Font_STARTID, |
||||
|
P_Font_Size = P_Font_STARTID, |
||||
|
P_Font_Italic, |
||||
|
P_Font_StrikeOut, |
||||
|
P_Font_Color, |
||||
|
P_Font_Bold, |
||||
|
P_Font_Script, |
||||
|
P_Font_Underline, |
||||
|
P_Font_Outline, |
||||
|
P_Font_Shadow, |
||||
|
P_Font_Name, |
||||
|
P_Font_Family, |
||||
|
P_Font_Charset, |
||||
|
P_Font_Scheme, |
||||
|
P_Font_Condense, |
||||
|
P_Font_Extend, |
||||
|
P_Font_ENDID, |
||||
|
|
||||
|
//border
|
||||
|
P_Border_STARTID, |
||||
|
P_Border_LeftStyle = P_Border_STARTID, |
||||
|
P_Border_RightStyle, |
||||
|
P_Border_TopStyle, |
||||
|
P_Border_BottomStyle, |
||||
|
P_Border_DiagonalStyle, |
||||
|
P_Border_LeftColor, |
||||
|
P_Border_RightColor, |
||||
|
P_Border_TopColor, |
||||
|
P_Border_BottomColor, |
||||
|
P_Border_DiagonalColor, |
||||
|
P_Border_DiagonalType, |
||||
|
P_Border_ENDID, |
||||
|
|
||||
|
//fill
|
||||
|
P_Fill_STARTID, |
||||
|
P_Fill_Pattern = P_Fill_STARTID, |
||||
|
P_Fill_BgColor, |
||||
|
P_Fill_FgColor, |
||||
|
P_Fill_ENDID, |
||||
|
|
||||
|
//alignment
|
||||
|
P_Alignment_STARTID, |
||||
|
P_Alignment_AlignH = P_Alignment_STARTID, |
||||
|
P_Alignment_AlignV, |
||||
|
P_Alignment_Wrap, |
||||
|
P_Alignment_Rotation, |
||||
|
P_Alignment_Indent, |
||||
|
P_Alignment_ShinkToFit, |
||||
|
P_Alignment_ENDID, |
||||
|
|
||||
|
//protection
|
||||
|
P_Protection_Locked, |
||||
|
P_Protection_Hidden, |
||||
|
|
||||
|
P_ENDID |
||||
|
}; |
||||
|
|
||||
|
FormatPrivate(); |
||||
|
FormatPrivate(const FormatPrivate &other); |
||||
|
~FormatPrivate(); |
||||
|
|
||||
|
bool dirty; //The key re-generation is need.
|
||||
|
QByteArray formatKey; |
||||
|
|
||||
|
bool font_dirty; |
||||
|
bool font_index_valid; |
||||
|
QByteArray font_key; |
||||
|
int font_index; |
||||
|
|
||||
|
bool fill_dirty; |
||||
|
bool fill_index_valid; |
||||
|
QByteArray fill_key; |
||||
|
int fill_index; |
||||
|
|
||||
|
bool border_dirty; |
||||
|
bool border_index_valid; |
||||
|
QByteArray border_key; |
||||
|
int border_index; |
||||
|
|
||||
|
int xf_index; |
||||
|
bool xf_indexValid; |
||||
|
|
||||
|
bool is_dxf_fomat; |
||||
|
int dxf_index; |
||||
|
bool dxf_indexValid; |
||||
|
|
||||
|
int theme; |
||||
|
|
||||
|
QMap<int, QVariant> properties; |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
|
||||
|
#endif |
@ -0,0 +1,33 @@ |
|||||
|
// xlsxglobal.h
|
||||
|
|
||||
|
#ifndef XLSXGLOBAL_H |
||||
|
#define XLSXGLOBAL_H |
||||
|
|
||||
|
#include <cstdio> |
||||
|
#include <string> |
||||
|
#include <iostream> |
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QObject> |
||||
|
#include <QString> |
||||
|
#include <QVariant> |
||||
|
#include <QIODevice> |
||||
|
#include <QByteArray> |
||||
|
#include <QStringList> |
||||
|
|
||||
|
#if defined(QXlsx_SHAREDLIB) |
||||
|
#if defined(QXlsx_EXPORTS) |
||||
|
# define QXLSX_EXPORT Q_DECL_EXPORT |
||||
|
#else |
||||
|
# define QXLSX_EXPORT Q_DECL_IMPORT |
||||
|
#endif |
||||
|
#else |
||||
|
# define QXLSX_EXPORT |
||||
|
#endif |
||||
|
|
||||
|
#define QT_BEGIN_NAMESPACE_XLSX namespace QXlsx { |
||||
|
#define QT_END_NAMESPACE_XLSX } |
||||
|
|
||||
|
#define QXLSX_USE_NAMESPACE using namespace QXlsx; |
||||
|
|
||||
|
#endif // XLSXGLOBAL_H
|
@ -0,0 +1,46 @@ |
|||||
|
// xlsxmediafile_p.h
|
||||
|
|
||||
|
#ifndef QXLSX_XLSXMEDIAFILE_H |
||||
|
#define QXLSX_XLSXMEDIAFILE_H |
||||
|
|
||||
|
#include "xlsxglobal.h" |
||||
|
|
||||
|
#include <QString> |
||||
|
#include <QByteArray> |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class MediaFile |
||||
|
{ |
||||
|
public: |
||||
|
MediaFile(const QString &fileName); |
||||
|
MediaFile(const QByteArray &bytes, const QString &suffix, const QString &mimeType=QString()); |
||||
|
|
||||
|
public: |
||||
|
void set(const QByteArray &bytes, const QString &suffix, const QString &mimeType=QString()); |
||||
|
QString suffix() const; |
||||
|
QString mimeType() const; |
||||
|
QByteArray contents() const; |
||||
|
|
||||
|
bool isIndexValid() const; |
||||
|
int index() const; |
||||
|
void setIndex(int idx); |
||||
|
QByteArray hashKey() const; |
||||
|
|
||||
|
void setFileName(const QString &name); |
||||
|
QString fileName() const; |
||||
|
|
||||
|
protected: |
||||
|
QString m_fileName; |
||||
|
QByteArray m_contents; |
||||
|
QString m_suffix; |
||||
|
QString m_mimeType; |
||||
|
|
||||
|
int m_index; |
||||
|
bool m_indexValid; |
||||
|
QByteArray m_hashKey; |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
|
||||
|
#endif // QXLSX_XLSXMEDIAFILE_H
|
@ -0,0 +1,51 @@ |
|||||
|
/****************************************************************************
|
||||
|
** 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_NUMFORMATPARSER_H |
||||
|
#define QXLSX_NUMFORMATPARSER_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" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class NumFormatParser |
||||
|
{ |
||||
|
public: |
||||
|
static bool isDateTime(const QString &formatCode); |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
|
||||
|
#endif // QXLSX_NUMFORMATPARSER_H
|
@ -0,0 +1,89 @@ |
|||||
|
/****************************************************************************
|
||||
|
** 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 XLSXRELATIONSHIPS_H |
||||
|
#define XLSXRELATIONSHIPS_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 <QList> |
||||
|
#include <QString> |
||||
|
#include <QIODevice> |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
struct XlsxRelationship |
||||
|
{ |
||||
|
QString id; |
||||
|
QString type; |
||||
|
QString target; |
||||
|
QString targetMode; |
||||
|
}; |
||||
|
|
||||
|
class Relationships |
||||
|
{ |
||||
|
public: |
||||
|
Relationships(); |
||||
|
|
||||
|
QList<XlsxRelationship> documentRelationships(const QString &relativeType) const; |
||||
|
QList<XlsxRelationship> packageRelationships(const QString &relativeType) const; |
||||
|
QList<XlsxRelationship> msPackageRelationships(const QString &relativeType) const; |
||||
|
QList<XlsxRelationship> worksheetRelationships(const QString &relativeType) const; |
||||
|
|
||||
|
void addDocumentRelationship(const QString &relativeType, const QString &target); |
||||
|
void addPackageRelationship(const QString &relativeType, const QString &target); |
||||
|
void addMsPackageRelationship(const QString &relativeType, const QString &target); |
||||
|
void addWorksheetRelationship(const QString &relativeType, const QString &target, const QString &targetMode=QString()); |
||||
|
|
||||
|
void saveToXmlFile(QIODevice *device) const; |
||||
|
QByteArray saveToXmlData() const; |
||||
|
bool loadFromXmlFile(QIODevice *device); |
||||
|
bool loadFromXmlData(const QByteArray &data); |
||||
|
XlsxRelationship getRelationshipById(const QString &id) const; |
||||
|
|
||||
|
void clear(); |
||||
|
int count() const; |
||||
|
bool isEmpty() const; |
||||
|
|
||||
|
private: |
||||
|
QList<XlsxRelationship> relationships(const QString &type) const; |
||||
|
void addRelationship(const QString &type, const QString &target, const QString &targetMode=QString()); |
||||
|
|
||||
|
QList<XlsxRelationship> m_relationships; |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
|
||||
|
#endif // XLSXRELATIONSHIPS_H
|
@ -0,0 +1,89 @@ |
|||||
|
/****************************************************************************
|
||||
|
** 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 XLSXRICHSTRING_H |
||||
|
#define XLSXRICHSTRING_H |
||||
|
|
||||
|
#include "xlsxglobal.h" |
||||
|
#include "xlsxformat.h" |
||||
|
#include <QVariant> |
||||
|
#include <QStringList> |
||||
|
#include <QSharedDataPointer> |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
class RichStringPrivate; |
||||
|
class RichString; |
||||
|
// qHash is a friend, but we can't use default arguments for friends (§8.3.6.4)
|
||||
|
uint qHash(const RichString &rs, uint seed = 0) Q_DECL_NOTHROW; |
||||
|
|
||||
|
class QXLSX_EXPORT RichString |
||||
|
{ |
||||
|
public: |
||||
|
RichString(); |
||||
|
explicit RichString(const QString& text); |
||||
|
RichString(const RichString &other); |
||||
|
~RichString(); |
||||
|
|
||||
|
bool isRichString() const; |
||||
|
bool isNull() const; |
||||
|
bool isEmtpy() const; |
||||
|
QString toPlainString() const; |
||||
|
QString toHtml() const; |
||||
|
void setHtml(const QString &text); |
||||
|
|
||||
|
int fragmentCount() const; |
||||
|
void addFragment(const QString &text, const Format &format); |
||||
|
QString fragmentText(int index) const; |
||||
|
Format fragmentFormat(int index) const; |
||||
|
|
||||
|
operator QVariant() const; |
||||
|
|
||||
|
RichString &operator=(const RichString &other); |
||||
|
private: |
||||
|
friend uint qHash(const RichString &rs, uint seed) Q_DECL_NOTHROW; |
||||
|
friend bool operator==(const RichString &rs1, const RichString &rs2); |
||||
|
friend bool operator!=(const RichString &rs1, const RichString &rs2); |
||||
|
friend bool operator<(const RichString &rs1, const RichString &rs2); |
||||
|
friend QDebug operator<<(QDebug dbg, const RichString &rs); |
||||
|
|
||||
|
QSharedDataPointer<RichStringPrivate> d; |
||||
|
}; |
||||
|
|
||||
|
bool operator==(const RichString &rs1, const RichString &rs2); |
||||
|
bool operator!=(const RichString &rs1, const RichString &rs2); |
||||
|
bool operator<(const RichString &rs1, const RichString &rs2); |
||||
|
bool operator==(const RichString &rs1, const QString &rs2); |
||||
|
bool operator==(const QString &rs1, const RichString &rs2); |
||||
|
bool operator!=(const RichString &rs1, const QString &rs2); |
||||
|
bool operator!=(const QString &rs1, const RichString &rs2); |
||||
|
|
||||
|
#ifndef QT_NO_DEBUG_STREAM |
||||
|
QDebug operator<<(QDebug dbg, const RichString &rs); |
||||
|
#endif |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
|
||||
|
Q_DECLARE_METATYPE(QXlsx::RichString) |
||||
|
|
||||
|
#endif // XLSXRICHSTRING_H
|
@ -0,0 +1,60 @@ |
|||||
|
/****************************************************************************
|
||||
|
** 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 XLSXRICHSTRING_P_H |
||||
|
#define XLSXRICHSTRING_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 "xlsxrichstring.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class RichStringPrivate : public QSharedData |
||||
|
{ |
||||
|
public: |
||||
|
RichStringPrivate(); |
||||
|
RichStringPrivate(const RichStringPrivate &other); |
||||
|
~RichStringPrivate(); |
||||
|
|
||||
|
QByteArray idKey() const; |
||||
|
|
||||
|
QStringList fragmentTexts; |
||||
|
QList<Format> fragmentFormats; |
||||
|
QByteArray _idKey; |
||||
|
bool _dirty; |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
|
||||
|
#endif // XLSXRICHSTRING_P_H
|
@ -0,0 +1,98 @@ |
|||||
|
/****************************************************************************
|
||||
|
** 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 XLSXSHAREDSTRINGS_H |
||||
|
#define XLSXSHAREDSTRINGS_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 <QHash> |
||||
|
#include <QStringList> |
||||
|
#include <QIODevice> |
||||
|
#include <QXmlStreamReader> |
||||
|
#include <QXmlStreamWriter> |
||||
|
|
||||
|
#include "xlsxglobal.h" |
||||
|
#include "xlsxrichstring.h" |
||||
|
#include "xlsxabstractooxmlfile.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class XlsxSharedStringInfo |
||||
|
{ |
||||
|
public: |
||||
|
XlsxSharedStringInfo(int index=0, int count = 1) : |
||||
|
index(index), count(count) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
int index; |
||||
|
int count; |
||||
|
}; |
||||
|
|
||||
|
class SharedStrings : public AbstractOOXmlFile |
||||
|
{ |
||||
|
public: |
||||
|
SharedStrings(CreateFlag flag); |
||||
|
int count() const; |
||||
|
bool isEmpty() const; |
||||
|
|
||||
|
int addSharedString(const QString &string); |
||||
|
int addSharedString(const RichString &string); |
||||
|
void removeSharedString(const QString &string); |
||||
|
void removeSharedString(const RichString &string); |
||||
|
void incRefByStringIndex(int idx); |
||||
|
|
||||
|
int getSharedStringIndex(const QString &string) const; |
||||
|
int getSharedStringIndex(const RichString &string) const; |
||||
|
RichString getSharedString(int index) const; |
||||
|
QList<RichString> getSharedStrings() const; |
||||
|
|
||||
|
void saveToXmlFile(QIODevice *device) const override; |
||||
|
bool loadFromXmlFile(QIODevice *device) override; |
||||
|
|
||||
|
private: |
||||
|
void readString(QXmlStreamReader &reader); // <si>
|
||||
|
void readRichStringPart(QXmlStreamReader &reader, RichString &rich); // <r>
|
||||
|
void readPlainStringPart(QXmlStreamReader &reader, RichString &rich); // <v>
|
||||
|
Format readRichStringPart_rPr(QXmlStreamReader &reader); |
||||
|
void writeRichStringPart_rPr(QXmlStreamWriter &writer, const Format &format) const; |
||||
|
|
||||
|
QHash<RichString, XlsxSharedStringInfo> m_stringTable; //for fast lookup
|
||||
|
QList<RichString> m_stringList; |
||||
|
int m_stringCount; |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
|
||||
|
#endif // XLSXSHAREDSTRINGS_H
|
@ -0,0 +1,60 @@ |
|||||
|
/****************************************************************************
|
||||
|
** 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 XLSXSIMPLEOOXMLFILE_H |
||||
|
#define XLSXSIMPLEOOXMLFILE_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 "xlsxabstractooxmlfile.h" |
||||
|
|
||||
|
#include <QString> |
||||
|
#include <QIODevice> |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class SimpleOOXmlFile : public AbstractOOXmlFile |
||||
|
{ |
||||
|
public: |
||||
|
SimpleOOXmlFile(CreateFlag flag); |
||||
|
|
||||
|
void saveToXmlFile(QIODevice *device) const override; |
||||
|
QByteArray saveToXmlData() const override; |
||||
|
bool loadFromXmlData(const QByteArray &data) override; |
||||
|
bool loadFromXmlFile(QIODevice *device) override; |
||||
|
|
||||
|
QByteArray xmlData; |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
|
||||
|
#endif // XLSXSIMPLEOOXMLFILE_H
|
@ -0,0 +1,143 @@ |
|||||
|
/****************************************************************************
|
||||
|
** 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 XLSXSTYLES_H |
||||
|
#define XLSXSTYLES_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 <QSharedPointer> |
||||
|
#include <QHash> |
||||
|
#include <QList> |
||||
|
#include <QMap> |
||||
|
#include <QStringList> |
||||
|
#include <QVector> |
||||
|
#include <QXmlStreamWriter> |
||||
|
#include <QXmlStreamReader> |
||||
|
#include <QIODevice> |
||||
|
|
||||
|
// class StylesTest;
|
||||
|
|
||||
|
#include "xlsxglobal.h" |
||||
|
#include "xlsxformat.h" |
||||
|
#include "xlsxabstractooxmlfile.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class Format; |
||||
|
class XlsxColor; |
||||
|
|
||||
|
struct XlsxFormatNumberData |
||||
|
{ |
||||
|
XlsxFormatNumberData() : formatIndex(0) {} |
||||
|
|
||||
|
int formatIndex; |
||||
|
QString formatString; |
||||
|
}; |
||||
|
|
||||
|
class Styles : public AbstractOOXmlFile |
||||
|
{ |
||||
|
public: |
||||
|
Styles(CreateFlag flag); |
||||
|
~Styles(); |
||||
|
void addXfFormat(const Format &format, bool force=false); |
||||
|
Format xfFormat(int idx) const; |
||||
|
void addDxfFormat(const Format &format, bool force=false); |
||||
|
Format dxfFormat(int idx) const; |
||||
|
|
||||
|
void saveToXmlFile(QIODevice *device) const override; |
||||
|
bool loadFromXmlFile(QIODevice *device) override; |
||||
|
|
||||
|
QColor getColorByIndex(int idx); |
||||
|
|
||||
|
private: |
||||
|
friend class Format; |
||||
|
// friend class ::StylesTest;
|
||||
|
|
||||
|
void fixNumFmt(const Format &format); |
||||
|
|
||||
|
void writeNumFmts(QXmlStreamWriter &writer) const; |
||||
|
void writeFonts(QXmlStreamWriter &writer) const; |
||||
|
void writeFont(QXmlStreamWriter &writer, const Format &font, bool isDxf = false) const; |
||||
|
void writeFills(QXmlStreamWriter &writer) const; |
||||
|
void writeFill(QXmlStreamWriter &writer, const Format &fill, bool isDxf = false) const; |
||||
|
void writeBorders(QXmlStreamWriter &writer) const; |
||||
|
void writeBorder(QXmlStreamWriter &writer, const Format &border, bool isDxf = false) const; |
||||
|
void writeSubBorder(QXmlStreamWriter &writer, const QString &type, int style, const XlsxColor &color) const; |
||||
|
void writeCellXfs(QXmlStreamWriter &writer) const; |
||||
|
void writeDxfs(QXmlStreamWriter &writer) const; |
||||
|
void writeDxf(QXmlStreamWriter &writer, const Format &format) const; |
||||
|
void writeColors(QXmlStreamWriter &writer) const; |
||||
|
|
||||
|
bool readNumFmts(QXmlStreamReader &reader); |
||||
|
bool readFonts(QXmlStreamReader &reader); |
||||
|
bool readFont(QXmlStreamReader &reader, Format &format); |
||||
|
bool readFills(QXmlStreamReader &reader); |
||||
|
bool readFill(QXmlStreamReader &reader, Format &format); |
||||
|
bool readBorders(QXmlStreamReader &reader); |
||||
|
bool readBorder(QXmlStreamReader &reader, Format &format); |
||||
|
bool readSubBorder(QXmlStreamReader &reader, const QString &name, Format::BorderStyle &style, XlsxColor &color); |
||||
|
bool readCellXfs(QXmlStreamReader &reader); |
||||
|
bool readDxfs(QXmlStreamReader &reader); |
||||
|
bool readDxf(QXmlStreamReader &reader); |
||||
|
bool readColors(QXmlStreamReader &reader); |
||||
|
bool readIndexedColors(QXmlStreamReader &reader); |
||||
|
|
||||
|
bool readCellStyleXfs(QXmlStreamReader &reader); |
||||
|
|
||||
|
QHash<QString, int> m_builtinNumFmtsHash; |
||||
|
QMap<int, QSharedPointer<XlsxFormatNumberData> > m_customNumFmtIdMap; |
||||
|
QHash<QString, QSharedPointer<XlsxFormatNumberData> > m_customNumFmtsHash; |
||||
|
int m_nextCustomNumFmtId; |
||||
|
QList<Format> m_fontsList; |
||||
|
QList<Format> m_fillsList; |
||||
|
QList<Format> m_bordersList; |
||||
|
QHash<QByteArray, Format> m_fontsHash; |
||||
|
QHash<QByteArray, Format> m_fillsHash; |
||||
|
QHash<QByteArray, Format> m_bordersHash; |
||||
|
|
||||
|
QVector<QColor> m_indexedColors; |
||||
|
bool m_isIndexedColorsDefault; |
||||
|
|
||||
|
QList<Format> m_xf_formatsList; |
||||
|
QHash<QByteArray, Format> m_xf_formatsHash; |
||||
|
|
||||
|
QList<Format> m_dxf_formatsList; |
||||
|
QHash<QByteArray, Format> m_dxf_formatsHash; |
||||
|
|
||||
|
bool m_emptyFormatAdded; |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
|
||||
|
#endif // XLSXSTYLES_H
|
@ -0,0 +1,29 @@ |
|||||
|
// xlsxtheme_p.h
|
||||
|
|
||||
|
#ifndef XLSXTHEME_H |
||||
|
#define XLSXTHEME_H |
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QString> |
||||
|
#include <QIODevice> |
||||
|
|
||||
|
#include "xlsxabstractooxmlfile.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class Theme : public AbstractOOXmlFile |
||||
|
{ |
||||
|
public: |
||||
|
Theme(CreateFlag flag); |
||||
|
|
||||
|
void saveToXmlFile(QIODevice *device) const override; |
||||
|
QByteArray saveToXmlData() const override; |
||||
|
bool loadFromXmlData(const QByteArray &data) override; |
||||
|
bool loadFromXmlFile(QIODevice *device) override; |
||||
|
|
||||
|
QByteArray xmlData; |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
|
||||
|
#endif // XLSXTHEME_H
|
@ -0,0 +1,42 @@ |
|||||
|
// xlsxutility_p.h
|
||||
|
|
||||
|
#ifndef XLSXUTILITY_H |
||||
|
#define XLSXUTILITY_H |
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QObject> |
||||
|
#include <QString> |
||||
|
#include <QPoint> |
||||
|
#include <QString> |
||||
|
#include <QStringList> |
||||
|
#include <QColor> |
||||
|
#include <QDateTime> |
||||
|
#include <QDate> |
||||
|
#include <QTime> |
||||
|
#include <QVariant> |
||||
|
|
||||
|
#include "xlsxglobal.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class CellReference; |
||||
|
|
||||
|
bool parseXsdBoolean(const QString &value, bool defaultValue=false); |
||||
|
|
||||
|
QStringList splitPath(const QString &path); |
||||
|
QString getRelFilePath(const QString &filePath); |
||||
|
|
||||
|
double datetimeToNumber(const QDateTime &dt, bool is1904=false); |
||||
|
QVariant datetimeFromNumber(double num, bool is1904=false); |
||||
|
double timeToNumber(const QTime &t); |
||||
|
|
||||
|
QString createSafeSheetName(const QString &nameProposal); |
||||
|
QString escapeSheetName(const QString &sheetName); |
||||
|
QString unescapeSheetName(const QString &sheetName); |
||||
|
|
||||
|
bool isSpaceReserveNeeded(const QString &string); |
||||
|
|
||||
|
QString convertSharedFormula(const QString &rootFormula, const CellReference &rootCell, const CellReference &cell); |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
#endif // XLSXUTILITY_H
|
@ -0,0 +1,95 @@ |
|||||
|
// xlsxworkbook.h
|
||||
|
|
||||
|
#ifndef XLSXWORKBOOK_H |
||||
|
#define XLSXWORKBOOK_H |
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QList> |
||||
|
#include <QImage> |
||||
|
#include <QSharedPointer> |
||||
|
#include <QIODevice> |
||||
|
|
||||
|
#include <memory> |
||||
|
|
||||
|
#include "xlsxglobal.h" |
||||
|
#include "xlsxabstractooxmlfile.h" |
||||
|
#include "xlsxabstractsheet.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class SharedStrings; |
||||
|
class Styles; |
||||
|
class Drawing; |
||||
|
class Document; |
||||
|
class Theme; |
||||
|
class Relationships; |
||||
|
class DocumentPrivate; |
||||
|
class MediaFile; |
||||
|
class Chart; |
||||
|
class Chartsheet; |
||||
|
class Worksheet; |
||||
|
class WorkbookPrivate; |
||||
|
|
||||
|
class QXLSX_EXPORT Workbook : public AbstractOOXmlFile |
||||
|
{ |
||||
|
Q_DECLARE_PRIVATE(Workbook) |
||||
|
public: |
||||
|
~Workbook(); |
||||
|
|
||||
|
int sheetCount() const; |
||||
|
AbstractSheet *sheet(int index) const; |
||||
|
|
||||
|
AbstractSheet *addSheet(const QString &name = QString(), AbstractSheet::SheetType type = AbstractSheet::ST_WorkSheet); |
||||
|
AbstractSheet *insertSheet(int index, const QString &name = QString(), AbstractSheet::SheetType type = AbstractSheet::ST_WorkSheet); |
||||
|
bool renameSheet(int index, const QString &name); |
||||
|
bool deleteSheet(int index); |
||||
|
bool copySheet(int index, const QString &newName=QString()); |
||||
|
bool moveSheet(int srcIndex, int distIndex); |
||||
|
|
||||
|
AbstractSheet *activeSheet() const; |
||||
|
bool setActiveSheet(int index); |
||||
|
|
||||
|
// void addChart();
|
||||
|
bool defineName(const QString &name, const QString &formula, const QString &comment=QString(), const QString &scope=QString()); |
||||
|
bool isDate1904() const; |
||||
|
void setDate1904(bool date1904); |
||||
|
bool isStringsToNumbersEnabled() const; |
||||
|
void setStringsToNumbersEnabled(bool enable=true); |
||||
|
bool isStringsToHyperlinksEnabled() const; |
||||
|
void setStringsToHyperlinksEnabled(bool enable=true); |
||||
|
bool isHtmlToRichStringEnabled() const; |
||||
|
void setHtmlToRichStringEnabled(bool enable=true); |
||||
|
QString defaultDateFormat() const; |
||||
|
void setDefaultDateFormat(const QString &format); |
||||
|
|
||||
|
//internal used member
|
||||
|
void addMediaFile(std::shared_ptr<MediaFile> media, bool force=false); |
||||
|
QList<std::shared_ptr<MediaFile> > mediaFiles() const; |
||||
|
void addChartFile(QSharedPointer<Chart> chartFile); |
||||
|
QList<QSharedPointer<Chart> > chartFiles() const; |
||||
|
|
||||
|
private: |
||||
|
friend class Worksheet; |
||||
|
friend class Chartsheet; |
||||
|
friend class WorksheetPrivate; |
||||
|
friend class Document; |
||||
|
friend class DocumentPrivate; |
||||
|
|
||||
|
Workbook(Workbook::CreateFlag flag); |
||||
|
|
||||
|
void saveToXmlFile(QIODevice *device) const override; |
||||
|
bool loadFromXmlFile(QIODevice *device) override; |
||||
|
|
||||
|
SharedStrings *sharedStrings() const; |
||||
|
Styles *styles(); |
||||
|
Theme *theme(); |
||||
|
QList<QImage> images(); |
||||
|
QList<Drawing *> drawings(); |
||||
|
QList<QSharedPointer<AbstractSheet> > getSheetsByTypes(AbstractSheet::SheetType type) const; |
||||
|
QStringList worksheetNames() const; |
||||
|
AbstractSheet *addSheet(const QString &name, int sheetId, AbstractSheet::SheetType type = AbstractSheet::ST_WorkSheet); |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
|
||||
|
#endif // XLSXWORKBOOK_H
|
@ -0,0 +1,74 @@ |
|||||
|
// xlsxworkbook_p.h
|
||||
|
|
||||
|
#ifndef XLSXWORKBOOK_P_H |
||||
|
#define XLSXWORKBOOK_P_H |
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QSharedPointer> |
||||
|
#include <QStringList> |
||||
|
|
||||
|
#include "xlsxworkbook.h" |
||||
|
#include "xlsxabstractooxmlfile_p.h" |
||||
|
#include "xlsxtheme_p.h" |
||||
|
#include "xlsxsimpleooxmlfile_p.h" |
||||
|
#include "xlsxrelationships_p.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
struct XlsxDefineNameData |
||||
|
{ |
||||
|
XlsxDefineNameData() |
||||
|
:sheetId(-1) |
||||
|
{} |
||||
|
XlsxDefineNameData(const QString &name, const QString &formula, const QString &comment, int sheetId=-1) |
||||
|
:name(name), formula(formula), comment(comment), sheetId(sheetId) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
QString name; |
||||
|
QString formula; |
||||
|
QString comment; |
||||
|
//using internal sheetId, instead of the localSheetId(order in the workbook)
|
||||
|
int sheetId; |
||||
|
}; |
||||
|
|
||||
|
class WorkbookPrivate : public AbstractOOXmlFilePrivate |
||||
|
{ |
||||
|
Q_DECLARE_PUBLIC(Workbook) |
||||
|
public: |
||||
|
WorkbookPrivate(Workbook *q, Workbook::CreateFlag flag); |
||||
|
|
||||
|
QSharedPointer<SharedStrings> sharedStrings; |
||||
|
QList<QSharedPointer<AbstractSheet> > sheets; |
||||
|
QList<QSharedPointer<SimpleOOXmlFile> > externalLinks; |
||||
|
QStringList sheetNames; |
||||
|
QSharedPointer<Styles> styles; |
||||
|
QSharedPointer<Theme> theme; |
||||
|
QList<std::shared_ptr<MediaFile> > mediaFiles; |
||||
|
QList<QSharedPointer<Chart> > chartFiles; |
||||
|
QList<XlsxDefineNameData> definedNamesList; |
||||
|
|
||||
|
bool strings_to_numbers_enabled; |
||||
|
bool strings_to_hyperlinks_enabled; |
||||
|
bool html_to_richstring_enabled; |
||||
|
bool date1904; |
||||
|
QString defaultDateFormat; |
||||
|
|
||||
|
int x_window; |
||||
|
int y_window; |
||||
|
int window_width; |
||||
|
int window_height; |
||||
|
|
||||
|
int activesheetIndex; |
||||
|
int firstsheet; |
||||
|
int table_count; |
||||
|
|
||||
|
//Used to generate new sheet name and id
|
||||
|
int last_worksheet_index; |
||||
|
int last_chartsheet_index; |
||||
|
int last_sheet_id; |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
|
||||
|
#endif // XLSXWORKBOOK_P_H
|
@ -0,0 +1,164 @@ |
|||||
|
// xlsxworksheet.h
|
||||
|
|
||||
|
#ifndef XLSXWORKSHEET_H |
||||
|
#define XLSXWORKSHEET_H |
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QObject> |
||||
|
#include <QStringList> |
||||
|
#include <QMap> |
||||
|
#include <QVariant> |
||||
|
#include <QPointF> |
||||
|
#include <QIODevice> |
||||
|
#include <QDateTime> |
||||
|
#include <QUrl> |
||||
|
#include <QImage> |
||||
|
|
||||
|
#include "xlsxabstractsheet.h" |
||||
|
#include "xlsxcell.h" |
||||
|
#include "xlsxcellrange.h" |
||||
|
#include "xlsxcellreference.h" |
||||
|
#include "xlsxcelllocation.h" |
||||
|
|
||||
|
class WorksheetTest; |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class DocumentPrivate; |
||||
|
class Workbook; |
||||
|
class Format; |
||||
|
class Drawing; |
||||
|
class DataValidation; |
||||
|
class ConditionalFormatting; |
||||
|
class CellRange; |
||||
|
class RichString; |
||||
|
class Relationships; |
||||
|
class Chart; |
||||
|
|
||||
|
class WorksheetPrivate; |
||||
|
class QXLSX_EXPORT Worksheet : public AbstractSheet |
||||
|
{ |
||||
|
Q_DECLARE_PRIVATE(Worksheet) |
||||
|
|
||||
|
private: |
||||
|
friend class DocumentPrivate; |
||||
|
friend class Workbook; |
||||
|
friend class ::WorksheetTest; |
||||
|
Worksheet(const QString &sheetName, int sheetId, Workbook *book, CreateFlag flag); |
||||
|
Worksheet *copy(const QString &distName, int distId) const override; |
||||
|
|
||||
|
public: |
||||
|
~Worksheet(); |
||||
|
|
||||
|
public: |
||||
|
bool write(const CellReference &row_column, const QVariant &value, const Format &format=Format()); |
||||
|
bool write(int row, int column, const QVariant &value, const Format &format=Format()); |
||||
|
|
||||
|
QVariant read(const CellReference &row_column) const; |
||||
|
QVariant read(int row, int column) const; |
||||
|
|
||||
|
bool writeString(const CellReference &row_column, const QString &value, const Format &format=Format()); |
||||
|
bool writeString(int row, int column, const QString &value, const Format &format=Format()); |
||||
|
bool writeString(const CellReference &row_column, const RichString &value, const Format &format=Format()); |
||||
|
bool writeString(int row, int column, const RichString &value, const Format &format=Format()); |
||||
|
|
||||
|
bool writeInlineString(const CellReference &row_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(int row, int column, double value, const Format &format=Format()); |
||||
|
|
||||
|
bool writeFormula(const CellReference &row_column, const CellFormula &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 writeBlank(const CellReference &row_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(int row, int column, bool value, const Format &format=Format()); |
||||
|
|
||||
|
bool writeDateTime(const CellReference &row_column, const QDateTime& dt, const Format &format=Format()); |
||||
|
bool writeDateTime(int row, int column, const QDateTime& dt, const Format &format=Format()); |
||||
|
|
||||
|
// dev67
|
||||
|
bool writeDate(const CellReference &row_column, const QDate& dt, const Format &format=Format()); |
||||
|
bool writeDate(int row, int column, const QDate& dt, const Format &format=Format()); |
||||
|
|
||||
|
bool writeTime(const CellReference &row_column, const QTime& t, const Format &format=Format()); |
||||
|
bool writeTime(int row, int column, const QTime& t, const Format &format=Format()); |
||||
|
|
||||
|
bool writeHyperlink(const CellReference &row_column, const QUrl &url, const Format &format=Format(), const QString &display=QString(), const QString &tip=QString()); |
||||
|
bool writeHyperlink(int row, int column, const QUrl &url, const Format &format=Format(), const QString &display=QString(), const QString &tip=QString()); |
||||
|
|
||||
|
bool addDataValidation(const DataValidation &validation); |
||||
|
bool addConditionalFormatting(const ConditionalFormatting &cf); |
||||
|
|
||||
|
Cell *cellAt(const CellReference &row_column) const; |
||||
|
Cell *cellAt(int row, int column) const; |
||||
|
|
||||
|
int insertImage(int row, int column, const QImage &image); |
||||
|
bool getImage(int imageIndex, QImage& img); |
||||
|
bool getImage(int row, int column, QImage& img); |
||||
|
uint getImageCount(); |
||||
|
|
||||
|
Chart *insertChart(int row, int column, const QSize &size); |
||||
|
|
||||
|
bool mergeCells(const CellRange &range, const Format &format=Format()); |
||||
|
bool unmergeCells(const CellRange &range); |
||||
|
QList<CellRange> mergedCells() const; |
||||
|
|
||||
|
bool setColumnWidth(const CellRange& range, double width); |
||||
|
bool setColumnFormat(const CellRange& range, const Format &format); |
||||
|
bool setColumnHidden(const CellRange& range, bool hidden); |
||||
|
bool setColumnWidth(int colFirst, int colLast, double width); |
||||
|
bool setColumnFormat(int colFirst, int colLast, const Format &format); |
||||
|
bool setColumnHidden(int colFirst, int colLast, bool hidden); |
||||
|
|
||||
|
double columnWidth(int column); |
||||
|
Format columnFormat(int column); |
||||
|
bool isColumnHidden(int column); |
||||
|
|
||||
|
bool setRowHeight(int rowFirst,int rowLast, double height); |
||||
|
bool setRowFormat(int rowFirst,int rowLast, const Format &format); |
||||
|
bool setRowHidden(int rowFirst,int rowLast, bool hidden); |
||||
|
|
||||
|
double rowHeight(int row); |
||||
|
Format rowFormat(int row); |
||||
|
bool isRowHidden(int row); |
||||
|
|
||||
|
bool groupRows(int rowFirst, int rowLast, bool collapsed = true); |
||||
|
bool groupColumns(int colFirst, int colLast, bool collapsed = true); |
||||
|
bool groupColumns(const CellRange &range, bool collapsed = true); |
||||
|
CellRange dimension() const; |
||||
|
|
||||
|
bool isWindowProtected() const; |
||||
|
void setWindowProtected(bool protect); |
||||
|
bool isFormulasVisible() const; |
||||
|
void setFormulasVisible(bool visible); |
||||
|
bool isGridLinesVisible() const; |
||||
|
void setGridLinesVisible(bool visible); |
||||
|
bool isRowColumnHeadersVisible() const; |
||||
|
void setRowColumnHeadersVisible(bool visible); |
||||
|
bool isZerosVisible() const; |
||||
|
void setZerosVisible(bool visible); |
||||
|
bool isRightToLeft() const; |
||||
|
void setRightToLeft(bool enable); |
||||
|
bool isSelected() const; |
||||
|
void setSelected(bool select); |
||||
|
bool isRulerVisible() const; |
||||
|
void setRulerVisible(bool visible); |
||||
|
bool isOutlineSymbolsVisible() const; |
||||
|
void setOutlineSymbolsVisible(bool visible); |
||||
|
bool isWhiteSpaceVisible() const; |
||||
|
void setWhiteSpaceVisible(bool visible); |
||||
|
bool setStartPage(int spagen); //add by liufeijin20181028
|
||||
|
|
||||
|
QVector<CellLocation> getFullCells(int* maxRow, int* maxCol); |
||||
|
|
||||
|
private: |
||||
|
void saveToXmlFile(QIODevice *device) const override; |
||||
|
bool loadFromXmlFile(QIODevice *device) override; |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
#endif // XLSXWORKSHEET_H
|
@ -0,0 +1,252 @@ |
|||||
|
// xlsxworksheet_p.h
|
||||
|
|
||||
|
#ifndef XLSXWORKSHEET_P_H |
||||
|
#define XLSXWORKSHEET_P_H |
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QObject> |
||||
|
#include <QString> |
||||
|
#include <QVector> |
||||
|
#include <QImage> |
||||
|
#include <QSharedPointer> |
||||
|
|
||||
|
#include <QRegularExpression> |
||||
|
|
||||
|
#include "xlsxworksheet.h" |
||||
|
#include "xlsxabstractsheet_p.h" |
||||
|
#include "xlsxcell.h" |
||||
|
#include "xlsxdatavalidation.h" |
||||
|
#include "xlsxconditionalformatting.h" |
||||
|
#include "xlsxcellformula.h" |
||||
|
|
||||
|
class QXmlStreamWriter; |
||||
|
class QXmlStreamReader; |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
const int XLSX_ROW_MAX = 1048576; |
||||
|
const int XLSX_COLUMN_MAX = 16384; |
||||
|
const int XLSX_STRING_MAX = 32767; |
||||
|
|
||||
|
class SharedStrings; |
||||
|
|
||||
|
struct XlsxHyperlinkData |
||||
|
{ |
||||
|
enum LinkType |
||||
|
{ |
||||
|
External, |
||||
|
Internal |
||||
|
}; |
||||
|
|
||||
|
XlsxHyperlinkData(LinkType linkType=External, const QString &target=QString(), const QString &location=QString() |
||||
|
, const QString &display=QString(), const QString &tip=QString()) |
||||
|
:linkType(linkType), target(target), location(location), display(display), tooltip(tip) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
LinkType linkType; |
||||
|
QString target; //For External link
|
||||
|
QString location; |
||||
|
QString display; |
||||
|
QString tooltip; |
||||
|
}; |
||||
|
|
||||
|
// ECMA-376 Part1 18.3.1.81
|
||||
|
struct XlsxSheetFormatProps |
||||
|
{ |
||||
|
XlsxSheetFormatProps(int baseColWidth = 8, |
||||
|
bool customHeight = false, |
||||
|
double defaultColWidth = 8.430f, // https://learn.microsoft.com/en-us/office/troubleshoot/excel/determine-column-widths
|
||||
|
double defaultRowHeight = 15, |
||||
|
quint8 outlineLevelCol = 0, |
||||
|
quint8 outlineLevelRow = 0, |
||||
|
bool thickBottom = false, |
||||
|
bool thickTop = false, |
||||
|
bool zeroHeight = false) : |
||||
|
baseColWidth(baseColWidth), |
||||
|
customHeight(customHeight), |
||||
|
defaultColWidth(defaultColWidth), |
||||
|
defaultRowHeight(defaultRowHeight), |
||||
|
outlineLevelCol(outlineLevelCol), |
||||
|
outlineLevelRow(outlineLevelRow), |
||||
|
thickBottom(thickBottom), |
||||
|
thickTop(thickTop), |
||||
|
zeroHeight(zeroHeight) { |
||||
|
} |
||||
|
|
||||
|
int baseColWidth; |
||||
|
bool customHeight; |
||||
|
double defaultColWidth; |
||||
|
double defaultRowHeight; |
||||
|
quint8 outlineLevelCol; |
||||
|
quint8 outlineLevelRow; |
||||
|
bool thickBottom; |
||||
|
bool thickTop; |
||||
|
bool zeroHeight; |
||||
|
}; |
||||
|
|
||||
|
struct XlsxRowInfo |
||||
|
{ |
||||
|
XlsxRowInfo(double height=0, const Format &format=Format(), bool hidden=false) : |
||||
|
customHeight(false), height(height), format(format), hidden(hidden), outlineLevel(0) |
||||
|
, collapsed(false) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
bool customHeight; |
||||
|
double height; |
||||
|
Format format; |
||||
|
bool hidden; |
||||
|
int outlineLevel; |
||||
|
bool collapsed; |
||||
|
}; |
||||
|
|
||||
|
struct XlsxColumnInfo |
||||
|
{ |
||||
|
XlsxColumnInfo( int firstColumn, // = 0,
|
||||
|
int lastColumn, // = 1,
|
||||
|
bool isSetWidth, |
||||
|
double width = 0, |
||||
|
const Format &format = Format(), |
||||
|
bool hidden = false) |
||||
|
: width(width), |
||||
|
format(format), |
||||
|
firstColumn(firstColumn), |
||||
|
lastColumn(lastColumn), |
||||
|
outlineLevel(0), |
||||
|
isSetWidth(isSetWidth), |
||||
|
customWidth(false), |
||||
|
hidden(hidden), |
||||
|
collapsed(false) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
double width; |
||||
|
Format format; |
||||
|
int firstColumn; |
||||
|
int lastColumn; |
||||
|
int outlineLevel; |
||||
|
bool isSetWidth; |
||||
|
bool customWidth; |
||||
|
bool hidden; |
||||
|
bool collapsed; |
||||
|
}; |
||||
|
|
||||
|
class WorksheetPrivate : public AbstractSheetPrivate |
||||
|
{ |
||||
|
Q_DECLARE_PUBLIC(Worksheet) |
||||
|
|
||||
|
public: |
||||
|
WorksheetPrivate(Worksheet *p, Worksheet::CreateFlag flag); |
||||
|
~WorksheetPrivate(); |
||||
|
|
||||
|
public: |
||||
|
int checkDimensions(int row, int col, bool ignore_row=false, bool ignore_col=false); |
||||
|
Format cellFormat(int row, int col) const; |
||||
|
QString generateDimensionString() const; |
||||
|
void calculateSpans() const; |
||||
|
void splitColsInfo(int colFirst, int colLast); |
||||
|
void validateDimension(); |
||||
|
|
||||
|
void saveXmlSheetData(QXmlStreamWriter &writer) const; |
||||
|
void saveXmlCellData(QXmlStreamWriter &writer, int row, int col, std::shared_ptr<Cell> cell) const; |
||||
|
void saveXmlMergeCells(QXmlStreamWriter &writer) const; |
||||
|
void saveXmlHyperlinks(QXmlStreamWriter &writer) const; |
||||
|
void saveXmlDrawings(QXmlStreamWriter &writer) const; |
||||
|
void saveXmlDataValidations(QXmlStreamWriter &writer) const; |
||||
|
|
||||
|
int rowPixelsSize(int row) const; |
||||
|
int colPixelsSize(int col) const; |
||||
|
|
||||
|
void loadXmlSheetData(QXmlStreamReader &reader); |
||||
|
void loadXmlColumnsInfo(QXmlStreamReader &reader); |
||||
|
void loadXmlMergeCells(QXmlStreamReader &reader); |
||||
|
void loadXmlDataValidations(QXmlStreamReader &reader); |
||||
|
void loadXmlSheetFormatProps(QXmlStreamReader &reader); |
||||
|
void loadXmlSheetViews(QXmlStreamReader &reader); |
||||
|
void loadXmlHyperlinks(QXmlStreamReader &reader); |
||||
|
|
||||
|
QList<QSharedPointer<XlsxRowInfo> > getRowInfoList(int rowFirst, int rowLast); |
||||
|
QList<QSharedPointer<XlsxColumnInfo> > getColumnInfoList(int colFirst, int colLast); |
||||
|
QList<int> getColumnIndexes(int colFirst, int colLast); |
||||
|
bool isColumnRangeValid(int colFirst, int colLast); |
||||
|
|
||||
|
SharedStrings *sharedStrings() const; |
||||
|
|
||||
|
public: |
||||
|
QMap<int, QMap<int, std::shared_ptr<Cell> > > cellTable; |
||||
|
|
||||
|
QMap<int, QMap<int, QString> > comments; |
||||
|
QMap<int, QMap<int, QSharedPointer<XlsxHyperlinkData> > > urlTable; |
||||
|
QList<CellRange> merges; |
||||
|
QMap<int, QSharedPointer<XlsxRowInfo> > rowsInfo; |
||||
|
QMap<int, QSharedPointer<XlsxColumnInfo> > colsInfo; |
||||
|
QMap<int, QSharedPointer<XlsxColumnInfo> > colsInfoHelper; |
||||
|
|
||||
|
QList<DataValidation> dataValidationsList; |
||||
|
QList<ConditionalFormatting> conditionalFormattingList; |
||||
|
|
||||
|
QMap<int, CellFormula> sharedFormulaMap; // shared formula map
|
||||
|
|
||||
|
CellRange dimension; |
||||
|
int previous_row; |
||||
|
|
||||
|
mutable QMap<int, QString> row_spans; |
||||
|
QMap<int, double> row_sizes; |
||||
|
QMap<int, double> col_sizes; |
||||
|
|
||||
|
int outline_row_level; |
||||
|
int outline_col_level; |
||||
|
|
||||
|
int default_row_height; |
||||
|
bool default_row_zeroed; |
||||
|
|
||||
|
// pagesetup and print settings add by liufeijin 20181028, liufeijin
|
||||
|
QString PpaperSize; |
||||
|
QString Pscale; |
||||
|
QString PfirstPageNumber; |
||||
|
QString Porientation; |
||||
|
QString PuseFirstPageNumber; |
||||
|
QString PhorizontalDpi; |
||||
|
QString PverticalDpi; |
||||
|
QString Prid; |
||||
|
QString Pcopies; |
||||
|
|
||||
|
// pageMargins, liufeijin
|
||||
|
QString PMheader; |
||||
|
QString PMfooter; |
||||
|
QString PMtop; |
||||
|
QString PMbotton; |
||||
|
QString PMleft; |
||||
|
QString PMright; |
||||
|
|
||||
|
// header footer, liufeijin
|
||||
|
QString MoodFooter; |
||||
|
QString ModdHeader; |
||||
|
QString MoodalignWithMargins; // add align 20190619
|
||||
|
|
||||
|
XlsxSheetFormatProps sheetFormatProps; |
||||
|
|
||||
|
bool windowProtection; |
||||
|
bool showFormulas; |
||||
|
bool showGridLines; |
||||
|
bool showRowColHeaders; |
||||
|
bool showZeros; |
||||
|
bool rightToLeft; |
||||
|
bool tabSelected; |
||||
|
bool showRuler; |
||||
|
bool showOutlineSymbols; |
||||
|
bool showWhiteSpace; |
||||
|
|
||||
|
QRegularExpression urlPattern; |
||||
|
|
||||
|
private: |
||||
|
|
||||
|
static double calculateColWidth(int characters); |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
#endif // XLSXWORKSHEET_P_H
|
@ -0,0 +1,37 @@ |
|||||
|
// xlsxzipreader_p.h
|
||||
|
|
||||
|
#ifndef QXLSX_XLSXZIPREADER_P_H |
||||
|
#define QXLSX_XLSXZIPREADER_P_H |
||||
|
|
||||
|
#include <QScopedPointer> |
||||
|
#include <QStringList> |
||||
|
#include <QIODevice> |
||||
|
|
||||
|
#include "xlsxglobal.h" |
||||
|
|
||||
|
#include <QVector> |
||||
|
|
||||
|
class QZipReader; |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class ZipReader |
||||
|
{ |
||||
|
public: |
||||
|
explicit ZipReader(const QString &fileName); |
||||
|
explicit ZipReader(QIODevice *device); |
||||
|
~ZipReader(); |
||||
|
bool exists() const; |
||||
|
QStringList filePaths() const; |
||||
|
QByteArray fileData(const QString &fileName) const; |
||||
|
|
||||
|
private: |
||||
|
Q_DISABLE_COPY(ZipReader) |
||||
|
void init(); |
||||
|
QScopedPointer<QZipReader> m_reader; |
||||
|
QStringList m_filePaths; |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
|
||||
|
#endif // QXLSX_XLSXZIPREADER_P_H
|
@ -0,0 +1,34 @@ |
|||||
|
// xlsxzipwriter_p.h
|
||||
|
|
||||
|
#ifndef QXLSX_ZIPWRITER_H |
||||
|
#define QXLSX_ZIPWRITER_H |
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QString> |
||||
|
#include <QIODevice> |
||||
|
|
||||
|
#include "xlsxglobal.h" |
||||
|
|
||||
|
class QZipWriter; |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
class ZipWriter |
||||
|
{ |
||||
|
public: |
||||
|
explicit ZipWriter(const QString &filePath); |
||||
|
explicit ZipWriter(QIODevice *device); |
||||
|
~ZipWriter(); |
||||
|
|
||||
|
void addFile(const QString &filePath, QIODevice *device); |
||||
|
void addFile(const QString &filePath, const QByteArray &data); |
||||
|
bool error() const; |
||||
|
void close(); |
||||
|
|
||||
|
private: |
||||
|
QZipWriter *m_writer; |
||||
|
}; |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
||||
|
|
||||
|
#endif // QXLSX_ZIPWRITER_H
|
@ -0,0 +1,12 @@ |
|||||
|
#ifndef XLSXREADER_H |
||||
|
#define XLSXREADER_H |
||||
|
#include <QList> |
||||
|
|
||||
|
class XlsxReader |
||||
|
{ |
||||
|
public: |
||||
|
XlsxReader(); |
||||
|
QList<QStringList> ReadeXlsx(QString pathOfXlsx); |
||||
|
}; |
||||
|
|
||||
|
#endif //XLSXREADER_H
|
@ -0,0 +1,23 @@ |
|||||
|
#ifndef XLSXXMLCONVERTER_H |
||||
|
#define XLSXXMLCONVERTER_H |
||||
|
#include <QString> |
||||
|
#include <QList> |
||||
|
|
||||
|
class XlsxXmlConverter |
||||
|
{ |
||||
|
private: |
||||
|
QString xlsxFilePath; |
||||
|
QString xmlPatternFilePath; |
||||
|
QString xmlOutPutFilePath; |
||||
|
QList<QStringList> xlsxData; |
||||
|
QList<QString> patternList; |
||||
|
|
||||
|
public: |
||||
|
XlsxXmlConverter(); |
||||
|
void initPath(QString xlsxPath, QString patternFilePath, QString outputFilePath); |
||||
|
void readXlsx(); |
||||
|
void readPattern(); |
||||
|
void wrtiteXMl(); |
||||
|
}; |
||||
|
|
||||
|
#endif //XLSXXMLCONVERTER_H
|
@ -0,0 +1,15 @@ |
|||||
|
#ifndef XMLGENERATOR_H |
||||
|
#define XMLGENERATOR_H |
||||
|
#include <QList> |
||||
|
|
||||
|
class XmlGenerator |
||||
|
{ |
||||
|
public: |
||||
|
XmlGenerator(); |
||||
|
void generateXML(QList<QStringList> inputList, |
||||
|
qint16 sheetCounter, |
||||
|
QList<QString> patternList, |
||||
|
QString outputPath); |
||||
|
}; |
||||
|
|
||||
|
#endif //XMLGENERATOR_H
|
@ -0,0 +1,12 @@ |
|||||
|
#ifndef XMLTEMPLATEREADER_H |
||||
|
#define XMLTEMPLATEREADER_H |
||||
|
#include <QList> |
||||
|
|
||||
|
class XmlTemplateReader |
||||
|
{ |
||||
|
public: |
||||
|
XmlTemplateReader(); |
||||
|
QList<QString> readxmlPattern(QString pathOfPattern); |
||||
|
}; |
||||
|
|
||||
|
#endif //XMLTEMPLATEREADER_H
|
@ -0,0 +1,15 @@ |
|||||
|
#include <QCoreApplication> |
||||
|
#include "include/XlsxXmlConverter.h" |
||||
|
|
||||
|
int main(int argc, char* argv[]) |
||||
|
{ |
||||
|
QCoreApplication a(argc, argv); |
||||
|
|
||||
|
XlsxXmlConverter convert; |
||||
|
convert.initPath("BPresetValue.xlsx", "Pattern.xml", ""); |
||||
|
convert.readXlsx(); |
||||
|
convert.readPattern(); |
||||
|
convert.wrtiteXMl(); |
||||
|
|
||||
|
return a.exec(); |
||||
|
} |
@ -0,0 +1,97 @@ |
|||||
|
//xlsxabstractooxmlfile.cpp
|
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QBuffer> |
||||
|
#include <QByteArray> |
||||
|
|
||||
|
#include "include/QXlsx/xlsxabstractooxmlfile.h" |
||||
|
#include "xlsxabstractooxmlfile_p.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
AbstractOOXmlFilePrivate::AbstractOOXmlFilePrivate(AbstractOOXmlFile* q, |
||||
|
AbstractOOXmlFile::CreateFlag flag = AbstractOOXmlFile::F_NewFromScratch) |
||||
|
: relationships(new Relationships), flag(flag), q_ptr(q) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
AbstractOOXmlFilePrivate::~AbstractOOXmlFilePrivate() |
||||
|
{ |
||||
|
if(relationships) |
||||
|
{ |
||||
|
delete relationships; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* \internal |
||||
|
* |
||||
|
* \class AbstractOOXmlFile |
||||
|
* |
||||
|
* Base class of all the ooxml part file. |
||||
|
*/ |
||||
|
|
||||
|
AbstractOOXmlFile::AbstractOOXmlFile(CreateFlag flag) |
||||
|
: d_ptr(new AbstractOOXmlFilePrivate(this, flag)) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
AbstractOOXmlFile::AbstractOOXmlFile(AbstractOOXmlFilePrivate* d) |
||||
|
: d_ptr(d) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
AbstractOOXmlFile::~AbstractOOXmlFile() |
||||
|
{ |
||||
|
delete d_ptr; |
||||
|
} |
||||
|
|
||||
|
QByteArray AbstractOOXmlFile::saveToXmlData() const |
||||
|
{ |
||||
|
QByteArray data; |
||||
|
QBuffer buffer(&data); |
||||
|
buffer.open(QIODevice::WriteOnly); |
||||
|
saveToXmlFile(&buffer); |
||||
|
|
||||
|
return data; |
||||
|
} |
||||
|
|
||||
|
bool AbstractOOXmlFile::loadFromXmlData(const QByteArray& data) |
||||
|
{ |
||||
|
QBuffer buffer; |
||||
|
buffer.setData(data); |
||||
|
buffer.open(QIODevice::ReadOnly); |
||||
|
|
||||
|
return loadFromXmlFile(&buffer); |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* \internal |
||||
|
*/ |
||||
|
void AbstractOOXmlFile::setFilePath(const QString path) |
||||
|
{ |
||||
|
Q_D(AbstractOOXmlFile); |
||||
|
d->filePathInPackage = path; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* \internal |
||||
|
*/ |
||||
|
QString AbstractOOXmlFile::filePath() const |
||||
|
{ |
||||
|
Q_D(const AbstractOOXmlFile); |
||||
|
|
||||
|
return d->filePathInPackage; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* \internal |
||||
|
*/ |
||||
|
Relationships* AbstractOOXmlFile::relationships() const |
||||
|
{ |
||||
|
Q_D(const AbstractOOXmlFile); |
||||
|
|
||||
|
return d->relationships; |
||||
|
} |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
@ -0,0 +1,186 @@ |
|||||
|
// xlsxabstractsheet.cpp
|
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
|
||||
|
#include "xlsxabstractsheet.h" |
||||
|
#include "xlsxabstractsheet_p.h" |
||||
|
#include "xlsxworkbook.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
AbstractSheetPrivate::AbstractSheetPrivate(AbstractSheet *p, AbstractSheet::CreateFlag flag) |
||||
|
: AbstractOOXmlFilePrivate(p, flag) |
||||
|
{ |
||||
|
type = AbstractSheet::ST_WorkSheet; |
||||
|
sheetState = AbstractSheet::SS_Visible; |
||||
|
} |
||||
|
|
||||
|
AbstractSheetPrivate::~AbstractSheetPrivate() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
\class AbstractSheet |
||||
|
\inmodule QtXlsx |
||||
|
\brief Base class for worksheet, chartsheet, etc. |
||||
|
*/ |
||||
|
|
||||
|
/*!
|
||||
|
\enum AbstractSheet::SheetType |
||||
|
|
||||
|
\value ST_WorkSheet |
||||
|
\value ST_ChartSheet |
||||
|
\omitvalue ST_DialogSheet |
||||
|
\omitvalue ST_MacroSheet |
||||
|
*/ |
||||
|
|
||||
|
/*!
|
||||
|
\enum AbstractSheet::SheetState |
||||
|
|
||||
|
\value SS_Visible |
||||
|
\value SS_Hidden |
||||
|
\value SS_VeryHidden User cann't make a veryHidden sheet visible in normal way. |
||||
|
*/ |
||||
|
|
||||
|
/*!
|
||||
|
\fn AbstractSheet::copy(const QString &distName, int distId) const |
||||
|
|
||||
|
Copies the current sheet to a sheet called \a distName with \a distId. |
||||
|
Returns the new sheet. |
||||
|
*/ |
||||
|
|
||||
|
/*!
|
||||
|
* \internal |
||||
|
*/ |
||||
|
AbstractSheet::AbstractSheet(const QString &name, int id, Workbook *workbook, AbstractSheetPrivate *d) : |
||||
|
AbstractOOXmlFile(d) |
||||
|
{ |
||||
|
d_func()->name = name; |
||||
|
d_func()->id = id; |
||||
|
d_func()->workbook = workbook; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/*!
|
||||
|
* Returns the name of the sheet. |
||||
|
*/ |
||||
|
QString AbstractSheet::sheetName() const |
||||
|
{ |
||||
|
Q_D(const AbstractSheet); |
||||
|
return d->name; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* \internal |
||||
|
*/ |
||||
|
void AbstractSheet::setSheetName(const QString &sheetName) |
||||
|
{ |
||||
|
Q_D(AbstractSheet); |
||||
|
d->name = sheetName; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* Returns the type of the sheet. |
||||
|
*/ |
||||
|
AbstractSheet::SheetType AbstractSheet::sheetType() const |
||||
|
{ |
||||
|
Q_D(const AbstractSheet); |
||||
|
return d->type; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* \internal |
||||
|
*/ |
||||
|
void AbstractSheet::setSheetType(SheetType type) |
||||
|
{ |
||||
|
Q_D(AbstractSheet); |
||||
|
d->type = type; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* Returns the state of the sheet. |
||||
|
* |
||||
|
* \sa isHidden(), isVisible(), setSheetState() |
||||
|
*/ |
||||
|
AbstractSheet::SheetState AbstractSheet::sheetState() const |
||||
|
{ |
||||
|
Q_D(const AbstractSheet); |
||||
|
return d->sheetState; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* Set the state of the sheet to \a state. |
||||
|
*/ |
||||
|
void AbstractSheet::setSheetState(SheetState state) |
||||
|
{ |
||||
|
Q_D(AbstractSheet); |
||||
|
d->sheetState = state; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* Returns true if the sheet is not visible, otherwise false will be returned. |
||||
|
* |
||||
|
* \sa sheetState(), setHidden() |
||||
|
*/ |
||||
|
bool AbstractSheet::isHidden() const |
||||
|
{ |
||||
|
Q_D(const AbstractSheet); |
||||
|
return d->sheetState != SS_Visible; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* Returns true if the sheet is visible. |
||||
|
*/ |
||||
|
bool AbstractSheet::isVisible() const |
||||
|
{ |
||||
|
return !isHidden(); |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* Make the sheet hiden or visible based on \a hidden. |
||||
|
*/ |
||||
|
void AbstractSheet::setHidden(bool hidden) |
||||
|
{ |
||||
|
Q_D(AbstractSheet); |
||||
|
if (hidden == isHidden()) |
||||
|
return; |
||||
|
|
||||
|
d->sheetState = hidden ? SS_Hidden : SS_Visible; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* Convenience function, equivalent to setHidden(! \a visible). |
||||
|
*/ |
||||
|
void AbstractSheet::setVisible(bool visible) |
||||
|
{ |
||||
|
setHidden(!visible); |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* \internal |
||||
|
*/ |
||||
|
int AbstractSheet::sheetId() const |
||||
|
{ |
||||
|
Q_D(const AbstractSheet); |
||||
|
return d->id; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* \internal |
||||
|
*/ |
||||
|
Drawing *AbstractSheet::drawing() const |
||||
|
{ |
||||
|
Q_D(const AbstractSheet); |
||||
|
return d->drawing.get(); |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* Return the workbook |
||||
|
*/ |
||||
|
Workbook *AbstractSheet::workbook() const |
||||
|
{ |
||||
|
Q_D(const AbstractSheet); |
||||
|
return d->workbook; |
||||
|
} |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
@ -0,0 +1,364 @@ |
|||||
|
// xlsxcell.cpp
|
||||
|
|
||||
|
#include <cmath> |
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QDebug> |
||||
|
#include <QDateTime> |
||||
|
#include <QDate> |
||||
|
#include <QTime> |
||||
|
|
||||
|
#include "xlsxcell.h" |
||||
|
#include "xlsxcell_p.h" |
||||
|
#include "xlsxformat.h" |
||||
|
#include "xlsxformat_p.h" |
||||
|
#include "xlsxutility_p.h" |
||||
|
#include "xlsxworksheet.h" |
||||
|
#include "xlsxworkbook.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
CellPrivate::CellPrivate(Cell *p) : |
||||
|
q_ptr(p) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
CellPrivate::CellPrivate(const CellPrivate * const cp) |
||||
|
: parent(cp->parent) |
||||
|
, cellType(cp->cellType) |
||||
|
, value(cp->value) |
||||
|
, formula(cp->formula) |
||||
|
, format(cp->format) |
||||
|
, richString(cp->richString) |
||||
|
, styleNumber(cp->styleNumber) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
\class Cell |
||||
|
\inmodule QtXlsx |
||||
|
\brief The Cell class provides a API that is used to handle the worksheet cell. |
||||
|
|
||||
|
*/ |
||||
|
|
||||
|
/*!
|
||||
|
\enum Cell::CellType |
||||
|
\value BooleanType Boolean type |
||||
|
\value NumberType Number type, can be blank or used with forumula |
||||
|
\value ErrorType Error type |
||||
|
\value SharedStringType Shared string type |
||||
|
\value StringType String type, can be used with forumula |
||||
|
\value InlineStringType Inline string type |
||||
|
*/ |
||||
|
|
||||
|
/*!
|
||||
|
* \internal |
||||
|
* Created by Worksheet only. |
||||
|
*/ |
||||
|
// qint32 styleIndex = (-1)
|
||||
|
Cell::Cell(const QVariant &data, |
||||
|
CellType type, |
||||
|
const Format &format, |
||||
|
Worksheet *parent, |
||||
|
qint32 styleIndex ) : |
||||
|
d_ptr(new CellPrivate(this)) |
||||
|
{ |
||||
|
d_ptr->value = data; |
||||
|
d_ptr->cellType = type; |
||||
|
d_ptr->format = format; |
||||
|
d_ptr->parent = parent; |
||||
|
d_ptr->styleNumber = styleIndex; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* \internal |
||||
|
*/ |
||||
|
Cell::Cell(const Cell * const cell): |
||||
|
d_ptr(new CellPrivate(cell->d_ptr)) |
||||
|
{ |
||||
|
d_ptr->q_ptr = this; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* Destroys the Cell and cleans up. |
||||
|
*/ |
||||
|
Cell::~Cell() |
||||
|
{ |
||||
|
if ( NULL != d_ptr ) |
||||
|
delete d_ptr; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* Return the dataType of this Cell |
||||
|
*/ |
||||
|
Cell::CellType Cell::cellType() const |
||||
|
{ |
||||
|
Q_D(const Cell); |
||||
|
|
||||
|
return d->cellType; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* Return the data content of this Cell |
||||
|
*/ |
||||
|
QVariant Cell::value() const |
||||
|
{ |
||||
|
Q_D(const Cell); |
||||
|
|
||||
|
return d->value; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* Return the data content of this Cell for reading |
||||
|
*/ |
||||
|
QVariant Cell::readValue() const |
||||
|
{ |
||||
|
Q_D(const Cell); |
||||
|
|
||||
|
QVariant ret; // return value
|
||||
|
ret = d->value; |
||||
|
|
||||
|
Format fmt = this->format(); |
||||
|
|
||||
|
if (isDateTime()) |
||||
|
{ |
||||
|
QVariant vDT = dateTime(); |
||||
|
if ( vDT.isNull() ) |
||||
|
{ |
||||
|
return QVariant(); |
||||
|
} |
||||
|
|
||||
|
// https://github.com/QtExcel/QXlsx/issues/171
|
||||
|
// https://www.qt.io/blog/whats-new-in-qmetatype-qvariant
|
||||
|
#if QT_VERSION >= 0x060000 // Qt 6.0 or over
|
||||
|
if ( vDT.metaType().id() == QMetaType::QDateTime ) |
||||
|
{ |
||||
|
ret = vDT; |
||||
|
} |
||||
|
else if ( vDT.metaType().id() == QMetaType::QDate ) |
||||
|
{ |
||||
|
ret = vDT; |
||||
|
} |
||||
|
else if ( vDT.metaType().id() == QMetaType::QTime ) |
||||
|
{ |
||||
|
ret = vDT; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
return QVariant(); |
||||
|
} |
||||
|
#else |
||||
|
if ( vDT.type() == QVariant::DateTime ) |
||||
|
{ |
||||
|
ret = vDT; |
||||
|
} |
||||
|
else if ( vDT.type() == QVariant::Date ) |
||||
|
{ |
||||
|
ret = vDT; |
||||
|
} |
||||
|
else if ( vDT.type() == QVariant::Time ) |
||||
|
{ |
||||
|
ret = vDT; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
return QVariant(); |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
// QDateTime dt = dateTime();
|
||||
|
// ret = dt;
|
||||
|
|
||||
|
// QString strFormat = fmt.numberFormat();
|
||||
|
// if (!strFormat.isEmpty())
|
||||
|
// {
|
||||
|
// // TODO: use number format
|
||||
|
// }
|
||||
|
|
||||
|
// qint32 styleNo = d->styleNumber;
|
||||
|
|
||||
|
// if (styleNo == 10)
|
||||
|
// {
|
||||
|
// }
|
||||
|
|
||||
|
// if (styleNo == 11)
|
||||
|
// {
|
||||
|
// QTime timeValue = dt.time(); // only time. (HH:mm:ss)
|
||||
|
// ret = timeValue;
|
||||
|
// return ret;
|
||||
|
// }
|
||||
|
|
||||
|
// if (styleNo == 12)
|
||||
|
// {
|
||||
|
// }
|
||||
|
|
||||
|
// if (styleNo == 13) // (HH:mm:ss)
|
||||
|
// {
|
||||
|
// double dValue = d->value.toDouble();
|
||||
|
// int day = int(dValue); // unit is day.
|
||||
|
// double deciamlPointValue1 = dValue - double(day);
|
||||
|
|
||||
|
// double dHour = deciamlPointValue1 * (double(1.0) / double(24.0));
|
||||
|
// int hour = int(dHour);
|
||||
|
|
||||
|
// double deciamlPointValue2 = deciamlPointValue1 - (double(hour) * (double(1.0) / double(24.0)));
|
||||
|
// double dMin = deciamlPointValue2 * (double(1.0) / double(60.0));
|
||||
|
// int min = int(dMin);
|
||||
|
|
||||
|
// double deciamlPointValue3 = deciamlPointValue2 - (double(min) * (double(1.0) / double(60.0)));
|
||||
|
// double dSec = deciamlPointValue3 * (double(1.0) / double(60.0));
|
||||
|
// int sec = int(dSec);
|
||||
|
|
||||
|
// int totalHour = hour + (day * 24);
|
||||
|
|
||||
|
// QString strTime;
|
||||
|
// strTime = QString("%1:%2:%3").arg(totalHour).arg(min).arg(sec);
|
||||
|
// ret = strTime;
|
||||
|
|
||||
|
// return ret;
|
||||
|
// }
|
||||
|
|
||||
|
// return ret;
|
||||
|
// */
|
||||
|
} |
||||
|
|
||||
|
if (hasFormula()) |
||||
|
{ |
||||
|
QString formulaString = this->formula().formulaText(); |
||||
|
ret = formulaString; |
||||
|
return ret; // return formula string
|
||||
|
} |
||||
|
|
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* Return the style used by this Cell. If no style used, 0 will be returned. |
||||
|
*/ |
||||
|
Format Cell::format() const |
||||
|
{ |
||||
|
Q_D(const Cell); |
||||
|
|
||||
|
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 |
||||
|
*/ |
||||
|
CellFormula Cell::formula() const |
||||
|
{ |
||||
|
Q_D(const Cell); |
||||
|
|
||||
|
return d->formula; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* Returns whether the value is probably a dateTime or not |
||||
|
*/ |
||||
|
bool Cell::isDateTime() const |
||||
|
{ |
||||
|
Q_D(const Cell); |
||||
|
|
||||
|
Cell::CellType cellType = d->cellType; |
||||
|
double dValue = d->value.toDouble(); // number
|
||||
|
// QString strValue = d->value.toString().toUtf8();
|
||||
|
bool isValidFormat = d->format.isValid(); |
||||
|
bool isDateTimeFormat = d->format.isDateTimeFormat(); // datetime format
|
||||
|
|
||||
|
// dev67
|
||||
|
if ( cellType == NumberType || |
||||
|
cellType == DateType || |
||||
|
cellType == CustomType ) |
||||
|
{ |
||||
|
if ( dValue >= 0 && |
||||
|
isValidFormat && |
||||
|
isDateTimeFormat ) |
||||
|
{ |
||||
|
return true; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* Return the data time value. |
||||
|
*/ |
||||
|
/*
|
||||
|
QDateTime Cell::dateTime() const |
||||
|
{ |
||||
|
Q_D(const Cell); |
||||
|
|
||||
|
if (!isDateTime()) |
||||
|
return QDateTime(); |
||||
|
|
||||
|
return datetimeFromNumber(d->value.toDouble(), d->parent->workbook()->isDate1904()); |
||||
|
} |
||||
|
*/ |
||||
|
QVariant Cell::dateTime() const |
||||
|
{ |
||||
|
Q_D(const Cell); |
||||
|
|
||||
|
if (!isDateTime()) |
||||
|
{ |
||||
|
return QVariant(); |
||||
|
} |
||||
|
|
||||
|
// dev57
|
||||
|
|
||||
|
QVariant ret; |
||||
|
double dValue = d->value.toDouble(); |
||||
|
bool isDate1904 = d->parent->workbook()->isDate1904(); |
||||
|
ret = datetimeFromNumber(dValue, isDate1904); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* Returns whether the cell is probably a rich string or not |
||||
|
*/ |
||||
|
bool Cell::isRichString() const |
||||
|
{ |
||||
|
Q_D(const Cell); |
||||
|
|
||||
|
if ( d->cellType != SharedStringType && |
||||
|
d->cellType != InlineStringType && |
||||
|
d->cellType != StringType ) |
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
return d->richString.isRichString(); |
||||
|
} |
||||
|
|
||||
|
qint32 Cell::styleNumber() const |
||||
|
{ |
||||
|
Q_D(const Cell); |
||||
|
|
||||
|
qint32 ret = d->styleNumber; |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
bool Cell::isDateType(CellType cellType, const Format &format) |
||||
|
{ |
||||
|
if ( cellType == NumberType || |
||||
|
cellType == DateType || |
||||
|
cellType == CustomType ) |
||||
|
{ |
||||
|
return format.isValid() && format.isDateTimeFormat(); |
||||
|
} |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
@ -0,0 +1,453 @@ |
|||||
|
// xlsxcellformula.cpp
|
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QObject> |
||||
|
#include <QString> |
||||
|
#include <QXmlStreamReader> |
||||
|
#include <QXmlStreamWriter> |
||||
|
#include <QDebug> |
||||
|
|
||||
|
#include "xlsxcellformula.h" |
||||
|
#include "xlsxcellformula_p.h" |
||||
|
#include "xlsxutility_p.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
CellFormulaPrivate::CellFormulaPrivate(const QString &formula_, const CellRange &ref_, CellFormula::FormulaType type_) |
||||
|
:formula(formula_), type(type_), reference(ref_), ca(false), 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) |
||||
|
, ca(other.ca), 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::formulaText() 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); |
||||
|
} |
||||
|
|
||||
|
/* aca (Always Calculate Array) // not-implmented attribute
|
||||
|
* |
||||
|
* Only applies to array formulas. |
||||
|
* |
||||
|
* true indicates that the entire array shall be calculated in full. |
||||
|
* If false the individual cells of the array shall be calculated as needed. |
||||
|
* |
||||
|
* The aca value shall be ignored unless the value of the corresponding |
||||
|
* t attribute is array. |
||||
|
* |
||||
|
* [Note: The primary case where an array formula must be calculated in |
||||
|
* part instead of in full is when some cells in the array depend on other |
||||
|
* cells that are semi-calculated, e.g., contains the function =(). end note] |
||||
|
* |
||||
|
* The possible values for this attribute are defined by the W3C XML Schema |
||||
|
* boolean datatype. |
||||
|
*/ |
||||
|
|
||||
|
/* bx (Assigns Value to Name) // not-implmented attribute
|
||||
|
* |
||||
|
* Specifies that this formula assigns a value to a name. |
||||
|
* |
||||
|
* The possible values for this attribute are defined by the W3C XML |
||||
|
* Schema boolean datatype. |
||||
|
*/ |
||||
|
|
||||
|
/* del1 (Input 1 Deleted) // not-implmented attribute
|
||||
|
* |
||||
|
* Whether the first input cell for data table has been deleted. |
||||
|
* Applies to data table formula only. Written on master cell of data table |
||||
|
* formula only. |
||||
|
* |
||||
|
* The possible values for this attribute are defined by the W3C XML Schema |
||||
|
* boolean datatype. |
||||
|
*/ |
||||
|
|
||||
|
/* del2 (Input 2 Deleted) // not-impplmented attribute
|
||||
|
* |
||||
|
* Whether the second input cell for data table has been deleted. |
||||
|
* Applies to data table formula only. Written on master cell of data |
||||
|
* table formula only. |
||||
|
* |
||||
|
* The possible values for this attribute are defined by the W3C XML Schema |
||||
|
* boolean datatype. |
||||
|
*/ |
||||
|
|
||||
|
/* dt2D (Data Table 2-D) // not-implmented attribute
|
||||
|
* |
||||
|
* Data table is two-dimentional. Only applies to the data tables function. |
||||
|
* Written on master cell of data table formula only. |
||||
|
* |
||||
|
* The possible values for this attribute are defined by the W3C XML Schema |
||||
|
* boolean datatype. |
||||
|
*/ |
||||
|
|
||||
|
/* dtr (Data Table Row) // not-implmented attribute
|
||||
|
* |
||||
|
* true if one-dimentional data table is a row, otherwise it's a column. |
||||
|
* Only applies to the data tables function. Written on master cell of data |
||||
|
* table formula only. |
||||
|
* |
||||
|
* The possible values for this attribute are defined by the W3C XML Schema |
||||
|
* boolean datatype. |
||||
|
*/ |
||||
|
|
||||
|
/* r1 (Data Table Cell 1) // not-implmented attribute
|
||||
|
* |
||||
|
* First input cell for data table. Only applies to the data tables array |
||||
|
* function "TABLE()". Written on master cell of data table formula only. |
||||
|
* |
||||
|
* The possible values for this attribute are defined by the ST_CellRef |
||||
|
* simple type (§18.18.7). |
||||
|
*/ |
||||
|
|
||||
|
/* r2 (Input Cell 2) // not-implmented attribute
|
||||
|
* |
||||
|
* Second input cell for data table when dt2D is '1'. Only applies to the |
||||
|
* data tables array function "TABLE()".Written on master cell of data table |
||||
|
* formula only. |
||||
|
* |
||||
|
* The possible values for this attribute are defined by the ST_CellRef |
||||
|
* simple type (§18.18.7). |
||||
|
*/ |
||||
|
|
||||
|
/*!
|
||||
|
* \internal |
||||
|
* \remark pair with loadFromXml() |
||||
|
*/ |
||||
|
bool CellFormula::saveToXml(QXmlStreamWriter &writer) const |
||||
|
{ |
||||
|
|
||||
|
// t (Formula Type)
|
||||
|
//
|
||||
|
// Type of formula.
|
||||
|
// The possible values for this attribute are defined by the
|
||||
|
// ST_CellFormulaType simple type (§18.18.6).
|
||||
|
//
|
||||
|
// 18.18.6 ST_CellFormulaType (Formula Type)
|
||||
|
// array (Array Formula)
|
||||
|
// dataTable (Table Formula)
|
||||
|
// normal (Normal)
|
||||
|
// shared (Shared Formula)
|
||||
|
|
||||
|
QString t; |
||||
|
switch (d->type) |
||||
|
{ |
||||
|
case CellFormula::ArrayType: |
||||
|
t = QStringLiteral("array"); |
||||
|
break; |
||||
|
case CellFormula::SharedType: |
||||
|
t = QStringLiteral("shared"); |
||||
|
break; |
||||
|
case CellFormula::NormalType: |
||||
|
t = QStringLiteral("normal"); |
||||
|
break; |
||||
|
case CellFormula::DataTableType: |
||||
|
t = QStringLiteral("dataTable"); |
||||
|
break; |
||||
|
default: // undefined type
|
||||
|
return false; |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
// f (Formula)
|
||||
|
//
|
||||
|
// Formula for the cell. The formula expression is contained in the
|
||||
|
// character node of this element.
|
||||
|
writer.writeStartElement(QStringLiteral("f")); |
||||
|
|
||||
|
if (!t.isEmpty()) |
||||
|
{ |
||||
|
writer.writeAttribute(QStringLiteral("t"), t); // write type(t)
|
||||
|
} |
||||
|
|
||||
|
// ref (Range of Cells)
|
||||
|
//
|
||||
|
// Range of cells which the formula applies to.
|
||||
|
// Only required for shared formula, array formula or data table.
|
||||
|
// Only written on the master formula,
|
||||
|
// not subsequent formulas belonging to the same shared group, array,
|
||||
|
// or data table.
|
||||
|
// The possible values for this attribute are defined by the ST_Ref
|
||||
|
// simple type (§18.18.62).
|
||||
|
|
||||
|
if ( d->type == CellFormula::SharedType || |
||||
|
d->type == CellFormula::ArrayType || |
||||
|
d->type == CellFormula::DataTableType ) |
||||
|
{ |
||||
|
if (d->reference.isValid()) |
||||
|
{ |
||||
|
writer.writeAttribute(QStringLiteral("ref"), d->reference.toString()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// ca (Calculate Cell)
|
||||
|
//
|
||||
|
// Indicates that this formula needs to be recalculated the next time
|
||||
|
// calculation is performed. [Example: This is always set on volatile
|
||||
|
// functions, like =(), and circular references. end example]
|
||||
|
// The possible values for this attribute are defined by the W3C XML
|
||||
|
// Schema boolean datatype.
|
||||
|
//
|
||||
|
// 3.2.2 boolean
|
||||
|
// 3.2.2.1 Lexical representation
|
||||
|
// An instance of a datatype that is defined as ·boolean· can have the
|
||||
|
// following legal literals {true, false, 1, 0}.
|
||||
|
|
||||
|
if (d->ca) |
||||
|
{ |
||||
|
writer.writeAttribute(QStringLiteral("ca"), QStringLiteral("1")); |
||||
|
} |
||||
|
|
||||
|
// si (Shared Group Index)
|
||||
|
// Optional attribute to optimize load performance by sharing formulas.
|
||||
|
//
|
||||
|
// When a formula is a shared formula (t value is shared) then this value
|
||||
|
// indicates the group to which this particular cell's formula belongs. The
|
||||
|
// first formula in a group of shared formulas is saved in the f element.
|
||||
|
// This is considered the 'master' formula cell. Subsequent cells sharing
|
||||
|
// this formula need not have the formula written in their f element.
|
||||
|
// Instead, the attribute si value for a particular cell is used to figure
|
||||
|
// what the formula expression should be based on the cell's relative
|
||||
|
// location to the master formula cell.
|
||||
|
|
||||
|
if (d->type == CellFormula::SharedType) |
||||
|
{ |
||||
|
int si = d->si; |
||||
|
writer.writeAttribute(QStringLiteral("si"), QString::number(si)); |
||||
|
} |
||||
|
|
||||
|
if (!d->formula.isEmpty()) |
||||
|
{ |
||||
|
QString strFormula = d->formula; |
||||
|
writer.writeCharacters(strFormula); // write formula
|
||||
|
} |
||||
|
|
||||
|
writer.writeEndElement(); // f
|
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* \internal |
||||
|
* \remark pair with saveToXml() |
||||
|
*/ |
||||
|
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(); |
||||
|
|
||||
|
// branch: shared-formula
|
||||
|
//
|
||||
|
if (typeString == QLatin1String("array")) { |
||||
|
d->type = ArrayType; |
||||
|
} |
||||
|
else if (typeString == QLatin1String("shared")) { |
||||
|
d->type = SharedType; |
||||
|
} |
||||
|
else if (typeString == QLatin1String("normal")) { |
||||
|
d->type = NormalType; |
||||
|
} |
||||
|
else if (typeString == QLatin1String("dataTable")) { |
||||
|
d->type = DataTableType; |
||||
|
} |
||||
|
else { |
||||
|
/*
|
||||
|
// undefined type
|
||||
|
// qDebug() << "Undefined type" << typeString;
|
||||
|
return false; |
||||
|
// */
|
||||
|
|
||||
|
// dev40 {{
|
||||
|
// https://github.com/QtExcel/QXlsx/issues/38
|
||||
|
d->type = NormalType; // Change: normal Type is not mentioned in the xml file!!!!!
|
||||
|
// }}
|
||||
|
} |
||||
|
|
||||
|
// branch: shared-formula
|
||||
|
//
|
||||
|
// ref (Range of Cells)
|
||||
|
// Range of cells which the formula applies to.
|
||||
|
// Only required for shared formula, array formula or data table.
|
||||
|
if ( d->type == CellFormula::SharedType || |
||||
|
d->type == CellFormula::ArrayType || |
||||
|
d->type == CellFormula::DataTableType ) |
||||
|
{ |
||||
|
if (attributes.hasAttribute(QLatin1String("ref"))) |
||||
|
{ |
||||
|
QString refString = attributes.value(QLatin1String("ref")).toString(); |
||||
|
d->reference = CellRange(refString); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// branch: shared-formula
|
||||
|
//
|
||||
|
// si (Shared Group Index)
|
||||
|
// Optional attribute to optimize load performance by sharing formulas.
|
||||
|
// When a formula is a shared formula (t value is shared) then this value
|
||||
|
// indicates the group to which this particular cell's formula belongs.
|
||||
|
if ( d->type == CellFormula::SharedType ) |
||||
|
{ |
||||
|
QString ca = attributes.value(QLatin1String("si")).toString(); |
||||
|
d->ca = parseXsdBoolean(ca, false); |
||||
|
|
||||
|
if (attributes.hasAttribute(QLatin1String("si"))) |
||||
|
{ |
||||
|
d->si = attributes.value(QLatin1String("si")).toInt(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
d->formula = reader.readElementText(); // read formula
|
||||
|
|
||||
|
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 |
@ -0,0 +1,23 @@ |
|||||
|
// xlsxcelllocation.cpp
|
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QObject> |
||||
|
#include <QString> |
||||
|
#include <QVector> |
||||
|
#include <QList> |
||||
|
|
||||
|
#include "xlsxglobal.h" |
||||
|
#include "xlsxcell.h" |
||||
|
#include "xlsxcelllocation.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
CellLocation::CellLocation() |
||||
|
{ |
||||
|
col = -1; |
||||
|
row = -1; |
||||
|
|
||||
|
cell.reset(); |
||||
|
} |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
@ -0,0 +1,127 @@ |
|||||
|
// xlsxcellrange.cpp
|
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QString> |
||||
|
#include <QPoint> |
||||
|
#include <QStringList> |
||||
|
|
||||
|
#include "xlsxcellrange.h" |
||||
|
#include "xlsxcellreference.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
/*!
|
||||
|
\class CellRange |
||||
|
\brief For a range "A1:B2" or single cell "A1" |
||||
|
\inmodule QtXlsx |
||||
|
|
||||
|
The CellRange class stores the top left and bottom |
||||
|
right rows and columns of a range in a worksheet. |
||||
|
*/ |
||||
|
|
||||
|
/*!
|
||||
|
Constructs an range, i.e. a range |
||||
|
whose rowCount() and columnCount() are 0. |
||||
|
*/ |
||||
|
CellRange::CellRange() |
||||
|
: top(-1), left(-1), bottom(-2), right(-2) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Constructs the range from the given \a top, \a |
||||
|
left, \a bottom and \a right rows and columns. |
||||
|
|
||||
|
\sa topRow(), leftColumn(), bottomRow(), rightColumn() |
||||
|
*/ |
||||
|
CellRange::CellRange(int top, int left, int bottom, int right) |
||||
|
: top(top), left(left), bottom(bottom), right(right) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
CellRange::CellRange(const CellReference &topLeft, const CellReference &bottomRight) |
||||
|
: top(topLeft.row()), left(topLeft.column()) |
||||
|
, bottom(bottomRight.row()), right(bottomRight.column()) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
\overload |
||||
|
Constructs the range form the given \a range string. |
||||
|
*/ |
||||
|
CellRange::CellRange(const QString &range) |
||||
|
{ |
||||
|
init(range); |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
\overload |
||||
|
Constructs the range form the given \a range string. |
||||
|
*/ |
||||
|
CellRange::CellRange(const char *range) |
||||
|
{ |
||||
|
init(QString::fromLatin1(range)); |
||||
|
} |
||||
|
|
||||
|
void CellRange::init(const QString &range) |
||||
|
{ |
||||
|
QStringList rs = range.split(QLatin1Char(':')); |
||||
|
if (rs.size() == 2) { |
||||
|
CellReference start(rs[0]); |
||||
|
CellReference end(rs[1]); |
||||
|
top = start.row(); |
||||
|
left = start.column(); |
||||
|
bottom = end.row(); |
||||
|
right = end.column(); |
||||
|
} else { |
||||
|
CellReference p(rs[0]); |
||||
|
top = p.row(); |
||||
|
left = p.column(); |
||||
|
bottom = p.row(); |
||||
|
right = p.column(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Constructs a the range by copying the given \a |
||||
|
other range. |
||||
|
*/ |
||||
|
CellRange::CellRange(const CellRange &other) |
||||
|
: top(other.top), left(other.left), bottom(other.bottom), right(other.right) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Destroys the range. |
||||
|
*/ |
||||
|
CellRange::~CellRange() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Convert the range to string notation, such as "A1:B5". |
||||
|
*/ |
||||
|
QString CellRange::toString(bool row_abs, bool col_abs) const |
||||
|
{ |
||||
|
if (!isValid()) |
||||
|
return QString(); |
||||
|
|
||||
|
if (left == right && top == bottom) { |
||||
|
//Single cell
|
||||
|
return CellReference(top, left).toString(row_abs, col_abs); |
||||
|
} |
||||
|
|
||||
|
QString cell_1 = CellReference(top, left).toString(row_abs, col_abs); |
||||
|
QString cell_2 = CellReference(bottom, right).toString(row_abs, col_abs); |
||||
|
return cell_1 + QLatin1String(":") + cell_2; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* Returns true if the Range is valid. |
||||
|
*/ |
||||
|
bool CellRange::isValid() const |
||||
|
{ |
||||
|
return left <= right && top <= bottom; |
||||
|
} |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
@ -0,0 +1,154 @@ |
|||||
|
// xlsxcellreference.cpp
|
||||
|
|
||||
|
#include "xlsxcellreference.h" |
||||
|
#include <QStringList> |
||||
|
#include <QMap> |
||||
|
|
||||
|
#include <QRegularExpression> |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
namespace { |
||||
|
|
||||
|
int intPow(int x, int p) |
||||
|
{ |
||||
|
if (p == 0) return 1; |
||||
|
if (p == 1) return x; |
||||
|
|
||||
|
int tmp = intPow(x, p/2); |
||||
|
if (p%2 == 0) return tmp * tmp; |
||||
|
else return x * tmp * tmp; |
||||
|
} |
||||
|
|
||||
|
QString col_to_name(int col_num) |
||||
|
{ |
||||
|
static thread_local QMap<int, QString> col_cache; |
||||
|
|
||||
|
auto it = col_cache.find(col_num); |
||||
|
if (it == col_cache.end()) { |
||||
|
QString col_str; |
||||
|
int remainder; |
||||
|
while (col_num) { |
||||
|
remainder = col_num % 26; |
||||
|
if (remainder == 0) |
||||
|
remainder = 26; |
||||
|
col_str.prepend(QChar('A'+remainder-1)); |
||||
|
col_num = (col_num - 1) / 26; |
||||
|
} |
||||
|
it = col_cache.insert(col_num, col_str); |
||||
|
} |
||||
|
|
||||
|
return it.value(); |
||||
|
} |
||||
|
|
||||
|
int col_from_name(const QString &col_str) |
||||
|
{ |
||||
|
int col = 0; |
||||
|
int expn = 0; |
||||
|
for (int i=col_str.size()-1; i>-1; --i) { |
||||
|
col += (col_str[i].unicode() - 'A' + 1) * intPow(26, expn); |
||||
|
expn++; |
||||
|
} |
||||
|
|
||||
|
return col; |
||||
|
} |
||||
|
} //namespace
|
||||
|
|
||||
|
/*!
|
||||
|
\class CellReference |
||||
|
\brief For one single cell such as "A1" |
||||
|
\inmodule QtXlsx |
||||
|
|
||||
|
The CellReference class stores the cell location in a worksheet. |
||||
|
*/ |
||||
|
|
||||
|
/*!
|
||||
|
Constructs an invalid Cell Reference |
||||
|
*/ |
||||
|
CellReference::CellReference() |
||||
|
: _row(-1), _column(-1) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Constructs the Reference from the given \a row, and \a column. |
||||
|
*/ |
||||
|
CellReference::CellReference(int row, int column) |
||||
|
: _row(row), _column(column) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
\overload |
||||
|
Constructs the Reference form the given \a cell string. |
||||
|
*/ |
||||
|
CellReference::CellReference(const QString &cell) |
||||
|
{ |
||||
|
init(cell); |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
\overload |
||||
|
Constructs the Reference form the given \a cell string. |
||||
|
*/ |
||||
|
CellReference::CellReference(const char *cell) |
||||
|
{ |
||||
|
init(QString::fromLatin1(cell)); |
||||
|
} |
||||
|
|
||||
|
void CellReference::init(const QString &cell_str) |
||||
|
{ |
||||
|
static thread_local QRegularExpression re(QStringLiteral("^\\$?([A-Z]{1,3})\\$?(\\d+)$")); |
||||
|
QRegularExpressionMatch match = re.match(cell_str); |
||||
|
if (match.hasMatch()) { |
||||
|
const QString col_str = match.captured(1); |
||||
|
const QString row_str = match.captured(2); |
||||
|
_row = row_str.toInt(); |
||||
|
_column = col_from_name(col_str); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Constructs a Reference by copying the given \a |
||||
|
other Reference. |
||||
|
*/ |
||||
|
CellReference::CellReference(const CellReference &other) |
||||
|
: _row(other._row), _column(other._column) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Destroys the Reference. |
||||
|
*/ |
||||
|
CellReference::~CellReference() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Convert the Reference to string notation, such as "A1" or "$A$1". |
||||
|
If current object is invalid, an empty string will be returned. |
||||
|
*/ |
||||
|
QString CellReference::toString(bool row_abs, bool col_abs) const |
||||
|
{ |
||||
|
if (!isValid()) |
||||
|
return QString(); |
||||
|
|
||||
|
QString cell_str; |
||||
|
if (col_abs) |
||||
|
cell_str.append(QLatin1Char('$')); |
||||
|
cell_str.append(col_to_name(_column)); |
||||
|
if (row_abs) |
||||
|
cell_str.append(QLatin1Char('$')); |
||||
|
cell_str.append(QString::number(_row)); |
||||
|
return cell_str; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* Returns true if the Reference is valid. |
||||
|
*/ |
||||
|
bool CellReference::isValid() const |
||||
|
{ |
||||
|
return _row > 0 && _column > 0; |
||||
|
} |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
File diff suppressed because it is too large
@ -0,0 +1,142 @@ |
|||||
|
// xlsxchartsheet.cpp
|
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QXmlStreamReader> |
||||
|
#include <QXmlStreamWriter> |
||||
|
#include <QDir> |
||||
|
|
||||
|
#include "xlsxchartsheet.h" |
||||
|
#include "xlsxchartsheet_p.h" |
||||
|
#include "xlsxworkbook.h" |
||||
|
#include "xlsxutility_p.h" |
||||
|
#include "xlsxdrawing_p.h" |
||||
|
#include "xlsxdrawinganchor_p.h" |
||||
|
#include "xlsxchart.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
ChartsheetPrivate::ChartsheetPrivate(Chartsheet *p, Chartsheet::CreateFlag flag) |
||||
|
: AbstractSheetPrivate(p, flag), chart(0) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
ChartsheetPrivate::~ChartsheetPrivate() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
\class Chartsheet |
||||
|
\inmodule QtXlsx |
||||
|
\brief Represent one chartsheet in the workbook. |
||||
|
*/ |
||||
|
|
||||
|
/*!
|
||||
|
* \internal |
||||
|
*/ |
||||
|
Chartsheet::Chartsheet(const QString &name, int id, Workbook *workbook, CreateFlag flag) |
||||
|
: AbstractSheet( name, id, workbook, new ChartsheetPrivate(this, flag) ) |
||||
|
{ |
||||
|
setSheetType(ST_ChartSheet); |
||||
|
|
||||
|
if (flag == Chartsheet::F_NewFromScratch) |
||||
|
{ |
||||
|
d_func()->drawing = std::make_shared<Drawing>(this, flag); |
||||
|
|
||||
|
DrawingAbsoluteAnchor *anchor = new DrawingAbsoluteAnchor(drawing(), DrawingAnchor::Picture); |
||||
|
|
||||
|
anchor->pos = QPoint(0, 0); |
||||
|
anchor->ext = QSize(9293679, 6068786); |
||||
|
|
||||
|
QSharedPointer<Chart> chart = QSharedPointer<Chart>(new Chart(this, flag)); |
||||
|
chart->setChartType(Chart::CT_BarChart); |
||||
|
anchor->setObjectGraphicFrame(chart); |
||||
|
|
||||
|
d_func()->chart = chart.data(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* \internal |
||||
|
* |
||||
|
* Make a copy of this sheet. |
||||
|
*/ |
||||
|
|
||||
|
Chartsheet *Chartsheet::copy(const QString &distName, int distId) const |
||||
|
{ |
||||
|
//:Todo
|
||||
|
Q_UNUSED(distName) |
||||
|
Q_UNUSED(distId) |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* Destroys this workssheet. |
||||
|
*/ |
||||
|
Chartsheet::~Chartsheet() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* Returns the chart object of the sheet. |
||||
|
*/ |
||||
|
Chart *Chartsheet::chart() |
||||
|
{ |
||||
|
Q_D(Chartsheet); |
||||
|
|
||||
|
return d->chart; |
||||
|
} |
||||
|
|
||||
|
void Chartsheet::saveToXmlFile(QIODevice *device) const |
||||
|
{ |
||||
|
Q_D(const Chartsheet); |
||||
|
d->relationships->clear(); |
||||
|
|
||||
|
QXmlStreamWriter writer(device); |
||||
|
|
||||
|
writer.writeStartDocument(QStringLiteral("1.0"), true); |
||||
|
writer.writeDefaultNamespace(QStringLiteral("http://schemas.openxmlformats.org/spreadsheetml/2006/main")); |
||||
|
writer.writeNamespace(QStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), QStringLiteral("r")); |
||||
|
writer.writeStartElement(QStringLiteral("chartsheet")); |
||||
|
|
||||
|
writer.writeStartElement(QStringLiteral("sheetViews")); |
||||
|
writer.writeEmptyElement(QStringLiteral("sheetView")); |
||||
|
writer.writeAttribute(QStringLiteral("workbookViewId"), QString::number(0)); |
||||
|
writer.writeAttribute(QStringLiteral("zoomToFit"), QStringLiteral("1")); |
||||
|
writer.writeEndElement(); //sheetViews
|
||||
|
|
||||
|
int idx = d->workbook->drawings().indexOf(d->drawing.get()); |
||||
|
d->relationships->addWorksheetRelationship(QStringLiteral("/drawing"), QStringLiteral("../drawings/drawing%1.xml").arg(idx+1)); |
||||
|
|
||||
|
writer.writeEmptyElement(QStringLiteral("drawing")); |
||||
|
writer.writeAttribute(QStringLiteral("r:id"), QStringLiteral("rId%1").arg(d->relationships->count())); |
||||
|
|
||||
|
writer.writeEndElement();//chartsheet
|
||||
|
writer.writeEndDocument(); |
||||
|
} |
||||
|
|
||||
|
bool Chartsheet::loadFromXmlFile(QIODevice *device) |
||||
|
{ |
||||
|
Q_D(Chartsheet); |
||||
|
|
||||
|
QXmlStreamReader reader(device); |
||||
|
while (!reader.atEnd()) { |
||||
|
reader.readNextStartElement(); |
||||
|
if (reader.tokenType() == QXmlStreamReader::StartElement) { |
||||
|
if (reader.name() == QLatin1String("drawing")) { |
||||
|
QString rId = reader.attributes().value(QStringLiteral("r:id")).toString(); |
||||
|
QString name = d->relationships->getRelationshipById(rId).target; |
||||
|
|
||||
|
const auto parts = splitPath(filePath()); |
||||
|
QString path = QDir::cleanPath(parts.first() + QLatin1String("/") + name); |
||||
|
|
||||
|
d->drawing = std::make_shared<Drawing>(this, F_LoadFromExists); |
||||
|
d->drawing->setFilePath(path); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
@ -0,0 +1,196 @@ |
|||||
|
// xlsxcolor.cpp
|
||||
|
|
||||
|
#include <QDataStream> |
||||
|
#include <QXmlStreamReader> |
||||
|
#include <QXmlStreamWriter> |
||||
|
#include <QDebug> |
||||
|
|
||||
|
#include "xlsxcolor_p.h" |
||||
|
#include "xlsxstyles_p.h" |
||||
|
#include "xlsxutility_p.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
XlsxColor::XlsxColor(const QColor &color) |
||||
|
{ |
||||
|
if (color.isValid()) |
||||
|
val.setValue(color); |
||||
|
} |
||||
|
|
||||
|
XlsxColor::XlsxColor(const QString &theme, const QString &tint) |
||||
|
:val(QStringList()<<theme<<tint) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
XlsxColor::XlsxColor(int index) |
||||
|
:val(index) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
bool XlsxColor::isRgbColor() const |
||||
|
{ |
||||
|
return val.userType() == qMetaTypeId<QColor>() && val.value<QColor>().isValid(); |
||||
|
} |
||||
|
|
||||
|
bool XlsxColor::isIndexedColor() const |
||||
|
{ |
||||
|
return val.userType() == QMetaType::Int; |
||||
|
} |
||||
|
|
||||
|
bool XlsxColor::isThemeColor() const |
||||
|
{ |
||||
|
return val.userType() == QMetaType::QStringList; |
||||
|
} |
||||
|
|
||||
|
bool XlsxColor::isInvalid() const |
||||
|
{ |
||||
|
return !val.isValid(); |
||||
|
} |
||||
|
|
||||
|
QColor XlsxColor::rgbColor() const |
||||
|
{ |
||||
|
return isRgbColor() ? val.value<QColor>() : QColor(); |
||||
|
} |
||||
|
|
||||
|
int XlsxColor::indexedColor() const |
||||
|
{ |
||||
|
return isIndexedColor() ? val.toInt() : -1; |
||||
|
} |
||||
|
|
||||
|
QStringList XlsxColor::themeColor() const |
||||
|
{ |
||||
|
return isThemeColor() ? val.toStringList() : QStringList(); |
||||
|
} |
||||
|
|
||||
|
bool XlsxColor::saveToXml(QXmlStreamWriter &writer, const QString &node) const |
||||
|
{ |
||||
|
if (!node.isEmpty()) |
||||
|
writer.writeEmptyElement(node); //color, bgColor, fgColor
|
||||
|
else |
||||
|
writer.writeEmptyElement(QStringLiteral("color")); |
||||
|
|
||||
|
if (val.userType() == qMetaTypeId<QColor>()) { |
||||
|
writer.writeAttribute(QStringLiteral("rgb"), XlsxColor::toARGBString(val.value<QColor>())); |
||||
|
} else if (val.userType() == QMetaType::QStringList) { |
||||
|
QStringList themes = val.toStringList(); |
||||
|
writer.writeAttribute(QStringLiteral("theme"), themes[0]); |
||||
|
if (!themes[1].isEmpty()) |
||||
|
writer.writeAttribute(QStringLiteral("tint"), themes[1]); |
||||
|
} else if (val.userType() == QMetaType::Int) { |
||||
|
writer.writeAttribute(QStringLiteral("indexed"), val.toString()); |
||||
|
} else { |
||||
|
writer.writeAttribute(QStringLiteral("auto"), QStringLiteral("1")); |
||||
|
} |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
bool XlsxColor::loadFromXml(QXmlStreamReader &reader) |
||||
|
{ |
||||
|
const auto& attributes = reader.attributes(); |
||||
|
|
||||
|
if (attributes.hasAttribute(QLatin1String("rgb"))) { |
||||
|
const auto& colorString = attributes.value(QLatin1String("rgb")).toString(); |
||||
|
val.setValue(fromARGBString(colorString)); |
||||
|
} else if (attributes.hasAttribute(QLatin1String("indexed"))) { |
||||
|
int index = attributes.value(QLatin1String("indexed")).toInt(); |
||||
|
val.setValue(index); |
||||
|
} else if (attributes.hasAttribute(QLatin1String("theme"))) { |
||||
|
const auto& theme = attributes.value(QLatin1String("theme")).toString(); |
||||
|
const auto& tint = attributes.value(QLatin1String("tint")).toString(); |
||||
|
val.setValue(QStringList()<<theme<<tint); |
||||
|
} |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
XlsxColor::operator QVariant() const |
||||
|
{ |
||||
|
const auto& cref |
||||
|
#if QT_VERSION >= 0x060000 // Qt 6.0 or over
|
||||
|
= QMetaType::fromType<XlsxColor>(); |
||||
|
#else |
||||
|
= qMetaTypeId<XlsxColor>() ; |
||||
|
#endif |
||||
|
return QVariant(cref, this); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
QColor XlsxColor::fromARGBString(const QString &c) |
||||
|
{ |
||||
|
QColor color; |
||||
|
if (c.startsWith(u'#')) { |
||||
|
color.setNamedColor(c); |
||||
|
} else { |
||||
|
color.setNamedColor(QLatin1Char('#') + c); |
||||
|
} |
||||
|
return color; |
||||
|
} |
||||
|
|
||||
|
QString XlsxColor::toARGBString(const QColor &c) |
||||
|
{ |
||||
|
return QString::asprintf("%02X%02X%02X%02X", c.alpha(), c.red(), c.green(), c.blue()); |
||||
|
} |
||||
|
|
||||
|
#if !defined(QT_NO_DATASTREAM) |
||||
|
QDataStream &operator<<(QDataStream &s, const XlsxColor &color) |
||||
|
{ |
||||
|
if (color.isInvalid()) |
||||
|
s<<0; |
||||
|
else if (color.isRgbColor()) |
||||
|
s<<1<<color.rgbColor(); |
||||
|
else if (color.isIndexedColor()) |
||||
|
s<<2<<color.indexedColor(); |
||||
|
else if (color.isThemeColor()) |
||||
|
s<<3<<color.themeColor(); |
||||
|
else |
||||
|
s<<4; |
||||
|
|
||||
|
return s; |
||||
|
} |
||||
|
|
||||
|
QDataStream &operator>>(QDataStream &s, XlsxColor &color) |
||||
|
{ |
||||
|
int marker(4); |
||||
|
s>>marker; |
||||
|
if (marker == 0) { |
||||
|
color = XlsxColor(); |
||||
|
} else if (marker == 1) { |
||||
|
QColor c; |
||||
|
s>>c; |
||||
|
color = XlsxColor(c); |
||||
|
} else if (marker == 2) { |
||||
|
int indexed; |
||||
|
s>>indexed; |
||||
|
color = XlsxColor(indexed); |
||||
|
} else if (marker == 3) { |
||||
|
QStringList list; |
||||
|
s>>list; |
||||
|
color = XlsxColor(list[0], list[1]); |
||||
|
} |
||||
|
|
||||
|
return s; |
||||
|
} |
||||
|
|
||||
|
#endif |
||||
|
|
||||
|
#ifndef QT_NO_DEBUG_STREAM |
||||
|
QDebug operator<<(QDebug dbg, const XlsxColor &c) |
||||
|
{ |
||||
|
if (c.isInvalid()) |
||||
|
dbg.nospace() << "XlsxColor(invalid)"; |
||||
|
else if (c.isRgbColor()) |
||||
|
dbg.nospace() << c.rgbColor(); |
||||
|
else if (c.isIndexedColor()) |
||||
|
dbg.nospace() << "XlsxColor(indexed," << c.indexedColor() << ")"; |
||||
|
else if (c.isThemeColor()) |
||||
|
dbg.nospace() << "XlsxColor(theme," << c.themeColor().join(QLatin1Char(':')) << ')'; |
||||
|
|
||||
|
return dbg.space(); |
||||
|
} |
||||
|
|
||||
|
#endif |
||||
|
|
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
@ -0,0 +1,751 @@ |
|||||
|
// xlsxconditionalformatting.cpp
|
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QXmlStreamReader> |
||||
|
#include <QXmlStreamWriter> |
||||
|
#include <QDebug> |
||||
|
|
||||
|
#include "xlsxconditionalformatting.h" |
||||
|
#include "xlsxconditionalformatting_p.h" |
||||
|
#include "xlsxworksheet.h" |
||||
|
#include "xlsxcellrange.h" |
||||
|
#include "xlsxstyles_p.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
ConditionalFormattingPrivate::ConditionalFormattingPrivate() |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
ConditionalFormattingPrivate::ConditionalFormattingPrivate(const ConditionalFormattingPrivate &other) |
||||
|
:QSharedData(other) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
ConditionalFormattingPrivate::~ConditionalFormattingPrivate() |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
void ConditionalFormattingPrivate::writeCfVo(QXmlStreamWriter &writer, const XlsxCfVoData &cfvo) const |
||||
|
{ |
||||
|
writer.writeEmptyElement(QStringLiteral("cfvo")); |
||||
|
QString type; |
||||
|
switch(cfvo.type) { |
||||
|
case ConditionalFormatting::VOT_Formula: type=QStringLiteral("formula"); break; |
||||
|
case ConditionalFormatting::VOT_Max: type=QStringLiteral("max"); break; |
||||
|
case ConditionalFormatting::VOT_Min: type=QStringLiteral("min"); break; |
||||
|
case ConditionalFormatting::VOT_Num: type=QStringLiteral("num"); break; |
||||
|
case ConditionalFormatting::VOT_Percent: type=QStringLiteral("percent"); break; |
||||
|
case ConditionalFormatting::VOT_Percentile: type=QStringLiteral("percentile"); break; |
||||
|
default: break; |
||||
|
} |
||||
|
writer.writeAttribute(QStringLiteral("type"), type); |
||||
|
writer.writeAttribute(QStringLiteral("val"), cfvo.value); |
||||
|
if (!cfvo.gte) |
||||
|
writer.writeAttribute(QStringLiteral("gte"), QStringLiteral("0")); |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* \class ConditionalFormatting |
||||
|
* \brief Conditional formatting for single cell or ranges |
||||
|
* \inmodule QtXlsx |
||||
|
* |
||||
|
* The conditional formatting can be applied to a single cell or ranges of cells. |
||||
|
*/ |
||||
|
|
||||
|
|
||||
|
/*!
|
||||
|
\enum ConditionalFormatting::HighlightRuleType |
||||
|
|
||||
|
\value Highlight_LessThan |
||||
|
\value Highlight_LessThanOrEqual |
||||
|
\value Highlight_Equal |
||||
|
\value Highlight_NotEqual |
||||
|
\value Highlight_GreaterThanOrEqual |
||||
|
\value Highlight_GreaterThan |
||||
|
\value Highlight_Between |
||||
|
\value Highlight_NotBetween |
||||
|
|
||||
|
\value Highlight_ContainsText |
||||
|
\value Highlight_NotContainsText |
||||
|
\value Highlight_BeginsWith |
||||
|
\value Highlight_EndsWith |
||||
|
|
||||
|
\value Highlight_TimePeriod |
||||
|
|
||||
|
\value Highlight_Duplicate |
||||
|
\value Highlight_Unique |
||||
|
|
||||
|
\value Highlight_Blanks |
||||
|
\value Highlight_NoBlanks |
||||
|
\value Highlight_Errors |
||||
|
\value Highlight_NoErrors |
||||
|
|
||||
|
\value Highlight_Top |
||||
|
\value Highlight_TopPercent |
||||
|
\value Highlight_Bottom |
||||
|
\value Highlight_BottomPercent |
||||
|
|
||||
|
\value Highlight_AboveAverage |
||||
|
\value Highlight_AboveOrEqualAverage |
||||
|
\value Highlight_BelowAverage |
||||
|
\value Highlight_BelowOrEqualAverage |
||||
|
\value Highlight_AboveStdDev1 |
||||
|
\value Highlight_AboveStdDev2 |
||||
|
\value Highlight_AboveStdDev3 |
||||
|
\value Highlight_BelowStdDev1 |
||||
|
\value Highlight_BelowStdDev2 |
||||
|
\value Highlight_BelowStdDev3 |
||||
|
|
||||
|
\value Highlight_Expression |
||||
|
*/ |
||||
|
|
||||
|
/*!
|
||||
|
\enum ConditionalFormatting::ValueObjectType |
||||
|
|
||||
|
\value VOT_Formula |
||||
|
\value VOT_Max |
||||
|
\value VOT_Min |
||||
|
\value VOT_Num |
||||
|
\value VOT_Percent |
||||
|
\value VOT_Percentile |
||||
|
*/ |
||||
|
|
||||
|
/*!
|
||||
|
Construct a conditional formatting object |
||||
|
*/ |
||||
|
ConditionalFormatting::ConditionalFormatting() |
||||
|
:d(new ConditionalFormattingPrivate()) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Constructs a copy of \a other. |
||||
|
*/ |
||||
|
ConditionalFormatting::ConditionalFormatting(const ConditionalFormatting &other) |
||||
|
:d(other.d) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Assigns \a other to this conditional formatting and returns a reference to |
||||
|
this conditional formatting. |
||||
|
*/ |
||||
|
ConditionalFormatting &ConditionalFormatting::operator=(const ConditionalFormatting &other) |
||||
|
{ |
||||
|
this->d = other.d; |
||||
|
return *this; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/*!
|
||||
|
* Destroy the object. |
||||
|
*/ |
||||
|
ConditionalFormatting::~ConditionalFormatting() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* Add a hightlight rule with the given \a type, \a formula1, \a formula2, |
||||
|
* \a format and \a stopIfTrue. |
||||
|
* Return false if failed. |
||||
|
*/ |
||||
|
bool ConditionalFormatting::addHighlightCellsRule(HighlightRuleType type, const QString &formula1, const QString &formula2, const Format &format, bool stopIfTrue) |
||||
|
{ |
||||
|
if (format.isEmpty()) |
||||
|
return false; |
||||
|
|
||||
|
bool skipFormula = false; |
||||
|
|
||||
|
auto cfRule = std::make_shared<XlsxCfRuleData>(); |
||||
|
if (type >= Highlight_LessThan && type <= Highlight_NotBetween) { |
||||
|
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("cellIs"); |
||||
|
QString op; |
||||
|
switch (type) { |
||||
|
case Highlight_Between: op = QStringLiteral("between"); break; |
||||
|
case Highlight_Equal: op = QStringLiteral("equal"); break; |
||||
|
case Highlight_GreaterThan: op = QStringLiteral("greaterThan"); break; |
||||
|
case Highlight_GreaterThanOrEqual: op = QStringLiteral("greaterThanOrEqual"); break; |
||||
|
case Highlight_LessThan: op = QStringLiteral("lessThan"); break; |
||||
|
case Highlight_LessThanOrEqual: op = QStringLiteral("lessThanOrEqual"); break; |
||||
|
case Highlight_NotBetween: op = QStringLiteral("notBetween"); break; |
||||
|
case Highlight_NotEqual: op = QStringLiteral("notEqual"); break; |
||||
|
default: break; |
||||
|
} |
||||
|
cfRule->attrs[XlsxCfRuleData::A_operator] = op; |
||||
|
} else if (type >= Highlight_ContainsText && type <= Highlight_EndsWith) { |
||||
|
if (type == Highlight_ContainsText) { |
||||
|
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("containsText"); |
||||
|
cfRule->attrs[XlsxCfRuleData::A_operator] = QStringLiteral("containsText"); |
||||
|
cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("NOT(ISERROR(SEARCH(\"%1\",%2)))").arg(formula1); |
||||
|
} else if (type == Highlight_NotContainsText) { |
||||
|
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("notContainsText"); |
||||
|
cfRule->attrs[XlsxCfRuleData::A_operator] = QStringLiteral("notContains"); |
||||
|
cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("ISERROR(SEARCH(\"%2\",%1))").arg(formula1); |
||||
|
} else if (type == Highlight_BeginsWith) { |
||||
|
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("beginsWith"); |
||||
|
cfRule->attrs[XlsxCfRuleData::A_operator] = QStringLiteral("beginsWith"); |
||||
|
cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("LEFT(%2,LEN(\"%1\"))=\"%1\"").arg(formula1); |
||||
|
} else { |
||||
|
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("endsWith"); |
||||
|
cfRule->attrs[XlsxCfRuleData::A_operator] = QStringLiteral("endsWith"); |
||||
|
cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("RIGHT(%2,LEN(\"%1\"))=\"%1\"").arg(formula1); |
||||
|
} |
||||
|
cfRule->attrs[XlsxCfRuleData::A_text] = formula1; |
||||
|
skipFormula = true; |
||||
|
} else if (type == Highlight_TimePeriod) { |
||||
|
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("timePeriod"); |
||||
|
//:Todo
|
||||
|
return false; |
||||
|
} else if (type == Highlight_Duplicate) { |
||||
|
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("duplicateValues"); |
||||
|
} else if (type == Highlight_Unique) { |
||||
|
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("uniqueValues"); |
||||
|
} else if (type == Highlight_Errors) { |
||||
|
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("containsErrors"); |
||||
|
cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("ISERROR(%1)"); |
||||
|
skipFormula = true; |
||||
|
} else if (type == Highlight_NoErrors) { |
||||
|
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("notContainsErrors"); |
||||
|
cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("NOT(ISERROR(%1))"); |
||||
|
skipFormula = true; |
||||
|
} else if (type == Highlight_Blanks) { |
||||
|
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("containsBlanks"); |
||||
|
cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("LEN(TRIM(%1))=0"); |
||||
|
skipFormula = true; |
||||
|
} else if (type == Highlight_NoBlanks) { |
||||
|
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("notContainsBlanks"); |
||||
|
cfRule->attrs[XlsxCfRuleData::A_formula1_temp] = QStringLiteral("LEN(TRIM(%1))>0"); |
||||
|
skipFormula = true; |
||||
|
} else if (type >= Highlight_Top && type <= Highlight_BottomPercent) { |
||||
|
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("top10"); |
||||
|
if (type == Highlight_Bottom || type == Highlight_BottomPercent) |
||||
|
cfRule->attrs[XlsxCfRuleData::A_bottom] = QStringLiteral("1"); |
||||
|
if (type == Highlight_TopPercent || type == Highlight_BottomPercent) |
||||
|
cfRule->attrs[XlsxCfRuleData::A_percent] = QStringLiteral("1"); |
||||
|
cfRule->attrs[XlsxCfRuleData::A_rank] = !formula1.isEmpty() ? formula1 : QStringLiteral("10"); |
||||
|
skipFormula = true; |
||||
|
} else if (type >= Highlight_AboveAverage && type <= Highlight_BelowStdDev3) { |
||||
|
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("aboveAverage"); |
||||
|
if (type >= Highlight_BelowAverage && type <= Highlight_BelowStdDev3) |
||||
|
cfRule->attrs[XlsxCfRuleData::A_aboveAverage] = QStringLiteral("0"); |
||||
|
if (type == Highlight_AboveOrEqualAverage || type == Highlight_BelowOrEqualAverage) |
||||
|
cfRule->attrs[XlsxCfRuleData::A_equalAverage] = QStringLiteral("1"); |
||||
|
if (type == Highlight_AboveStdDev1 || type == Highlight_BelowStdDev1) |
||||
|
cfRule->attrs[XlsxCfRuleData::A_stdDev] = QStringLiteral("1"); |
||||
|
else if (type == Highlight_AboveStdDev2 || type == Highlight_BelowStdDev2) |
||||
|
cfRule->attrs[XlsxCfRuleData::A_stdDev] = QStringLiteral("2"); |
||||
|
else if (type == Highlight_AboveStdDev3 || type == Highlight_BelowStdDev3) |
||||
|
cfRule->attrs[XlsxCfRuleData::A_stdDev] = QStringLiteral("3"); |
||||
|
} else if (type == Highlight_Expression){ |
||||
|
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("expression"); |
||||
|
} else { |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
cfRule->dxfFormat = format; |
||||
|
if (stopIfTrue) |
||||
|
cfRule->attrs[XlsxCfRuleData::A_stopIfTrue] = true; |
||||
|
if (!skipFormula) { |
||||
|
if (!formula1.isEmpty()) |
||||
|
cfRule->attrs[XlsxCfRuleData::A_formula1] = formula1.startsWith(QLatin1String("=")) ? formula1.mid(1) : formula1; |
||||
|
if (!formula2.isEmpty()) |
||||
|
cfRule->attrs[XlsxCfRuleData::A_formula2] = formula2.startsWith(QLatin1String("=")) ? formula2.mid(1) : formula2; |
||||
|
} |
||||
|
d->cfRules.append(cfRule); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* \overload |
||||
|
* |
||||
|
* Add a hightlight rule with the given \a type \a format and \a stopIfTrue. |
||||
|
*/ |
||||
|
bool ConditionalFormatting::addHighlightCellsRule(HighlightRuleType type, const Format &format, bool stopIfTrue) |
||||
|
{ |
||||
|
if ((type >= Highlight_AboveAverage && type <= Highlight_BelowStdDev3) |
||||
|
|| (type >= Highlight_Duplicate && type <= Highlight_NoErrors)) { |
||||
|
return addHighlightCellsRule(type, QString(), QString(), format, stopIfTrue); |
||||
|
} |
||||
|
|
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* \overload |
||||
|
* |
||||
|
* Add a hightlight rule with the given \a type, \a formula, \a format and \a stopIfTrue. |
||||
|
* Return false if failed. |
||||
|
*/ |
||||
|
bool ConditionalFormatting::addHighlightCellsRule(HighlightRuleType type, const QString &formula, const Format &format, bool stopIfTrue) |
||||
|
{ |
||||
|
if (type == Highlight_Between || type == Highlight_NotBetween) |
||||
|
return false; |
||||
|
|
||||
|
return addHighlightCellsRule(type, formula, QString(), format, stopIfTrue); |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* Add a dataBar rule with the given \a color, \a type1, \a val1 |
||||
|
* , \a type2, \a val2, \a showData and \a stopIfTrue. |
||||
|
* Return false if failed. |
||||
|
*/ |
||||
|
bool ConditionalFormatting::addDataBarRule(const QColor &color, ValueObjectType type1, const QString &val1, ValueObjectType type2, const QString &val2, bool showData, bool stopIfTrue) |
||||
|
{ |
||||
|
auto cfRule = std::make_shared<XlsxCfRuleData>(); |
||||
|
|
||||
|
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("dataBar"); |
||||
|
cfRule->attrs[XlsxCfRuleData::A_color1] = XlsxColor(color); |
||||
|
if (stopIfTrue) |
||||
|
cfRule->attrs[XlsxCfRuleData::A_stopIfTrue] = true; |
||||
|
if (!showData) |
||||
|
cfRule->attrs[XlsxCfRuleData::A_hideData] = true; |
||||
|
|
||||
|
XlsxCfVoData cfvo1(type1, val1); |
||||
|
XlsxCfVoData cfvo2(type2, val2); |
||||
|
cfRule->attrs[XlsxCfRuleData::A_cfvo1] = QVariant::fromValue(cfvo1); |
||||
|
cfRule->attrs[XlsxCfRuleData::A_cfvo2] = QVariant::fromValue(cfvo2); |
||||
|
|
||||
|
d->cfRules.append(cfRule); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* \overload |
||||
|
* Add a dataBar rule with the given \a color, \a showData and \a stopIfTrue. |
||||
|
*/ |
||||
|
bool ConditionalFormatting::addDataBarRule(const QColor &color, bool showData, bool stopIfTrue) |
||||
|
{ |
||||
|
return addDataBarRule(color, VOT_Min, QStringLiteral("0"), VOT_Max, QStringLiteral("0"), showData, stopIfTrue); |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* Add a colorScale rule with the given \a minColor, \a maxColor and \a stopIfTrue. |
||||
|
* Return false if failed. |
||||
|
*/ |
||||
|
bool ConditionalFormatting::add2ColorScaleRule(const QColor &minColor, const QColor &maxColor, bool stopIfTrue) |
||||
|
{ |
||||
|
ValueObjectType type1 = VOT_Min; |
||||
|
ValueObjectType type2 = VOT_Max; |
||||
|
QString val1 = QStringLiteral("0"); |
||||
|
QString val2 = QStringLiteral("0"); |
||||
|
|
||||
|
auto cfRule = std::make_shared<XlsxCfRuleData>(); |
||||
|
|
||||
|
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("colorScale"); |
||||
|
cfRule->attrs[XlsxCfRuleData::A_color1] = XlsxColor(minColor); |
||||
|
cfRule->attrs[XlsxCfRuleData::A_color2] = XlsxColor(maxColor); |
||||
|
if (stopIfTrue) |
||||
|
cfRule->attrs[XlsxCfRuleData::A_stopIfTrue] = true; |
||||
|
|
||||
|
XlsxCfVoData cfvo1(type1, val1); |
||||
|
XlsxCfVoData cfvo2(type2, val2); |
||||
|
cfRule->attrs[XlsxCfRuleData::A_cfvo1] = QVariant::fromValue(cfvo1); |
||||
|
cfRule->attrs[XlsxCfRuleData::A_cfvo2] = QVariant::fromValue(cfvo2); |
||||
|
|
||||
|
d->cfRules.append(cfRule); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* Add a colorScale rule with the given \a minColor, \a midColor, \a maxColor and \a stopIfTrue. |
||||
|
* Return false if failed. |
||||
|
*/ |
||||
|
bool ConditionalFormatting::add3ColorScaleRule(const QColor &minColor, const QColor &midColor, const QColor &maxColor, bool stopIfTrue) |
||||
|
{ |
||||
|
ValueObjectType type1 = VOT_Min; |
||||
|
ValueObjectType type2 = VOT_Percent; |
||||
|
ValueObjectType type3 = VOT_Max; |
||||
|
QString val1 = QStringLiteral("0"); |
||||
|
QString val2 = QStringLiteral("50"); |
||||
|
QString val3 = QStringLiteral("0"); |
||||
|
|
||||
|
auto cfRule = std::make_shared<XlsxCfRuleData>(); |
||||
|
|
||||
|
cfRule->attrs[XlsxCfRuleData::A_type] = QStringLiteral("colorScale"); |
||||
|
cfRule->attrs[XlsxCfRuleData::A_color1] = XlsxColor(minColor); |
||||
|
cfRule->attrs[XlsxCfRuleData::A_color2] = XlsxColor(midColor); |
||||
|
cfRule->attrs[XlsxCfRuleData::A_color3] = XlsxColor(maxColor); |
||||
|
|
||||
|
if (stopIfTrue) |
||||
|
cfRule->attrs[XlsxCfRuleData::A_stopIfTrue] = true; |
||||
|
|
||||
|
XlsxCfVoData cfvo1(type1, val1); |
||||
|
XlsxCfVoData cfvo2(type2, val2); |
||||
|
XlsxCfVoData cfvo3(type3, val3); |
||||
|
cfRule->attrs[XlsxCfRuleData::A_cfvo1] = QVariant::fromValue(cfvo1); |
||||
|
cfRule->attrs[XlsxCfRuleData::A_cfvo2] = QVariant::fromValue(cfvo2); |
||||
|
cfRule->attrs[XlsxCfRuleData::A_cfvo3] = QVariant::fromValue(cfvo3); |
||||
|
|
||||
|
d->cfRules.append(cfRule); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Returns the ranges on which the validation will be applied. |
||||
|
*/ |
||||
|
QList<CellRange> ConditionalFormatting::ranges() const |
||||
|
{ |
||||
|
return d->ranges; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Add the \a cell on which the conditional formatting will apply to. |
||||
|
*/ |
||||
|
void ConditionalFormatting::addCell(const CellReference &cell) |
||||
|
{ |
||||
|
d->ranges.append(CellRange(cell, cell)); |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
\overload |
||||
|
Add the cell(\a row, \a col) on which the conditional formatting will apply to. |
||||
|
*/ |
||||
|
void ConditionalFormatting::addCell(int row, int col) |
||||
|
{ |
||||
|
d->ranges.append(CellRange(row, col, row, col)); |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
\overload |
||||
|
Add the range(\a firstRow, \a firstCol, \a lastRow, \a lastCol) on |
||||
|
which the conditional formatting will apply to. |
||||
|
*/ |
||||
|
void ConditionalFormatting::addRange(int firstRow, int firstCol, int lastRow, int lastCol) |
||||
|
{ |
||||
|
d->ranges.append(CellRange(firstRow, firstCol, lastRow, lastCol)); |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Add the \a range on which the conditional formatting will apply to. |
||||
|
*/ |
||||
|
void ConditionalFormatting::addRange(const CellRange &range) |
||||
|
{ |
||||
|
d->ranges.append(range); |
||||
|
} |
||||
|
|
||||
|
bool ConditionalFormattingPrivate::readCfRule(QXmlStreamReader &reader, XlsxCfRuleData *rule, Styles *styles) |
||||
|
{ |
||||
|
Q_ASSERT(reader.name() == QLatin1String("cfRule")); |
||||
|
QXmlStreamAttributes attrs = reader.attributes(); |
||||
|
if (attrs.hasAttribute(QLatin1String("type"))) |
||||
|
rule->attrs[XlsxCfRuleData::A_type] = attrs.value(QLatin1String("type")).toString(); |
||||
|
if (attrs.hasAttribute(QLatin1String("dxfId"))) { |
||||
|
int id = attrs.value(QLatin1String("dxfId")).toInt(); |
||||
|
if (styles) |
||||
|
rule->dxfFormat = styles->dxfFormat(id); |
||||
|
else |
||||
|
rule->dxfFormat.setDxfIndex(id); |
||||
|
} |
||||
|
rule->priority = attrs.value(QLatin1String("priority")).toInt(); |
||||
|
if (attrs.value(QLatin1String("stopIfTrue")) == QLatin1String("1")) { |
||||
|
//default is false
|
||||
|
rule->attrs[XlsxCfRuleData::A_stopIfTrue] = QLatin1String("1"); |
||||
|
} |
||||
|
if (attrs.value(QLatin1String("aboveAverage")) == QLatin1String("0")) { |
||||
|
//default is true
|
||||
|
rule->attrs[XlsxCfRuleData::A_aboveAverage] = QLatin1String("0"); |
||||
|
} |
||||
|
if (attrs.value(QLatin1String("percent")) == QLatin1String("1")) { |
||||
|
//default is false
|
||||
|
rule->attrs[XlsxCfRuleData::A_percent] = QLatin1String("1"); |
||||
|
} |
||||
|
if (attrs.value(QLatin1String("bottom")) == QLatin1String("1")) { |
||||
|
//default is false
|
||||
|
rule->attrs[XlsxCfRuleData::A_bottom] = QLatin1String("1"); |
||||
|
} |
||||
|
if (attrs.hasAttribute(QLatin1String("operator"))) |
||||
|
rule->attrs[XlsxCfRuleData::A_operator] = attrs.value(QLatin1String("operator")).toString(); |
||||
|
|
||||
|
if (attrs.hasAttribute(QLatin1String("text"))) |
||||
|
rule->attrs[XlsxCfRuleData::A_text] = attrs.value(QLatin1String("text")).toString(); |
||||
|
|
||||
|
if (attrs.hasAttribute(QLatin1String("timePeriod"))) |
||||
|
rule->attrs[XlsxCfRuleData::A_timePeriod] = attrs.value(QLatin1String("timePeriod")).toString(); |
||||
|
|
||||
|
if (attrs.hasAttribute(QLatin1String("rank"))) |
||||
|
rule->attrs[XlsxCfRuleData::A_rank] = attrs.value(QLatin1String("rank")).toString(); |
||||
|
|
||||
|
if (attrs.hasAttribute(QLatin1String("stdDev"))) |
||||
|
rule->attrs[XlsxCfRuleData::A_stdDev] = attrs.value(QLatin1String("stdDev")).toString(); |
||||
|
|
||||
|
if (attrs.value(QLatin1String("equalAverage")) == QLatin1String("1")) { |
||||
|
//default is false
|
||||
|
rule->attrs[XlsxCfRuleData::A_equalAverage] = QLatin1String("1"); |
||||
|
} |
||||
|
|
||||
|
while (!reader.atEnd()) { |
||||
|
reader.readNextStartElement(); |
||||
|
if (reader.tokenType() == QXmlStreamReader::StartElement) { |
||||
|
if (reader.name() == QLatin1String("formula")) { |
||||
|
const QString f = reader.readElementText(); |
||||
|
if (!rule->attrs.contains(XlsxCfRuleData::A_formula1)) |
||||
|
rule->attrs[XlsxCfRuleData::A_formula1] = f; |
||||
|
else if (!rule->attrs.contains(XlsxCfRuleData::A_formula2)) |
||||
|
rule->attrs[XlsxCfRuleData::A_formula2] = f; |
||||
|
else if (!rule->attrs.contains(XlsxCfRuleData::A_formula3)) |
||||
|
rule->attrs[XlsxCfRuleData::A_formula3] = f; |
||||
|
} else if (reader.name() == QLatin1String("dataBar")) { |
||||
|
readCfDataBar(reader, rule); |
||||
|
} else if (reader.name() == QLatin1String("colorScale")) { |
||||
|
readCfColorScale(reader, rule); |
||||
|
} |
||||
|
} |
||||
|
if (reader.tokenType() == QXmlStreamReader::EndElement |
||||
|
&& reader.name() == QStringLiteral("conditionalFormatting")) { |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
bool ConditionalFormattingPrivate::readCfDataBar(QXmlStreamReader &reader, XlsxCfRuleData *rule) |
||||
|
{ |
||||
|
Q_ASSERT(reader.name() == QLatin1String("dataBar")); |
||||
|
QXmlStreamAttributes attrs = reader.attributes(); |
||||
|
if (attrs.value(QLatin1String("showValue")) == QLatin1String("0")) |
||||
|
rule->attrs[XlsxCfRuleData::A_hideData] = QStringLiteral("1"); |
||||
|
|
||||
|
while (!reader.atEnd()) { |
||||
|
reader.readNextStartElement(); |
||||
|
if (reader.tokenType() == QXmlStreamReader::StartElement) { |
||||
|
if (reader.name() == QLatin1String("cfvo")) { |
||||
|
XlsxCfVoData data; |
||||
|
readCfVo(reader, data); |
||||
|
if (!rule->attrs.contains(XlsxCfRuleData::A_cfvo1)) |
||||
|
rule->attrs[XlsxCfRuleData::A_cfvo1] = QVariant::fromValue(data); |
||||
|
else |
||||
|
rule->attrs[XlsxCfRuleData::A_cfvo2] = QVariant::fromValue(data); |
||||
|
} else if (reader.name() == QLatin1String("color")) { |
||||
|
XlsxColor color; |
||||
|
color.loadFromXml(reader); |
||||
|
rule->attrs[XlsxCfRuleData::A_color1] = color; |
||||
|
} |
||||
|
} |
||||
|
if (reader.tokenType() == QXmlStreamReader::EndElement |
||||
|
&& reader.name() == QStringLiteral("dataBar")) { |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
bool ConditionalFormattingPrivate::readCfColorScale(QXmlStreamReader &reader, XlsxCfRuleData *rule) |
||||
|
{ |
||||
|
Q_ASSERT(reader.name() == QLatin1String("colorScale")); |
||||
|
|
||||
|
while (!reader.atEnd()) { |
||||
|
reader.readNextStartElement(); |
||||
|
if (reader.tokenType() == QXmlStreamReader::StartElement) { |
||||
|
if (reader.name() == QLatin1String("cfvo")) { |
||||
|
XlsxCfVoData data; |
||||
|
readCfVo(reader, data); |
||||
|
if (!rule->attrs.contains(XlsxCfRuleData::A_cfvo1)) |
||||
|
rule->attrs[XlsxCfRuleData::A_cfvo1] = QVariant::fromValue(data); |
||||
|
else if (!rule->attrs.contains(XlsxCfRuleData::A_cfvo2)) |
||||
|
rule->attrs[XlsxCfRuleData::A_cfvo2] = QVariant::fromValue(data); |
||||
|
else |
||||
|
rule->attrs[XlsxCfRuleData::A_cfvo3] = QVariant::fromValue(data); |
||||
|
} else if (reader.name() == QLatin1String("color")) { |
||||
|
XlsxColor color; |
||||
|
color.loadFromXml(reader); |
||||
|
if (!rule->attrs.contains(XlsxCfRuleData::A_color1)) |
||||
|
rule->attrs[XlsxCfRuleData::A_color1] = color; |
||||
|
else if (!rule->attrs.contains(XlsxCfRuleData::A_color2)) |
||||
|
rule->attrs[XlsxCfRuleData::A_color2] = color; |
||||
|
else |
||||
|
rule->attrs[XlsxCfRuleData::A_color3] = color; |
||||
|
} |
||||
|
} |
||||
|
if (reader.tokenType() == QXmlStreamReader::EndElement |
||||
|
&& reader.name() == QStringLiteral("colorScale")) { |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
bool ConditionalFormattingPrivate::readCfVo(QXmlStreamReader &reader, XlsxCfVoData &cfvo) |
||||
|
{ |
||||
|
Q_ASSERT(reader.name() == QStringLiteral("cfvo")); |
||||
|
|
||||
|
QXmlStreamAttributes attrs = reader.attributes(); |
||||
|
|
||||
|
QString type = attrs.value(QLatin1String("type")).toString(); |
||||
|
ConditionalFormatting::ValueObjectType t; |
||||
|
if (type == QLatin1String("formula")) |
||||
|
t = ConditionalFormatting::VOT_Formula; |
||||
|
else if (type == QLatin1String("max")) |
||||
|
t = ConditionalFormatting::VOT_Max; |
||||
|
else if (type == QLatin1String("min")) |
||||
|
t = ConditionalFormatting::VOT_Min; |
||||
|
else if (type == QLatin1String("num")) |
||||
|
t = ConditionalFormatting::VOT_Num; |
||||
|
else if (type == QLatin1String("percent")) |
||||
|
t = ConditionalFormatting::VOT_Percent; |
||||
|
else //if (type == QLatin1String("percentile"))
|
||||
|
t = ConditionalFormatting::VOT_Percentile; |
||||
|
|
||||
|
cfvo.type = t; |
||||
|
cfvo.value = attrs.value(QLatin1String("val")).toString(); |
||||
|
if (attrs.value(QLatin1String("gte")) == QLatin1String("0")) { |
||||
|
//default is true
|
||||
|
cfvo.gte = false; |
||||
|
} |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
bool ConditionalFormatting::loadFromXml(QXmlStreamReader &reader, Styles *styles) |
||||
|
{ |
||||
|
Q_ASSERT(reader.name() == QStringLiteral("conditionalFormatting")); |
||||
|
|
||||
|
d->ranges.clear(); |
||||
|
d->cfRules.clear(); |
||||
|
QXmlStreamAttributes attrs = reader.attributes(); |
||||
|
const QString sqref = attrs.value(QLatin1String("sqref")).toString(); |
||||
|
const auto sqrefParts = sqref.split(QLatin1Char(' ')); |
||||
|
for (const QString &range : sqrefParts) { |
||||
|
this->addRange(range); |
||||
|
} |
||||
|
|
||||
|
while (!reader.atEnd()) { |
||||
|
reader.readNextStartElement(); |
||||
|
if (reader.tokenType() == QXmlStreamReader::StartElement) { |
||||
|
if (reader.name() == QLatin1String("cfRule")) { |
||||
|
auto cfRule = std::make_shared<XlsxCfRuleData>(); |
||||
|
d->readCfRule(reader, cfRule.get(), styles); |
||||
|
d->cfRules.append(cfRule); |
||||
|
} |
||||
|
} |
||||
|
if (reader.tokenType() == QXmlStreamReader::EndElement |
||||
|
&& reader.name() == QStringLiteral("conditionalFormatting")) { |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
bool ConditionalFormatting::saveToXml(QXmlStreamWriter &writer) const |
||||
|
{ |
||||
|
writer.writeStartElement(QStringLiteral("conditionalFormatting")); |
||||
|
QStringList sqref; |
||||
|
const auto rangeList = ranges(); |
||||
|
for (const CellRange &range : rangeList) { |
||||
|
sqref.append(range.toString()); |
||||
|
} |
||||
|
writer.writeAttribute(QStringLiteral("sqref"), sqref.join(QLatin1String(" "))); |
||||
|
|
||||
|
for (int i=0; i<d->cfRules.size(); ++i) { |
||||
|
const std::shared_ptr<XlsxCfRuleData> &rule = d->cfRules[i]; |
||||
|
writer.writeStartElement(QStringLiteral("cfRule")); |
||||
|
writer.writeAttribute(QStringLiteral("type"), rule->attrs[XlsxCfRuleData::A_type].toString()); |
||||
|
if (rule->dxfFormat.dxfIndexValid()) |
||||
|
writer.writeAttribute(QStringLiteral("dxfId"), QString::number(rule->dxfFormat.dxfIndex())); |
||||
|
writer.writeAttribute(QStringLiteral("priority"), QString::number(rule->priority)); |
||||
|
|
||||
|
auto it = rule->attrs.constFind(XlsxCfRuleData::A_stopIfTrue); |
||||
|
if (it != rule->attrs.constEnd()) |
||||
|
writer.writeAttribute(QStringLiteral("stopIfTrue"), it.value().toString()); |
||||
|
|
||||
|
it = rule->attrs.constFind(XlsxCfRuleData::A_aboveAverage); |
||||
|
if (it != rule->attrs.constEnd()) |
||||
|
writer.writeAttribute(QStringLiteral("aboveAverage"), it.value().toString()); |
||||
|
|
||||
|
it = rule->attrs.constFind(XlsxCfRuleData::A_percent); |
||||
|
if (it != rule->attrs.constEnd()) |
||||
|
writer.writeAttribute(QStringLiteral("percent"), it.value().toString()); |
||||
|
|
||||
|
it = rule->attrs.constFind(XlsxCfRuleData::A_bottom); |
||||
|
if (it != rule->attrs.constEnd()) |
||||
|
writer.writeAttribute(QStringLiteral("bottom"), it.value().toString()); |
||||
|
|
||||
|
it = rule->attrs.constFind(XlsxCfRuleData::A_operator); |
||||
|
if (it != rule->attrs.constEnd()) |
||||
|
writer.writeAttribute(QStringLiteral("operator"), it.value().toString()); |
||||
|
|
||||
|
it = rule->attrs.constFind(XlsxCfRuleData::A_text); |
||||
|
if (it != rule->attrs.constEnd()) |
||||
|
writer.writeAttribute(QStringLiteral("text"), it.value().toString()); |
||||
|
|
||||
|
it = rule->attrs.constFind(XlsxCfRuleData::A_timePeriod); |
||||
|
if (it != rule->attrs.constEnd()) |
||||
|
writer.writeAttribute(QStringLiteral("timePeriod"), it.value().toString()); |
||||
|
|
||||
|
it = rule->attrs.constFind(XlsxCfRuleData::A_rank); |
||||
|
if (it != rule->attrs.constEnd()) |
||||
|
writer.writeAttribute(QStringLiteral("rank"), it.value().toString()); |
||||
|
|
||||
|
it = rule->attrs.constFind(XlsxCfRuleData::A_stdDev); |
||||
|
if (it != rule->attrs.constEnd()) |
||||
|
writer.writeAttribute(QStringLiteral("stdDev"), it.value().toString()); |
||||
|
|
||||
|
it = rule->attrs.constFind(XlsxCfRuleData::A_equalAverage); |
||||
|
if (it != rule->attrs.constEnd()) |
||||
|
writer.writeAttribute(QStringLiteral("equalAverage"), it.value().toString()); |
||||
|
|
||||
|
if (rule->attrs[XlsxCfRuleData::A_type] == QLatin1String("dataBar")) { |
||||
|
writer.writeStartElement(QStringLiteral("dataBar")); |
||||
|
if (rule->attrs.contains(XlsxCfRuleData::A_hideData)) |
||||
|
writer.writeAttribute(QStringLiteral("showValue"), QStringLiteral("0")); |
||||
|
d->writeCfVo(writer, rule->attrs[XlsxCfRuleData::A_cfvo1].value<XlsxCfVoData>()); |
||||
|
d->writeCfVo(writer, rule->attrs[XlsxCfRuleData::A_cfvo2].value<XlsxCfVoData>()); |
||||
|
rule->attrs[XlsxCfRuleData::A_color1].value<XlsxColor>().saveToXml(writer); |
||||
|
writer.writeEndElement();//dataBar
|
||||
|
} else if (rule->attrs[XlsxCfRuleData::A_type] == QLatin1String("colorScale")) { |
||||
|
writer.writeStartElement(QStringLiteral("colorScale")); |
||||
|
d->writeCfVo(writer, rule->attrs[XlsxCfRuleData::A_cfvo1].value<XlsxCfVoData>()); |
||||
|
d->writeCfVo(writer, rule->attrs[XlsxCfRuleData::A_cfvo2].value<XlsxCfVoData>()); |
||||
|
|
||||
|
it = rule->attrs.constFind(XlsxCfRuleData::A_cfvo3); |
||||
|
if (it != rule->attrs.constEnd()) |
||||
|
d->writeCfVo(writer, it.value().value<XlsxCfVoData>()); |
||||
|
|
||||
|
rule->attrs[XlsxCfRuleData::A_color1].value<XlsxColor>().saveToXml(writer); |
||||
|
rule->attrs[XlsxCfRuleData::A_color2].value<XlsxColor>().saveToXml(writer); |
||||
|
|
||||
|
it = rule->attrs.constFind(XlsxCfRuleData::A_color3); |
||||
|
if (it != rule->attrs.constEnd()) |
||||
|
it.value().value<XlsxColor>().saveToXml(writer); |
||||
|
|
||||
|
writer.writeEndElement();//colorScale
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
it = rule->attrs.constFind(XlsxCfRuleData::A_formula1_temp); |
||||
|
if (it != rule->attrs.constEnd()) { |
||||
|
const auto _ranges = ranges(); |
||||
|
const auto begin = _ranges.begin(); |
||||
|
if (begin != _ranges.end()) { |
||||
|
QString str = begin->toString(); |
||||
|
QString startCell = str.mid(0, str.indexOf(u':')); |
||||
|
writer.writeTextElement(QStringLiteral("formula"), it.value().toString().arg(startCell)); |
||||
|
} |
||||
|
} else if ((it = rule->attrs.constFind(XlsxCfRuleData::A_formula1)) != rule->attrs.constEnd()) { |
||||
|
writer.writeTextElement(QStringLiteral("formula"), it.value().toString()); |
||||
|
} |
||||
|
|
||||
|
it = rule->attrs.constFind(XlsxCfRuleData::A_formula2); |
||||
|
if (it != rule->attrs.constEnd()) |
||||
|
writer.writeTextElement(QStringLiteral("formula"), it.value().toString()); |
||||
|
|
||||
|
it = rule->attrs.constFind(XlsxCfRuleData::A_formula3); |
||||
|
if (it != rule->attrs.constEnd()) |
||||
|
writer.writeTextElement(QStringLiteral("formula"), it.value().toString()); |
||||
|
|
||||
|
writer.writeEndElement(); //cfRule
|
||||
|
} |
||||
|
|
||||
|
writer.writeEndElement(); //conditionalFormatting
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
@ -0,0 +1,184 @@ |
|||||
|
// xlsxcontenttypes.cpp
|
||||
|
|
||||
|
#include <QXmlStreamWriter> |
||||
|
#include <QXmlStreamReader> |
||||
|
#include <QFile> |
||||
|
#include <QMapIterator> |
||||
|
#include <QBuffer> |
||||
|
#include <QDebug> |
||||
|
|
||||
|
#include "xlsxcontenttypes_p.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
ContentTypes::ContentTypes(CreateFlag flag) |
||||
|
:AbstractOOXmlFile(flag) |
||||
|
{ |
||||
|
m_package_prefix = QStringLiteral("application/vnd.openxmlformats-package."); |
||||
|
m_document_prefix = QStringLiteral("application/vnd.openxmlformats-officedocument."); |
||||
|
|
||||
|
m_defaults.insert(QStringLiteral("rels"), m_package_prefix + QLatin1String("relationships+xml")); |
||||
|
m_defaults.insert(QStringLiteral("xml"), QStringLiteral("application/xml")); |
||||
|
} |
||||
|
|
||||
|
void ContentTypes::addDefault(const QString &key, const QString &value) |
||||
|
{ |
||||
|
m_defaults.insert(key, value); |
||||
|
} |
||||
|
|
||||
|
void ContentTypes::addOverride(const QString &key, const QString &value) |
||||
|
{ |
||||
|
m_overrides.insert(key, value); |
||||
|
} |
||||
|
|
||||
|
void ContentTypes::addDocPropApp() |
||||
|
{ |
||||
|
addOverride(QStringLiteral("/docProps/app.xml"), m_document_prefix + QLatin1String("extended-properties+xml")); |
||||
|
} |
||||
|
|
||||
|
void ContentTypes::addDocPropCore() |
||||
|
{ |
||||
|
addOverride(QStringLiteral("/docProps/core.xml"), m_package_prefix + QLatin1String("core-properties+xml")); |
||||
|
} |
||||
|
|
||||
|
void ContentTypes::addStyles() |
||||
|
{ |
||||
|
addOverride(QStringLiteral("/xl/styles.xml"), m_document_prefix + QLatin1String("spreadsheetml.styles+xml")); |
||||
|
} |
||||
|
|
||||
|
void ContentTypes::addTheme() |
||||
|
{ |
||||
|
addOverride(QStringLiteral("/xl/theme/theme1.xml"), m_document_prefix + QLatin1String("theme+xml")); |
||||
|
} |
||||
|
|
||||
|
void ContentTypes::addWorkbook() |
||||
|
{ |
||||
|
addOverride(QStringLiteral("/xl/workbook.xml"), m_document_prefix + QLatin1String("spreadsheetml.sheet.main+xml")); |
||||
|
} |
||||
|
|
||||
|
void ContentTypes::addWorksheetName(const QString &name) |
||||
|
{ |
||||
|
addOverride(QStringLiteral("/xl/worksheets/%1.xml").arg(name), m_document_prefix + QLatin1String("spreadsheetml.worksheet+xml")); |
||||
|
} |
||||
|
|
||||
|
void ContentTypes::addChartsheetName(const QString &name) |
||||
|
{ |
||||
|
addOverride(QStringLiteral("/xl/chartsheets/%1.xml").arg(name), m_document_prefix + QLatin1String("spreadsheetml.chartsheet+xml")); |
||||
|
} |
||||
|
|
||||
|
void ContentTypes::addDrawingName(const QString &name) |
||||
|
{ |
||||
|
addOverride(QStringLiteral("/xl/drawings/%1.xml").arg(name), m_document_prefix + QLatin1String("drawing+xml")); |
||||
|
} |
||||
|
|
||||
|
void ContentTypes::addChartName(const QString &name) |
||||
|
{ |
||||
|
addOverride(QStringLiteral("/xl/charts/%1.xml").arg(name), m_document_prefix + QLatin1String("drawingml.chart+xml")); |
||||
|
} |
||||
|
|
||||
|
void ContentTypes::addCommentName(const QString &name) |
||||
|
{ |
||||
|
addOverride(QStringLiteral("/xl/%1.xml").arg(name), m_document_prefix + QLatin1String("spreadsheetml.comments+xml")); |
||||
|
} |
||||
|
|
||||
|
void ContentTypes::addTableName(const QString &name) |
||||
|
{ |
||||
|
addOverride(QStringLiteral("/xl/tables/%1.xml").arg(name), m_document_prefix + QLatin1String("spreadsheetml.table+xml")); |
||||
|
} |
||||
|
|
||||
|
void ContentTypes::addExternalLinkName(const QString &name) |
||||
|
{ |
||||
|
addOverride(QStringLiteral("/xl/externalLinks/%1.xml").arg(name), m_document_prefix + QLatin1String("spreadsheetml.externalLink+xml")); |
||||
|
} |
||||
|
|
||||
|
void ContentTypes::addSharedString() |
||||
|
{ |
||||
|
addOverride(QStringLiteral("/xl/sharedStrings.xml"), m_document_prefix + QLatin1String("spreadsheetml.sharedStrings+xml")); |
||||
|
} |
||||
|
|
||||
|
void ContentTypes::addVmlName() |
||||
|
{ |
||||
|
addOverride(QStringLiteral("vml"), m_document_prefix + QLatin1String("vmlDrawing")); |
||||
|
} |
||||
|
|
||||
|
void ContentTypes::addCalcChain() |
||||
|
{ |
||||
|
addOverride(QStringLiteral("/xl/calcChain.xml"), m_document_prefix + QLatin1String("spreadsheetml.calcChain+xml")); |
||||
|
} |
||||
|
|
||||
|
void ContentTypes::addVbaProject() |
||||
|
{ |
||||
|
//:TODO
|
||||
|
addOverride(QStringLiteral("bin"), QStringLiteral("application/vnd.ms-office.vbaProject")); |
||||
|
} |
||||
|
|
||||
|
void ContentTypes::clearOverrides() |
||||
|
{ |
||||
|
m_overrides.clear(); |
||||
|
} |
||||
|
|
||||
|
void ContentTypes::saveToXmlFile(QIODevice *device) const |
||||
|
{ |
||||
|
QXmlStreamWriter writer(device); |
||||
|
|
||||
|
writer.writeStartDocument(QStringLiteral("1.0"), true); |
||||
|
writer.writeStartElement(QStringLiteral("Types")); |
||||
|
writer.writeAttribute(QStringLiteral("xmlns"), QStringLiteral("http://schemas.openxmlformats.org/package/2006/content-types")); |
||||
|
|
||||
|
{ |
||||
|
QMapIterator<QString, QString> it(m_defaults); |
||||
|
while (it.hasNext()) { |
||||
|
it.next(); |
||||
|
writer.writeStartElement(QStringLiteral("Default")); |
||||
|
writer.writeAttribute(QStringLiteral("Extension"), it.key()); |
||||
|
writer.writeAttribute(QStringLiteral("ContentType"), it.value()); |
||||
|
writer.writeEndElement();//Default
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
{ |
||||
|
QMapIterator<QString, QString> it(m_overrides); |
||||
|
while (it.hasNext()) { |
||||
|
it.next(); |
||||
|
writer.writeStartElement(QStringLiteral("Override")); |
||||
|
writer.writeAttribute(QStringLiteral("PartName"), it.key()); |
||||
|
writer.writeAttribute(QStringLiteral("ContentType"), it.value()); |
||||
|
writer.writeEndElement(); //Override
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
writer.writeEndElement();//Types
|
||||
|
writer.writeEndDocument(); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
bool ContentTypes::loadFromXmlFile(QIODevice *device) |
||||
|
{ |
||||
|
m_defaults.clear(); |
||||
|
m_overrides.clear(); |
||||
|
|
||||
|
QXmlStreamReader reader(device); |
||||
|
while (!reader.atEnd()) { |
||||
|
QXmlStreamReader::TokenType token = reader.readNext(); |
||||
|
if (token == QXmlStreamReader::StartElement) { |
||||
|
if (reader.name() == QLatin1String("Default")) { |
||||
|
QXmlStreamAttributes attrs = reader.attributes(); |
||||
|
QString extension = attrs.value(QLatin1String("Extension")).toString(); |
||||
|
QString type = attrs.value(QLatin1String("ContentType")).toString(); |
||||
|
m_defaults.insert(extension, type); |
||||
|
} else if (reader.name() == QLatin1String("Override")) { |
||||
|
QXmlStreamAttributes attrs = reader.attributes(); |
||||
|
QString partName = attrs.value(QLatin1String("PartName")).toString(); |
||||
|
QString type = attrs.value(QLatin1String("ContentType")).toString(); |
||||
|
m_overrides.insert(partName, type); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (reader.hasError()) { |
||||
|
qDebug()<<reader.errorString(); |
||||
|
} |
||||
|
} |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
@ -0,0 +1,537 @@ |
|||||
|
// xlsxdatavalidation.cpp
|
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QXmlStreamReader> |
||||
|
#include <QXmlStreamWriter> |
||||
|
|
||||
|
#include "xlsxdatavalidation.h" |
||||
|
#include "xlsxdatavalidation_p.h" |
||||
|
#include "xlsxworksheet.h" |
||||
|
#include "xlsxcellrange.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
DataValidationPrivate::DataValidationPrivate() |
||||
|
:validationType(DataValidation::None), validationOperator(DataValidation::Between) |
||||
|
, errorStyle(DataValidation::Stop), allowBlank(false), isPromptMessageVisible(true) |
||||
|
, isErrorMessageVisible(true) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
DataValidationPrivate::DataValidationPrivate(DataValidation::ValidationType type, DataValidation::ValidationOperator op, const QString &formula1, const QString &formula2, bool allowBlank) |
||||
|
:validationType(type), validationOperator(op) |
||||
|
, errorStyle(DataValidation::Stop), allowBlank(allowBlank), isPromptMessageVisible(true) |
||||
|
, isErrorMessageVisible(true), formula1(formula1), formula2(formula2) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
DataValidationPrivate::DataValidationPrivate(const DataValidationPrivate &other) |
||||
|
:QSharedData(other) |
||||
|
, validationType(DataValidation::None), validationOperator(DataValidation::Between) |
||||
|
, errorStyle(DataValidation::Stop), allowBlank(false), isPromptMessageVisible(true) |
||||
|
, isErrorMessageVisible(true) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
DataValidationPrivate::~DataValidationPrivate() |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* \class DataValidation |
||||
|
* \brief Data validation for single cell or a range |
||||
|
* \inmodule QtXlsx |
||||
|
* |
||||
|
* The data validation can be applied to a single cell or a range of cells. |
||||
|
*/ |
||||
|
|
||||
|
/*!
|
||||
|
* \enum DataValidation::ValidationType |
||||
|
* |
||||
|
* The enum type defines the type of data that you wish to validate. |
||||
|
* |
||||
|
* \value None the type of data is unrestricted. This is the same as not applying a data validation. |
||||
|
* \value Whole restricts the cell to integer values. Means "Whole number"? |
||||
|
* \value Decimal restricts the cell to decimal values. |
||||
|
* \value List restricts the cell to a set of user specified values. |
||||
|
* \value Date restricts the cell to date values. |
||||
|
* \value Time restricts the cell to time values. |
||||
|
* \value TextLength restricts the cell data based on an integer string length. |
||||
|
* \value Custom restricts the cell based on an external Excel formula that returns a true/false value. |
||||
|
*/ |
||||
|
|
||||
|
/*!
|
||||
|
* \enum DataValidation::ValidationOperator |
||||
|
* |
||||
|
* The enum type defines the criteria by which the data in the |
||||
|
* cell is validated |
||||
|
* |
||||
|
* \value Between |
||||
|
* \value NotBetween |
||||
|
* \value Equal |
||||
|
* \value NotEqual |
||||
|
* \value LessThan |
||||
|
* \value LessThanOrEqual |
||||
|
* \value GreaterThan |
||||
|
* \value GreaterThanOrEqual |
||||
|
*/ |
||||
|
|
||||
|
/*!
|
||||
|
* \enum DataValidation::ErrorStyle |
||||
|
* |
||||
|
* The enum type defines the type of error dialog that |
||||
|
* is displayed. |
||||
|
* |
||||
|
* \value Stop |
||||
|
* \value Warning |
||||
|
* \value Information |
||||
|
*/ |
||||
|
|
||||
|
/*!
|
||||
|
* Construct a data validation object with the given \a type, \a op, \a formula1 |
||||
|
* \a formula2, and \a allowBlank. |
||||
|
*/ |
||||
|
DataValidation::DataValidation(ValidationType type, ValidationOperator op, const QString &formula1, const QString &formula2, bool allowBlank) |
||||
|
:d(new DataValidationPrivate(type, op, formula1, formula2, allowBlank)) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Construct a data validation object |
||||
|
*/ |
||||
|
DataValidation::DataValidation() |
||||
|
:d(new DataValidationPrivate()) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Constructs a copy of \a other. |
||||
|
*/ |
||||
|
DataValidation::DataValidation(const DataValidation &other) |
||||
|
:d(other.d) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Assigns \a other to this validation and returns a reference to this validation. |
||||
|
*/ |
||||
|
DataValidation &DataValidation::operator=(const DataValidation &other) |
||||
|
{ |
||||
|
this->d = other.d; |
||||
|
return *this; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/*!
|
||||
|
* Destroy the object. |
||||
|
*/ |
||||
|
DataValidation::~DataValidation() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Returns the validation type. |
||||
|
*/ |
||||
|
DataValidation::ValidationType DataValidation::validationType() const |
||||
|
{ |
||||
|
return d->validationType; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Returns the validation operator. |
||||
|
*/ |
||||
|
DataValidation::ValidationOperator DataValidation::validationOperator() const |
||||
|
{ |
||||
|
return d->validationOperator; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Returns the validation error style. |
||||
|
*/ |
||||
|
DataValidation::ErrorStyle DataValidation::errorStyle() const |
||||
|
{ |
||||
|
return d->errorStyle; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Returns the formula1. |
||||
|
*/ |
||||
|
QString DataValidation::formula1() const |
||||
|
{ |
||||
|
return d->formula1; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Returns the formula2. |
||||
|
*/ |
||||
|
QString DataValidation::formula2() const |
||||
|
{ |
||||
|
return d->formula2; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Returns whether blank is allowed. |
||||
|
*/ |
||||
|
bool DataValidation::allowBlank() const |
||||
|
{ |
||||
|
return d->allowBlank; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Returns the error message. |
||||
|
*/ |
||||
|
QString DataValidation::errorMessage() const |
||||
|
{ |
||||
|
return d->errorMessage; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Returns the error message title. |
||||
|
*/ |
||||
|
QString DataValidation::errorMessageTitle() const |
||||
|
{ |
||||
|
return d->errorMessageTitle; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Returns the prompt message. |
||||
|
*/ |
||||
|
QString DataValidation::promptMessage() const |
||||
|
{ |
||||
|
return d->promptMessage; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Returns the prompt message title. |
||||
|
*/ |
||||
|
QString DataValidation::promptMessageTitle() const |
||||
|
{ |
||||
|
return d->promptMessageTitle; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Returns the whether prompt message is shown. |
||||
|
*/ |
||||
|
bool DataValidation::isPromptMessageVisible() const |
||||
|
{ |
||||
|
return d->isPromptMessageVisible; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Returns the whether error message is shown. |
||||
|
*/ |
||||
|
bool DataValidation::isErrorMessageVisible() const |
||||
|
{ |
||||
|
return d->isErrorMessageVisible; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Returns the ranges on which the validation will be applied. |
||||
|
*/ |
||||
|
QList<CellRange> DataValidation::ranges() const |
||||
|
{ |
||||
|
return d->ranges; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Sets the validation type to \a type. |
||||
|
*/ |
||||
|
void DataValidation::setValidationType(DataValidation::ValidationType type) |
||||
|
{ |
||||
|
d->validationType = type; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Sets the validation operator to \a op. |
||||
|
*/ |
||||
|
void DataValidation::setValidationOperator(DataValidation::ValidationOperator op) |
||||
|
{ |
||||
|
d->validationOperator = op; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Sets the error style to \a es. |
||||
|
*/ |
||||
|
void DataValidation::setErrorStyle(DataValidation::ErrorStyle es) |
||||
|
{ |
||||
|
d->errorStyle = es; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Sets the formula1 to \a formula. |
||||
|
*/ |
||||
|
void DataValidation::setFormula1(const QString &formula) |
||||
|
{ |
||||
|
if (formula.startsWith(QLatin1Char('='))) |
||||
|
d->formula1 = formula.mid(1); |
||||
|
else |
||||
|
d->formula1 = formula; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Sets the formulas to \a formula. |
||||
|
*/ |
||||
|
void DataValidation::setFormula2(const QString &formula) |
||||
|
{ |
||||
|
if (formula.startsWith(QLatin1Char('='))) |
||||
|
d->formula2 = formula.mid(1); |
||||
|
else |
||||
|
d->formula2 = formula; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Sets the error message to \a error with title \a title. |
||||
|
*/ |
||||
|
void DataValidation::setErrorMessage(const QString &error, const QString &title) |
||||
|
{ |
||||
|
d->errorMessage = error; |
||||
|
d->errorMessageTitle = title; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Sets the prompt message to \a prompt with title \a title. |
||||
|
*/ |
||||
|
void DataValidation::setPromptMessage(const QString &prompt, const QString &title) |
||||
|
{ |
||||
|
d->promptMessage = prompt; |
||||
|
d->promptMessageTitle = title; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Enable/disabe blank allow based on \a enable. |
||||
|
*/ |
||||
|
void DataValidation::setAllowBlank(bool enable) |
||||
|
{ |
||||
|
d->allowBlank = enable; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Enable/disabe prompt message visible based on \a visible. |
||||
|
*/ |
||||
|
void DataValidation::setPromptMessageVisible(bool visible) |
||||
|
{ |
||||
|
d->isPromptMessageVisible = visible; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Enable/disabe error message visible based on \a visible. |
||||
|
*/ |
||||
|
void DataValidation::setErrorMessageVisible(bool visible) |
||||
|
{ |
||||
|
d->isErrorMessageVisible = visible; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Add the \a cell on which the DataValidation will apply to. |
||||
|
*/ |
||||
|
void DataValidation::addCell(const CellReference &cell) |
||||
|
{ |
||||
|
d->ranges.append(CellRange(cell, cell)); |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
\overload |
||||
|
Add the cell(\a row, \a col) on which the DataValidation will apply to. |
||||
|
*/ |
||||
|
void DataValidation::addCell(int row, int col) |
||||
|
{ |
||||
|
d->ranges.append(CellRange(row, col, row, col)); |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
\overload |
||||
|
Add the range(\a firstRow, \a firstCol, \a lastRow, \a lastCol) on |
||||
|
which the DataValidation will apply to. |
||||
|
*/ |
||||
|
void DataValidation::addRange(int firstRow, int firstCol, int lastRow, int lastCol) |
||||
|
{ |
||||
|
d->ranges.append(CellRange(firstRow, firstCol, lastRow, lastCol)); |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Add the \a range on which the DataValidation will apply to. |
||||
|
*/ |
||||
|
void DataValidation::addRange(const CellRange &range) |
||||
|
{ |
||||
|
d->ranges.append(range); |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* \internal |
||||
|
*/ |
||||
|
bool DataValidation::saveToXml(QXmlStreamWriter &writer) const |
||||
|
{ |
||||
|
static const QMap<DataValidation::ValidationType, QString> typeMap = { |
||||
|
{DataValidation::None, QStringLiteral("none")}, |
||||
|
{DataValidation::Whole, QStringLiteral("whole")}, |
||||
|
{DataValidation::Decimal, QStringLiteral("decimal")}, |
||||
|
{DataValidation::List, QStringLiteral("list")}, |
||||
|
{DataValidation::Date, QStringLiteral("date")}, |
||||
|
{DataValidation::Time, QStringLiteral("time")}, |
||||
|
{DataValidation::TextLength, QStringLiteral("textLength")}, |
||||
|
{DataValidation::Custom, QStringLiteral("custom")} |
||||
|
}; |
||||
|
|
||||
|
static const QMap<DataValidation::ValidationOperator, QString> opMap = { |
||||
|
{DataValidation::Between, QStringLiteral("between")}, |
||||
|
{DataValidation::NotBetween, QStringLiteral("notBetween")}, |
||||
|
{DataValidation::Equal, QStringLiteral("equal")}, |
||||
|
{DataValidation::NotEqual, QStringLiteral("notEqual")}, |
||||
|
{DataValidation::LessThan, QStringLiteral("lessThan")}, |
||||
|
{DataValidation::LessThanOrEqual, QStringLiteral("lessThanOrEqual")}, |
||||
|
{DataValidation::GreaterThan, QStringLiteral("greaterThan")}, |
||||
|
{DataValidation::GreaterThanOrEqual, QStringLiteral("greaterThanOrEqual")} |
||||
|
}; |
||||
|
|
||||
|
static const QMap<DataValidation::ErrorStyle, QString> esMap = { |
||||
|
{DataValidation::Stop, QStringLiteral("stop")}, |
||||
|
{DataValidation::Warning, QStringLiteral("warning")}, |
||||
|
{DataValidation::Information, QStringLiteral("information")} |
||||
|
}; |
||||
|
|
||||
|
writer.writeStartElement(QStringLiteral("dataValidation")); |
||||
|
if (validationType() != DataValidation::None) |
||||
|
writer.writeAttribute(QStringLiteral("type"), typeMap[validationType()]); |
||||
|
if (errorStyle() != DataValidation::Stop) |
||||
|
writer.writeAttribute(QStringLiteral("errorStyle"), esMap[errorStyle()]); |
||||
|
if (validationOperator() != DataValidation::Between) |
||||
|
writer.writeAttribute(QStringLiteral("operator"), opMap[validationOperator()]); |
||||
|
if (allowBlank()) |
||||
|
writer.writeAttribute(QStringLiteral("allowBlank"), QStringLiteral("1")); |
||||
|
// if (dropDownVisible())
|
||||
|
// writer.writeAttribute(QStringLiteral("showDropDown"), QStringLiteral("1"));
|
||||
|
if (isPromptMessageVisible()) |
||||
|
writer.writeAttribute(QStringLiteral("showInputMessage"), QStringLiteral("1")); |
||||
|
if (isErrorMessageVisible()) |
||||
|
writer.writeAttribute(QStringLiteral("showErrorMessage"), QStringLiteral("1")); |
||||
|
if (!errorMessageTitle().isEmpty()) |
||||
|
writer.writeAttribute(QStringLiteral("errorTitle"), errorMessageTitle()); |
||||
|
if (!errorMessage().isEmpty()) |
||||
|
writer.writeAttribute(QStringLiteral("error"), errorMessage()); |
||||
|
if (!promptMessageTitle().isEmpty()) |
||||
|
writer.writeAttribute(QStringLiteral("promptTitle"), promptMessageTitle()); |
||||
|
if (!promptMessage().isEmpty()) |
||||
|
writer.writeAttribute(QStringLiteral("prompt"), promptMessage()); |
||||
|
|
||||
|
QStringList sqref; |
||||
|
const auto rangeList = ranges(); |
||||
|
for (const CellRange &range : rangeList) |
||||
|
sqref.append(range.toString()); |
||||
|
writer.writeAttribute(QStringLiteral("sqref"), sqref.join(QLatin1String(" "))); |
||||
|
|
||||
|
if (!formula1().isEmpty()) |
||||
|
writer.writeTextElement(QStringLiteral("formula1"), formula1()); |
||||
|
if (!formula2().isEmpty()) |
||||
|
writer.writeTextElement(QStringLiteral("formula2"), formula2()); |
||||
|
|
||||
|
writer.writeEndElement(); //dataValidation
|
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* \internal |
||||
|
*/ |
||||
|
DataValidation DataValidation::loadFromXml(QXmlStreamReader &reader) |
||||
|
{ |
||||
|
Q_ASSERT(reader.name() == QLatin1String("dataValidation")); |
||||
|
|
||||
|
static const QMap<QString, DataValidation::ValidationType> typeMap = { |
||||
|
{QStringLiteral("none"), DataValidation::None}, |
||||
|
{QStringLiteral("whole"), DataValidation::Whole}, |
||||
|
{QStringLiteral("decimal"), DataValidation::Decimal}, |
||||
|
{QStringLiteral("list"), DataValidation::List}, |
||||
|
{QStringLiteral("date"), DataValidation::Date}, |
||||
|
{QStringLiteral("time"), DataValidation::Time}, |
||||
|
{QStringLiteral("textLength"), DataValidation::TextLength}, |
||||
|
{QStringLiteral("custom"), DataValidation::Custom} |
||||
|
}; |
||||
|
|
||||
|
static const QMap<QString, DataValidation::ValidationOperator> opMap = { |
||||
|
{QStringLiteral("between"), DataValidation::Between}, |
||||
|
{QStringLiteral("notBetween"), DataValidation::NotBetween}, |
||||
|
{QStringLiteral("equal"), DataValidation::Equal}, |
||||
|
{QStringLiteral("notEqual"), DataValidation::NotEqual}, |
||||
|
{QStringLiteral("lessThan"), DataValidation::LessThan}, |
||||
|
{QStringLiteral("lessThanOrEqual"), DataValidation::LessThanOrEqual}, |
||||
|
{QStringLiteral("greaterThan"), DataValidation::GreaterThan}, |
||||
|
{QStringLiteral("greaterThanOrEqual"), DataValidation::GreaterThanOrEqual} |
||||
|
}; |
||||
|
|
||||
|
static const QMap<QString, DataValidation::ErrorStyle> esMap = { |
||||
|
{QStringLiteral("stop"), DataValidation::Stop}, |
||||
|
{QStringLiteral("warning"), DataValidation::Warning}, |
||||
|
{QStringLiteral("information"), DataValidation::Information} |
||||
|
}; |
||||
|
|
||||
|
DataValidation validation; |
||||
|
QXmlStreamAttributes attrs = reader.attributes(); |
||||
|
|
||||
|
QString sqref = attrs.value(QLatin1String("sqref")).toString(); |
||||
|
const auto sqrefParts = sqref.split(QLatin1Char(' ')); |
||||
|
for (const QString &range : sqrefParts) |
||||
|
validation.addRange(range); |
||||
|
|
||||
|
if (attrs.hasAttribute(QLatin1String("type"))) { |
||||
|
QString t = attrs.value(QLatin1String("type")).toString(); |
||||
|
auto it = typeMap.constFind(t); |
||||
|
validation.setValidationType(it != typeMap.constEnd() ? it.value() : DataValidation::None); |
||||
|
} |
||||
|
if (attrs.hasAttribute(QLatin1String("errorStyle"))) { |
||||
|
QString es = attrs.value(QLatin1String("errorStyle")).toString(); |
||||
|
auto it = esMap.constFind(es); |
||||
|
validation.setErrorStyle(it != esMap.constEnd() ? it.value() : DataValidation::Stop); |
||||
|
} |
||||
|
if (attrs.hasAttribute(QLatin1String("operator"))) { |
||||
|
QString op = attrs.value(QLatin1String("operator")).toString(); |
||||
|
auto it = opMap.constFind(op); |
||||
|
validation.setValidationOperator(it != opMap.constEnd() ? it.value() : DataValidation::Between); |
||||
|
} |
||||
|
if (attrs.hasAttribute(QLatin1String("allowBlank"))) { |
||||
|
validation.setAllowBlank(true); |
||||
|
} else { |
||||
|
validation.setAllowBlank(false); |
||||
|
} |
||||
|
if (attrs.hasAttribute(QLatin1String("showInputMessage"))) { |
||||
|
validation.setPromptMessageVisible(true); |
||||
|
} else { |
||||
|
validation.setPromptMessageVisible(false); |
||||
|
} |
||||
|
if (attrs.hasAttribute(QLatin1String("showErrorMessage"))) { |
||||
|
validation.setErrorMessageVisible(true); |
||||
|
} else { |
||||
|
validation.setErrorMessageVisible(false); |
||||
|
} |
||||
|
|
||||
|
QString et = attrs.value(QLatin1String("errorTitle")).toString(); |
||||
|
QString e = attrs.value(QLatin1String("error")).toString(); |
||||
|
if (!e.isEmpty() || !et.isEmpty()) |
||||
|
validation.setErrorMessage(e, et); |
||||
|
|
||||
|
QString pt = attrs.value(QLatin1String("promptTitle")).toString(); |
||||
|
QString p = attrs.value(QLatin1String("prompt")).toString(); |
||||
|
if (!p.isEmpty() || !pt.isEmpty()) |
||||
|
validation.setPromptMessage(p, pt); |
||||
|
|
||||
|
//find the end
|
||||
|
while(!(reader.name() == QLatin1String("dataValidation") && reader.tokenType() == QXmlStreamReader::EndElement)) { |
||||
|
reader.readNextStartElement(); |
||||
|
if (reader.tokenType() == QXmlStreamReader::StartElement) { |
||||
|
if (reader.name() == QLatin1String("formula1")) { |
||||
|
validation.setFormula1(reader.readElementText()); |
||||
|
} else if (reader.name() == QLatin1String("formula2")) { |
||||
|
validation.setFormula2(reader.readElementText()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return validation; |
||||
|
} |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
@ -0,0 +1,85 @@ |
|||||
|
// xlsxdatetype.cpp
|
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
|
||||
|
#include "xlsxglobal.h" |
||||
|
#include "xlsxutility_p.h" |
||||
|
#include "xlsxdatetype.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
DateType::DateType() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/*
|
||||
|
DateType::DateType(bool is1904) |
||||
|
{ |
||||
|
isSet = false; |
||||
|
} |
||||
|
|
||||
|
DateType::DateType(double d, bool is1904) |
||||
|
{ |
||||
|
// TODO: check date
|
||||
|
|
||||
|
// int iVaue = (int) d;
|
||||
|
// double surplus = d - double(iVaue);
|
||||
|
|
||||
|
dValue = d; |
||||
|
is1904Type = is1904; |
||||
|
isSet = true; |
||||
|
} |
||||
|
|
||||
|
DateType::DateType(QDateTime qdt, bool is1904) |
||||
|
{ |
||||
|
double ret = datetimeToNumber( qdt, is1904 ); |
||||
|
dValue = ret; |
||||
|
is1904Type = is1904; |
||||
|
isSet = true; |
||||
|
} |
||||
|
|
||||
|
DateType::DateType(QDate qd, bool is1904) |
||||
|
{ |
||||
|
|
||||
|
is1904Type = is1904; |
||||
|
isSet = true; |
||||
|
} |
||||
|
|
||||
|
DateType::DateType(QTime qt, bool is1904) |
||||
|
{ |
||||
|
double ret = timeToNumber( qt ); |
||||
|
dValue = ret; |
||||
|
is1904Type = is1904; |
||||
|
isSet = true; |
||||
|
} |
||||
|
|
||||
|
// enum currentDateType { DateAndTimeType, OnlyDateType, OnlyTimeType };
|
||||
|
|
||||
|
DateType::currentDateType DateType::getType() |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
bool DateType::getValue(QDateTime* pQdt) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
bool DateType::getValue(QDate* pQd) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
bool DateType::getValue(QTime* pQt) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
bool DateType::getValue(double* pD) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
*/ |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
@ -0,0 +1,138 @@ |
|||||
|
// xlsxdocpropsapp.cpp
|
||||
|
|
||||
|
#include "xlsxdocpropsapp_p.h" |
||||
|
|
||||
|
#include <QXmlStreamWriter> |
||||
|
#include <QXmlStreamReader> |
||||
|
#include <QDir> |
||||
|
#include <QFile> |
||||
|
#include <QDateTime> |
||||
|
#include <QVariant> |
||||
|
#include <QBuffer> |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
DocPropsApp::DocPropsApp(CreateFlag flag) |
||||
|
:AbstractOOXmlFile(flag) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
void DocPropsApp::addPartTitle(const QString &title) |
||||
|
{ |
||||
|
m_titlesOfPartsList.append(title); |
||||
|
} |
||||
|
|
||||
|
void DocPropsApp::addHeadingPair(const QString &name, int value) |
||||
|
{ |
||||
|
m_headingPairsList.append({ name, value }); |
||||
|
} |
||||
|
|
||||
|
bool DocPropsApp::setProperty(const QString &name, const QString &value) |
||||
|
{ |
||||
|
static const QStringList validKeys = { |
||||
|
QStringLiteral("manager"), QStringLiteral("company") |
||||
|
}; |
||||
|
|
||||
|
if (!validKeys.contains(name)) |
||||
|
return false; |
||||
|
|
||||
|
if (value.isEmpty()) |
||||
|
m_properties.remove(name); |
||||
|
else |
||||
|
m_properties[name] = value; |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
QString DocPropsApp::property(const QString &name) const |
||||
|
{ |
||||
|
auto it = m_properties.constFind(name); |
||||
|
if (it != m_properties.constEnd()) |
||||
|
return it.value(); |
||||
|
|
||||
|
return QString(); |
||||
|
} |
||||
|
|
||||
|
QStringList DocPropsApp::propertyNames() const |
||||
|
{ |
||||
|
return m_properties.keys(); |
||||
|
} |
||||
|
|
||||
|
void DocPropsApp::saveToXmlFile(QIODevice *device) const |
||||
|
{ |
||||
|
QXmlStreamWriter writer(device); |
||||
|
QString vt = QStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"); |
||||
|
|
||||
|
writer.writeStartDocument(QStringLiteral("1.0"), true); |
||||
|
writer.writeStartElement(QStringLiteral("Properties")); |
||||
|
writer.writeDefaultNamespace(QStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/extended-properties")); |
||||
|
writer.writeNamespace(vt, QStringLiteral("vt")); |
||||
|
writer.writeTextElement(QStringLiteral("Application"), QStringLiteral("Microsoft Excel")); |
||||
|
writer.writeTextElement(QStringLiteral("DocSecurity"), QStringLiteral("0")); |
||||
|
writer.writeTextElement(QStringLiteral("ScaleCrop"), QStringLiteral("false")); |
||||
|
|
||||
|
writer.writeStartElement(QStringLiteral("HeadingPairs")); |
||||
|
writer.writeStartElement(vt, QStringLiteral("vector")); |
||||
|
writer.writeAttribute(QStringLiteral("size"), QString::number(m_headingPairsList.size()*2)); |
||||
|
writer.writeAttribute(QStringLiteral("baseType"), QStringLiteral("variant")); |
||||
|
|
||||
|
for (const auto &pair : m_headingPairsList) { |
||||
|
writer.writeStartElement(vt, QStringLiteral("variant")); |
||||
|
writer.writeTextElement(vt, QStringLiteral("lpstr"), pair.first); |
||||
|
writer.writeEndElement(); //vt:variant
|
||||
|
writer.writeStartElement(vt, QStringLiteral("variant")); |
||||
|
writer.writeTextElement(vt, QStringLiteral("i4"), QString::number(pair.second)); |
||||
|
writer.writeEndElement(); //vt:variant
|
||||
|
} |
||||
|
writer.writeEndElement();//vt:vector
|
||||
|
writer.writeEndElement();//HeadingPairs
|
||||
|
|
||||
|
writer.writeStartElement(QStringLiteral("TitlesOfParts")); |
||||
|
writer.writeStartElement(vt, QStringLiteral("vector")); |
||||
|
writer.writeAttribute(QStringLiteral("size"), QString::number(m_titlesOfPartsList.size())); |
||||
|
writer.writeAttribute(QStringLiteral("baseType"), QStringLiteral("lpstr")); |
||||
|
for (const QString &title : m_titlesOfPartsList) |
||||
|
writer.writeTextElement(vt, QStringLiteral("lpstr"), title); |
||||
|
writer.writeEndElement();//vt:vector
|
||||
|
writer.writeEndElement();//TitlesOfParts
|
||||
|
|
||||
|
auto it = m_properties.constFind(QStringLiteral("manager")); |
||||
|
if (it != m_properties.constEnd()) |
||||
|
writer.writeTextElement(QStringLiteral("Manager"), it.value()); |
||||
|
//Not like "manager", "company" always exists for Excel generated file.
|
||||
|
|
||||
|
it = m_properties.constFind(QStringLiteral("company")); |
||||
|
writer.writeTextElement(QStringLiteral("Company"), it != m_properties.constEnd() ? it.value() : QString()); |
||||
|
writer.writeTextElement(QStringLiteral("LinksUpToDate"), QStringLiteral("false")); |
||||
|
writer.writeTextElement(QStringLiteral("SharedDoc"), QStringLiteral("false")); |
||||
|
writer.writeTextElement(QStringLiteral("HyperlinksChanged"), QStringLiteral("false")); |
||||
|
writer.writeTextElement(QStringLiteral("AppVersion"), QStringLiteral("12.0000")); |
||||
|
|
||||
|
writer.writeEndElement(); //Properties
|
||||
|
writer.writeEndDocument(); |
||||
|
} |
||||
|
|
||||
|
bool DocPropsApp::loadFromXmlFile(QIODevice *device) |
||||
|
{ |
||||
|
QXmlStreamReader reader(device); |
||||
|
while (!reader.atEnd()) { |
||||
|
QXmlStreamReader::TokenType token = reader.readNext(); |
||||
|
if (token == QXmlStreamReader::StartElement) { |
||||
|
if (reader.name() == QLatin1String("Properties")) |
||||
|
continue; |
||||
|
|
||||
|
if (reader.name() == QStringLiteral("Manager")) { |
||||
|
setProperty(QStringLiteral("manager"), reader.readElementText()); |
||||
|
} else if (reader.name() == QStringLiteral("Company")) { |
||||
|
setProperty(QStringLiteral("company"), reader.readElementText()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (reader.hasError()) { |
||||
|
qDebug("Error when read doc props app file."); |
||||
|
} |
||||
|
} |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
@ -0,0 +1,176 @@ |
|||||
|
// xlsxdocpropscore.cpp
|
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QXmlStreamWriter> |
||||
|
#include <QXmlStreamReader> |
||||
|
#include <QDir> |
||||
|
#include <QFile> |
||||
|
#include <QDateTime> |
||||
|
#include <QDebug> |
||||
|
#include <QBuffer> |
||||
|
|
||||
|
#include "xlsxdocpropscore_p.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
DocPropsCore::DocPropsCore(CreateFlag flag) |
||||
|
:AbstractOOXmlFile(flag) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
bool DocPropsCore::setProperty(const QString &name, const QString &value) |
||||
|
{ |
||||
|
static const QStringList validKeys = { |
||||
|
QStringLiteral("title"), QStringLiteral("subject"), |
||||
|
QStringLiteral("keywords"), QStringLiteral("description"), |
||||
|
QStringLiteral("category"), QStringLiteral("status"), |
||||
|
QStringLiteral("created"), QStringLiteral("creator") |
||||
|
}; |
||||
|
|
||||
|
if (!validKeys.contains(name)) |
||||
|
return false; |
||||
|
|
||||
|
if (value.isEmpty()) |
||||
|
m_properties.remove(name); |
||||
|
else |
||||
|
m_properties[name] = value; |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
QString DocPropsCore::property(const QString &name) const |
||||
|
{ |
||||
|
auto it = m_properties.constFind(name); |
||||
|
if (it != m_properties.constEnd()) |
||||
|
return it.value(); |
||||
|
|
||||
|
return QString(); |
||||
|
} |
||||
|
|
||||
|
QStringList DocPropsCore::propertyNames() const |
||||
|
{ |
||||
|
return m_properties.keys(); |
||||
|
} |
||||
|
|
||||
|
void DocPropsCore::saveToXmlFile(QIODevice *device) const |
||||
|
{ |
||||
|
QXmlStreamWriter writer(device); |
||||
|
const QString cp = QStringLiteral("http://schemas.openxmlformats.org/package/2006/metadata/core-properties"); |
||||
|
const QString dc = QStringLiteral("http://purl.org/dc/elements/1.1/"); |
||||
|
const QString dcterms = QStringLiteral("http://purl.org/dc/terms/"); |
||||
|
const QString dcmitype = QStringLiteral("http://purl.org/dc/dcmitype/"); |
||||
|
const QString xsi = QStringLiteral("http://www.w3.org/2001/XMLSchema-instance"); |
||||
|
writer.writeStartDocument(QStringLiteral("1.0"), true); |
||||
|
writer.writeStartElement(QStringLiteral("cp:coreProperties")); |
||||
|
writer.writeNamespace(cp, QStringLiteral("cp")); |
||||
|
writer.writeNamespace(dc, QStringLiteral("dc")); |
||||
|
writer.writeNamespace(dcterms, QStringLiteral("dcterms")); |
||||
|
writer.writeNamespace(dcmitype, QStringLiteral("dcmitype")); |
||||
|
writer.writeNamespace(xsi, QStringLiteral("xsi")); |
||||
|
|
||||
|
auto it = m_properties.constFind(QStringLiteral("title")); |
||||
|
if (it != m_properties.constEnd()) |
||||
|
writer.writeTextElement(dc, QStringLiteral("title"), it.value()); |
||||
|
|
||||
|
it = m_properties.constFind(QStringLiteral("subject")); |
||||
|
if (it != m_properties.constEnd()) |
||||
|
writer.writeTextElement(dc, QStringLiteral("subject"), it.value()); |
||||
|
|
||||
|
it = m_properties.constFind(QStringLiteral("creator")); |
||||
|
writer.writeTextElement(dc, QStringLiteral("creator"), it != m_properties.constEnd() ? it.value() : QStringLiteral("Qt Xlsx Library")); |
||||
|
|
||||
|
it = m_properties.constFind(QStringLiteral("keywords")); |
||||
|
if (it != m_properties.constEnd()) |
||||
|
writer.writeTextElement(cp, QStringLiteral("keywords"), it.value()); |
||||
|
|
||||
|
it = m_properties.constFind(QStringLiteral("description")); |
||||
|
if (it != m_properties.constEnd()) |
||||
|
writer.writeTextElement(dc, QStringLiteral("description"), it.value()); |
||||
|
|
||||
|
it = m_properties.constFind(QStringLiteral("creator")); |
||||
|
writer.writeTextElement(cp, QStringLiteral("lastModifiedBy"), it != m_properties.constEnd() ? it.value() : QStringLiteral("Qt Xlsx Library")); |
||||
|
|
||||
|
writer.writeStartElement(dcterms, QStringLiteral("created")); |
||||
|
writer.writeAttribute(xsi, QStringLiteral("type"), QStringLiteral("dcterms:W3CDTF")); |
||||
|
it = m_properties.constFind(QStringLiteral("created")); |
||||
|
writer.writeCharacters(it != m_properties.constEnd() ? it.value() : QDateTime::currentDateTime().toString(Qt::ISODate)); |
||||
|
writer.writeEndElement();//dcterms:created
|
||||
|
|
||||
|
writer.writeStartElement(dcterms, QStringLiteral("modified")); |
||||
|
writer.writeAttribute(xsi, QStringLiteral("type"), QStringLiteral("dcterms:W3CDTF")); |
||||
|
writer.writeCharacters(QDateTime::currentDateTime().toString(Qt::ISODate)); |
||||
|
writer.writeEndElement();//dcterms:created
|
||||
|
|
||||
|
it = m_properties.constFind(QStringLiteral("category")); |
||||
|
if (it != m_properties.constEnd()) |
||||
|
writer.writeTextElement(cp, QStringLiteral("category"), it.value()); |
||||
|
|
||||
|
it = m_properties.constFind(QStringLiteral("status")); |
||||
|
if (it != m_properties.constEnd()) |
||||
|
writer.writeTextElement(cp, QStringLiteral("contentStatus"), it.value()); |
||||
|
|
||||
|
writer.writeEndElement(); //cp:coreProperties
|
||||
|
writer.writeEndDocument(); |
||||
|
} |
||||
|
|
||||
|
bool DocPropsCore::loadFromXmlFile(QIODevice *device) |
||||
|
{ |
||||
|
QXmlStreamReader reader(device); |
||||
|
|
||||
|
const QString cp = QStringLiteral("http://schemas.openxmlformats.org/package/2006/metadata/core-properties"); |
||||
|
const QString dc = QStringLiteral("http://purl.org/dc/elements/1.1/"); |
||||
|
const QString dcterms = QStringLiteral("http://purl.org/dc/terms/"); |
||||
|
|
||||
|
while (!reader.atEnd()) |
||||
|
{ |
||||
|
QXmlStreamReader::TokenType token = reader.readNext(); |
||||
|
|
||||
|
if (token == QXmlStreamReader::StartElement) |
||||
|
{ |
||||
|
|
||||
|
const auto& nsUri = reader.namespaceUri(); |
||||
|
const auto& name = reader.name(); |
||||
|
|
||||
|
if (name == QStringLiteral("subject") && nsUri == dc) |
||||
|
{ |
||||
|
setProperty(QStringLiteral("subject"), reader.readElementText()); |
||||
|
} |
||||
|
else if (name == QStringLiteral("title") && nsUri == dc) |
||||
|
{ |
||||
|
setProperty(QStringLiteral("title"), reader.readElementText()); |
||||
|
} |
||||
|
else if (name == QStringLiteral("creator") && nsUri == dc) |
||||
|
{ |
||||
|
setProperty(QStringLiteral("creator"), reader.readElementText()); |
||||
|
} |
||||
|
else if (name == QStringLiteral("description") && nsUri == dc) |
||||
|
{ |
||||
|
setProperty(QStringLiteral("description"), reader.readElementText()); |
||||
|
} |
||||
|
else if (name == QStringLiteral("keywords") && nsUri == cp) |
||||
|
{ |
||||
|
setProperty(QStringLiteral("keywords"), reader.readElementText()); |
||||
|
} |
||||
|
else if (name == QStringLiteral("created") && nsUri == dcterms) |
||||
|
{ |
||||
|
setProperty(QStringLiteral("created"), reader.readElementText()); |
||||
|
} |
||||
|
else if (name == QStringLiteral("category") && nsUri == cp) |
||||
|
{ |
||||
|
setProperty(QStringLiteral("category"), reader.readElementText()); |
||||
|
} |
||||
|
else if (name == QStringLiteral("contentStatus") && nsUri == cp) |
||||
|
{ |
||||
|
setProperty(QStringLiteral("status"), reader.readElementText()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (reader.hasError()) |
||||
|
{ |
||||
|
qDebug() << "Error when read doc props core file." << reader.errorString(); |
||||
|
} |
||||
|
} |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
File diff suppressed because it is too large
@ -0,0 +1,84 @@ |
|||||
|
// xlsxdrawing.cpp
|
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QXmlStreamWriter> |
||||
|
#include <QXmlStreamReader> |
||||
|
#include <QBuffer> |
||||
|
|
||||
|
#include "xlsxdrawing_p.h" |
||||
|
#include "xlsxdrawinganchor_p.h" |
||||
|
#include "xlsxabstractsheet.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
Drawing::Drawing(AbstractSheet *sheet, CreateFlag flag) |
||||
|
:AbstractOOXmlFile(flag), sheet(sheet) |
||||
|
{ |
||||
|
workbook = sheet->workbook(); |
||||
|
} |
||||
|
|
||||
|
Drawing::~Drawing() |
||||
|
{ |
||||
|
qDeleteAll(anchors); |
||||
|
} |
||||
|
|
||||
|
void Drawing::saveToXmlFile(QIODevice *device) const |
||||
|
{ |
||||
|
relationships()->clear(); |
||||
|
|
||||
|
QXmlStreamWriter writer(device); |
||||
|
|
||||
|
writer.writeStartDocument(QStringLiteral("1.0"), true); |
||||
|
writer.writeStartElement(QStringLiteral("xdr:wsDr")); |
||||
|
writer.writeAttribute(QStringLiteral("xmlns:xdr"), QStringLiteral("http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing")); |
||||
|
writer.writeAttribute(QStringLiteral("xmlns:a"), QStringLiteral("http://schemas.openxmlformats.org/drawingml/2006/main")); |
||||
|
|
||||
|
for (DrawingAnchor *anchor : anchors) |
||||
|
anchor->saveToXml(writer); |
||||
|
|
||||
|
writer.writeEndElement();//xdr:wsDr
|
||||
|
writer.writeEndDocument(); |
||||
|
} |
||||
|
|
||||
|
// check point
|
||||
|
bool Drawing::loadFromXmlFile(QIODevice *device) |
||||
|
{ |
||||
|
/*
|
||||
|
<xsd:group name="EG_Anchor"> |
||||
|
<xsd:choice> |
||||
|
<xsd:element name="twoCellAnchor" type="CT_TwoCellAnchor"/> |
||||
|
<xsd:element name="oneCellAnchor" type="CT_OneCellAnchor"/> |
||||
|
<xsd:element name="absoluteAnchor" type="CT_AbsoluteAnchor"/> |
||||
|
</xsd:choice> |
||||
|
</xsd:group> |
||||
|
*/ |
||||
|
|
||||
|
QXmlStreamReader reader(device); |
||||
|
|
||||
|
while (!reader.atEnd()) |
||||
|
{ |
||||
|
reader.readNextStartElement(); |
||||
|
if (reader.tokenType() == QXmlStreamReader::StartElement) |
||||
|
{ |
||||
|
if (reader.name() == QLatin1String("absoluteAnchor")) // CT_AbsoluteAnchor
|
||||
|
{ |
||||
|
DrawingAbsoluteAnchor * anchor = new DrawingAbsoluteAnchor(this); |
||||
|
anchor->loadFromXml(reader); |
||||
|
} |
||||
|
else if (reader.name() == QLatin1String("oneCellAnchor")) // CT_OneCellAnchor
|
||||
|
{ |
||||
|
DrawingOneCellAnchor * anchor = new DrawingOneCellAnchor(this); |
||||
|
anchor->loadFromXml(reader); |
||||
|
} |
||||
|
else if (reader.name() == QLatin1String("twoCellAnchor")) // CT_TwoCellAnchor
|
||||
|
{ |
||||
|
DrawingTwoCellAnchor * anchor = new DrawingTwoCellAnchor(this); |
||||
|
anchor->loadFromXml(reader); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
File diff suppressed because it is too large
File diff suppressed because it is too large
@ -0,0 +1,78 @@ |
|||||
|
// xlsxmediafile.cpp
|
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QCryptographicHash> |
||||
|
|
||||
|
#include "xlsxmediafile_p.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
MediaFile::MediaFile(const QByteArray &bytes, const QString &suffix, const QString &mimeType) |
||||
|
: m_contents(bytes), m_suffix(suffix), m_mimeType(mimeType) |
||||
|
, m_index(0), m_indexValid(false) |
||||
|
{ |
||||
|
m_hashKey = QCryptographicHash::hash(m_contents, QCryptographicHash::Md5); |
||||
|
} |
||||
|
|
||||
|
MediaFile::MediaFile(const QString &fileName) |
||||
|
:m_fileName(fileName), m_index(0), m_indexValid(false) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
void MediaFile::set(const QByteArray &bytes, const QString &suffix, const QString &mimeType) |
||||
|
{ |
||||
|
m_contents = bytes; |
||||
|
m_suffix = suffix; |
||||
|
m_mimeType = mimeType; |
||||
|
m_hashKey = QCryptographicHash::hash(m_contents, QCryptographicHash::Md5); |
||||
|
m_indexValid = false; |
||||
|
} |
||||
|
|
||||
|
void MediaFile::setFileName(const QString &name) |
||||
|
{ |
||||
|
m_fileName = name; |
||||
|
} |
||||
|
|
||||
|
QString MediaFile::fileName() const |
||||
|
{ |
||||
|
return m_fileName; |
||||
|
} |
||||
|
|
||||
|
QString MediaFile::suffix() const |
||||
|
{ |
||||
|
return m_suffix; |
||||
|
} |
||||
|
|
||||
|
QString MediaFile::mimeType() const |
||||
|
{ |
||||
|
return m_mimeType; |
||||
|
} |
||||
|
|
||||
|
QByteArray MediaFile::contents() const |
||||
|
{ |
||||
|
return m_contents; |
||||
|
} |
||||
|
|
||||
|
int MediaFile::index() const |
||||
|
{ |
||||
|
return m_index; |
||||
|
} |
||||
|
|
||||
|
bool MediaFile::isIndexValid() const |
||||
|
{ |
||||
|
return m_indexValid; |
||||
|
} |
||||
|
|
||||
|
void MediaFile::setIndex(int idx) |
||||
|
{ |
||||
|
m_index = idx; |
||||
|
m_indexValid = true; |
||||
|
} |
||||
|
|
||||
|
QByteArray MediaFile::hashKey() const |
||||
|
{ |
||||
|
return m_hashKey; |
||||
|
} |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
@ -0,0 +1,74 @@ |
|||||
|
// xlsxnumformatparser.cpp
|
||||
|
|
||||
|
#include "xlsxnumformatparser_p.h" |
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QString> |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
bool NumFormatParser::isDateTime(const QString &formatCode) |
||||
|
{ |
||||
|
for (int i = 0; i < formatCode.length(); ++i) { |
||||
|
const QChar &c = formatCode[i]; |
||||
|
|
||||
|
switch (c.unicode()) { |
||||
|
case '[': |
||||
|
// [h], [m], [s] are valid format for time
|
||||
|
if (i < formatCode.length()-2 && formatCode[i+2] == QLatin1Char(']')) { |
||||
|
const QChar cc = formatCode[i+1].toLower(); |
||||
|
if (cc == QLatin1Char('h') || cc == QLatin1Char('m') || cc == QLatin1Char('s')) |
||||
|
return true; |
||||
|
i+=2; |
||||
|
break; |
||||
|
} else { |
||||
|
// condition or color: don't care, ignore
|
||||
|
while (i < formatCode.length() && formatCode[i] != QLatin1Char(']')) |
||||
|
++i; |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
// quoted plain text block: don't care, ignore
|
||||
|
case '"': |
||||
|
while (i < formatCode.length()-1 && formatCode[++i] != QLatin1Char('"')) |
||||
|
; |
||||
|
break; |
||||
|
|
||||
|
// escaped char: don't care, ignore
|
||||
|
case '\\': |
||||
|
if (i < formatCode.length() - 1) |
||||
|
++i; |
||||
|
break; |
||||
|
|
||||
|
// date/time can only be positive number,
|
||||
|
// so only the first section of the format make sense.
|
||||
|
case '#': // this is new an working // https://github.com/QtExcel/QXlsx/issues/190
|
||||
|
case ';': |
||||
|
return false; |
||||
|
break; |
||||
|
|
||||
|
// days
|
||||
|
case 'D': |
||||
|
case 'd': |
||||
|
// years
|
||||
|
case 'Y': |
||||
|
case 'y': |
||||
|
// hours
|
||||
|
case 'H': |
||||
|
case 'h': |
||||
|
// seconds
|
||||
|
case 'S': |
||||
|
case 's': |
||||
|
// minutes or months, depending on context
|
||||
|
case 'M': |
||||
|
case 'm': |
||||
|
return true; |
||||
|
|
||||
|
default: |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
@ -0,0 +1,169 @@ |
|||||
|
// xlsxrelationships.cpp
|
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QXmlStreamWriter> |
||||
|
#include <QXmlStreamReader> |
||||
|
#include <QDir> |
||||
|
#include <QFile> |
||||
|
#include <QBuffer> |
||||
|
|
||||
|
#include "xlsxrelationships_p.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
const QLatin1String schema_doc("http://schemas.openxmlformats.org/officeDocument/2006/relationships"); |
||||
|
const QLatin1String schema_msPackage("http://schemas.microsoft.com/office/2006/relationships"); |
||||
|
const QLatin1String schema_package("http://schemas.openxmlformats.org/package/2006/relationships"); |
||||
|
//const QString schema_worksheet = QStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/relationships");
|
||||
|
Relationships::Relationships() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
QList<XlsxRelationship> Relationships::documentRelationships(const QString &relativeType) const |
||||
|
{ |
||||
|
return relationships(schema_doc + relativeType); |
||||
|
} |
||||
|
|
||||
|
void Relationships::addDocumentRelationship(const QString &relativeType, const QString &target) |
||||
|
{ |
||||
|
addRelationship(schema_doc + relativeType, target); |
||||
|
} |
||||
|
|
||||
|
QList<XlsxRelationship> Relationships::msPackageRelationships(const QString &relativeType) const |
||||
|
{ |
||||
|
return relationships(schema_msPackage + relativeType); |
||||
|
} |
||||
|
|
||||
|
void Relationships::addMsPackageRelationship(const QString &relativeType, const QString &target) |
||||
|
{ |
||||
|
addRelationship(schema_msPackage + relativeType, target); |
||||
|
} |
||||
|
|
||||
|
QList<XlsxRelationship> Relationships::packageRelationships(const QString &relativeType) const |
||||
|
{ |
||||
|
return relationships(schema_package + relativeType); |
||||
|
} |
||||
|
|
||||
|
void Relationships::addPackageRelationship(const QString &relativeType, const QString &target) |
||||
|
{ |
||||
|
addRelationship(schema_package + relativeType, target); |
||||
|
} |
||||
|
|
||||
|
QList<XlsxRelationship> Relationships::worksheetRelationships(const QString &relativeType) const |
||||
|
{ |
||||
|
return relationships(schema_doc + relativeType); |
||||
|
} |
||||
|
|
||||
|
void Relationships::addWorksheetRelationship(const QString &relativeType, const QString &target, const QString &targetMode) |
||||
|
{ |
||||
|
addRelationship(schema_doc + relativeType, target, targetMode); |
||||
|
} |
||||
|
|
||||
|
QList<XlsxRelationship> Relationships::relationships(const QString &type) const |
||||
|
{ |
||||
|
QList<XlsxRelationship> res; |
||||
|
for (const XlsxRelationship &ship : m_relationships) { |
||||
|
if (ship.type == type) |
||||
|
res.append(ship); |
||||
|
} |
||||
|
return res; |
||||
|
} |
||||
|
|
||||
|
void Relationships::addRelationship(const QString &type, const QString &target, const QString &targetMode) |
||||
|
{ |
||||
|
XlsxRelationship relation; |
||||
|
relation.id = QStringLiteral("rId%1").arg(m_relationships.size()+1); |
||||
|
relation.type = type; |
||||
|
relation.target = target; |
||||
|
relation.targetMode = targetMode; |
||||
|
|
||||
|
m_relationships.append(relation); |
||||
|
} |
||||
|
|
||||
|
void Relationships::saveToXmlFile(QIODevice *device) const |
||||
|
{ |
||||
|
QXmlStreamWriter writer(device); |
||||
|
|
||||
|
writer.writeStartDocument(QStringLiteral("1.0"), true); |
||||
|
writer.writeStartElement(QStringLiteral("Relationships")); |
||||
|
writer.writeAttribute(QStringLiteral("xmlns"), QStringLiteral("http://schemas.openxmlformats.org/package/2006/relationships")); |
||||
|
for (const XlsxRelationship &relation : m_relationships) { |
||||
|
writer.writeStartElement(QStringLiteral("Relationship")); |
||||
|
writer.writeAttribute(QStringLiteral("Id"), relation.id); |
||||
|
writer.writeAttribute(QStringLiteral("Type"), relation.type); |
||||
|
writer.writeAttribute(QStringLiteral("Target"), relation.target); |
||||
|
if (!relation.targetMode.isNull()) |
||||
|
writer.writeAttribute(QStringLiteral("TargetMode"), relation.targetMode); |
||||
|
writer.writeEndElement(); |
||||
|
} |
||||
|
writer.writeEndElement();//Relationships
|
||||
|
writer.writeEndDocument(); |
||||
|
} |
||||
|
|
||||
|
QByteArray Relationships::saveToXmlData() const |
||||
|
{ |
||||
|
QByteArray data; |
||||
|
QBuffer buffer(&data); |
||||
|
buffer.open(QIODevice::WriteOnly); |
||||
|
saveToXmlFile(&buffer); |
||||
|
|
||||
|
return data; |
||||
|
} |
||||
|
|
||||
|
bool Relationships::loadFromXmlFile(QIODevice *device) |
||||
|
{ |
||||
|
clear(); |
||||
|
QXmlStreamReader reader(device); |
||||
|
while (!reader.atEnd()) { |
||||
|
QXmlStreamReader::TokenType token = reader.readNext(); |
||||
|
if (token == QXmlStreamReader::StartElement) { |
||||
|
if (reader.name() == QStringLiteral("Relationship")) { |
||||
|
QXmlStreamAttributes attributes = reader.attributes(); |
||||
|
XlsxRelationship relationship; |
||||
|
relationship.id = attributes.value(QLatin1String("Id")).toString(); |
||||
|
relationship.type = attributes.value(QLatin1String("Type")).toString(); |
||||
|
relationship.target = attributes.value(QLatin1String("Target")).toString(); |
||||
|
relationship.targetMode = attributes.value(QLatin1String("TargetMode")).toString(); |
||||
|
m_relationships.append(relationship); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (reader.hasError()) |
||||
|
return false; |
||||
|
} |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
bool Relationships::loadFromXmlData(const QByteArray &data) |
||||
|
{ |
||||
|
QBuffer buffer; |
||||
|
buffer.setData(data); |
||||
|
buffer.open(QIODevice::ReadOnly); |
||||
|
return loadFromXmlFile(&buffer); |
||||
|
} |
||||
|
|
||||
|
XlsxRelationship Relationships::getRelationshipById(const QString &id) const |
||||
|
{ |
||||
|
for (const XlsxRelationship &ship : m_relationships) { |
||||
|
if (ship.id == id) |
||||
|
return ship; |
||||
|
} |
||||
|
return XlsxRelationship(); |
||||
|
} |
||||
|
|
||||
|
void Relationships::clear() |
||||
|
{ |
||||
|
m_relationships.clear(); |
||||
|
} |
||||
|
|
||||
|
int Relationships::count() const |
||||
|
{ |
||||
|
return m_relationships.count(); |
||||
|
} |
||||
|
|
||||
|
bool Relationships::isEmpty() const |
||||
|
{ |
||||
|
return m_relationships.isEmpty(); |
||||
|
} |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
@ -0,0 +1,329 @@ |
|||||
|
// xlsxrichstring.cpp
|
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QDebug> |
||||
|
#include <QTextDocument> |
||||
|
#include <QTextFragment> |
||||
|
|
||||
|
#include "xlsxrichstring.h" |
||||
|
#include "xlsxrichstring_p.h" |
||||
|
#include "xlsxformat_p.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
RichStringPrivate::RichStringPrivate() |
||||
|
:_dirty(true) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
RichStringPrivate::RichStringPrivate(const RichStringPrivate &other) |
||||
|
:QSharedData(other), fragmentTexts(other.fragmentTexts) |
||||
|
,fragmentFormats(other.fragmentFormats) |
||||
|
, _idKey(other.idKey()), _dirty(other._dirty) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
RichStringPrivate::~RichStringPrivate() |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
\class RichString |
||||
|
\inmodule QtXlsx |
||||
|
\brief This class add support for the rich text string of the cell. |
||||
|
*/ |
||||
|
|
||||
|
/*!
|
||||
|
Constructs a null string. |
||||
|
*/ |
||||
|
RichString::RichString() |
||||
|
:d(new RichStringPrivate) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Constructs a plain string with the given \a text. |
||||
|
*/ |
||||
|
RichString::RichString(const QString& text) |
||||
|
:d(new RichStringPrivate) |
||||
|
{ |
||||
|
addFragment(text, Format()); |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Constructs a copy of \a other. |
||||
|
*/ |
||||
|
RichString::RichString(const RichString &other) |
||||
|
:d(other.d) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Destructs the string. |
||||
|
*/ |
||||
|
RichString::~RichString() |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Assigns \a other to this string and returns a reference to this string |
||||
|
*/ |
||||
|
RichString &RichString::operator =(const RichString &other) |
||||
|
{ |
||||
|
this->d = other.d; |
||||
|
return *this; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Returns the rich string as a QVariant |
||||
|
*/ |
||||
|
RichString::operator QVariant() const |
||||
|
{ |
||||
|
const auto& cref |
||||
|
#if QT_VERSION >= 0x060000 // Qt 6.0 or over
|
||||
|
= QMetaType::fromType<RichString>(); |
||||
|
#else |
||||
|
= qMetaTypeId<RichString>() ; |
||||
|
#endif |
||||
|
return QVariant(cref, this); |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Returns true if this is rich text string. |
||||
|
*/ |
||||
|
bool RichString::isRichString() const |
||||
|
{ |
||||
|
if (fragmentCount() > 1) //Is this enough??
|
||||
|
return true; |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Returns true is this is an Null string. |
||||
|
*/ |
||||
|
bool RichString::isNull() const |
||||
|
{ |
||||
|
return d->fragmentTexts.size() == 0; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Returns true is this is an empty string. |
||||
|
*/ |
||||
|
bool RichString::isEmtpy() const |
||||
|
{ |
||||
|
for (const auto& str : d->fragmentTexts) { |
||||
|
if (!str.isEmpty()) |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Converts to plain text string. |
||||
|
*/ |
||||
|
QString RichString::toPlainString() const |
||||
|
{ |
||||
|
if (isEmtpy()) |
||||
|
return QString(); |
||||
|
if (d->fragmentTexts.size() == 1) |
||||
|
return d->fragmentTexts[0]; |
||||
|
|
||||
|
return d->fragmentTexts.join(QString()); |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Converts to html string |
||||
|
*/ |
||||
|
QString RichString::toHtml() const |
||||
|
{ |
||||
|
//: Todo
|
||||
|
return QString(); |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Replaces the entire contents of the document |
||||
|
with the given HTML-formatted text in the \a text string |
||||
|
*/ |
||||
|
void RichString::setHtml(const QString &text) |
||||
|
{ |
||||
|
QTextDocument doc; |
||||
|
doc.setHtml(text); |
||||
|
QTextBlock block = doc.firstBlock(); |
||||
|
QTextBlock::iterator it; |
||||
|
for (it = block.begin(); !(it.atEnd()); ++it) { |
||||
|
QTextFragment textFragment = it.fragment(); |
||||
|
if (textFragment.isValid()) { |
||||
|
Format fmt; |
||||
|
fmt.setFont(textFragment.charFormat().font()); |
||||
|
fmt.setFontColor(textFragment.charFormat().foreground().color()); |
||||
|
addFragment(textFragment.text(), fmt); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Returns fragment count. |
||||
|
*/ |
||||
|
int RichString::fragmentCount() const |
||||
|
{ |
||||
|
return d->fragmentTexts.size(); |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Appends a fragment with the given \a text and \a format. |
||||
|
*/ |
||||
|
void RichString::addFragment(const QString &text, const Format &format) |
||||
|
{ |
||||
|
d->fragmentTexts.append(text); |
||||
|
d->fragmentFormats.append(format); |
||||
|
d->_dirty = true; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Returns fragment text at the position \a index. |
||||
|
*/ |
||||
|
QString RichString::fragmentText(int index) const |
||||
|
{ |
||||
|
if (index < 0 || index >= fragmentCount()) |
||||
|
return QString(); |
||||
|
|
||||
|
return d->fragmentTexts[index]; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Returns fragment format at the position \a index. |
||||
|
*/ |
||||
|
Format RichString::fragmentFormat(int index) const |
||||
|
{ |
||||
|
if (index < 0 || index >= fragmentCount()) |
||||
|
return Format(); |
||||
|
|
||||
|
return d->fragmentFormats[index]; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* \internal |
||||
|
*/ |
||||
|
QByteArray RichStringPrivate::idKey() const |
||||
|
{ |
||||
|
if (_dirty) { |
||||
|
RichStringPrivate *rs = const_cast<RichStringPrivate *>(this); |
||||
|
QByteArray bytes; |
||||
|
if (fragmentTexts.size() == 1) { |
||||
|
bytes = fragmentTexts[0].toUtf8(); |
||||
|
} else { |
||||
|
//Generate a hash value base on QByteArray ?
|
||||
|
bytes.append("@@QtXlsxRichString="); |
||||
|
for (int i=0; i<fragmentTexts.size(); ++i) { |
||||
|
bytes.append("@Text"); |
||||
|
bytes.append(fragmentTexts[i].toUtf8()); |
||||
|
bytes.append("@Format"); |
||||
|
if (fragmentFormats[i].hasFontData()) |
||||
|
bytes.append(fragmentFormats[i].fontKey()); |
||||
|
} |
||||
|
} |
||||
|
rs->_idKey = bytes; |
||||
|
rs->_dirty = false; |
||||
|
} |
||||
|
|
||||
|
return _idKey; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Returns true if this string \a rs1 is equal to string \a rs2; |
||||
|
otherwise returns false. |
||||
|
*/ |
||||
|
bool operator==(const RichString &rs1, const RichString &rs2) |
||||
|
{ |
||||
|
if (rs1.fragmentCount() != rs2.fragmentCount()) |
||||
|
return false; |
||||
|
|
||||
|
return rs1.d->idKey() == rs2.d->idKey(); |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Returns true if this string \a rs1 is not equal to string \a rs2; |
||||
|
otherwise returns false. |
||||
|
*/ |
||||
|
bool operator!=(const RichString &rs1, const RichString &rs2) |
||||
|
{ |
||||
|
if (rs1.fragmentCount() != rs2.fragmentCount()) |
||||
|
return true; |
||||
|
|
||||
|
return rs1.d->idKey() != rs2.d->idKey(); |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* \internal |
||||
|
*/ |
||||
|
bool operator<(const RichString &rs1, const RichString &rs2) |
||||
|
{ |
||||
|
return rs1.d->idKey() < rs2.d->idKey(); |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
\overload |
||||
|
Returns true if this string \a rs1 is equal to string \a rs2; |
||||
|
otherwise returns false. |
||||
|
*/ |
||||
|
bool operator ==(const RichString &rs1, const QString &rs2) |
||||
|
{ |
||||
|
if (rs1.fragmentCount() == 1 && rs1.fragmentText(0) == rs2) //format == 0
|
||||
|
return true; |
||||
|
|
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
\overload |
||||
|
Returns true if this string \a rs1 is not equal to string \a rs2; |
||||
|
otherwise returns false. |
||||
|
*/ |
||||
|
bool operator !=(const RichString &rs1, const QString &rs2) |
||||
|
{ |
||||
|
if (rs1.fragmentCount() == 1 && rs1.fragmentText(0) == rs2) //format == 0
|
||||
|
return false; |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
\overload |
||||
|
Returns true if this string \a rs1 is equal to string \a rs2; |
||||
|
otherwise returns false. |
||||
|
*/ |
||||
|
bool operator ==(const QString &rs1, const RichString &rs2) |
||||
|
{ |
||||
|
return rs2 == rs1; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
\overload |
||||
|
Returns true if this string \a rs1 is not equal to string \a rs2; |
||||
|
otherwise returns false. |
||||
|
*/ |
||||
|
bool operator !=(const QString &rs1, const RichString &rs2) |
||||
|
{ |
||||
|
return rs2 != rs1; |
||||
|
} |
||||
|
|
||||
|
uint qHash(const RichString &rs, uint seed) Q_DECL_NOTHROW |
||||
|
{ |
||||
|
return qHash(rs.d->idKey(), seed); |
||||
|
} |
||||
|
|
||||
|
#ifndef QT_NO_DEBUG_STREAM |
||||
|
QDebug operator<<(QDebug dbg, const RichString &rs) |
||||
|
{ |
||||
|
dbg.nospace() << "QXlsx::RichString(" << rs.d->fragmentTexts << ")"; |
||||
|
return dbg.space(); |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
@ -0,0 +1,382 @@ |
|||||
|
// xlsxsharedstrings.cpp
|
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QXmlStreamWriter> |
||||
|
#include <QXmlStreamReader> |
||||
|
#include <QDir> |
||||
|
#include <QFile> |
||||
|
#include <QDebug> |
||||
|
#include <QBuffer> |
||||
|
|
||||
|
#include "xlsxrichstring.h" |
||||
|
#include "xlsxsharedstrings_p.h" |
||||
|
#include "xlsxutility_p.h" |
||||
|
#include "xlsxformat_p.h" |
||||
|
#include "xlsxcolor_p.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
/*
|
||||
|
* Note that, when we open an existing .xlsx file (broken file?), |
||||
|
* duplicated string items may exist in the shared string table. |
||||
|
* |
||||
|
* In such case, the size of stringList will larger than stringTable. |
||||
|
* Duplicated items can be removed once we loaded all the worksheets. |
||||
|
*/ |
||||
|
|
||||
|
SharedStrings::SharedStrings(CreateFlag flag) |
||||
|
:AbstractOOXmlFile(flag) |
||||
|
{ |
||||
|
m_stringCount = 0; |
||||
|
} |
||||
|
|
||||
|
int SharedStrings::count() const |
||||
|
{ |
||||
|
return m_stringCount; |
||||
|
} |
||||
|
|
||||
|
bool SharedStrings::isEmpty() const |
||||
|
{ |
||||
|
return m_stringList.isEmpty(); |
||||
|
} |
||||
|
|
||||
|
int SharedStrings::addSharedString(const QString &string) |
||||
|
{ |
||||
|
return addSharedString(RichString(string)); |
||||
|
} |
||||
|
|
||||
|
int SharedStrings::addSharedString(const RichString &string) |
||||
|
{ |
||||
|
m_stringCount += 1; |
||||
|
|
||||
|
auto it = m_stringTable.find(string); |
||||
|
if (it != m_stringTable.end()) { |
||||
|
it->count += 1; |
||||
|
return it->index; |
||||
|
} |
||||
|
|
||||
|
int index = m_stringList.size(); |
||||
|
m_stringTable[string] = XlsxSharedStringInfo(index); |
||||
|
m_stringList.append(string); |
||||
|
return index; |
||||
|
} |
||||
|
|
||||
|
void SharedStrings::incRefByStringIndex(int idx) |
||||
|
{ |
||||
|
if (idx <0 || idx >= m_stringList.size()) { |
||||
|
qDebug("SharedStrings: invlid index"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
addSharedString(m_stringList[idx]); |
||||
|
} |
||||
|
|
||||
|
/*
|
||||
|
* Broken, don't use. |
||||
|
*/ |
||||
|
void SharedStrings::removeSharedString(const QString &string) |
||||
|
{ |
||||
|
removeSharedString(RichString(string)); |
||||
|
} |
||||
|
|
||||
|
/*
|
||||
|
* Broken, don't use. |
||||
|
*/ |
||||
|
void SharedStrings::removeSharedString(const RichString &string) |
||||
|
{ |
||||
|
auto it = m_stringTable.find(string); |
||||
|
if (it == m_stringTable.end()) |
||||
|
return; |
||||
|
|
||||
|
m_stringCount -= 1; |
||||
|
|
||||
|
it->count -= 1; |
||||
|
|
||||
|
if (it->count <= 0) { |
||||
|
for (int i=it->index+1; i<m_stringList.size(); ++i) |
||||
|
m_stringTable[m_stringList[i]].index -= 1; |
||||
|
|
||||
|
m_stringList.removeAt(it->index); |
||||
|
m_stringTable.remove(string); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
int SharedStrings::getSharedStringIndex(const QString &string) const |
||||
|
{ |
||||
|
return getSharedStringIndex(RichString(string)); |
||||
|
} |
||||
|
|
||||
|
int SharedStrings::getSharedStringIndex(const RichString &string) const |
||||
|
{ |
||||
|
auto it = m_stringTable.constFind(string); |
||||
|
if (it != m_stringTable.constEnd()) |
||||
|
return it->index; |
||||
|
return -1; |
||||
|
} |
||||
|
|
||||
|
RichString SharedStrings::getSharedString(int index) const |
||||
|
{ |
||||
|
if (index < m_stringList.count() && index >= 0) |
||||
|
return m_stringList[index]; |
||||
|
return RichString(); |
||||
|
} |
||||
|
|
||||
|
QList<RichString> SharedStrings::getSharedStrings() const |
||||
|
{ |
||||
|
return m_stringList; |
||||
|
} |
||||
|
|
||||
|
void SharedStrings::writeRichStringPart_rPr(QXmlStreamWriter &writer, const Format &format) const |
||||
|
{ |
||||
|
if (!format.hasFontData()) |
||||
|
return; |
||||
|
|
||||
|
if (format.fontBold()) |
||||
|
writer.writeEmptyElement(QStringLiteral("b")); |
||||
|
if (format.fontItalic()) |
||||
|
writer.writeEmptyElement(QStringLiteral("i")); |
||||
|
if (format.fontStrikeOut()) |
||||
|
writer.writeEmptyElement(QStringLiteral("strike")); |
||||
|
if (format.fontOutline()) |
||||
|
writer.writeEmptyElement(QStringLiteral("outline")); |
||||
|
if (format.boolProperty(FormatPrivate::P_Font_Shadow)) |
||||
|
writer.writeEmptyElement(QStringLiteral("shadow")); |
||||
|
if (format.hasProperty(FormatPrivate::P_Font_Underline)) { |
||||
|
Format::FontUnderline u = format.fontUnderline(); |
||||
|
if (u != Format::FontUnderlineNone) { |
||||
|
writer.writeEmptyElement(QStringLiteral("u")); |
||||
|
if (u== Format::FontUnderlineDouble) |
||||
|
writer.writeAttribute(QStringLiteral("val"), QStringLiteral("double")); |
||||
|
else if (u == Format::FontUnderlineSingleAccounting) |
||||
|
writer.writeAttribute(QStringLiteral("val"), QStringLiteral("singleAccounting")); |
||||
|
else if (u == Format::FontUnderlineDoubleAccounting) |
||||
|
writer.writeAttribute(QStringLiteral("val"), QStringLiteral("doubleAccounting")); |
||||
|
} |
||||
|
} |
||||
|
if (format.hasProperty(FormatPrivate::P_Font_Script)) { |
||||
|
Format::FontScript s = format.fontScript(); |
||||
|
if (s != Format::FontScriptNormal) { |
||||
|
writer.writeEmptyElement(QStringLiteral("vertAlign")); |
||||
|
if (s == Format::FontScriptSuper) |
||||
|
writer.writeAttribute(QStringLiteral("val"), QStringLiteral("superscript")); |
||||
|
else |
||||
|
writer.writeAttribute(QStringLiteral("val"), QStringLiteral("subscript")); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (format.hasProperty(FormatPrivate::P_Font_Size)) { |
||||
|
writer.writeEmptyElement(QStringLiteral("sz")); |
||||
|
writer.writeAttribute(QStringLiteral("val"), QString::number(format.fontSize())); |
||||
|
} |
||||
|
|
||||
|
if (format.hasProperty(FormatPrivate::P_Font_Color)) { |
||||
|
XlsxColor color = format.property(FormatPrivate::P_Font_Color).value<XlsxColor>(); |
||||
|
color.saveToXml(writer); |
||||
|
} |
||||
|
|
||||
|
if (!format.fontName().isEmpty()) { |
||||
|
writer.writeEmptyElement(QStringLiteral("rFont")); |
||||
|
writer.writeAttribute(QStringLiteral("val"), format.fontName()); |
||||
|
} |
||||
|
if (format.hasProperty(FormatPrivate::P_Font_Family)) { |
||||
|
writer.writeEmptyElement(QStringLiteral("family")); |
||||
|
writer.writeAttribute(QStringLiteral("val"), QString::number(format.intProperty(FormatPrivate::P_Font_Family))); |
||||
|
} |
||||
|
|
||||
|
if (format.hasProperty(FormatPrivate::P_Font_Scheme)) { |
||||
|
writer.writeEmptyElement(QStringLiteral("scheme")); |
||||
|
writer.writeAttribute(QStringLiteral("val"), format.stringProperty(FormatPrivate::P_Font_Scheme)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void SharedStrings::saveToXmlFile(QIODevice *device) const |
||||
|
{ |
||||
|
QXmlStreamWriter writer(device); |
||||
|
|
||||
|
if (m_stringList.size() != m_stringTable.size()) { |
||||
|
//Duplicated string items exist in m_stringList
|
||||
|
//Clean up can not be done here, as the indices
|
||||
|
//have been used when we save the worksheets part.
|
||||
|
} |
||||
|
|
||||
|
writer.writeStartDocument(QStringLiteral("1.0"), true); |
||||
|
writer.writeStartElement(QStringLiteral("sst")); |
||||
|
writer.writeAttribute(QStringLiteral("xmlns"), QStringLiteral("http://schemas.openxmlformats.org/spreadsheetml/2006/main")); |
||||
|
writer.writeAttribute(QStringLiteral("count"), QString::number(m_stringCount)); |
||||
|
writer.writeAttribute(QStringLiteral("uniqueCount"), QString::number(m_stringList.size())); |
||||
|
|
||||
|
for (const RichString &string : m_stringList) { |
||||
|
writer.writeStartElement(QStringLiteral("si")); |
||||
|
if (string.isRichString()) { |
||||
|
//Rich text string
|
||||
|
for (int i=0; i<string.fragmentCount(); ++i) { |
||||
|
writer.writeStartElement(QStringLiteral("r")); |
||||
|
if (string.fragmentFormat(i).hasFontData()) { |
||||
|
writer.writeStartElement(QStringLiteral("rPr")); |
||||
|
writeRichStringPart_rPr(writer, string.fragmentFormat(i)); |
||||
|
writer.writeEndElement();// rPr
|
||||
|
} |
||||
|
writer.writeStartElement(QStringLiteral("t")); |
||||
|
if (isSpaceReserveNeeded(string.fragmentText(i))) |
||||
|
writer.writeAttribute(QStringLiteral("xml:space"), QStringLiteral("preserve")); |
||||
|
writer.writeCharacters(string.fragmentText(i)); |
||||
|
writer.writeEndElement();// t
|
||||
|
|
||||
|
writer.writeEndElement(); //r
|
||||
|
} |
||||
|
} else { |
||||
|
writer.writeStartElement(QStringLiteral("t")); |
||||
|
QString pString = string.toPlainString(); |
||||
|
if (isSpaceReserveNeeded(pString)) |
||||
|
writer.writeAttribute(QStringLiteral("xml:space"), QStringLiteral("preserve")); |
||||
|
writer.writeCharacters(pString); |
||||
|
writer.writeEndElement();//t
|
||||
|
} |
||||
|
writer.writeEndElement();//si
|
||||
|
} |
||||
|
|
||||
|
writer.writeEndElement(); //sst
|
||||
|
writer.writeEndDocument(); |
||||
|
} |
||||
|
|
||||
|
void SharedStrings::readString(QXmlStreamReader &reader) |
||||
|
{ |
||||
|
Q_ASSERT(reader.name() == QLatin1String("si")); |
||||
|
|
||||
|
RichString richString; |
||||
|
|
||||
|
while (!reader.atEnd() && !(reader.name() == QLatin1String("si") && reader.tokenType() == QXmlStreamReader::EndElement)) { |
||||
|
reader.readNextStartElement(); |
||||
|
if (reader.tokenType() == QXmlStreamReader::StartElement) { |
||||
|
if (reader.name() == QLatin1String("r")) |
||||
|
readRichStringPart(reader, richString); |
||||
|
else if (reader.name() == QLatin1String("t")) |
||||
|
readPlainStringPart(reader, richString); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
int idx = m_stringList.size(); |
||||
|
m_stringTable[richString] = XlsxSharedStringInfo(idx, 0); |
||||
|
m_stringList.append(richString); |
||||
|
} |
||||
|
|
||||
|
void SharedStrings::readRichStringPart(QXmlStreamReader &reader, RichString &richString) |
||||
|
{ |
||||
|
Q_ASSERT(reader.name() == QLatin1String("r")); |
||||
|
|
||||
|
QString text; |
||||
|
Format format; |
||||
|
while (!reader.atEnd() && !(reader.name() == QLatin1String("r") && reader.tokenType() == QXmlStreamReader::EndElement)) { |
||||
|
reader.readNextStartElement(); |
||||
|
if (reader.tokenType() == QXmlStreamReader::StartElement) { |
||||
|
if (reader.name() == QLatin1String("rPr")) { |
||||
|
format = readRichStringPart_rPr(reader); |
||||
|
} else if (reader.name() == QLatin1String("t")) { |
||||
|
text = reader.readElementText(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
richString.addFragment(text, format); |
||||
|
} |
||||
|
|
||||
|
void SharedStrings::readPlainStringPart(QXmlStreamReader &reader, RichString &richString) |
||||
|
{ |
||||
|
Q_ASSERT(reader.name() == QLatin1String("t")); |
||||
|
|
||||
|
//QXmlStreamAttributes attributes = reader.attributes();
|
||||
|
|
||||
|
// NOTICE: CHECK POINT
|
||||
|
QString text = reader.readElementText(); |
||||
|
richString.addFragment(text, Format()); |
||||
|
} |
||||
|
|
||||
|
Format SharedStrings::readRichStringPart_rPr(QXmlStreamReader &reader) |
||||
|
{ |
||||
|
Q_ASSERT(reader.name() == QLatin1String("rPr")); |
||||
|
Format format; |
||||
|
while (!reader.atEnd() && !(reader.name() == QLatin1String("rPr") && reader.tokenType() == QXmlStreamReader::EndElement)) { |
||||
|
reader.readNextStartElement(); |
||||
|
if (reader.tokenType() == QXmlStreamReader::StartElement) { |
||||
|
QXmlStreamAttributes attributes = reader.attributes(); |
||||
|
if (reader.name() == QLatin1String("rFont")) { |
||||
|
format.setFontName(attributes.value(QLatin1String("val")).toString()); |
||||
|
} else if (reader.name() == QLatin1String("charset")) { |
||||
|
format.setProperty(FormatPrivate::P_Font_Charset, attributes.value(QLatin1String("val")).toInt()); |
||||
|
} else if (reader.name() == QLatin1String("family")) { |
||||
|
format.setProperty(FormatPrivate::P_Font_Family, attributes.value(QLatin1String("val")).toInt()); |
||||
|
} else if (reader.name() == QLatin1String("b")) { |
||||
|
format.setFontBold(true); |
||||
|
} else if (reader.name() == QLatin1String("i")) { |
||||
|
format.setFontItalic(true); |
||||
|
} else if (reader.name() == QLatin1String("strike")) { |
||||
|
format.setFontStrikeOut(true); |
||||
|
} else if (reader.name() == QLatin1String("outline")) { |
||||
|
format.setFontOutline(true); |
||||
|
} else if (reader.name() == QLatin1String("shadow")) { |
||||
|
format.setProperty(FormatPrivate::P_Font_Shadow, true); |
||||
|
} else if (reader.name() == QLatin1String("condense")) { |
||||
|
format.setProperty(FormatPrivate::P_Font_Condense, attributes.value(QLatin1String("val")).toInt()); |
||||
|
} else if (reader.name() == QLatin1String("extend")) { |
||||
|
format.setProperty(FormatPrivate::P_Font_Extend, attributes.value(QLatin1String("val")).toInt()); |
||||
|
} else if (reader.name() == QLatin1String("color")) { |
||||
|
XlsxColor color; |
||||
|
color.loadFromXml(reader); |
||||
|
format.setProperty(FormatPrivate::P_Font_Color, color); |
||||
|
} else if (reader.name() == QLatin1String("sz")) { |
||||
|
format.setFontSize(attributes.value(QLatin1String("val")).toInt()); |
||||
|
} else if (reader.name() == QLatin1String("u")) { |
||||
|
QString value = attributes.value(QLatin1String("val")).toString(); |
||||
|
if (value == QLatin1String("double")) |
||||
|
format.setFontUnderline(Format::FontUnderlineDouble); |
||||
|
else if (value == QLatin1String("doubleAccounting")) |
||||
|
format.setFontUnderline(Format::FontUnderlineDoubleAccounting); |
||||
|
else if (value == QLatin1String("singleAccounting")) |
||||
|
format.setFontUnderline(Format::FontUnderlineSingleAccounting); |
||||
|
else |
||||
|
format.setFontUnderline(Format::FontUnderlineSingle); |
||||
|
} else if (reader.name() == QLatin1String("vertAlign")) { |
||||
|
QString value = attributes.value(QLatin1String("val")).toString(); |
||||
|
if (value == QLatin1String("superscript")) |
||||
|
format.setFontScript(Format::FontScriptSuper); |
||||
|
else if (value == QLatin1String("subscript")) |
||||
|
format.setFontScript(Format::FontScriptSub); |
||||
|
} else if (reader.name() == QLatin1String("scheme")) { |
||||
|
format.setProperty(FormatPrivate::P_Font_Scheme, attributes.value(QLatin1String("val")).toString()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return format; |
||||
|
} |
||||
|
|
||||
|
bool SharedStrings::loadFromXmlFile(QIODevice *device) |
||||
|
{ |
||||
|
QXmlStreamReader reader(device); |
||||
|
int count = 0; |
||||
|
bool hasUniqueCountAttr=true; |
||||
|
while (!reader.atEnd()) { |
||||
|
QXmlStreamReader::TokenType token = reader.readNext(); |
||||
|
if (token == QXmlStreamReader::StartElement) { |
||||
|
if (reader.name() == QLatin1String("sst")) { |
||||
|
QXmlStreamAttributes attributes = reader.attributes(); |
||||
|
if ((hasUniqueCountAttr = attributes.hasAttribute(QLatin1String("uniqueCount")))) |
||||
|
count = attributes.value(QLatin1String("uniqueCount")).toInt(); |
||||
|
} else if (reader.name() == QLatin1String("si")) { |
||||
|
readString(reader); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (hasUniqueCountAttr && m_stringList.size() != count) { |
||||
|
qDebug("Error: Shared string count"); |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
if (m_stringList.size() != m_stringTable.size()) { |
||||
|
//qDebug("Warning: Duplicated items exist in shared string table.");
|
||||
|
//Nothing we can do here, as indices of the strings will be used when loading sheets.
|
||||
|
} |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
@ -0,0 +1,37 @@ |
|||||
|
// xlsxsimpleooxmlfile.cpp
|
||||
|
|
||||
|
#include "xlsxsimpleooxmlfile_p.h" |
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QIODevice> |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
SimpleOOXmlFile::SimpleOOXmlFile(CreateFlag flag) |
||||
|
:AbstractOOXmlFile(flag) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
void SimpleOOXmlFile::saveToXmlFile(QIODevice *device) const |
||||
|
{ |
||||
|
device->write(xmlData); |
||||
|
} |
||||
|
|
||||
|
QByteArray SimpleOOXmlFile::saveToXmlData() const |
||||
|
{ |
||||
|
return xmlData; |
||||
|
} |
||||
|
|
||||
|
bool SimpleOOXmlFile::loadFromXmlData(const QByteArray &data) |
||||
|
{ |
||||
|
xmlData = data; |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
bool SimpleOOXmlFile::loadFromXmlFile(QIODevice *device) |
||||
|
{ |
||||
|
xmlData = device->readAll(); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
File diff suppressed because it is too large
@ -0,0 +1,216 @@ |
|||||
|
// xlsxtheme.cpp
|
||||
|
|
||||
|
#include "xlsxtheme_p.h" |
||||
|
|
||||
|
#include <QIODevice> |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
const char *defaultXmlData = |
||||
|
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" |
||||
|
"<a:theme xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\" name=\"Office \xe4\xb8\xbb\xe9\xa2\x98\">" |
||||
|
"<a:themeElements>" |
||||
|
"<a:clrScheme name=\"Office\">" |
||||
|
"<a:dk1><a:sysClr val=\"windowText\" lastClr=\"000000\"/></a:dk1>" |
||||
|
"<a:lt1><a:sysClr val=\"window\" lastClr=\"FFFFFF\"/></a:lt1>" |
||||
|
"<a:dk2><a:srgbClr val=\"1F497D\"/></a:dk2>" |
||||
|
"<a:lt2><a:srgbClr val=\"EEECE1\"/></a:lt2>" |
||||
|
"<a:accent1><a:srgbClr val=\"4F81BD\"/></a:accent1>" |
||||
|
"<a:accent2><a:srgbClr val=\"C0504D\"/></a:accent2>" |
||||
|
"<a:accent3><a:srgbClr val=\"9BBB59\"/></a:accent3>" |
||||
|
"<a:accent4><a:srgbClr val=\"8064A2\"/></a:accent4>" |
||||
|
"<a:accent5><a:srgbClr val=\"4BACC6\"/></a:accent5>" |
||||
|
"<a:accent6><a:srgbClr val=\"F79646\"/></a:accent6>" |
||||
|
"<a:hlink><a:srgbClr val=\"0000FF\"/></a:hlink>" |
||||
|
"<a:folHlink><a:srgbClr val=\"800080\"/></a:folHlink>" |
||||
|
"</a:clrScheme>" |
||||
|
"<a:fontScheme name=\"Office\">" |
||||
|
"<a:majorFont>" |
||||
|
"<a:latin typeface=\"Cambria\"/>" |
||||
|
"<a:ea typeface=\"\"/>" |
||||
|
"<a:cs typeface=\"\"/>" |
||||
|
"<a:font script=\"Jpan\" typeface=\"\xef\xbc\xad\xef\xbc\xb3 \xef\xbc\xb0\xe3\x82\xb4\xe3\x82\xb7\xe3\x83\x83\xe3\x82\xaf\"/>" |
||||
|
"<a:font script=\"Hang\" typeface=\"\xeb\xa7\x91\xec\x9d\x80 \xea\xb3\xa0\xeb\x94\x95\"/>" |
||||
|
"<a:font script=\"Hans\" typeface=\"\xe5\xae\x8b\xe4\xbd\x93\"/>" |
||||
|
"<a:font script=\"Hant\" typeface=\"\xe6\x96\xb0\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94\"/>" |
||||
|
"<a:font script=\"Arab\" typeface=\"Times New Roman\"/>" |
||||
|
"<a:font script=\"Hebr\" typeface=\"Times New Roman\"/>" |
||||
|
"<a:font script=\"Thai\" typeface=\"Tahoma\"/>" |
||||
|
"<a:font script=\"Ethi\" typeface=\"Nyala\"/>" |
||||
|
"<a:font script=\"Beng\" typeface=\"Vrinda\"/>" |
||||
|
"<a:font script=\"Gujr\" typeface=\"Shruti\"/>" |
||||
|
"<a:font script=\"Khmr\" typeface=\"MoolBoran\"/>" |
||||
|
"<a:font script=\"Knda\" typeface=\"Tunga\"/>" |
||||
|
"<a:font script=\"Guru\" typeface=\"Raavi\"/>" |
||||
|
"<a:font script=\"Cans\" typeface=\"Euphemia\"/>" |
||||
|
"<a:font script=\"Cher\" typeface=\"Plantagenet Cherokee\"/>" |
||||
|
"<a:font script=\"Yiii\" typeface=\"Microsoft Yi Baiti\"/>" |
||||
|
"<a:font script=\"Tibt\" typeface=\"Microsoft Himalaya\"/>" |
||||
|
"<a:font script=\"Thaa\" typeface=\"MV Boli\"/>" |
||||
|
"<a:font script=\"Deva\" typeface=\"Mangal\"/>" |
||||
|
"<a:font script=\"Telu\" typeface=\"Gautami\"/>" |
||||
|
"<a:font script=\"Taml\" typeface=\"Latha\"/>" |
||||
|
"<a:font script=\"Syrc\" typeface=\"Estrangelo Edessa\"/>" |
||||
|
"<a:font script=\"Orya\" typeface=\"Kalinga\"/>" |
||||
|
"<a:font script=\"Mlym\" typeface=\"Kartika\"/>" |
||||
|
"<a:font script=\"Laoo\" typeface=\"DokChampa\"/>" |
||||
|
"<a:font script=\"Sinh\" typeface=\"Iskoola Pota\"/>" |
||||
|
"<a:font script=\"Mong\" typeface=\"Mongolian Baiti\"/>" |
||||
|
"<a:font script=\"Viet\" typeface=\"Times New Roman\"/>" |
||||
|
"<a:font script=\"Uigh\" typeface=\"Microsoft Uighur\"/>" |
||||
|
"</a:majorFont>" |
||||
|
"<a:minorFont>" |
||||
|
"<a:latin typeface=\"Calibri\"/>" |
||||
|
"<a:ea typeface=\"\"/>" |
||||
|
"<a:cs typeface=\"\"/>" |
||||
|
"<a:font script=\"Jpan\" typeface=\"\xef\xbc\xad\xef\xbc\xb3 \xef\xbc\xb0\xe3\x82\xb4\xe3\x82\xb7\xe3\x83\x83\xe3\x82\xaf\"/>" |
||||
|
"<a:font script=\"Hang\" typeface=\"\xeb\xa7\x91\xec\x9d\x80 \xea\xb3\xa0\xeb\x94\x95\"/>" |
||||
|
"<a:font script=\"Hans\" typeface=\"\xe5\xae\x8b\xe4\xbd\x93\"/>" |
||||
|
"<a:font script=\"Hant\" typeface=\"\xe6\x96\xb0\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94\"/>" |
||||
|
"<a:font script=\"Arab\" typeface=\"Arial\"/>" |
||||
|
"<a:font script=\"Hebr\" typeface=\"Arial\"/>" |
||||
|
"<a:font script=\"Thai\" typeface=\"Tahoma\"/>" |
||||
|
"<a:font script=\"Ethi\" typeface=\"Nyala\"/>" |
||||
|
"<a:font script=\"Beng\" typeface=\"Vrinda\"/>" |
||||
|
"<a:font script=\"Gujr\" typeface=\"Shruti\"/>" |
||||
|
"<a:font script=\"Khmr\" typeface=\"DaunPenh\"/>" |
||||
|
"<a:font script=\"Knda\" typeface=\"Tunga\"/>" |
||||
|
"<a:font script=\"Guru\" typeface=\"Raavi\"/>" |
||||
|
"<a:font script=\"Cans\" typeface=\"Euphemia\"/>" |
||||
|
"<a:font script=\"Cher\" typeface=\"Plantagenet Cherokee\"/>" |
||||
|
"<a:font script=\"Yiii\" typeface=\"Microsoft Yi Baiti\"/>" |
||||
|
"<a:font script=\"Tibt\" typeface=\"Microsoft Himalaya\"/>" |
||||
|
"<a:font script=\"Thaa\" typeface=\"MV Boli\"/>" |
||||
|
"<a:font script=\"Deva\" typeface=\"Mangal\"/>" |
||||
|
"<a:font script=\"Telu\" typeface=\"Gautami\"/>" |
||||
|
"<a:font script=\"Taml\" typeface=\"Latha\"/>" |
||||
|
"<a:font script=\"Syrc\" typeface=\"Estrangelo Edessa\"/>" |
||||
|
"<a:font script=\"Orya\" typeface=\"Kalinga\"/>" |
||||
|
"<a:font script=\"Mlym\" typeface=\"Kartika\"/>" |
||||
|
"<a:font script=\"Laoo\" typeface=\"DokChampa\"/>" |
||||
|
"<a:font script=\"Sinh\" typeface=\"Iskoola Pota\"/>" |
||||
|
"<a:font script=\"Mong\" typeface=\"Mongolian Baiti\"/>" |
||||
|
"<a:font script=\"Viet\" typeface=\"Arial\"/>" |
||||
|
"<a:font script=\"Uigh\" typeface=\"Microsoft Uighur\"/>" |
||||
|
"</a:minorFont>" |
||||
|
"</a:fontScheme>" |
||||
|
"<a:fmtScheme name=\"Office\">" |
||||
|
"<a:fillStyleLst>" |
||||
|
"<a:solidFill><a:schemeClr val=\"phClr\"/></a:solidFill>" |
||||
|
"<a:gradFill rotWithShape=\"1\">" |
||||
|
"<a:gsLst>" |
||||
|
"<a:gs pos=\"0\"><a:schemeClr val=\"phClr\"><a:tint val=\"50000\"/><a:satMod val=\"300000\"/></a:schemeClr></a:gs>" |
||||
|
"<a:gs pos=\"35000\"><a:schemeClr val=\"phClr\"><a:tint val=\"37000\"/><a:satMod val=\"300000\"/></a:schemeClr></a:gs>" |
||||
|
"<a:gs pos=\"100000\"><a:schemeClr val=\"phClr\"><a:tint val=\"15000\"/><a:satMod val=\"350000\"/></a:schemeClr></a:gs>" |
||||
|
"</a:gsLst>" |
||||
|
"<a:lin ang=\"16200000\" scaled=\"1\"/>" |
||||
|
"</a:gradFill>" |
||||
|
"<a:gradFill rotWithShape=\"1\">" |
||||
|
"<a:gsLst>" |
||||
|
"<a:gs pos=\"0\"><a:schemeClr val=\"phClr\"><a:shade val=\"51000\"/><a:satMod val=\"130000\"/></a:schemeClr></a:gs>" |
||||
|
"<a:gs pos=\"80000\"><a:schemeClr val=\"phClr\"><a:shade val=\"93000\"/><a:satMod val=\"130000\"/></a:schemeClr></a:gs>" |
||||
|
"<a:gs pos=\"100000\"><a:schemeClr val=\"phClr\"><a:shade val=\"94000\"/><a:satMod val=\"135000\"/></a:schemeClr></a:gs>" |
||||
|
"</a:gsLst>" |
||||
|
"<a:lin ang=\"16200000\" scaled=\"0\"/>" |
||||
|
"</a:gradFill>" |
||||
|
"</a:fillStyleLst>" |
||||
|
"<a:lnStyleLst>" |
||||
|
"<a:ln w=\"9525\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\">" |
||||
|
"<a:solidFill><a:schemeClr val=\"phClr\"><a:shade val=\"95000\"/><a:satMod val=\"105000\"/></a:schemeClr></a:solidFill>" |
||||
|
"<a:prstDash val=\"solid\"/>" |
||||
|
"</a:ln>" |
||||
|
"<a:ln w=\"25400\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\">" |
||||
|
"<a:solidFill><a:schemeClr val=\"phClr\"/></a:solidFill>" |
||||
|
"<a:prstDash val=\"solid\"/>" |
||||
|
"</a:ln>" |
||||
|
"<a:ln w=\"38100\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\">" |
||||
|
"<a:solidFill><a:schemeClr val=\"phClr\"/></a:solidFill>" |
||||
|
"<a:prstDash val=\"solid\"/>" |
||||
|
"</a:ln>" |
||||
|
"</a:lnStyleLst>" |
||||
|
"<a:effectStyleLst>" |
||||
|
"<a:effectStyle>" |
||||
|
"<a:effectLst>" |
||||
|
"<a:outerShdw blurRad=\"40000\" dist=\"20000\" dir=\"5400000\" rotWithShape=\"0\">" |
||||
|
"<a:srgbClr val=\"000000\"><a:alpha val=\"38000\"/></a:srgbClr>" |
||||
|
"</a:outerShdw>" |
||||
|
"</a:effectLst>" |
||||
|
"</a:effectStyle>" |
||||
|
"<a:effectStyle>" |
||||
|
"<a:effectLst>" |
||||
|
"<a:outerShdw blurRad=\"40000\" dist=\"23000\" dir=\"5400000\" rotWithShape=\"0\">" |
||||
|
"<a:srgbClr val=\"000000\"><a:alpha val=\"35000\"/></a:srgbClr>" |
||||
|
"</a:outerShdw>" |
||||
|
"</a:effectLst>" |
||||
|
"</a:effectStyle>" |
||||
|
"<a:effectStyle>" |
||||
|
"<a:effectLst>" |
||||
|
"<a:outerShdw blurRad=\"40000\" dist=\"23000\" dir=\"5400000\" rotWithShape=\"0\">" |
||||
|
"<a:srgbClr val=\"000000\"><a:alpha val=\"35000\"/></a:srgbClr>" |
||||
|
"</a:outerShdw>" |
||||
|
"</a:effectLst>" |
||||
|
"<a:scene3d>" |
||||
|
"<a:camera prst=\"orthographicFront\"><a:rot lat=\"0\" lon=\"0\" rev=\"0\"/></a:camera>" |
||||
|
"<a:lightRig rig=\"threePt\" dir=\"t\"><a:rot lat=\"0\" lon=\"0\" rev=\"1200000\"/></a:lightRig>" |
||||
|
"</a:scene3d>" |
||||
|
"<a:sp3d><a:bevelT w=\"63500\" h=\"25400\"/></a:sp3d>" |
||||
|
"</a:effectStyle>" |
||||
|
"</a:effectStyleLst>" |
||||
|
"<a:bgFillStyleLst>" |
||||
|
"<a:solidFill><a:schemeClr val=\"phClr\"/></a:solidFill>" |
||||
|
"<a:gradFill rotWithShape=\"1\">" |
||||
|
"<a:gsLst>" |
||||
|
"<a:gs pos=\"0\"><a:schemeClr val=\"phClr\"><a:tint val=\"40000\"/><a:satMod val=\"350000\"/></a:schemeClr></a:gs>" |
||||
|
"<a:gs pos=\"40000\"><a:schemeClr val=\"phClr\"><a:tint val=\"45000\"/><a:shade val=\"99000\"/><a:satMod val=\"350000\"/></a:schemeClr></a:gs>" |
||||
|
"<a:gs pos=\"100000\"><a:schemeClr val=\"phClr\"><a:shade val=\"20000\"/><a:satMod val=\"255000\"/></a:schemeClr></a:gs></a:gsLst>" |
||||
|
"<a:path path=\"circle\"><a:fillToRect l=\"50000\" t=\"-80000\" r=\"50000\" b=\"180000\"/></a:path>" |
||||
|
"</a:gradFill>" |
||||
|
"<a:gradFill rotWithShape=\"1\">" |
||||
|
"<a:gsLst>" |
||||
|
"<a:gs pos=\"0\"><a:schemeClr val=\"phClr\"><a:tint val=\"80000\"/><a:satMod val=\"300000\"/></a:schemeClr></a:gs>" |
||||
|
"<a:gs pos=\"100000\"><a:schemeClr val=\"phClr\"><a:shade val=\"30000\"/><a:satMod val=\"200000\"/></a:schemeClr></a:gs>" |
||||
|
"</a:gsLst>" |
||||
|
"<a:path path=\"circle\"><a:fillToRect l=\"50000\" t=\"50000\" r=\"50000\" b=\"50000\"/></a:path>" |
||||
|
"</a:gradFill>" |
||||
|
"</a:bgFillStyleLst>" |
||||
|
"</a:fmtScheme>" |
||||
|
"</a:themeElements>" |
||||
|
"<a:objectDefaults/>" |
||||
|
"<a:extraClrSchemeLst/>" |
||||
|
"</a:theme>" |
||||
|
; |
||||
|
|
||||
|
Theme::Theme(CreateFlag flag) |
||||
|
:AbstractOOXmlFile(flag) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
void Theme::saveToXmlFile(QIODevice *device) const |
||||
|
{ |
||||
|
if (xmlData.isEmpty()) |
||||
|
device->write(defaultXmlData); |
||||
|
else |
||||
|
device->write(xmlData); |
||||
|
} |
||||
|
|
||||
|
QByteArray Theme::saveToXmlData() const |
||||
|
{ |
||||
|
if (xmlData.isEmpty()) |
||||
|
return defaultXmlData; |
||||
|
else |
||||
|
return xmlData; |
||||
|
} |
||||
|
|
||||
|
bool Theme::loadFromXmlData(const QByteArray &data) |
||||
|
{ |
||||
|
xmlData = data; |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
bool Theme::loadFromXmlFile(QIODevice *device) |
||||
|
{ |
||||
|
xmlData = device->readAll(); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
@ -0,0 +1,291 @@ |
|||||
|
// xlsxutility.cpp
|
||||
|
|
||||
|
#include "xlsxutility_p.h" |
||||
|
#include "xlsxcellreference.h" |
||||
|
|
||||
|
#include <QString> |
||||
|
#include <QPoint> |
||||
|
#include <QRegularExpression> |
||||
|
#include <QMap> |
||||
|
#include <QStringList> |
||||
|
#include <QColor> |
||||
|
#include <QDateTime> |
||||
|
#include <QDebug> |
||||
|
|
||||
|
#include <cmath> |
||||
|
#include <string> |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
bool parseXsdBoolean(const QString &value, bool defaultValue) |
||||
|
{ |
||||
|
if (value == QLatin1String("1") || value == QLatin1String("true")) |
||||
|
return true; |
||||
|
if (value == QLatin1String("0") || value == QLatin1String("false")) |
||||
|
return false; |
||||
|
return defaultValue; |
||||
|
} |
||||
|
|
||||
|
QStringList splitPath(const QString &path) |
||||
|
{ |
||||
|
int idx = path.lastIndexOf(QLatin1Char('/')); |
||||
|
if (idx == -1) |
||||
|
return { QStringLiteral("."), path }; |
||||
|
|
||||
|
return { path.left(idx), path.mid(idx+1) }; |
||||
|
} |
||||
|
|
||||
|
/*
|
||||
|
* Return the .rel file path based on filePath |
||||
|
*/ |
||||
|
QString getRelFilePath(const QString &filePath) |
||||
|
{ |
||||
|
QString ret; |
||||
|
|
||||
|
int idx = filePath.lastIndexOf(QLatin1Char('/')); |
||||
|
if (idx == -1) // not found
|
||||
|
{ |
||||
|
// return QString();
|
||||
|
|
||||
|
// dev34
|
||||
|
ret = QLatin1String("_rels/") + QStringLiteral("%0.rels").arg(filePath); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
ret = QString( filePath.left(idx) + QLatin1String("/_rels/") + filePath.mid(idx+1) + QLatin1String(".rels")); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
double datetimeToNumber(const QDateTime &dt, bool is1904) |
||||
|
{ |
||||
|
//Note, for number 0, Excel2007 shown as 1900-1-0, which should be 1899-12-31
|
||||
|
QDateTime epoch(is1904 ? QDate(1904, 1, 1): QDate(1899, 12, 31), QTime(0,0)); |
||||
|
|
||||
|
double excel_time = epoch.msecsTo(dt) / (1000*60*60*24.0); |
||||
|
|
||||
|
if (dt.isDaylightTime()) // Add one hour if the date is Daylight
|
||||
|
excel_time += 1.0 / 24.0; |
||||
|
|
||||
|
if (!is1904 && excel_time > 59) {//31+28
|
||||
|
//Account for Excel erroneously treating 1900 as a leap year.
|
||||
|
excel_time += 1; |
||||
|
} |
||||
|
|
||||
|
return excel_time; |
||||
|
} |
||||
|
|
||||
|
double timeToNumber(const QTime &time) |
||||
|
{ |
||||
|
return QTime(0,0).msecsTo(time) / (1000*60*60*24.0); |
||||
|
} |
||||
|
|
||||
|
QVariant datetimeFromNumber(double num, bool is1904) |
||||
|
{ |
||||
|
QDateTime dtRet; // return value
|
||||
|
|
||||
|
if (!is1904 && num > 60) // for mac os excel
|
||||
|
{ |
||||
|
num = num - 1; |
||||
|
} |
||||
|
|
||||
|
qint64 msecs = static_cast<qint64>(num * 1000*60*60*24.0 + 0.5); |
||||
|
QDateTime epoch(is1904 ? QDate(1904, 1, 1): QDate(1899, 12, 31), QTime(0,0)); |
||||
|
QDateTime dtOld = epoch.addMSecs(msecs); |
||||
|
dtRet = dtOld; |
||||
|
|
||||
|
// Remove one hour to see whether the date is Daylight
|
||||
|
QDateTime dtNew = dtRet.addMSecs( -3600000 ); // issue102
|
||||
|
if ( dtNew.isDaylightTime() ) |
||||
|
{ |
||||
|
dtRet = dtNew; |
||||
|
} |
||||
|
|
||||
|
double whole = 0; |
||||
|
double fractional = std::modf(num, &whole); |
||||
|
|
||||
|
if ( num < double(1) ) |
||||
|
{ |
||||
|
// only time
|
||||
|
QTime t = dtRet.time(); |
||||
|
return QVariant(t); |
||||
|
} |
||||
|
|
||||
|
if ( fractional == 0.0 ) |
||||
|
{ |
||||
|
// only date
|
||||
|
QDate onlyDT = dtRet.date(); |
||||
|
return QVariant(onlyDT); |
||||
|
} |
||||
|
|
||||
|
return QVariant(dtRet); |
||||
|
} |
||||
|
|
||||
|
/*
|
||||
|
Creates a valid sheet name |
||||
|
minimum length is 1 |
||||
|
maximum length is 31 |
||||
|
doesn't contain special chars: / \ ? * ] [ : |
||||
|
Sheet names must not begin or end with ' (apostrophe) |
||||
|
|
||||
|
Invalid characters are replaced by one space character ' '. |
||||
|
*/ |
||||
|
QString createSafeSheetName(const QString &nameProposal) |
||||
|
{ |
||||
|
if (nameProposal.isEmpty()) |
||||
|
return QString(); |
||||
|
|
||||
|
QString ret = nameProposal; |
||||
|
if (nameProposal.length() > 2 && nameProposal.startsWith(QLatin1Char('\'')) && nameProposal.endsWith(QLatin1Char('\''))) |
||||
|
ret = unescapeSheetName(ret); |
||||
|
|
||||
|
//Replace invalid chars with space.
|
||||
|
static QRegularExpression invalidChars(QStringLiteral("[/\\\\?*\\][:]")); |
||||
|
if (nameProposal.contains(invalidChars)) { |
||||
|
static QRegularExpression validChars(QStringLiteral("[/\\\\?*\\][:]")); |
||||
|
ret.replace(validChars, QStringLiteral(" ")); |
||||
|
} |
||||
|
|
||||
|
if (ret.startsWith(QLatin1Char('\''))) |
||||
|
ret[0] = QLatin1Char(' '); |
||||
|
|
||||
|
if (ret.endsWith(QLatin1Char('\''))) |
||||
|
ret[ret.size()-1] = QLatin1Char(' '); |
||||
|
|
||||
|
if (ret.size() > 31) |
||||
|
ret = ret.left(31); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
/*
|
||||
|
* When sheetName contains space or apostrophe, escaped is needed by cellFormula/definedName/chartSerials. |
||||
|
*/ |
||||
|
QString escapeSheetName(const QString &sheetName) |
||||
|
{ |
||||
|
//Already escaped.
|
||||
|
Q_ASSERT(!sheetName.startsWith(QLatin1Char('\'')) && !sheetName.endsWith(QLatin1Char('\''))); |
||||
|
|
||||
|
//These is no need to escape
|
||||
|
static const auto escape = QRegularExpression(QStringLiteral("[ +\\-,%^=<>'&]")); |
||||
|
if (!sheetName.contains(escape)) |
||||
|
return sheetName; |
||||
|
|
||||
|
//OK, escape is needed.
|
||||
|
QString name = sheetName; |
||||
|
name.replace(QLatin1Char('\''), QLatin1String("\'\'")); |
||||
|
return QLatin1Char('\'') + name + QLatin1Char('\''); |
||||
|
} |
||||
|
|
||||
|
/*
|
||||
|
*/ |
||||
|
QString unescapeSheetName(const QString &sheetName) |
||||
|
{ |
||||
|
Q_ASSERT(sheetName.length() > 2 && sheetName.startsWith(QLatin1Char('\'')) && sheetName.endsWith(QLatin1Char('\''))); |
||||
|
|
||||
|
QString name = sheetName.mid(1, sheetName.length()-2); |
||||
|
name.replace(QLatin1String("\'\'"), QLatin1String("\'")); |
||||
|
return name; |
||||
|
} |
||||
|
|
||||
|
/*
|
||||
|
* whether the string s starts or ends with space |
||||
|
*/ |
||||
|
bool isSpaceReserveNeeded(const QString &s) |
||||
|
{ |
||||
|
QString spaces(QStringLiteral(" \t\n\r")); |
||||
|
return !s.isEmpty() && (spaces.contains(s.at(0))||spaces.contains(s.at(s.length()-1))); |
||||
|
} |
||||
|
|
||||
|
/*
|
||||
|
* Convert shared formula for non-root cells. |
||||
|
* |
||||
|
* For example, if "B1:B10" have shared formula "=A1*A1", this function will return "=A2*A2" |
||||
|
* for "B2" cell, "=A3*A3" for "B3" cell, etc. |
||||
|
* |
||||
|
* Note, the formula "=A1*A1" for B1 can also be written as "=RC[-1]*RC[-1]", which is the same |
||||
|
* for all other cells. In other words, this formula is shared. |
||||
|
* |
||||
|
* For long run, we need a formula parser. |
||||
|
*/ |
||||
|
QString convertSharedFormula(const QString &rootFormula, const CellReference &rootCell, const CellReference &cell) |
||||
|
{ |
||||
|
Q_UNUSED(rootCell) |
||||
|
Q_UNUSED(cell) |
||||
|
//Find all the "$?[A-Z]+$?[0-9]+" patterns in the rootFormula.
|
||||
|
QVector<std::pair<QString, int> > segments; |
||||
|
|
||||
|
QString segment; |
||||
|
bool inQuote = false; |
||||
|
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
|
||||
|
for (QChar ch : rootFormula) { |
||||
|
if (inQuote) { |
||||
|
segment.append(ch); |
||||
|
if (ch == QLatin1Char('"')) |
||||
|
inQuote = false; |
||||
|
} else { |
||||
|
if (ch == QLatin1Char('"')) { |
||||
|
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(std::make_pair(segment, refState==_09 ? refFlag : -1 )); |
||||
|
segment = QString(ch); //Start new segment.
|
||||
|
refState = PRE_AZ; |
||||
|
refFlag = 0x01; |
||||
|
} |
||||
|
} else if (ch >= QLatin1Char('A') && ch <=QLatin1Char('Z')) { |
||||
|
if (refState == PRE_AZ || refState == AZ) { |
||||
|
segment.append(ch); |
||||
|
} else { |
||||
|
segments.append(std::make_pair(segment, refState==_09 ? refFlag : -1 )); |
||||
|
segment = QString(ch); //Start new segment.
|
||||
|
refFlag = 0x00; |
||||
|
} |
||||
|
refState = AZ; |
||||
|
} else if (ch >= QLatin1Char('0') && ch <=QLatin1Char('9')) { |
||||
|
segment.append(ch); |
||||
|
|
||||
|
if (refState == AZ || refState == PRE_09 || refState == _09) |
||||
|
refState = _09; |
||||
|
else |
||||
|
refState = INVALID; |
||||
|
} else { |
||||
|
if (refState == _09) { |
||||
|
segments.append(std::make_pair(segment, refFlag )); |
||||
|
segment = QString(ch); //Start new segment.
|
||||
|
} else { |
||||
|
segment.append(ch); |
||||
|
} |
||||
|
refState = INVALID; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (!segment.isEmpty()) |
||||
|
segments.append(std::make_pair(segment, refState==_09 ? refFlag : -1 )); |
||||
|
|
||||
|
//Replace "A1", "$A1", "A$1" segment with proper one.
|
||||
|
QStringList result; |
||||
|
for (const auto &p : segments) { |
||||
|
//qDebug()<<p.first<<p.second;
|
||||
|
if (p.second != -1 && p.second != 3) { |
||||
|
CellReference oldRef(p.first); |
||||
|
int row = p.second & 0x02 ? oldRef.row() : oldRef.row()-rootCell.row()+cell.row(); |
||||
|
int col = p.second & 0x01 ? oldRef.column() : oldRef.column()-rootCell.column()+cell.column(); |
||||
|
result.append(CellReference(row, col).toString(p.second & 0x02, p.second & 0x01)); |
||||
|
} else { |
||||
|
result.append(p.first); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
//OK
|
||||
|
return result.join(QString()); |
||||
|
} |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
@ -0,0 +1,740 @@ |
|||||
|
// xlsxworkbook.cpp
|
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QXmlStreamWriter> |
||||
|
#include <QXmlStreamReader> |
||||
|
#include <QFile> |
||||
|
#include <QBuffer> |
||||
|
#include <QDir> |
||||
|
#include <QtDebug> |
||||
|
|
||||
|
#include "xlsxworkbook.h" |
||||
|
#include "xlsxworkbook_p.h" |
||||
|
#include "xlsxsharedstrings_p.h" |
||||
|
#include "xlsxworksheet.h" |
||||
|
#include "xlsxchartsheet.h" |
||||
|
#include "xlsxstyles_p.h" |
||||
|
#include "xlsxformat.h" |
||||
|
#include "xlsxworksheet_p.h" |
||||
|
#include "xlsxformat_p.h" |
||||
|
#include "xlsxmediafile_p.h" |
||||
|
#include "xlsxutility_p.h" |
||||
|
#include "xlsxchart.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
WorkbookPrivate::WorkbookPrivate(Workbook *q, Workbook::CreateFlag flag) : |
||||
|
AbstractOOXmlFilePrivate(q, flag) |
||||
|
{ |
||||
|
sharedStrings = QSharedPointer<SharedStrings> (new SharedStrings(flag)); |
||||
|
styles = QSharedPointer<Styles>(new Styles(flag)); |
||||
|
theme = QSharedPointer<Theme>(new Theme(flag)); |
||||
|
|
||||
|
x_window = 240; |
||||
|
y_window = 15; |
||||
|
window_width = 16095; |
||||
|
window_height = 9660; |
||||
|
|
||||
|
strings_to_numbers_enabled = false; |
||||
|
strings_to_hyperlinks_enabled = true; |
||||
|
html_to_richstring_enabled = false; |
||||
|
date1904 = false; |
||||
|
defaultDateFormat = QStringLiteral("yyyy-mm-dd"); |
||||
|
activesheetIndex = 0; |
||||
|
firstsheet = 0; |
||||
|
table_count = 0; |
||||
|
|
||||
|
last_worksheet_index = 0; |
||||
|
last_chartsheet_index = 0; |
||||
|
last_sheet_id = 0; |
||||
|
} |
||||
|
|
||||
|
Workbook::Workbook(CreateFlag flag) |
||||
|
: AbstractOOXmlFile(new WorkbookPrivate(this, flag)) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
Workbook::~Workbook() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
bool Workbook::isDate1904() const |
||||
|
{ |
||||
|
Q_D(const Workbook); |
||||
|
return d->date1904; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
Excel for Windows uses a default epoch of 1900 and Excel |
||||
|
for Mac uses an epoch of 1904. However, Excel on either |
||||
|
platform will convert automatically between one system |
||||
|
and the other. Qt Xlsx stores dates in the 1900 format |
||||
|
by default. |
||||
|
|
||||
|
\note This function should be called before any date/time |
||||
|
has been written. |
||||
|
*/ |
||||
|
void Workbook::setDate1904(bool date1904) |
||||
|
{ |
||||
|
Q_D(Workbook); |
||||
|
d->date1904 = date1904; |
||||
|
} |
||||
|
|
||||
|
/*
|
||||
|
Enable the worksheet.write() method to convert strings |
||||
|
to numbers, where possible, using float() in order to avoid |
||||
|
an Excel warning about "Numbers Stored as Text". |
||||
|
|
||||
|
The default is false |
||||
|
*/ |
||||
|
void Workbook::setStringsToNumbersEnabled(bool enable) |
||||
|
{ |
||||
|
Q_D(Workbook); |
||||
|
d->strings_to_numbers_enabled = enable; |
||||
|
} |
||||
|
|
||||
|
bool Workbook::isStringsToNumbersEnabled() const |
||||
|
{ |
||||
|
Q_D(const Workbook); |
||||
|
return d->strings_to_numbers_enabled; |
||||
|
} |
||||
|
|
||||
|
void Workbook::setStringsToHyperlinksEnabled(bool enable) |
||||
|
{ |
||||
|
Q_D(Workbook); |
||||
|
d->strings_to_hyperlinks_enabled = enable; |
||||
|
} |
||||
|
|
||||
|
bool Workbook::isStringsToHyperlinksEnabled() const |
||||
|
{ |
||||
|
Q_D(const Workbook); |
||||
|
return d->strings_to_hyperlinks_enabled; |
||||
|
} |
||||
|
|
||||
|
void Workbook::setHtmlToRichStringEnabled(bool enable) |
||||
|
{ |
||||
|
Q_D(Workbook); |
||||
|
d->html_to_richstring_enabled = enable; |
||||
|
} |
||||
|
|
||||
|
bool Workbook::isHtmlToRichStringEnabled() const |
||||
|
{ |
||||
|
Q_D(const Workbook); |
||||
|
return d->html_to_richstring_enabled; |
||||
|
} |
||||
|
|
||||
|
QString Workbook::defaultDateFormat() const |
||||
|
{ |
||||
|
Q_D(const Workbook); |
||||
|
return d->defaultDateFormat; |
||||
|
} |
||||
|
|
||||
|
void Workbook::setDefaultDateFormat(const QString &format) |
||||
|
{ |
||||
|
Q_D(Workbook); |
||||
|
d->defaultDateFormat = format; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* \brief Create a defined name in the workbook. |
||||
|
* \param name The defined name |
||||
|
* \param formula The cell or range that the defined name refers to. |
||||
|
* \param comment |
||||
|
* \param scope The name of one worksheet, or empty which means golbal scope. |
||||
|
* \return Return false if the name invalid. |
||||
|
*/ |
||||
|
bool Workbook::defineName(const QString &name, const QString &formula, const QString &comment, const QString &scope) |
||||
|
{ |
||||
|
Q_D(Workbook); |
||||
|
|
||||
|
//Remove the = sign from the formula if it exists.
|
||||
|
QString formulaString = formula; |
||||
|
if (formulaString.startsWith(QLatin1Char('='))) |
||||
|
formulaString = formula.mid(1); |
||||
|
|
||||
|
int id=-1; |
||||
|
if (!scope.isEmpty()) { |
||||
|
for (int i=0; i<d->sheets.size(); ++i) { |
||||
|
if (d->sheets[i]->sheetName() == scope) { |
||||
|
id = d->sheets[i]->sheetId(); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
d->definedNamesList.append(XlsxDefineNameData(name, formulaString, comment, id)); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
AbstractSheet *Workbook::addSheet(const QString &name, AbstractSheet::SheetType type) |
||||
|
{ |
||||
|
Q_D(Workbook); |
||||
|
return insertSheet(d->sheets.size(), name, type); |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* \internal |
||||
|
*/ |
||||
|
QStringList Workbook::worksheetNames() const |
||||
|
{ |
||||
|
Q_D(const Workbook); |
||||
|
return d->sheetNames; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* \internal |
||||
|
* Used only when load the xlsx file!! |
||||
|
*/ |
||||
|
AbstractSheet *Workbook::addSheet(const QString &name, int sheetId, AbstractSheet::SheetType type) |
||||
|
{ |
||||
|
Q_D(Workbook); |
||||
|
if (sheetId > d->last_sheet_id) |
||||
|
d->last_sheet_id = sheetId; |
||||
|
|
||||
|
AbstractSheet *sheet = NULL; |
||||
|
if (type == AbstractSheet::ST_WorkSheet) |
||||
|
{ |
||||
|
// create work sheet (value sheet)
|
||||
|
sheet = new Worksheet(name, sheetId, this, F_LoadFromExists); |
||||
|
} |
||||
|
else if (type == AbstractSheet::ST_ChartSheet) |
||||
|
{ |
||||
|
// create chart sheet
|
||||
|
sheet = new Chartsheet(name, sheetId, this, F_LoadFromExists); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
qWarning("unsupported sheet type."); |
||||
|
Q_ASSERT(false); |
||||
|
} |
||||
|
|
||||
|
d->sheets.append(QSharedPointer<AbstractSheet>(sheet)); |
||||
|
d->sheetNames.append(name); |
||||
|
|
||||
|
return sheet; |
||||
|
} |
||||
|
|
||||
|
AbstractSheet *Workbook::insertSheet(int index, const QString &name, AbstractSheet::SheetType type) |
||||
|
{ |
||||
|
Q_D(Workbook); |
||||
|
QString sheetName = createSafeSheetName(name); |
||||
|
if(index > d->last_sheet_id){ |
||||
|
//User tries to insert, where no sheet has gone before.
|
||||
|
return 0; |
||||
|
} |
||||
|
if (!sheetName.isEmpty()) { |
||||
|
//If user given an already in-used name, we should not continue any more!
|
||||
|
if (d->sheetNames.contains(sheetName)) |
||||
|
return 0; |
||||
|
} else { |
||||
|
if (type == AbstractSheet::ST_WorkSheet) { |
||||
|
do { |
||||
|
++d->last_worksheet_index; |
||||
|
sheetName = QStringLiteral("Sheet%1").arg(d->last_worksheet_index); |
||||
|
} while (d->sheetNames.contains(sheetName)); |
||||
|
} else if (type == AbstractSheet::ST_ChartSheet) { |
||||
|
do { |
||||
|
++d->last_chartsheet_index; |
||||
|
sheetName = QStringLiteral("Chart%1").arg(d->last_chartsheet_index); |
||||
|
} while (d->sheetNames.contains(sheetName)); |
||||
|
} else { |
||||
|
qWarning("unsupported sheet type."); |
||||
|
return 0; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
++d->last_sheet_id; |
||||
|
|
||||
|
AbstractSheet *sheet = NULL; |
||||
|
if ( type == AbstractSheet::ST_WorkSheet ) |
||||
|
{ |
||||
|
sheet = new Worksheet(sheetName, d->last_sheet_id, this, F_NewFromScratch); |
||||
|
} |
||||
|
else if ( type == AbstractSheet::ST_ChartSheet ) |
||||
|
{ |
||||
|
sheet = new Chartsheet(sheetName, d->last_sheet_id, this, F_NewFromScratch); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
qWarning("unsupported sheet type."); |
||||
|
Q_ASSERT(false); |
||||
|
} |
||||
|
|
||||
|
d->sheets.insert(index, QSharedPointer<AbstractSheet>(sheet)); |
||||
|
d->sheetNames.insert(index, sheetName); |
||||
|
d->activesheetIndex = index; |
||||
|
|
||||
|
return sheet; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* Returns current active worksheet. |
||||
|
*/ |
||||
|
AbstractSheet *Workbook::activeSheet() const |
||||
|
{ |
||||
|
Q_D(const Workbook); |
||||
|
if (d->sheets.isEmpty()) |
||||
|
const_cast<Workbook*>(this)->addSheet(); |
||||
|
return d->sheets[d->activesheetIndex].data(); |
||||
|
} |
||||
|
|
||||
|
bool Workbook::setActiveSheet(int index) |
||||
|
{ |
||||
|
Q_D(Workbook); |
||||
|
if (index < 0 || index >= d->sheets.size()) { |
||||
|
//warning
|
||||
|
return false; |
||||
|
} |
||||
|
d->activesheetIndex = index; |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* Rename the worksheet at the \a index to \a newName. |
||||
|
*/ |
||||
|
bool Workbook::renameSheet(int index, const QString &newName) |
||||
|
{ |
||||
|
Q_D(Workbook); |
||||
|
QString name = createSafeSheetName(newName); |
||||
|
if (index < 0 || index >= d->sheets.size()) |
||||
|
return false; |
||||
|
|
||||
|
//If user given an already in-used name, return false
|
||||
|
for (int i=0; i<d->sheets.size(); ++i) { |
||||
|
if (d->sheets[i]->sheetName() == name) |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
d->sheets[index]->setSheetName(name); |
||||
|
d->sheetNames[index] = name; |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* Remove the worksheet at pos \a index. |
||||
|
*/ |
||||
|
bool Workbook::deleteSheet(int index) |
||||
|
{ |
||||
|
Q_D(Workbook); |
||||
|
if (d->sheets.size() <= 1) |
||||
|
return false; |
||||
|
if (index < 0 || index >= d->sheets.size()) |
||||
|
return false; |
||||
|
d->sheets.removeAt(index); |
||||
|
d->sheetNames.removeAt(index); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* Moves the worksheet form \a srcIndex to \a distIndex. |
||||
|
*/ |
||||
|
bool Workbook::moveSheet(int srcIndex, int distIndex) |
||||
|
{ |
||||
|
Q_D(Workbook); |
||||
|
if (srcIndex == distIndex) |
||||
|
return false; |
||||
|
|
||||
|
if (srcIndex < 0 || srcIndex >= d->sheets.size()) |
||||
|
return false; |
||||
|
|
||||
|
QSharedPointer<AbstractSheet> sheet = d->sheets.takeAt(srcIndex); |
||||
|
d->sheetNames.takeAt(srcIndex); |
||||
|
if (distIndex >= 0 || distIndex <= d->sheets.size()) { |
||||
|
d->sheets.insert(distIndex, sheet); |
||||
|
d->sheetNames.insert(distIndex, sheet->sheetName()); |
||||
|
} else { |
||||
|
d->sheets.append(sheet); |
||||
|
d->sheetNames.append(sheet->sheetName()); |
||||
|
} |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
bool Workbook::copySheet(int index, const QString &newName) |
||||
|
{ |
||||
|
Q_D(Workbook); |
||||
|
if (index < 0 || index >= d->sheets.size()) |
||||
|
return false; |
||||
|
|
||||
|
QString worksheetName = createSafeSheetName(newName); |
||||
|
if (!newName.isEmpty()) { |
||||
|
//If user given an already in-used name, we should not continue any more!
|
||||
|
if (d->sheetNames.contains(newName)) |
||||
|
return false; |
||||
|
} else { |
||||
|
int copy_index = 1; |
||||
|
do { |
||||
|
++copy_index; |
||||
|
worksheetName = QStringLiteral("%1(%2)").arg(d->sheets[index]->sheetName()).arg(copy_index); |
||||
|
} while (d->sheetNames.contains(worksheetName)); |
||||
|
} |
||||
|
|
||||
|
++d->last_sheet_id; |
||||
|
AbstractSheet *sheet = d->sheets[index]->copy(worksheetName, d->last_sheet_id); |
||||
|
d->sheets.append(QSharedPointer<AbstractSheet> (sheet)); |
||||
|
d->sheetNames.append(sheet->sheetName()); |
||||
|
|
||||
|
return true; // #162
|
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* Returns count of worksheets. |
||||
|
*/ |
||||
|
int Workbook::sheetCount() const |
||||
|
{ |
||||
|
Q_D(const Workbook); |
||||
|
return d->sheets.count(); |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* Returns the sheet object at index \a sheetIndex. |
||||
|
*/ |
||||
|
AbstractSheet *Workbook::sheet(int index) const |
||||
|
{ |
||||
|
Q_D(const Workbook); |
||||
|
if (index < 0 || index >= d->sheets.size()) |
||||
|
return 0; |
||||
|
return d->sheets.at(index).data(); |
||||
|
} |
||||
|
|
||||
|
SharedStrings *Workbook::sharedStrings() const |
||||
|
{ |
||||
|
Q_D(const Workbook); |
||||
|
return d->sharedStrings.data(); |
||||
|
} |
||||
|
|
||||
|
Styles *Workbook::styles() |
||||
|
{ |
||||
|
Q_D(Workbook); |
||||
|
return d->styles.data(); |
||||
|
} |
||||
|
|
||||
|
Theme *Workbook::theme() |
||||
|
{ |
||||
|
Q_D(Workbook); |
||||
|
return d->theme.data(); |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* \internal |
||||
|
* |
||||
|
* Unlike media files, drawing file is a property of the sheet. |
||||
|
*/ |
||||
|
QList<Drawing *> Workbook::drawings() |
||||
|
{ |
||||
|
Q_D(Workbook); |
||||
|
QList<Drawing *> ds; |
||||
|
for (int i=0; i<d->sheets.size(); ++i) { |
||||
|
QSharedPointer<AbstractSheet> sheet = d->sheets[i]; |
||||
|
if (sheet->drawing()) |
||||
|
ds.append(sheet->drawing()); |
||||
|
} |
||||
|
|
||||
|
return ds; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* \internal |
||||
|
*/ |
||||
|
QList<QSharedPointer<AbstractSheet> > Workbook::getSheetsByTypes(AbstractSheet::SheetType type) const |
||||
|
{ |
||||
|
Q_D(const Workbook); |
||||
|
QList<QSharedPointer<AbstractSheet> > list; |
||||
|
for (int i=0; i<d->sheets.size(); ++i) { |
||||
|
if (d->sheets[i]->sheetType() == type) |
||||
|
list.append(d->sheets[i]); |
||||
|
} |
||||
|
return list; |
||||
|
} |
||||
|
|
||||
|
void Workbook::saveToXmlFile(QIODevice *device) const |
||||
|
{ |
||||
|
Q_D(const Workbook); |
||||
|
d->relationships->clear(); |
||||
|
if (d->sheets.isEmpty()) |
||||
|
const_cast<Workbook *>(this)->addSheet(); |
||||
|
|
||||
|
QXmlStreamWriter writer(device); |
||||
|
|
||||
|
writer.writeStartDocument(QStringLiteral("1.0"), true); |
||||
|
writer.writeStartElement(QStringLiteral("workbook")); |
||||
|
writer.writeAttribute(QStringLiteral("xmlns"), QStringLiteral("http://schemas.openxmlformats.org/spreadsheetml/2006/main")); |
||||
|
writer.writeAttribute(QStringLiteral("xmlns:r"), QStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/relationships")); |
||||
|
|
||||
|
writer.writeEmptyElement(QStringLiteral("fileVersion")); |
||||
|
writer.writeAttribute(QStringLiteral("appName"), QStringLiteral("xl")); |
||||
|
writer.writeAttribute(QStringLiteral("lastEdited"), QStringLiteral("4")); |
||||
|
writer.writeAttribute(QStringLiteral("lowestEdited"), QStringLiteral("4")); |
||||
|
writer.writeAttribute(QStringLiteral("rupBuild"), QStringLiteral("4505")); |
||||
|
// writer.writeAttribute(QStringLiteral("codeName"), QStringLiteral("{37E998C4-C9E5-D4B9-71C8-EB1FF731991C}"));
|
||||
|
|
||||
|
writer.writeEmptyElement(QStringLiteral("workbookPr")); |
||||
|
if (d->date1904) |
||||
|
writer.writeAttribute(QStringLiteral("date1904"), QStringLiteral("1")); |
||||
|
writer.writeAttribute(QStringLiteral("defaultThemeVersion"), QStringLiteral("124226")); |
||||
|
|
||||
|
writer.writeStartElement(QStringLiteral("bookViews")); |
||||
|
writer.writeEmptyElement(QStringLiteral("workbookView")); |
||||
|
writer.writeAttribute(QStringLiteral("xWindow"), QString::number(d->x_window)); |
||||
|
writer.writeAttribute(QStringLiteral("yWindow"), QString::number(d->y_window)); |
||||
|
writer.writeAttribute(QStringLiteral("windowWidth"), QString::number(d->window_width)); |
||||
|
writer.writeAttribute(QStringLiteral("windowHeight"), QString::number(d->window_height)); |
||||
|
//Store the firstSheet when it isn't the default
|
||||
|
//For example, when "the first sheet 0 is hidden", the first sheet will be 1
|
||||
|
if (d->firstsheet > 0) |
||||
|
writer.writeAttribute(QStringLiteral("firstSheet"), QString::number(d->firstsheet + 1)); |
||||
|
//Store the activeTab when it isn't the first sheet
|
||||
|
if (d->activesheetIndex > 0) |
||||
|
writer.writeAttribute(QStringLiteral("activeTab"), QString::number(d->activesheetIndex)); |
||||
|
writer.writeEndElement();//bookViews
|
||||
|
|
||||
|
writer.writeStartElement(QStringLiteral("sheets")); |
||||
|
int worksheetIndex = 0; |
||||
|
int chartsheetIndex = 0; |
||||
|
for (int i=0; i<d->sheets.size(); ++i) { |
||||
|
QSharedPointer<AbstractSheet> sheet = d->sheets[i]; |
||||
|
writer.writeEmptyElement(QStringLiteral("sheet")); |
||||
|
writer.writeAttribute(QStringLiteral("name"), sheet->sheetName()); |
||||
|
writer.writeAttribute(QStringLiteral("sheetId"), QString::number(sheet->sheetId())); |
||||
|
if (sheet->sheetState() == AbstractSheet::SS_Hidden) |
||||
|
writer.writeAttribute(QStringLiteral("state"), QStringLiteral("hidden")); |
||||
|
else if (sheet->sheetState() == AbstractSheet::SS_VeryHidden) |
||||
|
writer.writeAttribute(QStringLiteral("state"), QStringLiteral("veryHidden")); |
||||
|
|
||||
|
if (sheet->sheetType() == AbstractSheet::ST_WorkSheet) |
||||
|
d->relationships->addDocumentRelationship(QStringLiteral("/worksheet"), QStringLiteral("worksheets/sheet%1.xml").arg(++worksheetIndex)); |
||||
|
else |
||||
|
d->relationships->addDocumentRelationship(QStringLiteral("/chartsheet"), QStringLiteral("chartsheets/sheet%1.xml").arg(++chartsheetIndex)); |
||||
|
|
||||
|
writer.writeAttribute(QStringLiteral("r:id"), QStringLiteral("rId%1").arg(d->relationships->count())); |
||||
|
} |
||||
|
writer.writeEndElement();//sheets
|
||||
|
|
||||
|
if (d->externalLinks.size() > 0) { |
||||
|
writer.writeStartElement(QStringLiteral("externalReferences")); |
||||
|
for (int i=0; i<d->externalLinks.size(); ++i) { |
||||
|
writer.writeEmptyElement(QStringLiteral("externalReference")); |
||||
|
d->relationships->addDocumentRelationship(QStringLiteral("/externalLink"), QStringLiteral("externalLinks/externalLink%1.xml").arg(i+1)); |
||||
|
writer.writeAttribute(QStringLiteral("r:id"), QStringLiteral("rId%1").arg(d->relationships->count())); |
||||
|
} |
||||
|
writer.writeEndElement();//externalReferences
|
||||
|
} |
||||
|
|
||||
|
if (!d->definedNamesList.isEmpty()) { |
||||
|
writer.writeStartElement(QStringLiteral("definedNames")); |
||||
|
for (const XlsxDefineNameData &data : d->definedNamesList) { |
||||
|
writer.writeStartElement(QStringLiteral("definedName")); |
||||
|
writer.writeAttribute(QStringLiteral("name"), data.name); |
||||
|
if (!data.comment.isEmpty()) |
||||
|
writer.writeAttribute(QStringLiteral("comment"), data.comment); |
||||
|
if (data.sheetId != -1) { |
||||
|
//find the local index of the sheet.
|
||||
|
for (int i=0; i<d->sheets.size(); ++i) { |
||||
|
if (d->sheets[i]->sheetId() == data.sheetId) { |
||||
|
writer.writeAttribute(QStringLiteral("localSheetId"), QString::number(i)); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
writer.writeCharacters(data.formula); |
||||
|
writer.writeEndElement();//definedName
|
||||
|
} |
||||
|
writer.writeEndElement();//definedNames
|
||||
|
} |
||||
|
|
||||
|
writer.writeStartElement(QStringLiteral("calcPr")); |
||||
|
writer.writeAttribute(QStringLiteral("calcId"), QStringLiteral("124519")); |
||||
|
writer.writeEndElement(); //calcPr
|
||||
|
|
||||
|
writer.writeEndElement();//workbook
|
||||
|
writer.writeEndDocument(); |
||||
|
|
||||
|
d->relationships->addDocumentRelationship(QStringLiteral("/theme"), QStringLiteral("theme/theme1.xml")); |
||||
|
d->relationships->addDocumentRelationship(QStringLiteral("/styles"), QStringLiteral("styles.xml")); |
||||
|
if (!sharedStrings()->isEmpty()) |
||||
|
d->relationships->addDocumentRelationship(QStringLiteral("/sharedStrings"), QStringLiteral("sharedStrings.xml")); |
||||
|
} |
||||
|
|
||||
|
bool Workbook::loadFromXmlFile(QIODevice *device) |
||||
|
{ |
||||
|
Q_D(Workbook); |
||||
|
|
||||
|
QXmlStreamReader reader(device); |
||||
|
while (!reader.atEnd()) |
||||
|
{ |
||||
|
QXmlStreamReader::TokenType token = reader.readNext(); |
||||
|
if (token == QXmlStreamReader::StartElement) |
||||
|
{ |
||||
|
if (reader.name() == QLatin1String("sheet")) |
||||
|
{ |
||||
|
QXmlStreamAttributes attributes = reader.attributes(); |
||||
|
|
||||
|
const auto& name = attributes.value(QLatin1String("name")).toString(); |
||||
|
|
||||
|
int sheetId = attributes.value(QLatin1String("sheetId")).toInt(); |
||||
|
|
||||
|
const auto& rId = attributes.value(QLatin1String("r:id")).toString(); |
||||
|
|
||||
|
const auto& stateString = attributes.value(QLatin1String("state")); |
||||
|
|
||||
|
AbstractSheet::SheetState state = AbstractSheet::SS_Visible; |
||||
|
if (stateString == QLatin1String("hidden")) |
||||
|
state = AbstractSheet::SS_Hidden; |
||||
|
else if (stateString == QLatin1String("veryHidden")) |
||||
|
state = AbstractSheet::SS_VeryHidden; |
||||
|
|
||||
|
XlsxRelationship relationship = d->relationships->getRelationshipById(rId); |
||||
|
|
||||
|
AbstractSheet::SheetType type = AbstractSheet::ST_WorkSheet; |
||||
|
if (relationship.type.endsWith(QLatin1String("/worksheet"))) |
||||
|
{ |
||||
|
type = AbstractSheet::ST_WorkSheet; |
||||
|
} |
||||
|
else if (relationship.type.endsWith(QLatin1String("/chartsheet"))) |
||||
|
{ |
||||
|
type = AbstractSheet::ST_ChartSheet; |
||||
|
} |
||||
|
else if (relationship.type.endsWith(QLatin1String("/dialogsheet"))) |
||||
|
{ |
||||
|
type = AbstractSheet::ST_DialogSheet; |
||||
|
} |
||||
|
else if (relationship.type.endsWith(QLatin1String("/xlMacrosheet"))) |
||||
|
{ |
||||
|
type = AbstractSheet::ST_MacroSheet; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
qWarning() << "unknown sheet type : " << relationship.type ; |
||||
|
} |
||||
|
|
||||
|
AbstractSheet *sheet = addSheet(name, sheetId, type); |
||||
|
sheet->setSheetState(state); |
||||
|
QString strFilePath = filePath(); |
||||
|
|
||||
|
// const QString fullPath = QDir::cleanPath(splitPath(strFilePath).constFirst() + QLatin1String("/") + relationship.target);
|
||||
|
const auto parts = splitPath(strFilePath); |
||||
|
QString fullPath = QDir::cleanPath(parts.first() + QLatin1String("/") + relationship.target); |
||||
|
|
||||
|
sheet->setFilePath(fullPath); |
||||
|
} |
||||
|
else if (reader.name() == QLatin1String("workbookPr")) |
||||
|
{ |
||||
|
QXmlStreamAttributes attrs = reader.attributes(); |
||||
|
if (attrs.hasAttribute(QLatin1String("date1904"))) |
||||
|
d->date1904 = true; |
||||
|
} |
||||
|
else if (reader.name() == QLatin1String("bookviews")) |
||||
|
{ |
||||
|
while (!(reader.name() == QLatin1String("bookviews") && |
||||
|
reader.tokenType() == QXmlStreamReader::EndElement)) |
||||
|
{ |
||||
|
reader.readNextStartElement(); |
||||
|
if (reader.tokenType() == QXmlStreamReader::StartElement) |
||||
|
{ |
||||
|
if (reader.name() == QLatin1String("workbookView")) |
||||
|
{ |
||||
|
QXmlStreamAttributes attrs = reader.attributes(); |
||||
|
if (attrs.hasAttribute(QLatin1String("xWindow"))) |
||||
|
d->x_window = attrs.value(QLatin1String("xWindow")).toInt(); |
||||
|
if (attrs.hasAttribute(QLatin1String("yWindow"))) |
||||
|
d->y_window = attrs.value(QLatin1String("yWindow")).toInt(); |
||||
|
if (attrs.hasAttribute(QLatin1String("windowWidth"))) |
||||
|
d->window_width = attrs.value(QLatin1String("windowWidth")).toInt(); |
||||
|
if (attrs.hasAttribute(QLatin1String("windowHeight"))) |
||||
|
d->window_height = attrs.value(QLatin1String("windowHeight")).toInt(); |
||||
|
if (attrs.hasAttribute(QLatin1String("firstSheet"))) |
||||
|
d->firstsheet = attrs.value(QLatin1String("firstSheet")).toInt(); |
||||
|
if (attrs.hasAttribute(QLatin1String("activeTab"))) |
||||
|
d->activesheetIndex = attrs.value(QLatin1String("activeTab")).toInt(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
else if (reader.name() == QLatin1String("externalReference")) |
||||
|
{ |
||||
|
QXmlStreamAttributes attributes = reader.attributes(); |
||||
|
const QString rId = attributes.value(QLatin1String("r:id")).toString(); |
||||
|
XlsxRelationship relationship = d->relationships->getRelationshipById(rId); |
||||
|
|
||||
|
QSharedPointer<SimpleOOXmlFile> link(new SimpleOOXmlFile(F_LoadFromExists)); |
||||
|
|
||||
|
const auto parts = splitPath(filePath()); |
||||
|
QString fullPath = QDir::cleanPath(parts.first() + QLatin1String("/") + relationship.target); |
||||
|
|
||||
|
link->setFilePath(fullPath); |
||||
|
d->externalLinks.append(link); |
||||
|
} else if (reader.name() == QLatin1String("definedName")) { |
||||
|
QXmlStreamAttributes attrs = reader.attributes(); |
||||
|
XlsxDefineNameData data; |
||||
|
|
||||
|
data.name = attrs.value(QLatin1String("name")).toString(); |
||||
|
if (attrs.hasAttribute(QLatin1String("comment"))) |
||||
|
data.comment = attrs.value(QLatin1String("comment")).toString(); |
||||
|
if (attrs.hasAttribute(QLatin1String("localSheetId"))) { |
||||
|
int localId = attrs.value(QLatin1String("localSheetId")).toInt(); |
||||
|
int sheetId = d->sheets.at(localId)->sheetId(); |
||||
|
data.sheetId = sheetId; |
||||
|
} |
||||
|
data.formula = reader.readElementText(); |
||||
|
d->definedNamesList.append(data); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* \internal |
||||
|
*/ |
||||
|
QList<std::shared_ptr<MediaFile> > Workbook::mediaFiles() const |
||||
|
{ |
||||
|
Q_D(const Workbook); |
||||
|
|
||||
|
return d->mediaFiles; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* \internal |
||||
|
*/ |
||||
|
void Workbook::addMediaFile(std::shared_ptr<MediaFile> media, bool force) |
||||
|
{ |
||||
|
Q_D(Workbook); |
||||
|
|
||||
|
if (!force) |
||||
|
{ |
||||
|
for (int i=0; i<d->mediaFiles.size(); ++i) |
||||
|
{ |
||||
|
if (d->mediaFiles[i]->hashKey() == media->hashKey()) |
||||
|
{ |
||||
|
media->setIndex(i); |
||||
|
return; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
media->setIndex(d->mediaFiles.size()); |
||||
|
d->mediaFiles.append(media); |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* \internal |
||||
|
*/ |
||||
|
QList<QSharedPointer<Chart> > Workbook::chartFiles() const |
||||
|
{ |
||||
|
Q_D(const Workbook); |
||||
|
|
||||
|
return d->chartFiles; |
||||
|
} |
||||
|
|
||||
|
/*!
|
||||
|
* \internal |
||||
|
*/ |
||||
|
void Workbook::addChartFile(QSharedPointer<Chart> chart) |
||||
|
{ |
||||
|
Q_D(Workbook); |
||||
|
|
||||
|
if (!d->chartFiles.contains(chart)) |
||||
|
d->chartFiles.append(chart); |
||||
|
} |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
File diff suppressed because it is too large
@ -0,0 +1,50 @@ |
|||||
|
// xlsxzipreader.cpp
|
||||
|
|
||||
|
#include "xlsxzipreader_p.h" |
||||
|
|
||||
|
#include <private/qzipreader_p.h> |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
ZipReader::ZipReader(const QString &filePath) : |
||||
|
m_reader(new QZipReader(filePath)) |
||||
|
{ |
||||
|
init(); |
||||
|
} |
||||
|
|
||||
|
ZipReader::ZipReader(QIODevice *device) : |
||||
|
m_reader(new QZipReader(device)) |
||||
|
{ |
||||
|
init(); |
||||
|
} |
||||
|
|
||||
|
ZipReader::~ZipReader() |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
void ZipReader::init() |
||||
|
{ |
||||
|
const auto& allFiles = m_reader->fileInfoList(); |
||||
|
for (const auto &fi : allFiles) { |
||||
|
if (fi.isFile || (!fi.isDir && !fi.isFile && !fi.isSymLink)) |
||||
|
m_filePaths.append(fi.filePath); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
bool ZipReader::exists() const |
||||
|
{ |
||||
|
return m_reader->exists(); |
||||
|
} |
||||
|
|
||||
|
QStringList ZipReader::filePaths() const |
||||
|
{ |
||||
|
return m_filePaths; |
||||
|
} |
||||
|
|
||||
|
QByteArray ZipReader::fileData(const QString &fileName) const |
||||
|
{ |
||||
|
return m_reader->fileData(fileName); |
||||
|
} |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
@ -0,0 +1,48 @@ |
|||||
|
// xlsxzipwriter.cpp
|
||||
|
|
||||
|
#include "xlsxzipwriter_p.h" |
||||
|
|
||||
|
#include <QtGlobal> |
||||
|
#include <QDebug> |
||||
|
#include <private/qzipwriter_p.h> |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE_XLSX |
||||
|
|
||||
|
ZipWriter::ZipWriter(const QString &filePath) |
||||
|
{ |
||||
|
m_writer = new QZipWriter(filePath, QIODevice::WriteOnly); |
||||
|
m_writer->setCompressionPolicy(QZipWriter::AutoCompress); |
||||
|
} |
||||
|
|
||||
|
ZipWriter::ZipWriter(QIODevice *device) |
||||
|
{ |
||||
|
m_writer = new QZipWriter(device); |
||||
|
m_writer->setCompressionPolicy(QZipWriter::AutoCompress); |
||||
|
} |
||||
|
|
||||
|
ZipWriter::~ZipWriter() |
||||
|
{ |
||||
|
delete m_writer; |
||||
|
} |
||||
|
|
||||
|
bool ZipWriter::error() const |
||||
|
{ |
||||
|
return m_writer->status() != QZipWriter::NoError; |
||||
|
} |
||||
|
|
||||
|
void ZipWriter::addFile(const QString &filePath, QIODevice *device) |
||||
|
{ |
||||
|
m_writer->addFile(filePath, device); |
||||
|
} |
||||
|
|
||||
|
void ZipWriter::addFile(const QString &filePath, const QByteArray &data) |
||||
|
{ |
||||
|
m_writer->addFile(filePath, data); |
||||
|
} |
||||
|
|
||||
|
void ZipWriter::close() |
||||
|
{ |
||||
|
m_writer->close(); |
||||
|
} |
||||
|
|
||||
|
QT_END_NAMESPACE_XLSX |
@ -0,0 +1,61 @@ |
|||||
|
#include "include/XlsxReader.h" |
||||
|
|
||||
|
#include "include/QXlsx/xlsxdocument.h" |
||||
|
#include "include/QXlsx/xlsxcellrange.h" |
||||
|
#include "include/QXlsx/xlsxrichstring.h" |
||||
|
#include "include/QXlsx/xlsxworkbook.h" |
||||
|
#include "include/QXlsx/xlsxcellrange.h" |
||||
|
|
||||
|
using namespace QXlsx; |
||||
|
XlsxReader::XlsxReader() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
QList<QStringList> XlsxReader::ReadeXlsx(QString pathOfXlsx) |
||||
|
{ |
||||
|
QList<QStringList> cellValues; |
||||
|
auto sheetCounter = 0; |
||||
|
QXlsx::Document xlsxDoc(pathOfXlsx); |
||||
|
//QXlsx::Document xlsxDoc("Test.xlsx");
|
||||
|
int sheetIndexNumber = 0; |
||||
|
foreach(QString currentSheetName, xlsxDoc.sheetNames()) |
||||
|
{ |
||||
|
sheetCounter++; |
||||
|
//get current sheet
|
||||
|
AbstractSheet* currentSheet = xlsxDoc.sheet(currentSheetName); |
||||
|
if(NULL == currentSheet) |
||||
|
{ |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
//get full cells of current sheet
|
||||
|
int maxRow = -1; |
||||
|
int maxCol = -1; |
||||
|
currentSheet->workbook()->setActiveSheet(sheetIndexNumber); |
||||
|
Worksheet* wsheet = (Worksheet*)currentSheet->workbook()->activeSheet(); |
||||
|
if(NULL == wsheet) |
||||
|
{ |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
QString strSheetName = wsheet->sheetName(); //sheet name
|
||||
|
|
||||
|
QVector<CellLocation> clList = wsheet->getFullCells(&maxRow, &maxCol); |
||||
|
|
||||
|
//to do QList<QStringList> cellValues;
|
||||
|
for(int rc = 1; rc <= maxRow; rc++) |
||||
|
{ |
||||
|
QStringList tempValue = {}; |
||||
|
for(int cc = 1; cc <= maxCol; cc++) |
||||
|
{ |
||||
|
QVariant var = xlsxDoc.read(rc, cc); |
||||
|
tempValue.append(var.toString()); |
||||
|
} |
||||
|
cellValues.append(tempValue); |
||||
|
} |
||||
|
//generateXML(cellValues, sheetCounter, fieldNames);
|
||||
|
sheetIndexNumber++; |
||||
|
} |
||||
|
|
||||
|
return cellValues; |
||||
|
} |
@ -0,0 +1,38 @@ |
|||||
|
#include "include/XlsxXmlConverter.h" |
||||
|
#include "include/XlsxReader.h" |
||||
|
#include "include/XmlTemplateReader.h" |
||||
|
#include "include/XmlGenerator.h" |
||||
|
|
||||
|
XlsxXmlConverter::XlsxXmlConverter() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/*************************************************************************************************/ |
||||
|
void XlsxXmlConverter::initPath(QString xlsxPath, QString patternFilePath, QString outputFilePath) |
||||
|
{ |
||||
|
xlsxFilePath = xlsxPath; |
||||
|
xmlPatternFilePath = patternFilePath; |
||||
|
xmlOutPutFilePath = outputFilePath; |
||||
|
} |
||||
|
|
||||
|
/*************************************************************************************************/ |
||||
|
void XlsxXmlConverter::readXlsx() |
||||
|
{ |
||||
|
XlsxReader xlsReader; |
||||
|
xlsxData = xlsReader.ReadeXlsx(xlsxFilePath); |
||||
|
} |
||||
|
|
||||
|
/*************************************************************************************************/ |
||||
|
void XlsxXmlConverter::readPattern() |
||||
|
{ |
||||
|
XmlTemplateReader readPattern; |
||||
|
patternList = readPattern.readxmlPattern(xmlPatternFilePath); |
||||
|
} |
||||
|
|
||||
|
/*************************************************************************************************/ |
||||
|
void XlsxXmlConverter::wrtiteXMl() |
||||
|
{ |
||||
|
XmlGenerator generatorXml; |
||||
|
qint16 sheetCounter = 1; |
||||
|
generatorXml.generateXML(xlsxData, sheetCounter, patternList, xmlOutPutFilePath); |
||||
|
} |
@ -0,0 +1,44 @@ |
|||||
|
#include "include/XmlGenerator.h" |
||||
|
#include <QtXml> |
||||
|
#include <QTextStream> |
||||
|
XmlGenerator::XmlGenerator() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/*************************************************************************************************/ |
||||
|
void XmlGenerator::generateXML(QList<QStringList> inputList, |
||||
|
qint16 sheetCounter, |
||||
|
QList<QString> patternList, |
||||
|
QString outputPath) |
||||
|
{ |
||||
|
QFile xmlFile("xmlSample" + QString::number(sheetCounter) + ".xml"); |
||||
|
if(!xmlFile.open(QFile::WriteOnly | QFile::Text)) |
||||
|
{ |
||||
|
qDebug() << "Already opened or there is another issue"; |
||||
|
xmlFile.close(); |
||||
|
} |
||||
|
|
||||
|
QXmlStreamWriter xmlWriter(&xmlFile); |
||||
|
xmlWriter.setAutoFormatting(true); |
||||
|
xmlWriter.writeStartDocument(); |
||||
|
|
||||
|
xmlWriter.writeStartElement(patternList[0]); |
||||
|
xmlWriter.writeAttribute("name", patternList[1]); |
||||
|
for(int rc = 1; rc < inputList.count(); rc++) |
||||
|
{ |
||||
|
xmlWriter.writeStartElement(patternList[2]); |
||||
|
for(int cc = 0; cc < inputList.at(0).count(); cc++) |
||||
|
{ |
||||
|
if(patternList.contains(inputList.at(0).at(cc))) |
||||
|
{ |
||||
|
xmlWriter.writeStartElement(patternList[3]); |
||||
|
xmlWriter.writeAttribute("name", inputList.at(0).at(cc)); |
||||
|
xmlWriter.writeAttribute("value", inputList.at(rc).at(cc)); |
||||
|
xmlWriter.writeEndElement(); |
||||
|
} |
||||
|
} |
||||
|
xmlWriter.writeEndElement(); |
||||
|
} |
||||
|
xmlWriter.writeEndElement(); |
||||
|
xmlFile.close(); |
||||
|
} |
@ -0,0 +1,71 @@ |
|||||
|
#include "include/XmlTemplateReader.h" |
||||
|
|
||||
|
#include <QtXml> |
||||
|
#include <QTextStream> |
||||
|
|
||||
|
XmlTemplateReader::XmlTemplateReader() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/*************************************************************************************************/ |
||||
|
QList<QString> XmlTemplateReader::readxmlPattern(QString pathOfPattern) |
||||
|
{ |
||||
|
QList<QString> fieldNamelist; |
||||
|
//------------------------------------------
|
||||
|
/* Open the file for reading by using the path specified in lineEditWrite */ |
||||
|
QFile xmlPatternFile(pathOfPattern); |
||||
|
|
||||
|
//The QDomDocument class represents an XML document.
|
||||
|
|
||||
|
if(!xmlPatternFile.open(QIODevice::ReadOnly | QIODevice::Text)) |
||||
|
{ |
||||
|
qDebug() << "Already opened or there is another issue"; |
||||
|
xmlPatternFile.close(); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
QDomDocument xmlPattern; |
||||
|
xmlPattern.setContent(&xmlPatternFile); |
||||
|
xmlPatternFile.close(); |
||||
|
|
||||
|
//_________________________
|
||||
|
//::: Read the root tag :::
|
||||
|
QDomElement root = xmlPattern.documentElement(); |
||||
|
|
||||
|
//Get root names and attributes
|
||||
|
QString rootName = root.tagName(); |
||||
|
auto rootAttValue = root.attributes().item(0).nodeValue(); |
||||
|
|
||||
|
//::: Read data :::
|
||||
|
//Get the first child of the root (Markup COMPONENT is expected)
|
||||
|
QDomElement entity = root.firstChild().toElement(); |
||||
|
auto entityName = entity.tagName(); |
||||
|
|
||||
|
QDomElement field = entity.firstChild().toElement(); |
||||
|
auto fieldName = field.tagName(); |
||||
|
|
||||
|
fieldNamelist.append(rootName); |
||||
|
fieldNamelist.append(rootAttValue); |
||||
|
fieldNamelist.append(entityName); |
||||
|
fieldNamelist.append(fieldName); |
||||
|
//Loop while there is a child
|
||||
|
while(!entity.isNull()) |
||||
|
{ |
||||
|
//Get the first child of the component
|
||||
|
field = entity.firstChild().toElement(); |
||||
|
//Read each child of the component node
|
||||
|
while(!field.isNull()) |
||||
|
{ |
||||
|
auto secondattName = field.attributes().item(0).nodeName(); |
||||
|
auto secondattValue = field.attributes().item(0).nodeValue(); |
||||
|
fieldNamelist.append(secondattValue); |
||||
|
//Next child
|
||||
|
field = field.nextSibling().toElement(); |
||||
|
} |
||||
|
|
||||
|
entity = entity.nextSibling().toElement(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return fieldNamelist; |
||||
|
} |
Loading…
Reference in new issue