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