LibreOffice Module sc (master)  1
xelink.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <xelink.hxx>
21 
22 #include <algorithm>
23 #include <formula/errorcodes.hxx>
24 #include <oox/token/namespaces.hxx>
27 #include <svl/zforlist.hxx>
28 #include <sal/log.hxx>
29 #include <document.hxx>
30 #include <scextopt.hxx>
31 #include <externalrefmgr.hxx>
32 #include <tokenarray.hxx>
33 #include <xecontent.hxx>
34 #include <xeformula.hxx>
35 #include <xehelper.hxx>
36 #include <xllink.hxx>
37 #include <xltools.hxx>
38 
39 #include <vector>
40 #include <memory>
41 
42 using ::std::unique_ptr;
43 using ::std::vector;
44 using ::com::sun::star::uno::Any;
45 
46 using namespace oox;
47 
48 // *** Helper classes ***
49 
50 // External names =============================================================
51 
52 namespace {
53 
56 class XclExpExtNameBase : public XclExpRecord, protected XclExpRoot
57 {
58 public:
60  explicit XclExpExtNameBase( const XclExpRoot& rRoot,
61  const OUString& rName, sal_uInt16 nFlags = 0 );
62 
64  const OUString& GetName() const { return maName; }
65 
66 private:
68  virtual void WriteBody( XclExpStream& rStrm ) override;
71  virtual void WriteAddData( XclExpStream& rStrm );
72 
73 protected:
74  OUString maName;
75  XclExpStringRef mxName;
76  sal_uInt16 mnFlags;
77 };
78 
80 class XclExpExtNameAddIn : public XclExpExtNameBase
81 {
82 public:
83  explicit XclExpExtNameAddIn( const XclExpRoot& rRoot, const OUString& rName );
84 
85 private:
87  virtual void WriteAddData( XclExpStream& rStrm ) override;
88 };
89 
91 class XclExpExtNameDde : public XclExpExtNameBase
92 {
93 public:
94  explicit XclExpExtNameDde( const XclExpRoot& rRoot, const OUString& rName,
95  sal_uInt16 nFlags, const ScMatrix* pResults = nullptr );
96 
97 private:
99  virtual void WriteAddData( XclExpStream& rStrm ) override;
100 
101 private:
102  typedef std::shared_ptr< XclExpCachedMatrix > XclExpCachedMatRef;
103  XclExpCachedMatRef mxMatrix;
104 };
105 
106 class XclExpSupbook;
107 
108 class XclExpExtName : public XclExpExtNameBase
109 {
110 public:
111  explicit XclExpExtName( const XclExpRoot& rRoot, const XclExpSupbook& rSupbook, const OUString& rName,
112  const ScExternalRefCache::TokenArrayRef& rArray );
113 
114  virtual void SaveXml(XclExpXmlStream& rStrm) override;
115 
116 private:
118  virtual void WriteAddData( XclExpStream& rStrm ) override;
119 
120 private:
121  const XclExpSupbook& mrSupbook;
122  unique_ptr<ScTokenArray> mpArray;
123 };
124 
125 // List of external names =====================================================
126 
128 class XclExpExtNameBuffer : public XclExpRecordBase, protected XclExpRoot
129 {
130 public:
131  explicit XclExpExtNameBuffer( const XclExpRoot& rRoot );
132 
135  sal_uInt16 InsertAddIn( const OUString& rName );
137  sal_uInt16 InsertEuroTool( const OUString& rName );
140  sal_uInt16 InsertDde( const OUString& rApplic, const OUString& rTopic, const OUString& rItem );
141 
142  sal_uInt16 InsertExtName( const XclExpSupbook& rSupbook, const OUString& rName, const ScExternalRefCache::TokenArrayRef& rArray );
143 
145  virtual void Save( XclExpStream& rStrm ) override;
146 
147  virtual void SaveXml(XclExpXmlStream& rStrm) override;
148 
149 private:
151  sal_uInt16 GetIndex( const OUString& rName ) const;
154  sal_uInt16 AppendNew( XclExpExtNameBase* pExtName );
155 
157 };
158 
159 // Cached external cells ======================================================
160 
162 class XclExpCrn : public XclExpRecord
163 {
164 public:
165  explicit XclExpCrn( SCCOL nScCol, SCROW nScRow, const Any& rValue );
166 
168  bool InsertValue( SCCOL nScCol, SCROW nScRow, const Any& rValue );
169 
171  virtual void SaveXml( XclExpXmlStream& rStrm ) override;
172 
173 private:
174  virtual void WriteBody( XclExpStream& rStrm ) override;
175 
176  static void WriteBool( XclExpStream& rStrm, bool bValue );
177  static void WriteDouble( XclExpStream& rStrm, double fValue );
178  static void WriteString( XclExpStream& rStrm, const OUString& rValue );
179  static void WriteError( XclExpStream& rStrm, sal_uInt8 nErrCode );
180  static void WriteEmpty( XclExpStream& rStrm );
181 
182 private:
183  typedef ::std::vector< Any > CachedValues;
184 
185  CachedValues maValues;
186  SCCOL mnScCol;
187  SCROW mnScRow;
188 };
189 
190 class XclExpCrnList;
191 
194 class XclExpXct : public XclExpRecordBase, protected XclExpRoot
195 {
196 public:
197  explicit XclExpXct( const XclExpRoot& rRoot,
198  const OUString& rTabName, sal_uInt16 nSBTab,
199  ScExternalRefCache::TableTypeRef const & xCacheTable );
200 
202  const XclExpString& GetTabName() const { return maTabName; }
203 
205  void StoreCellRange( const ScRange& rRange );
206 
207  void StoreCell_( const ScAddress& rCell );
208  void StoreCellRange_( const ScRange& rRange );
209 
211  virtual void Save( XclExpStream& rStrm ) override;
212 
214  virtual void SaveXml( XclExpXmlStream& rStrm ) override;
215 
216 private:
218  ScMarkData maUsedCells;
219  ScRange maBoundRange;
220  XclExpString maTabName;
221  sal_uInt16 mnSBTab;
222 
224  bool BuildCrnList( XclExpCrnList& rCrnRecs );
225 };
226 
227 // External documents (EXTERNSHEET/SUPBOOK), base class =======================
228 
236 class XclExpExternSheetBase : public XclExpRecord, protected XclExpRoot
237 {
238 public:
239  explicit XclExpExternSheetBase( const XclExpRoot& rRoot,
240  sal_uInt16 nRecId, sal_uInt32 nRecSize = 0 );
241 
242 protected:
244  XclExpExtNameBuffer& GetExtNameBuffer();
246  void WriteExtNameBuffer( XclExpStream& rStrm );
248  void WriteExtNameBufferXml( XclExpXmlStream& rStrm );
249 
250 protected:
251  typedef std::shared_ptr< XclExpExtNameBuffer > XclExpExtNameBfrRef;
252  XclExpExtNameBfrRef mxExtNameBfr;
253 };
254 
255 // External documents (EXTERNSHEET, BIFF5/BIFF7) ==============================
256 
260 class XclExpExternSheet : public XclExpExternSheetBase
261 {
262 public:
264  explicit XclExpExternSheet( const XclExpRoot& rRoot, sal_Unicode cCode );
266  explicit XclExpExternSheet( const XclExpRoot& rRoot, const OUString& rTabName );
267 
270  sal_uInt16 InsertAddIn( const OUString& rName );
271 
273  virtual void Save( XclExpStream& rStrm ) override;
274 
275 private:
277  void Init( const OUString& rEncUrl );
279  virtual void WriteBody( XclExpStream& rStrm ) override;
280 
281 private:
282  XclExpString maTabName;
283 };
284 
285 // External documents (SUPBOOK, BIFF8) ========================================
286 
288 class XclExpSupbook : public XclExpExternSheetBase
289 {
290 public:
292  explicit XclExpSupbook( const XclExpRoot& rRoot, sal_uInt16 nXclTabCount );
294  explicit XclExpSupbook( const XclExpRoot& rRoot );
296  explicit XclExpSupbook( const XclExpRoot& rRoot, const OUString& rUrl, XclSupbookType );
298  explicit XclExpSupbook( const XclExpRoot& rRoot, const OUString& rUrl );
300  explicit XclExpSupbook( const XclExpRoot& rRoot, const OUString& rApplic, const OUString& rTopic );
301 
303  bool IsUrlLink( const OUString& rUrl ) const;
305  bool IsDdeLink( const OUString& rApplic, const OUString& rTopic ) const;
307  void FillRefLogEntry( XclExpRefLogEntry& rRefLogEntry,
308  sal_uInt16 nFirstSBTab, sal_uInt16 nLastSBTab ) const;
309 
311  void StoreCellRange( const ScRange& rRange, sal_uInt16 nSBTab );
312 
313  void StoreCell_( sal_uInt16 nSBTab, const ScAddress& rCell );
314  void StoreCellRange_( sal_uInt16 nSBTab, const ScRange& rRange );
315 
316  sal_uInt16 GetTabIndex( const OUString& rTabName ) const;
317  sal_uInt16 GetTabCount() const;
318 
320  sal_uInt16 InsertTabName( const OUString& rTabName, ScExternalRefCache::TableTypeRef const & xCacheTable );
323  sal_uInt16 InsertAddIn( const OUString& rName );
325  sal_uInt16 InsertEuroTool( const OUString& rName );
328  sal_uInt16 InsertDde( const OUString& rItem );
329 
330  sal_uInt16 InsertExtName( const OUString& rName, const ScExternalRefCache::TokenArrayRef& rArray );
331 
333  XclSupbookType GetType() const;
334 
336  sal_uInt16 GetFileId() const;
337 
339  const OUString& GetUrl() const;
340 
342  virtual void Save( XclExpStream& rStrm ) override;
343 
345  virtual void SaveXml( XclExpXmlStream& rStrm ) override;
346 
347 private:
349  const XclExpString* GetTabName( sal_uInt16 nSBTab ) const;
350 
352  virtual void WriteBody( XclExpStream& rStrm ) override;
353 
354 private:
355  typedef XclExpRecordList< XclExpXct > XclExpXctList;
356  typedef XclExpXctList::RecordRefType XclExpXctRef;
357 
358  XclExpXctList maXctList;
359  OUString maUrl;
360  OUString maDdeTopic;
361  XclExpString maUrlEncoded;
363  sal_uInt16 mnXclTabCount;
364  sal_uInt16 mnFileId;
365 };
366 
367 // All SUPBOOKS in a document =================================================
368 
372 struct XclExpXti
373 {
374  sal_uInt16 mnSupbook;
375  sal_uInt16 mnFirstSBTab;
376  sal_uInt16 mnLastSBTab;
377 
378  explicit XclExpXti() : mnSupbook( 0 ), mnFirstSBTab( 0 ), mnLastSBTab( 0 ) {}
379  explicit XclExpXti( sal_uInt16 nSupbook, sal_uInt16 nFirstSBTab, sal_uInt16 nLastSBTab ) :
380  mnSupbook( nSupbook ), mnFirstSBTab( nFirstSBTab ), mnLastSBTab( nLastSBTab ) {}
381 
383  void Save( XclExpStream& rStrm ) const
384  { rStrm << mnSupbook << mnFirstSBTab << mnLastSBTab; }
385 };
386 
387 bool operator==( const XclExpXti& rLeft, const XclExpXti& rRight )
388 {
389  return
390  (rLeft.mnSupbook == rRight.mnSupbook) &&
391  (rLeft.mnFirstSBTab == rRight.mnFirstSBTab) &&
392  (rLeft.mnLastSBTab == rRight.mnLastSBTab);
393 }
394 
396 class XclExpSupbookBuffer : public XclExpRecordBase, protected XclExpRoot
397 {
398 public:
399  explicit XclExpSupbookBuffer( const XclExpRoot& rRoot );
400 
403  XclExpXti GetXti( sal_uInt16 nFirstXclTab, sal_uInt16 nLastXclTab,
404  XclExpRefLogEntry* pRefLogEntry = nullptr ) const;
405 
407  void StoreCellRange( const ScRange& rRange );
408 
409  void StoreCell( sal_uInt16 nFileId, const OUString& rTabName, const ScAddress& rCell );
410  void StoreCellRange( sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange );
411 
415  bool InsertAddIn(
416  sal_uInt16& rnSupbook, sal_uInt16& rnExtName,
417  const OUString& rName );
419  bool InsertEuroTool(
420  sal_uInt16& rnSupbook, sal_uInt16& rnExtName,
421  const OUString& rName );
425  bool InsertDde(
426  sal_uInt16& rnSupbook, sal_uInt16& rnExtName,
427  const OUString& rApplic, const OUString& rTopic, const OUString& rItem );
428 
429  bool InsertExtName(
430  sal_uInt16& rnSupbook, sal_uInt16& rnExtName, const OUString& rUrl,
431  const OUString& rName, const ScExternalRefCache::TokenArrayRef& rArray );
432 
433  XclExpXti GetXti( sal_uInt16 nFileId, const OUString& rTabName, sal_uInt16 nXclTabSpan,
434  XclExpRefLogEntry* pRefLogEntry );
435 
437  virtual void Save( XclExpStream& rStrm ) override;
438 
440  virtual void SaveXml( XclExpXmlStream& rStrm ) override;
441 
443  bool HasExternalReferences() const;
444 
445  struct XclExpSBIndex
446  {
447  sal_uInt16 mnSupbook;
448  sal_uInt16 mnSBTab;
449  void Set( sal_uInt16 nSupbook, sal_uInt16 nSBTab )
450  { mnSupbook = nSupbook; mnSBTab = nSBTab; }
451  };
452 
453 private:
454  typedef XclExpRecordList< XclExpSupbook > XclExpSupbookList;
455  typedef XclExpSupbookList::RecordRefType XclExpSupbookRef;
456 
457 private:
462  bool GetSupbookUrl( XclExpSupbookRef& rxSupbook, sal_uInt16& rnIndex,
463  const OUString& rUrl ) const;
468  bool GetSupbookDde( XclExpSupbookRef& rxSupbook, sal_uInt16& rnIndex,
469  const OUString& rApplic, const OUString& rTopic ) const;
470 
473  sal_uInt16 Append( XclExpSupbookRef const & xSupbook );
474 
475 private:
476  XclExpSupbookList maSupbookList;
477  std::vector< XclExpSBIndex >
478  maSBIndexVec;
479  sal_uInt16 mnOwnDocSB;
480  sal_uInt16 mnAddInSB;
481 };
482 
483 }
484 
485 // Export link manager ========================================================
486 
489 {
490 public:
492  virtual void FindExtSheet( sal_uInt16& rnExtSheet,
493  sal_uInt16& rnFirstXclTab, sal_uInt16& rnLastXclTab,
494  SCTAB nFirstScTab, SCTAB nLastScTab,
495  XclExpRefLogEntry* pRefLogEntry ) = 0;
497  virtual sal_uInt16 FindExtSheet( sal_Unicode cCode ) = 0;
498 
499  virtual void FindExtSheet( sal_uInt16 nFileId, const OUString& rTabName, sal_uInt16 nXclTabSpan,
500  sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
501  XclExpRefLogEntry* pRefLogEntry ) = 0;
502 
504  virtual void StoreCellRange( const ScSingleRefData& rRef1, const ScSingleRefData& rRef2, const ScAddress& rPos ) = 0;
505 
506  virtual void StoreCell( sal_uInt16 nFileId, const OUString& rTabName, const ScAddress& rPos ) = 0;
507  virtual void StoreCellRange( sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange ) = 0;
508 
510  virtual bool InsertAddIn(
511  sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
512  const OUString& rName ) = 0;
514  virtual bool InsertEuroTool(
515  sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
516  const OUString& rName ) = 0;
517 
519  virtual bool InsertDde(
520  sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
521  const OUString& rApplic, const OUString& rTopic, const OUString& rItem ) = 0;
522 
523  virtual bool InsertExtName(
524  sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rUrl,
525  const OUString& rName, const ScExternalRefCache::TokenArrayRef& rArray ) = 0;
526 
528  virtual void Save( XclExpStream& rStrm ) = 0;
529 
531  virtual void SaveXml( XclExpXmlStream& rStrm ) = 0;
532 
533 protected:
534  explicit XclExpLinkManagerImpl( const XclExpRoot& rRoot );
535 };
536 
537 namespace {
538 
540 class XclExpLinkManagerImpl5 : public XclExpLinkManagerImpl
541 {
542 public:
543  explicit XclExpLinkManagerImpl5( const XclExpRoot& rRoot );
544 
545  virtual void FindExtSheet( sal_uInt16& rnExtSheet,
546  sal_uInt16& rnFirstXclTab, sal_uInt16& rnLastXclTab,
547  SCTAB nFirstScTab, SCTAB nLastScTab,
548  XclExpRefLogEntry* pRefLogEntry ) override;
549  virtual sal_uInt16 FindExtSheet( sal_Unicode cCode ) override;
550 
551  virtual void FindExtSheet( sal_uInt16 nFileId, const OUString& rTabName, sal_uInt16 nXclTabSpan,
552  sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
553  XclExpRefLogEntry* pRefLogEntry ) override;
554 
555  virtual void StoreCellRange( const ScSingleRefData& rRef1, const ScSingleRefData& rRef2, const ScAddress& rPos ) override;
556 
557  virtual void StoreCell( sal_uInt16 nFileId, const OUString& rTabName, const ScAddress& rPos ) override;
558  virtual void StoreCellRange( sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange ) override;
559 
560  virtual bool InsertAddIn(
561  sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
562  const OUString& rName ) override;
563 
565  virtual bool InsertEuroTool(
566  sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
567  const OUString& rName ) override;
568 
569  virtual bool InsertDde(
570  sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
571  const OUString& rApplic, const OUString& rTopic, const OUString& rItem ) override;
572 
573  virtual bool InsertExtName(
574  sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rUrl,
575  const OUString& rName, const ScExternalRefCache::TokenArrayRef& rArray ) override;
576 
577  virtual void Save( XclExpStream& rStrm ) override;
578 
579  virtual void SaveXml( XclExpXmlStream& rStrm ) override;
580 
581 private:
582  typedef XclExpRecordList< XclExpExternSheet > XclExpExtSheetList;
583  typedef XclExpExtSheetList::RecordRefType XclExpExtSheetRef;
584  typedef ::std::map< SCTAB, sal_uInt16 > XclExpIntTabMap;
585  typedef ::std::map< sal_Unicode, sal_uInt16 > XclExpCodeMap;
586 
587 private:
589  sal_uInt16 GetExtSheetCount() const;
590 
592  sal_uInt16 AppendInternal( XclExpExtSheetRef const & xExtSheet );
594  void CreateInternal();
595 
597  XclExpExtSheetRef GetInternal( sal_uInt16 nExtSheet );
599  XclExpExtSheetRef FindInternal( sal_uInt16& rnExtSheet, sal_uInt16& rnXclTab, SCTAB nScTab );
601  XclExpExtSheetRef FindInternal( sal_uInt16& rnExtSheet, sal_Unicode cCode );
602 
603 private:
604  XclExpExtSheetList maExtSheetList;
605  XclExpIntTabMap maIntTabMap;
606  XclExpCodeMap maCodeMap;
607 };
608 
610 class XclExpLinkManagerImpl8 : public XclExpLinkManagerImpl
611 {
612 public:
613  explicit XclExpLinkManagerImpl8( const XclExpRoot& rRoot );
614 
615  virtual void FindExtSheet( sal_uInt16& rnExtSheet,
616  sal_uInt16& rnFirstXclTab, sal_uInt16& rnLastXclTab,
617  SCTAB nFirstScTab, SCTAB nLastScTab,
618  XclExpRefLogEntry* pRefLogEntry ) override;
619  virtual sal_uInt16 FindExtSheet( sal_Unicode cCode ) override;
620 
621  virtual void FindExtSheet( sal_uInt16 nFileId, const OUString& rTabName, sal_uInt16 nXclTabSpan,
622  sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
623  XclExpRefLogEntry* pRefLogEntry ) override;
624 
625  virtual void StoreCellRange( const ScSingleRefData& rRef1, const ScSingleRefData& rRef2, const ScAddress& rPos ) override;
626 
627  virtual void StoreCell( sal_uInt16 nFileId, const OUString& rTabName, const ScAddress& rPos ) override;
628  virtual void StoreCellRange( sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange ) override;
629 
630  virtual bool InsertAddIn(
631  sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
632  const OUString& rName ) override;
634  virtual bool InsertEuroTool(
635  sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
636  const OUString& rName ) override;
637 
638  virtual bool InsertDde(
639  sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
640  const OUString& rApplic, const OUString& rTopic, const OUString& rItem ) override;
641 
642  virtual bool InsertExtName(
643  sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rUrl,
644  const OUString& rName, const ScExternalRefCache::TokenArrayRef& rArray ) override;
645 
646  virtual void Save( XclExpStream& rStrm ) override;
647 
648  virtual void SaveXml( XclExpXmlStream& rStrm ) override;
649 
650 private:
653  sal_uInt16 InsertXti( const XclExpXti& rXti );
654 
655 private:
656 
657  XclExpSupbookBuffer maSBBuffer;
658  std::vector< XclExpXti > maXtiVec;
659 };
660 
661 }
662 
663 // *** Implementation ***
664 
665 // Excel sheet indexes ========================================================
666 
667 
669  XclExpRoot( rRoot ),
670  mnScCnt( 0 ),
671  mnXclCnt( 0 ),
672  mnXclExtCnt( 0 ),
673  mnXclSelCnt( 0 ),
674  mnDisplXclTab( 0 ),
675  mnFirstVisXclTab( 0 )
676 {
677  ScDocument& rDoc = GetDoc();
678  ScExtDocOptions& rDocOpt = GetExtDocOptions();
679 
680  mnScCnt = rDoc.GetTableCount();
681 
682  SCTAB nScTab;
683  SCTAB nFirstVisScTab = SCTAB_INVALID; // first visible sheet
684  SCTAB nFirstExpScTab = SCTAB_INVALID; // first exported sheet
685 
686  // --- initialize the flags in the index buffer ---
687 
688  maTabInfoVec.resize( mnScCnt );
689  for( nScTab = 0; nScTab < mnScCnt; ++nScTab )
690  {
691  // ignored sheets (skipped by export, with invalid Excel sheet index)
692  if( rDoc.IsScenario( nScTab ) )
693  {
694  SetFlag( nScTab, ExcTabBufFlags::Ignore );
695  }
696 
697  // external sheets (skipped, but with valid Excel sheet index for ref's)
698  else if( rDoc.GetLinkMode( nScTab ) == ScLinkMode::VALUE )
699  {
700  SetFlag( nScTab, ExcTabBufFlags::Extern );
701  }
702 
703  // exported sheets
704  else
705  {
706  // sheet name
707  rDoc.GetName( nScTab, maTabInfoVec[ nScTab ].maScName );
708 
709  // remember first exported sheet
710  if( nFirstExpScTab == SCTAB_INVALID )
711  nFirstExpScTab = nScTab;
712  // remember first visible exported sheet
713  if( (nFirstVisScTab == SCTAB_INVALID) && rDoc.IsVisible( nScTab ) )
714  nFirstVisScTab = nScTab;
715 
716  // sheet visible (only exported sheets)
717  SetFlag( nScTab, ExcTabBufFlags::Visible, rDoc.IsVisible( nScTab ) );
718 
719  // sheet selected (only exported sheets)
720  if( const ScExtTabSettings* pTabSett = rDocOpt.GetTabSettings( nScTab ) )
721  SetFlag( nScTab, ExcTabBufFlags::Selected, pTabSett->mbSelected );
722 
723  // sheet mirrored (only exported sheets)
724  SetFlag( nScTab, ExcTabBufFlags::Mirrored, rDoc.IsLayoutRTL( nScTab ) );
725  }
726  }
727 
728  // --- visible/selected sheets ---
729 
730  SCTAB nDisplScTab = rDocOpt.GetDocSettings().mnDisplTab;
731 
732  // missing viewdata at embedded XLSX OLE objects
733  if (nDisplScTab == -1 )
734  nDisplScTab = rDoc.GetVisibleTab();
735 
736  // find first visible exported sheet
737  if( (nFirstVisScTab == SCTAB_INVALID) || !IsExportTab( nFirstVisScTab ) )
738  {
739  // no exportable visible sheet -> use first exportable sheet
740  nFirstVisScTab = nFirstExpScTab;
741  if( (nFirstVisScTab == SCTAB_INVALID) || !IsExportTab( nFirstVisScTab ) )
742  {
743  // no exportable sheet at all -> use active sheet and export it
744  nFirstVisScTab = nDisplScTab;
745  SetFlag( nFirstVisScTab, ExcTabBufFlags::SkipMask, false ); // clear skip flags
746  }
747  SetFlag( nFirstVisScTab, ExcTabBufFlags::Visible ); // must be visible, even if originally hidden
748  }
749 
750  // find currently displayed sheet
751  if( !IsExportTab( nDisplScTab ) ) // selected sheet not exported (i.e. scenario) -> use first visible
752  nDisplScTab = nFirstVisScTab;
754 
755  // number of selected sheets
756  for( nScTab = 0; nScTab < mnScCnt; ++nScTab )
757  if( IsSelectedTab( nScTab ) )
758  ++mnXclSelCnt;
759 
760  // --- calculate resulting Excel sheet indexes ---
761 
762  CalcXclIndexes();
763  mnFirstVisXclTab = GetXclTab( nFirstVisScTab );
764  mnDisplXclTab = GetXclTab( nDisplScTab );
765 
766  // --- sorted vectors for index lookup ---
767 
769 }
770 
771 bool XclExpTabInfo::IsExportTab( SCTAB nScTab ) const
772 {
773  /* Check sheet index before to avoid assertion in GetFlag(). */
774  return (nScTab < mnScCnt && nScTab >= 0) && !GetFlag( nScTab, ExcTabBufFlags::SkipMask );
775 }
776 
778 {
779  /* Check sheet index before to avoid assertion (called from formula
780  compiler also for deleted references). */
781  return (nScTab < mnScCnt && nScTab >= 0) && GetFlag( nScTab, ExcTabBufFlags::Extern );
782 }
783 
784 bool XclExpTabInfo::IsVisibleTab( SCTAB nScTab ) const
785 {
786  return GetFlag( nScTab, ExcTabBufFlags::Visible );
787 }
788 
790 {
791  return GetFlag( nScTab, ExcTabBufFlags::Selected );
792 }
793 
795 {
796  OSL_ENSURE( nScTab < mnScCnt && nScTab >= 0, "XclExpTabInfo::IsActiveTab - sheet out of range" );
797  return GetXclTab( nScTab ) == mnDisplXclTab;
798 }
799 
801 {
802  return GetFlag( nScTab, ExcTabBufFlags::Mirrored );
803 }
804 
805 OUString XclExpTabInfo::GetScTabName( SCTAB nScTab ) const
806 {
807  OSL_ENSURE( nScTab < mnScCnt && nScTab >= 0, "XclExpTabInfo::IsActiveTab - sheet out of range" );
808  return (nScTab < mnScCnt && nScTab >= 0) ? maTabInfoVec[ nScTab ].maScName : OUString();
809 }
810 
811 sal_uInt16 XclExpTabInfo::GetXclTab( SCTAB nScTab ) const
812 {
813  return (nScTab < mnScCnt && nScTab >= 0) ? maTabInfoVec[ nScTab ].mnXclTab : EXC_TAB_DELETED;
814 }
815 
817 {
818  OSL_ENSURE( nSortedScTab < mnScCnt && nSortedScTab >= 0, "XclExpTabInfo::GetRealScTab - sheet out of range" );
819  return (nSortedScTab < mnScCnt && nSortedScTab >= 0) ? maFromSortedVec[ nSortedScTab ] : SCTAB_INVALID;
820 }
821 
822 bool XclExpTabInfo::GetFlag( SCTAB nScTab, ExcTabBufFlags nFlags ) const
823 {
824  OSL_ENSURE( nScTab < mnScCnt && nScTab >= 0, "XclExpTabInfo::GetFlag - sheet out of range" );
825  return (nScTab < mnScCnt && nScTab >= 0) && (maTabInfoVec[ nScTab ].mnFlags & nFlags);
826 }
827 
828 void XclExpTabInfo::SetFlag( SCTAB nScTab, ExcTabBufFlags nFlags, bool bSet )
829 {
830  OSL_ENSURE( nScTab < mnScCnt && nScTab >= 0, "XclExpTabInfo::SetFlag - sheet out of range" );
831  if( nScTab < mnScCnt && nScTab >= 0 )
832  {
833  if (bSet)
834  maTabInfoVec[ nScTab ].mnFlags |= nFlags;
835  else
836  maTabInfoVec[ nScTab ].mnFlags &= ~nFlags;
837  }
838 }
839 
841 {
842  sal_uInt16 nXclTab = 0;
843  SCTAB nScTab = 0;
844 
845  // --- pass 1: process regular sheets ---
846  for( nScTab = 0; nScTab < mnScCnt; ++nScTab )
847  {
848  if( IsExportTab( nScTab ) )
849  {
850  maTabInfoVec[ nScTab ].mnXclTab = nXclTab;
851  ++nXclTab;
852  }
853  else
854  maTabInfoVec[ nScTab ].mnXclTab = EXC_TAB_DELETED;
855  }
856  mnXclCnt = nXclTab;
857 
858  // --- pass 2: process external sheets (nXclTab continues) ---
859  for( nScTab = 0; nScTab < mnScCnt; ++nScTab )
860  {
861  if( IsExternalTab( nScTab ) )
862  {
863  maTabInfoVec[ nScTab ].mnXclTab = nXclTab;
864  ++nXclTab;
865  ++mnXclExtCnt;
866  }
867  }
868 
869  // result: first occur all exported sheets, followed by all external sheets
870 }
871 
872 typedef ::std::pair< OUString, SCTAB > XclExpTabName;
873 
874 namespace {
875 
876 struct XclExpTabNameSort {
877  bool operator ()( const XclExpTabName& rArg1, const XclExpTabName& rArg2 )
878  {
879  // compare the sheet names only
880  return ScGlobal::GetCollator()->compareString( rArg1.first, rArg2.first ) < 0;
881  }
882 };
883 
884 }
885 
887 {
888  ScDocument& rDoc = GetDoc();
889  ::std::vector< XclExpTabName > aVec( mnScCnt );
890  SCTAB nScTab;
891 
892  // fill with sheet names
893  for( nScTab = 0; nScTab < mnScCnt; ++nScTab )
894  {
895  rDoc.GetName( nScTab, aVec[ nScTab ].first );
896  aVec[ nScTab ].second = nScTab;
897  }
898  ::std::sort( aVec.begin(), aVec.end(), XclExpTabNameSort() );
899 
900  // fill index vectors from sorted sheet name vector
901  maFromSortedVec.resize( mnScCnt );
902  maToSortedVec.resize( mnScCnt );
903  for( nScTab = 0; nScTab < mnScCnt; ++nScTab )
904  {
905  maFromSortedVec[ nScTab ] = aVec[ nScTab ].second;
906  maToSortedVec[ aVec[ nScTab ].second ] = nScTab;
907  }
908 }
909 
910 // External names =============================================================
911 
912 XclExpExtNameBase::XclExpExtNameBase(
913  const XclExpRoot& rRoot, const OUString& rName, sal_uInt16 nFlags ) :
915  XclExpRoot( rRoot ),
916  maName( rName ),
917  mxName( XclExpStringHelper::CreateString( rRoot, rName, XclStrFlags::EightBitLength ) ),
918  mnFlags( nFlags )
919 {
920  OSL_ENSURE( maName.getLength() <= 255, "XclExpExtNameBase::XclExpExtNameBase - string too long" );
921  SetRecSize( 6 + mxName->GetSize() );
922 }
923 
924 void XclExpExtNameBase::WriteBody( XclExpStream& rStrm )
925 {
926  rStrm << mnFlags
927  << sal_uInt32( 0 )
928  << *mxName;
929  WriteAddData( rStrm );
930 }
931 
932 void XclExpExtNameBase::WriteAddData( XclExpStream& /*rStrm*/ )
933 {
934 }
935 
936 XclExpExtNameAddIn::XclExpExtNameAddIn( const XclExpRoot& rRoot, const OUString& rName ) :
937  XclExpExtNameBase( rRoot, rName )
938 {
939  AddRecSize( 4 );
940 }
941 
942 void XclExpExtNameAddIn::WriteAddData( XclExpStream& rStrm )
943 {
944  // write a #REF! error formula
945  rStrm << sal_uInt16( 2 ) << EXC_TOKID_ERR << EXC_ERR_REF;
946 }
947 
948 XclExpExtNameDde::XclExpExtNameDde( const XclExpRoot& rRoot,
949  const OUString& rName, sal_uInt16 nFlags, const ScMatrix* pResults ) :
950  XclExpExtNameBase( rRoot, rName, nFlags )
951 {
952  if( pResults )
953  {
954  mxMatrix = std::make_shared<XclExpCachedMatrix>( *pResults );
955  AddRecSize( mxMatrix->GetSize() );
956  }
957 }
958 
959 void XclExpExtNameDde::WriteAddData( XclExpStream& rStrm )
960 {
961  if( mxMatrix )
962  mxMatrix->Save( rStrm );
963 }
964 
965 XclExpExtName::XclExpExtName( const XclExpRoot& rRoot, const XclExpSupbook& rSupbook,
966  const OUString& rName, const ScExternalRefCache::TokenArrayRef& rArray ) :
967  XclExpExtNameBase( rRoot, rName ),
968  mrSupbook(rSupbook),
969  mpArray(rArray->Clone())
970 {
971 }
972 
973 void XclExpExtName::WriteAddData( XclExpStream& rStrm )
974 {
975  // Write only if it only has a single token that is either a cell or cell
976  // range address. Excel just writes '02 00 1C 17' for all the other types
977  // of external names.
978 
979  using namespace ::formula;
980  do
981  {
982  if (mpArray->GetLen() != 1)
983  break;
984 
985  const formula::FormulaToken* p = mpArray->FirstToken();
986  if (!p->IsExternalRef())
987  break;
988 
989  switch (p->GetType())
990  {
991  case svExternalSingleRef:
992  {
993  const ScSingleRefData& rRef = *p->GetSingleRef();
994  if (rRef.IsTabRel())
995  break;
996 
997  bool bColRel = rRef.IsColRel();
998  bool bRowRel = rRef.IsRowRel();
999  sal_uInt16 nCol = static_cast<sal_uInt16>(rRef.Col());
1000  sal_uInt16 nRow = static_cast<sal_uInt16>(rRef.Row());
1001  if (bColRel) nCol |= 0x4000;
1002  if (bRowRel) nCol |= 0x8000;
1003 
1004  OUString aTabName = p->GetString().getString();
1005  sal_uInt16 nSBTab = mrSupbook.GetTabIndex(aTabName);
1006 
1007  // size is always 9
1008  rStrm << static_cast<sal_uInt16>(9);
1009  // operator token (3A for cell reference)
1010  rStrm << static_cast<sal_uInt8>(0x3A);
1011  // cell address (Excel's address has 2 sheet IDs.)
1012  rStrm << nSBTab << nSBTab << nRow << nCol;
1013  return;
1014  }
1015  case svExternalDoubleRef:
1016  {
1017  const ScComplexRefData& rRef = *p->GetDoubleRef();
1018  const ScSingleRefData& r1 = rRef.Ref1;
1019  const ScSingleRefData& r2 = rRef.Ref2;
1020  if (r1.IsTabRel() || r2.IsTabRel())
1021  break;
1022 
1023  sal_uInt16 nTab1 = r1.Tab();
1024  sal_uInt16 nTab2 = r2.Tab();
1025  bool bCol1Rel = r1.IsColRel();
1026  bool bRow1Rel = r1.IsRowRel();
1027  bool bCol2Rel = r2.IsColRel();
1028  bool bRow2Rel = r2.IsRowRel();
1029 
1030  sal_uInt16 nCol1 = static_cast<sal_uInt16>(r1.Col());
1031  sal_uInt16 nCol2 = static_cast<sal_uInt16>(r2.Col());
1032  sal_uInt16 nRow1 = static_cast<sal_uInt16>(r1.Row());
1033  sal_uInt16 nRow2 = static_cast<sal_uInt16>(r2.Row());
1034  if (bCol1Rel) nCol1 |= 0x4000;
1035  if (bRow1Rel) nCol1 |= 0x8000;
1036  if (bCol2Rel) nCol2 |= 0x4000;
1037  if (bRow2Rel) nCol2 |= 0x8000;
1038 
1039  OUString aTabName = p->GetString().getString();
1040  sal_uInt16 nSBTab = mrSupbook.GetTabIndex(aTabName);
1041 
1042  // size is always 13 (0x0D)
1043  rStrm << static_cast<sal_uInt16>(13);
1044  // operator token (3B for area reference)
1045  rStrm << static_cast<sal_uInt8>(0x3B);
1046  // range (area) address
1047  sal_uInt16 nSBTab2 = nSBTab + nTab2 - nTab1;
1048  rStrm << nSBTab << nSBTab2 << nRow1 << nRow2 << nCol1 << nCol2;
1049  return;
1050  }
1051  default:
1052  ; // nothing
1053  }
1054  }
1055  while (false);
1056 
1057  // special value for #REF! (02 00 1C 17)
1058  rStrm << static_cast<sal_uInt16>(2) << EXC_TOKID_ERR << EXC_ERR_REF;
1059 }
1060 
1061 void XclExpExtName::SaveXml(XclExpXmlStream& rStrm)
1062 {
1063  sax_fastparser::FSHelperPtr pExternalLink = rStrm.GetCurrentStream();
1064 
1065  pExternalLink->startElement(XML_definedName,
1066  XML_name, maName.toUtf8(),
1067  XML_refersTo, nullptr,
1068  XML_sheetId, nullptr);
1069 
1070  pExternalLink->endElement(XML_definedName);
1071 }
1072 
1073 // List of external names =====================================================
1074 
1075 XclExpExtNameBuffer::XclExpExtNameBuffer( const XclExpRoot& rRoot ) :
1076  XclExpRoot( rRoot )
1077 {
1078 }
1079 
1080 sal_uInt16 XclExpExtNameBuffer::InsertAddIn( const OUString& rName )
1081 {
1082  sal_uInt16 nIndex = GetIndex( rName );
1083  return nIndex ? nIndex : AppendNew( new XclExpExtNameAddIn( GetRoot(), rName ) );
1084 }
1085 
1086 sal_uInt16 XclExpExtNameBuffer::InsertEuroTool( const OUString& rName )
1087 {
1088  sal_uInt16 nIndex = GetIndex( rName );
1089  return nIndex ? nIndex : AppendNew( new XclExpExtNameBase( GetRoot(), rName ) );
1090 }
1091 
1092 sal_uInt16 XclExpExtNameBuffer::InsertDde(
1093  const OUString& rApplic, const OUString& rTopic, const OUString& rItem )
1094 {
1095  sal_uInt16 nIndex = GetIndex( rItem );
1096  if( nIndex == 0 )
1097  {
1098  size_t nPos;
1099  if( GetDoc().FindDdeLink( rApplic, rTopic, rItem, SC_DDE_IGNOREMODE, nPos ) )
1100  {
1101  // create the leading 'StdDocumentName' EXTERNNAME record
1102  if( maNameList.IsEmpty() )
1103  AppendNew( new XclExpExtNameDde(
1104  GetRoot(), "StdDocumentName", EXC_EXTN_EXPDDE_STDDOC ) );
1105 
1106  // try to find DDE result array, but create EXTERNNAME record without them too
1107  const ScMatrix* pScMatrix = GetDoc().GetDdeLinkResultMatrix( nPos );
1108  nIndex = AppendNew( new XclExpExtNameDde( GetRoot(), rItem, EXC_EXTN_EXPDDE, pScMatrix ) );
1109  }
1110  }
1111  return nIndex;
1112 }
1113 
1114 sal_uInt16 XclExpExtNameBuffer::InsertExtName( const XclExpSupbook& rSupbook,
1115  const OUString& rName, const ScExternalRefCache::TokenArrayRef& rArray )
1116 {
1117  sal_uInt16 nIndex = GetIndex( rName );
1118  return nIndex ? nIndex : AppendNew( new XclExpExtName( GetRoot(), rSupbook, rName, rArray ) );
1119 }
1120 
1121 void XclExpExtNameBuffer::Save( XclExpStream& rStrm )
1122 {
1123  maNameList.Save( rStrm );
1124 }
1125 
1126 void XclExpExtNameBuffer::SaveXml(XclExpXmlStream& rStrm)
1127 {
1128  maNameList.SaveXml(rStrm);
1129 }
1130 
1131 sal_uInt16 XclExpExtNameBuffer::GetIndex( const OUString& rName ) const
1132 {
1133  for( size_t nPos = 0, nSize = maNameList.GetSize(); nPos < nSize; ++nPos )
1134  if( maNameList.GetRecord( nPos )->GetName() == rName )
1135  return static_cast< sal_uInt16 >( nPos + 1 );
1136  return 0;
1137 }
1138 
1139 sal_uInt16 XclExpExtNameBuffer::AppendNew( XclExpExtNameBase* pExtName )
1140 {
1141  size_t nSize = maNameList.GetSize();
1142  if( nSize < 0x7FFF )
1143  {
1144  maNameList.AppendRecord( pExtName );
1145  return static_cast< sal_uInt16 >( nSize + 1 );
1146  }
1147  return 0;
1148 }
1149 
1150 // Cached external cells ======================================================
1151 
1152 XclExpCrn::XclExpCrn( SCCOL nScCol, SCROW nScRow, const Any& rValue ) :
1153  XclExpRecord( EXC_ID_CRN, 4 ),
1154  mnScCol( nScCol ),
1155  mnScRow( nScRow )
1156 {
1157  maValues.push_back( rValue );
1158 }
1159 
1160 bool XclExpCrn::InsertValue( SCCOL nScCol, SCROW nScRow, const Any& rValue )
1161 {
1162  if( (nScRow != mnScRow) || (nScCol != static_cast< SCCOL >( mnScCol + maValues.size() )) )
1163  return false;
1164  maValues.push_back( rValue );
1165  return true;
1166 }
1167 
1168 void XclExpCrn::WriteBody( XclExpStream& rStrm )
1169 {
1170  rStrm << static_cast< sal_uInt8 >( mnScCol + maValues.size() - 1 )
1171  << static_cast< sal_uInt8 >( mnScCol )
1172  << static_cast< sal_uInt16 >( mnScRow );
1173  for( const auto& rValue : maValues )
1174  {
1175  if( rValue.has< bool >() )
1176  WriteBool( rStrm, rValue.get< bool >() );
1177  else if( rValue.has< double >() )
1178  WriteDouble( rStrm, rValue.get< double >() );
1179  else if( rValue.has< OUString >() )
1180  WriteString( rStrm, rValue.get< OUString >() );
1181  else
1182  WriteEmpty( rStrm );
1183  }
1184 }
1185 
1186 void XclExpCrn::WriteBool( XclExpStream& rStrm, bool bValue )
1187 {
1188  rStrm << EXC_CACHEDVAL_BOOL << sal_uInt8( bValue ? 1 : 0);
1189  rStrm.WriteZeroBytes( 7 );
1190 }
1191 
1192 void XclExpCrn::WriteDouble( XclExpStream& rStrm, double fValue )
1193 {
1194  if( !std::isfinite( fValue ) )
1195  {
1196  FormulaError nScError = GetDoubleErrorValue(fValue);
1197  WriteError( rStrm, XclTools::GetXclErrorCode( nScError ) );
1198  }
1199  else
1200  {
1201  rStrm << EXC_CACHEDVAL_DOUBLE << fValue;
1202  }
1203 }
1204 
1205 void XclExpCrn::WriteString( XclExpStream& rStrm, const OUString& rValue )
1206 {
1207  rStrm << EXC_CACHEDVAL_STRING << XclExpString( rValue );
1208 }
1209 
1210 void XclExpCrn::WriteError( XclExpStream& rStrm, sal_uInt8 nErrCode )
1211 {
1212  rStrm << EXC_CACHEDVAL_ERROR << nErrCode;
1213  rStrm.WriteZeroBytes( 7 );
1214 }
1215 
1216 void XclExpCrn::WriteEmpty( XclExpStream& rStrm )
1217 {
1218  rStrm << EXC_CACHEDVAL_EMPTY;
1219  rStrm.WriteZeroBytes( 8 );
1220 }
1221 
1222 void XclExpCrn::SaveXml( XclExpXmlStream& rStrm )
1223 {
1225 
1226  pFS->startElement(XML_row, XML_r, OString::number(mnScRow + 1));
1227 
1228  ScAddress aAdr( mnScCol, mnScRow, 0); // Tab number doesn't matter
1229  for( const auto& rValue : maValues )
1230  {
1231  bool bCloseCell = true;
1232  if( rValue.has< double >() )
1233  {
1234  double fVal = rValue.get< double >();
1235  if (std::isfinite( fVal))
1236  {
1237  // t='n' is omitted
1238  pFS->startElement(XML_cell, XML_r, XclXmlUtils::ToOString(rStrm.GetRoot().GetDoc(), aAdr));
1239  pFS->startElement(XML_v);
1240  pFS->write( fVal );
1241  }
1242  else
1243  {
1244  pFS->startElement(XML_cell, XML_r, XclXmlUtils::ToOString(rStrm.GetRoot().GetDoc(), aAdr), XML_t, "e");
1245  pFS->startElement(XML_v);
1246  pFS->write( "#VALUE!" ); // OOXTODO: support other error values
1247  }
1248  }
1249  else if( rValue.has< OUString >() )
1250  {
1251  pFS->startElement(XML_cell, XML_r, XclXmlUtils::ToOString(rStrm.GetRoot().GetDoc(), aAdr), XML_t, "str");
1252  pFS->startElement(XML_v);
1253  pFS->write( rValue.get< OUString >() );
1254  }
1255  else if( rValue.has< bool >() )
1256  {
1257  pFS->startElement(XML_cell, XML_r, XclXmlUtils::ToOString(rStrm.GetRoot().GetDoc(), aAdr), XML_t, "b");
1258  pFS->startElement(XML_v);
1259  pFS->write( rValue.get< bool >() ? "1" : "0" );
1260  }
1261  // OOXTODO: error type cell t='e'
1262  else
1263  {
1264  // Empty/blank cell not stored, only aAdr is incremented.
1265  bCloseCell = false;
1266  }
1267  if (bCloseCell)
1268  {
1269  pFS->endElement(XML_v);
1270  pFS->endElement(XML_cell);
1271  }
1272  aAdr.IncCol();
1273  }
1274 
1275  pFS->endElement( XML_row);
1276 }
1277 
1278 // Cached cells of a sheet ====================================================
1279 
1280 XclExpXct::XclExpXct( const XclExpRoot& rRoot, const OUString& rTabName,
1281  sal_uInt16 nSBTab, ScExternalRefCache::TableTypeRef const & xCacheTable ) :
1282  XclExpRoot( rRoot ),
1283  mxCacheTable( xCacheTable ),
1284  maUsedCells( rRoot.GetDoc().GetSheetLimits() ),
1285  maBoundRange( ScAddress::INITIALIZE_INVALID ),
1286  maTabName( rTabName ),
1287  mnSBTab( nSBTab )
1288 {
1289 }
1290 
1291 void XclExpXct::StoreCellRange( const ScRange& rRange )
1292 {
1293  // #i70418# restrict size of external range to prevent memory overflow
1294  if( (rRange.aEnd.Col() - rRange.aStart.Col()) * (rRange.aEnd.Row() - rRange.aStart.Row()) > 1024 )
1295  return;
1296 
1297  maUsedCells.SetMultiMarkArea( rRange );
1298  maBoundRange.ExtendTo( rRange );
1299 }
1300 
1301 void XclExpXct::StoreCell_( const ScAddress& rCell )
1302 {
1303  maUsedCells.SetMultiMarkArea( ScRange( rCell ) );
1304  maBoundRange.ExtendTo( ScRange( rCell ) );
1305 }
1306 
1307 void XclExpXct::StoreCellRange_( const ScRange& rRange )
1308 {
1309  maUsedCells.SetMultiMarkArea( rRange );
1310  maBoundRange.ExtendTo( rRange );
1311 }
1312 
1313 namespace {
1314 
1315 class XclExpCrnList : public XclExpRecordList< XclExpCrn >
1316 {
1317 public:
1320  bool InsertValue( SCCOL nScCol, SCROW nScRow, const Any& rValue );
1321 };
1322 
1323 bool XclExpCrnList::InsertValue( SCCOL nScCol, SCROW nScRow, const Any& rValue )
1324 {
1325  RecordRefType xLastRec = GetLastRecord();
1326  if( xLastRec && xLastRec->InsertValue( nScCol, nScRow, rValue ) )
1327  return true;
1328  if( GetSize() == SAL_MAX_UINT16 )
1329  return false;
1330  AppendNewRecord( new XclExpCrn( nScCol, nScRow, rValue ) );
1331  return true;
1332 }
1333 
1334 } // namespace
1335 
1336 bool XclExpXct::BuildCrnList( XclExpCrnList& rCrnRecs )
1337 {
1338  if( !mxCacheTable )
1339  return false;
1340 
1341  /* Get the range of used rows in the cache table. This may help to
1342  optimize building the CRN record list if the cache table does not
1343  contain all referred cells, e.g. if big empty ranges are used in the
1344  formulas. */
1345  ::std::pair< SCROW, SCROW > aRowRange = mxCacheTable->getRowRange();
1346  if( aRowRange.first >= aRowRange.second )
1347  return false;
1348 
1349  /* Crop the bounding range of used cells in this table to Excel limits.
1350  Return if there is no external cell inside these limits. */
1351  if( !GetAddressConverter().ValidateRange( maBoundRange, false ) )
1352  return false;
1353 
1354  /* Find the resulting row range that needs to be processed. */
1355  SCROW nScRow1 = ::std::max( aRowRange.first, maBoundRange.aStart.Row() );
1356  SCROW nScRow2 = ::std::min( aRowRange.second - 1, maBoundRange.aEnd.Row() );
1357  if( nScRow1 > nScRow2 )
1358  return false;
1359 
1360  /* Build and collect all CRN records before writing the XCT record. This
1361  is needed to determine the total number of CRN records which must be
1362  known when writing the XCT record (possibly encrypted, so seeking the
1363  output stream back after writing the CRN records is not an option). */
1364  SvNumberFormatter& rFormatter = GetFormatter();
1365  bool bValid = true;
1366  for( SCROW nScRow = nScRow1; bValid && (nScRow <= nScRow2); ++nScRow )
1367  {
1368  ::std::pair< SCCOL, SCCOL > aColRange = mxCacheTable->getColRange( nScRow );
1369  const SCCOL nScEnd = ::std::min( aColRange.second, MAXCOLCOUNT );
1370  for( SCCOL nScCol = aColRange.first; bValid && (nScCol < nScEnd); ++nScCol )
1371  {
1372  if( maUsedCells.IsCellMarked( nScCol, nScRow, true ) )
1373  {
1374  sal_uInt32 nScNumFmt = 0;
1375  ScExternalRefCache::TokenRef xToken = mxCacheTable->getCell( nScCol, nScRow, &nScNumFmt );
1376  using namespace ::formula;
1377  if( xToken )
1378  switch( xToken->GetType() )
1379  {
1380  case svDouble:
1381  bValid = (rFormatter.GetType( nScNumFmt ) == SvNumFormatType::LOGICAL) ?
1382  rCrnRecs.InsertValue( nScCol, nScRow, Any( xToken->GetDouble() != 0 ) ) :
1383  rCrnRecs.InsertValue( nScCol, nScRow, Any( xToken->GetDouble() ) );
1384  break;
1385  case svString:
1386  // do not save empty strings (empty cells) to cache
1387  if( !xToken->GetString().isEmpty() )
1388  bValid = rCrnRecs.InsertValue( nScCol, nScRow, Any( xToken->GetString().getString() ) );
1389  break;
1390  default:
1391  break;
1392  }
1393  }
1394  }
1395  }
1396  return true;
1397 }
1398 
1399 void XclExpXct::Save( XclExpStream& rStrm )
1400 {
1401  XclExpCrnList aCrnRecs;
1402  if (!BuildCrnList( aCrnRecs))
1403  return;
1404 
1405  // write the XCT record and the list of CRN records
1406  rStrm.StartRecord( EXC_ID_XCT, 4 );
1407  rStrm << static_cast< sal_uInt16 >( aCrnRecs.GetSize() ) << mnSBTab;
1408  rStrm.EndRecord();
1409  aCrnRecs.Save( rStrm );
1410 }
1411 
1412 void XclExpXct::SaveXml( XclExpXmlStream& rStrm )
1413 {
1414  XclExpCrnList aCrnRecs;
1415 
1417 
1418  bool bValid = BuildCrnList( aCrnRecs);
1419  pFS->startElement(XML_sheetData, XML_sheetId, OString::number(mnSBTab));
1420  if (bValid)
1421  {
1422  // row elements
1423  aCrnRecs.SaveXml( rStrm );
1424  }
1425  pFS->endElement( XML_sheetData);
1426 }
1427 
1428 // External documents (EXTERNSHEET/SUPBOOK), base class =======================
1429 
1430 XclExpExternSheetBase::XclExpExternSheetBase( const XclExpRoot& rRoot, sal_uInt16 nRecId, sal_uInt32 nRecSize ) :
1431  XclExpRecord( nRecId, nRecSize ),
1432  XclExpRoot( rRoot )
1433 {
1434 }
1435 
1436 XclExpExtNameBuffer& XclExpExternSheetBase::GetExtNameBuffer()
1437 {
1438  if( !mxExtNameBfr )
1439  mxExtNameBfr = std::make_shared<XclExpExtNameBuffer>( GetRoot() );
1440  return *mxExtNameBfr;
1441 }
1442 
1443 void XclExpExternSheetBase::WriteExtNameBuffer( XclExpStream& rStrm )
1444 {
1445  if( mxExtNameBfr )
1446  mxExtNameBfr->Save( rStrm );
1447 }
1448 
1449 void XclExpExternSheetBase::WriteExtNameBufferXml( XclExpXmlStream& rStrm )
1450 {
1451  if( mxExtNameBfr )
1452  mxExtNameBfr->SaveXml( rStrm );
1453 }
1454 
1455 // External documents (EXTERNSHEET, BIFF5/BIFF7) ==============================
1456 
1457 XclExpExternSheet::XclExpExternSheet( const XclExpRoot& rRoot, sal_Unicode cCode ) :
1458  XclExpExternSheetBase( rRoot, EXC_ID_EXTERNSHEET )
1459 {
1460  Init( OUString(cCode) );
1461 }
1462 
1463 XclExpExternSheet::XclExpExternSheet( const XclExpRoot& rRoot, const OUString& rTabName ) :
1464  XclExpExternSheetBase( rRoot, EXC_ID_EXTERNSHEET )
1465 {
1466  // reference to own sheet: \03<sheetname>
1467  Init(OUStringChar(EXC_EXTSH_TABNAME) + rTabName);
1468 }
1469 
1470 void XclExpExternSheet::Save( XclExpStream& rStrm )
1471 {
1472  // EXTERNSHEET record
1473  XclExpRecord::Save( rStrm );
1474  // EXTERNNAME records
1475  WriteExtNameBuffer( rStrm );
1476 }
1477 
1478 void XclExpExternSheet::Init( const OUString& rEncUrl )
1479 {
1480  OSL_ENSURE_BIFF( GetBiff() <= EXC_BIFF5 );
1481  maTabName.AssignByte( rEncUrl, GetTextEncoding(), XclStrFlags::EightBitLength );
1482  SetRecSize( maTabName.GetSize() );
1483 }
1484 
1485 sal_uInt16 XclExpExternSheet::InsertAddIn( const OUString& rName )
1486 {
1487  return GetExtNameBuffer().InsertAddIn( rName );
1488 }
1489 
1490 void XclExpExternSheet::WriteBody( XclExpStream& rStrm )
1491 {
1492  sal_uInt8 nNameSize = static_cast< sal_uInt8 >( maTabName.Len() );
1493  // special case: reference to own sheet (starting with '\03') needs wrong string length
1494  if( maTabName.GetChar( 0 ) == EXC_EXTSH_TABNAME )
1495  --nNameSize;
1496  rStrm << nNameSize;
1497  maTabName.WriteBuffer( rStrm );
1498 }
1499 
1500 // External document (SUPBOOK, BIFF8) =========================================
1501 
1502 XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, sal_uInt16 nXclTabCount ) :
1503  XclExpExternSheetBase( rRoot, EXC_ID_SUPBOOK, 4 ),
1505  mnXclTabCount( nXclTabCount ),
1506  mnFileId( 0 )
1507 {
1508 }
1509 
1510 XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot ) :
1511  XclExpExternSheetBase( rRoot, EXC_ID_SUPBOOK, 4 ),
1513  mnXclTabCount( 1 ),
1514  mnFileId( 0 )
1515 {
1516 }
1517 
1518 XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, const OUString& rUrl, XclSupbookType ) :
1519  XclExpExternSheetBase( rRoot, EXC_ID_SUPBOOK ),
1520  maUrl( rUrl ),
1521  maUrlEncoded( rUrl ),
1523  mnXclTabCount( 0 ),
1524  mnFileId( 0 )
1525 {
1526  SetRecSize( 2 + maUrlEncoded.GetSize() );
1527 }
1528 
1529 XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, const OUString& rUrl ) :
1530  XclExpExternSheetBase( rRoot, EXC_ID_SUPBOOK ),
1531  maUrl( rUrl ),
1532  maUrlEncoded( XclExpUrlHelper::EncodeUrl( rRoot, rUrl ) ),
1534  mnXclTabCount( 0 ),
1535  mnFileId( 0 )
1536 {
1537  SetRecSize( 2 + maUrlEncoded.GetSize() );
1538 
1539  // We need to create all tables up front to ensure the correct table order.
1540  ScExternalRefManager* pRefMgr = rRoot.GetDoc().GetExternalRefManager();
1541  sal_uInt16 nFileId = pRefMgr->getExternalFileId( rUrl );
1542  mnFileId = nFileId + 1;
1543  ScfStringVec aTabNames;
1544  pRefMgr->getAllCachedTableNames( nFileId, aTabNames );
1545  size_t nTabIndex = 0;
1546  for( const auto& rTabName : aTabNames )
1547  {
1548  InsertTabName( rTabName, pRefMgr->getCacheTable( nFileId, nTabIndex ) );
1549  ++nTabIndex;
1550  }
1551 }
1552 
1553 XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, const OUString& rApplic, const OUString& rTopic ) :
1554  XclExpExternSheetBase( rRoot, EXC_ID_SUPBOOK, 4 ),
1555  maUrl( rApplic ),
1556  maDdeTopic( rTopic ),
1557  maUrlEncoded( XclExpUrlHelper::EncodeDde( rApplic, rTopic ) ),
1559  mnXclTabCount( 0 ),
1560  mnFileId( 0 )
1561 {
1562  SetRecSize( 2 + maUrlEncoded.GetSize() );
1563 }
1564 
1565 bool XclExpSupbook::IsUrlLink( const OUString& rUrl ) const
1566 {
1567  return (meType == XclSupbookType::Extern || meType == XclSupbookType::Eurotool) && (maUrl == rUrl);
1568 }
1569 
1570 bool XclExpSupbook::IsDdeLink( const OUString& rApplic, const OUString& rTopic ) const
1571 {
1572  return (meType == XclSupbookType::Special) && (maUrl == rApplic) && (maDdeTopic == rTopic);
1573 }
1574 
1575 void XclExpSupbook::FillRefLogEntry( XclExpRefLogEntry& rRefLogEntry,
1576  sal_uInt16 nFirstSBTab, sal_uInt16 nLastSBTab ) const
1577 {
1578  rRefLogEntry.mpUrl = maUrlEncoded.IsEmpty() ? nullptr : &maUrlEncoded;
1579  rRefLogEntry.mpFirstTab = GetTabName( nFirstSBTab );
1580  rRefLogEntry.mpLastTab = GetTabName( nLastSBTab );
1581 }
1582 
1583 void XclExpSupbook::StoreCellRange( const ScRange& rRange, sal_uInt16 nSBTab )
1584 {
1585  if( XclExpXct* pXct = maXctList.GetRecord( nSBTab ) )
1586  pXct->StoreCellRange( rRange );
1587 }
1588 
1589 void XclExpSupbook::StoreCell_( sal_uInt16 nSBTab, const ScAddress& rCell )
1590 {
1591  if( XclExpXct* pXct = maXctList.GetRecord( nSBTab ) )
1592  pXct->StoreCell_( rCell );
1593 }
1594 
1595 void XclExpSupbook::StoreCellRange_( sal_uInt16 nSBTab, const ScRange& rRange )
1596 {
1597  // multi-table range is not allowed!
1598  if( rRange.aStart.Tab() == rRange.aEnd.Tab() )
1599  if( XclExpXct* pXct = maXctList.GetRecord( nSBTab ) )
1600  pXct->StoreCellRange_( rRange );
1601 }
1602 
1603 sal_uInt16 XclExpSupbook::GetTabIndex( const OUString& rTabName ) const
1604 {
1605  XclExpString aXclName(rTabName);
1606  size_t nSize = maXctList.GetSize();
1607  for (size_t i = 0; i < nSize; ++i)
1608  {
1609  XclExpXctRef aRec = maXctList.GetRecord(i);
1610  if (aXclName == aRec->GetTabName())
1611  return ulimit_cast<sal_uInt16>(i);
1612  }
1613  return EXC_NOTAB;
1614 }
1615 
1616 sal_uInt16 XclExpSupbook::GetTabCount() const
1617 {
1618  return ulimit_cast<sal_uInt16>(maXctList.GetSize());
1619 }
1620 
1621 sal_uInt16 XclExpSupbook::InsertTabName( const OUString& rTabName, ScExternalRefCache::TableTypeRef const & xCacheTable )
1622 {
1623  SAL_WARN_IF( meType != XclSupbookType::Extern, "sc.filter", "Don't insert sheet names here" );
1624  sal_uInt16 nSBTab = ulimit_cast< sal_uInt16 >( maXctList.GetSize() );
1625  XclExpXctRef xXct = new XclExpXct( GetRoot(), rTabName, nSBTab, xCacheTable );
1626  AddRecSize( xXct->GetTabName().GetSize() );
1627  maXctList.AppendRecord( xXct );
1628  return nSBTab;
1629 }
1630 
1631 sal_uInt16 XclExpSupbook::InsertAddIn( const OUString& rName )
1632 {
1633  return GetExtNameBuffer().InsertAddIn( rName );
1634 }
1635 
1636 sal_uInt16 XclExpSupbook::InsertEuroTool( const OUString& rName )
1637 {
1638  return GetExtNameBuffer().InsertEuroTool( rName );
1639 }
1640 
1641 sal_uInt16 XclExpSupbook::InsertDde( const OUString& rItem )
1642 {
1643  return GetExtNameBuffer().InsertDde( maUrl, maDdeTopic, rItem );
1644 }
1645 
1646 sal_uInt16 XclExpSupbook::InsertExtName( const OUString& rName, const ScExternalRefCache::TokenArrayRef& rArray )
1647 {
1648  return GetExtNameBuffer().InsertExtName(*this, rName, rArray);
1649 }
1650 
1651 XclSupbookType XclExpSupbook::GetType() const
1652 {
1653  return meType;
1654 }
1655 
1656 sal_uInt16 XclExpSupbook::GetFileId() const
1657 {
1658  return mnFileId;
1659 }
1660 
1661 const OUString& XclExpSupbook::GetUrl() const
1662 {
1663  return maUrl;
1664 }
1665 
1666 void XclExpSupbook::Save( XclExpStream& rStrm )
1667 {
1668  // SUPBOOK record
1669  XclExpRecord::Save( rStrm );
1670  // XCT record, CRN records
1671  maXctList.Save( rStrm );
1672  // EXTERNNAME records
1673  WriteExtNameBuffer( rStrm );
1674 }
1675 
1676 void XclExpSupbook::SaveXml( XclExpXmlStream& rStrm )
1677 {
1678  sax_fastparser::FSHelperPtr pExternalLink = rStrm.GetCurrentStream();
1679 
1680  // Add relation for this stream, e.g. xl/externalLinks/_rels/externalLink1.xml.rels
1681  sal_uInt16 nLevel = 0;
1682  bool bRel = true;
1683  OUString sId = rStrm.addRelation( pExternalLink->getOutputStream(),
1684  oox::getRelationship(Relationship::EXTERNALLINKPATH),
1685  XclExpHyperlink::BuildFileName( nLevel, bRel, maUrl, GetRoot(), true),
1686  true );
1687 
1688  pExternalLink->startElement( XML_externalLink,
1689  XML_xmlns, rStrm.getNamespaceURL(OOX_NS(xls)).toUtf8());
1690 
1691  pExternalLink->startElement( XML_externalBook,
1692  FSNS(XML_xmlns, XML_r), rStrm.getNamespaceURL(OOX_NS(officeRel)).toUtf8(),
1693  FSNS(XML_r, XML_id), sId.toUtf8());
1694 
1695  if (!maXctList.IsEmpty())
1696  {
1697  pExternalLink->startElement(XML_sheetNames);
1698  for (size_t nPos = 0, nSize = maXctList.GetSize(); nPos < nSize; ++nPos)
1699  {
1700  pExternalLink->singleElement(XML_sheetName,
1701  XML_val, XclXmlUtils::ToOString(maXctList.GetRecord(nPos)->GetTabName()));
1702  }
1703  pExternalLink->endElement( XML_sheetNames);
1704 
1705  }
1706 
1707  if (mxExtNameBfr)
1708  {
1709  pExternalLink->startElement(XML_definedNames);
1710  // externalName elements
1711  WriteExtNameBufferXml( rStrm );
1712  pExternalLink->endElement(XML_definedNames);
1713  }
1714 
1715  if (!maXctList.IsEmpty())
1716  {
1717  pExternalLink->startElement(XML_sheetDataSet);
1718 
1719  // sheetData elements
1720  maXctList.SaveXml( rStrm );
1721 
1722  pExternalLink->endElement( XML_sheetDataSet);
1723 
1724  }
1725  pExternalLink->endElement( XML_externalBook);
1726  pExternalLink->endElement( XML_externalLink);
1727 }
1728 
1729 const XclExpString* XclExpSupbook::GetTabName( sal_uInt16 nSBTab ) const
1730 {
1731  XclExpXctRef xXct = maXctList.GetRecord( nSBTab );
1732  return xXct ? &xXct->GetTabName() : nullptr;
1733 }
1734 
1735 void XclExpSupbook::WriteBody( XclExpStream& rStrm )
1736 {
1737  switch( meType )
1738  {
1739  case XclSupbookType::Self:
1740  rStrm << mnXclTabCount << EXC_SUPB_SELF;
1741  break;
1745  {
1746  sal_uInt16 nCount = ulimit_cast< sal_uInt16 >( maXctList.GetSize() );
1747  rStrm << nCount << maUrlEncoded;
1748 
1749  for( size_t nPos = 0, nSize = maXctList.GetSize(); nPos < nSize; ++nPos )
1750  rStrm << maXctList.GetRecord( nPos )->GetTabName();
1751  }
1752  break;
1753  case XclSupbookType::Addin:
1754  rStrm << mnXclTabCount << EXC_SUPB_ADDIN;
1755  break;
1756  default:
1757  SAL_WARN( "sc.filter", "Unhandled SUPBOOK type " << meType);
1758  }
1759 }
1760 
1761 // All SUPBOOKS in a document =================================================
1762 
1763 XclExpSupbookBuffer::XclExpSupbookBuffer( const XclExpRoot& rRoot ) :
1764  XclExpRoot( rRoot ),
1765  mnOwnDocSB( SAL_MAX_UINT16 ),
1766  mnAddInSB( SAL_MAX_UINT16 )
1767 {
1768  XclExpTabInfo& rTabInfo = GetTabInfo();
1769  sal_uInt16 nXclCnt = rTabInfo.GetXclTabCount();
1770  sal_uInt16 nCodeCnt = static_cast< sal_uInt16 >( GetExtDocOptions().GetCodeNameCount() );
1771  size_t nCount = nXclCnt + rTabInfo.GetXclExtTabCount();
1772 
1773  OSL_ENSURE( nCount > 0, "XclExpSupbookBuffer::XclExpSupbookBuffer - no sheets to export" );
1774  if( nCount )
1775  {
1776  maSBIndexVec.resize( nCount );
1777 
1778  // self-ref SUPBOOK first of list
1779  XclExpSupbookRef xSupbook = new XclExpSupbook( GetRoot(), ::std::max( nXclCnt, nCodeCnt ) );
1780  mnOwnDocSB = Append( xSupbook );
1781  for( sal_uInt16 nXclTab = 0; nXclTab < nXclCnt; ++nXclTab )
1782  maSBIndexVec[ nXclTab ].Set( mnOwnDocSB, nXclTab );
1783  }
1784 }
1785 
1786 XclExpXti XclExpSupbookBuffer::GetXti( sal_uInt16 nFirstXclTab, sal_uInt16 nLastXclTab,
1787  XclExpRefLogEntry* pRefLogEntry ) const
1788 {
1789  XclExpXti aXti;
1790  size_t nSize = maSBIndexVec.size();
1791  if( (nFirstXclTab < nSize) && (nLastXclTab < nSize) )
1792  {
1793  // index of the SUPBOOK record
1794  aXti.mnSupbook = maSBIndexVec[ nFirstXclTab ].mnSupbook;
1795 
1796  // all sheets in the same supbook?
1797  bool bSameSB = true;
1798  for( sal_uInt16 nXclTab = nFirstXclTab + 1; bSameSB && (nXclTab <= nLastXclTab); ++nXclTab )
1799  {
1800  bSameSB = maSBIndexVec[ nXclTab ].mnSupbook == aXti.mnSupbook;
1801  if( !bSameSB )
1802  nLastXclTab = nXclTab - 1;
1803  }
1804  aXti.mnFirstSBTab = maSBIndexVec[ nFirstXclTab ].mnSBTab;
1805  aXti.mnLastSBTab = maSBIndexVec[ nLastXclTab ].mnSBTab;
1806 
1807  // fill external reference log entry (for change tracking)
1808  if( pRefLogEntry )
1809  {
1810  pRefLogEntry->mnFirstXclTab = nFirstXclTab;
1811  pRefLogEntry->mnLastXclTab = nLastXclTab;
1812  XclExpSupbookRef xSupbook = maSupbookList.GetRecord( aXti.mnSupbook );
1813  if( xSupbook )
1814  xSupbook->FillRefLogEntry( *pRefLogEntry, aXti.mnFirstSBTab, aXti.mnLastSBTab );
1815  }
1816  }
1817  else
1818  {
1819  // special range, i.e. for deleted sheets or add-ins
1820  aXti.mnSupbook = mnOwnDocSB;
1821  aXti.mnFirstSBTab = nFirstXclTab;
1822  aXti.mnLastSBTab = nLastXclTab;
1823  }
1824 
1825  return aXti;
1826 }
1827 
1828 void XclExpSupbookBuffer::StoreCellRange( const ScRange& rRange )
1829 {
1830  sal_uInt16 nXclTab = GetTabInfo().GetXclTab( rRange.aStart.Tab() );
1831  if( nXclTab < maSBIndexVec.size() )
1832  {
1833  const XclExpSBIndex& rSBIndex = maSBIndexVec[ nXclTab ];
1834  XclExpSupbookRef xSupbook = maSupbookList.GetRecord( rSBIndex.mnSupbook );
1835  OSL_ENSURE( xSupbook , "XclExpSupbookBuffer::StoreCellRange - missing SUPBOOK record" );
1836  if( xSupbook )
1837  xSupbook->StoreCellRange( rRange, rSBIndex.mnSBTab );
1838  }
1839 }
1840 
1841 namespace {
1842 
1843 class FindSBIndexEntry
1844 {
1845 public:
1846  explicit FindSBIndexEntry(sal_uInt16 nSupbookId, sal_uInt16 nTabId) :
1847  mnSupbookId(nSupbookId), mnTabId(nTabId) {}
1848 
1849  bool operator()(const XclExpSupbookBuffer::XclExpSBIndex& r) const
1850  {
1851  return mnSupbookId == r.mnSupbook && mnTabId == r.mnSBTab;
1852  }
1853 
1854 private:
1855  sal_uInt16 mnSupbookId;
1856  sal_uInt16 mnTabId;
1857 };
1858 
1859 }
1860 
1861 void XclExpSupbookBuffer::StoreCell( sal_uInt16 nFileId, const OUString& rTabName, const ScAddress& rCell )
1862 {
1863  ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager();
1864  const OUString* pUrl = pRefMgr->getExternalFileName(nFileId);
1865  if (!pUrl)
1866  return;
1867 
1868  XclExpSupbookRef xSupbook;
1869  sal_uInt16 nSupbookId;
1870  if (!GetSupbookUrl(xSupbook, nSupbookId, *pUrl))
1871  {
1872  xSupbook = new XclExpSupbook(GetRoot(), *pUrl);
1873  nSupbookId = Append(xSupbook);
1874  }
1875 
1876  sal_uInt16 nSheetId = xSupbook->GetTabIndex(rTabName);
1877  if (nSheetId == EXC_NOTAB)
1878  // specified table name not found in this SUPBOOK.
1879  return;
1880 
1881  FindSBIndexEntry f(nSupbookId, nSheetId);
1882  if (::std::none_of(maSBIndexVec.begin(), maSBIndexVec.end(), f))
1883  {
1884  maSBIndexVec.emplace_back();
1885  XclExpSBIndex& r = maSBIndexVec.back();
1886  r.mnSupbook = nSupbookId;
1887  r.mnSBTab = nSheetId;
1888  }
1889 
1890  xSupbook->StoreCell_(nSheetId, rCell);
1891 }
1892 
1893 void XclExpSupbookBuffer::StoreCellRange( sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange )
1894 {
1895  ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager();
1896  const OUString* pUrl = pRefMgr->getExternalFileName(nFileId);
1897  if (!pUrl)
1898  return;
1899 
1900  XclExpSupbookRef xSupbook;
1901  sal_uInt16 nSupbookId;
1902  if (!GetSupbookUrl(xSupbook, nSupbookId, *pUrl))
1903  {
1904  xSupbook = new XclExpSupbook(GetRoot(), *pUrl);
1905  nSupbookId = Append(xSupbook);
1906  }
1907 
1908  SCTAB nTabCount = rRange.aEnd.Tab() - rRange.aStart.Tab() + 1;
1909 
1910  // If this is a multi-table range, get token for each table.
1911  using namespace ::formula;
1912  SCTAB aMatrixListSize = 0;
1913 
1914  // This is a new'ed instance, so we must manage its life cycle here.
1915  ScExternalRefCache::TokenArrayRef pArray = pRefMgr->getDoubleRefTokens(nFileId, rTabName, rRange, nullptr);
1916  if (!pArray)
1917  return;
1918 
1919  FormulaTokenArrayPlainIterator aIter(*pArray);
1920  for (FormulaToken* p = aIter.First(); p; p = aIter.Next())
1921  {
1922  if (p->GetType() == svMatrix)
1923  ++aMatrixListSize;
1924  else if (p->GetOpCode() != ocSep)
1925  {
1926  // This is supposed to be ocSep!!!
1927  return;
1928  }
1929  }
1930 
1931  if (aMatrixListSize != nTabCount)
1932  {
1933  // matrix size mismatch!
1934  return;
1935  }
1936 
1937  sal_uInt16 nFirstSheetId = xSupbook->GetTabIndex(rTabName);
1938 
1939  ScRange aRange(rRange);
1940  aRange.aStart.SetTab(0);
1941  aRange.aEnd.SetTab(0);
1942  for (SCTAB nTab = 0; nTab < nTabCount; ++nTab)
1943  {
1944  sal_uInt16 nSheetId = nFirstSheetId + static_cast<sal_uInt16>(nTab);
1945  FindSBIndexEntry f(nSupbookId, nSheetId);
1946  if (::std::none_of(maSBIndexVec.begin(), maSBIndexVec.end(), f))
1947  {
1948  maSBIndexVec.emplace_back();
1949  XclExpSBIndex& r = maSBIndexVec.back();
1950  r.mnSupbook = nSupbookId;
1951  r.mnSBTab = nSheetId;
1952  }
1953 
1954  xSupbook->StoreCellRange_(nSheetId, aRange);
1955  }
1956 }
1957 
1958 bool XclExpSupbookBuffer::InsertAddIn(
1959  sal_uInt16& rnSupbook, sal_uInt16& rnExtName, const OUString& rName )
1960 {
1961  XclExpSupbookRef xSupbook;
1962  if( mnAddInSB == SAL_MAX_UINT16 )
1963  {
1964  xSupbook = new XclExpSupbook( GetRoot() );
1965  mnAddInSB = Append( xSupbook );
1966  }
1967  else
1968  xSupbook = maSupbookList.GetRecord( mnAddInSB );
1969  OSL_ENSURE( xSupbook, "XclExpSupbookBuffer::InsertAddin - missing add-in supbook" );
1970  rnSupbook = mnAddInSB;
1971  rnExtName = xSupbook->InsertAddIn( rName );
1972  return rnExtName > 0;
1973 }
1974 
1975 bool XclExpSupbookBuffer::InsertEuroTool(
1976  sal_uInt16& rnSupbook, sal_uInt16& rnExtName, const OUString& rName )
1977 {
1978  XclExpSupbookRef xSupbook;
1979  OUString aUrl( "\001\010EUROTOOL.XLA" );
1980  if( !GetSupbookUrl( xSupbook, rnSupbook, aUrl ) )
1981  {
1982  xSupbook = new XclExpSupbook( GetRoot(), aUrl, XclSupbookType::Eurotool );
1983  rnSupbook = Append( xSupbook );
1984  }
1985  rnExtName = xSupbook->InsertEuroTool( rName );
1986  return rnExtName > 0;
1987 }
1988 
1989 bool XclExpSupbookBuffer::InsertDde(
1990  sal_uInt16& rnSupbook, sal_uInt16& rnExtName,
1991  const OUString& rApplic, const OUString& rTopic, const OUString& rItem )
1992 {
1993  XclExpSupbookRef xSupbook;
1994  if( !GetSupbookDde( xSupbook, rnSupbook, rApplic, rTopic ) )
1995  {
1996  xSupbook = new XclExpSupbook( GetRoot(), rApplic, rTopic );
1997  rnSupbook = Append( xSupbook );
1998  }
1999  rnExtName = xSupbook->InsertDde( rItem );
2000  return rnExtName > 0;
2001 }
2002 
2003 bool XclExpSupbookBuffer::InsertExtName(
2004  sal_uInt16& rnSupbook, sal_uInt16& rnExtName, const OUString& rUrl,
2005  const OUString& rName, const ScExternalRefCache::TokenArrayRef& rArray )
2006 {
2007  XclExpSupbookRef xSupbook;
2008  if (!GetSupbookUrl(xSupbook, rnSupbook, rUrl))
2009  {
2010  xSupbook = new XclExpSupbook(GetRoot(), rUrl);
2011  rnSupbook = Append(xSupbook);
2012  }
2013  rnExtName = xSupbook->InsertExtName(rName, rArray);
2014  return rnExtName > 0;
2015 }
2016 
2017 XclExpXti XclExpSupbookBuffer::GetXti( sal_uInt16 nFileId, const OUString& rTabName, sal_uInt16 nXclTabSpan,
2018  XclExpRefLogEntry* pRefLogEntry )
2019 {
2020  XclExpXti aXti(0, EXC_NOTAB, EXC_NOTAB);
2021  ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager();
2022  const OUString* pUrl = pRefMgr->getExternalFileName(nFileId);
2023  if (!pUrl)
2024  return aXti;
2025 
2026  XclExpSupbookRef xSupbook;
2027  sal_uInt16 nSupbookId;
2028  if (!GetSupbookUrl(xSupbook, nSupbookId, *pUrl))
2029  {
2030  xSupbook = new XclExpSupbook(GetRoot(), *pUrl);
2031  nSupbookId = Append(xSupbook);
2032  }
2033  aXti.mnSupbook = nSupbookId;
2034 
2035  sal_uInt16 nFirstSheetId = xSupbook->GetTabIndex(rTabName);
2036  if (nFirstSheetId == EXC_NOTAB)
2037  {
2038  // first sheet not found in SUPBOOK.
2039  return aXti;
2040  }
2041  sal_uInt16 nSheetCount = xSupbook->GetTabCount();
2042  for (sal_uInt16 i = 0; i < nXclTabSpan; ++i)
2043  {
2044  sal_uInt16 nSheetId = nFirstSheetId + i;
2045  if (nSheetId >= nSheetCount)
2046  return aXti;
2047 
2048  FindSBIndexEntry f(nSupbookId, nSheetId);
2049  if (::std::none_of(maSBIndexVec.begin(), maSBIndexVec.end(), f))
2050  {
2051  maSBIndexVec.emplace_back();
2052  XclExpSBIndex& r = maSBIndexVec.back();
2053  r.mnSupbook = nSupbookId;
2054  r.mnSBTab = nSheetId;
2055  }
2056  if (i == 0)
2057  aXti.mnFirstSBTab = nSheetId;
2058  if (i == nXclTabSpan - 1)
2059  aXti.mnLastSBTab = nSheetId;
2060  }
2061 
2062  if (pRefLogEntry)
2063  {
2064  pRefLogEntry->mnFirstXclTab = 0;
2065  pRefLogEntry->mnLastXclTab = 0;
2066  if (xSupbook)
2067  xSupbook->FillRefLogEntry(*pRefLogEntry, aXti.mnFirstSBTab, aXti.mnLastSBTab);
2068  }
2069 
2070  return aXti;
2071 }
2072 
2073 void XclExpSupbookBuffer::Save( XclExpStream& rStrm )
2074 {
2075  maSupbookList.Save( rStrm );
2076 }
2077 
2078 void XclExpSupbookBuffer::SaveXml( XclExpXmlStream& rStrm )
2079 {
2080  ::std::map< sal_uInt16, OUString > aMap;
2081  for (size_t nPos = 0, nSize = maSupbookList.GetSize(); nPos < nSize; ++nPos)
2082  {
2083  XclExpSupbookRef xRef( maSupbookList.GetRecord( nPos));
2084  if (xRef->GetType() != XclSupbookType::Extern)
2085  continue; // handle only external reference (for now?)
2086 
2087  sal_uInt16 nId = xRef->GetFileId();
2088  const OUString& rUrl = xRef->GetUrl();
2089  ::std::pair< ::std::map< sal_uInt16, OUString >::iterator, bool > aInsert(
2090  aMap.insert( ::std::make_pair( nId, rUrl)));
2091  if (!aInsert.second)
2092  {
2093  SAL_WARN( "sc.filter", "XclExpSupbookBuffer::SaveXml: file ID already used: " << nId <<
2094  " wanted for " << rUrl << " and is " << (*aInsert.first).second <<
2095  (rUrl == (*aInsert.first).second ? " multiple Supbook not supported" : ""));
2096  continue;
2097  }
2098 
2099  OUString sId;
2100  sax_fastparser::FSHelperPtr pExternalLink = rStrm.CreateOutputStream(
2101  XclXmlUtils::GetStreamName( "xl/", "externalLinks/externalLink", nId),
2102  XclXmlUtils::GetStreamName( nullptr, "externalLinks/externalLink", nId),
2103  rStrm.GetCurrentStream()->getOutputStream(),
2104  "application/vnd.openxmlformats-officedocument.spreadsheetml.externalLink+xml",
2105  CREATE_OFFICEDOC_RELATION_TYPE("externalLink"),
2106  &sId );
2107 
2108  // externalReference entry in workbook externalReferences
2109  rStrm.GetCurrentStream()->singleElement( XML_externalReference,
2110  FSNS(XML_r, XML_id), sId.toUtf8() );
2111 
2112  // Each externalBook in a separate stream.
2113  rStrm.PushStream( pExternalLink );
2114  xRef->SaveXml( rStrm );
2115  rStrm.PopStream();
2116  }
2117 }
2118 
2119 bool XclExpSupbookBuffer::HasExternalReferences() const
2120 {
2121  for (size_t nPos = 0, nSize = maSupbookList.GetSize(); nPos < nSize; ++nPos)
2122  {
2123  if (maSupbookList.GetRecord( nPos)->GetType() == XclSupbookType::Extern)
2124  return true;
2125  }
2126  return false;
2127 }
2128 
2129 bool XclExpSupbookBuffer::GetSupbookUrl(
2130  XclExpSupbookRef& rxSupbook, sal_uInt16& rnIndex, const OUString& rUrl ) const
2131 {
2132  for( size_t nPos = 0, nSize = maSupbookList.GetSize(); nPos < nSize; ++nPos )
2133  {
2134  rxSupbook = maSupbookList.GetRecord( nPos );
2135  if( rxSupbook->IsUrlLink( rUrl ) )
2136  {
2137  rnIndex = ulimit_cast< sal_uInt16 >( nPos );
2138  return true;
2139  }
2140  }
2141  return false;
2142 }
2143 
2144 bool XclExpSupbookBuffer::GetSupbookDde( XclExpSupbookRef& rxSupbook,
2145  sal_uInt16& rnIndex, const OUString& rApplic, const OUString& rTopic ) const
2146 {
2147  for( size_t nPos = 0, nSize = maSupbookList.GetSize(); nPos < nSize; ++nPos )
2148  {
2149  rxSupbook = maSupbookList.GetRecord( nPos );
2150  if( rxSupbook->IsDdeLink( rApplic, rTopic ) )
2151  {
2152  rnIndex = ulimit_cast< sal_uInt16 >( nPos );
2153  return true;
2154  }
2155  }
2156  return false;
2157 }
2158 
2159 sal_uInt16 XclExpSupbookBuffer::Append( XclExpSupbookRef const & xSupbook )
2160 {
2161  maSupbookList.AppendRecord( xSupbook );
2162  return ulimit_cast< sal_uInt16 >( maSupbookList.GetSize() - 1 );
2163 }
2164 
2165 // Export link manager ========================================================
2166 
2168  XclExpRoot( rRoot )
2169 {
2170 }
2171 
2172 XclExpLinkManagerImpl5::XclExpLinkManagerImpl5( const XclExpRoot& rRoot ) :
2173  XclExpLinkManagerImpl( rRoot )
2174 {
2175 }
2176 
2177 void XclExpLinkManagerImpl5::FindExtSheet(
2178  sal_uInt16& rnExtSheet, sal_uInt16& rnFirstXclTab, sal_uInt16& rnLastXclTab,
2179  SCTAB nFirstScTab, SCTAB nLastScTab, XclExpRefLogEntry* pRefLogEntry )
2180 {
2181  FindInternal( rnExtSheet, rnFirstXclTab, nFirstScTab );
2182  if( (rnFirstXclTab == EXC_TAB_DELETED) || (nFirstScTab == nLastScTab) )
2183  {
2184  rnLastXclTab = rnFirstXclTab;
2185  }
2186  else
2187  {
2188  sal_uInt16 nDummyExtSheet;
2189  FindInternal( nDummyExtSheet, rnLastXclTab, nLastScTab );
2190  }
2191 
2192  OSL_ENSURE( !pRefLogEntry, "XclExpLinkManagerImpl5::FindExtSheet - fill reflog entry not implemented" );
2193 }
2194 
2195 sal_uInt16 XclExpLinkManagerImpl5::FindExtSheet( sal_Unicode cCode )
2196 {
2197  sal_uInt16 nExtSheet;
2198  FindInternal( nExtSheet, cCode );
2199  return nExtSheet;
2200 }
2201 
2202 void XclExpLinkManagerImpl5::FindExtSheet(
2203  sal_uInt16 /*nFileId*/, const OUString& /*rTabName*/, sal_uInt16 /*nXclTabSpan*/,
2204  sal_uInt16& /*rnExtSheet*/, sal_uInt16& /*rnFirstSBTab*/, sal_uInt16& /*rnLastSBTab*/,
2205  XclExpRefLogEntry* /*pRefLogEntry*/ )
2206 {
2207  // not implemented
2208 }
2209 
2210 void XclExpLinkManagerImpl5::StoreCellRange( const ScSingleRefData& /*rRef1*/, const ScSingleRefData& /*rRef2*/, const ScAddress& /*rPos*/ )
2211 {
2212  // not implemented
2213 }
2214 
2215 void XclExpLinkManagerImpl5::StoreCell( sal_uInt16 /*nFileId*/, const OUString& /*rTabName*/, const ScAddress& /*rPos*/ )
2216 {
2217  // not implemented
2218 }
2219 
2220 void XclExpLinkManagerImpl5::StoreCellRange( sal_uInt16 /*nFileId*/, const OUString& /*rTabName*/, const ScRange& /*rRange*/ )
2221 {
2222  // not implemented
2223 }
2224 
2225 bool XclExpLinkManagerImpl5::InsertAddIn(
2226  sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rName )
2227 {
2228  XclExpExtSheetRef xExtSheet = FindInternal( rnExtSheet, EXC_EXTSH_ADDIN );
2229  if( xExtSheet )
2230  {
2231  rnExtName = xExtSheet->InsertAddIn( rName );
2232  return rnExtName > 0;
2233  }
2234  return false;
2235 }
2236 
2237 bool XclExpLinkManagerImpl5::InsertEuroTool(
2238  sal_uInt16& /*rnExtSheet*/, sal_uInt16& /*rnExtName*/, const OUString& /*rName*/ )
2239 {
2240  return false;
2241 }
2242 
2243 bool XclExpLinkManagerImpl5::InsertDde(
2244  sal_uInt16& /*rnExtSheet*/, sal_uInt16& /*rnExtName*/,
2245  const OUString& /*rApplic*/, const OUString& /*rTopic*/, const OUString& /*rItem*/ )
2246 {
2247  // not implemented
2248  return false;
2249 }
2250 
2251 bool XclExpLinkManagerImpl5::InsertExtName(
2252  sal_uInt16& /*rnExtSheet*/, sal_uInt16& /*rnExtName*/, const OUString& /*rUrl*/,
2253  const OUString& /*rName*/, const ScExternalRefCache::TokenArrayRef& /*rArray*/ )
2254 {
2255  // not implemented
2256  return false;
2257 }
2258 
2259 void XclExpLinkManagerImpl5::Save( XclExpStream& rStrm )
2260 {
2261  if( sal_uInt16 nExtSheetCount = GetExtSheetCount() )
2262  {
2263  // EXTERNCOUNT record
2264  XclExpUInt16Record( EXC_ID_EXTERNCOUNT, nExtSheetCount ).Save( rStrm );
2265  // list of EXTERNSHEET records with EXTERNNAME, XCT, CRN records
2266  maExtSheetList.Save( rStrm );
2267  }
2268 }
2269 
2270 void XclExpLinkManagerImpl5::SaveXml( XclExpXmlStream& /*rStrm*/ )
2271 {
2272  // not applicable
2273 }
2274 
2275 sal_uInt16 XclExpLinkManagerImpl5::GetExtSheetCount() const
2276 {
2277  return static_cast< sal_uInt16 >( maExtSheetList.GetSize() );
2278 }
2279 
2280 sal_uInt16 XclExpLinkManagerImpl5::AppendInternal( XclExpExtSheetRef const & xExtSheet )
2281 {
2282  if( GetExtSheetCount() < 0x7FFF )
2283  {
2284  maExtSheetList.AppendRecord( xExtSheet );
2285  // return negated one-based EXTERNSHEET index (i.e. 0xFFFD for 3rd record)
2286  return static_cast< sal_uInt16 >( -GetExtSheetCount() );
2287  }
2288  return 0;
2289 }
2290 
2291 void XclExpLinkManagerImpl5::CreateInternal()
2292 {
2293  if( !maIntTabMap.empty() )
2294  return;
2295 
2296  // create EXTERNSHEET records for all internal exported sheets
2297  XclExpTabInfo& rTabInfo = GetTabInfo();
2298  for( SCTAB nScTab = 0, nScCnt = rTabInfo.GetScTabCount(); nScTab < nScCnt; ++nScTab )
2299  {
2300  if( rTabInfo.IsExportTab( nScTab ) )
2301  {
2302  XclExpExtSheetRef xRec;
2303  if( nScTab == GetCurrScTab() )
2304  xRec = new XclExpExternSheet( GetRoot(), EXC_EXTSH_OWNTAB );
2305  else
2306  xRec = new XclExpExternSheet( GetRoot(), rTabInfo.GetScTabName( nScTab ) );
2307  maIntTabMap[ nScTab ] = AppendInternal( xRec );
2308  }
2309  }
2310 }
2311 
2312 XclExpLinkManagerImpl5::XclExpExtSheetRef XclExpLinkManagerImpl5::GetInternal( sal_uInt16 nExtSheet )
2313 {
2314  return maExtSheetList.GetRecord( static_cast< sal_uInt16 >( -nExtSheet - 1 ) );
2315 }
2316 
2317 XclExpLinkManagerImpl5::XclExpExtSheetRef XclExpLinkManagerImpl5::FindInternal(
2318  sal_uInt16& rnExtSheet, sal_uInt16& rnXclTab, SCTAB nScTab )
2319 {
2320  // create internal EXTERNSHEET records on demand
2321  CreateInternal();
2322 
2323  // try to find an EXTERNSHEET record - if not, return a "deleted sheet" reference
2324  XclExpExtSheetRef xExtSheet;
2325  XclExpIntTabMap::const_iterator aIt = maIntTabMap.find( nScTab );
2326  if( aIt == maIntTabMap.end() )
2327  {
2328  xExtSheet = FindInternal( rnExtSheet, EXC_EXTSH_OWNDOC );
2329  rnXclTab = EXC_TAB_DELETED;
2330  }
2331  else
2332  {
2333  rnExtSheet = aIt->second;
2334  xExtSheet = GetInternal( rnExtSheet );
2335  rnXclTab = GetTabInfo().GetXclTab( nScTab );
2336  }
2337  return xExtSheet;
2338 }
2339 
2340 XclExpLinkManagerImpl5::XclExpExtSheetRef XclExpLinkManagerImpl5::FindInternal(
2341  sal_uInt16& rnExtSheet, sal_Unicode cCode )
2342 {
2343  XclExpExtSheetRef xExtSheet;
2344  XclExpCodeMap::const_iterator aIt = maCodeMap.find( cCode );
2345  if( aIt == maCodeMap.end() )
2346  {
2347  xExtSheet = new XclExpExternSheet( GetRoot(), cCode );
2348  rnExtSheet = maCodeMap[ cCode ] = AppendInternal( xExtSheet );
2349  }
2350  else
2351  {
2352  rnExtSheet = aIt->second;
2353  xExtSheet = GetInternal( rnExtSheet );
2354  }
2355  return xExtSheet;
2356 }
2357 
2358 XclExpLinkManagerImpl8::XclExpLinkManagerImpl8( const XclExpRoot& rRoot ) :
2359  XclExpLinkManagerImpl( rRoot ),
2360  maSBBuffer( rRoot )
2361 {
2362 }
2363 
2364 void XclExpLinkManagerImpl8::FindExtSheet(
2365  sal_uInt16& rnExtSheet, sal_uInt16& rnFirstXclTab, sal_uInt16& rnLastXclTab,
2366  SCTAB nFirstScTab, SCTAB nLastScTab, XclExpRefLogEntry* pRefLogEntry )
2367 {
2368  XclExpTabInfo& rTabInfo = GetTabInfo();
2369  rnFirstXclTab = rTabInfo.GetXclTab( nFirstScTab );
2370  rnLastXclTab = rTabInfo.GetXclTab( nLastScTab );
2371  rnExtSheet = InsertXti( maSBBuffer.GetXti( rnFirstXclTab, rnLastXclTab, pRefLogEntry ) );
2372 }
2373 
2374 sal_uInt16 XclExpLinkManagerImpl8::FindExtSheet( sal_Unicode cCode )
2375 {
2376  OSL_ENSURE( (cCode == EXC_EXTSH_OWNDOC) || (cCode == EXC_EXTSH_ADDIN),
2377  "XclExpLinkManagerImpl8::FindExtSheet - unknown externsheet code" );
2378  return InsertXti( maSBBuffer.GetXti( EXC_TAB_EXTERNAL, EXC_TAB_EXTERNAL ) );
2379 }
2380 
2381 void XclExpLinkManagerImpl8::FindExtSheet(
2382  sal_uInt16 nFileId, const OUString& rTabName, sal_uInt16 nXclTabSpan,
2383  sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
2384  XclExpRefLogEntry* pRefLogEntry )
2385 {
2386  XclExpXti aXti = maSBBuffer.GetXti(nFileId, rTabName, nXclTabSpan, pRefLogEntry);
2387  rnExtSheet = InsertXti(aXti);
2388  rnFirstSBTab = aXti.mnFirstSBTab;
2389  rnLastSBTab = aXti.mnLastSBTab;
2390 }
2391 
2392 void XclExpLinkManagerImpl8::StoreCellRange( const ScSingleRefData& rRef1, const ScSingleRefData& rRef2, const ScAddress& rPos )
2393 {
2394  ScAddress aAbs1 = rRef1.toAbs(GetRoot().GetDoc(), rPos);
2395  ScAddress aAbs2 = rRef2.toAbs(GetRoot().GetDoc(), rPos);
2396  if (!(!rRef1.IsDeleted() && !rRef2.IsDeleted() && (aAbs1.Tab() >= 0) && (aAbs2.Tab() >= 0)))
2397  return;
2398 
2399  const XclExpTabInfo& rTabInfo = GetTabInfo();
2400  SCTAB nFirstScTab = aAbs1.Tab();
2401  SCTAB nLastScTab = aAbs2.Tab();
2402  ScRange aRange(aAbs1.Col(), aAbs1.Row(), 0, aAbs2.Col(), aAbs2.Row(), 0);
2403  for (SCTAB nScTab = nFirstScTab; nScTab <= nLastScTab; ++nScTab)
2404  {
2405  if( rTabInfo.IsExternalTab( nScTab ) )
2406  {
2407  aRange.aStart.SetTab( nScTab );
2408  aRange.aEnd.SetTab( nScTab );
2409  maSBBuffer.StoreCellRange( aRange );
2410  }
2411  }
2412 }
2413 
2414 void XclExpLinkManagerImpl8::StoreCell( sal_uInt16 nFileId, const OUString& rTabName, const ScAddress& rPos )
2415 {
2416  maSBBuffer.StoreCell(nFileId, rTabName, rPos);
2417 }
2418 
2419 void XclExpLinkManagerImpl8::StoreCellRange( sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange )
2420 {
2421  maSBBuffer.StoreCellRange(nFileId, rTabName, rRange);
2422 }
2423 
2424 bool XclExpLinkManagerImpl8::InsertAddIn(
2425  sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rName )
2426 {
2427  sal_uInt16 nSupbook;
2428  if( maSBBuffer.InsertAddIn( nSupbook, rnExtName, rName ) )
2429  {
2430  rnExtSheet = InsertXti( XclExpXti( nSupbook, EXC_TAB_EXTERNAL, EXC_TAB_EXTERNAL ) );
2431  return true;
2432  }
2433  return false;
2434 }
2435 
2436 bool XclExpLinkManagerImpl8::InsertEuroTool(
2437  sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rName )
2438 {
2439  sal_uInt16 nSupbook;
2440  if( maSBBuffer.InsertEuroTool( nSupbook, rnExtName, rName ) )
2441  {
2442  rnExtSheet = InsertXti( XclExpXti( nSupbook, EXC_TAB_EXTERNAL, EXC_TAB_EXTERNAL ) );
2443  return true;
2444  }
2445  return false;
2446 }
2447 
2448 bool XclExpLinkManagerImpl8::InsertDde(
2449  sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
2450  const OUString& rApplic, const OUString& rTopic, const OUString& rItem )
2451 {
2452  sal_uInt16 nSupbook;
2453  if( maSBBuffer.InsertDde( nSupbook, rnExtName, rApplic, rTopic, rItem ) )
2454  {
2455  rnExtSheet = InsertXti( XclExpXti( nSupbook, EXC_TAB_EXTERNAL, EXC_TAB_EXTERNAL ) );
2456  return true;
2457  }
2458  return false;
2459 }
2460 
2461 bool XclExpLinkManagerImpl8::InsertExtName( sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
2462  const OUString& rUrl, const OUString& rName, const ScExternalRefCache::TokenArrayRef& rArray )
2463 {
2464  sal_uInt16 nSupbook;
2465  if( maSBBuffer.InsertExtName( nSupbook, rnExtName, rUrl, rName, rArray ) )
2466  {
2467  rnExtSheet = InsertXti( XclExpXti( nSupbook, EXC_TAB_EXTERNAL, EXC_TAB_EXTERNAL ) );
2468  return true;
2469  }
2470  return false;
2471 }
2472 
2473 void XclExpLinkManagerImpl8::Save( XclExpStream& rStrm )
2474 {
2475  if( maXtiVec.empty() )
2476  return;
2477 
2478  // SUPBOOKs, XCTs, CRNs, EXTERNNAMEs
2479  maSBBuffer.Save( rStrm );
2480 
2481  // EXTERNSHEET
2482  sal_uInt16 nCount = ulimit_cast< sal_uInt16 >( maXtiVec.size() );
2483  rStrm.StartRecord( EXC_ID_EXTERNSHEET, 2 + 6 * nCount );
2484  rStrm << nCount;
2485  rStrm.SetSliceSize( 6 );
2486  for( const auto& rXti : maXtiVec )
2487  rXti.Save( rStrm );
2488  rStrm.EndRecord();
2489 }
2490 
2491 void XclExpLinkManagerImpl8::SaveXml( XclExpXmlStream& rStrm )
2492 {
2493  if (maSBBuffer.HasExternalReferences())
2494  {
2495  sax_fastparser::FSHelperPtr pWorkbook = rStrm.GetCurrentStream();
2496  pWorkbook->startElement(XML_externalReferences);
2497 
2498  // externalLink, externalBook, sheetNames, sheetDataSet, externalName
2499  maSBBuffer.SaveXml( rStrm );
2500 
2501  pWorkbook->endElement( XML_externalReferences);
2502  }
2503 
2504  // TODO: equivalent for EXTERNSHEET in OOXML?
2505 #if 0
2506  if( !maXtiVec.empty() )
2507  {
2508  for( const auto& rXti : maXtiVec )
2509  rXti.SaveXml( rStrm );
2510  }
2511 #endif
2512 }
2513 
2514 sal_uInt16 XclExpLinkManagerImpl8::InsertXti( const XclExpXti& rXti )
2515 {
2516  auto aIt = std::find(maXtiVec.begin(), maXtiVec.end(), rXti);
2517  if (aIt != maXtiVec.end())
2518  return ulimit_cast< sal_uInt16 >( std::distance(maXtiVec.begin(), aIt) );
2519  maXtiVec.push_back( rXti );
2520  return ulimit_cast< sal_uInt16 >( maXtiVec.size() - 1 );
2521 }
2522 
2524  XclExpRoot( rRoot )
2525 {
2526  switch( GetBiff() )
2527  {
2528  case EXC_BIFF5:
2529  mxImpl = std::make_shared<XclExpLinkManagerImpl5>( rRoot );
2530  break;
2531  case EXC_BIFF8:
2532  mxImpl = std::make_shared<XclExpLinkManagerImpl8>( rRoot );
2533  break;
2534  default:
2535  DBG_ERROR_BIFF();
2536  }
2537 }
2538 
2540 {
2541 }
2542 
2544  sal_uInt16& rnExtSheet, sal_uInt16& rnXclTab,
2545  SCTAB nScTab, XclExpRefLogEntry* pRefLogEntry )
2546 {
2547  mxImpl->FindExtSheet( rnExtSheet, rnXclTab, rnXclTab, nScTab, nScTab, pRefLogEntry );
2548 }
2549 
2551  sal_uInt16& rnExtSheet, sal_uInt16& rnFirstXclTab, sal_uInt16& rnLastXclTab,
2552  SCTAB nFirstScTab, SCTAB nLastScTab, XclExpRefLogEntry* pRefLogEntry )
2553 {
2554  mxImpl->FindExtSheet( rnExtSheet, rnFirstXclTab, rnLastXclTab, nFirstScTab, nLastScTab, pRefLogEntry );
2555 }
2556 
2558 {
2559  return mxImpl->FindExtSheet( cCode );
2560 }
2561 
2562 void XclExpLinkManager::FindExtSheet( sal_uInt16 nFileId, const OUString& rTabName, sal_uInt16 nXclTabSpan,
2563  sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
2564  XclExpRefLogEntry* pRefLogEntry )
2565 {
2566  mxImpl->FindExtSheet( nFileId, rTabName, nXclTabSpan, rnExtSheet, rnFirstSBTab, rnLastSBTab, pRefLogEntry );
2567 }
2568 
2570 {
2571  mxImpl->StoreCellRange(rRef, rRef, rPos);
2572 }
2573 
2575 {
2576  mxImpl->StoreCellRange(rRef.Ref1, rRef.Ref2, rPos);
2577 }
2578 
2579 void XclExpLinkManager::StoreCell( sal_uInt16 nFileId, const OUString& rTabName, const ScAddress& rPos )
2580 {
2581  mxImpl->StoreCell(nFileId, rTabName, rPos);
2582 }
2583 
2584 void XclExpLinkManager::StoreCellRange( sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange )
2585 {
2586  mxImpl->StoreCellRange(nFileId, rTabName, rRange);
2587 }
2588 
2590  sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rName )
2591 {
2592  return mxImpl->InsertAddIn( rnExtSheet, rnExtName, rName );
2593 }
2594 
2596  sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rName )
2597 {
2598  return mxImpl->InsertEuroTool( rnExtSheet, rnExtName, rName );
2599 }
2600 
2602  sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
2603  const OUString& rApplic, const OUString& rTopic, const OUString& rItem )
2604 {
2605  return mxImpl->InsertDde( rnExtSheet, rnExtName, rApplic, rTopic, rItem );
2606 }
2607 
2609  sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rUrl, const OUString& rName,
2610  const ScExternalRefCache::TokenArrayRef& rArray )
2611 {
2612  return mxImpl->InsertExtName(rnExtSheet, rnExtName, rUrl, rName, rArray);
2613 }
2614 
2616 {
2617  mxImpl->Save( rStrm );
2618 }
2619 
2621 {
2622  mxImpl->SaveXml( rStrm );
2623 }
2624 
2625 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool IsTabRel() const
Definition: refdata.hxx:70
bool operator==(const XclFontData &rLeft, const XclFontData &rRight)
Definition: xlstyle.cxx:517
Matrix data type that can store values of mixed types.
Definition: scmatrix.hxx:113
This class stores an unformatted or formatted string for Excel export.
Definition: xestring.hxx:43
svString
SCCOL Col() const
Definition: refdata.cxx:247
#define DBG_ERROR_BIFF()
Definition: xltools.hxx:31
static OString ToOString(const Color &rColor)
Definition: xestream.cxx:698
virtual svl::SharedString GetString() const
sal_Int32 nIndex
OUString getString() const
void CalcXclIndexes()
Searches for sheets not to be exported.
Definition: xelink.cxx:840
ScAddress aStart
Definition: address.hxx:500
A list of Excel record objects.
Definition: xerecord.hxx:322
bool IsSelectedTab(SCTAB nScTab) const
Returns true, if the specified Calc sheet is selected and will be exported.
Definition: xelink.cxx:789
todo: It should be possible to have MarkArrays for each table, in order to enable "search all" across...
Definition: markdata.hxx:43
SC_DLLPUBLIC ScLinkMode GetLinkMode(SCTAB nTab) const
Definition: documen3.cxx:499
sal_Int32 compareString(const OUString &s1, const OUString &s2) const
bool IsExportTab(SCTAB nScTab) const
Returns true, if the specified Calc sheet will be exported.
Definition: xelink.cxx:771
void Init()
XclExpTabInfo(const XclExpRoot &rRoot)
Initializes the complete buffer from the current exported document.
Definition: xelink.cxx:668
const XclExpRoot & GetRoot() const
Returns the filter root data.
Definition: xestream.hxx:290
bool InsertEuroTool(sal_uInt16 &rnExtSheet, sal_uInt16 &rnExtName, const OUString &rName)
InsertEuroTool.
Definition: xelink.cxx:2595
This class is used to export Excel record streams.
Definition: xestream.hxx:71
bool IsExternalTab(SCTAB nScTab) const
Returns true, if the specified Calc sheet is used to store external cell contents.
Definition: xelink.cxx:777
SCROW Row() const
Definition: address.hxx:262
SCTAB GetCodeNameCount() const
Definition: scextopt.cxx:195
Single reference (one address) into the sheet.
Definition: refdata.hxx:30
XclStrFlags
Flags used to specify import/export mode of strings.
Definition: xlstring.hxx:29
ScAddress toAbs(const ScSheetLimits &rLimits, const ScAddress &rPos) const
Definition: refdata.cxx:193
bool IsVisibleTab(SCTAB nScTab) const
Returns true, if the specified Calc sheet is visible and will be exported.
Definition: xelink.cxx:784
#define CREATE_OFFICEDOC_RELATION_TYPE(ascii)
OUString GetScTabName(SCTAB nScTab) const
Returns the Calc name of the specified sheet.
Definition: xelink.cxx:805
sal_uInt16 mnDisplXclTab
Count of selected and exported sheets.
Definition: xelink.hxx:134
static SC_DLLPUBLIC CollatorWrapper * GetCollator()
Definition: global.cxx:1029
SvNumFormatType GetType(sal_uInt32 nFIndex) const
sal_Int16 nId
bool IsExternalRef() const
const ScExtDocSettings & GetDocSettings() const
Definition: scextopt.cxx:170
sal_uInt16 mnFirstXclTab
Name of the last sheet.
Definition: xeformula.hxx:37
sal_uInt16 mnXclCnt
Count of Calc sheets.
Definition: xelink.hxx:131
ScAddress aEnd
Definition: address.hxx:501
Extended options held by an ScDocument containing additional settings for filters.
Definition: scextopt.hxx:77
sal_uInt16 getExternalFileId(const OUString &rFile)
OpCode GetOpCode() const
std::vector< XclExpTabInfoEntry > maTabInfoVec
Definition: xelink.hxx:128
void FindExtSheet(sal_uInt16 &rnExtSheet, sal_uInt16 &rnXclTab, SCTAB nScTab, XclExpRefLogEntry *pRefLogEntry=nullptr)
Searches for an EXTERNSHEET index for the given Calc sheet.
Definition: xelink.cxx:2543
const sal_uInt8 EXC_CACHEDVAL_ERROR
Definition: xlconst.hxx:119
ScDocument & GetDoc() const
Returns reference to the destination document (import) or source document (export).
Definition: xlroot.cxx:276
const SCCOL MAXCOLCOUNT
Definition: address.hxx:64
ValueVectorType maValues
bool IsEmpty() const
Returns true, if the string is empty.
Definition: xestring.hxx:116
bool IsDeleted() const
Definition: refdata.cxx:125
const OUString * getExternalFileName(sal_uInt16 nFileId, bool bForceOriginal=false)
It returns a pointer to the name of the URI associated with a given external file ID...
HashMap_OWString_Interface aMap
FuncFlags mnFlags
Information about all parameters.
sal_uInt16 sal_Unicode
virtual void SaveXml(XclExpXmlStream &rStrm) override
Writes the entire Link table to OOXML.
Definition: xelink.cxx:2620
Access to global data from other classes.
Definition: xeroot.hxx:113
OUString getNamespaceURL(sal_Int32 nNSID) const
MS Excel 4.0.
Definition: xlconst.hxx:35
#define SAL_MAX_UINT16
SC_DLLPUBLIC SCTAB GetTableCount() const
Definition: document.cxx:314
ReturnType ulimit_cast(Type nValue, ReturnType nMax)
Returns the value, if it is not greater than nMax, otherwise nMax.
Definition: ftools.hxx:51
const SCTAB SCTAB_INVALID
An invalid Excel sheet index, for common use.
Definition: xlconst.hxx:74
OUString maUrl
ScTabVec maToSortedVec
Sorted Calc sheet index -> real Calc sheet index.
Definition: xelink.hxx:138
sal_uInt16 mnLastXclTab
Calc index of the first sheet.
Definition: xeformula.hxx:38
int nCount
virtual const ScSingleRefData * GetSingleRef() const
void PushStream(sax_fastparser::FSHelperPtr const &aStream)
Definition: xestream.cxx:916
SC_DLLPUBLIC ScExternalRefManager * GetExternalRefManager() const
Definition: documen3.cxx:618
svDouble
SCTAB Tab() const
Definition: address.hxx:271
sal_uInt16 mnFirstVisXclTab
Displayed (active) sheet.
Definition: xelink.hxx:135
Base class for all Excel records.
Definition: xerecord.hxx:39
bool IsColRel() const
Definition: refdata.hxx:66
const sal_uInt8 SC_DDE_IGNOREMODE
Definition: document.hxx:294
FormulaError GetDoubleErrorValue(double fVal)
bool GetFlag(SCTAB nScTab, ExcTabBufFlags nFlags) const
Returns true, if any of the passed flags is set for the specified Calc sheet.
Definition: xelink.cxx:822
sax_fastparser::FSHelperPtr & GetCurrentStream()
Definition: xestream.cxx:910
OUString getRelationship(Relationship eRelationship)
void StoreCell(const ScSingleRefData &rRef, const ScAddress &rPos)
Stores the cell with the given address in a CRN record list.
Definition: xelink.cxx:2569
void PopStream()
Definition: xestream.cxx:921
const sal_uInt8 EXC_ERR_REF
Definition: xlconst.hxx:108
void SetSliceSize(sal_uInt16 nSize)
Sets data slice length.
Definition: xestream.cxx:129
bool IsMirroredTab(SCTAB nScTab) const
Returns true, if the specified Calc sheet is displayed in right-to-left mode.
Definition: xelink.cxx:800
ocSep
sal_uInt16 GetXclExtTabCount() const
Returns the number of external linked sheets.
Definition: xelink.hxx:95
bool InsertAddIn(sal_uInt16 &rnExtSheet, sal_uInt16 &rnExtName, const OUString &rName)
Finds or inserts an EXTERNNAME record for an add-in function name.
Definition: xelink.cxx:2589
sal_uInt16 GetXclTab(SCTAB nScTab) const
Returns the Excel sheet index for a given Calc sheet.
Definition: xelink.cxx:811
const sal_uInt8 EXC_TOKID_ERR
End of a sheet reference (BIFF2-BIFF4).
Definition: xlformula.hxx:80
void SetTab(SCTAB nTabP)
Definition: address.hxx:283
virtual void Save(XclExpStream &rStrm) override
Writes the entire Link table.
Definition: xelink.cxx:2615
MS Excel 5.0, MS Excel 7.0 (95)
Definition: xlconst.hxx:36
virtual const ScComplexRefData * GetDoubleRef() const
bool InsertDde(sal_uInt16 &rnExtSheet, sal_uInt16 &rnExtName, const OUString &rApplic, const OUString &rTopic, const OUString &rItem)
Finds or inserts an EXTERNNAME record for DDE links.
Definition: xelink.cxx:2601
XclExpLinkMgrImplPtr mxImpl
Definition: xelink.hxx:220
sal_uInt16 mnXclSelCnt
Count of external link sheets.
Definition: xelink.hxx:133
int i
Reference< XAnimationNode > Clone(const Reference< XAnimationNode > &xSourceNode, const SdPage *pSource, const SdPage *pTarget)
ScExtDocOptions & GetExtDocOptions() const
Returns the extended document options.
Definition: xlroot.cxx:419
static sal_uInt8 GetXclErrorCode(FormulaError nScError)
Converts a Calc error code to an Excel error code.
Definition: xltools.cxx:200
sal_Int16 SCCOL
Definition: types.hxx:22
SCTAB mnScCnt
Array of Calc sheet index information.
Definition: xelink.hxx:130
const XclExpString * mpLastTab
Name of the first sheet.
Definition: xeformula.hxx:36
ScSingleRefData Ref1
Definition: refdata.hxx:125
ScSingleRefData Ref2
Definition: refdata.hxx:126
const XclExpString * mpFirstTab
URL of the document containing the first sheet.
Definition: xeformula.hxx:35
void EndRecord()
Checks and corrects real record length.
Definition: xestream.cxx:120
Stores the correct Excel sheet index for each Calc sheet.
Definition: xelink.hxx:62
const sal_uInt8 EXC_CACHEDVAL_BOOL
Definition: xlconst.hxx:118
svExternalDoubleRef
svExternalSingleRef
bool IsRowRel() const
Definition: refdata.hxx:68
XclExpTabInfo & GetTabInfo() const
Returns the buffer for Calc->Excel sheet index conversion.
Definition: xeroot.cxx:75
XclExpLinkManager(const XclExpRoot &rRoot)
Definition: xelink.cxx:2523
Abstract base class for implementation classes of the link manager.
Definition: xelink.cxx:488
const ScExtTabSettings * GetTabSettings(SCTAB nTab) const
Definition: scextopt.cxx:180
std::shared_ptr< FastSerializerHelper > FSHelperPtr
This class contains static methods to encode a file URL.
Definition: xehelper.hxx:397
const sal_uInt8 EXC_CACHEDVAL_EMPTY
Definition: xlconst.hxx:115
Extended settings for a sheet, used in import/export filters.
Definition: scextopt.hxx:48
SCTAB Tab() const
Definition: refdata.cxx:254
FormulaError
SCCOL Col() const
Definition: address.hxx:267
const XclExpRoot & GetRoot() const
Returns this root instance - for code readability in derived classes.
Definition: xeroot.hxx:119
XclExpValueRecord< sal_uInt16 > XclExpUInt16Record
A record containing an unsigned 16-bit value.
Definition: xerecord.hxx:248
static OUString GetStreamName(const char *sStreamDir, const char *sStream, sal_Int32 nId)
Definition: xestream.cxx:683
SCTAB GetScTabCount() const
Returns the number of Calc sheets.
Definition: xelink.hxx:90
const sal_uInt8 EXC_CACHEDVAL_DOUBLE
Definition: xlconst.hxx:116
::formula::FormulaTokenRef TokenRef
OUString addRelation(const OUString &rType, const OUString &rTarget)
sal_Int32 SCROW
Definition: types.hxx:18
bool InsertExtName(sal_uInt16 &rnExtSheet, sal_uInt16 &rnExtName, const OUString &rUrl, const OUString &rName, const ScExternalRefCache::TokenArrayRef &rArray)
Definition: xelink.cxx:2608
void StoreCellRange(const ScComplexRefData &rRef, const ScAddress &rPos)
Stores all cells in the given range in a CRN record list.
Definition: xelink.cxx:2574
#define OSL_ENSURE_BIFF(c)
Definition: xltools.hxx:32
SC_DLLPUBLIC bool IsScenario(SCTAB nTab) const
Definition: documen3.cxx:427
#define SAL_WARN_IF(condition, area, stream)
const sal_uInt8 EXC_CACHEDVAL_STRING
Definition: xlconst.hxx:117
unsigned char sal_uInt8
ScExternalRefCache::TokenArrayRef getDoubleRefTokens(sal_uInt16 nFileId, const OUString &rTabName, const ScRange &rRange, const ScAddress *pCurPos)
Get an array of tokens that consist of the specified external cell range.
sal_uInt16 GetXclTabCount() const
Returns the number of Excel sheets to be exported.
Definition: xelink.hxx:93
void CalcSortedIndexes()
Sorts the names of all tables and stores the indexes of the sorted indexes.
Definition: xelink.cxx:886
OUString maName
std::shared_ptr< ScTokenArray > TokenArrayRef
std::shared_ptr< Table > TableTypeRef
Always use UCS-2 characters (default: try to compress). BIFF8 only.
svMatrix
SCROW Row() const
Definition: refdata.cxx:240
const XclExpString * mpUrl
Definition: xeformula.hxx:34
void * p
const sal_uInt16 EXC_NOTAB
Definition: xlconst.hxx:73
XclBiff GetBiff() const
Returns the current BIFF version of the importer/exporter.
Definition: xlroot.hxx:141
Log entry for external references in a formula, used i.e.
Definition: xeformula.hxx:32
constexpr sal_Int32 FSNS(sal_Int32 namespc, sal_Int32 element)
SC_DLLPUBLIC bool IsLayoutRTL(SCTAB nTab) const
Definition: document.cxx:994
Complex reference (a range) into the sheet.
Definition: refdata.hxx:123
void SetFlag(SCTAB nScTab, ExcTabBufFlags nFlags, bool bSet=true)
Sets or clears (depending on bSet) all passed flags for the specified Calc sheet. ...
Definition: xelink.cxx:828
This class provides methods to create an XclExpString.
Definition: xehelper.hxx:212
void StartRecord(sal_uInt16 nRecId, std::size_t nRecSize)
Starts a new record: writes header data, stores calculated record size.
Definition: xestream.cxx:108
SbxDimArrayRef mpArray
OUString sId
SC_DLLPUBLIC bool IsVisible(SCTAB nTab) const
Definition: document.cxx:908
#define SAL_WARN(area, stream)
void(* f)(TrueTypeTable *)
virtual ~XclExpLinkManager() override
Definition: xelink.cxx:2539
std::shared_ptr< XclExpString > XclExpStringRef
Definition: xeroot.hxx:36
sal_uInt16 mnXclExtCnt
Count of Excel sheets to be exported.
Definition: xelink.hxx:132
SCTAB GetVisibleTab() const
Definition: document.hxx:859
SCTAB GetRealScTab(SCTAB nSortedScTab) const
Returns the Calc sheet index of the nSortedTab-th entry in the sorted sheet names list...
Definition: xelink.cxx:816
virtual void Save(XclExpStream &rStrm) override
Writes the record header and calls WriteBody().
Definition: xerecord.cxx:150
void SvStream & rStrm
sax_fastparser::FSHelperPtr CreateOutputStream(const OUString &sFullStream, const OUString &sRelativeStream, const css::uno::Reference< css::io::XOutputStream > &xParentRelation, const char *sContentType, const char *sRelationshipType, OUString *pRelationshipId=nullptr)
Definition: xestream.cxx:939
ScTabVec maFromSortedVec
First visible sheet.
Definition: xelink.hxx:137
::std::vector< OUString > ScfStringVec
Definition: ftools.hxx:256
StackVar GetType() const
RedlineType meType
XclExpLinkManagerImpl(const XclExpRoot &rRoot)
Definition: xelink.cxx:2167
SC_DLLPUBLIC bool GetName(SCTAB nTab, OUString &rName) const
Definition: document.cxx:213
bool IsDisplayedTab(SCTAB nScTab) const
Returns true, if the specified Calc sheet is the displayed (active) sheet.
Definition: xelink.cxx:794
Base class for single records with any content.
Definition: xerecord.hxx:143
sal_uInt16 nPos
sal_Int16 SCTAB
Definition: types.hxx:23
const char first[]
SCTAB mnDisplTab
Index of displayed sheet.
Definition: scextopt.hxx:33
void WriteZeroBytes(std::size_t nBytes)
Writes a sequence of nBytes zero bytes (respects slice setting).
Definition: xestream.cxx:256