andre@1: /**************************************************************************** andre@1: ** Copyright (c) 2013-2014 Debao Zhang andre@1: ** All right reserved. andre@1: ** andre@1: ** Permission is hereby granted, free of charge, to any person obtaining andre@1: ** a copy of this software and associated documentation files (the andre@1: ** "Software"), to deal in the Software without restriction, including andre@1: ** without limitation the rights to use, copy, modify, merge, publish, andre@1: ** distribute, sublicense, and/or sell copies of the Software, and to andre@1: ** permit persons to whom the Software is furnished to do so, subject to andre@1: ** the following conditions: andre@1: ** andre@1: ** The above copyright notice and this permission notice shall be andre@1: ** included in all copies or substantial portions of the Software. andre@1: ** andre@1: ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, andre@1: ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF andre@1: ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND andre@1: ** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE andre@1: ** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION andre@1: ** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION andre@1: ** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. andre@1: ** andre@1: ****************************************************************************/ andre@1: #include "xlsxworkbook.h" andre@1: #include "xlsxworkbook_p.h" andre@1: #include "xlsxsharedstrings_p.h" andre@1: #include "xlsxworksheet.h" andre@1: #include "xlsxchartsheet.h" andre@1: #include "xlsxstyles_p.h" andre@1: #include "xlsxformat.h" andre@1: #include "xlsxworksheet_p.h" andre@1: #include "xlsxformat_p.h" andre@1: #include "xlsxmediafile_p.h" andre@1: #include "xlsxutility_p.h" andre@1: andre@1: #include andre@1: #include andre@1: #include andre@1: #include andre@1: #include andre@1: andre@1: QT_BEGIN_NAMESPACE_XLSX andre@1: andre@1: WorkbookPrivate::WorkbookPrivate(Workbook *q, Workbook::CreateFlag flag) : andre@1: AbstractOOXmlFilePrivate(q, flag) andre@1: { andre@1: sharedStrings = QSharedPointer (new SharedStrings(flag)); andre@1: styles = QSharedPointer(new Styles(flag)); andre@1: theme = QSharedPointer(new Theme(flag)); andre@1: andre@1: x_window = 240; andre@1: y_window = 15; andre@1: window_width = 16095; andre@1: window_height = 9660; andre@1: andre@1: strings_to_numbers_enabled = false; andre@1: strings_to_hyperlinks_enabled = true; andre@1: html_to_richstring_enabled = false; andre@1: date1904 = false; andre@1: defaultDateFormat = QStringLiteral("yyyy-mm-dd"); andre@1: activesheetIndex = 0; andre@1: firstsheet = 0; andre@1: table_count = 0; andre@1: andre@1: last_worksheet_index = 0; andre@1: last_chartsheet_index = 0; andre@1: last_sheet_id = 0; andre@1: } andre@1: andre@1: Workbook::Workbook(CreateFlag flag) andre@1: : AbstractOOXmlFile(new WorkbookPrivate(this, flag)) andre@1: { andre@1: andre@1: } andre@1: andre@1: Workbook::~Workbook() andre@1: { andre@1: } andre@1: andre@1: bool Workbook::isDate1904() const andre@1: { andre@1: Q_D(const Workbook); andre@1: return d->date1904; andre@1: } andre@1: andre@1: /*! andre@1: Excel for Windows uses a default epoch of 1900 and Excel andre@1: for Mac uses an epoch of 1904. However, Excel on either andre@1: platform will convert automatically between one system andre@1: and the other. Qt Xlsx stores dates in the 1900 format andre@1: by default. andre@1: andre@1: \note This function should be called before any date/time andre@1: has been written. andre@1: */ andre@1: void Workbook::setDate1904(bool date1904) andre@1: { andre@1: Q_D(Workbook); andre@1: d->date1904 = date1904; andre@1: } andre@1: andre@1: /* andre@1: Enable the worksheet.write() method to convert strings andre@1: to numbers, where possible, using float() in order to avoid andre@1: an Excel warning about "Numbers Stored as Text". andre@1: andre@1: The default is false andre@1: */ andre@1: void Workbook::setStringsToNumbersEnabled(bool enable) andre@1: { andre@1: Q_D(Workbook); andre@1: d->strings_to_numbers_enabled = enable; andre@1: } andre@1: andre@1: bool Workbook::isStringsToNumbersEnabled() const andre@1: { andre@1: Q_D(const Workbook); andre@1: return d->strings_to_numbers_enabled; andre@1: } andre@1: andre@1: void Workbook::setStringsToHyperlinksEnabled(bool enable) andre@1: { andre@1: Q_D(Workbook); andre@1: d->strings_to_hyperlinks_enabled = enable; andre@1: } andre@1: andre@1: bool Workbook::isStringsToHyperlinksEnabled() const andre@1: { andre@1: Q_D(const Workbook); andre@1: return d->strings_to_hyperlinks_enabled; andre@1: } andre@1: andre@1: void Workbook::setHtmlToRichStringEnabled(bool enable) andre@1: { andre@1: Q_D(Workbook); andre@1: d->html_to_richstring_enabled = enable; andre@1: } andre@1: andre@1: bool Workbook::isHtmlToRichStringEnabled() const andre@1: { andre@1: Q_D(const Workbook); andre@1: return d->html_to_richstring_enabled; andre@1: } andre@1: andre@1: QString Workbook::defaultDateFormat() const andre@1: { andre@1: Q_D(const Workbook); andre@1: return d->defaultDateFormat; andre@1: } andre@1: andre@1: void Workbook::setDefaultDateFormat(const QString &format) andre@1: { andre@1: Q_D(Workbook); andre@1: d->defaultDateFormat = format; andre@1: } andre@1: andre@1: /*! andre@1: * \brief Create a defined name in the workbook. andre@1: * \param name The defined name andre@1: * \param formula The cell or range that the defined name refers to. andre@1: * \param comment andre@1: * \param scope The name of one worksheet, or empty which means golbal scope. andre@1: * \return Return false if the name invalid. andre@1: */ andre@1: bool Workbook::defineName(const QString &name, const QString &formula, const QString &comment, const QString &scope) andre@1: { andre@1: Q_D(Workbook); andre@1: andre@1: //Remove the = sign from the formula if it exists. andre@1: QString formulaString = formula; andre@1: if (formulaString.startsWith(QLatin1Char('='))) andre@1: formulaString = formula.mid(1); andre@1: andre@1: int id=-1; andre@1: if (!scope.isEmpty()) { andre@1: for (int i=0; isheets.size(); ++i) { andre@1: if (d->sheets[i]->sheetName() == scope) { andre@1: id = d->sheets[i]->sheetId(); andre@1: break; andre@1: } andre@1: } andre@1: } andre@1: andre@1: d->definedNamesList.append(XlsxDefineNameData(name, formulaString, comment, id)); andre@1: return true; andre@1: } andre@1: andre@1: AbstractSheet *Workbook::addSheet(const QString &name, AbstractSheet::SheetType type) andre@1: { andre@1: Q_D(Workbook); andre@1: return insertSheet(d->sheets.size(), name, type); andre@1: } andre@1: andre@1: /*! andre@1: * \internal andre@1: */ andre@1: QStringList Workbook::worksheetNames() const andre@1: { andre@1: Q_D(const Workbook); andre@1: return d->sheetNames; andre@1: } andre@1: andre@1: /*! andre@1: * \internal andre@1: * Used only when load the xlsx file!! andre@1: */ andre@1: AbstractSheet *Workbook::addSheet(const QString &name, int sheetId, AbstractSheet::SheetType type) andre@1: { andre@1: Q_D(Workbook); andre@1: if (sheetId > d->last_sheet_id) andre@1: d->last_sheet_id = sheetId; andre@1: AbstractSheet *sheet=0; andre@1: if (type == AbstractSheet::ST_WorkSheet) { andre@1: sheet = new Worksheet(name, sheetId, this, F_LoadFromExists); andre@1: } else if (type == AbstractSheet::ST_ChartSheet) { andre@1: sheet = new Chartsheet(name, sheetId, this, F_LoadFromExists); andre@1: } else { andre@1: qWarning("unsupported sheet type."); andre@1: Q_ASSERT(false); andre@1: } andre@1: d->sheets.append(QSharedPointer(sheet)); andre@1: d->sheetNames.append(name); andre@1: return sheet; andre@1: } andre@1: andre@1: AbstractSheet *Workbook::insertSheet(int index, const QString &name, AbstractSheet::SheetType type) andre@1: { andre@1: Q_D(Workbook); andre@1: QString sheetName = createSafeSheetName(name); andre@1: if (!sheetName.isEmpty()) { andre@1: //If user given an already in-used name, we should not continue any more! andre@1: if (d->sheetNames.contains(sheetName)) andre@1: return 0; andre@1: } else { andre@1: if (type == AbstractSheet::ST_WorkSheet) { andre@1: do { andre@1: ++d->last_worksheet_index; andre@1: sheetName = QStringLiteral("Sheet%1").arg(d->last_worksheet_index); andre@1: } while (d->sheetNames.contains(sheetName)); andre@1: } else if (type == AbstractSheet::ST_ChartSheet) { andre@1: do { andre@1: ++d->last_chartsheet_index; andre@1: sheetName = QStringLiteral("Chart%1").arg(d->last_chartsheet_index); andre@1: } while (d->sheetNames.contains(sheetName)); andre@1: } else { andre@1: qWarning("unsupported sheet type."); andre@1: return 0; andre@1: } andre@1: } andre@1: andre@1: ++d->last_sheet_id; andre@1: AbstractSheet *sheet; andre@1: if (type == AbstractSheet::ST_WorkSheet) andre@1: sheet = new Worksheet(sheetName, d->last_sheet_id, this, F_NewFromScratch); andre@1: else andre@1: sheet = new Chartsheet(sheetName, d->last_sheet_id, this, F_NewFromScratch); andre@1: andre@1: d->sheets.insert(index, QSharedPointer(sheet)); andre@1: d->sheetNames.insert(index, sheetName); andre@1: d->activesheetIndex = index; andre@1: return sheet; andre@1: } andre@1: andre@1: /*! andre@1: * Returns current active worksheet. andre@1: */ andre@1: AbstractSheet *Workbook::activeSheet() const andre@1: { andre@1: Q_D(const Workbook); andre@1: if (d->sheets.isEmpty()) andre@1: const_cast(this)->addSheet(); andre@1: return d->sheets[d->activesheetIndex].data(); andre@1: } andre@1: andre@1: bool Workbook::setActiveSheet(int index) andre@1: { andre@1: Q_D(Workbook); andre@1: if (index < 0 || index >= d->sheets.size()) { andre@1: //warning andre@1: return false; andre@1: } andre@1: d->activesheetIndex = index; andre@1: return true; andre@1: } andre@1: andre@1: /*! andre@1: * Rename the worksheet at the \a index to \a newName. andre@1: */ andre@1: bool Workbook::renameSheet(int index, const QString &newName) andre@1: { andre@1: Q_D(Workbook); andre@1: QString name = createSafeSheetName(newName); andre@1: if (index < 0 || index >= d->sheets.size()) andre@1: return false; andre@1: andre@1: //If user given an already in-used name, return false andre@1: for (int i=0; isheets.size(); ++i) { andre@1: if (d->sheets[i]->sheetName() == name) andre@1: return false; andre@1: } andre@1: andre@1: d->sheets[index]->setSheetName(name); andre@1: d->sheetNames[index] = name; andre@1: return true; andre@1: } andre@1: andre@1: /*! andre@1: * Remove the worksheet at pos \a index. andre@1: */ andre@1: bool Workbook::deleteSheet(int index) andre@1: { andre@1: Q_D(Workbook); andre@1: if (d->sheets.size() <= 1) andre@1: return false; andre@1: if (index < 0 || index >= d->sheets.size()) andre@1: return false; andre@1: d->sheets.removeAt(index); andre@1: d->sheetNames.removeAt(index); andre@1: return true; andre@1: } andre@1: andre@1: /*! andre@1: * Moves the worksheet form \a srcIndex to \a distIndex. andre@1: */ andre@1: bool Workbook::moveSheet(int srcIndex, int distIndex) andre@1: { andre@1: Q_D(Workbook); andre@1: if (srcIndex == distIndex) andre@1: return false; andre@1: andre@1: if (srcIndex < 0 || srcIndex >= d->sheets.size()) andre@1: return false; andre@1: andre@1: QSharedPointer sheet = d->sheets.takeAt(srcIndex); andre@1: d->sheetNames.takeAt(srcIndex); andre@1: if (distIndex >= 0 || distIndex <= d->sheets.size()) { andre@1: d->sheets.insert(distIndex, sheet); andre@1: d->sheetNames.insert(distIndex, sheet->sheetName()); andre@1: } else { andre@1: d->sheets.append(sheet); andre@1: d->sheetNames.append(sheet->sheetName()); andre@1: } andre@1: return true; andre@1: } andre@1: andre@1: bool Workbook::copySheet(int index, const QString &newName) andre@1: { andre@1: Q_D(Workbook); andre@1: if (index < 0 || index >= d->sheets.size()) andre@1: return false; andre@1: andre@1: QString worksheetName = createSafeSheetName(newName); andre@1: if (!newName.isEmpty()) { andre@1: //If user given an already in-used name, we should not continue any more! andre@1: if (d->sheetNames.contains(newName)) andre@1: return false; andre@1: } else { andre@1: int copy_index = 1; andre@1: do { andre@1: ++copy_index; andre@1: worksheetName = QStringLiteral("%1(%2)").arg(d->sheets[index]->sheetName()).arg(copy_index); andre@1: } while (d->sheetNames.contains(worksheetName)); andre@1: } andre@1: andre@1: ++d->last_sheet_id; andre@1: AbstractSheet *sheet = d->sheets[index]->copy(worksheetName, d->last_sheet_id); andre@1: d->sheets.append(QSharedPointer (sheet)); andre@1: d->sheetNames.append(sheet->sheetName()); andre@1: andre@1: return false; andre@1: } andre@1: andre@1: /*! andre@1: * Returns count of worksheets. andre@1: */ andre@1: int Workbook::sheetCount() const andre@1: { andre@1: Q_D(const Workbook); andre@1: return d->sheets.count(); andre@1: } andre@1: andre@1: /*! andre@1: * Returns the sheet object at index \a sheetIndex. andre@1: */ andre@1: AbstractSheet *Workbook::sheet(int index) const andre@1: { andre@1: Q_D(const Workbook); andre@1: if (index < 0 || index >= d->sheets.size()) andre@1: return 0; andre@1: return d->sheets.at(index).data(); andre@1: } andre@1: andre@1: SharedStrings *Workbook::sharedStrings() const andre@1: { andre@1: Q_D(const Workbook); andre@1: return d->sharedStrings.data(); andre@1: } andre@1: andre@1: Styles *Workbook::styles() andre@1: { andre@1: Q_D(Workbook); andre@1: return d->styles.data(); andre@1: } andre@1: andre@1: Theme *Workbook::theme() andre@1: { andre@1: Q_D(Workbook); andre@1: return d->theme.data(); andre@1: } andre@1: andre@1: /*! andre@1: * \internal andre@1: * andre@1: * Unlike media files, drawing file is a property of the sheet. andre@1: */ andre@1: QList Workbook::drawings() andre@1: { andre@1: Q_D(Workbook); andre@1: QList ds; andre@1: for (int i=0; isheets.size(); ++i) { andre@1: QSharedPointer sheet = d->sheets[i]; andre@1: if (sheet->drawing()) andre@1: ds.append(sheet->drawing()); andre@1: } andre@1: andre@1: return ds; andre@1: } andre@1: andre@1: /*! andre@1: * \internal andre@1: */ andre@1: QList > Workbook::getSheetsByTypes(AbstractSheet::SheetType type) const andre@1: { andre@1: Q_D(const Workbook); andre@1: QList > list; andre@1: for (int i=0; isheets.size(); ++i) { andre@1: if (d->sheets[i]->sheetType() == type) andre@1: list.append(d->sheets[i]); andre@1: } andre@1: return list; andre@1: } andre@1: andre@1: void Workbook::saveToXmlFile(QIODevice *device) const andre@1: { andre@1: Q_D(const Workbook); andre@1: d->relationships->clear(); andre@1: if (d->sheets.isEmpty()) andre@1: const_cast(this)->addSheet(); andre@1: andre@1: QXmlStreamWriter writer(device); andre@1: andre@1: writer.writeStartDocument(QStringLiteral("1.0"), true); andre@1: writer.writeStartElement(QStringLiteral("workbook")); andre@1: writer.writeAttribute(QStringLiteral("xmlns"), QStringLiteral("http://schemas.openxmlformats.org/spreadsheetml/2006/main")); andre@1: writer.writeAttribute(QStringLiteral("xmlns:r"), QStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/relationships")); andre@1: andre@1: writer.writeEmptyElement(QStringLiteral("fileVersion")); andre@1: writer.writeAttribute(QStringLiteral("appName"), QStringLiteral("xl")); andre@1: writer.writeAttribute(QStringLiteral("lastEdited"), QStringLiteral("4")); andre@1: writer.writeAttribute(QStringLiteral("lowestEdited"), QStringLiteral("4")); andre@1: writer.writeAttribute(QStringLiteral("rupBuild"), QStringLiteral("4505")); andre@1: // writer.writeAttribute(QStringLiteral("codeName"), QStringLiteral("{37E998C4-C9E5-D4B9-71C8-EB1FF731991C}")); andre@1: andre@1: writer.writeEmptyElement(QStringLiteral("workbookPr")); andre@1: if (d->date1904) andre@1: writer.writeAttribute(QStringLiteral("date1904"), QStringLiteral("1")); andre@1: writer.writeAttribute(QStringLiteral("defaultThemeVersion"), QStringLiteral("124226")); andre@1: andre@1: writer.writeStartElement(QStringLiteral("bookViews")); andre@1: writer.writeEmptyElement(QStringLiteral("workbookView")); andre@1: writer.writeAttribute(QStringLiteral("xWindow"), QString::number(d->x_window)); andre@1: writer.writeAttribute(QStringLiteral("yWindow"), QString::number(d->y_window)); andre@1: writer.writeAttribute(QStringLiteral("windowWidth"), QString::number(d->window_width)); andre@1: writer.writeAttribute(QStringLiteral("windowHeight"), QString::number(d->window_height)); andre@1: //Store the firstSheet when it isn't the default andre@1: //For example, when "the first sheet 0 is hidden", the first sheet will be 1 andre@1: if (d->firstsheet > 0) andre@1: writer.writeAttribute(QStringLiteral("firstSheet"), QString::number(d->firstsheet + 1)); andre@1: //Store the activeTab when it isn't the first sheet andre@1: if (d->activesheetIndex > 0) andre@1: writer.writeAttribute(QStringLiteral("activeTab"), QString::number(d->activesheetIndex)); andre@1: writer.writeEndElement();//bookViews andre@1: andre@1: writer.writeStartElement(QStringLiteral("sheets")); andre@1: int worksheetIndex = 0; andre@1: int chartsheetIndex = 0; andre@1: for (int i=0; isheets.size(); ++i) { andre@1: QSharedPointer sheet = d->sheets[i]; andre@1: writer.writeEmptyElement(QStringLiteral("sheet")); andre@1: writer.writeAttribute(QStringLiteral("name"), sheet->sheetName()); andre@1: writer.writeAttribute(QStringLiteral("sheetId"), QString::number(sheet->sheetId())); andre@1: if (sheet->sheetState() == AbstractSheet::SS_Hidden) andre@1: writer.writeAttribute(QStringLiteral("state"), QStringLiteral("hidden")); andre@1: else if (sheet->sheetState() == AbstractSheet::SS_VeryHidden) andre@1: writer.writeAttribute(QStringLiteral("state"), QStringLiteral("veryHidden")); andre@1: andre@1: if (sheet->sheetType() == AbstractSheet::ST_WorkSheet) andre@1: d->relationships->addDocumentRelationship(QStringLiteral("/worksheet"), QStringLiteral("worksheets/sheet%1.xml").arg(++worksheetIndex)); andre@1: else andre@1: d->relationships->addDocumentRelationship(QStringLiteral("/chartsheet"), QStringLiteral("chartsheets/sheet%1.xml").arg(++chartsheetIndex)); andre@1: andre@1: writer.writeAttribute(QStringLiteral("r:id"), QStringLiteral("rId%1").arg(d->relationships->count())); andre@1: } andre@1: writer.writeEndElement();//sheets andre@1: andre@1: if (d->externalLinks.size() > 0) { andre@1: writer.writeStartElement(QStringLiteral("externalReferences")); andre@1: for (int i=0; iexternalLinks.size(); ++i) { andre@1: writer.writeEmptyElement(QStringLiteral("externalReference")); andre@1: d->relationships->addDocumentRelationship(QStringLiteral("/externalLink"), QStringLiteral("externalLinks/externalLink%1.xml").arg(i+1)); andre@1: writer.writeAttribute(QStringLiteral("r:id"), QStringLiteral("rId%1").arg(d->relationships->count())); andre@1: } andre@1: writer.writeEndElement();//externalReferences andre@1: } andre@1: andre@1: if (!d->definedNamesList.isEmpty()) { andre@1: writer.writeStartElement(QStringLiteral("definedNames")); andre@1: foreach (XlsxDefineNameData data, d->definedNamesList) { andre@1: writer.writeStartElement(QStringLiteral("definedName")); andre@1: writer.writeAttribute(QStringLiteral("name"), data.name); andre@1: if (!data.comment.isEmpty()) andre@1: writer.writeAttribute(QStringLiteral("comment"), data.comment); andre@1: if (data.sheetId != -1) { andre@1: //find the local index of the sheet. andre@1: for (int i=0; isheets.size(); ++i) { andre@1: if (d->sheets[i]->sheetId() == data.sheetId) { andre@1: writer.writeAttribute(QStringLiteral("localSheetId"), QString::number(i)); andre@1: break; andre@1: } andre@1: } andre@1: } andre@1: writer.writeCharacters(data.formula); andre@1: writer.writeEndElement();//definedName andre@1: } andre@1: writer.writeEndElement();//definedNames andre@1: } andre@1: andre@1: writer.writeStartElement(QStringLiteral("calcPr")); andre@1: writer.writeAttribute(QStringLiteral("calcId"), QStringLiteral("124519")); andre@1: writer.writeEndElement(); //calcPr andre@1: andre@1: writer.writeEndElement();//workbook andre@1: writer.writeEndDocument(); andre@1: andre@1: d->relationships->addDocumentRelationship(QStringLiteral("/theme"), QStringLiteral("theme/theme1.xml")); andre@1: d->relationships->addDocumentRelationship(QStringLiteral("/styles"), QStringLiteral("styles.xml")); andre@1: if (!sharedStrings()->isEmpty()) andre@1: d->relationships->addDocumentRelationship(QStringLiteral("/sharedStrings"), QStringLiteral("sharedStrings.xml")); andre@1: } andre@1: andre@1: bool Workbook::loadFromXmlFile(QIODevice *device) andre@1: { andre@1: Q_D(Workbook); andre@1: andre@1: QXmlStreamReader reader(device); andre@1: while (!reader.atEnd()) { andre@1: QXmlStreamReader::TokenType token = reader.readNext(); andre@1: if (token == QXmlStreamReader::StartElement) { andre@1: if (reader.name() == QLatin1String("sheet")) { andre@1: QXmlStreamAttributes attributes = reader.attributes(); andre@1: const QString name = attributes.value(QLatin1String("name")).toString(); andre@1: int sheetId = attributes.value(QLatin1String("sheetId")).toString().toInt(); andre@1: const QString rId = attributes.value(QLatin1String("r:id")).toString(); andre@1: const QStringRef &stateString = attributes.value(QLatin1String("state")); andre@1: AbstractSheet::SheetState state = AbstractSheet::SS_Visible; andre@1: if (stateString == QLatin1String("hidden")) andre@1: state = AbstractSheet::SS_Hidden; andre@1: else if (stateString == QLatin1String("veryHidden")) andre@1: state = AbstractSheet::SS_VeryHidden; andre@1: andre@1: XlsxRelationship relationship = d->relationships->getRelationshipById(rId); andre@1: andre@1: AbstractSheet::SheetType type = AbstractSheet::ST_WorkSheet; andre@1: if (relationship.type.endsWith(QLatin1String("/worksheet"))) andre@1: type = AbstractSheet::ST_WorkSheet; andre@1: else if (relationship.type.endsWith(QLatin1String("/chartsheet"))) andre@1: type = AbstractSheet::ST_ChartSheet; andre@1: else if (relationship.type.endsWith(QLatin1String("/dialogsheet"))) andre@1: type = AbstractSheet::ST_DialogSheet; andre@1: else if (relationship.type.endsWith(QLatin1String("/xlMacrosheet"))) andre@1: type = AbstractSheet::ST_MacroSheet; andre@1: else andre@1: qWarning("unknown sheet type"); andre@1: andre@1: AbstractSheet *sheet = addSheet(name, sheetId, type); andre@1: sheet->setSheetState(state); andre@1: const QString fullPath = QDir::cleanPath(splitPath(filePath())[0] +QLatin1String("/")+ relationship.target); andre@1: sheet->setFilePath(fullPath); andre@1: } else if (reader.name() == QLatin1String("workbookPr")) { andre@1: QXmlStreamAttributes attrs = reader.attributes(); andre@1: if (attrs.hasAttribute(QLatin1String("date1904"))) andre@1: d->date1904 = true; andre@1: } else if (reader.name() == QLatin1String("bookviews")) { andre@1: while (!(reader.name() == QLatin1String("bookviews") && reader.tokenType() == QXmlStreamReader::EndElement)) { andre@1: reader.readNextStartElement(); andre@1: if (reader.tokenType() == QXmlStreamReader::StartElement) { andre@1: if (reader.name() == QLatin1String("workbookView")) { andre@1: QXmlStreamAttributes attrs = reader.attributes(); andre@1: if (attrs.hasAttribute(QLatin1String("xWindow"))) andre@1: d->x_window = attrs.value(QLatin1String("xWindow")).toString().toInt(); andre@1: if (attrs.hasAttribute(QLatin1String("yWindow"))) andre@1: d->y_window = attrs.value(QLatin1String("yWindow")).toString().toInt(); andre@1: if (attrs.hasAttribute(QLatin1String("windowWidth"))) andre@1: d->window_width = attrs.value(QLatin1String("windowWidth")).toString().toInt(); andre@1: if (attrs.hasAttribute(QLatin1String("windowHeight"))) andre@1: d->window_height = attrs.value(QLatin1String("windowHeight")).toString().toInt(); andre@1: if (attrs.hasAttribute(QLatin1String("firstSheet"))) andre@1: d->firstsheet = attrs.value(QLatin1String("firstSheet")).toString().toInt(); andre@1: if (attrs.hasAttribute(QLatin1String("activeTab"))) andre@1: d->activesheetIndex = attrs.value(QLatin1String("activeTab")).toString().toInt(); andre@1: } andre@1: } andre@1: } andre@1: } else if (reader.name() == QLatin1String("externalReference")) { andre@1: QXmlStreamAttributes attributes = reader.attributes(); andre@1: const QString rId = attributes.value(QLatin1String("r:id")).toString(); andre@1: XlsxRelationship relationship = d->relationships->getRelationshipById(rId); andre@1: andre@1: QSharedPointer link(new SimpleOOXmlFile(F_LoadFromExists)); andre@1: const QString fullPath = QDir::cleanPath(splitPath(filePath())[0] +QLatin1String("/")+ relationship.target); andre@1: link->setFilePath(fullPath); andre@1: d->externalLinks.append(link); andre@1: } else if (reader.name() == QLatin1String("definedName")) { andre@1: QXmlStreamAttributes attrs = reader.attributes(); andre@1: XlsxDefineNameData data; andre@1: andre@1: data.name = attrs.value(QLatin1String("name")).toString(); andre@1: if (attrs.hasAttribute(QLatin1String("comment"))) andre@1: data.comment = attrs.value(QLatin1String("comment")).toString(); andre@1: if (attrs.hasAttribute(QLatin1String("localSheetId"))) { andre@1: int localId = attrs.value(QLatin1String("localSheetId")).toString().toInt(); andre@1: int sheetId = d->sheets.at(localId)->sheetId(); andre@1: data.sheetId = sheetId; andre@1: } andre@1: data.formula = reader.readElementText(); andre@1: d->definedNamesList.append(data); andre@1: } andre@1: } andre@1: } andre@1: return true; andre@1: } andre@1: andre@1: /*! andre@1: * \internal andre@1: */ andre@1: QList > Workbook::mediaFiles() const andre@1: { andre@1: Q_D(const Workbook); andre@1: andre@1: return d->mediaFiles; andre@1: } andre@1: andre@1: /*! andre@1: * \internal andre@1: */ andre@1: void Workbook::addMediaFile(QSharedPointer media, bool force) andre@1: { andre@1: Q_D(Workbook); andre@1: if (!force) { andre@1: for (int i=0; imediaFiles.size(); ++i) { andre@1: if (d->mediaFiles[i]->hashKey() == media->hashKey()) { andre@1: media->setIndex(i); andre@1: return; andre@1: } andre@1: } andre@1: } andre@1: media->setIndex(d->mediaFiles.size()); andre@1: d->mediaFiles.append(media); andre@1: } andre@1: andre@1: /*! andre@1: * \internal andre@1: */ andre@1: QList > Workbook::chartFiles() const andre@1: { andre@1: Q_D(const Workbook); andre@1: andre@1: return d->chartFiles; andre@1: } andre@1: andre@1: /*! andre@1: * \internal andre@1: */ andre@1: void Workbook::addChartFile(QSharedPointer chart) andre@1: { andre@1: Q_D(Workbook); andre@1: andre@1: if (!d->chartFiles.contains(chart)) andre@1: d->chartFiles.append(chart); andre@1: } andre@1: andre@1: QT_END_NAMESPACE_XLSX