| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046 |
- /****************************************************************************
- ** Copyright (c) 2013-2014 Debao Zhang <hello@debao.me>
- ** All right reserved.
- **
- ** Permission is hereby granted, free of charge, to any person obtaining
- ** a copy of this software and associated documentation files (the
- ** "Software"), to deal in the Software without restriction, including
- ** without limitation the rights to use, copy, modify, merge, publish,
- ** distribute, sublicense, and/or sell copies of the Software, and to
- ** permit persons to whom the Software is furnished to do so, subject to
- ** the following conditions:
- **
- ** The above copyright notice and this permission notice shall be
- ** included in all copies or substantial portions of the Software.
- **
- ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- ** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- ** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- ** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- ** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- **
- ****************************************************************************/
- #include "xlsxdocument.h"
- #include "xlsxdocument_p.h"
- #include "xlsxworkbook.h"
- #include "xlsxworksheet.h"
- #include "xlsxcontenttypes_p.h"
- #include "xlsxrelationships_p.h"
- #include "xlsxstyles_p.h"
- #include "xlsxtheme_p.h"
- #include "xlsxdocpropsapp_p.h"
- #include "xlsxdocpropscore_p.h"
- #include "xlsxsharedstrings_p.h"
- #include "xlsxutility_p.h"
- #include "xlsxworkbook_p.h"
- #include "xlsxdrawing_p.h"
- #include "xlsxmediafile_p.h"
- #include "xlsxchart.h"
- #include "xlsxzipreader_p.h"
- #include "xlsxzipwriter_p.h"
- #include <QFile>
- #include <QPointF>
- #include <QBuffer>
- #include <QDir>
- QT_BEGIN_NAMESPACE_XLSX
- /*
- From Wikipedia: The Open Packaging Conventions (OPC) is a
- container-file technology initially created by Microsoft to store
- a combination of XML and non-XML files that together form a single
- entity such as an Open XML Paper Specification (OpenXPS)
- document. http://en.wikipedia.org/wiki/Open_Packaging_Conventions.
- At its simplest an Excel XLSX file contains the following elements:
- ____ [Content_Types].xml
- |
- |____ docProps
- | |____ app.xml
- | |____ core.xml
- |
- |____ xl
- | |____ workbook.xml
- | |____ worksheets
- | | |____ sheet1.xml
- | |
- | |____ styles.xml
- | |
- | |____ theme
- | | |____ theme1.xml
- | |
- | |_____rels
- | |____ workbook.xml.rels
- |
- |_____rels
- |____ .rels
- The Packager class coordinates the classes that represent the
- elements of the package and writes them into the XLSX file.
- */
- DocumentPrivate::DocumentPrivate(Document *p) :
- q_ptr(p), defaultPackageName(QStringLiteral("Book1.xlsx"))
- {
- }
- void DocumentPrivate::init()
- {
- if (contentTypes.isNull())
- contentTypes = QSharedPointer<ContentTypes>(new ContentTypes(ContentTypes::F_NewFromScratch));
- if (workbook.isNull())
- workbook = QSharedPointer<Workbook>(new Workbook(Workbook::F_NewFromScratch));
- }
- bool DocumentPrivate::loadPackage(QIODevice *device)
- {
- Q_Q(Document);
- ZipReader zipReader(device);
- QStringList filePaths = zipReader.filePaths();
- //Load the Content_Types file
- if (!filePaths.contains(QLatin1String("[Content_Types].xml")))
- return false;
- contentTypes = QSharedPointer<ContentTypes>(new ContentTypes(ContentTypes::F_LoadFromExists));
- contentTypes->loadFromXmlData(zipReader.fileData(QStringLiteral("[Content_Types].xml")));
- //Load root rels file
- if (!filePaths.contains(QLatin1String("_rels/.rels")))
- return false;
- Relationships rootRels;
- rootRels.loadFromXmlData(zipReader.fileData(QStringLiteral("_rels/.rels")));
- //load core property
- QList<XlsxRelationship> rels_core = rootRels.packageRelationships(QStringLiteral("/metadata/core-properties"));
- if (!rels_core.isEmpty()) {
- //Get the core property file name if it exists.
- //In normal case, this should be "docProps/core.xml"
- QString docPropsCore_Name = rels_core[0].target;
- DocPropsCore props(DocPropsCore::F_LoadFromExists);
- props.loadFromXmlData(zipReader.fileData(docPropsCore_Name));
- foreach (QString name, props.propertyNames())
- q->setDocumentProperty(name, props.property(name));
- }
- //load app property
- QList<XlsxRelationship> rels_app = rootRels.documentRelationships(QStringLiteral("/extended-properties"));
- if (!rels_app.isEmpty()) {
- //Get the app property file name if it exists.
- //In normal case, this should be "docProps/app.xml"
- QString docPropsApp_Name = rels_app[0].target;
- DocPropsApp props(DocPropsApp::F_LoadFromExists);
- props.loadFromXmlData(zipReader.fileData(docPropsApp_Name));
- foreach (QString name, props.propertyNames())
- q->setDocumentProperty(name, props.property(name));
- }
- //load workbook now, Get the workbook file path from the root rels file
- //In normal case, this should be "xl/workbook.xml"
- workbook = QSharedPointer<Workbook>(new Workbook(Workbook::F_LoadFromExists));
- QList<XlsxRelationship> rels_xl = rootRels.documentRelationships(QStringLiteral("/officeDocument"));
- if (rels_xl.isEmpty())
- return false;
- QString xlworkbook_Path = rels_xl[0].target;
- QString xlworkbook_Dir = splitPath(xlworkbook_Path)[0];
- workbook->relationships()->loadFromXmlData(zipReader.fileData(getRelFilePath(xlworkbook_Path)));
- workbook->setFilePath(xlworkbook_Path);
- workbook->loadFromXmlData(zipReader.fileData(xlworkbook_Path));
- //load styles
- QList<XlsxRelationship> rels_styles = workbook->relationships()->documentRelationships(QStringLiteral("/styles"));
- if (!rels_styles.isEmpty()) {
- //In normal case this should be styles.xml which in xl
- QString name = rels_styles[0].target;
- QString path = xlworkbook_Dir + QLatin1String("/") + name;
- QSharedPointer<Styles> styles (new Styles(Styles::F_LoadFromExists));
- styles->loadFromXmlData(zipReader.fileData(path));
- workbook->d_func()->styles = styles;
- }
- //load sharedStrings
- QList<XlsxRelationship> rels_sharedStrings = workbook->relationships()->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;
- workbook->d_func()->sharedStrings->loadFromXmlData(zipReader.fileData(path));
- }
- //load theme
- QList<XlsxRelationship> rels_theme = workbook->relationships()->documentRelationships(QStringLiteral("/theme"));
- if (!rels_theme.isEmpty()) {
- //In normal case this should be theme/theme1.xml which in xl
- QString name = rels_theme[0].target;
- QString path = xlworkbook_Dir + QLatin1String("/") + name;
- workbook->theme()->loadFromXmlData(zipReader.fileData(path));
- }
- //load sheets
- for (int i=0; i<workbook->sheetCount(); ++i) {
- AbstractSheet *sheet = workbook->sheet(i);
- QString rel_path = getRelFilePath(sheet->filePath());
- //If the .rel file exists, load it.
- if (zipReader.filePaths().contains(rel_path))
- sheet->relationships()->loadFromXmlData(zipReader.fileData(rel_path));
- sheet->loadFromXmlData(zipReader.fileData(sheet->filePath()));
- }
- //load external links
- for (int i=0; i<workbook->d_func()->externalLinks.count(); ++i) {
- SimpleOOXmlFile *link = workbook->d_func()->externalLinks[i].data();
- QString rel_path = getRelFilePath(link->filePath());
- //If the .rel file exists, load it.
- if (zipReader.filePaths().contains(rel_path))
- link->relationships()->loadFromXmlData(zipReader.fileData(rel_path));
- link->loadFromXmlData(zipReader.fileData(link->filePath()));
- }
- //load drawings
- for (int i=0; i<workbook->drawings().size(); ++i) {
- Drawing *drawing = workbook->drawings()[i];
- QString rel_path = getRelFilePath(drawing->filePath());
- if (zipReader.filePaths().contains(rel_path))
- drawing->relationships()->loadFromXmlData(zipReader.fileData(rel_path));
- drawing->loadFromXmlData(zipReader.fileData(drawing->filePath()));
- }
- //load charts
- QList<QSharedPointer<Chart> > chartFileToLoad = workbook->chartFiles();
- for (int i=0; i<chartFileToLoad.size(); ++i) {
- QSharedPointer<Chart> cf = chartFileToLoad[i];
- cf->loadFromXmlData(zipReader.fileData(cf->filePath()));
- }
- //load media files
- QList<QSharedPointer<MediaFile> > mediaFileToLoad = workbook->mediaFiles();
- for (int i=0; i<mediaFileToLoad.size(); ++i) {
- QSharedPointer<MediaFile> mf = mediaFileToLoad[i];
- const QString path = mf->fileName();
- const QString suffix = path.mid(path.lastIndexOf(QLatin1Char('.'))+1);
- mf->set(zipReader.fileData(path), suffix);
- }
- return true;
- }
- bool DocumentPrivate::savePackage(QIODevice *device) const
- {
- Q_Q(const Document);
- ZipWriter zipWriter(device);
- if (zipWriter.error())
- return false;
- contentTypes->clearOverrides();
- DocPropsApp docPropsApp(DocPropsApp::F_NewFromScratch);
- DocPropsCore docPropsCore(DocPropsCore::F_NewFromScratch);
- // save worksheet xml files
- QList<QSharedPointer<AbstractSheet> > worksheets = workbook->getSheetsByTypes(AbstractSheet::ST_WorkSheet);
- if (!worksheets.isEmpty())
- docPropsApp.addHeadingPair(QStringLiteral("Worksheets"), worksheets.size());
- for (int i=0; i<worksheets.size(); ++i) {
- QSharedPointer<AbstractSheet> sheet = worksheets[i];
- contentTypes->addWorksheetName(QStringLiteral("sheet%1").arg(i+1));
- docPropsApp.addPartTitle(sheet->sheetName());
- zipWriter.addFile(QStringLiteral("xl/worksheets/sheet%1.xml").arg(i+1), sheet->saveToXmlData());
- Relationships *rel = sheet->relationships();
- if (!rel->isEmpty())
- zipWriter.addFile(QStringLiteral("xl/worksheets/_rels/sheet%1.xml.rels").arg(i+1), rel->saveToXmlData());
- }
- //save chartsheet xml files
- QList<QSharedPointer<AbstractSheet> > chartsheets = workbook->getSheetsByTypes(AbstractSheet::ST_ChartSheet);
- if (!chartsheets.isEmpty())
- docPropsApp.addHeadingPair(QStringLiteral("Chartsheets"), chartsheets.size());
- for (int i=0; i<chartsheets.size(); ++i) {
- QSharedPointer<AbstractSheet> sheet = chartsheets[i];
- contentTypes->addWorksheetName(QStringLiteral("sheet%1").arg(i+1));
- docPropsApp.addPartTitle(sheet->sheetName());
- zipWriter.addFile(QStringLiteral("xl/chartsheets/sheet%1.xml").arg(i+1), sheet->saveToXmlData());
- Relationships *rel = sheet->relationships();
- if (!rel->isEmpty())
- zipWriter.addFile(QStringLiteral("xl/chartsheets/_rels/sheet%1.xml.rels").arg(i+1), rel->saveToXmlData());
- }
- // save external links xml files
- for (int i=0; i<workbook->d_func()->externalLinks.count(); ++i) {
- SimpleOOXmlFile *link = workbook->d_func()->externalLinks[i].data();
- contentTypes->addExternalLinkName(QStringLiteral("externalLink%1").arg(i+1));
- zipWriter.addFile(QStringLiteral("xl/externalLinks/externalLink%1.xml").arg(i+1), link->saveToXmlData());
- Relationships *rel = link->relationships();
- if (!rel->isEmpty())
- zipWriter.addFile(QStringLiteral("xl/externalLinks/_rels/externalLink%1.xml.rels").arg(i+1), rel->saveToXmlData());
- }
- // save workbook xml file
- contentTypes->addWorkbook();
- zipWriter.addFile(QStringLiteral("xl/workbook.xml"), workbook->saveToXmlData());
- zipWriter.addFile(QStringLiteral("xl/_rels/workbook.xml.rels"), workbook->relationships()->saveToXmlData());
- // save drawing xml files
- for (int i=0; i<workbook->drawings().size(); ++i) {
- contentTypes->addDrawingName(QStringLiteral("drawing%1").arg(i+1));
- Drawing *drawing = workbook->drawings()[i];
- zipWriter.addFile(QStringLiteral("xl/drawings/drawing%1.xml").arg(i+1), drawing->saveToXmlData());
- if (!drawing->relationships()->isEmpty())
- zipWriter.addFile(QStringLiteral("xl/drawings/_rels/drawing%1.xml.rels").arg(i+1), drawing->relationships()->saveToXmlData());
- }
- // save docProps app/core xml file
- foreach (QString name, q->documentPropertyNames()) {
- docPropsApp.setProperty(name, q->documentProperty(name));
- docPropsCore.setProperty(name, q->documentProperty(name));
- }
- contentTypes->addDocPropApp();
- contentTypes->addDocPropCore();
- zipWriter.addFile(QStringLiteral("docProps/app.xml"), docPropsApp.saveToXmlData());
- zipWriter.addFile(QStringLiteral("docProps/core.xml"), docPropsCore.saveToXmlData());
- // save sharedStrings xml file
- if (!workbook->sharedStrings()->isEmpty()) {
- contentTypes->addSharedString();
- zipWriter.addFile(QStringLiteral("xl/sharedStrings.xml"), workbook->sharedStrings()->saveToXmlData());
- }
- // save styles xml file
- contentTypes->addStyles();
- zipWriter.addFile(QStringLiteral("xl/styles.xml"), workbook->styles()->saveToXmlData());
- // save theme xml file
- contentTypes->addTheme();
- zipWriter.addFile(QStringLiteral("xl/theme/theme1.xml"), workbook->theme()->saveToXmlData());
- // save chart xml files
- for (int i=0; i<workbook->chartFiles().size(); ++i) {
- contentTypes->addChartName(QStringLiteral("chart%1").arg(i+1));
- QSharedPointer<Chart> cf = workbook->chartFiles()[i];
- zipWriter.addFile(QStringLiteral("xl/charts/chart%1.xml").arg(i+1), cf->saveToXmlData());
- }
- // save image files
- for (int i=0; i<workbook->mediaFiles().size(); ++i) {
- QSharedPointer<MediaFile> mf = workbook->mediaFiles()[i];
- if (!mf->mimeType().isEmpty())
- contentTypes->addDefault(mf->suffix(), mf->mimeType());
- zipWriter.addFile(QStringLiteral("xl/media/image%1.%2").arg(i+1).arg(mf->suffix()), mf->contents());
- }
- // save root .rels xml file
- Relationships rootrels;
- rootrels.addDocumentRelationship(QStringLiteral("/officeDocument"), QStringLiteral("xl/workbook.xml"));
- rootrels.addPackageRelationship(QStringLiteral("/metadata/core-properties"), QStringLiteral("docProps/core.xml"));
- rootrels.addDocumentRelationship(QStringLiteral("/extended-properties"), QStringLiteral("docProps/app.xml"));
- zipWriter.addFile(QStringLiteral("_rels/.rels"), rootrels.saveToXmlData());
- // save content types xml file
- zipWriter.addFile(QStringLiteral("[Content_Types].xml"), contentTypes->saveToXmlData());
- zipWriter.close();
- return true;
- }
- /*!
- \class Document
- \inmodule QtXlsx
- \brief The Document class provides a API that is used to handle the contents of .xlsx files.
- */
- /*!
- * Creates a new empty xlsx document.
- * The \a parent argument is passed to QObject's constructor.
- */
- Document::Document(QObject *parent) :
- QObject(parent), d_ptr(new DocumentPrivate(this))
- {
- d_ptr->init();
- }
- /*!
- * \overload
- * Try to open an existing xlsx document named \a name.
- * The \a parent argument is passed to QObject's constructor.
- */
- Document::Document(const QString &name, QObject *parent) :
- QObject(parent), d_ptr(new DocumentPrivate(this))
- {
- d_ptr->packageName = name;
- if (QFile::exists(name)) {
- QFile xlsx(name);
- if (xlsx.open(QFile::ReadOnly))
- d_ptr->loadPackage(&xlsx);
- }
- d_ptr->init();
- }
- /*!
- * \overload
- * Try to open an existing xlsx document from \a device.
- * The \a parent argument is passed to QObject's constructor.
- */
- Document::Document(QIODevice *device, QObject *parent) :
- QObject(parent), d_ptr(new DocumentPrivate(this))
- {
- if (device && device->isReadable())
- d_ptr->loadPackage(device);
- d_ptr->init();
- }
- /*!
- \overload
- Write \a value to cell \a row_column with the given \a format.
- */
- bool Document::write(const CellReference &row_column, const QVariant &value, const Format &format)
- {
- if (Worksheet *sheet = currentWorksheet())
- return sheet->write(row_column, value, format);
- return false;
- }
- /*!
- * Write \a value to cell (\a row, \a col) with the \a format.
- * Returns true on success.
- */
- bool Document::write(int row, int col, const QVariant &value, const Format &format)
- {
- if (Worksheet *sheet = currentWorksheet())
- return sheet->write(row, col, value, format);
- return false;
- }
- /*!
- \overload
- Returns the contents of the cell \a cell.
- \sa cellAt()
- */
- QVariant Document::read(const CellReference &cell) const
- {
- if (Worksheet *sheet = currentWorksheet())
- return sheet->read(cell);
- return QVariant();
- }
- /*!
- Returns the contents of the cell (\a row, \a col).
- \sa cellAt()
- */
- QVariant Document::read(int row, int col) const
- {
- if (Worksheet *sheet = currentWorksheet())
- return sheet->read(row, col);
- return QVariant();
- }
- /*!
- * Insert an \a image to current active worksheet at the position \a row, \a column
- * Returns ture if success.
- */
- bool Document::insertImage(int row, int column, const QImage &image)
- {
- if (Worksheet *sheet = currentWorksheet())
- return sheet->insertImage(row, column, image);
- return false;
- }
- /*!
- * Creates an chart with the given \a size and insert it to the current
- * active worksheet at the position \a row, \a col.
- * The chart will be returned.
- */
- Chart *Document::insertChart(int row, int col, const QSize &size)
- {
- if (Worksheet *sheet = currentWorksheet())
- return sheet->insertChart(row, col, size);
- return 0;
- }
- /*!
- Merge a \a range of cells. The first cell should contain the data and the others should
- be blank. All cells will be applied the same style if a valid \a format is given.
- Returns true on success.
- \note All cells except the top-left one will be cleared.
- */
- bool Document::mergeCells(const CellRange &range, const Format &format)
- {
- if (Worksheet *sheet = currentWorksheet())
- return sheet->mergeCells(range, format);
- return false;
- }
- /*!
- Unmerge the cells in the \a range.
- Returns true on success.
- */
- bool Document::unmergeCells(const CellRange &range)
- {
- if (Worksheet *sheet = currentWorksheet())
- return sheet->unmergeCells(range);
- return false;
- }
- /*!
- Sets width in characters of columns with the given \a range and \a width.
- Returns true on success.
- */
- bool Document::setColumnWidth(const CellRange &range, double width)
- {
- if (Worksheet *sheet = currentWorksheet())
- return sheet->setColumnWidth(range, width);
- return false;
- }
- /*!
- Sets format property of columns with the gien \a range and \a format.
- Returns true on success.
- */
- bool Document::setColumnFormat(const CellRange &range, const Format &format)
- {
- if (Worksheet *sheet = currentWorksheet())
- return sheet->setColumnFormat(range, format);
- return false;
- }
- /*!
- Sets hidden property of columns \a range to \a hidden. Columns are 1-indexed.
- Hidden columns are not visible.
- Returns true on success.
- */
- bool Document::setColumnHidden(const CellRange &range, bool hidden)
- {
- if (Worksheet *sheet = currentWorksheet())
- return sheet->setColumnWidth(range, hidden);
- return false;
- }
- /*!
- Sets width in characters \a column to \a width. Columns are 1-indexed.
- Returns true on success.
- */
- bool Document::setColumnWidth(int column, double width)
- {
- return setColumnWidth(column,column,width);
- }
- /*!
- Sets format property \a column to \a format. Columns are 1-indexed.
- Returns true on success.
- */
- bool Document::setColumnFormat(int column, const Format &format)
- {
- return setColumnFormat(column,column,format);
- }
- /*!
- Sets hidden property of a \a column. Columns are 1-indexed.
- Returns true on success.
- */
- bool Document::setColumnHidden(int column, bool hidden)
- {
- return setColumnHidden(column,column,hidden);
- }
- /*!
- Sets width in characters for columns [\a colFirst, \a colLast]. Columns are 1-indexed.
- Returns true on success.
- */
- bool Document::setColumnWidth(int colFirst, int colLast, double width)
- {
- if (Worksheet *sheet = currentWorksheet())
- return sheet->setColumnWidth(colFirst, colLast, width);
- return false;
- }
- /*!
- Sets format property of columns [\a colFirst, \a colLast] to \a format.
- Columns are 1-indexed.
- Returns true on success.
- */
- bool Document::setColumnFormat(int colFirst, int colLast, const Format &format)
- {
- if (Worksheet *sheet = currentWorksheet())
- return sheet->setColumnFormat(colFirst, colLast, format);
- return false;
- }
- /*!
- Sets hidden property of columns [\a colFirst, \a colLast] to \a hidden.
- Columns are 1-indexed.
- Returns true on success.
- */
- bool Document::setColumnHidden(int colFirst, int colLast, bool hidden)
- {
- if (Worksheet *sheet = currentWorksheet())
- return sheet->setColumnHidden(colFirst, colLast, hidden);
- return false;
- }
- /*!
- Returns width of the \a column in characters of the normal font.
- Columns are 1-indexed.
- Returns true on success.
- */
- double Document::columnWidth(int column)
- {
- if (Worksheet *sheet = currentWorksheet())
- return sheet->columnWidth(column);
- return 0.0;
- }
- /*!
- Returns formatting of the \a column. Columns are 1-indexed.
- */
- Format Document::columnFormat(int column)
- {
- if (Worksheet *sheet = currentWorksheet())
- return sheet->columnFormat(column);
- return Format();
- }
- /*!
- Returns true if \a column is hidden. Columns are 1-indexed.
- */
- bool Document::isColumnHidden(int column)
- {
- if (Worksheet *sheet = currentWorksheet())
- return sheet->isColumnHidden(column);
- return false;
- }
- /*!
- Sets the \a format of the \a row.
- Rows are 1-indexed.
- Returns true if success.
- */
- bool Document::setRowFormat(int row, const Format &format)
- {
- return setRowFormat(row,row, format);
- }
- /*!
- Sets the \a format of the rows including and between \a rowFirst and \a rowLast.
- Rows are 1-indexed.
- Returns true if success.
- */
- bool Document::setRowFormat(int rowFirst, int rowLast, const Format &format)
- {
- if (Worksheet *sheet = currentWorksheet())
- return sheet->setRowFormat(rowFirst, rowLast, format);
- return false;
- }
- /*!
- Sets the \a hidden property of the row \a row.
- Rows are 1-indexed. If hidden is true rows will not be visible.
- Returns true if success.
- */
- bool Document::setRowHidden(int row, bool hidden)
- {
- return setRowHidden(row,row,hidden);
- }
- /*!
- Sets the \a hidden property of the rows including and between \a rowFirst and \a rowLast.
- Rows are 1-indexed. If hidden is true rows will not be visible.
- Returns true if success.
- */
- bool Document::setRowHidden(int rowFirst, int rowLast, bool hidden)
- {
- if (Worksheet *sheet = currentWorksheet())
- return sheet->setRowHidden(rowFirst, rowLast, hidden);
- return false;
- }
- /*!
- Sets the \a height of the row \a row.
- Row height measured in point size.
- Rows are 1-indexed.
- Returns true if success.
- */
- bool Document::setRowHeight(int row, double height)
- {
- return setRowHeight(row,row,height);
- }
- /*!
- Sets the \a height of the rows including and between \a rowFirst and \a rowLast.
- Row height measured in point size.
- Rows are 1-indexed.
- Returns true if success.
- */
- bool Document::setRowHeight(int rowFirst, int rowLast, double height)
- {
- if (Worksheet *sheet = currentWorksheet())
- return sheet->setRowHeight(rowFirst, rowLast, height);
- return false;
- }
- /*!
- Returns height of \a row in points.
- */
- double Document::rowHeight(int row)
- {
- if (Worksheet *sheet = currentWorksheet())
- return sheet->rowHeight(row);
- return 0.0;
- }
- /*!
- Returns format of \a row.
- */
- Format Document::rowFormat(int row)
- {
- if (Worksheet *sheet = currentWorksheet())
- return sheet->rowFormat(row);
- return Format();
- }
- /*!
- Returns true if \a row is hidden.
- */
- bool Document::isRowHidden(int row)
- {
- if (Worksheet *sheet = currentWorksheet())
- return sheet->isRowHidden(row);
- return false;
- }
- /*!
- Groups rows from \a rowFirst to \a rowLast with the given \a collapsed.
- Returns false if error occurs.
- */
- bool Document::groupRows(int rowFirst, int rowLast, bool collapsed)
- {
- if (Worksheet *sheet = currentWorksheet())
- return sheet->groupRows(rowFirst, rowLast, collapsed);
- return false;
- }
- /*!
- Groups columns from \a colFirst to \a colLast with the given \a collapsed.
- Returns false if error occurs.
- */
- bool Document::groupColumns(int colFirst, int colLast, bool collapsed)
- {
- if (Worksheet *sheet = currentWorksheet())
- return sheet->groupColumns(colFirst, colLast, collapsed);
- return false;
- }
- /*!
- * Add a data \a validation rule for current worksheet. Returns true if successful.
- */
- bool Document::addDataValidation(const DataValidation &validation)
- {
- if (Worksheet *sheet = currentWorksheet())
- return sheet->addDataValidation(validation);
- return false;
- }
- /*!
- * Add a conditional formatting \a cf for current worksheet. Returns true if successful.
- */
- bool Document::addConditionalFormatting(const ConditionalFormatting &cf)
- {
- if (Worksheet *sheet = currentWorksheet())
- return sheet->addConditionalFormatting(cf);
- return false;
- }
- /*!
- * \overload
- * Returns the cell at the position \a pos. If there is no cell at
- * the specified position, the function returns 0.
- *
- * \sa read()
- */
- Cell *Document::cellAt(const CellReference &pos) const
- {
- if (Worksheet *sheet = currentWorksheet())
- return sheet->cellAt(pos);
- return 0;
- }
- /*!
- * Returns the cell at the given \a row and \a col. If there
- * is no cell at the specified position, the function returns 0.
- *
- * \sa read()
- */
- Cell *Document::cellAt(int row, int col) const
- {
- if (Worksheet *sheet = currentWorksheet())
- return sheet->cellAt(row, col);
- return 0;
- }
- /*!
- * \brief Create a defined name in the workbook with the given \a name, \a formula, \a comment
- * and \a scope.
- *
- * \param name The defined name.
- * \param formula The cell or range that the defined name refers to.
- * \param scope The name of one worksheet, or empty which means golbal scope.
- * \return Return false if the name invalid.
- */
- bool Document::defineName(const QString &name, const QString &formula, const QString &comment, const QString &scope)
- {
- Q_D(Document);
- return d->workbook->defineName(name, formula, comment, scope);
- }
- /*!
- Return the range that contains cell data.
- */
- CellRange Document::dimension() const
- {
- if (Worksheet *sheet = currentWorksheet())
- return sheet->dimension();
- return CellRange();
- }
- /*!
- * Returns the value of the document's \a key property.
- */
- QString Document::documentProperty(const QString &key) const
- {
- Q_D(const Document);
- if (d->documentProperties.contains(key))
- return d->documentProperties[key];
- else
- return QString();
- }
- /*!
- Set the document properties such as Title, Author etc.
- The method can be used to set the document properties of the Excel
- file created by Qt Xlsx. These properties are visible when you use the
- Office Button -> Prepare -> Properties option in Excel and are also
- available to external applications that read or index windows files.
- The \a property \a key that can be set are:
- \list
- \li title
- \li subject
- \li creator
- \li manager
- \li company
- \li category
- \li keywords
- \li description
- \li status
- \endlist
- */
- void Document::setDocumentProperty(const QString &key, const QString &property)
- {
- Q_D(Document);
- d->documentProperties[key] = property;
- }
- /*!
- * Returns the names of all properties that were addedusing setDocumentProperty().
- */
- QStringList Document::documentPropertyNames() const
- {
- Q_D(const Document);
- return d->documentProperties.keys();
- }
- /*!
- * Return the internal Workbook object.
- */
- Workbook *Document::workbook() const
- {
- Q_D(const Document);
- return d->workbook.data();
- }
- /*!
- * Returns the sheet object named \a sheetName.
- */
- AbstractSheet *Document::sheet(const QString &sheetName) const
- {
- Q_D(const Document);
- return d->workbook->sheet(sheetNames().indexOf(sheetName));
- }
- /*!
- * Creates and append an sheet with the given \a name and \a type.
- * Return true if success.
- */
- bool Document::addSheet(const QString &name, AbstractSheet::SheetType type)
- {
- Q_D(Document);
- return d->workbook->addSheet(name, type);
- }
- /*!
- * Creates and inserts an document with the given \a name and \a type at the \a index.
- * Returns false if the \a name already used.
- */
- bool Document::insertSheet(int index, const QString &name, AbstractSheet::SheetType type)
- {
- Q_D(Document);
- return d->workbook->insertSheet(index, name, type);
- }
- /*!
- Rename the worksheet from \a oldName to \a newName.
- Returns true if the success.
- */
- bool Document::renameSheet(const QString &oldName, const QString &newName)
- {
- Q_D(Document);
- if (oldName == newName)
- return false;
- return d->workbook->renameSheet(sheetNames().indexOf(oldName), newName);
- }
- /*!
- Make a copy of the worksheet \a srcName with the new name \a distName.
- Returns true if the success.
- */
- bool Document::copySheet(const QString &srcName, const QString &distName)
- {
- Q_D(Document);
- if (srcName == distName)
- return false;
- return d->workbook->copySheet(sheetNames().indexOf(srcName), distName);
- }
- /*!
- Move the worksheet \a srcName to the new pos \a distIndex.
- Returns true if the success.
- */
- bool Document::moveSheet(const QString &srcName, int distIndex)
- {
- Q_D(Document);
- return d->workbook->moveSheet(sheetNames().indexOf(srcName), distIndex);
- }
- /*!
- Delete the worksheet \a name.
- Returns true if current sheet was deleted successfully.
- */
- bool Document::deleteSheet(const QString &name)
- {
- Q_D(Document);
- return d->workbook->deleteSheet(sheetNames().indexOf(name));
- }
- /*!
- * \brief Return pointer of current sheet.
- */
- AbstractSheet *Document::currentSheet() const
- {
- Q_D(const Document);
- return d->workbook->activeSheet();
- }
- /*!
- * \brief Return pointer of current worksheet.
- * If the type of sheet is not AbstractSheet::ST_WorkSheet, then 0 will be returned.
- */
- Worksheet *Document::currentWorksheet() const
- {
- AbstractSheet *st = currentSheet();
- if (st && st->sheetType() == AbstractSheet::ST_WorkSheet)
- return static_cast<Worksheet *>(st);
- else
- return 0;
- }
- /*!
- * \brief Set worksheet named \a name to be active sheet.
- * Returns true if success.
- */
- bool Document::selectSheet(const QString &name)
- {
- Q_D(Document);
- return d->workbook->setActiveSheet(sheetNames().indexOf(name));
- }
- /*!
- * Returns the names of worksheets contained in current document.
- */
- QStringList Document::sheetNames() const
- {
- Q_D(const Document);
- return d->workbook->worksheetNames();
- }
- /*!
- * Save current document to the filesystem. If no name specified when
- * the document constructed, a default name "book1.xlsx" will be used.
- * Returns true if saved successfully.
- */
- bool Document::save() const
- {
- Q_D(const Document);
- QString name = d->packageName.isEmpty() ? d->defaultPackageName : d->packageName;
- return saveAs(name);
- }
- /*!
- * Saves the document to the file with the given \a name.
- * Returns true if saved successfully.
- */
- bool Document::saveAs(const QString &name) const
- {
- QFile file(name);
- if (file.open(QIODevice::WriteOnly))
- return saveAs(&file);
- return false;
- }
- /*!
- * \overload
- * This function writes a document to the given \a device.
- *
- * \warning The \a device will be closed when this function returned.
- */
- bool Document::saveAs(QIODevice *device) const
- {
- Q_D(const Document);
- return d->savePackage(device);
- }
- /*!
- * Destroys the document and cleans up.
- */
- Document::~Document()
- {
- delete d_ptr;
- }
- QT_END_NAMESPACE_XLSX
|