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>
24 #include <scextopt.hxx>
25 #include <docoptio.hxx>
26 #include <tabprotection.hxx>
31 #include <xeextlst.hxx>
32 #include <biffhelper.hxx>
34 #include <xcl97rec.hxx>
35 #include <xetable.hxx>
39 #include <xecontent.hxx>
40 #include <xeescher.hxx>
41 #include <xepivot.hxx>
42 #include <export/SparklineExt.hxx>
43 #include <XclExpChangeTrack.hxx>
44 #include <xepivotxml.hxx>
45 #include <xedbdata.hxx>
46 #include <xlcontent.hxx>
49 #include <xltools.hxx>
51 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
52 #include <com/sun/star/frame/XModel.hpp>
53 #include <o3tl/safeint.hxx>
54 #include <oox/token/tokens.hxx>
55 #include <oox/token/namespaces.hxx>
60 static OUString
lcl_GetVbaTabName( SCTAB n
)
62 OUString aRet
= "__VBA__" + OUString::number( static_cast<sal_uInt16
>(n
) );
66 static void lcl_AddBookviews( XclExpRecordList
<>& aRecList
, const ExcTable
& self
)
68 aRecList
.AppendNewRecord( new XclExpXmlStartElementRecord( XML_bookViews
) );
69 aRecList
.AppendNewRecord( new XclExpWindow1( self
.GetRoot() ) );
70 aRecList
.AppendNewRecord( new XclExpXmlEndElementRecord( XML_bookViews
) );
73 static void lcl_AddCalcPr( XclExpRecordList
<>& aRecList
, const ExcTable
& self
)
75 ScDocument
& rDoc
= self
.GetDoc();
77 aRecList
.AppendNewRecord( new XclExpXmlStartSingleElementRecord( XML_calcPr
) );
78 // OOXTODO: calcCompleted, calcId, calcMode, calcOnSave,
79 // concurrentCalc, concurrentManualCount,
80 // forceFullCalc, fullCalcOnLoad, fullPrecision
81 aRecList
.AppendNewRecord( new XclCalccount( rDoc
) );
82 aRecList
.AppendNewRecord( new XclRefmode( rDoc
) );
83 aRecList
.AppendNewRecord( new XclIteration( rDoc
) );
84 aRecList
.AppendNewRecord( new XclDelta( rDoc
) );
85 aRecList
.AppendNewRecord( new XclExpBoolRecord(oox::xls::BIFF_ID_SAVERECALC
, true) );
86 aRecList
.AppendNewRecord( new XclExpXmlEndSingleElementRecord() ); // XML_calcPr
89 static void lcl_AddWorkbookProtection( XclExpRecordList
<>& aRecList
, const ExcTable
& self
)
91 aRecList
.AppendNewRecord( new XclExpXmlStartSingleElementRecord( XML_workbookProtection
) );
93 const ScDocProtection
* pProtect
= self
.GetDoc().GetDocProtection();
94 if (pProtect
&& pProtect
->isProtected())
96 aRecList
.AppendNewRecord( new XclExpWindowProtection(pProtect
->isOptionEnabled(ScDocProtection::WINDOWS
)) );
97 aRecList
.AppendNewRecord( new XclExpProtection(pProtect
->isOptionEnabled(ScDocProtection::STRUCTURE
)) );
98 aRecList
.AppendNewRecord( new XclExpPassHash(pProtect
->getPasswordHash(PASSHASH_XL
)) );
101 aRecList
.AppendNewRecord( new XclExpXmlEndSingleElementRecord() ); // XML_workbookProtection
104 static void lcl_AddScenariosAndFilters( XclExpRecordList
<>& aRecList
, const XclExpRoot
& rRoot
, SCTAB nScTab
)
107 aRecList
.AppendNewRecord( new ExcEScenarioManager( rRoot
, nScTab
) );
109 aRecList
.AppendRecord( rRoot
.GetFilterManager().CreateRecord( nScTab
) );
112 ExcTable::ExcTable( const XclExpRoot
& rRoot
) :
114 mnScTab( SCTAB_GLOBAL
),
115 nExcTab( EXC_NOTAB
),
116 mxNoteList( new XclExpNoteList
)
120 ExcTable::ExcTable( const XclExpRoot
& rRoot
, SCTAB nScTab
) :
123 nExcTab( rRoot
.GetTabInfo().GetXclTab( nScTab
) ),
124 mxNoteList( new XclExpNoteList
)
128 ExcTable::~ExcTable()
132 void ExcTable::Add( XclExpRecordBase
* pRec
)
134 OSL_ENSURE( pRec
, "-ExcTable::Add(): pRec is NULL!" );
135 aRecList
.AppendNewRecord( pRec
);
138 void ExcTable::FillAsHeaderBinary( ExcBoundsheetList
& rBoundsheetList
)
142 RootData
& rR
= GetOldRoot();
143 ScDocument
& rDoc
= GetDoc();
144 XclExpTabInfo
& rTabInfo
= GetTabInfo();
146 if ( GetBiff() <= EXC_BIFF5
)
151 sal_uInt16 nExcTabCount
= rTabInfo
.GetXclTabCount();
152 sal_uInt16 nCodenames
= static_cast< sal_uInt16
>( GetExtDocOptions().GetCodeNameCount() );
154 SfxObjectShell
* pShell
= GetDocShell();
155 sal_uInt16 nWriteProtHash
= pShell
? pShell
->GetModifyPasswordHash() : 0;
156 bool bRecommendReadOnly
= pShell
&& pShell
->IsLoadReadonly();
158 if( (nWriteProtHash
> 0) || bRecommendReadOnly
)
159 Add( new XclExpEmptyRecord( EXC_ID_WRITEPROT
) );
161 // TODO: correct codepage for BIFF5?
162 sal_uInt16 nCodePage
= XclTools::GetXclCodePage( (GetBiff() <= EXC_BIFF5
) ? RTL_TEXTENCODING_MS_1252
: RTL_TEXTENCODING_UNICODE
);
164 if( GetBiff() <= EXC_BIFF5
)
166 Add( new XclExpEmptyRecord( EXC_ID_INTERFACEHDR
) );
167 Add( new XclExpUInt16Record( EXC_ID_MMS
, 0 ) );
168 Add( new XclExpEmptyRecord( EXC_ID_TOOLBARHDR
) );
169 Add( new XclExpEmptyRecord( EXC_ID_TOOLBAREND
) );
170 Add( new XclExpEmptyRecord( EXC_ID_INTERFACEEND
) );
171 Add( new ExcDummy_00
);
175 if( IsDocumentEncrypted() )
176 Add( new XclExpFileEncryption( GetRoot() ) );
177 Add( new XclExpInterfaceHdr( nCodePage
) );
178 Add( new XclExpUInt16Record( EXC_ID_MMS
, 0 ) );
179 Add( new XclExpInterfaceEnd
);
180 Add( new XclExpWriteAccess
);
183 Add( new XclExpFileSharing( GetRoot(), nWriteProtHash
, bRecommendReadOnly
) );
184 Add( new XclExpUInt16Record( EXC_ID_CODEPAGE
, nCodePage
) );
186 if( GetBiff() == EXC_BIFF8
)
188 Add( new XclExpBoolRecord( EXC_ID_DSF
, false ) );
189 Add( new XclExpEmptyRecord( EXC_ID_XL9FILE
) );
190 rR
.pTabId
= new XclExpChTrTabId( std::max( nExcTabCount
, nCodenames
) );
192 if( HasVbaStorage() )
194 Add( new XclObproj
);
195 const OUString
& rCodeName
= GetExtDocOptions().GetDocSettings().maGlobCodeName
;
196 if( !rCodeName
.isEmpty() )
197 Add( new XclCodename( rCodeName
) );
201 Add( new XclExpUInt16Record( EXC_ID_FNGROUPCOUNT
, 14 ) );
203 if ( GetBiff() <= EXC_BIFF5
)
205 // global link table: EXTERNCOUNT, EXTERNSHEET, NAME
206 aRecList
.AppendRecord( CreateRecord( EXC_ID_EXTERNSHEET
) );
207 aRecList
.AppendRecord( CreateRecord( EXC_ID_NAME
) );
210 // document protection options
211 lcl_AddWorkbookProtection( aRecList
, *this );
213 if( GetBiff() == EXC_BIFF8
)
215 Add( new XclExpProt4Rev
);
216 Add( new XclExpProt4RevPass
);
219 lcl_AddBookviews( aRecList
, *this );
221 Add( new XclExpXmlStartSingleElementRecord( XML_workbookPr
) );
222 if ( GetBiff() == EXC_BIFF8
&& GetOutput() != EXC_OUTPUT_BINARY
)
224 Add( new XclExpBoolRecord(0x0040, false, XML_backupFile
) ); // BACKUP
225 Add( new XclExpBoolRecord(0x008D, false, XML_showObjects
) ); // HIDEOBJ
228 if ( GetBiff() == EXC_BIFF8
)
230 Add( new XclExpBoolRecord(0x0040, false) ); // BACKUP
231 Add( new XclExpBoolRecord(0x008D, false) ); // HIDEOBJ
234 if( GetBiff() <= EXC_BIFF5
)
236 Add( new ExcDummy_040
);
237 Add( new Exc1904( rDoc
) );
238 Add( new ExcDummy_041
);
243 Add( new Exc1904( rDoc
) );
244 Add( new XclExpBoolRecord( 0x000E, !rDoc
.GetDocOptions().IsCalcAsShown() ) );
245 Add( new XclExpBoolRecord(0x01B7, false) ); // REFRESHALL
246 Add( new XclExpBoolRecord(0x00DA, false) ); // BOOKBOOL
249 // Formatting: FONT, FORMAT, XF, STYLE, PALETTE
250 aRecList
.AppendRecord( CreateRecord( EXC_ID_FONTLIST
) );
251 aRecList
.AppendRecord( CreateRecord( EXC_ID_FORMATLIST
) );
252 aRecList
.AppendRecord( CreateRecord( EXC_ID_XFLIST
) );
253 aRecList
.AppendRecord( CreateRecord( EXC_ID_PALETTE
) );
256 SCTAB nScTabCount
= rTabInfo
.GetScTabCount();
257 if( GetBiff() <= EXC_BIFF5
)
260 for( nC
= 0 ; nC
< nScTabCount
; nC
++ )
261 if( rTabInfo
.IsExportTab( nC
) )
263 ExcBoundsheetList::RecordRefType xBoundsheet
= new ExcBundlesheet( rR
, nC
);
264 aRecList
.AppendRecord( xBoundsheet
);
265 rBoundsheetList
.AppendRecord( xBoundsheet
);
271 GetPivotTableManager().CreatePivotTables();
272 aRecList
.AppendRecord( GetPivotTableManager().CreatePivotCachesRecord() );
275 if( rDoc
.GetChangeTrack() )
277 rR
.pUserBViewList
= new XclExpUserBViewList( *rDoc
.GetChangeTrack() );
278 Add( rR
.pUserBViewList
);
281 // Natural Language Formulas Flag
282 aRecList
.AppendNewRecord( new XclExpBoolRecord( EXC_ID_USESELFS
, GetDoc().GetDocOptions().IsLookUpColRowNames() ) );
285 for( nC
= 0 ; nC
< nScTabCount
; nC
++ )
286 if( rTabInfo
.IsExportTab( nC
) )
288 ExcBoundsheetList::RecordRefType xBoundsheet
= new ExcBundlesheet8( rR
, nC
);
289 aRecList
.AppendRecord( xBoundsheet
);
290 rBoundsheetList
.AppendRecord( xBoundsheet
);
294 for( SCTAB nAdd
= 0; nC
< static_cast<SCTAB
>(nCodenames
) ; nC
++, nAdd
++ )
296 aTmpString
= lcl_GetVbaTabName( nAdd
);
297 ExcBoundsheetList::RecordRefType xBoundsheet
= new ExcBundlesheet8( aTmpString
);
298 aRecList
.AppendRecord( xBoundsheet
);
299 rBoundsheetList
.AppendRecord( xBoundsheet
);
302 // COUNTRY - in BIFF8 in workbook globals
303 Add( new XclExpCountry( GetRoot() ) );
305 // link table: SUPBOOK, XCT, CRN, EXTERNNAME, EXTERNSHEET, NAME
306 aRecList
.AppendRecord( CreateRecord( EXC_ID_EXTERNSHEET
) );
307 aRecList
.AppendRecord( CreateRecord( EXC_ID_NAME
) );
309 Add( new XclExpRecalcId
);
311 // MSODRAWINGGROUP per-document data
312 aRecList
.AppendRecord( GetObjectManager().CreateDrawingGroup() );
313 // Shared string table: SST, EXTSST
314 aRecList
.AppendRecord( CreateRecord( EXC_ID_SST
) );
316 Add( new XclExpBookExt
);
322 void ExcTable::FillAsHeaderXml( ExcBoundsheetList
& rBoundsheetList
)
326 RootData
& rR
= GetOldRoot();
327 ScDocument
& rDoc
= GetDoc();
328 XclExpTabInfo
& rTabInfo
= GetTabInfo();
330 sal_uInt16 nExcTabCount
= rTabInfo
.GetXclTabCount();
331 sal_uInt16 nCodenames
= static_cast< sal_uInt16
>( GetExtDocOptions().GetCodeNameCount() );
333 rR
.pTabId
= new XclExpChTrTabId( std::max( nExcTabCount
, nCodenames
) );
336 Add( new XclExpXmlStartSingleElementRecord( XML_workbookPr
) );
337 Add( new XclExpBoolRecord(0x0040, false, XML_backupFile
) ); // BACKUP
338 Add( new XclExpBoolRecord(0x008D, false, XML_showObjects
) ); // HIDEOBJ
340 Add( new Exc1904( rDoc
) );
341 // OOXTODO: The following /workbook/workbookPr attributes are mapped
342 // to various BIFF records that are not currently supported:
344 // XML_allowRefreshQuery: QSISTAG 802h: fEnableRefresh
345 // XML_autoCompressPictures: COMPRESSPICTURES 89Bh: fAutoCompressPictures
346 // XML_checkCompatibility: COMPAT12 88Ch: fNoCompatChk
347 // XML_codeName: "Calc"
348 // XML_defaultThemeVersion: ???
349 // XML_filterPrivacy: BOOKEXT 863h: fFilterPrivacy
350 // XML_hidePivotFieldList: BOOKBOOL DAh: fHidePivotTableFList
351 // XML_promptedSolutions: BOOKEXT 863h: fBuggedUserAboutSolution
352 // XML_publishItems: NAMEPUBLISH 893h: fPublished
353 // XML_saveExternalLinkValues: BOOKBOOL DAh: fNoSavSupp
354 // XML_showBorderUnselectedTables: BOOKBOOL DAh: fHideBorderUnsels
355 // XML_showInkAnnotation: BOOKEXT 863h: fShowInkAnnotation
356 // XML_showPivotChart: PIVOTCHARTBITS 859h: fGXHide??
357 // XML_updateLinks: BOOKBOOL DAh: grbitUpdateLinks
358 Add( new XclExpXmlEndSingleElementRecord() ); // XML_workbookPr
360 // Formatting: FONT, FORMAT, XF, STYLE, PALETTE
361 aRecList
.AppendNewRecord( new XclExpXmlStyleSheet( *this ) );
364 if( rDoc
.GetChangeTrack() )
366 rR
.pUserBViewList
= new XclExpUserBViewList( *rDoc
.GetChangeTrack() );
367 Add( rR
.pUserBViewList
);
370 lcl_AddWorkbookProtection( aRecList
, *this );
371 lcl_AddBookviews( aRecList
, *this );
375 SCTAB nScTabCount
= rTabInfo
.GetScTabCount();
376 aRecList
.AppendNewRecord( new XclExpXmlStartElementRecord( XML_sheets
) );
377 for( nC
= 0 ; nC
< nScTabCount
; nC
++ )
378 if( rTabInfo
.IsExportTab( nC
) )
380 ExcBoundsheetList::RecordRefType xBoundsheet
= new ExcBundlesheet8( rR
, nC
);
381 aRecList
.AppendRecord( xBoundsheet
);
382 rBoundsheetList
.AppendRecord( xBoundsheet
);
384 aRecList
.AppendNewRecord( new XclExpXmlEndElementRecord( XML_sheets
) );
387 for( SCTAB nAdd
= 0; nC
< static_cast<SCTAB
>(nCodenames
) ; nC
++, nAdd
++ )
389 aTmpString
= lcl_GetVbaTabName( nAdd
);
390 ExcBoundsheetList::RecordRefType xBoundsheet
= new ExcBundlesheet8( aTmpString
);
391 aRecList
.AppendRecord( xBoundsheet
);
392 rBoundsheetList
.AppendRecord( xBoundsheet
);
395 // link table: SUPBOOK, XCT, CRN, EXTERNNAME, EXTERNSHEET, NAME
396 aRecList
.AppendRecord( CreateRecord( EXC_ID_EXTERNSHEET
) );
397 aRecList
.AppendRecord( CreateRecord( EXC_ID_NAME
) );
399 lcl_AddCalcPr( aRecList
, *this );
401 // MSODRAWINGGROUP per-document data
402 aRecList
.AppendRecord( GetObjectManager().CreateDrawingGroup() );
403 // Shared string table: SST, EXTSST
404 aRecList
.AppendRecord( CreateRecord( EXC_ID_SST
) );
407 void ExcTable::FillAsTableBinary( SCTAB nCodeNameIdx
)
409 InitializeTable( mnScTab
);
411 RootData
& rR
= GetOldRoot();
412 XclBiff eBiff
= GetBiff();
413 ScDocument
& rDoc
= GetDoc();
415 OSL_ENSURE( (mnScTab
>= 0) && (mnScTab
<= MAXTAB
), "-ExcTable::Table(): mnScTab - no ordinary table!" );
416 OSL_ENSURE( nExcTab
<= o3tl::make_unsigned(MAXTAB
), "-ExcTable::Table(): nExcTab - no ordinary table!" );
418 // create a new OBJ list for this sheet (may be used by notes, autofilter, data validation)
419 if( eBiff
== EXC_BIFF8
)
420 GetObjectManager().StartSheet();
422 // cell table: DEFROWHEIGHT, DEFCOLWIDTH, COLINFO, DIMENSIONS, ROW, cell records
423 mxCellTable
= new XclExpCellTable( GetRoot() );
426 std::vector
<sc::NoteEntry
> aNotes
;
427 rDoc
.GetAllNoteEntries(aNotes
);
428 for (const auto& rNote
: aNotes
)
430 if (rNote
.maPos
.Tab() != mnScTab
)
433 mxNoteList
->AppendNewRecord(new XclExpNote(GetRoot(), rNote
.maPos
, rNote
.mpNote
, u
""));
436 // WSBOOL needs data from page settings, create it here, add it later
437 rtl::Reference
<XclExpPageSettings
> xPageSett
= new XclExpPageSettings( GetRoot() );
438 bool bFitToPages
= xPageSett
->GetPageData().mbFitToPages
;
440 if( eBiff
<= EXC_BIFF5
)
443 Add( new ExcDummy_02a
);
448 lcl_AddCalcPr( aRecList
, *this );
451 // GUTS (count & size of outline icons)
452 aRecList
.AppendRecord( mxCellTable
->CreateRecord( EXC_ID_GUTS
) );
453 // DEFROWHEIGHT, created by the cell table
454 aRecList
.AppendRecord( mxCellTable
->CreateRecord( EXC_ID2_DEFROWHEIGHT
) );
456 // COUNTRY - in BIFF5/7 in every worksheet
457 if( eBiff
<= EXC_BIFF5
)
458 Add( new XclExpCountry( GetRoot() ) );
460 Add( new XclExpWsbool( bFitToPages
) );
462 // page settings (SETUP and various other records)
463 aRecList
.AppendRecord( xPageSett
);
465 const ScTableProtection
* pTabProtect
= rDoc
.GetTabProtection(mnScTab
);
466 if (pTabProtect
&& pTabProtect
->isProtected())
468 Add( new XclExpProtection(true) );
469 Add( new XclExpBoolRecord(oox::xls::BIFF_ID_SCENPROTECT
, pTabProtect
->isOptionEnabled(ScTableProtection::SCENARIOS
)) );
470 if (pTabProtect
->isOptionEnabled(ScTableProtection::OBJECTS
))
471 Add( new XclExpBoolRecord(oox::xls::BIFF_ID_OBJECTPROTECT
, true ));
472 Add( new XclExpPassHash(pTabProtect
->getPasswordHash(PASSHASH_XL
)) );
475 // local link table: EXTERNCOUNT, EXTERNSHEET
476 if( eBiff
<= EXC_BIFF5
)
477 aRecList
.AppendRecord( CreateRecord( EXC_ID_EXTERNSHEET
) );
479 if ( eBiff
== EXC_BIFF8
)
480 lcl_AddScenariosAndFilters( aRecList
, GetRoot(), mnScTab
);
482 // cell table: DEFCOLWIDTH, COLINFO, DIMENSIONS, ROW, cell records
483 aRecList
.AppendRecord( mxCellTable
);
485 // MERGEDCELLS record, generated by the cell table
486 aRecList
.AppendRecord( mxCellTable
->CreateRecord( EXC_ID_MERGEDCELLS
) );
488 if( eBiff
== EXC_BIFF8
)
489 Add( new XclExpLabelranges( GetRoot() ) );
490 // data validation (DVAL and list of DV records), generated by the cell table
491 aRecList
.AppendRecord( mxCellTable
->CreateRecord( EXC_ID_DVAL
) );
493 if( eBiff
== EXC_BIFF8
)
495 // all MSODRAWING and OBJ stuff of this sheet goes here
496 aRecList
.AppendRecord( GetObjectManager().ProcessDrawing( GetSdrPage( mnScTab
) ) );
498 aRecList
.AppendRecord( GetPivotTableManager().CreatePivotTablesRecord( mnScTab
) );
501 // list of NOTE records, generated by the cell table
502 aRecList
.AppendRecord( mxNoteList
);
504 // sheet view settings: WINDOW2, SCL, PANE, SELECTION
505 aRecList
.AppendNewRecord( new XclExpTabViewSettings( GetRoot(), mnScTab
) );
507 if( eBiff
== EXC_BIFF8
)
509 // sheet protection options
510 Add( new XclExpSheetProtectOptions( GetRoot(), mnScTab
) );
512 // enhanced protections if there are
515 const ::std::vector
<ScEnhancedProtection
>& rProts( pTabProtect
->getEnhancedProtection());
516 for (const auto& rProt
: rProts
)
518 Add( new XclExpSheetEnhancedProtection( GetRoot(), rProt
));
523 Add( new XclExpWebQueryBuffer( GetRoot() ) );
525 // conditional formats
526 Add( new XclExpCondFormatBuffer( GetRoot(), XclExtLstRef() ) );
528 if( HasVbaStorage() )
529 if( nCodeNameIdx
< GetExtDocOptions().GetCodeNameCount() )
530 Add( new XclCodename( GetExtDocOptions().GetCodeName( nCodeNameIdx
) ) );
533 // list of HLINK records, generated by the cell table
534 aRecList
.AppendRecord( mxCellTable
->CreateRecord( EXC_ID_HLINK
) );
537 if( rR
.pUserBViewList
)
539 XclExpUserBViewList::const_iterator iter
;
540 for ( iter
= rR
.pUserBViewList
->cbegin(); iter
!= rR
.pUserBViewList
->cend(); ++iter
)
542 Add( new XclExpUsersViewBegin( (*iter
).GetGUID(), nExcTab
) );
543 Add( new XclExpUsersViewEnd
);
551 void ExcTable::FillAsTableXml()
553 InitializeTable( mnScTab
);
555 ScDocument
& rDoc
= GetDoc();
557 OSL_ENSURE( (mnScTab
>= 0) && (mnScTab
<= MAXTAB
), "-ExcTable::Table(): mnScTab - no ordinary table!" );
558 OSL_ENSURE( nExcTab
<= o3tl::make_unsigned(MAXTAB
), "-ExcTable::Table(): nExcTab - no ordinary table!" );
560 // create a new OBJ list for this sheet (may be used by notes, autofilter, data validation)
561 GetObjectManager().StartSheet();
563 // cell table: DEFROWHEIGHT, DEFCOLWIDTH, COLINFO, DIMENSIONS, ROW, cell records
564 mxCellTable
= new XclExpCellTable( GetRoot() );
567 std::vector
<sc::NoteEntry
> aNotes
;
568 rDoc
.GetAllNoteEntries(aNotes
);
569 for (const auto& rNote
: aNotes
)
571 if (rNote
.maPos
.Tab() != mnScTab
)
574 mxNoteList
->AppendNewRecord(new XclExpNote(GetRoot(), rNote
.maPos
, rNote
.mpNote
, u
""));
577 // WSBOOL needs data from page settings, create it here, add it later
578 rtl::Reference
<XclExpPageSettings
> xPageSett
= new XclExpPageSettings( GetRoot() );
579 XclExtLstRef xExtLst
= new XclExtLst( GetRoot() );
580 bool bFitToPages
= xPageSett
->GetPageData().mbFitToPages
;
582 Color aTabColor
= GetRoot().GetDoc().GetTabBgColor(mnScTab
);
583 Add(new XclExpXmlSheetPr(bFitToPages
, mnScTab
, aTabColor
, &GetFilterManager()));
585 // GUTS (count & size of outline icons)
586 aRecList
.AppendRecord( mxCellTable
->CreateRecord( EXC_ID_GUTS
) );
587 // DEFROWHEIGHT, created by the cell table
588 aRecList
.AppendRecord( mxCellTable
->CreateRecord( EXC_ID2_DEFROWHEIGHT
) );
590 aRecList
.AppendRecord( mxCellTable
->CreateRecord( EXC_ID3_DIMENSIONS
) );
592 // sheet view settings: WINDOW2, SCL, PANE, SELECTION
593 aRecList
.AppendNewRecord( new XclExpTabViewSettings( GetRoot(), mnScTab
) );
595 // cell table: DEFCOLWIDTH, COLINFO, DIMENSIONS, ROW, cell records
596 aRecList
.AppendRecord( mxCellTable
);
598 // list of NOTE records, generated by the cell table
599 // not in the worksheet file
600 if( mxNoteList
!= nullptr && !mxNoteList
->IsEmpty() )
601 aRecList
.AppendNewRecord( new XclExpComments( mnScTab
, *mxNoteList
) );
603 const ScTableProtection
* pTabProtect
= rDoc
.GetTabProtection(mnScTab
);
604 if (pTabProtect
&& pTabProtect
->isProtected())
605 Add( new XclExpSheetProtection(true, mnScTab
) );
607 lcl_AddScenariosAndFilters( aRecList
, GetRoot(), mnScTab
);
609 // MERGEDCELLS record, generated by the cell table
610 aRecList
.AppendRecord( mxCellTable
->CreateRecord( EXC_ID_MERGEDCELLS
) );
612 // conditional formats
613 Add( new XclExpCondFormatBuffer( GetRoot(), xExtLst
) );
615 Add(new xcl::exp::SparklineBuffer(GetRoot(), xExtLst
));
617 // data validation (DVAL and list of DV records), generated by the cell table
618 aRecList
.AppendRecord( mxCellTable
->CreateRecord( EXC_ID_DVAL
) );
620 // list of HLINK records, generated by the cell table
621 XclExpRecordRef xHyperlinks
= mxCellTable
->CreateRecord( EXC_ID_HLINK
);
622 XclExpHyperlinkList
* pHyperlinkList
= dynamic_cast<XclExpHyperlinkList
*>(xHyperlinks
.get());
623 if( pHyperlinkList
!= nullptr && !pHyperlinkList
->IsEmpty() )
625 aRecList
.AppendNewRecord( new XclExpXmlStartElementRecord( XML_hyperlinks
) );
626 aRecList
.AppendRecord( xHyperlinks
);
627 aRecList
.AppendNewRecord( new XclExpXmlEndElementRecord( XML_hyperlinks
) );
630 aRecList
.AppendRecord( xPageSett
);
632 // all MSODRAWING and OBJ stuff of this sheet goes here
633 aRecList
.AppendRecord( GetObjectManager().ProcessDrawing( GetSdrPage( mnScTab
) ) );
635 XclExpImgData
* pImgData
= xPageSett
->getGraphicExport();
637 aRecList
.AppendRecord(pImgData
);
639 // <tableParts> after <drawing> and before <extLst>
640 aRecList
.AppendRecord( GetTablesManager().GetTablesBySheet( mnScTab
));
642 aRecList
.AppendRecord( xExtLst
);
645 void ExcTable::FillAsEmptyTable( SCTAB nCodeNameIdx
)
647 InitializeTable( mnScTab
);
649 if( !(HasVbaStorage() && (nCodeNameIdx
< GetExtDocOptions().GetCodeNameCount())) )
652 if( GetBiff() <= EXC_BIFF5
)
659 Add( new XclCodename( GetExtDocOptions().GetCodeName( nCodeNameIdx
) ) );
661 // sheet view settings: WINDOW2, SCL, PANE, SELECTION
662 aRecList
.AppendNewRecord( new XclExpTabViewSettings( GetRoot(), mnScTab
) );
666 void ExcTable::Write( XclExpStream
& rStrm
)
668 SetCurrScTab( mnScTab
);
670 mxCellTable
->Finalize(true);
671 aRecList
.Save( rStrm
);
674 void ExcTable::WriteXml( XclExpXmlStream
& rStrm
)
676 if (!GetTabInfo().IsExportTab(mnScTab
))
679 SetCurrScTab(mnScTab
);
681 mxCellTable
->Finalize(false);
682 aRecList
.SaveXml(rStrm
);
688 OUString sSheetName
= XclXmlUtils::GetStreamName( "xl/", "worksheets/sheet", mnScTab
+1 );
690 sax_fastparser::FSHelperPtr pWorksheet
= rStrm
.GetStreamForPath( sSheetName
);
692 rStrm
.PushStream( pWorksheet
);
694 pWorksheet
->startElement( XML_worksheet
,
695 XML_xmlns
, rStrm
.getNamespaceURL(OOX_NS(xls
)).toUtf8(),
696 FSNS(XML_xmlns
, XML_r
), rStrm
.getNamespaceURL(OOX_NS(officeRel
)).toUtf8(),
697 FSNS(XML_xmlns
, XML_xdr
), "http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing", // rStrm.getNamespaceURL(OOX_NS(xm)).toUtf8() -> "http://schemas.microsoft.com/office/excel/2006/main",
698 FSNS(XML_xmlns
, XML_x14
), rStrm
.getNamespaceURL(OOX_NS(xls14Lst
)).toUtf8(),
699 FSNS(XML_xmlns
, XML_xr2
), rStrm
.getNamespaceURL(OOX_NS(xr2
)).toUtf8(),
700 FSNS(XML_xmlns
, XML_mc
), rStrm
.getNamespaceURL(OOX_NS(mce
)).toUtf8());
702 SetCurrScTab( mnScTab
);
704 mxCellTable
->Finalize(false);
705 aRecList
.SaveXml( rStrm
);
707 XclExpXmlPivotTables
* pPT
= GetXmlPivotTableManager().GetTablesBySheet(mnScTab
);
711 rStrm
.GetCurrentStream()->endElement( XML_worksheet
);
715 ExcDocument::ExcDocument( const XclExpRoot
& rRoot
) :
721 ExcDocument::~ExcDocument()
723 maTableList
.RemoveAllRecords(); // for the following assertion!
726 void ExcDocument::ReadDoc()
730 if (GetOutput() == EXC_OUTPUT_BINARY
)
731 aHeader
.FillAsHeaderBinary(maBoundsheetList
);
734 aHeader
.FillAsHeaderXml(maBoundsheetList
);
735 GetXmlPivotTableManager().Initialize();
736 GetTablesManager().Initialize(); // Move outside conditions if we wanted to support BIFF.
739 SCTAB nScTab
= 0, nScTabCount
= GetTabInfo().GetScTabCount();
740 SCTAB nCodeNameIdx
= 0, nCodeNameCount
= GetExtDocOptions().GetCodeNameCount();
742 for( ; nScTab
< nScTabCount
; ++nScTab
)
744 if( GetTabInfo().IsExportTab( nScTab
) )
746 ExcTableList::RecordRefType xTab
= new ExcTable( GetRoot(), nScTab
);
747 maTableList
.AppendRecord( xTab
);
748 if (GetOutput() == EXC_OUTPUT_BINARY
)
749 xTab
->FillAsTableBinary(nCodeNameIdx
);
751 xTab
->FillAsTableXml();
756 for( ; nCodeNameIdx
< nCodeNameCount
; ++nScTab
, ++nCodeNameIdx
)
758 ExcTableList::RecordRefType xTab
= new ExcTable( GetRoot(), nScTab
);
759 maTableList
.AppendRecord( xTab
);
760 xTab
->FillAsEmptyTable( nCodeNameIdx
);
763 if ( GetBiff() == EXC_BIFF8
)
765 // complete temporary Escher stream
766 GetObjectManager().EndDocument();
769 if ( GetDoc().GetChangeTrack() )
770 m_xExpChangeTrack
.reset(new XclExpChangeTrack( GetRoot() ));
774 void ExcDocument::Write( SvStream
& rSvStrm
)
776 if( !maTableList
.IsEmpty() )
780 XclExpStream
aXclStrm( rSvStrm
, GetRoot() );
782 aHeader
.Write( aXclStrm
);
784 OSL_ENSURE( maTableList
.GetSize() == maBoundsheetList
.GetSize(),
785 "ExcDocument::Write - different number of sheets and BOUNDSHEET records" );
787 for( size_t nTab
= 0, nTabCount
= maTableList
.GetSize(); nTab
< nTabCount
; ++nTab
)
789 // set current stream position in BOUNDSHEET record
790 ExcBoundsheetRef xBoundsheet
= maBoundsheetList
.GetRecord( nTab
);
792 xBoundsheet
->SetStreamPos( aXclStrm
.GetSvStreamPos() );
794 maTableList
.GetRecord( nTab
)->Write( aXclStrm
);
797 // write the table stream positions into the BOUNDSHEET records
798 for( size_t nBSheet
= 0, nBSheetCount
= maBoundsheetList
.GetSize(); nBSheet
< nBSheetCount
; ++nBSheet
)
799 maBoundsheetList
.GetRecord( nBSheet
)->UpdateStreamPos( aXclStrm
);
801 if( m_xExpChangeTrack
)
802 m_xExpChangeTrack
->Write();
805 void ExcDocument::WriteXml( XclExpXmlStream
& rStrm
)
807 SfxObjectShell
* pDocShell
= GetDocShell();
809 using namespace ::com::sun::star
;
810 uno::Reference
<document::XDocumentPropertiesSupplier
> xDPS( pDocShell
->GetModel(), uno::UNO_QUERY_THROW
);
811 uno::Reference
<document::XDocumentProperties
> xDocProps
= xDPS
->getDocumentProperties();
813 OUString sUserName
= GetUserName();
814 sal_uInt32 nWriteProtHash
= pDocShell
->GetModifyPasswordHash();
815 bool bHasPasswordHash
= nWriteProtHash
&& !sUserName
.isEmpty();
816 const uno::Sequence
<beans::PropertyValue
> aInfo
= pDocShell
->GetModifyPasswordInfo();
817 OUString sAlgorithm
, sSalt
, sHash
;
818 sal_Int32 nCount
= 0;
819 for (const auto& prop
: aInfo
)
821 if (prop
.Name
== "algorithm-name")
822 prop
.Value
>>= sAlgorithm
;
823 else if (prop
.Name
== "salt")
824 prop
.Value
>>= sSalt
;
825 else if (prop
.Name
== "iteration-count")
826 prop
.Value
>>= nCount
;
827 else if (prop
.Name
== "hash")
828 prop
.Value
>>= sHash
;
830 bool bHasPasswordInfo
831 = sAlgorithm
!= "PBKDF2" && !sSalt
.isEmpty() && !sHash
.isEmpty() && !sUserName
.isEmpty();
832 rStrm
.exportDocumentProperties(xDocProps
, pDocShell
->IsSecurityOptOpenReadOnly()
833 && !bHasPasswordHash
&& !bHasPasswordInfo
);
834 rStrm
.exportCustomFragments();
836 sax_fastparser::FSHelperPtr
& rWorkbook
= rStrm
.GetCurrentStream();
837 rWorkbook
->startElement( XML_workbook
,
838 XML_xmlns
, rStrm
.getNamespaceURL(OOX_NS(xls
)).toUtf8(),
839 FSNS(XML_xmlns
, XML_r
), rStrm
.getNamespaceURL(OOX_NS(officeRel
)).toUtf8() );
840 rWorkbook
->singleElement( XML_fileVersion
,
842 // OOXTODO: XML_codeName
843 // OOXTODO: XML_lastEdited
844 // OOXTODO: XML_lowestEdited
845 // OOXTODO: XML_rupBuild
848 if (bHasPasswordHash
)
849 rWorkbook
->singleElement(XML_fileSharing
,
850 XML_userName
, sUserName
,
851 XML_reservationPassword
, OString::number(nWriteProtHash
, 16).getStr());
852 else if (bHasPasswordInfo
)
853 rWorkbook
->singleElement(XML_fileSharing
,
854 XML_userName
, sUserName
,
855 XML_algorithmName
, sAlgorithm
.toUtf8().getStr(),
856 XML_hashValue
, sHash
.toUtf8().getStr(),
857 XML_saltValue
, sSalt
.toUtf8().getStr(),
858 XML_spinCount
, OString::number(nCount
).getStr());
860 if( !maTableList
.IsEmpty() )
864 aHeader
.WriteXml( rStrm
);
866 for( size_t nTab
= 0, nTabCount
= maTableList
.GetSize(); nTab
< nTabCount
; ++nTab
)
869 maTableList
.GetRecord( nTab
)->WriteXml( rStrm
);
873 if( m_xExpChangeTrack
)
874 m_xExpChangeTrack
->WriteXml( rStrm
);
876 XclExpXmlPivotCaches
& rCaches
= GetXmlPivotTableManager().GetCaches();
877 if (rCaches
.HasCaches())
878 rCaches
.SaveXml(rStrm
);
880 const ScCalcConfig
& rCalcConfig
= GetDoc().GetCalcConfig();
881 formula::FormulaGrammar::AddressConvention eConv
= rCalcConfig
.meStringRefAddressSyntax
;
883 // don't save "unspecified" string ref syntax ... query formula grammar
884 // and save that instead
885 if( eConv
== formula::FormulaGrammar::CONV_UNSPECIFIED
)
887 eConv
= GetDoc().GetAddressConvention();
890 // write if it has been read|imported or explicitly changed
891 // or if ref syntax isn't what would be native for our file format
892 // i.e. ExcelA1 in this case
893 if ( rCalcConfig
.mbHasStringRefSyntax
||
894 (eConv
!= formula::FormulaGrammar::CONV_XL_A1
) )
896 XclExtLstRef xExtLst
= new XclExtLst( GetRoot() );
897 xExtLst
->AddRecord( new XclExpExtCalcPr( GetRoot(), eConv
) );
898 xExtLst
->SaveXml(rStrm
);
901 rWorkbook
->endElement( XML_workbook
);
905 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */