File indexing completed on 2025-03-23 03:32:51
0001 // xlsxworkbook.cpp 0002 0003 #include <QtGlobal> 0004 #include <QXmlStreamWriter> 0005 #include <QXmlStreamReader> 0006 #include <QFile> 0007 #include <QBuffer> 0008 #include <QDir> 0009 #include <QtDebug> 0010 0011 #include "xlsxworkbook.h" 0012 #include "xlsxworkbook_p.h" 0013 #include "xlsxsharedstrings_p.h" 0014 #include "xlsxworksheet.h" 0015 #include "xlsxchartsheet.h" 0016 #include "xlsxstyles_p.h" 0017 #include "xlsxformat.h" 0018 #include "xlsxworksheet_p.h" 0019 #include "xlsxformat_p.h" 0020 #include "xlsxmediafile_p.h" 0021 #include "xlsxutility_p.h" 0022 #include "xlsxchart.h" 0023 0024 QT_BEGIN_NAMESPACE_XLSX 0025 0026 WorkbookPrivate::WorkbookPrivate(Workbook *q, Workbook::CreateFlag flag) : 0027 AbstractOOXmlFilePrivate(q, flag) 0028 { 0029 sharedStrings = QSharedPointer<SharedStrings> (new SharedStrings(flag)); 0030 styles = QSharedPointer<Styles>(new Styles(flag)); 0031 theme = QSharedPointer<Theme>(new Theme(flag)); 0032 0033 x_window = 240; 0034 y_window = 15; 0035 window_width = 16095; 0036 window_height = 9660; 0037 0038 strings_to_numbers_enabled = false; 0039 strings_to_hyperlinks_enabled = true; 0040 html_to_richstring_enabled = false; 0041 date1904 = false; 0042 defaultDateFormat = QStringLiteral("yyyy-mm-dd"); 0043 activesheetIndex = 0; 0044 firstsheet = 0; 0045 table_count = 0; 0046 0047 last_worksheet_index = 0; 0048 last_chartsheet_index = 0; 0049 last_sheet_id = 0; 0050 } 0051 0052 Workbook::Workbook(CreateFlag flag) 0053 : AbstractOOXmlFile(new WorkbookPrivate(this, flag)) 0054 { 0055 0056 } 0057 0058 Workbook::~Workbook() 0059 { 0060 } 0061 0062 bool Workbook::isDate1904() const 0063 { 0064 Q_D(const Workbook); 0065 return d->date1904; 0066 } 0067 0068 /*! 0069 Excel for Windows uses a default epoch of 1900 and Excel 0070 for Mac uses an epoch of 1904. However, Excel on either 0071 platform will convert automatically between one system 0072 and the other. Qt Xlsx stores dates in the 1900 format 0073 by default. 0074 0075 \note This function should be called before any date/time 0076 has been written. 0077 */ 0078 void Workbook::setDate1904(bool date1904) 0079 { 0080 Q_D(Workbook); 0081 d->date1904 = date1904; 0082 } 0083 0084 /* 0085 Enable the worksheet.write() method to convert strings 0086 to numbers, where possible, using float() in order to avoid 0087 an Excel warning about "Numbers Stored as Text". 0088 0089 The default is false 0090 */ 0091 void Workbook::setStringsToNumbersEnabled(bool enable) 0092 { 0093 Q_D(Workbook); 0094 d->strings_to_numbers_enabled = enable; 0095 } 0096 0097 bool Workbook::isStringsToNumbersEnabled() const 0098 { 0099 Q_D(const Workbook); 0100 return d->strings_to_numbers_enabled; 0101 } 0102 0103 void Workbook::setStringsToHyperlinksEnabled(bool enable) 0104 { 0105 Q_D(Workbook); 0106 d->strings_to_hyperlinks_enabled = enable; 0107 } 0108 0109 bool Workbook::isStringsToHyperlinksEnabled() const 0110 { 0111 Q_D(const Workbook); 0112 return d->strings_to_hyperlinks_enabled; 0113 } 0114 0115 void Workbook::setHtmlToRichStringEnabled(bool enable) 0116 { 0117 Q_D(Workbook); 0118 d->html_to_richstring_enabled = enable; 0119 } 0120 0121 bool Workbook::isHtmlToRichStringEnabled() const 0122 { 0123 Q_D(const Workbook); 0124 return d->html_to_richstring_enabled; 0125 } 0126 0127 QString Workbook::defaultDateFormat() const 0128 { 0129 Q_D(const Workbook); 0130 return d->defaultDateFormat; 0131 } 0132 0133 void Workbook::setDefaultDateFormat(const QString &format) 0134 { 0135 Q_D(Workbook); 0136 d->defaultDateFormat = format; 0137 } 0138 0139 /*! 0140 * \brief Create a defined name in the workbook. 0141 * \param name The defined name 0142 * \param formula The cell or range that the defined name refers to. 0143 * \param comment 0144 * \param scope The name of one worksheet, or empty which means golbal scope. 0145 * \return Return false if the name invalid. 0146 */ 0147 bool Workbook::defineName(const QString &name, const QString &formula, const QString &comment, const QString &scope) 0148 { 0149 Q_D(Workbook); 0150 0151 //Remove the = sign from the formula if it exists. 0152 QString formulaString = formula; 0153 if (formulaString.startsWith(QLatin1Char('='))) 0154 formulaString = formula.mid(1); 0155 0156 int id=-1; 0157 if (!scope.isEmpty()) { 0158 for (int i=0; i<d->sheets.size(); ++i) { 0159 if (d->sheets[i]->sheetName() == scope) { 0160 id = d->sheets[i]->sheetId(); 0161 break; 0162 } 0163 } 0164 } 0165 0166 d->definedNamesList.append(XlsxDefineNameData(name, formulaString, comment, id)); 0167 return true; 0168 } 0169 0170 AbstractSheet *Workbook::addSheet(const QString &name, AbstractSheet::SheetType type) 0171 { 0172 Q_D(Workbook); 0173 return insertSheet(d->sheets.size(), name, type); 0174 } 0175 0176 /*! 0177 * \internal 0178 */ 0179 QStringList Workbook::worksheetNames() const 0180 { 0181 Q_D(const Workbook); 0182 return d->sheetNames; 0183 } 0184 0185 /*! 0186 * \internal 0187 * Used only when load the xlsx file!! 0188 */ 0189 AbstractSheet *Workbook::addSheet(const QString &name, int sheetId, AbstractSheet::SheetType type) 0190 { 0191 Q_D(Workbook); 0192 if (sheetId > d->last_sheet_id) 0193 d->last_sheet_id = sheetId; 0194 0195 AbstractSheet *sheet = nullptr; 0196 if (type == AbstractSheet::ST_WorkSheet) 0197 { 0198 // create work sheet (value sheet) 0199 sheet = new Worksheet(name, sheetId, this, F_LoadFromExists); 0200 } 0201 else if (type == AbstractSheet::ST_ChartSheet) 0202 { 0203 // create chart sheet 0204 sheet = new Chartsheet(name, sheetId, this, F_LoadFromExists); 0205 } 0206 else 0207 { 0208 qWarning("unsupported sheet type."); 0209 Q_ASSERT(false); 0210 } 0211 0212 d->sheets.append(QSharedPointer<AbstractSheet>(sheet)); 0213 d->sheetNames.append(name); 0214 0215 return sheet; 0216 } 0217 0218 AbstractSheet *Workbook::insertSheet(int index, const QString &name, AbstractSheet::SheetType type) 0219 { 0220 Q_D(Workbook); 0221 QString sheetName = createSafeSheetName(name); 0222 if(index > d->last_sheet_id){ 0223 //User tries to insert, where no sheet has gone before. 0224 return nullptr; 0225 } 0226 if (!sheetName.isEmpty()) { 0227 //If user given an already in-used name, we should not continue any more! 0228 if (d->sheetNames.contains(sheetName)) 0229 return nullptr; 0230 } else { 0231 if (type == AbstractSheet::ST_WorkSheet) { 0232 do { 0233 ++d->last_worksheet_index; 0234 sheetName = QStringLiteral("Sheet%1").arg(d->last_worksheet_index); 0235 } while (d->sheetNames.contains(sheetName)); 0236 } else if (type == AbstractSheet::ST_ChartSheet) { 0237 do { 0238 ++d->last_chartsheet_index; 0239 sheetName = QStringLiteral("Chart%1").arg(d->last_chartsheet_index); 0240 } while (d->sheetNames.contains(sheetName)); 0241 } else { 0242 qWarning("unsupported sheet type."); 0243 return nullptr; 0244 } 0245 } 0246 0247 ++d->last_sheet_id; 0248 0249 AbstractSheet *sheet = nullptr; 0250 if ( type == AbstractSheet::ST_WorkSheet ) 0251 { 0252 sheet = new Worksheet(sheetName, d->last_sheet_id, this, F_NewFromScratch); 0253 } 0254 else if ( type == AbstractSheet::ST_ChartSheet ) 0255 { 0256 sheet = new Chartsheet(sheetName, d->last_sheet_id, this, F_NewFromScratch); 0257 } 0258 else 0259 { 0260 qWarning("unsupported sheet type."); 0261 Q_ASSERT(false); 0262 } 0263 0264 d->sheets.insert(index, QSharedPointer<AbstractSheet>(sheet)); 0265 d->sheetNames.insert(index, sheetName); 0266 d->activesheetIndex = index; 0267 0268 return sheet; 0269 } 0270 0271 /*! 0272 * Returns current active worksheet. 0273 */ 0274 AbstractSheet *Workbook::activeSheet() const 0275 { 0276 Q_D(const Workbook); 0277 if (d->sheets.isEmpty()) 0278 const_cast<Workbook*>(this)->addSheet(); 0279 return d->sheets[d->activesheetIndex].data(); 0280 } 0281 0282 bool Workbook::setActiveSheet(int index) 0283 { 0284 Q_D(Workbook); 0285 if (index < 0 || index >= d->sheets.size()) { 0286 //warning 0287 return false; 0288 } 0289 d->activesheetIndex = index; 0290 return true; 0291 } 0292 0293 /*! 0294 * Rename the worksheet at the \a index to \a newName. 0295 */ 0296 bool Workbook::renameSheet(int index, const QString &newName) 0297 { 0298 Q_D(Workbook); 0299 QString name = createSafeSheetName(newName); 0300 if (index < 0 || index >= d->sheets.size()) 0301 return false; 0302 0303 //If user given an already in-used name, return false 0304 for (int i=0; i<d->sheets.size(); ++i) { 0305 if (d->sheets[i]->sheetName() == name) 0306 return false; 0307 } 0308 0309 d->sheets[index]->setSheetName(name); 0310 d->sheetNames[index] = name; 0311 return true; 0312 } 0313 0314 /*! 0315 * Remove the worksheet at pos \a index. 0316 */ 0317 bool Workbook::deleteSheet(int index) 0318 { 0319 Q_D(Workbook); 0320 if (d->sheets.size() <= 1) 0321 return false; 0322 if (index < 0 || index >= d->sheets.size()) 0323 return false; 0324 d->sheets.removeAt(index); 0325 d->sheetNames.removeAt(index); 0326 return true; 0327 } 0328 0329 /*! 0330 * Moves the worksheet form \a srcIndex to \a distIndex. 0331 */ 0332 bool Workbook::moveSheet(int srcIndex, int distIndex) 0333 { 0334 Q_D(Workbook); 0335 if (srcIndex == distIndex) 0336 return false; 0337 0338 if (srcIndex < 0 || srcIndex >= d->sheets.size()) 0339 return false; 0340 0341 QSharedPointer<AbstractSheet> sheet = d->sheets.takeAt(srcIndex); 0342 d->sheetNames.takeAt(srcIndex); 0343 if (distIndex >= 0 || distIndex <= d->sheets.size()) { 0344 d->sheets.insert(distIndex, sheet); 0345 d->sheetNames.insert(distIndex, sheet->sheetName()); 0346 } else { 0347 d->sheets.append(sheet); 0348 d->sheetNames.append(sheet->sheetName()); 0349 } 0350 return true; 0351 } 0352 0353 bool Workbook::copySheet(int index, const QString &newName) 0354 { 0355 Q_D(Workbook); 0356 if (index < 0 || index >= d->sheets.size()) 0357 return false; 0358 0359 QString worksheetName = createSafeSheetName(newName); 0360 if (!newName.isEmpty()) { 0361 //If user given an already in-used name, we should not continue any more! 0362 if (d->sheetNames.contains(newName)) 0363 return false; 0364 } else { 0365 int copy_index = 1; 0366 do { 0367 ++copy_index; 0368 worksheetName = QStringLiteral("%1(%2)").arg(d->sheets[index]->sheetName()).arg(copy_index); 0369 } while (d->sheetNames.contains(worksheetName)); 0370 } 0371 0372 ++d->last_sheet_id; 0373 AbstractSheet *sheet = d->sheets[index]->copy(worksheetName, d->last_sheet_id); 0374 d->sheets.append(QSharedPointer<AbstractSheet> (sheet)); 0375 d->sheetNames.append(sheet->sheetName()); 0376 0377 return true; // #162 0378 } 0379 0380 /*! 0381 * Returns count of worksheets. 0382 */ 0383 int Workbook::sheetCount() const 0384 { 0385 Q_D(const Workbook); 0386 return d->sheets.count(); 0387 } 0388 0389 /*! 0390 * Returns the sheet object at index \a sheetIndex. 0391 */ 0392 AbstractSheet *Workbook::sheet(int index) const 0393 { 0394 Q_D(const Workbook); 0395 if (index < 0 || index >= d->sheets.size()) 0396 return nullptr; 0397 return d->sheets.at(index).data(); 0398 } 0399 0400 SharedStrings *Workbook::sharedStrings() const 0401 { 0402 Q_D(const Workbook); 0403 return d->sharedStrings.data(); 0404 } 0405 0406 Styles *Workbook::styles() 0407 { 0408 Q_D(Workbook); 0409 return d->styles.data(); 0410 } 0411 0412 Theme *Workbook::theme() 0413 { 0414 Q_D(Workbook); 0415 return d->theme.data(); 0416 } 0417 0418 /*! 0419 * \internal 0420 * 0421 * Unlike media files, drawing file is a property of the sheet. 0422 */ 0423 QList<Drawing *> Workbook::drawings() 0424 { 0425 Q_D(Workbook); 0426 QList<Drawing *> ds; 0427 for (int i=0; i<d->sheets.size(); ++i) { 0428 QSharedPointer<AbstractSheet> sheet = d->sheets[i]; 0429 if (sheet->drawing()) 0430 ds.append(sheet->drawing()); 0431 } 0432 0433 return ds; 0434 } 0435 0436 /*! 0437 * \internal 0438 */ 0439 QList<QSharedPointer<AbstractSheet> > Workbook::getSheetsByTypes(AbstractSheet::SheetType type) const 0440 { 0441 Q_D(const Workbook); 0442 QList<QSharedPointer<AbstractSheet> > list; 0443 for (int i=0; i<d->sheets.size(); ++i) { 0444 if (d->sheets[i]->sheetType() == type) 0445 list.append(d->sheets[i]); 0446 } 0447 return list; 0448 } 0449 0450 void Workbook::saveToXmlFile(QIODevice *device) const 0451 { 0452 Q_D(const Workbook); 0453 d->relationships->clear(); 0454 if (d->sheets.isEmpty()) 0455 const_cast<Workbook *>(this)->addSheet(); 0456 0457 QXmlStreamWriter writer(device); 0458 0459 writer.writeStartDocument(QStringLiteral("1.0"), true); 0460 writer.writeStartElement(QStringLiteral("workbook")); 0461 writer.writeAttribute(QStringLiteral("xmlns"), QStringLiteral("http://schemas.openxmlformats.org/spreadsheetml/2006/main")); 0462 writer.writeAttribute(QStringLiteral("xmlns:r"), QStringLiteral("http://schemas.openxmlformats.org/officeDocument/2006/relationships")); 0463 0464 writer.writeEmptyElement(QStringLiteral("fileVersion")); 0465 writer.writeAttribute(QStringLiteral("appName"), QStringLiteral("xl")); 0466 writer.writeAttribute(QStringLiteral("lastEdited"), QStringLiteral("4")); 0467 writer.writeAttribute(QStringLiteral("lowestEdited"), QStringLiteral("4")); 0468 writer.writeAttribute(QStringLiteral("rupBuild"), QStringLiteral("4505")); 0469 // writer.writeAttribute(QStringLiteral("codeName"), QStringLiteral("{37E998C4-C9E5-D4B9-71C8-EB1FF731991C}")); 0470 0471 writer.writeEmptyElement(QStringLiteral("workbookPr")); 0472 if (d->date1904) 0473 writer.writeAttribute(QStringLiteral("date1904"), QStringLiteral("1")); 0474 writer.writeAttribute(QStringLiteral("defaultThemeVersion"), QStringLiteral("124226")); 0475 0476 writer.writeStartElement(QStringLiteral("bookViews")); 0477 writer.writeEmptyElement(QStringLiteral("workbookView")); 0478 writer.writeAttribute(QStringLiteral("xWindow"), QString::number(d->x_window)); 0479 writer.writeAttribute(QStringLiteral("yWindow"), QString::number(d->y_window)); 0480 writer.writeAttribute(QStringLiteral("windowWidth"), QString::number(d->window_width)); 0481 writer.writeAttribute(QStringLiteral("windowHeight"), QString::number(d->window_height)); 0482 //Store the firstSheet when it isn't the default 0483 //For example, when "the first sheet 0 is hidden", the first sheet will be 1 0484 if (d->firstsheet > 0) 0485 writer.writeAttribute(QStringLiteral("firstSheet"), QString::number(d->firstsheet + 1)); 0486 //Store the activeTab when it isn't the first sheet 0487 if (d->activesheetIndex > 0) 0488 writer.writeAttribute(QStringLiteral("activeTab"), QString::number(d->activesheetIndex)); 0489 writer.writeEndElement();//bookViews 0490 0491 writer.writeStartElement(QStringLiteral("sheets")); 0492 int worksheetIndex = 0; 0493 int chartsheetIndex = 0; 0494 for (int i=0; i<d->sheets.size(); ++i) { 0495 QSharedPointer<AbstractSheet> sheet = d->sheets[i]; 0496 writer.writeEmptyElement(QStringLiteral("sheet")); 0497 writer.writeAttribute(QStringLiteral("name"), sheet->sheetName()); 0498 writer.writeAttribute(QStringLiteral("sheetId"), QString::number(sheet->sheetId())); 0499 if (sheet->sheetState() == AbstractSheet::SS_Hidden) 0500 writer.writeAttribute(QStringLiteral("state"), QStringLiteral("hidden")); 0501 else if (sheet->sheetState() == AbstractSheet::SS_VeryHidden) 0502 writer.writeAttribute(QStringLiteral("state"), QStringLiteral("veryHidden")); 0503 0504 if (sheet->sheetType() == AbstractSheet::ST_WorkSheet) 0505 d->relationships->addDocumentRelationship(QStringLiteral("/worksheet"), QStringLiteral("worksheets/sheet%1.xml").arg(++worksheetIndex)); 0506 else 0507 d->relationships->addDocumentRelationship(QStringLiteral("/chartsheet"), QStringLiteral("chartsheets/sheet%1.xml").arg(++chartsheetIndex)); 0508 0509 writer.writeAttribute(QStringLiteral("r:id"), QStringLiteral("rId%1").arg(d->relationships->count())); 0510 } 0511 writer.writeEndElement();//sheets 0512 0513 if (d->externalLinks.size() > 0) { 0514 writer.writeStartElement(QStringLiteral("externalReferences")); 0515 for (int i=0; i<d->externalLinks.size(); ++i) { 0516 writer.writeEmptyElement(QStringLiteral("externalReference")); 0517 d->relationships->addDocumentRelationship(QStringLiteral("/externalLink"), QStringLiteral("externalLinks/externalLink%1.xml").arg(i+1)); 0518 writer.writeAttribute(QStringLiteral("r:id"), QStringLiteral("rId%1").arg(d->relationships->count())); 0519 } 0520 writer.writeEndElement();//externalReferences 0521 } 0522 0523 if (!d->definedNamesList.isEmpty()) { 0524 writer.writeStartElement(QStringLiteral("definedNames")); 0525 for (const XlsxDefineNameData &data : d->definedNamesList) { 0526 writer.writeStartElement(QStringLiteral("definedName")); 0527 writer.writeAttribute(QStringLiteral("name"), data.name); 0528 if (!data.comment.isEmpty()) 0529 writer.writeAttribute(QStringLiteral("comment"), data.comment); 0530 if (data.sheetId != -1) { 0531 //find the local index of the sheet. 0532 for (int i=0; i<d->sheets.size(); ++i) { 0533 if (d->sheets[i]->sheetId() == data.sheetId) { 0534 writer.writeAttribute(QStringLiteral("localSheetId"), QString::number(i)); 0535 break; 0536 } 0537 } 0538 } 0539 writer.writeCharacters(data.formula); 0540 writer.writeEndElement();//definedName 0541 } 0542 writer.writeEndElement();//definedNames 0543 } 0544 0545 writer.writeStartElement(QStringLiteral("calcPr")); 0546 writer.writeAttribute(QStringLiteral("calcId"), QStringLiteral("124519")); 0547 writer.writeEndElement(); //calcPr 0548 0549 writer.writeEndElement();//workbook 0550 writer.writeEndDocument(); 0551 0552 d->relationships->addDocumentRelationship(QStringLiteral("/theme"), QStringLiteral("theme/theme1.xml")); 0553 d->relationships->addDocumentRelationship(QStringLiteral("/styles"), QStringLiteral("styles.xml")); 0554 if (!sharedStrings()->isEmpty()) 0555 d->relationships->addDocumentRelationship(QStringLiteral("/sharedStrings"), QStringLiteral("sharedStrings.xml")); 0556 } 0557 0558 bool Workbook::loadFromXmlFile(QIODevice *device) 0559 { 0560 Q_D(Workbook); 0561 0562 QXmlStreamReader reader(device); 0563 while (!reader.atEnd()) 0564 { 0565 QXmlStreamReader::TokenType token = reader.readNext(); 0566 if (token == QXmlStreamReader::StartElement) 0567 { 0568 if (reader.name() == QLatin1String("sheet")) 0569 { 0570 QXmlStreamAttributes attributes = reader.attributes(); 0571 0572 const auto& name = attributes.value(QLatin1String("name")).toString(); 0573 0574 int sheetId = attributes.value(QLatin1String("sheetId")).toInt(); 0575 0576 const auto& rId = attributes.value(QLatin1String("r:id")).toString(); 0577 0578 const auto& stateString = attributes.value(QLatin1String("state")); 0579 0580 AbstractSheet::SheetState state = AbstractSheet::SS_Visible; 0581 if (stateString == QLatin1String("hidden")) 0582 state = AbstractSheet::SS_Hidden; 0583 else if (stateString == QLatin1String("veryHidden")) 0584 state = AbstractSheet::SS_VeryHidden; 0585 0586 XlsxRelationship relationship = d->relationships->getRelationshipById(rId); 0587 0588 AbstractSheet::SheetType type = AbstractSheet::ST_WorkSheet; 0589 if (relationship.type.endsWith(QLatin1String("/worksheet"))) 0590 { 0591 type = AbstractSheet::ST_WorkSheet; 0592 } 0593 else if (relationship.type.endsWith(QLatin1String("/chartsheet"))) 0594 { 0595 type = AbstractSheet::ST_ChartSheet; 0596 } 0597 else if (relationship.type.endsWith(QLatin1String("/dialogsheet"))) 0598 { 0599 type = AbstractSheet::ST_DialogSheet; 0600 } 0601 else if (relationship.type.endsWith(QLatin1String("/xlMacrosheet"))) 0602 { 0603 type = AbstractSheet::ST_MacroSheet; 0604 } 0605 else 0606 { 0607 qWarning() << "unknown sheet type : " << relationship.type ; 0608 } 0609 0610 AbstractSheet *sheet = addSheet(name, sheetId, type); 0611 sheet->setSheetState(state); 0612 QString strFilePath = filePath(); 0613 0614 // const QString fullPath = QDir::cleanPath(splitPath(strFilePath).constFirst() + QLatin1String("/") + relationship.target); 0615 const auto parts = splitPath(strFilePath); 0616 QString fullPath = QDir::cleanPath(parts.first() + QLatin1String("/") + relationship.target); 0617 0618 sheet->setFilePath(fullPath); 0619 } 0620 else if (reader.name() == QLatin1String("workbookPr")) 0621 { 0622 QXmlStreamAttributes attrs = reader.attributes(); 0623 if (attrs.hasAttribute(QLatin1String("date1904"))) 0624 d->date1904 = true; 0625 } 0626 else if (reader.name() == QLatin1String("bookviews")) 0627 { 0628 while (!(reader.name() == QLatin1String("bookviews") && 0629 reader.tokenType() == QXmlStreamReader::EndElement)) 0630 { 0631 reader.readNextStartElement(); 0632 if (reader.tokenType() == QXmlStreamReader::StartElement) 0633 { 0634 if (reader.name() == QLatin1String("workbookView")) 0635 { 0636 QXmlStreamAttributes attrs = reader.attributes(); 0637 if (attrs.hasAttribute(QLatin1String("xWindow"))) 0638 d->x_window = attrs.value(QLatin1String("xWindow")).toInt(); 0639 if (attrs.hasAttribute(QLatin1String("yWindow"))) 0640 d->y_window = attrs.value(QLatin1String("yWindow")).toInt(); 0641 if (attrs.hasAttribute(QLatin1String("windowWidth"))) 0642 d->window_width = attrs.value(QLatin1String("windowWidth")).toInt(); 0643 if (attrs.hasAttribute(QLatin1String("windowHeight"))) 0644 d->window_height = attrs.value(QLatin1String("windowHeight")).toInt(); 0645 if (attrs.hasAttribute(QLatin1String("firstSheet"))) 0646 d->firstsheet = attrs.value(QLatin1String("firstSheet")).toInt(); 0647 if (attrs.hasAttribute(QLatin1String("activeTab"))) 0648 d->activesheetIndex = attrs.value(QLatin1String("activeTab")).toInt(); 0649 } 0650 } 0651 } 0652 } 0653 else if (reader.name() == QLatin1String("externalReference")) 0654 { 0655 QXmlStreamAttributes attributes = reader.attributes(); 0656 const QString rId = attributes.value(QLatin1String("r:id")).toString(); 0657 XlsxRelationship relationship = d->relationships->getRelationshipById(rId); 0658 0659 QSharedPointer<SimpleOOXmlFile> link(new SimpleOOXmlFile(F_LoadFromExists)); 0660 0661 const auto parts = splitPath(filePath()); 0662 QString fullPath = QDir::cleanPath(parts.first() + QLatin1String("/") + relationship.target); 0663 0664 link->setFilePath(fullPath); 0665 d->externalLinks.append(link); 0666 } else if (reader.name() == QLatin1String("definedName")) { 0667 QXmlStreamAttributes attrs = reader.attributes(); 0668 XlsxDefineNameData data; 0669 0670 data.name = attrs.value(QLatin1String("name")).toString(); 0671 if (attrs.hasAttribute(QLatin1String("comment"))) 0672 data.comment = attrs.value(QLatin1String("comment")).toString(); 0673 if (attrs.hasAttribute(QLatin1String("localSheetId"))) { 0674 int localId = attrs.value(QLatin1String("localSheetId")).toInt(); 0675 int sheetId = d->sheets.at(localId)->sheetId(); 0676 data.sheetId = sheetId; 0677 } 0678 data.formula = reader.readElementText(); 0679 d->definedNamesList.append(data); 0680 } 0681 } 0682 } 0683 return true; 0684 } 0685 0686 /*! 0687 * \internal 0688 */ 0689 QList<std::shared_ptr<MediaFile> > Workbook::mediaFiles() const 0690 { 0691 Q_D(const Workbook); 0692 0693 return d->mediaFiles; 0694 } 0695 0696 /*! 0697 * \internal 0698 */ 0699 void Workbook::addMediaFile(std::shared_ptr<MediaFile> media, bool force) 0700 { 0701 Q_D(Workbook); 0702 0703 if (!force) 0704 { 0705 for (int i=0; i<d->mediaFiles.size(); ++i) 0706 { 0707 if (d->mediaFiles[i]->hashKey() == media->hashKey()) 0708 { 0709 media->setIndex(i); 0710 return; 0711 } 0712 } 0713 } 0714 0715 media->setIndex(d->mediaFiles.size()); 0716 d->mediaFiles.append(media); 0717 } 0718 0719 /*! 0720 * \internal 0721 */ 0722 QList<QSharedPointer<Chart> > Workbook::chartFiles() const 0723 { 0724 Q_D(const Workbook); 0725 0726 return d->chartFiles; 0727 } 0728 0729 /*! 0730 * \internal 0731 */ 0732 void Workbook::addChartFile(QSharedPointer<Chart> chart) 0733 { 0734 Q_D(Workbook); 0735 0736 if (!d->chartFiles.contains(chart)) 0737 d->chartFiles.append(chart); 0738 } 0739 0740 QT_END_NAMESPACE_XLSX