use insert function instead of for loop
[LibreOffice.git] / sc / source / filter / excel / excdoc.cxx
blob7907a87223c07961bc8a0d4b26cdf3f9a54a2385
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sfx2/objsh.hxx>
21 #include <rtl/ustring.hxx>
23 #include <document.hxx>
24 #include <docsh.hxx>
25 #include <scextopt.hxx>
26 #include <docoptio.hxx>
27 #include <tabprotection.hxx>
28 #include <postit.hxx>
29 #include <root.hxx>
30 #include <connectionsbuffer.hxx>
31 #include <connectionsfragment.hxx>
33 #include <excdoc.hxx>
34 #include <xeextlst.hxx>
35 #include <biffhelper.hxx>
37 #include <xcl97rec.hxx>
38 #include <xetable.hxx>
39 #include <xelink.hxx>
40 #include <xepage.hxx>
41 #include <xeview.hxx>
42 #include <xecontent.hxx>
43 #include <xeescher.hxx>
44 #include <xepivot.hxx>
45 #include <export/SparklineExt.hxx>
46 #include <XclExpChangeTrack.hxx>
47 #include <xepivotxml.hxx>
48 #include <xedbdata.hxx>
49 #include <xlcontent.hxx>
50 #include <xlname.hxx>
51 #include <xllink.hxx>
52 #include <xltools.hxx>
54 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
55 #include <com/sun/star/frame/XModel.hpp>
56 #include <o3tl/safeint.hxx>
57 #include <oox/token/tokens.hxx>
58 #include <oox/token/namespaces.hxx>
59 #include <oox/token/relationship.hxx>
60 #include <oox/export/ThemeExport.hxx>
61 #include <docmodel/theme/Theme.hxx>
62 #include <svx/svdpage.hxx>
63 #include <memory>
65 using namespace oox;
67 static OUString lcl_GetVbaTabName( SCTAB n )
69 OUString aRet = "__VBA__" + OUString::number( static_cast<sal_uInt16>(n) );
70 return aRet;
73 static void lcl_AddBookviews( XclExpRecordList<>& aRecList, const ExcTable& self )
75 aRecList.AppendNewRecord( new XclExpXmlStartElementRecord( XML_bookViews ) );
76 aRecList.AppendNewRecord( new XclExpWindow1( self.GetRoot() ) );
77 aRecList.AppendNewRecord( new XclExpXmlEndElementRecord( XML_bookViews ) );
80 static void lcl_AddCalcPr( XclExpRecordList<>& aRecList, const ExcTable& self )
82 ScDocument& rDoc = self.GetDoc();
84 aRecList.AppendNewRecord( new XclExpXmlStartSingleElementRecord( XML_calcPr ) );
85 // OOXTODO: calcCompleted, calcId, calcMode, calcOnSave,
86 // concurrentCalc, concurrentManualCount,
87 // forceFullCalc, fullCalcOnLoad, fullPrecision
88 aRecList.AppendNewRecord( new XclCalccount( rDoc ) );
89 aRecList.AppendNewRecord( new XclRefmode( rDoc ) );
90 aRecList.AppendNewRecord( new XclIteration( rDoc ) );
91 aRecList.AppendNewRecord( new XclDelta( rDoc ) );
92 aRecList.AppendNewRecord( new XclExpBoolRecord(oox::xls::BIFF_ID_SAVERECALC, true) );
93 aRecList.AppendNewRecord( new XclExpXmlEndSingleElementRecord() ); // XML_calcPr
96 static void lcl_AddWorkbookProtection( XclExpRecordList<>& aRecList, const ExcTable& self )
98 aRecList.AppendNewRecord( new XclExpXmlStartSingleElementRecord( XML_workbookProtection ) );
100 const ScDocProtection* pProtect = self.GetDoc().GetDocProtection();
101 if (pProtect && pProtect->isProtected())
103 aRecList.AppendNewRecord( new XclExpWindowProtection(pProtect->isOptionEnabled(ScDocProtection::WINDOWS)) );
104 aRecList.AppendNewRecord( new XclExpProtection(pProtect->isOptionEnabled(ScDocProtection::STRUCTURE)) );
105 aRecList.AppendNewRecord( new XclExpPassHash(pProtect->getPasswordHash(PASSHASH_XL)) );
108 aRecList.AppendNewRecord( new XclExpXmlEndSingleElementRecord() ); // XML_workbookProtection
111 static void lcl_AddScenariosAndFilters( XclExpRecordList<>& aRecList, const XclExpRoot& rRoot, SCTAB nScTab )
113 // Scenarios
114 aRecList.AppendNewRecord( new ExcEScenarioManager( rRoot, nScTab ) );
115 // filter
116 aRecList.AppendRecord( rRoot.GetFilterManager().CreateRecord( nScTab ) );
119 ExcTable::ExcTable( const XclExpRoot& rRoot ) :
120 XclExpRoot( rRoot ),
121 mnScTab( SCTAB_GLOBAL ),
122 nExcTab( EXC_NOTAB ),
123 mxNoteList( new XclExpNoteList )
127 ExcTable::ExcTable( const XclExpRoot& rRoot, SCTAB nScTab ) :
128 XclExpRoot( rRoot ),
129 mnScTab( nScTab ),
130 nExcTab( rRoot.GetTabInfo().GetXclTab( nScTab ) ),
131 mxNoteList( new XclExpNoteList )
135 ExcTable::~ExcTable()
139 void ExcTable::Add( XclExpRecordBase* pRec )
141 OSL_ENSURE( pRec, "-ExcTable::Add(): pRec is NULL!" );
142 aRecList.AppendNewRecord( pRec );
145 void ExcTable::FillAsHeaderBinary( ExcBoundsheetList& rBoundsheetList )
147 InitializeGlobals();
149 RootData& rR = GetOldRoot();
150 ScDocument& rDoc = GetDoc();
151 XclExpTabInfo& rTabInfo = GetTabInfo();
153 if ( GetBiff() <= EXC_BIFF5 )
154 Add( new ExcBofW );
155 else
156 Add( new ExcBofW8 );
158 sal_uInt16 nExcTabCount = rTabInfo.GetXclTabCount();
159 sal_uInt16 nCodenames = static_cast< sal_uInt16 >( GetExtDocOptions().GetCodeNameCount() );
161 ScDocShell* pShell = GetDocShell();
162 sal_uInt16 nWriteProtHash = pShell ? pShell->GetModifyPasswordHash() : 0;
163 bool bRecommendReadOnly = pShell && pShell->IsLoadReadonly();
165 if( (nWriteProtHash > 0) || bRecommendReadOnly )
166 Add( new XclExpEmptyRecord( EXC_ID_WRITEPROT ) );
168 // TODO: correct codepage for BIFF5?
169 sal_uInt16 nCodePage = XclTools::GetXclCodePage( (GetBiff() <= EXC_BIFF5) ? RTL_TEXTENCODING_MS_1252 : RTL_TEXTENCODING_UNICODE );
171 if( GetBiff() <= EXC_BIFF5 )
173 Add( new XclExpEmptyRecord( EXC_ID_INTERFACEHDR ) );
174 Add( new XclExpUInt16Record( EXC_ID_MMS, 0 ) );
175 Add( new XclExpEmptyRecord( EXC_ID_TOOLBARHDR ) );
176 Add( new XclExpEmptyRecord( EXC_ID_TOOLBAREND ) );
177 Add( new XclExpEmptyRecord( EXC_ID_INTERFACEEND ) );
178 Add( new ExcDummy_00 );
180 else
182 if( IsDocumentEncrypted() )
183 Add( new XclExpFileEncryption( GetRoot() ) );
184 Add( new XclExpInterfaceHdr( nCodePage ) );
185 Add( new XclExpUInt16Record( EXC_ID_MMS, 0 ) );
186 Add( new XclExpInterfaceEnd );
187 Add( new XclExpWriteAccess );
190 Add( new XclExpFileSharing( GetRoot(), nWriteProtHash, bRecommendReadOnly ) );
191 Add( new XclExpUInt16Record( EXC_ID_CODEPAGE, nCodePage ) );
193 if( GetBiff() == EXC_BIFF8 )
195 Add( new XclExpBoolRecord( EXC_ID_DSF, false ) );
196 Add( new XclExpEmptyRecord( EXC_ID_XL9FILE ) );
197 rR.pTabId = new XclExpChTrTabId( std::max( nExcTabCount, nCodenames ) );
198 Add( rR.pTabId );
199 if( HasVbaStorage() )
201 Add( new XclObproj );
202 const OUString& rCodeName = GetExtDocOptions().GetDocSettings().maGlobCodeName;
203 if( !rCodeName.isEmpty() )
204 Add( new XclCodename( rCodeName ) );
208 Add( new XclExpUInt16Record( EXC_ID_FNGROUPCOUNT, 14 ) );
210 if ( GetBiff() <= EXC_BIFF5 )
212 // global link table: EXTERNCOUNT, EXTERNSHEET, NAME
213 aRecList.AppendRecord( CreateRecord( EXC_ID_EXTERNSHEET ) );
214 aRecList.AppendRecord( CreateRecord( EXC_ID_NAME ) );
217 // document protection options
218 lcl_AddWorkbookProtection( aRecList, *this );
220 if( GetBiff() == EXC_BIFF8 )
222 Add( new XclExpProt4Rev );
223 Add( new XclExpProt4RevPass );
226 lcl_AddBookviews( aRecList, *this );
228 Add( new XclExpXmlStartSingleElementRecord( XML_workbookPr ) );
229 if ( GetBiff() == EXC_BIFF8 && GetOutput() != EXC_OUTPUT_BINARY )
231 Add( new XclExpBoolRecord(0x0040, false, XML_backupFile ) ); // BACKUP
232 Add( new XclExpBoolRecord(0x008D, false, XML_showObjects ) ); // HIDEOBJ
235 if ( GetBiff() == EXC_BIFF8 )
237 Add( new XclExpBoolRecord(0x0040, false) ); // BACKUP
238 Add( new XclExpBoolRecord(0x008D, false) ); // HIDEOBJ
241 if( GetBiff() <= EXC_BIFF5 )
243 Add( new ExcDummy_040 );
244 Add( new Exc1904( rDoc ) );
245 Add( new ExcDummy_041 );
247 else
249 // BIFF8
250 Add( new Exc1904( rDoc ) );
251 Add( new XclExpBoolRecord( 0x000E, !rDoc.GetDocOptions().IsCalcAsShown() ) );
252 Add( new XclExpBoolRecord(0x01B7, false) ); // REFRESHALL
253 Add( new XclExpBoolRecord(0x00DA, false) ); // BOOKBOOL
256 // Formatting: FONT, FORMAT, XF, STYLE, PALETTE
257 aRecList.AppendRecord( CreateRecord( EXC_ID_FONTLIST ) );
258 aRecList.AppendRecord( CreateRecord( EXC_ID_FORMATLIST ) );
259 aRecList.AppendRecord( CreateRecord( EXC_ID_XFLIST ) );
260 aRecList.AppendRecord( CreateRecord( EXC_ID_PALETTE ) );
262 SCTAB nC;
263 SCTAB nScTabCount = rTabInfo.GetScTabCount();
264 if( GetBiff() <= EXC_BIFF5 )
266 // Bundlesheet
267 for( nC = 0 ; nC < nScTabCount ; nC++ )
268 if( rTabInfo.IsExportTab( nC ) )
270 ExcBoundsheetList::RecordRefType xBoundsheet = new ExcBundlesheet( rR, nC );
271 aRecList.AppendRecord( xBoundsheet );
272 rBoundsheetList.AppendRecord( xBoundsheet );
275 else
277 // Pivot Cache
278 GetPivotTableManager().CreatePivotTables();
279 aRecList.AppendRecord( GetPivotTableManager().CreatePivotCachesRecord() );
281 // Change tracking
282 if( rDoc.GetChangeTrack() )
284 rR.pUserBViewList = new XclExpUserBViewList( *rDoc.GetChangeTrack() );
285 Add( rR.pUserBViewList );
288 // Natural Language Formulas Flag
289 aRecList.AppendNewRecord( new XclExpBoolRecord( EXC_ID_USESELFS, GetDoc().GetDocOptions().IsLookUpColRowNames() ) );
291 // Bundlesheet
292 for( nC = 0 ; nC < nScTabCount ; nC++ )
293 if( rTabInfo.IsExportTab( nC ) )
295 ExcBoundsheetList::RecordRefType xBoundsheet = new ExcBundlesheet8( rR, nC );
296 aRecList.AppendRecord( xBoundsheet );
297 rBoundsheetList.AppendRecord( xBoundsheet );
300 OUString aTmpString;
301 for( SCTAB nAdd = 0; nC < static_cast<SCTAB>(nCodenames) ; nC++, nAdd++ )
303 aTmpString = lcl_GetVbaTabName( nAdd );
304 ExcBoundsheetList::RecordRefType xBoundsheet = new ExcBundlesheet8( aTmpString );
305 aRecList.AppendRecord( xBoundsheet );
306 rBoundsheetList.AppendRecord( xBoundsheet );
309 // COUNTRY - in BIFF8 in workbook globals
310 Add( new XclExpCountry( GetRoot() ) );
312 // link table: SUPBOOK, XCT, CRN, EXTERNNAME, EXTERNSHEET, NAME
313 aRecList.AppendRecord( CreateRecord( EXC_ID_EXTERNSHEET ) );
314 aRecList.AppendRecord( CreateRecord( EXC_ID_NAME ) );
316 Add( new XclExpRecalcId );
318 // MSODRAWINGGROUP per-document data
319 aRecList.AppendRecord( GetObjectManager().CreateDrawingGroup() );
320 // Shared string table: SST, EXTSST
321 aRecList.AppendRecord( CreateRecord( EXC_ID_SST ) );
323 Add( new XclExpBookExt );
326 Add( new ExcEof );
329 void ExcTable::FillAsHeaderXml( ExcBoundsheetList& rBoundsheetList )
331 InitializeGlobals();
333 RootData& rR = GetOldRoot();
334 ScDocument& rDoc = GetDoc();
335 XclExpTabInfo& rTabInfo = GetTabInfo();
337 sal_uInt16 nExcTabCount = rTabInfo.GetXclTabCount();
338 sal_uInt16 nCodenames = static_cast< sal_uInt16 >( GetExtDocOptions().GetCodeNameCount() );
340 rR.pTabId = new XclExpChTrTabId( std::max( nExcTabCount, nCodenames ) );
341 Add( rR.pTabId );
343 Add( new XclExpXmlStartSingleElementRecord( XML_workbookPr ) );
344 Add( new XclExpBoolRecord(0x0040, false, XML_backupFile ) ); // BACKUP
345 Add( new XclExpBoolRecord(0x008D, false, XML_showObjects ) ); // HIDEOBJ
347 Add( new Exc1904( rDoc ) );
348 // OOXTODO: The following /workbook/workbookPr attributes are mapped
349 // to various BIFF records that are not currently supported:
351 // XML_allowRefreshQuery: QSISTAG 802h: fEnableRefresh
352 // XML_autoCompressPictures: COMPRESSPICTURES 89Bh: fAutoCompressPictures
353 // XML_checkCompatibility: COMPAT12 88Ch: fNoCompatChk
354 // XML_codeName: "Calc"
355 // XML_defaultThemeVersion: ???
356 // XML_filterPrivacy: BOOKEXT 863h: fFilterPrivacy
357 // XML_hidePivotFieldList: BOOKBOOL DAh: fHidePivotTableFList
358 // XML_promptedSolutions: BOOKEXT 863h: fBuggedUserAboutSolution
359 // XML_publishItems: NAMEPUBLISH 893h: fPublished
360 // XML_saveExternalLinkValues: BOOKBOOL DAh: fNoSavSupp
361 // XML_showBorderUnselectedTables: BOOKBOOL DAh: fHideBorderUnsels
362 // XML_showInkAnnotation: BOOKEXT 863h: fShowInkAnnotation
363 // XML_showPivotChart: PIVOTCHARTBITS 859h: fGXHide??
364 // XML_updateLinks: BOOKBOOL DAh: grbitUpdateLinks
365 Add( new XclExpXmlEndSingleElementRecord() ); // XML_workbookPr
367 // Formatting: FONT, FORMAT, XF, STYLE, PALETTE
368 aRecList.AppendNewRecord( new XclExpXmlStyleSheet( *this ) );
370 // Change tracking
371 if( rDoc.GetChangeTrack() )
373 rR.pUserBViewList = new XclExpUserBViewList( *rDoc.GetChangeTrack() );
374 Add( rR.pUserBViewList );
377 lcl_AddWorkbookProtection( aRecList, *this );
378 lcl_AddBookviews( aRecList, *this );
380 // Bundlesheet
381 SCTAB nC;
382 SCTAB nScTabCount = rTabInfo.GetScTabCount();
383 aRecList.AppendNewRecord( new XclExpXmlStartElementRecord( XML_sheets ) );
384 for( nC = 0 ; nC < nScTabCount ; nC++ )
385 if( rTabInfo.IsExportTab( nC ) )
387 ExcBoundsheetList::RecordRefType xBoundsheet = new ExcBundlesheet8( rR, nC );
388 aRecList.AppendRecord( xBoundsheet );
389 rBoundsheetList.AppendRecord( xBoundsheet );
391 aRecList.AppendNewRecord( new XclExpXmlEndElementRecord( XML_sheets ) );
393 OUString aTmpString;
394 for( SCTAB nAdd = 0; nC < static_cast<SCTAB>(nCodenames) ; nC++, nAdd++ )
396 aTmpString = lcl_GetVbaTabName( nAdd );
397 ExcBoundsheetList::RecordRefType xBoundsheet = new ExcBundlesheet8( aTmpString );
398 aRecList.AppendRecord( xBoundsheet );
399 rBoundsheetList.AppendRecord( xBoundsheet );
402 // link table: SUPBOOK, XCT, CRN, EXTERNNAME, EXTERNSHEET, NAME
403 aRecList.AppendRecord( CreateRecord( EXC_ID_EXTERNSHEET ) );
404 aRecList.AppendRecord( CreateRecord( EXC_ID_NAME ) );
406 lcl_AddCalcPr( aRecList, *this );
408 // MSODRAWINGGROUP per-document data
409 aRecList.AppendRecord( GetObjectManager().CreateDrawingGroup() );
410 // Shared string table: SST, EXTSST
411 aRecList.AppendRecord( CreateRecord( EXC_ID_SST ) );
414 void ExcTable::FillAsTableBinary( SCTAB nCodeNameIdx )
416 InitializeTable( mnScTab );
418 RootData& rR = GetOldRoot();
419 XclBiff eBiff = GetBiff();
420 ScDocument& rDoc = GetDoc();
422 OSL_ENSURE( (mnScTab >= 0) && (mnScTab <= MAXTAB), "-ExcTable::Table(): mnScTab - no ordinary table!" );
423 OSL_ENSURE( nExcTab <= o3tl::make_unsigned(MAXTAB), "-ExcTable::Table(): nExcTab - no ordinary table!" );
425 // create a new OBJ list for this sheet (may be used by notes, autofilter, data validation)
426 if( eBiff == EXC_BIFF8 )
427 GetObjectManager().StartSheet();
429 // cell table: DEFROWHEIGHT, DEFCOLWIDTH, COLINFO, DIMENSIONS, ROW, cell records
430 mxCellTable = new XclExpCellTable( GetRoot() );
432 //export cell notes
433 std::vector<sc::NoteEntry> aNotes;
434 rDoc.GetAllNoteEntries(aNotes);
435 for (const auto& rNote : aNotes)
437 if (rNote.maPos.Tab() != mnScTab)
438 continue;
440 mxNoteList->AppendNewRecord(new XclExpNote(GetRoot(), rNote.maPos, rNote.mpNote, u""));
443 // WSBOOL needs data from page settings, create it here, add it later
444 rtl::Reference<XclExpPageSettings> xPageSett = new XclExpPageSettings( GetRoot() );
445 bool bFitToPages = xPageSett->GetPageData().mbFitToPages;
447 if( eBiff <= EXC_BIFF5 )
449 Add( new ExcBof );
450 Add( new ExcDummy_02a );
452 else
454 Add( new ExcBof8 );
455 lcl_AddCalcPr( aRecList, *this );
458 // GUTS (count & size of outline icons)
459 aRecList.AppendRecord( mxCellTable->CreateRecord( EXC_ID_GUTS ) );
460 // DEFROWHEIGHT, created by the cell table
461 aRecList.AppendRecord( mxCellTable->CreateRecord( EXC_ID2_DEFROWHEIGHT ) );
463 // COUNTRY - in BIFF5/7 in every worksheet
464 if( eBiff <= EXC_BIFF5 )
465 Add( new XclExpCountry( GetRoot() ) );
467 Add( new XclExpWsbool( bFitToPages ) );
469 // page settings (SETUP and various other records)
470 aRecList.AppendRecord( xPageSett );
472 const ScTableProtection* pTabProtect = rDoc.GetTabProtection(mnScTab);
473 if (pTabProtect && pTabProtect->isProtected())
475 Add( new XclExpProtection(true) );
476 Add( new XclExpBoolRecord(oox::xls::BIFF_ID_SCENPROTECT, pTabProtect->isOptionEnabled(ScTableProtection::SCENARIOS)) );
477 if (pTabProtect->isOptionEnabled(ScTableProtection::OBJECTS))
478 Add( new XclExpBoolRecord(oox::xls::BIFF_ID_OBJECTPROTECT, true ));
479 Add( new XclExpPassHash(pTabProtect->getPasswordHash(PASSHASH_XL)) );
482 // local link table: EXTERNCOUNT, EXTERNSHEET
483 if( eBiff <= EXC_BIFF5 )
484 aRecList.AppendRecord( CreateRecord( EXC_ID_EXTERNSHEET ) );
486 if ( eBiff == EXC_BIFF8 )
487 lcl_AddScenariosAndFilters( aRecList, GetRoot(), mnScTab );
489 // cell table: DEFCOLWIDTH, COLINFO, DIMENSIONS, ROW, cell records
490 aRecList.AppendRecord( mxCellTable );
492 // MERGEDCELLS record, generated by the cell table
493 aRecList.AppendRecord( mxCellTable->CreateRecord( EXC_ID_MERGEDCELLS ) );
494 // label ranges
495 if( eBiff == EXC_BIFF8 )
496 Add( new XclExpLabelranges( GetRoot() ) );
497 // data validation (DVAL and list of DV records), generated by the cell table
498 aRecList.AppendRecord( mxCellTable->CreateRecord( EXC_ID_DVAL ) );
500 if( eBiff == EXC_BIFF8 )
502 // all MSODRAWING and OBJ stuff of this sheet goes here
503 aRecList.AppendRecord( GetObjectManager().ProcessDrawing( GetSdrPage( mnScTab ) ) );
504 // pivot tables
505 aRecList.AppendRecord( GetPivotTableManager().CreatePivotTablesRecord( mnScTab ) );
508 // list of NOTE records, generated by the cell table
509 aRecList.AppendRecord( mxNoteList );
511 // sheet view settings: WINDOW2, SCL, PANE, SELECTION
512 aRecList.AppendNewRecord( new XclExpTabViewSettings( GetRoot(), mnScTab ) );
514 if( eBiff == EXC_BIFF8 )
516 // sheet protection options
517 Add( new XclExpSheetProtectOptions( GetRoot(), mnScTab ) );
519 // enhanced protections if there are
520 if (pTabProtect)
522 const ::std::vector<ScEnhancedProtection>& rProts( pTabProtect->getEnhancedProtection());
523 for (const auto& rProt : rProts)
525 Add( new XclExpSheetEnhancedProtection( GetRoot(), rProt));
529 // web queries
530 Add( new XclExpWebQueryBuffer( GetRoot() ) );
532 // conditional formats
533 Add( new XclExpCondFormatBuffer( GetRoot(), XclExtLstRef() ) );
535 if( HasVbaStorage() )
536 if( nCodeNameIdx < GetExtDocOptions().GetCodeNameCount() )
537 Add( new XclCodename( GetExtDocOptions().GetCodeName( nCodeNameIdx ) ) );
540 // list of HLINK records, generated by the cell table
541 aRecList.AppendRecord( mxCellTable->CreateRecord( EXC_ID_HLINK ) );
543 // change tracking
544 if( rR.pUserBViewList )
546 XclExpUserBViewList::const_iterator iter;
547 for ( iter = rR.pUserBViewList->cbegin(); iter != rR.pUserBViewList->cend(); ++iter)
549 Add( new XclExpUsersViewBegin( (*iter).GetGUID(), nExcTab ) );
550 Add( new XclExpUsersViewEnd );
554 // EOF
555 Add( new ExcEof );
558 void ExcTable::FillAsTableXml()
560 InitializeTable( mnScTab );
562 ScDocument& rDoc = GetDoc();
564 OSL_ENSURE( (mnScTab >= 0) && (mnScTab <= MAXTAB), "-ExcTable::Table(): mnScTab - no ordinary table!" );
565 OSL_ENSURE( nExcTab <= o3tl::make_unsigned(MAXTAB), "-ExcTable::Table(): nExcTab - no ordinary table!" );
567 // create a new OBJ list for this sheet (may be used by notes, autofilter, data validation)
568 GetObjectManager().StartSheet();
570 // cell table: DEFROWHEIGHT, DEFCOLWIDTH, COLINFO, DIMENSIONS, ROW, cell records
571 mxCellTable = new XclExpCellTable( GetRoot() );
573 //export cell notes
574 std::vector<sc::NoteEntry> aNotes;
575 rDoc.GetAllNoteEntries(aNotes);
576 for (const auto& rNote : aNotes)
578 if (rNote.maPos.Tab() != mnScTab)
579 continue;
581 mxNoteList->AppendNewRecord(new XclExpNote(GetRoot(), rNote.maPos, rNote.mpNote, u""));
584 // WSBOOL needs data from page settings, create it here, add it later
585 rtl::Reference<XclExpPageSettings> xPageSett = new XclExpPageSettings( GetRoot() );
586 XclExtLstRef xExtLst = new XclExtLst( GetRoot() );
587 bool bFitToPages = xPageSett->GetPageData().mbFitToPages;
589 bool bSummaryBelow = GetRoot().GetDoc().GetTotalsRowBelow(mnScTab);
590 Color aTabColor = GetRoot().GetDoc().GetTabBgColor(mnScTab);
591 Add(new XclExpXmlSheetPr(bFitToPages, mnScTab, aTabColor, bSummaryBelow, &GetFilterManager()));
593 // GUTS (count & size of outline icons)
594 aRecList.AppendRecord( mxCellTable->CreateRecord( EXC_ID_GUTS ) );
595 // DEFROWHEIGHT, created by the cell table
596 aRecList.AppendRecord( mxCellTable->CreateRecord( EXC_ID2_DEFROWHEIGHT ) );
598 aRecList.AppendRecord( mxCellTable->CreateRecord( EXC_ID3_DIMENSIONS ) );
600 // sheet view settings: WINDOW2, SCL, PANE, SELECTION
601 aRecList.AppendNewRecord( new XclExpTabViewSettings( GetRoot(), mnScTab ) );
603 // cell table: DEFCOLWIDTH, COLINFO, DIMENSIONS, ROW, cell records
604 aRecList.AppendRecord( mxCellTable );
606 // list of NOTE records, generated by the cell table
607 // not in the worksheet file
608 if( mxNoteList != nullptr && !mxNoteList->IsEmpty() )
609 aRecList.AppendNewRecord( new XclExpComments( mnScTab, *mxNoteList ) );
611 const ScTableProtection* pTabProtect = rDoc.GetTabProtection(mnScTab);
612 if (pTabProtect && pTabProtect->isProtected())
613 Add( new XclExpSheetProtection(true, mnScTab) );
615 lcl_AddScenariosAndFilters( aRecList, GetRoot(), mnScTab );
617 // MERGEDCELLS record, generated by the cell table
618 aRecList.AppendRecord( mxCellTable->CreateRecord( EXC_ID_MERGEDCELLS ) );
620 // conditional formats
621 Add( new XclExpCondFormatBuffer( GetRoot(), xExtLst ) );
623 Add(new xcl::exp::SparklineBuffer(GetRoot(), xExtLst));
625 // data validation (DVAL and list of DV records), generated by the cell table
626 aRecList.AppendRecord( mxCellTable->CreateRecord( EXC_ID_DVAL ) );
628 // list of HLINK records, generated by the cell table
629 XclExpRecordRef xHyperlinks = mxCellTable->CreateRecord( EXC_ID_HLINK );
630 XclExpHyperlinkList* pHyperlinkList = dynamic_cast<XclExpHyperlinkList*>(xHyperlinks.get());
631 if( pHyperlinkList != nullptr && !pHyperlinkList->IsEmpty() )
633 aRecList.AppendNewRecord( new XclExpXmlStartElementRecord( XML_hyperlinks ) );
634 aRecList.AppendRecord( xHyperlinks );
635 aRecList.AppendNewRecord( new XclExpXmlEndElementRecord( XML_hyperlinks ) );
638 aRecList.AppendRecord( xPageSett );
640 // all MSODRAWING and OBJ stuff of this sheet goes here
641 aRecList.AppendRecord( GetObjectManager().ProcessDrawing( GetSdrPage( mnScTab ) ) );
643 XclExpImgData* pImgData = xPageSett->getGraphicExport();
644 if (pImgData)
645 aRecList.AppendRecord(pImgData);
647 // <tableParts> after <drawing> and before <extLst>
648 aRecList.AppendRecord( GetTablesManager().GetTablesBySheet( mnScTab));
650 aRecList.AppendRecord( xExtLst );
653 void ExcTable::FillAsEmptyTable( SCTAB nCodeNameIdx )
655 InitializeTable( mnScTab );
657 if( !(HasVbaStorage() && (nCodeNameIdx < GetExtDocOptions().GetCodeNameCount())) )
658 return;
660 if( GetBiff() <= EXC_BIFF5 )
662 Add( new ExcBof );
664 else
666 Add( new ExcBof8 );
667 Add( new XclCodename( GetExtDocOptions().GetCodeName( nCodeNameIdx ) ) );
669 // sheet view settings: WINDOW2, SCL, PANE, SELECTION
670 aRecList.AppendNewRecord( new XclExpTabViewSettings( GetRoot(), mnScTab ) );
671 Add( new ExcEof );
674 void ExcTable::Write( XclExpStream& rStrm )
676 SetCurrScTab( mnScTab );
677 if( mxCellTable )
678 mxCellTable->Finalize(true);
679 aRecList.Save( rStrm );
682 void ExcTable::WriteXml( XclExpXmlStream& rStrm )
684 if (!GetTabInfo().IsExportTab(mnScTab))
686 // header export.
687 SetCurrScTab(mnScTab);
688 if (mxCellTable)
689 mxCellTable->Finalize(false);
690 aRecList.SaveXml(rStrm);
692 return;
695 // worksheet export
696 OUString sSheetName = XclXmlUtils::GetStreamName( "xl/", "worksheets/sheet", mnScTab+1 );
698 sax_fastparser::FSHelperPtr pWorksheet = rStrm.GetStreamForPath( sSheetName );
700 rStrm.PushStream( pWorksheet );
702 pWorksheet->startElement( XML_worksheet,
703 XML_xmlns, rStrm.getNamespaceURL(OOX_NS(xls)),
704 FSNS(XML_xmlns, XML_r), rStrm.getNamespaceURL(OOX_NS(officeRel)),
705 FSNS(XML_xmlns, XML_xdr), "http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing", // rStrm.getNamespaceURL(OOX_NS(xm)) -> "http://schemas.microsoft.com/office/excel/2006/main",
706 FSNS(XML_xmlns, XML_x14), rStrm.getNamespaceURL(OOX_NS(xls14Lst)),
707 FSNS(XML_xmlns, XML_xr2), rStrm.getNamespaceURL(OOX_NS(xr2)),
708 FSNS(XML_xmlns, XML_mc), rStrm.getNamespaceURL(OOX_NS(mce)));
710 SetCurrScTab( mnScTab );
711 if (mxCellTable)
712 mxCellTable->Finalize(false);
713 aRecList.SaveXml( rStrm );
715 XclExpXmlPivotTables* pPT = GetXmlPivotTableManager().GetTablesBySheet(mnScTab);
716 if (pPT)
717 pPT->SaveXml(rStrm);
719 rStrm.GetCurrentStream()->endElement( XML_worksheet );
720 rStrm.PopStream();
723 ExcDocument::ExcDocument( const XclExpRoot& rRoot ) :
724 XclExpRoot( rRoot ),
725 aHeader( rRoot )
729 ExcDocument::~ExcDocument()
731 maTableList.RemoveAllRecords(); // for the following assertion!
734 void ExcDocument::ReadDoc()
736 InitializeConvert();
738 if (GetOutput() == EXC_OUTPUT_BINARY)
739 aHeader.FillAsHeaderBinary(maBoundsheetList);
740 else
742 aHeader.FillAsHeaderXml(maBoundsheetList);
743 GetXmlPivotTableManager().Initialize();
744 GetTablesManager().Initialize(); // Move outside conditions if we wanted to support BIFF.
747 SCTAB nScTab = 0, nScTabCount = GetTabInfo().GetScTabCount();
748 SCTAB nCodeNameIdx = 0, nCodeNameCount = GetExtDocOptions().GetCodeNameCount();
750 for( ; nScTab < nScTabCount; ++nScTab )
752 if( GetTabInfo().IsExportTab( nScTab ) )
754 ExcTableList::RecordRefType xTab = new ExcTable( GetRoot(), nScTab );
755 maTableList.AppendRecord( xTab );
756 if (GetOutput() == EXC_OUTPUT_BINARY)
757 xTab->FillAsTableBinary(nCodeNameIdx);
758 else
759 xTab->FillAsTableXml();
761 ++nCodeNameIdx;
764 for( ; nCodeNameIdx < nCodeNameCount; ++nScTab, ++nCodeNameIdx )
766 ExcTableList::RecordRefType xTab = new ExcTable( GetRoot(), nScTab );
767 maTableList.AppendRecord( xTab );
768 xTab->FillAsEmptyTable( nCodeNameIdx );
771 if ( GetBiff() == EXC_BIFF8 )
773 // complete temporary Escher stream
774 GetObjectManager().EndDocument();
776 // change tracking
777 if ( GetDoc().GetChangeTrack() )
778 m_xExpChangeTrack.reset(new XclExpChangeTrack( GetRoot() ));
782 void ExcDocument::Write( SvStream& rSvStrm )
784 if( !maTableList.IsEmpty() )
786 InitializeSave();
788 XclExpStream aXclStrm( rSvStrm, GetRoot() );
790 aHeader.Write( aXclStrm );
792 OSL_ENSURE( maTableList.GetSize() == maBoundsheetList.GetSize(),
793 "ExcDocument::Write - different number of sheets and BOUNDSHEET records" );
795 for( size_t nTab = 0, nTabCount = maTableList.GetSize(); nTab < nTabCount; ++nTab )
797 // set current stream position in BOUNDSHEET record
798 ExcBoundsheetRef xBoundsheet = maBoundsheetList.GetRecord( nTab );
799 if( xBoundsheet )
800 xBoundsheet->SetStreamPos( aXclStrm.GetSvStreamPos() );
801 // write the table
802 maTableList.GetRecord( nTab )->Write( aXclStrm );
805 // write the table stream positions into the BOUNDSHEET records
806 for( size_t nBSheet = 0, nBSheetCount = maBoundsheetList.GetSize(); nBSheet < nBSheetCount; ++nBSheet )
807 maBoundsheetList.GetRecord( nBSheet )->UpdateStreamPos( aXclStrm );
809 if( m_xExpChangeTrack )
810 m_xExpChangeTrack->Write();
813 void ExcDocument::WriteXml( XclExpXmlStream& rStrm )
815 ScDocShell* pDocShell = GetDocShell();
817 using namespace ::com::sun::star;
818 uno::Reference<document::XDocumentPropertiesSupplier> xDPS( static_cast<cppu::OWeakObject*>(pDocShell->GetModel()), uno::UNO_QUERY_THROW );
819 uno::Reference<document::XDocumentProperties> xDocProps = xDPS->getDocumentProperties();
821 OUString sUserName = GetUserName();
822 sal_uInt32 nWriteProtHash = pDocShell->GetModifyPasswordHash();
823 bool bHasPasswordHash = nWriteProtHash && !sUserName.isEmpty();
824 const uno::Sequence<beans::PropertyValue> aInfo = pDocShell->GetModifyPasswordInfo();
825 OUString sAlgorithm, sSalt, sHash;
826 sal_Int32 nCount = 0;
827 for (const auto& prop : aInfo)
829 if (prop.Name == "algorithm-name")
830 prop.Value >>= sAlgorithm;
831 else if (prop.Name == "salt")
832 prop.Value >>= sSalt;
833 else if (prop.Name == "iteration-count")
834 prop.Value >>= nCount;
835 else if (prop.Name == "hash")
836 prop.Value >>= sHash;
838 bool bHasPasswordInfo
839 = sAlgorithm != "PBKDF2" && !sSalt.isEmpty() && !sHash.isEmpty() && !sUserName.isEmpty();
840 rStrm.exportDocumentProperties(xDocProps, pDocShell->IsSecurityOptOpenReadOnly()
841 && !bHasPasswordHash && !bHasPasswordInfo);
842 rStrm.exportCustomFragments();
844 sax_fastparser::FSHelperPtr& rWorkbook = rStrm.GetCurrentStream();
845 rWorkbook->startElement( XML_workbook,
846 XML_xmlns, rStrm.getNamespaceURL(OOX_NS(xls)),
847 FSNS(XML_xmlns, XML_r), rStrm.getNamespaceURL(OOX_NS(officeRel)) );
848 rWorkbook->singleElement( XML_fileVersion,
849 XML_appName, "Calc"
850 // OOXTODO: XML_codeName
851 // OOXTODO: XML_lastEdited
852 // OOXTODO: XML_lowestEdited
853 // OOXTODO: XML_rupBuild
856 if (bHasPasswordHash)
857 rWorkbook->singleElement(XML_fileSharing,
858 XML_userName, sUserName,
859 XML_reservationPassword, OString::number(nWriteProtHash, 16));
860 else if (bHasPasswordInfo)
861 rWorkbook->singleElement(XML_fileSharing,
862 XML_userName, sUserName,
863 XML_algorithmName, sAlgorithm,
864 XML_hashValue, sHash,
865 XML_saltValue, sSalt,
866 XML_spinCount, OString::number(nCount));
868 if( !maTableList.IsEmpty() )
870 InitializeSave();
872 auto* pDrawLayer = GetDoc().GetDrawLayer();
873 if (pDrawLayer)
875 std::shared_ptr<model::Theme> pTheme = pDrawLayer->getTheme();
876 if (pTheme)
878 OUString sThemeRelationshipPath = u"theme/theme1.xml"_ustr;
879 OUString sThemeDocumentPath = "xl/" + sThemeRelationshipPath;
881 oox::ThemeExport aThemeExport(&rStrm, oox::drawingml::DOCUMENT_XLSX);
882 aThemeExport.write(sThemeDocumentPath, *pTheme);
884 // xl/_rels/workbook.xml.rels
885 // TODO: check if Theme import & export work correctly
886 rStrm.addRelation(rStrm.GetCurrentStream()->getOutputStream(),
887 oox::getRelationship(Relationship::THEME),
888 sThemeRelationshipPath);
892 aHeader.WriteXml( rStrm );
894 for( size_t nTab = 0, nTabCount = maTableList.GetSize(); nTab < nTabCount; ++nTab )
896 // write the table
897 maTableList.GetRecord( nTab )->WriteXml( rStrm );
901 if( m_xExpChangeTrack )
902 m_xExpChangeTrack->WriteXml( rStrm );
904 XclExpXmlPivotCaches& rCaches = GetXmlPivotTableManager().GetCaches();
905 if (rCaches.HasCaches())
906 rCaches.SaveXml(rStrm);
908 const ScCalcConfig& rCalcConfig = GetDoc().GetCalcConfig();
909 formula::FormulaGrammar::AddressConvention eConv = rCalcConfig.meStringRefAddressSyntax;
911 // don't save "unspecified" string ref syntax ... query formula grammar
912 // and save that instead
913 if( eConv == formula::FormulaGrammar::CONV_UNSPECIFIED)
915 eConv = GetDoc().GetAddressConvention();
918 ScDocument& rDoc = GetDoc();
919 bool connectionXml = rDoc.hasConnectionXml();
921 if (connectionXml)
923 // save xl/connections.xml reference into [Content_Types].xml
924 sax_fastparser::FSHelperPtr aConnectionsXml = rStrm.CreateOutputStream(
925 "xl/connections.xml", u"connections.xml", rStrm.GetCurrentStream()->getOutputStream(),
926 "application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml",
927 oox::getRelationship(Relationship::CONNECTIONS));
928 rStrm.PushStream(aConnectionsXml);
931 <connections
932 xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"
933 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
934 xmlns:xr16="http://schemas.microsoft.com/office/spreadsheetml/2017/revision16"
935 mc:Ignorable="xr16">
938 // write into xl/connections.xml
939 // export <connections>
940 aConnectionsXml->startElement(
941 XML_connections, XML_xmlns, rStrm.getNamespaceURL(OOX_NS(xls)), FSNS(XML_xmlns, XML_mc),
942 rStrm.getNamespaceURL(OOX_NS(mce)), FSNS(XML_xmlns, XML_xr16),
943 rStrm.getNamespaceURL(OOX_NS(xr16)), FSNS(XML_mc, XML_Ignorable), "xr16");
945 // get a list of <connection> element and export it with its child elements
946 ConnectionVector vConnVector = rDoc.getConnectionVector();
947 for (const auto& rConnection : vConnVector)
949 const oox::xls::ConnectionModel& rModel = rConnection->getModel();
951 if (rModel.mnId == -1 || rModel.mnRefreshedVersion == -1)
952 continue; // incorrect values, skip
954 rtl::Reference<sax_fastparser::FastAttributeList> pAttrList
955 = sax_fastparser::FastSerializerHelper::createAttrList();
957 pAttrList->add(XML_id, OUString::number(rModel.mnId));
959 if (!rModel.maXr16Uid.isEmpty())
960 pAttrList->add(FSNS(XML_xr16, XML_uid), rModel.maXr16Uid);
961 if (!rModel.maSourceFile.isEmpty())
962 pAttrList->add(XML_sourceFile, rModel.maSourceFile);
963 if (!rModel.maSourceConnFile.isEmpty())
964 pAttrList->add(XML_odcFile, rModel.maSourceConnFile);
966 pAttrList->add(XML_keepAlive, ToPsz10(rModel.mbKeepAlive));
967 pAttrList->add(XML_interval, OUString::number(rModel.mnInterval));
969 if (!rModel.maName.isEmpty())
970 pAttrList->add(XML_name, rModel.maName);
971 if (!rModel.maDescription.isEmpty())
972 pAttrList->add(XML_description, rModel.maDescription);
973 if (OUString::number(rModel.mnType).length > 0)
974 pAttrList->add(XML_type, OUString::number(rModel.mnType));
976 pAttrList->add(XML_reconnectionMethod, OUString::number(rModel.mnReconnectMethod));
977 pAttrList->add(XML_refreshedVersion, OUString::number(rModel.mnRefreshedVersion));
978 pAttrList->add(XML_minRefreshableVersion,
979 OUString::number(rModel.mnMinRefreshableVersion));
980 pAttrList->add(XML_savePassword, ToPsz10(rModel.mbSavePassword));
981 pAttrList->add(XML_new, ToPsz10(rModel.mbNew));
982 pAttrList->add(XML_deleted, ToPsz10(rModel.mbDeleted));
983 pAttrList->add(XML_onlyUseConnectionFile, ToPsz10(rModel.mbOnlyUseConnFile));
984 pAttrList->add(XML_background, ToPsz10(rModel.mbBackground));
985 pAttrList->add(XML_refreshOnLoad, ToPsz10(rModel.mbRefreshOnLoad));
986 pAttrList->add(XML_saveData, ToPsz10(rModel.mbSaveData));
988 // import credentials="" attribute of <connection> element
989 if (rModel.mnCredentials != -1)
991 sal_Int32 nToken = rModel.mnCredentials;
992 OUString nValue;
994 switch (nToken)
996 case XML_none:
997 nValue = "none";
998 break;
999 case XML_stored:
1000 nValue = "stored";
1001 break;
1002 case XML_prompt:
1003 nValue = "prompt";
1004 break;
1005 default:
1006 nValue = "integrated";
1007 break;
1010 pAttrList->add(XML_credentials, nValue);
1013 if (!rModel.maSsoId.isEmpty())
1014 pAttrList->add(XML_singleSignOnId, rModel.maSsoId);
1016 // export <connection> with attributes
1017 rStrm.GetCurrentStream()->startElement(XML_connection, pAttrList);
1020 start export child elements of <connection>
1022 <xsd:sequence>
1023 <xsd:element name="dbPr" minOccurs="0" maxOccurs="1" type="CT_DbPr"/>
1024 <xsd:element name="olapPr" minOccurs="0" maxOccurs="1" type="CT_OlapPr"/>
1025 <xsd:element name="webPr" minOccurs="0" maxOccurs="1" type="CT_WebPr"/>
1026 <xsd:element name="textPr" minOccurs="0" maxOccurs="1" type="CT_TextPr"/>
1027 <xsd:element name="parameters" minOccurs="0" maxOccurs="1" type="CT_Parameters"/>
1028 <xsd:element name="extLst" minOccurs="0" maxOccurs="1" type="CT_ExtensionList"/>
1029 </xsd:sequence>
1032 { // export <dbPr>
1034 rtl::Reference<sax_fastparser::FastAttributeList> pAttrListDbPr
1035 = sax_fastparser::FastSerializerHelper::createAttrList();
1037 css::uno::Sequence<css::uno::Any> aSeqs = rConnection->getDbPrSequenceAny();
1038 addElemensToAttrList(pAttrListDbPr, aSeqs);
1040 rStrm.GetCurrentStream()->singleElement(XML_dbPr, pAttrListDbPr);
1043 { // export <olapPr>
1045 rtl::Reference<sax_fastparser::FastAttributeList> pAttrListOlapPr
1046 = sax_fastparser::FastSerializerHelper::createAttrList();
1048 css::uno::Sequence<css::uno::Any> aSeqs = rConnection->getOlapPrSequenceAny();
1049 addElemensToAttrList(pAttrListOlapPr, aSeqs);
1051 // this prints empty <olapPr/> even if aSeqs is empty, TODO: check if aSeqs is empty
1052 rStrm.GetCurrentStream()->singleElement(XML_olapPr, pAttrListOlapPr);
1055 { // export <webPr> and its child elements
1056 rtl::Reference<sax_fastparser::FastAttributeList> pAttrListWebPr
1057 = sax_fastparser::FastSerializerHelper::createAttrList();
1059 if (rModel.mxWebPr)
1061 pAttrListWebPr->add(XML_xml, ToPsz10(rModel.mxWebPr->mbXml));
1062 pAttrListWebPr->add(XML_sourceData, ToPsz10(rModel.mxWebPr->mbSourceData));
1063 pAttrListWebPr->add(XML_parsePre, ToPsz10(rModel.mxWebPr->mbParsePre));
1064 pAttrListWebPr->add(XML_consecutive, ToPsz10(rModel.mxWebPr->mbConsecutive));
1065 pAttrListWebPr->add(XML_firstRow, ToPsz10(rModel.mxWebPr->mbFirstRow));
1066 pAttrListWebPr->add(XML_xl97, ToPsz10(rModel.mxWebPr->mbXl97Created));
1067 pAttrListWebPr->add(XML_textDates, ToPsz10(rModel.mxWebPr->mbTextDates));
1068 pAttrListWebPr->add(XML_xl2000, ToPsz10(rModel.mxWebPr->mbXl2000Refreshed));
1069 pAttrListWebPr->add(XML_htmlTables, ToPsz10(rModel.mxWebPr->mbHtmlTables));
1071 if (!rModel.mxWebPr->maUrl.isEmpty())
1072 pAttrListWebPr->add(XML_url, rModel.mxWebPr->maUrl);
1073 if (!rModel.mxWebPr->maPostMethod.isEmpty())
1074 pAttrListWebPr->add(XML_post, rModel.mxWebPr->maPostMethod);
1075 if (!rModel.mxWebPr->maEditPage.isEmpty())
1076 pAttrListWebPr->add(XML_editPage, rModel.mxWebPr->maEditPage);
1078 // import htmlFormat="" attribute of <webPr> element
1079 if (rModel.mxWebPr->mnHtmlFormat != -1)
1081 sal_Int32 nToken = rModel.mxWebPr->mnHtmlFormat;
1082 OUString nValue;
1084 switch (nToken)
1086 case XML_all:
1087 nValue = "all";
1088 break;
1089 case XML_rtf:
1090 nValue = "rtf";
1091 break;
1092 default:
1093 nValue = "none";
1094 break;
1097 pAttrListWebPr->add(XML_htmlFormat, nValue);
1100 // export <webPr> with attributes
1101 rStrm.GetCurrentStream()->startElement(XML_webPr, pAttrListWebPr);
1103 { // export <tables> and its child elements
1105 rtl::Reference<sax_fastparser::FastAttributeList> pAttrListTables
1106 = sax_fastparser::FastSerializerHelper::createAttrList();
1108 // <tables count="<xsd:unsignedInt>">
1109 if (rModel.mxWebPr->mnCount >= 0)
1111 pAttrListTables->add(XML_count,
1112 OUString::number(rModel.mxWebPr->mnCount));
1114 // export <tables> with attributes
1115 rStrm.GetCurrentStream()->startElement(XML_tables, pAttrListTables);
1117 { // export <m>, <s> and <x> elements
1118 for (auto& tableElement : rModel.mxWebPr->maTables)
1120 OUString sElement;
1121 tableElement >>= sElement;
1122 OUString token = sElement.getToken(0, ',');
1123 OUString attributeValue = sElement.getToken(1, ',');
1125 if (token == "s")
1126 rStrm.GetCurrentStream()->singleElement(XML_s, XML_v,
1127 attributeValue);
1128 else if (token == "x")
1129 rStrm.GetCurrentStream()->singleElement(XML_x, XML_v,
1130 attributeValue);
1131 else
1132 rStrm.GetCurrentStream()->singleElement(XML_m);
1136 // put </tables>
1137 rStrm.GetCurrentStream()->endElement(XML_tables);
1141 // put </webPr>
1142 rStrm.GetCurrentStream()->endElement(XML_webPr);
1146 { // export <textPr>
1148 rtl::Reference<sax_fastparser::FastAttributeList> pAttrListTextPr
1149 = sax_fastparser::FastSerializerHelper::createAttrList();
1151 if (rModel.mxTextPr)
1153 addElemensToAttrList(pAttrListTextPr, rModel.mxTextPr->maTextPrSequenceAny);
1155 rStrm.GetCurrentStream()->startElement(XML_textPr, pAttrListTextPr);
1157 { // export <textFields>
1158 rtl::Reference<sax_fastparser::FastAttributeList> pAttrListTextFields
1159 = sax_fastparser::FastSerializerHelper::createAttrList();
1161 addElemensToAttrList(pAttrListTextFields,
1162 rModel.mxTextPr->maTextFieldsSequenceAny);
1164 rStrm.GetCurrentStream()->startElement(XML_textFields, pAttrListTextFields);
1166 { // export <textField>
1168 for (auto& textFieldAttr : rModel.mxTextPr->vTextField)
1170 rtl::Reference<sax_fastparser::FastAttributeList> pAttrListTextField
1171 = sax_fastparser::FastSerializerHelper::createAttrList();
1173 addElemensToAttrList(pAttrListTextField, textFieldAttr);
1175 rStrm.GetCurrentStream()->singleElement(XML_textField,
1176 pAttrListTextField);
1180 // put </textFields>
1181 rStrm.GetCurrentStream()->endElement(XML_textFields);
1184 // put </textPr>
1185 rStrm.GetCurrentStream()->endElement(XML_textPr);
1189 { // export <parameters>
1191 rtl::Reference<sax_fastparser::FastAttributeList> pAttrListParameters
1192 = sax_fastparser::FastSerializerHelper::createAttrList();
1194 if (rModel.mxParameters && rModel.mxParameters->mnCount > -1)
1196 pAttrListParameters->add(XML_count,
1197 OUString::number(rModel.mxParameters->mnCount));
1199 rStrm.GetCurrentStream()->startElement(XML_parameters, pAttrListParameters);
1201 // export <parameter>
1202 for (auto& parameterAttr : rModel.mxParameters->vParameter)
1204 rtl::Reference<sax_fastparser::FastAttributeList> pAttrListParameter
1205 = sax_fastparser::FastSerializerHelper::createAttrList();
1207 addElemensToAttrList(pAttrListParameter, parameterAttr);
1209 rStrm.GetCurrentStream()->singleElement(XML_parameter, pAttrListParameter);
1212 // put </parameters>
1213 rStrm.GetCurrentStream()->endElement(XML_parameters);
1217 { // export <extLst>
1218 if (rModel.mxExtensionList)
1220 // put <extLst>, it has no attributes
1221 rStrm.GetCurrentStream()->startElement(XML_extLst);
1223 // export uri attribute of <ext> element
1224 for (auto& uriValue : rModel.mxExtensionList->vExtension)
1226 // export <ext> with uri attribute.
1227 rStrm.GetCurrentStream()->startElement(XML_ext, XML_uri, uriValue);
1230 TODO: export child elements of <ext>. We should export "any element in any namespace", which seems challenging.
1232 <extLst>
1233 <ext>
1234 (Any element in any namespace)
1235 </ext>
1236 </extLst>
1239 // put </ext>
1240 rStrm.GetCurrentStream()->endElement(XML_ext);
1243 // put </extLst>
1244 rStrm.GetCurrentStream()->endElement(XML_extLst);
1248 // put </connection>
1249 rStrm.GetCurrentStream()->endElement(XML_connection);
1252 // put </connections>
1253 aConnectionsXml->endElement(XML_connections);
1254 rStrm.PopStream();
1257 if (rDoc.hasCustomXml())
1259 // export customXml/item1.xml into xl/_rels/workbook.xml.rels
1260 OUString sCustomXmlPath = OUString::Concat("../") + rDoc.getCustomXmlItems();
1262 // FIXME: what if there are customXml/item2.xml, customXml/item3.xml etc?
1263 // we need to save all customXml/item*.xml paths into ScDocument from XmlFilterBase::importCustomFragments
1264 // then we should get them with rDoc here.
1265 rStrm.addRelation(rStrm.GetCurrentStream()->getOutputStream(),
1266 oox::getRelationship(Relationship::CUSTOMXML), sCustomXmlPath);
1269 // write if it has been read|imported or explicitly changed
1270 // or if ref syntax isn't what would be native for our file format
1271 // i.e. ExcelA1 in this case
1272 if ( rCalcConfig.mbHasStringRefSyntax ||
1273 (eConv != formula::FormulaGrammar::CONV_XL_A1) )
1275 XclExtLstRef xExtLst = new XclExtLst( GetRoot() );
1276 xExtLst->AddRecord( new XclExpExtCalcPr( GetRoot(), eConv ) );
1277 xExtLst->SaveXml(rStrm);
1280 rWorkbook->endElement( XML_workbook );
1281 rWorkbook.reset();
1284 void ExcDocument::addElemensToAttrList(rtl::Reference<sax_fastparser::FastAttributeList>& pAttrList,
1285 css::uno::Sequence<css::uno::Any>& aSeqs)
1287 css::uno::Sequence<css::xml::FastAttribute> aFastSeq;
1288 css::uno::Sequence<css::xml::Attribute> aUnkSeq;
1290 // TODO: check if aSeqs is empty or not
1291 for (const auto& a : aSeqs)
1293 if (a >>= aFastSeq)
1295 for (const auto& rAttr : aFastSeq)
1296 pAttrList->add(rAttr.Token, rAttr.Value);
1298 else if (a >>= aUnkSeq)
1300 for (const auto& rAttr : aUnkSeq)
1301 pAttrList->addUnknown(rAttr.NamespaceURL,
1302 OUStringToOString(rAttr.Name, RTL_TEXTENCODING_UTF8),
1303 OUStringToOString(rAttr.Value, RTL_TEXTENCODING_UTF8));
1308 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */