LanguageTool: don't crash if REST protocol isn't set
[LibreOffice.git] / sc / source / filter / excel / excdoc.cxx
blobc01dde32981cf09b853a26d9e75638c43ba01d26
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 <scextopt.hxx>
25 #include <docoptio.hxx>
26 #include <tabprotection.hxx>
27 #include <postit.hxx>
28 #include <root.hxx>
30 #include <excdoc.hxx>
31 #include <xeextlst.hxx>
32 #include <biffhelper.hxx>
34 #include <xcl97rec.hxx>
35 #include <xetable.hxx>
36 #include <xelink.hxx>
37 #include <xepage.hxx>
38 #include <xeview.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>
47 #include <xlname.hxx>
48 #include <xllink.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>
56 #include <memory>
58 using namespace oox;
60 static OUString lcl_GetVbaTabName( SCTAB n )
62 OUString aRet = "__VBA__" + OUString::number( static_cast<sal_uInt16>(n) );
63 return aRet;
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 )
106 // Scenarios
107 aRecList.AppendNewRecord( new ExcEScenarioManager( rRoot, nScTab ) );
108 // filter
109 aRecList.AppendRecord( rRoot.GetFilterManager().CreateRecord( nScTab ) );
112 ExcTable::ExcTable( const XclExpRoot& rRoot ) :
113 XclExpRoot( rRoot ),
114 mnScTab( SCTAB_GLOBAL ),
115 nExcTab( EXC_NOTAB ),
116 mxNoteList( new XclExpNoteList )
120 ExcTable::ExcTable( const XclExpRoot& rRoot, SCTAB nScTab ) :
121 XclExpRoot( rRoot ),
122 mnScTab( 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 )
140 InitializeGlobals();
142 RootData& rR = GetOldRoot();
143 ScDocument& rDoc = GetDoc();
144 XclExpTabInfo& rTabInfo = GetTabInfo();
146 if ( GetBiff() <= EXC_BIFF5 )
147 Add( new ExcBofW );
148 else
149 Add( new ExcBofW8 );
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 );
173 else
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 ) );
191 Add( rR.pTabId );
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 );
240 else
242 // BIFF8
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 ) );
255 SCTAB nC;
256 SCTAB nScTabCount = rTabInfo.GetScTabCount();
257 if( GetBiff() <= EXC_BIFF5 )
259 // Bundlesheet
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 );
268 else
270 // Pivot Cache
271 GetPivotTableManager().CreatePivotTables();
272 aRecList.AppendRecord( GetPivotTableManager().CreatePivotCachesRecord() );
274 // Change tracking
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() ) );
284 // Bundlesheet
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 );
293 OUString aTmpString;
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 );
319 Add( new ExcEof );
322 void ExcTable::FillAsHeaderXml( ExcBoundsheetList& rBoundsheetList )
324 InitializeGlobals();
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 ) );
334 Add( rR.pTabId );
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 ) );
363 // Change tracking
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 );
373 // Bundlesheet
374 SCTAB nC;
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 ) );
386 OUString aTmpString;
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() );
425 //export cell notes
426 std::vector<sc::NoteEntry> aNotes;
427 rDoc.GetAllNoteEntries(aNotes);
428 for (const auto& rNote : aNotes)
430 if (rNote.maPos.Tab() != mnScTab)
431 continue;
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 )
442 Add( new ExcBof );
443 Add( new ExcDummy_02a );
445 else
447 Add( new ExcBof8 );
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 ) );
487 // label ranges
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 ) ) );
497 // pivot tables
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
513 if (pTabProtect)
515 const ::std::vector<ScEnhancedProtection>& rProts( pTabProtect->getEnhancedProtection());
516 for (const auto& rProt : rProts)
518 Add( new XclExpSheetEnhancedProtection( GetRoot(), rProt));
522 // web queries
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 ) );
536 // change tracking
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 );
547 // EOF
548 Add( new ExcEof );
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() );
566 //export cell notes
567 std::vector<sc::NoteEntry> aNotes;
568 rDoc.GetAllNoteEntries(aNotes);
569 for (const auto& rNote : aNotes)
571 if (rNote.maPos.Tab() != mnScTab)
572 continue;
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();
636 if (pImgData)
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())) )
650 return;
652 if( GetBiff() <= EXC_BIFF5 )
654 Add( new ExcBof );
656 else
658 Add( new ExcBof8 );
659 Add( new XclCodename( GetExtDocOptions().GetCodeName( nCodeNameIdx ) ) );
661 // sheet view settings: WINDOW2, SCL, PANE, SELECTION
662 aRecList.AppendNewRecord( new XclExpTabViewSettings( GetRoot(), mnScTab ) );
663 Add( new ExcEof );
666 void ExcTable::Write( XclExpStream& rStrm )
668 SetCurrScTab( mnScTab );
669 if( mxCellTable )
670 mxCellTable->Finalize(true);
671 aRecList.Save( rStrm );
674 void ExcTable::WriteXml( XclExpXmlStream& rStrm )
676 if (!GetTabInfo().IsExportTab(mnScTab))
678 // header export.
679 SetCurrScTab(mnScTab);
680 if (mxCellTable)
681 mxCellTable->Finalize(false);
682 aRecList.SaveXml(rStrm);
684 return;
687 // worksheet export
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 );
703 if (mxCellTable)
704 mxCellTable->Finalize(false);
705 aRecList.SaveXml( rStrm );
707 XclExpXmlPivotTables* pPT = GetXmlPivotTableManager().GetTablesBySheet(mnScTab);
708 if (pPT)
709 pPT->SaveXml(rStrm);
711 rStrm.GetCurrentStream()->endElement( XML_worksheet );
712 rStrm.PopStream();
715 ExcDocument::ExcDocument( const XclExpRoot& rRoot ) :
716 XclExpRoot( rRoot ),
717 aHeader( rRoot )
721 ExcDocument::~ExcDocument()
723 maTableList.RemoveAllRecords(); // for the following assertion!
726 void ExcDocument::ReadDoc()
728 InitializeConvert();
730 if (GetOutput() == EXC_OUTPUT_BINARY)
731 aHeader.FillAsHeaderBinary(maBoundsheetList);
732 else
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);
750 else
751 xTab->FillAsTableXml();
753 ++nCodeNameIdx;
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();
768 // change tracking
769 if ( GetDoc().GetChangeTrack() )
770 m_xExpChangeTrack.reset(new XclExpChangeTrack( GetRoot() ));
774 void ExcDocument::Write( SvStream& rSvStrm )
776 if( !maTableList.IsEmpty() )
778 InitializeSave();
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 );
791 if( xBoundsheet )
792 xBoundsheet->SetStreamPos( aXclStrm.GetSvStreamPos() );
793 // write the table
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,
841 XML_appName, "Calc"
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() )
862 InitializeSave();
864 aHeader.WriteXml( rStrm );
866 for( size_t nTab = 0, nTabCount = maTableList.GetSize(); nTab < nTabCount; ++nTab )
868 // write the table
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 );
902 rWorkbook.reset();
905 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */