We can read and modify existing simple .xlsx file now

This commit is contained in:
Debao Zhang
2013-10-19 13:28:06 +08:00
parent 7f218898b6
commit d04a02e55c
16 changed files with 135 additions and 33 deletions
+1
View File
@@ -72,6 +72,7 @@ The library, the header files, and the feature file will be installed to your sy
## References
* https://github.com/jmcnamara/XlsxWriter
* http://openpyxl.readthedocs.org
* http://officeopenxml.com/anatomyofOOXML-xlsx.php
* http://www.libxl.com
* http://closedxml.codeplex.com/
@@ -0,0 +1,10 @@
/*!
\title Xlsx Readwrite Example
\example readwrite
\brief Open an existing xlsx file, modify and save it.
\ingroup qtxlsx
This example demonstrates how to modify an existing
.xlsx file with Qt Xlsx Library.
*/
+18
View File
@@ -0,0 +1,18 @@
#include "xlsxdocument.h"
int main()
{
//Generate a simple xlsx file at first.
QXlsx::Document xlsx;
xlsx.write("A1", "Hello Qt!");
xlsx.write("A2", 500);
xlsx.saveAs("first.xlsx");
//Read, edit, save
QXlsx::Document xlsx2("first.xlsx");
xlsx2.addWorksheet("Second");
xlsx2.write("A1", "Hello Qt again!");
xlsx2.saveAs("second.xlsx");
return 0;
}
+12
View File
@@ -0,0 +1,12 @@
TARGET = mergecells
#include(../../../src/xlsx/qtxlsx.pri)
QT += xlsx
TARGET = readwrite
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp
+2 -1
View File
@@ -4,5 +4,6 @@ SUBDIRS = hello style \
image \
mergecells \
rowcolumn \
numberformat
numberformat \
readwrite
+1
View File
@@ -110,5 +110,6 @@
\li \l{Xlsx Hello Example}
\li \l{Xlsx Style Example}
\li \l{Xlsx DocProperties Example}
\li \l{Xlsx Readwrite Example}
\endlist
*/
+1
View File
@@ -28,6 +28,7 @@
#include "xlsxglobal.h"
#include <QObject>
#include <QVariant>
class QIODevice;
class QImage;
+52 -6
View File
@@ -25,6 +25,8 @@
#include "xlsxpackage_p.h"
#include "xlsxworkbook.h"
#include "xlsxworksheet.h"
#include "xlsxworkbook_p.h"
#include "xlsxutility_p.h"
#include "xlsxcontenttypes_p.h"
#include "xlsxsharedstrings_p.h"
#include "xlsxdocpropscore_p.h"
@@ -38,6 +40,8 @@
#include "xlsxdocument.h"
#include <QBuffer>
#include <QDebug>
#include <QDir>
#include <QFileInfo>
namespace QXlsx {
@@ -125,17 +129,59 @@ bool Package::parsePackage(QIODevice *packageDevice)
m_document->setDocumentProperty(name, props.property(name));
}
//load workbook now
QList<XlsxRelationship> rels_xl = rootRels.documentRelationships(QStringLiteral("/officeDocument"));
if (!rels_xl.isEmpty()) {
//Get the app property file name if it exists.
//load workbook now, Get the workbook file path from the root rels file
//In normal case, this should be "xl/workbook.xml"
QString xlworkbook_Name = rels_xl[0].target;
QList<XlsxRelationship> rels_xl = rootRels.documentRelationships(QStringLiteral("/officeDocument"));
if (rels_xl.isEmpty())
return false;
QString xlworkbook_Path = rels_xl[0].target;
QStringList xlworkbook_PathList = splitPath(xlworkbook_Path);
QString xlworkbook_Dir = xlworkbook_PathList[0];
QString xlworkbook_Name = xlworkbook_PathList[1];
QSharedPointer<Workbook> book = Workbook::loadFromXmlData(zipReader.fileData(xlworkbook_Path));
QList<QPair<QString, QString> > sheetNameIdPairList = book->d_func()->sheetNameIdPairList;
Relationships xlworkbook_Rels = Relationships::loadFromXmlData(
zipReader.fileData(xlworkbook_Dir+QStringLiteral("/_rels/")+xlworkbook_Name+QStringLiteral(".rels")));
//ToDo: Read the workbook here!
//load styles
QList<XlsxRelationship> rels_styles = xlworkbook_Rels.documentRelationships(QStringLiteral("/styles"));
if (!rels_styles.isEmpty()) {
//In normal case this should be styles.xml which in xl
//:Todo
}
//load sharedStrings
QList<XlsxRelationship> rels_sharedStrings = xlworkbook_Rels.documentRelationships(QStringLiteral("/sharedStrings"));
if (!rels_sharedStrings.isEmpty()) {
//In normal case this should be sharedStrings.xml which in xl
QString name = rels_sharedStrings[0].target;
QString path = xlworkbook_Dir + QLatin1String("/") + name;
QSharedPointer<SharedStrings> sst= SharedStrings::loadFromXmlData(zipReader.fileData(path));
m_document->workbook()->d_ptr->sharedStrings = sst;
}
//load theme
QList<XlsxRelationship> rels_theme = xlworkbook_Rels.documentRelationships(QStringLiteral("/theme"));
if (!rels_theme.isEmpty()) {
//In normal case this should be theme/theme1.xml which in xl
//:Todo
}
//load worksheets
QList<XlsxRelationship> rels_worksheets = xlworkbook_Rels.documentRelationships(QStringLiteral("/worksheet"));
if (rels_worksheets.isEmpty())
return false;
for (int i=0; i<sheetNameIdPairList.size(); ++i) {
QPair<QString, QString> pair = sheetNameIdPairList[i];
QString worksheet_rId = pair.second;
QString name = xlworkbook_Rels.getRelationshipById(worksheet_rId).target;
QString worksheet_path = xlworkbook_Dir + QLatin1String("/") + name;
Worksheet *sheet = m_document->workbook()->addWorksheet(pair.first);
sheet->loadFromXmlData(zipReader.fileData(worksheet_path));
}
return true;
}
bool Package::createPackage(QIODevice *package)
+5
View File
@@ -59,6 +59,11 @@ int SharedStrings::addSharedString(const QString &string)
return index;
}
void SharedStrings::incRefByStringIndex(int idx)
{
addSharedString(m_stringList[idx]);
}
void SharedStrings::removeSharedString(const QString &string)
{
if (!m_stringTable.contains(string))
+1
View File
@@ -54,6 +54,7 @@ public:
int addSharedString(const QString &string);
void removeSharedString(const QString &string);
void incRefByStringIndex(int idx);
int getSharedStringIndex(const QString &string) const;
QString getSharedString(int index) const;
+10
View File
@@ -28,6 +28,7 @@
#include <QPoint>
#include <QRegularExpression>
#include <QMap>
#include <QStringList>
namespace QXlsx {
@@ -41,6 +42,15 @@ int intPow(int x, int p)
else return x * tmp * tmp;
}
QStringList splitPath(const QString &path)
{
int idx = path.lastIndexOf(QLatin1Char('/'));
if (idx == -1)
return QStringList()<<QStringLiteral(".")<<path;
return QStringList()<<path.left(idx)<<path.mid(idx+1);
}
QPoint xl_cell_to_rowcol(const QString &cell_str)
{
if (cell_str.isEmpty())
+4
View File
@@ -28,13 +28,17 @@
#include "xlsxglobal.h"
class QPoint;
class QString;
class QStringList;
namespace QXlsx {
XLSX_AUTOTEST_EXPORT int intPow(int x, int p);
XLSX_AUTOTEST_EXPORT QStringList splitPath(const QString &path);
XLSX_AUTOTEST_EXPORT QPoint xl_cell_to_rowcol(const QString &cell_str);
XLSX_AUTOTEST_EXPORT QString xl_col_to_name(int col_num);
XLSX_AUTOTEST_EXPORT QString xl_rowcol_to_cell(int row, int col, bool row_abs=false, bool col_abs=false);
XLSX_AUTOTEST_EXPORT QString xl_rowcol_to_cell_fast(int row, int col);
} //QXlsx
#endif // XLSXUTILITY_H
-8
View File
@@ -337,12 +337,4 @@ QSharedPointer<Workbook> Workbook::loadFromXmlData(const QByteArray &data)
return loadFromXmlFile(&buffer);
}
void Workbook::addWorksheet(const QString &name, QSharedPointer<Worksheet> sheet)
{
Q_D(Workbook);
sheet->setSheetName(name);
d->worksheets.append(sheet);
}
QT_END_NAMESPACE_XLSX
-1
View File
@@ -78,7 +78,6 @@ private:
QByteArray saveToXmlData();
static QSharedPointer<Workbook> loadFromXmlFile(QIODevice *device);
static QSharedPointer<Workbook> loadFromXmlData(const QByteArray &data);
void addWorksheet(const QString &name, QSharedPointer<Worksheet> sheet);
SharedStrings *sharedStrings();
Styles *styles();
+15 -14
View File
@@ -1074,9 +1074,9 @@ QByteArray Worksheet::saveToXmlData()
return data;
}
QSharedPointer<Worksheet> Worksheet::loadFromXmlFile(QIODevice *device)
bool Worksheet::loadFromXmlFile(QIODevice *device)
{
Worksheet *sheet = new Worksheet(QStringLiteral("Sheet9999"));
Q_D(Worksheet);
XmlStreamReader reader(device);
while(!reader.atEnd()) {
@@ -1088,16 +1088,16 @@ QSharedPointer<Worksheet> Worksheet::loadFromXmlFile(QIODevice *device)
if (range.size() == 2) {
QPoint start = xl_cell_to_rowcol(range[0]);
QPoint end = xl_cell_to_rowcol(range[1]);
sheet->d_func()->dim_rowmin = start.x();
sheet->d_func()->dim_colmin = start.y();
sheet->d_func()->dim_rowmax = end.x();
sheet->d_func()->dim_colmax = end.y();
d->dim_rowmin = start.x();
d->dim_colmin = start.y();
d->dim_rowmax = end.x();
d->dim_colmax = end.y();
} else {
QPoint p = xl_cell_to_rowcol(range[0]);
sheet->d_func()->dim_rowmin = p.x();
sheet->d_func()->dim_colmin = p.y();
sheet->d_func()->dim_rowmax = p.x();
sheet->d_func()->dim_colmax = p.y();
d->dim_rowmin = p.x();
d->dim_colmin = p.y();
d->dim_rowmax = p.x();
d->dim_colmax = p.y();
}
} else if (reader.name() == QLatin1String("c")) {
QXmlStreamAttributes attributes = reader.attributes();
@@ -1111,8 +1111,9 @@ QSharedPointer<Worksheet> Worksheet::loadFromXmlFile(QIODevice *device)
reader.readNextStartElement();
if (reader.name() == QLatin1String("v")) {
QString value = reader.readElementText();
d->workbook->sharedStrings()->incRefByStringIndex(value.toInt());
XlsxCellData *data = new XlsxCellData(value ,XlsxCellData::String);
sheet->d_func()->cellTable[pos.x()][pos.y()] = QSharedPointer<XlsxCellData>(data);
d->cellTable[pos.x()][pos.y()] = QSharedPointer<XlsxCellData>(data);
}
}
} else {
@@ -1121,17 +1122,17 @@ QSharedPointer<Worksheet> Worksheet::loadFromXmlFile(QIODevice *device)
if (reader.name() == QLatin1String("v")) {
QString value = reader.readElementText();
XlsxCellData *data = new XlsxCellData(value ,XlsxCellData::Number);
sheet->d_func()->cellTable[pos.x()][pos.y()] = QSharedPointer<XlsxCellData>(data);
d->cellTable[pos.x()][pos.y()] = QSharedPointer<XlsxCellData>(data);
}
}
}
}
}
return QSharedPointer<Worksheet> (sheet);
return true;
}
QSharedPointer<Worksheet> Worksheet::loadFromXmlData(const QByteArray &data)
bool Worksheet::loadFromXmlData(const QByteArray &data)
{
QBuffer buffer;
buffer.setData(data);
+2 -2
View File
@@ -74,8 +74,8 @@ public:
void saveToXmlFile(QIODevice *device);
QByteArray saveToXmlData();
static QSharedPointer<Worksheet> loadFromXmlFile(QIODevice *device);
static QSharedPointer<Worksheet> loadFromXmlData(const QByteArray &data);
bool loadFromXmlFile(QIODevice *device);
bool loadFromXmlData(const QByteArray &data);
~Worksheet();
private: