1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
25 #include <scextopt.hxx>
26 #include <docoptio.hxx>
27 #include <tabprotection.hxx>
30 #include <connectionsbuffer.hxx>
31 #include <connectionsfragment.hxx>
34 #include <xeextlst.hxx>
35 #include <biffhelper.hxx>
37 #include <xcl97rec.hxx>
38 #include <xetable.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>
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>
67 static OUString
lcl_GetVbaTabName( SCTAB n
)
69 OUString aRet
= "__VBA__" + OUString::number( static_cast<sal_uInt16
>(n
) );
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
)
114 aRecList
.AppendNewRecord( new ExcEScenarioManager( rRoot
, nScTab
) );
116 aRecList
.AppendRecord( rRoot
.GetFilterManager().CreateRecord( nScTab
) );
119 ExcTable::ExcTable( const XclExpRoot
& rRoot
) :
121 mnScTab( SCTAB_GLOBAL
),
122 nExcTab( EXC_NOTAB
),
123 mxNoteList( new XclExpNoteList
)
127 ExcTable::ExcTable( const XclExpRoot
& rRoot
, SCTAB 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
)
149 RootData
& rR
= GetOldRoot();
150 ScDocument
& rDoc
= GetDoc();
151 XclExpTabInfo
& rTabInfo
= GetTabInfo();
153 if ( GetBiff() <= EXC_BIFF5
)
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
);
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
) );
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
);
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
) );
263 SCTAB nScTabCount
= rTabInfo
.GetScTabCount();
264 if( GetBiff() <= EXC_BIFF5
)
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
);
278 GetPivotTableManager().CreatePivotTables();
279 aRecList
.AppendRecord( GetPivotTableManager().CreatePivotCachesRecord() );
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() ) );
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
);
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
);
329 void ExcTable::FillAsHeaderXml( ExcBoundsheetList
& rBoundsheetList
)
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
) );
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 ) );
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 );
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
) );
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() );
433 std::vector
<sc::NoteEntry
> aNotes
;
434 rDoc
.GetAllNoteEntries(aNotes
);
435 for (const auto& rNote
: aNotes
)
437 if (rNote
.maPos
.Tab() != mnScTab
)
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
)
450 Add( new ExcDummy_02a
);
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
) );
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
) ) );
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
522 const ::std::vector
<ScEnhancedProtection
>& rProts( pTabProtect
->getEnhancedProtection());
523 for (const auto& rProt
: rProts
)
525 Add( new XclExpSheetEnhancedProtection( GetRoot(), rProt
));
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
) );
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
);
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() );
574 std::vector
<sc::NoteEntry
> aNotes
;
575 rDoc
.GetAllNoteEntries(aNotes
);
576 for (const auto& rNote
: aNotes
)
578 if (rNote
.maPos
.Tab() != mnScTab
)
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();
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())) )
660 if( GetBiff() <= EXC_BIFF5
)
667 Add( new XclCodename( GetExtDocOptions().GetCodeName( nCodeNameIdx
) ) );
669 // sheet view settings: WINDOW2, SCL, PANE, SELECTION
670 aRecList
.AppendNewRecord( new XclExpTabViewSettings( GetRoot(), mnScTab
) );
674 void ExcTable::Write( XclExpStream
& rStrm
)
676 SetCurrScTab( mnScTab
);
678 mxCellTable
->Finalize(true);
679 aRecList
.Save( rStrm
);
682 void ExcTable::WriteXml( XclExpXmlStream
& rStrm
)
684 if (!GetTabInfo().IsExportTab(mnScTab
))
687 SetCurrScTab(mnScTab
);
689 mxCellTable
->Finalize(false);
690 aRecList
.SaveXml(rStrm
);
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
);
712 mxCellTable
->Finalize(false);
713 aRecList
.SaveXml( rStrm
);
715 XclExpXmlPivotTables
* pPT
= GetXmlPivotTableManager().GetTablesBySheet(mnScTab
);
719 rStrm
.GetCurrentStream()->endElement( XML_worksheet
);
723 ExcDocument::ExcDocument( const XclExpRoot
& rRoot
) :
729 ExcDocument::~ExcDocument()
731 maTableList
.RemoveAllRecords(); // for the following assertion!
734 void ExcDocument::ReadDoc()
738 if (GetOutput() == EXC_OUTPUT_BINARY
)
739 aHeader
.FillAsHeaderBinary(maBoundsheetList
);
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
);
759 xTab
->FillAsTableXml();
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();
777 if ( GetDoc().GetChangeTrack() )
778 m_xExpChangeTrack
.reset(new XclExpChangeTrack( GetRoot() ));
782 void ExcDocument::Write( SvStream
& rSvStrm
)
784 if( !maTableList
.IsEmpty() )
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
);
800 xBoundsheet
->SetStreamPos( aXclStrm
.GetSvStreamPos() );
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
,
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() )
872 auto* pDrawLayer
= GetDoc().GetDrawLayer();
875 std::shared_ptr
<model::Theme
> pTheme
= pDrawLayer
->getTheme();
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
)
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();
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
);
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"
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
;
1006 nValue
= "integrated";
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>
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"/>
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();
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
;
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
)
1121 tableElement
>>= sElement
;
1122 OUString token
= sElement
.getToken(0, ',');
1123 OUString attributeValue
= sElement
.getToken(1, ',');
1126 rStrm
.GetCurrentStream()->singleElement(XML_s
, XML_v
,
1128 else if (token
== "x")
1129 rStrm
.GetCurrentStream()->singleElement(XML_x
, XML_v
,
1132 rStrm
.GetCurrentStream()->singleElement(XML_m
);
1137 rStrm
.GetCurrentStream()->endElement(XML_tables
);
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
);
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.
1234 (Any element in any namespace)
1240 rStrm
.GetCurrentStream()->endElement(XML_ext
);
1244 rStrm
.GetCurrentStream()->endElement(XML_extLst
);
1248 // put </connection>
1249 rStrm
.GetCurrentStream()->endElement(XML_connection
);
1252 // put </connections>
1253 aConnectionsXml
->endElement(XML_connections
);
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
);
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
)
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: */