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