From c6898ff732851fd7cf977c0f31de2f389cc5b764 Mon Sep 17 00:00:00 2001 From: Debao Zhang Date: Thu, 2 Jan 2014 11:35:57 +0800 Subject: [PATCH] Add basic worksheet copy support --- .../doc/src/worksheetoperations.qdoc | 8 +++ examples/xlsx/worksheetoperations/main.cpp | 33 ++++++++++++ .../worksheetoperations.pro | 9 ++++ examples/xlsx/xlsx.pro | 1 + src/xlsx/xlsxcell.cpp | 17 ++++++ src/xlsx/xlsxcell.h | 1 + src/xlsx/xlsxcell_p.h | 1 + src/xlsx/xlsxdocument.h | 2 +- src/xlsx/xlsxworkbook.cpp | 28 +++++++++- src/xlsx/xlsxworkbook.h | 2 +- src/xlsx/xlsxworksheet.cpp | 38 +++++++++++++ src/xlsx/xlsxworksheet.h | 1 + tests/auto/document/tst_documenttest.cpp | 53 +++++++++++++++++++ 13 files changed, 191 insertions(+), 3 deletions(-) create mode 100644 examples/xlsx/worksheetoperations/doc/src/worksheetoperations.qdoc create mode 100644 examples/xlsx/worksheetoperations/main.cpp create mode 100644 examples/xlsx/worksheetoperations/worksheetoperations.pro diff --git a/examples/xlsx/worksheetoperations/doc/src/worksheetoperations.qdoc b/examples/xlsx/worksheetoperations/doc/src/worksheetoperations.qdoc new file mode 100644 index 0000000..87dab42 --- /dev/null +++ b/examples/xlsx/worksheetoperations/doc/src/worksheetoperations.qdoc @@ -0,0 +1,8 @@ +/*! + \example worksheetoperations + \title Worksheet Operations Example + \brief Copy, delete, move worksheet + \ingroup qtxlsx-examples + + This example demonstrates how to copy, delete, move worksheet. +*/ diff --git a/examples/xlsx/worksheetoperations/main.cpp b/examples/xlsx/worksheetoperations/main.cpp new file mode 100644 index 0000000..3f1647d --- /dev/null +++ b/examples/xlsx/worksheetoperations/main.cpp @@ -0,0 +1,33 @@ +#include +#include "xlsxdocument.h" + +int main() +{ + QXlsx::Document xlsx; + + xlsx.renameWorksheet("Sheet1", "TheFirstSheet"); + + for (int i=1; i<20; ++i) { + for (int j=1; j<15; ++j) + xlsx.write(i, j, QString("R %1 C %2").arg(i).arg(j)); + } + + xlsx.addWorksheet("TheSecondSheet"); + xlsx.write(2, 2, "Hello Qt Xlsx"); + + xlsx.copyWorksheet("TheFirstSheet", "CopyOfTheFirst"); + + xlsx.addWorksheet("TheForthSheet"); + xlsx.write(3, 3, "This will be deleted..."); + + xlsx.selectWorksheet("CopyOfTheFirst"); + xlsx.write(25, 2, "On the Copy Sheet"); + + xlsx.deleteWorksheet("TheForthSheet"); + + xlsx.moveWorksheet("TheSecondSheet", 0); + + xlsx.save(); + + return 0; +} diff --git a/examples/xlsx/worksheetoperations/worksheetoperations.pro b/examples/xlsx/worksheetoperations/worksheetoperations.pro new file mode 100644 index 0000000..ce90d1c --- /dev/null +++ b/examples/xlsx/worksheetoperations/worksheetoperations.pro @@ -0,0 +1,9 @@ +TARGET = worksheetoperations + +#include(../../../src/xlsx/qtxlsx.pri) +QT+=xlsx + +CONFIG += console +CONFIG -= app_bundle + +SOURCES += main.cpp diff --git a/examples/xlsx/xlsx.pro b/examples/xlsx/xlsx.pro index e5a1e42..8a212d0 100644 --- a/examples/xlsx/xlsx.pro +++ b/examples/xlsx/xlsx.pro @@ -12,5 +12,6 @@ SUBDIRS = hello \ formulas \ richtext \ conditionalformatting \ + worksheetoperations \ demo diff --git a/src/xlsx/xlsxcell.cpp b/src/xlsx/xlsxcell.cpp index b8a6cd4..4da6322 100644 --- a/src/xlsx/xlsxcell.cpp +++ b/src/xlsx/xlsxcell.cpp @@ -39,6 +39,14 @@ CellPrivate::CellPrivate(Cell *p) : } +CellPrivate::CellPrivate(const CellPrivate * const cp) + : value(cp->value), formula(cp->formula), dataType(cp->dataType) + , format(cp->format), range(cp->range), richString(cp->richString) + , parent(cp->parent) +{ + +} + /*! \class Cell \inmodule QtXlsx @@ -72,6 +80,15 @@ Cell::Cell(const QVariant &data, DataType type, const Format &format, Worksheet d_ptr->parent = parent; } +/*! + * \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. */ diff --git a/src/xlsx/xlsxcell.h b/src/xlsx/xlsxcell.h index 96cca9d..dd04c31 100644 --- a/src/xlsx/xlsxcell.h +++ b/src/xlsx/xlsxcell.h @@ -67,6 +67,7 @@ private: friend class WorksheetPrivate; Cell(const QVariant &data=QVariant(), DataType type=Blank, const Format &format=Format(), Worksheet *parent=0); + Cell(const Cell * const cell); CellPrivate * const d_ptr; }; diff --git a/src/xlsx/xlsxcell_p.h b/src/xlsx/xlsxcell_p.h index 7ed06cf..22ca53a 100644 --- a/src/xlsx/xlsxcell_p.h +++ b/src/xlsx/xlsxcell_p.h @@ -50,6 +50,7 @@ class CellPrivate Q_DECLARE_PUBLIC(Cell) public: CellPrivate(Cell *p); + CellPrivate(const CellPrivate * const cp); QVariant value; QString formula; diff --git a/src/xlsx/xlsxdocument.h b/src/xlsx/xlsxdocument.h index 0ff8165..22ca5b8 100644 --- a/src/xlsx/xlsxdocument.h +++ b/src/xlsx/xlsxdocument.h @@ -88,7 +88,7 @@ public: bool insertWorkSheet(int index, const QString &name = QString()); bool selectWorksheet(const QString &name); bool renameWorksheet(const QString &oldName, const QString &newName); - bool copyWorksheet(const QString &srcName, const QString &distName); + bool copyWorksheet(const QString &srcName, const QString &distName = QString()); bool moveWorksheet(const QString &srcName, int distIndex); bool deleteWorksheet(const QString &name); diff --git a/src/xlsx/xlsxworkbook.cpp b/src/xlsx/xlsxworkbook.cpp index 6456273..ee8833c 100755 --- a/src/xlsx/xlsxworkbook.cpp +++ b/src/xlsx/xlsxworkbook.cpp @@ -282,7 +282,33 @@ bool Workbook::copyWorksheet(int index, const QString &newName) Q_D(Workbook); if (index < 0 || index >= d->worksheets.size()) return false; - //! Todo + + QString worksheetName = newName; + if (!newName.isEmpty()) { + //If user given an already in-used name, we should not continue any more! + for (int i=0; iworksheets.size(); ++i) { + if (d->worksheets[i]->sheetName() == newName) { + return 0; + } + } + } else { + int copy_index = 1; + bool exists; + do { + ++copy_index; + exists = false; + worksheetName = QStringLiteral("%1(%2)").arg(d->worksheets[index]->sheetName()).arg(copy_index); + for (int i=0; iworksheets.size(); ++i) { + if (d->worksheets[i]->sheetName() == worksheetName) + exists = true; + } + } while (exists); + } + + ++d->last_sheet_id; + QSharedPointer sheet = d->worksheets[index]->copy(worksheetName, d->last_sheet_id); + d->worksheets.append(sheet); + return false; } diff --git a/src/xlsx/xlsxworkbook.h b/src/xlsx/xlsxworkbook.h index 24e5970..e1aad66 100755 --- a/src/xlsx/xlsxworkbook.h +++ b/src/xlsx/xlsxworkbook.h @@ -58,7 +58,7 @@ public: Worksheet *insertWorkSheet(int index, const QString &name = QString()); bool renameWorksheet(int index, const QString &name); bool deleteWorksheet(int index); - bool copyWorksheet(int index, const QString &newName); + bool copyWorksheet(int index, const QString &newName=QString()); bool moveWorksheet(int srcIndex, int distIndex); Worksheet *activeWorksheet() const; diff --git a/src/xlsx/xlsxworksheet.cpp b/src/xlsx/xlsxworksheet.cpp index de3a30c..1d4e662 100755 --- a/src/xlsx/xlsxworksheet.cpp +++ b/src/xlsx/xlsxworksheet.cpp @@ -182,6 +182,44 @@ Worksheet::Worksheet(const QString &name, int id, Workbook *workbook) : d_ptr->workbook = workbook; } +QSharedPointer Worksheet::copy(const QString &distName, int distId) const +{ + Q_D(const Worksheet); + QSharedPointer sheet(new Worksheet(distName, distId, d->workbook)); + + WorksheetPrivate *sheet_d = sheet->d_ptr; + + sheet_d->dimension = d->dimension; + + QMapIterator > > it(d->cellTable); + while (it.hasNext()) { + it.next(); + int row = it.key(); + QMapIterator > it2(it.value()); + while (it2.hasNext()) { + it2.next(); + int col = it2.key(); + + QSharedPointer cell(new Cell(it2.value().data())); + cell->d_ptr->parent = sheet.data(); + + if (cell->dataType() == Cell::String) + d->workbook->sharedStrings()->addSharedString(cell->d_ptr->richString); + + sheet_d->cellTable[row][col] = cell; + } + } + + sheet_d->merges = d->merges; +// sheet_d->rowsInfo = d->rowsInfo; +// sheet_d->colsInfo = d->colsInfo; +// sheet_d->colsInfoHelper = d->colsInfoHelper; +// sheet_d->dataValidationsList = d->dataValidationsList; +// sheet_d->conditionalFormattingList = d->conditionalFormattingList; + + return sheet; +} + Worksheet::~Worksheet() { delete d_ptr; diff --git a/src/xlsx/xlsxworksheet.h b/src/xlsx/xlsxworksheet.h index 50c054f..91c6546 100755 --- a/src/xlsx/xlsxworksheet.h +++ b/src/xlsx/xlsxworksheet.h @@ -135,6 +135,7 @@ private: friend class Workbook; friend class ::WorksheetTest; Worksheet(const QString &sheetName, int sheetId, Workbook *book); + QSharedPointer copy(const QString &distName, int distId) const; void saveToXmlFile(QIODevice *device); QByteArray saveToXmlData(); diff --git a/tests/auto/document/tst_documenttest.cpp b/tests/auto/document/tst_documenttest.cpp index abd4bcf..25ce880 100644 --- a/tests/auto/document/tst_documenttest.cpp +++ b/tests/auto/document/tst_documenttest.cpp @@ -23,6 +23,10 @@ private Q_SLOTS: void testReadWriteDateTime(); void testReadWriteDate(); void testReadWriteTime(); + + void testMoveWorksheet(); + void testDeleteWorksheet(); + void testCopyWorksheet(); }; DocumentTest::DocumentTest() @@ -294,6 +298,55 @@ void DocumentTest::testReadWriteTime() QCOMPARE(xlsx2.read("A2").toTime(), QTime(1, 22)); } +void DocumentTest::testMoveWorksheet() +{ + Document xlsx1; + xlsx1.addWorksheet(); + + QCOMPARE(xlsx1.worksheetNames(), QStringList()<<"Sheet1"<<"Sheet2"); + xlsx1.moveWorksheet("Sheet2", 0); + QCOMPARE(xlsx1.worksheetNames(), QStringList()<<"Sheet2"<<"Sheet1"); + xlsx1.moveWorksheet("Sheet2", 1); + QCOMPARE(xlsx1.worksheetNames(), QStringList()<<"Sheet1"<<"Sheet2"); +} + +void DocumentTest::testCopyWorksheet() +{ + Document xlsx1; + xlsx1.addWorksheet(); + xlsx1.write("A1", "String"); + xlsx1.write("A2", 999); + xlsx1.write("A3", true); + xlsx1.addWorksheet(); + QCOMPARE(xlsx1.worksheetNames(), QStringList()<<"Sheet1"<<"Sheet2"<<"Sheet3"); + + xlsx1.copyWorksheet("Sheet2"); + QCOMPARE(xlsx1.worksheetNames(), QStringList()<<"Sheet1"<<"Sheet2"<<"Sheet3"<<"Sheet2(2)"); + + xlsx1.deleteWorksheet("Sheet2"); + QCOMPARE(xlsx1.worksheetNames(), QStringList()<<"Sheet1"<<"Sheet3"<<"Sheet2(2)"); + + xlsx1.selectWorksheet("Sheet2(2)"); + QCOMPARE(xlsx1.read("A1").toString(), QString("String")); + QCOMPARE(xlsx1.read("A2").toInt(), 999); + QCOMPARE(xlsx1.read("A3").toBool(), true); +} + +void DocumentTest::testDeleteWorksheet() +{ + Document xlsx1; + xlsx1.addWorksheet(); + xlsx1.addWorksheet(); + + QCOMPARE(xlsx1.worksheetNames(), QStringList()<<"Sheet1"<<"Sheet2"<<"Sheet3"); + xlsx1.deleteWorksheet("Sheet2"); + QCOMPARE(xlsx1.worksheetNames(), QStringList()<<"Sheet1"<<"Sheet3"); + xlsx1.deleteWorksheet("Sheet1"); + QCOMPARE(xlsx1.worksheetNames(), QStringList()<<"Sheet3"); +// xlsx1.deleteWorksheet("Sheet3"); +// QCOMPARE(xlsx1.worksheetNames(), QStringList()<<"Sheet4"); +} + QTEST_APPLESS_MAIN(DocumentTest) #include "tst_documenttest.moc"