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