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  /* TODO: mpArray contains external references. It doesn't cause any problems, but it's enough
1068  to export it without the external document identifier. */
1069  if (mpArray->GetLen())
1070  {
1071  const OUString aFormula = XclXmlUtils::ToOUString(GetCompileFormulaContext(), ScAddress(0, 0, 0), mpArray.get());
1072  pExternalLink->startElement(XML_definedName,
1073  XML_name, maName.toUtf8(),
1074  XML_refersTo, aFormula.toUtf8(),
1075  XML_sheetId, nullptr);
1076  }
1077  else
1078  {
1079  pExternalLink->startElement(XML_definedName,
1080  XML_name, maName.toUtf8(),
1081  XML_refersTo, nullptr,
1082  XML_sheetId, nullptr);
1083  }
1084 
1085  pExternalLink->endElement(XML_definedName);
1086 }
1087 
1088 // List of external names =====================================================
1089 
1090 XclExpExtNameBuffer::XclExpExtNameBuffer( const XclExpRoot& rRoot ) :
1091  XclExpRoot( rRoot )
1092 {
1093 }
1094 
1095 sal_uInt16 XclExpExtNameBuffer::InsertAddIn( const OUString& rName )
1096 {
1097  sal_uInt16 nIndex = GetIndex( rName );
1098  return nIndex ? nIndex : AppendNew( new XclExpExtNameAddIn( GetRoot(), rName ) );
1099 }
1100 
1101 sal_uInt16 XclExpExtNameBuffer::InsertEuroTool( const OUString& rName )
1102 {
1103  sal_uInt16 nIndex = GetIndex( rName );
1104  return nIndex ? nIndex : AppendNew( new XclExpExtNameBase( GetRoot(), rName ) );
1105 }
1106 
1107 sal_uInt16 XclExpExtNameBuffer::InsertDde(
1108  std::u16string_view rApplic, std::u16string_view rTopic, const OUString& rItem )
1109 {
1110  sal_uInt16 nIndex = GetIndex( rItem );
1111  if( nIndex == 0 )
1112  {
1113  size_t nPos;
1114  if( GetDoc().FindDdeLink( rApplic, rTopic, rItem, SC_DDE_IGNOREMODE, nPos ) )
1115  {
1116  // create the leading 'StdDocumentName' EXTERNNAME record
1117  if( maNameList.IsEmpty() )
1118  AppendNew( new XclExpExtNameDde(
1119  GetRoot(), "StdDocumentName", EXC_EXTN_EXPDDE_STDDOC ) );
1120 
1121  // try to find DDE result array, but create EXTERNNAME record without them too
1122  const ScMatrix* pScMatrix = GetDoc().GetDdeLinkResultMatrix( nPos );
1123  nIndex = AppendNew( new XclExpExtNameDde( GetRoot(), rItem, EXC_EXTN_EXPDDE, pScMatrix ) );
1124  }
1125  }
1126  return nIndex;
1127 }
1128 
1129 sal_uInt16 XclExpExtNameBuffer::InsertExtName( const XclExpSupbook& rSupbook,
1130  const OUString& rName, const ScExternalRefCache::TokenArrayRef& rArray )
1131 {
1132  sal_uInt16 nIndex = GetIndex( rName );
1133  return nIndex ? nIndex : AppendNew( new XclExpExtName( GetRoot(), rSupbook, rName, rArray ) );
1134 }
1135 
1136 void XclExpExtNameBuffer::Save( XclExpStream& rStrm )
1137 {
1138  maNameList.Save( rStrm );
1139 }
1140 
1141 void XclExpExtNameBuffer::SaveXml(XclExpXmlStream& rStrm)
1142 {
1143  maNameList.SaveXml(rStrm);
1144 }
1145 
1146 sal_uInt16 XclExpExtNameBuffer::GetIndex( std::u16string_view rName ) const
1147 {
1148  for( size_t nPos = 0, nSize = maNameList.GetSize(); nPos < nSize; ++nPos )
1149  if( maNameList.GetRecord( nPos )->GetName() == rName )
1150  return static_cast< sal_uInt16 >( nPos + 1 );
1151  return 0;
1152 }
1153 
1154 sal_uInt16 XclExpExtNameBuffer::AppendNew( XclExpExtNameBase* pExtName )
1155 {
1156  size_t nSize = maNameList.GetSize();
1157  if( nSize < 0x7FFF )
1158  {
1159  maNameList.AppendRecord( pExtName );
1160  return static_cast< sal_uInt16 >( nSize + 1 );
1161  }
1162  return 0;
1163 }
1164 
1165 // Cached external cells ======================================================
1166 
1167 XclExpCrn::XclExpCrn( SCCOL nScCol, SCROW nScRow, const Any& rValue ) :
1168  XclExpRecord( EXC_ID_CRN, 4 ),
1169  mnScCol( nScCol ),
1170  mnScRow( nScRow )
1171 {
1172  maValues.push_back( rValue );
1173 }
1174 
1175 bool XclExpCrn::InsertValue( SCCOL nScCol, SCROW nScRow, const Any& rValue )
1176 {
1177  if( (nScRow != mnScRow) || (nScCol != static_cast< SCCOL >( mnScCol + maValues.size() )) )
1178  return false;
1179  maValues.push_back( rValue );
1180  return true;
1181 }
1182 
1183 void XclExpCrn::WriteBody( XclExpStream& rStrm )
1184 {
1185  rStrm << static_cast< sal_uInt8 >( mnScCol + maValues.size() - 1 )
1186  << static_cast< sal_uInt8 >( mnScCol )
1187  << static_cast< sal_uInt16 >( mnScRow );
1188  for( const auto& rValue : maValues )
1189  {
1190  if( rValue.has< bool >() )
1191  WriteBool( rStrm, rValue.get< bool >() );
1192  else if( rValue.has< double >() )
1193  WriteDouble( rStrm, rValue.get< double >() );
1194  else if( rValue.has< OUString >() )
1195  WriteString( rStrm, rValue.get< OUString >() );
1196  else
1197  WriteEmpty( rStrm );
1198  }
1199 }
1200 
1201 void XclExpCrn::WriteBool( XclExpStream& rStrm, bool bValue )
1202 {
1203  rStrm << EXC_CACHEDVAL_BOOL << sal_uInt8( bValue ? 1 : 0);
1204  rStrm.WriteZeroBytes( 7 );
1205 }
1206 
1207 void XclExpCrn::WriteDouble( XclExpStream& rStrm, double fValue )
1208 {
1209  if( !std::isfinite( fValue ) )
1210  {
1211  FormulaError nScError = GetDoubleErrorValue(fValue);
1212  WriteError( rStrm, XclTools::GetXclErrorCode( nScError ) );
1213  }
1214  else
1215  {
1216  rStrm << EXC_CACHEDVAL_DOUBLE << fValue;
1217  }
1218 }
1219 
1220 void XclExpCrn::WriteString( XclExpStream& rStrm, const OUString& rValue )
1221 {
1222  rStrm << EXC_CACHEDVAL_STRING << XclExpString( rValue );
1223 }
1224 
1225 void XclExpCrn::WriteError( XclExpStream& rStrm, sal_uInt8 nErrCode )
1226 {
1227  rStrm << EXC_CACHEDVAL_ERROR << nErrCode;
1228  rStrm.WriteZeroBytes( 7 );
1229 }
1230 
1231 void XclExpCrn::WriteEmpty( XclExpStream& rStrm )
1232 {
1233  rStrm << EXC_CACHEDVAL_EMPTY;
1234  rStrm.WriteZeroBytes( 8 );
1235 }
1236 
1237 void XclExpCrn::SaveXml( XclExpXmlStream& rStrm )
1238 {
1240 
1241  pFS->startElement(XML_row, XML_r, OString::number(mnScRow + 1));
1242 
1243  ScAddress aAdr( mnScCol, mnScRow, 0); // Tab number doesn't matter
1244  for( const auto& rValue : maValues )
1245  {
1246  bool bCloseCell = true;
1247  if( rValue.has< double >() )
1248  {
1249  double fVal = rValue.get< double >();
1250  if (std::isfinite( fVal))
1251  {
1252  // t='n' is omitted
1253  pFS->startElement(XML_cell, XML_r, XclXmlUtils::ToOString(rStrm.GetRoot().GetDoc(), aAdr));
1254  pFS->startElement(XML_v);
1255  pFS->write( fVal );
1256  }
1257  else
1258  {
1259  pFS->startElement(XML_cell, XML_r, XclXmlUtils::ToOString(rStrm.GetRoot().GetDoc(), aAdr), XML_t, "e");
1260  pFS->startElement(XML_v);
1261  pFS->write( "#VALUE!" ); // OOXTODO: support other error values
1262  }
1263  }
1264  else if( rValue.has< OUString >() )
1265  {
1266  pFS->startElement(XML_cell, XML_r, XclXmlUtils::ToOString(rStrm.GetRoot().GetDoc(), aAdr), XML_t, "str");
1267  pFS->startElement(XML_v);
1268  pFS->write( rValue.get< OUString >() );
1269  }
1270  else if( rValue.has< bool >() )
1271  {
1272  pFS->startElement(XML_cell, XML_r, XclXmlUtils::ToOString(rStrm.GetRoot().GetDoc(), aAdr), XML_t, "b");
1273  pFS->startElement(XML_v);
1274  pFS->write( rValue.get< bool >() ? "1" : "0" );
1275  }
1276  // OOXTODO: error type cell t='e'
1277  else
1278  {
1279  // Empty/blank cell not stored, only aAdr is incremented.
1280  bCloseCell = false;
1281  }
1282  if (bCloseCell)
1283  {
1284  pFS->endElement(XML_v);
1285  pFS->endElement(XML_cell);
1286  }
1287  aAdr.IncCol();
1288  }
1289 
1290  pFS->endElement( XML_row);
1291 }
1292 
1293 // Cached cells of a sheet ====================================================
1294 
1295 XclExpXct::XclExpXct( const XclExpRoot& rRoot, const OUString& rTabName,
1296  sal_uInt16 nSBTab, ScExternalRefCache::TableTypeRef const & xCacheTable ) :
1297  XclExpRoot( rRoot ),
1298  mxCacheTable( xCacheTable ),
1299  maUsedCells( rRoot.GetDoc().GetSheetLimits() ),
1300  maBoundRange( ScAddress::INITIALIZE_INVALID ),
1301  maTabName( rTabName ),
1302  mnSBTab( nSBTab )
1303 {
1304 }
1305 
1306 void XclExpXct::StoreCellRange( const ScRange& rRange )
1307 {
1308  // #i70418# restrict size of external range to prevent memory overflow
1309  if( (rRange.aEnd.Col() - rRange.aStart.Col()) * (rRange.aEnd.Row() - rRange.aStart.Row()) > 1024 )
1310  return;
1311 
1312  maUsedCells.SetMultiMarkArea( rRange );
1313  maBoundRange.ExtendTo( rRange );
1314 }
1315 
1316 void XclExpXct::StoreCell_( const ScAddress& rCell )
1317 {
1318  maUsedCells.SetMultiMarkArea( ScRange( rCell ) );
1319  maBoundRange.ExtendTo( ScRange( rCell ) );
1320 }
1321 
1322 void XclExpXct::StoreCellRange_( const ScRange& rRange )
1323 {
1324  maUsedCells.SetMultiMarkArea( rRange );
1325  maBoundRange.ExtendTo( rRange );
1326 }
1327 
1328 namespace {
1329 
1330 class XclExpCrnList : public XclExpRecordList< XclExpCrn >
1331 {
1332 public:
1335  bool InsertValue( SCCOL nScCol, SCROW nScRow, const Any& rValue );
1336 };
1337 
1338 bool XclExpCrnList::InsertValue( SCCOL nScCol, SCROW nScRow, const Any& rValue )
1339 {
1340  RecordRefType xLastRec = GetLastRecord();
1341  if( xLastRec && xLastRec->InsertValue( nScCol, nScRow, rValue ) )
1342  return true;
1343  if( GetSize() == SAL_MAX_UINT16 )
1344  return false;
1345  AppendNewRecord( new XclExpCrn( nScCol, nScRow, rValue ) );
1346  return true;
1347 }
1348 
1349 } // namespace
1350 
1351 bool XclExpXct::BuildCrnList( XclExpCrnList& rCrnRecs )
1352 {
1353  if( !mxCacheTable )
1354  return false;
1355 
1356  /* Get the range of used rows in the cache table. This may help to
1357  optimize building the CRN record list if the cache table does not
1358  contain all referred cells, e.g. if big empty ranges are used in the
1359  formulas. */
1360  ::std::pair< SCROW, SCROW > aRowRange = mxCacheTable->getRowRange();
1361  if( aRowRange.first >= aRowRange.second )
1362  return false;
1363 
1364  /* Crop the bounding range of used cells in this table to Excel limits.
1365  Return if there is no external cell inside these limits. */
1366  if( !GetAddressConverter().ValidateRange( maBoundRange, false ) )
1367  return false;
1368 
1369  /* Find the resulting row range that needs to be processed. */
1370  SCROW nScRow1 = ::std::max( aRowRange.first, maBoundRange.aStart.Row() );
1371  SCROW nScRow2 = ::std::min( aRowRange.second - 1, maBoundRange.aEnd.Row() );
1372  if( nScRow1 > nScRow2 )
1373  return false;
1374 
1375  /* Build and collect all CRN records before writing the XCT record. This
1376  is needed to determine the total number of CRN records which must be
1377  known when writing the XCT record (possibly encrypted, so seeking the
1378  output stream back after writing the CRN records is not an option). */
1379  SvNumberFormatter& rFormatter = GetFormatter();
1380  bool bValid = true;
1381  for( SCROW nScRow = nScRow1; bValid && (nScRow <= nScRow2); ++nScRow )
1382  {
1383  ::std::pair< SCCOL, SCCOL > aColRange = mxCacheTable->getColRange( nScRow );
1384  const SCCOL nScEnd = ::std::min( aColRange.second, GetDoc().GetSheetLimits().GetMaxColCount() );
1385  for( SCCOL nScCol = aColRange.first; bValid && (nScCol < nScEnd); ++nScCol )
1386  {
1387  if( maUsedCells.IsCellMarked( nScCol, nScRow, true ) )
1388  {
1389  sal_uInt32 nScNumFmt = 0;
1390  ScExternalRefCache::TokenRef xToken = mxCacheTable->getCell( nScCol, nScRow, &nScNumFmt );
1391  using namespace ::formula;
1392  if( xToken )
1393  switch( xToken->GetType() )
1394  {
1395  case svDouble:
1396  bValid = (rFormatter.GetType( nScNumFmt ) == SvNumFormatType::LOGICAL) ?
1397  rCrnRecs.InsertValue( nScCol, nScRow, Any( xToken->GetDouble() != 0 ) ) :
1398  rCrnRecs.InsertValue( nScCol, nScRow, Any( xToken->GetDouble() ) );
1399  break;
1400  case svString:
1401  // do not save empty strings (empty cells) to cache
1402  if( !xToken->GetString().isEmpty() )
1403  bValid = rCrnRecs.InsertValue( nScCol, nScRow, Any( xToken->GetString().getString() ) );
1404  break;
1405  default:
1406  break;
1407  }
1408  }
1409  }
1410  }
1411  return true;
1412 }
1413 
1414 void XclExpXct::Save( XclExpStream& rStrm )
1415 {
1416  XclExpCrnList aCrnRecs;
1417  if (!BuildCrnList( aCrnRecs))
1418  return;
1419 
1420  // write the XCT record and the list of CRN records
1421  rStrm.StartRecord( EXC_ID_XCT, 4 );
1422  rStrm << static_cast< sal_uInt16 >( aCrnRecs.GetSize() ) << mnSBTab;
1423  rStrm.EndRecord();
1424  aCrnRecs.Save( rStrm );
1425 }
1426 
1427 void XclExpXct::SaveXml( XclExpXmlStream& rStrm )
1428 {
1429  XclExpCrnList aCrnRecs;
1430 
1432 
1433  bool bValid = BuildCrnList( aCrnRecs);
1434  pFS->startElement(XML_sheetData, XML_sheetId, OString::number(mnSBTab));
1435  if (bValid)
1436  {
1437  // row elements
1438  aCrnRecs.SaveXml( rStrm );
1439  }
1440  pFS->endElement( XML_sheetData);
1441 }
1442 
1443 // External documents (EXTERNSHEET/SUPBOOK), base class =======================
1444 
1445 XclExpExternSheetBase::XclExpExternSheetBase( const XclExpRoot& rRoot, sal_uInt16 nRecId, sal_uInt32 nRecSize ) :
1446  XclExpRecord( nRecId, nRecSize ),
1447  XclExpRoot( rRoot )
1448 {
1449 }
1450 
1451 XclExpExtNameBuffer& XclExpExternSheetBase::GetExtNameBuffer()
1452 {
1453  if( !mxExtNameBfr )
1454  mxExtNameBfr = std::make_shared<XclExpExtNameBuffer>( GetRoot() );
1455  return *mxExtNameBfr;
1456 }
1457 
1458 void XclExpExternSheetBase::WriteExtNameBuffer( XclExpStream& rStrm )
1459 {
1460  if( mxExtNameBfr )
1461  mxExtNameBfr->Save( rStrm );
1462 }
1463 
1464 void XclExpExternSheetBase::WriteExtNameBufferXml( XclExpXmlStream& rStrm )
1465 {
1466  if( mxExtNameBfr )
1467  mxExtNameBfr->SaveXml( rStrm );
1468 }
1469 
1470 // External documents (EXTERNSHEET, BIFF5/BIFF7) ==============================
1471 
1472 XclExpExternSheet::XclExpExternSheet( const XclExpRoot& rRoot, sal_Unicode cCode ) :
1473  XclExpExternSheetBase( rRoot, EXC_ID_EXTERNSHEET )
1474 {
1475  Init( OUStringChar(cCode) );
1476 }
1477 
1478 XclExpExternSheet::XclExpExternSheet( const XclExpRoot& rRoot, std::u16string_view rTabName ) :
1479  XclExpExternSheetBase( rRoot, EXC_ID_EXTERNSHEET )
1480 {
1481  // reference to own sheet: \03<sheetname>
1482  Init(OUStringConcatenation(OUStringChar(EXC_EXTSH_TABNAME) + rTabName));
1483 }
1484 
1485 void XclExpExternSheet::Save( XclExpStream& rStrm )
1486 {
1487  // EXTERNSHEET record
1488  XclExpRecord::Save( rStrm );
1489  // EXTERNNAME records
1490  WriteExtNameBuffer( rStrm );
1491 }
1492 
1493 void XclExpExternSheet::Init( std::u16string_view rEncUrl )
1494 {
1495  OSL_ENSURE_BIFF( GetBiff() <= EXC_BIFF5 );
1496  maTabName.AssignByte( rEncUrl, GetTextEncoding(), XclStrFlags::EightBitLength );
1497  SetRecSize( maTabName.GetSize() );
1498 }
1499 
1500 sal_uInt16 XclExpExternSheet::InsertAddIn( const OUString& rName )
1501 {
1502  return GetExtNameBuffer().InsertAddIn( rName );
1503 }
1504 
1505 void XclExpExternSheet::WriteBody( XclExpStream& rStrm )
1506 {
1507  sal_uInt8 nNameSize = static_cast< sal_uInt8 >( maTabName.Len() );
1508  // special case: reference to own sheet (starting with '\03') needs wrong string length
1509  if( maTabName.GetChar( 0 ) == EXC_EXTSH_TABNAME )
1510  --nNameSize;
1511  rStrm << nNameSize;
1512  maTabName.WriteBuffer( rStrm );
1513 }
1514 
1515 // External document (SUPBOOK, BIFF8) =========================================
1516 
1517 XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, sal_uInt16 nXclTabCount ) :
1518  XclExpExternSheetBase( rRoot, EXC_ID_SUPBOOK, 4 ),
1520  mnXclTabCount( nXclTabCount ),
1521  mnFileId( 0 )
1522 {
1523 }
1524 
1525 XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot ) :
1526  XclExpExternSheetBase( rRoot, EXC_ID_SUPBOOK, 4 ),
1528  mnXclTabCount( 1 ),
1529  mnFileId( 0 )
1530 {
1531 }
1532 
1533 XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, const OUString& rUrl, XclSupbookType ) :
1534  XclExpExternSheetBase( rRoot, EXC_ID_SUPBOOK ),
1535  maUrl( rUrl ),
1536  maUrlEncoded( rUrl ),
1538  mnXclTabCount( 0 ),
1539  mnFileId( 0 )
1540 {
1541  SetRecSize( 2 + maUrlEncoded.GetSize() );
1542 }
1543 
1544 XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, const OUString& rUrl ) :
1545  XclExpExternSheetBase( rRoot, EXC_ID_SUPBOOK ),
1546  maUrl( rUrl ),
1547  maUrlEncoded( XclExpUrlHelper::EncodeUrl( rRoot, rUrl ) ),
1549  mnXclTabCount( 0 ),
1550  mnFileId( 0 )
1551 {
1552  SetRecSize( 2 + maUrlEncoded.GetSize() );
1553 
1554  // We need to create all tables up front to ensure the correct table order.
1555  ScExternalRefManager* pRefMgr = rRoot.GetDoc().GetExternalRefManager();
1556  sal_uInt16 nFileId = pRefMgr->getExternalFileId( rUrl );
1557  mnFileId = nFileId + 1;
1558  ScfStringVec aTabNames;
1559  pRefMgr->getAllCachedTableNames( nFileId, aTabNames );
1560  size_t nTabIndex = 0;
1561  for( const auto& rTabName : aTabNames )
1562  {
1563  InsertTabName( rTabName, pRefMgr->getCacheTable( nFileId, nTabIndex ) );
1564  ++nTabIndex;
1565  }
1566 }
1567 
1568 XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, const OUString& rApplic, const OUString& rTopic ) :
1569  XclExpExternSheetBase( rRoot, EXC_ID_SUPBOOK, 4 ),
1570  maUrl( rApplic ),
1571  maDdeTopic( rTopic ),
1572  maUrlEncoded( XclExpUrlHelper::EncodeDde( rApplic, rTopic ) ),
1574  mnXclTabCount( 0 ),
1575  mnFileId( 0 )
1576 {
1577  SetRecSize( 2 + maUrlEncoded.GetSize() );
1578 }
1579 
1580 bool XclExpSupbook::IsUrlLink( std::u16string_view rUrl ) const
1581 {
1582  return (meType == XclSupbookType::Extern || meType == XclSupbookType::Eurotool) && (maUrl == rUrl);
1583 }
1584 
1585 bool XclExpSupbook::IsDdeLink( std::u16string_view rApplic, std::u16string_view rTopic ) const
1586 {
1587  return (meType == XclSupbookType::Special) && (maUrl == rApplic) && (maDdeTopic == rTopic);
1588 }
1589 
1590 void XclExpSupbook::FillRefLogEntry( XclExpRefLogEntry& rRefLogEntry,
1591  sal_uInt16 nFirstSBTab, sal_uInt16 nLastSBTab ) const
1592 {
1593  rRefLogEntry.mpUrl = maUrlEncoded.IsEmpty() ? nullptr : &maUrlEncoded;
1594  rRefLogEntry.mpFirstTab = GetTabName( nFirstSBTab );
1595  rRefLogEntry.mpLastTab = GetTabName( nLastSBTab );
1596 }
1597 
1598 void XclExpSupbook::StoreCellRange( const ScRange& rRange, sal_uInt16 nSBTab )
1599 {
1600  if( XclExpXct* pXct = maXctList.GetRecord( nSBTab ) )
1601  pXct->StoreCellRange( rRange );
1602 }
1603 
1604 void XclExpSupbook::StoreCell_( sal_uInt16 nSBTab, const ScAddress& rCell )
1605 {
1606  if( XclExpXct* pXct = maXctList.GetRecord( nSBTab ) )
1607  pXct->StoreCell_( rCell );
1608 }
1609 
1610 void XclExpSupbook::StoreCellRange_( sal_uInt16 nSBTab, const ScRange& rRange )
1611 {
1612  // multi-table range is not allowed!
1613  if( rRange.aStart.Tab() == rRange.aEnd.Tab() )
1614  if( XclExpXct* pXct = maXctList.GetRecord( nSBTab ) )
1615  pXct->StoreCellRange_( rRange );
1616 }
1617 
1618 sal_uInt16 XclExpSupbook::GetTabIndex( const OUString& rTabName ) const
1619 {
1620  XclExpString aXclName(rTabName);
1621  size_t nSize = maXctList.GetSize();
1622  for (size_t i = 0; i < nSize; ++i)
1623  {
1624  XclExpXctRef aRec = maXctList.GetRecord(i);
1625  if (aXclName == aRec->GetTabName())
1626  return ulimit_cast<sal_uInt16>(i);
1627  }
1628  return EXC_NOTAB;
1629 }
1630 
1631 sal_uInt16 XclExpSupbook::GetTabCount() const
1632 {
1633  return ulimit_cast<sal_uInt16>(maXctList.GetSize());
1634 }
1635 
1636 sal_uInt16 XclExpSupbook::InsertTabName( const OUString& rTabName, ScExternalRefCache::TableTypeRef const & xCacheTable )
1637 {
1638  SAL_WARN_IF( meType != XclSupbookType::Extern, "sc.filter", "Don't insert sheet names here" );
1639  sal_uInt16 nSBTab = ulimit_cast< sal_uInt16 >( maXctList.GetSize() );
1640  XclExpXctRef xXct = new XclExpXct( GetRoot(), rTabName, nSBTab, xCacheTable );
1641  AddRecSize( xXct->GetTabName().GetSize() );
1642  maXctList.AppendRecord( xXct );
1643  return nSBTab;
1644 }
1645 
1646 sal_uInt16 XclExpSupbook::InsertAddIn( const OUString& rName )
1647 {
1648  return GetExtNameBuffer().InsertAddIn( rName );
1649 }
1650 
1651 sal_uInt16 XclExpSupbook::InsertEuroTool( const OUString& rName )
1652 {
1653  return GetExtNameBuffer().InsertEuroTool( rName );
1654 }
1655 
1656 sal_uInt16 XclExpSupbook::InsertDde( const OUString& rItem )
1657 {
1658  return GetExtNameBuffer().InsertDde( maUrl, maDdeTopic, rItem );
1659 }
1660 
1661 sal_uInt16 XclExpSupbook::InsertExtName( const OUString& rName, const ScExternalRefCache::TokenArrayRef& rArray )
1662 {
1663  return GetExtNameBuffer().InsertExtName(*this, rName, rArray);
1664 }
1665 
1666 XclSupbookType XclExpSupbook::GetType() const
1667 {
1668  return meType;
1669 }
1670 
1671 sal_uInt16 XclExpSupbook::GetFileId() const
1672 {
1673  return mnFileId;
1674 }
1675 
1676 const OUString& XclExpSupbook::GetUrl() const
1677 {
1678  return maUrl;
1679 }
1680 
1681 void XclExpSupbook::Save( XclExpStream& rStrm )
1682 {
1683  // SUPBOOK record
1684  XclExpRecord::Save( rStrm );
1685  // XCT record, CRN records
1686  maXctList.Save( rStrm );
1687  // EXTERNNAME records
1688  WriteExtNameBuffer( rStrm );
1689 }
1690 
1691 void XclExpSupbook::SaveXml( XclExpXmlStream& rStrm )
1692 {
1693  sax_fastparser::FSHelperPtr pExternalLink = rStrm.GetCurrentStream();
1694 
1695  // Add relation for this stream, e.g. xl/externalLinks/_rels/externalLink1.xml.rels
1696  sal_uInt16 nLevel = 0;
1697  bool bRel = true;
1698 
1699  // BuildFileName delete ../ and convert them to nLevel
1700  // but addrelation needs ../ instead of nLevel, so we have to convert it back
1701  OUString sFile = XclExpHyperlink::BuildFileName(nLevel, bRel, maUrl, GetRoot(), true);
1702  while (nLevel-- > 0)
1703  sFile = "../" + sFile;
1704 
1705  OUString sId = rStrm.addRelation( pExternalLink->getOutputStream(),
1706  oox::getRelationship(Relationship::EXTERNALLINKPATH), sFile, true );
1707 
1708  pExternalLink->startElement( XML_externalLink,
1709  XML_xmlns, rStrm.getNamespaceURL(OOX_NS(xls)).toUtf8());
1710 
1711  pExternalLink->startElement( XML_externalBook,
1712  FSNS(XML_xmlns, XML_r), rStrm.getNamespaceURL(OOX_NS(officeRel)).toUtf8(),
1713  FSNS(XML_r, XML_id), sId.toUtf8());
1714 
1715  if (!maXctList.IsEmpty())
1716  {
1717  pExternalLink->startElement(XML_sheetNames);
1718  for (size_t nPos = 0, nSize = maXctList.GetSize(); nPos < nSize; ++nPos)
1719  {
1720  pExternalLink->singleElement(XML_sheetName,
1721  XML_val, XclXmlUtils::ToOString(maXctList.GetRecord(nPos)->GetTabName()));
1722  }
1723  pExternalLink->endElement( XML_sheetNames);
1724 
1725  }
1726 
1727  if (mxExtNameBfr)
1728  {
1729  pExternalLink->startElement(XML_definedNames);
1730  // externalName elements
1731  WriteExtNameBufferXml( rStrm );
1732  pExternalLink->endElement(XML_definedNames);
1733  }
1734 
1735  if (!maXctList.IsEmpty())
1736  {
1737  pExternalLink->startElement(XML_sheetDataSet);
1738 
1739  // sheetData elements
1740  maXctList.SaveXml( rStrm );
1741 
1742  pExternalLink->endElement( XML_sheetDataSet);
1743 
1744  }
1745  pExternalLink->endElement( XML_externalBook);
1746  pExternalLink->endElement( XML_externalLink);
1747 }
1748 
1749 const XclExpString* XclExpSupbook::GetTabName( sal_uInt16 nSBTab ) const
1750 {
1751  XclExpXctRef xXct = maXctList.GetRecord( nSBTab );
1752  return xXct ? &xXct->GetTabName() : nullptr;
1753 }
1754 
1755 void XclExpSupbook::WriteBody( XclExpStream& rStrm )
1756 {
1757  switch( meType )
1758  {
1759  case XclSupbookType::Self:
1760  rStrm << mnXclTabCount << EXC_SUPB_SELF;
1761  break;
1765  {
1766  sal_uInt16 nCount = ulimit_cast< sal_uInt16 >( maXctList.GetSize() );
1767  rStrm << nCount << maUrlEncoded;
1768 
1769  for( size_t nPos = 0, nSize = maXctList.GetSize(); nPos < nSize; ++nPos )
1770  rStrm << maXctList.GetRecord( nPos )->GetTabName();
1771  }
1772  break;
1773  case XclSupbookType::Addin:
1774  rStrm << mnXclTabCount << EXC_SUPB_ADDIN;
1775  break;
1776  default:
1777  SAL_WARN( "sc.filter", "Unhandled SUPBOOK type " << meType);
1778  }
1779 }
1780 
1781 // All SUPBOOKS in a document =================================================
1782 
1783 XclExpSupbookBuffer::XclExpSupbookBuffer( const XclExpRoot& rRoot ) :
1784  XclExpRoot( rRoot ),
1785  mnOwnDocSB( SAL_MAX_UINT16 ),
1786  mnAddInSB( SAL_MAX_UINT16 )
1787 {
1788  XclExpTabInfo& rTabInfo = GetTabInfo();
1789  sal_uInt16 nXclCnt = rTabInfo.GetXclTabCount();
1790  sal_uInt16 nCodeCnt = static_cast< sal_uInt16 >( GetExtDocOptions().GetCodeNameCount() );
1791  size_t nCount = nXclCnt + rTabInfo.GetXclExtTabCount();
1792 
1793  OSL_ENSURE( nCount > 0, "XclExpSupbookBuffer::XclExpSupbookBuffer - no sheets to export" );
1794  if( nCount )
1795  {
1796  maSBIndexVec.resize( nCount );
1797 
1798  // self-ref SUPBOOK first of list
1799  XclExpSupbookRef xSupbook = new XclExpSupbook( GetRoot(), ::std::max( nXclCnt, nCodeCnt ) );
1800  mnOwnDocSB = Append( xSupbook );
1801  for( sal_uInt16 nXclTab = 0; nXclTab < nXclCnt; ++nXclTab )
1802  maSBIndexVec[ nXclTab ].Set( mnOwnDocSB, nXclTab );
1803  }
1804 }
1805 
1806 XclExpXti XclExpSupbookBuffer::GetXti( sal_uInt16 nFirstXclTab, sal_uInt16 nLastXclTab,
1807  XclExpRefLogEntry* pRefLogEntry ) const
1808 {
1809  XclExpXti aXti;
1810  size_t nSize = maSBIndexVec.size();
1811  if( (nFirstXclTab < nSize) && (nLastXclTab < nSize) )
1812  {
1813  // index of the SUPBOOK record
1814  aXti.mnSupbook = maSBIndexVec[ nFirstXclTab ].mnSupbook;
1815 
1816  // all sheets in the same supbook?
1817  bool bSameSB = true;
1818  for( sal_uInt16 nXclTab = nFirstXclTab + 1; bSameSB && (nXclTab <= nLastXclTab); ++nXclTab )
1819  {
1820  bSameSB = maSBIndexVec[ nXclTab ].mnSupbook == aXti.mnSupbook;
1821  if( !bSameSB )
1822  nLastXclTab = nXclTab - 1;
1823  }
1824  aXti.mnFirstSBTab = maSBIndexVec[ nFirstXclTab ].mnSBTab;
1825  aXti.mnLastSBTab = maSBIndexVec[ nLastXclTab ].mnSBTab;
1826 
1827  // fill external reference log entry (for change tracking)
1828  if( pRefLogEntry )
1829  {
1830  pRefLogEntry->mnFirstXclTab = nFirstXclTab;
1831  pRefLogEntry->mnLastXclTab = nLastXclTab;
1832  XclExpSupbookRef xSupbook = maSupbookList.GetRecord( aXti.mnSupbook );
1833  if( xSupbook )
1834  xSupbook->FillRefLogEntry( *pRefLogEntry, aXti.mnFirstSBTab, aXti.mnLastSBTab );
1835  }
1836  }
1837  else
1838  {
1839  // special range, i.e. for deleted sheets or add-ins
1840  aXti.mnSupbook = mnOwnDocSB;
1841  aXti.mnFirstSBTab = nFirstXclTab;
1842  aXti.mnLastSBTab = nLastXclTab;
1843  }
1844 
1845  return aXti;
1846 }
1847 
1848 void XclExpSupbookBuffer::StoreCellRange( const ScRange& rRange )
1849 {
1850  sal_uInt16 nXclTab = GetTabInfo().GetXclTab( rRange.aStart.Tab() );
1851  if( nXclTab < maSBIndexVec.size() )
1852  {
1853  const XclExpSBIndex& rSBIndex = maSBIndexVec[ nXclTab ];
1854  XclExpSupbookRef xSupbook = maSupbookList.GetRecord( rSBIndex.mnSupbook );
1855  OSL_ENSURE( xSupbook , "XclExpSupbookBuffer::StoreCellRange - missing SUPBOOK record" );
1856  if( xSupbook )
1857  xSupbook->StoreCellRange( rRange, rSBIndex.mnSBTab );
1858  }
1859 }
1860 
1861 namespace {
1862 
1863 class FindSBIndexEntry
1864 {
1865 public:
1866  explicit FindSBIndexEntry(sal_uInt16 nSupbookId, sal_uInt16 nTabId) :
1867  mnSupbookId(nSupbookId), mnTabId(nTabId) {}
1868 
1869  bool operator()(const XclExpSupbookBuffer::XclExpSBIndex& r) const
1870  {
1871  return mnSupbookId == r.mnSupbook && mnTabId == r.mnSBTab;
1872  }
1873 
1874 private:
1875  sal_uInt16 mnSupbookId;
1876  sal_uInt16 mnTabId;
1877 };
1878 
1879 }
1880 
1881 void XclExpSupbookBuffer::StoreCell( sal_uInt16 nFileId, const OUString& rTabName, const ScAddress& rCell )
1882 {
1883  ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager();
1884  const OUString* pUrl = pRefMgr->getExternalFileName(nFileId);
1885  if (!pUrl)
1886  return;
1887 
1888  XclExpSupbookRef xSupbook;
1889  sal_uInt16 nSupbookId;
1890  if (!GetSupbookUrl(xSupbook, nSupbookId, *pUrl))
1891  {
1892  xSupbook = new XclExpSupbook(GetRoot(), *pUrl);
1893  nSupbookId = Append(xSupbook);
1894  }
1895 
1896  sal_uInt16 nSheetId = xSupbook->GetTabIndex(rTabName);
1897  if (nSheetId == EXC_NOTAB)
1898  // specified table name not found in this SUPBOOK.
1899  return;
1900 
1901  FindSBIndexEntry f(nSupbookId, nSheetId);
1902  if (::std::none_of(maSBIndexVec.begin(), maSBIndexVec.end(), f))
1903  {
1904  maSBIndexVec.emplace_back();
1905  XclExpSBIndex& r = maSBIndexVec.back();
1906  r.mnSupbook = nSupbookId;
1907  r.mnSBTab = nSheetId;
1908  }
1909 
1910  xSupbook->StoreCell_(nSheetId, rCell);
1911 }
1912 
1913 void XclExpSupbookBuffer::StoreCellRange( sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange )
1914 {
1915  ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager();
1916  const OUString* pUrl = pRefMgr->getExternalFileName(nFileId);
1917  if (!pUrl)
1918  return;
1919 
1920  XclExpSupbookRef xSupbook;
1921  sal_uInt16 nSupbookId;
1922  if (!GetSupbookUrl(xSupbook, nSupbookId, *pUrl))
1923  {
1924  xSupbook = new XclExpSupbook(GetRoot(), *pUrl);
1925  nSupbookId = Append(xSupbook);
1926  }
1927 
1928  SCTAB nTabCount = rRange.aEnd.Tab() - rRange.aStart.Tab() + 1;
1929 
1930  // If this is a multi-table range, get token for each table.
1931  using namespace ::formula;
1932  SCTAB aMatrixListSize = 0;
1933 
1934  // This is a new'ed instance, so we must manage its life cycle here.
1935  ScExternalRefCache::TokenArrayRef pArray = pRefMgr->getDoubleRefTokens(nFileId, rTabName, rRange, nullptr);
1936  if (!pArray)
1937  return;
1938 
1939  FormulaTokenArrayPlainIterator aIter(*pArray);
1940  for (FormulaToken* p = aIter.First(); p; p = aIter.Next())
1941  {
1942  if (p->GetType() == svMatrix)
1943  ++aMatrixListSize;
1944  else if (p->GetOpCode() != ocSep)
1945  {
1946  // This is supposed to be ocSep!!!
1947  return;
1948  }
1949  }
1950 
1951  if (aMatrixListSize != nTabCount)
1952  {
1953  // matrix size mismatch!
1954  return;
1955  }
1956 
1957  sal_uInt16 nFirstSheetId = xSupbook->GetTabIndex(rTabName);
1958 
1959  ScRange aRange(rRange);
1960  aRange.aStart.SetTab(0);
1961  aRange.aEnd.SetTab(0);
1962  for (SCTAB nTab = 0; nTab < nTabCount; ++nTab)
1963  {
1964  sal_uInt16 nSheetId = nFirstSheetId + static_cast<sal_uInt16>(nTab);
1965  FindSBIndexEntry f(nSupbookId, nSheetId);
1966  if (::std::none_of(maSBIndexVec.begin(), maSBIndexVec.end(), f))
1967  {
1968  maSBIndexVec.emplace_back();
1969  XclExpSBIndex& r = maSBIndexVec.back();
1970  r.mnSupbook = nSupbookId;
1971  r.mnSBTab = nSheetId;
1972  }
1973 
1974  xSupbook->StoreCellRange_(nSheetId, aRange);
1975  }
1976 }
1977 
1978 bool XclExpSupbookBuffer::InsertAddIn(
1979  sal_uInt16& rnSupbook, sal_uInt16& rnExtName, const OUString& rName )
1980 {
1981  XclExpSupbookRef xSupbook;
1982  if( mnAddInSB == SAL_MAX_UINT16 )
1983  {
1984  xSupbook = new XclExpSupbook( GetRoot() );
1985  mnAddInSB = Append( xSupbook );
1986  }
1987  else
1988  xSupbook = maSupbookList.GetRecord( mnAddInSB );
1989  OSL_ENSURE( xSupbook, "XclExpSupbookBuffer::InsertAddin - missing add-in supbook" );
1990  rnSupbook = mnAddInSB;
1991  rnExtName = xSupbook->InsertAddIn( rName );
1992  return rnExtName > 0;
1993 }
1994 
1995 bool XclExpSupbookBuffer::InsertEuroTool(
1996  sal_uInt16& rnSupbook, sal_uInt16& rnExtName, const OUString& rName )
1997 {
1998  XclExpSupbookRef xSupbook;
1999  OUString aUrl( "\001\010EUROTOOL.XLA" );
2000  if( !GetSupbookUrl( xSupbook, rnSupbook, aUrl ) )
2001  {
2002  xSupbook = new XclExpSupbook( GetRoot(), aUrl, XclSupbookType::Eurotool );
2003  rnSupbook = Append( xSupbook );
2004  }
2005  rnExtName = xSupbook->InsertEuroTool( rName );
2006  return rnExtName > 0;
2007 }
2008 
2009 bool XclExpSupbookBuffer::InsertDde(
2010  sal_uInt16& rnSupbook, sal_uInt16& rnExtName,
2011  const OUString& rApplic, const OUString& rTopic, const OUString& rItem )
2012 {
2013  XclExpSupbookRef xSupbook;
2014  if( !GetSupbookDde( xSupbook, rnSupbook, rApplic, rTopic ) )
2015  {
2016  xSupbook = new XclExpSupbook( GetRoot(), rApplic, rTopic );
2017  rnSupbook = Append( xSupbook );
2018  }
2019  rnExtName = xSupbook->InsertDde( rItem );
2020  return rnExtName > 0;
2021 }
2022 
2023 bool XclExpSupbookBuffer::InsertExtName(
2024  sal_uInt16& rnSupbook, sal_uInt16& rnExtName, const OUString& rUrl,
2025  const OUString& rName, const ScExternalRefCache::TokenArrayRef& rArray )
2026 {
2027  XclExpSupbookRef xSupbook;
2028  if (!GetSupbookUrl(xSupbook, rnSupbook, rUrl))
2029  {
2030  xSupbook = new XclExpSupbook(GetRoot(), rUrl);
2031  rnSupbook = Append(xSupbook);
2032  }
2033  rnExtName = xSupbook->InsertExtName(rName, rArray);
2034  return rnExtName > 0;
2035 }
2036 
2037 XclExpXti XclExpSupbookBuffer::GetXti( sal_uInt16 nFileId, const OUString& rTabName, sal_uInt16 nXclTabSpan,
2038  XclExpRefLogEntry* pRefLogEntry )
2039 {
2040  XclExpXti aXti(0, EXC_NOTAB, EXC_NOTAB);
2041  ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager();
2042  const OUString* pUrl = pRefMgr->getExternalFileName(nFileId);
2043  if (!pUrl)
2044  return aXti;
2045 
2046  XclExpSupbookRef xSupbook;
2047  sal_uInt16 nSupbookId;
2048  if (!GetSupbookUrl(xSupbook, nSupbookId, *pUrl))
2049  {
2050  xSupbook = new XclExpSupbook(GetRoot(), *pUrl);
2051  nSupbookId = Append(xSupbook);
2052  }
2053  aXti.mnSupbook = nSupbookId;
2054 
2055  sal_uInt16 nFirstSheetId = xSupbook->GetTabIndex(rTabName);
2056  if (nFirstSheetId == EXC_NOTAB)
2057  {
2058  // first sheet not found in SUPBOOK.
2059  return aXti;
2060  }
2061  sal_uInt16 nSheetCount = xSupbook->GetTabCount();
2062  for (sal_uInt16 i = 0; i < nXclTabSpan; ++i)
2063  {
2064  sal_uInt16 nSheetId = nFirstSheetId + i;
2065  if (nSheetId >= nSheetCount)
2066  return aXti;
2067 
2068  FindSBIndexEntry f(nSupbookId, nSheetId);
2069  if (::std::none_of(maSBIndexVec.begin(), maSBIndexVec.end(), f))
2070  {
2071  maSBIndexVec.emplace_back();
2072  XclExpSBIndex& r = maSBIndexVec.back();
2073  r.mnSupbook = nSupbookId;
2074  r.mnSBTab = nSheetId;
2075  }
2076  if (i == 0)
2077  aXti.mnFirstSBTab = nSheetId;
2078  if (i == nXclTabSpan - 1)
2079  aXti.mnLastSBTab = nSheetId;
2080  }
2081 
2082  if (pRefLogEntry)
2083  {
2084  pRefLogEntry->mnFirstXclTab = 0;
2085  pRefLogEntry->mnLastXclTab = 0;
2086  if (xSupbook)
2087  xSupbook->FillRefLogEntry(*pRefLogEntry, aXti.mnFirstSBTab, aXti.mnLastSBTab);
2088  }
2089 
2090  return aXti;
2091 }
2092 
2093 void XclExpSupbookBuffer::Save( XclExpStream& rStrm )
2094 {
2095  maSupbookList.Save( rStrm );
2096 }
2097 
2098 void XclExpSupbookBuffer::SaveXml( XclExpXmlStream& rStrm )
2099 {
2100  // Unused external references are not saved, only kept in memory.
2101  // Those that are saved must be indexed from 1, so indexes must be reordered
2102  ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager();
2103  vector<sal_uInt16> aExternFileIds;
2104  for (size_t nPos = 0, nSize = maSupbookList.GetSize(); nPos < nSize; ++nPos)
2105  {
2106  XclExpSupbookRef xRef(maSupbookList.GetRecord(nPos));
2107  // fileIDs are indexed from 1 in xlsx, and from 0 in ScExternalRefManager
2108  // converting between them require a -1 or +1
2109  if (xRef->GetType() == XclSupbookType::Extern)
2110  aExternFileIds.push_back(xRef->GetFileId() - 1);
2111  }
2112  if (aExternFileIds.size() > 0)
2113  pRefMgr->setSkipUnusedFileIds(aExternFileIds);
2114 
2115  ::std::map< sal_uInt16, OUString > aMap;
2116  for (size_t nPos = 0, nSize = maSupbookList.GetSize(); nPos < nSize; ++nPos)
2117  {
2118  XclExpSupbookRef xRef( maSupbookList.GetRecord( nPos));
2119  if (xRef->GetType() != XclSupbookType::Extern)
2120  continue; // handle only external reference (for now?)
2121 
2122  sal_uInt16 nId = xRef->GetFileId();
2123  sal_uInt16 nUsedId = pRefMgr->convertFileIdToUsedFileId(nId - 1) + 1;
2124  const OUString& rUrl = xRef->GetUrl();
2125  ::std::pair< ::std::map< sal_uInt16, OUString >::iterator, bool > aInsert(
2126  aMap.insert( ::std::make_pair( nId, rUrl)));
2127  if (!aInsert.second)
2128  {
2129  SAL_WARN( "sc.filter", "XclExpSupbookBuffer::SaveXml: file ID already used: " << nId <<
2130  " wanted for " << rUrl << " and is " << (*aInsert.first).second <<
2131  (rUrl == (*aInsert.first).second ? " multiple Supbook not supported" : ""));
2132  continue;
2133  }
2134  OUString sId;
2135  sax_fastparser::FSHelperPtr pExternalLink = rStrm.CreateOutputStream(
2136  XclXmlUtils::GetStreamName( "xl/", "externalLinks/externalLink", nUsedId),
2137  XclXmlUtils::GetStreamName( nullptr, "externalLinks/externalLink", nUsedId),
2138  rStrm.GetCurrentStream()->getOutputStream(),
2139  "application/vnd.openxmlformats-officedocument.spreadsheetml.externalLink+xml",
2140  CREATE_OFFICEDOC_RELATION_TYPE("externalLink"),
2141  &sId );
2142 
2143  // externalReference entry in workbook externalReferences
2144  rStrm.GetCurrentStream()->singleElement( XML_externalReference,
2145  FSNS(XML_r, XML_id), sId.toUtf8() );
2146 
2147  // Each externalBook in a separate stream.
2148  rStrm.PushStream( pExternalLink );
2149  xRef->SaveXml( rStrm );
2150  rStrm.PopStream();
2151  }
2152 }
2153 
2154 bool XclExpSupbookBuffer::HasExternalReferences() const
2155 {
2156  for (size_t nPos = 0, nSize = maSupbookList.GetSize(); nPos < nSize; ++nPos)
2157  {
2158  if (maSupbookList.GetRecord( nPos)->GetType() == XclSupbookType::Extern)
2159  return true;
2160  }
2161  return false;
2162 }
2163 
2164 bool XclExpSupbookBuffer::GetSupbookUrl(
2165  XclExpSupbookRef& rxSupbook, sal_uInt16& rnIndex, std::u16string_view rUrl ) const
2166 {
2167  for( size_t nPos = 0, nSize = maSupbookList.GetSize(); nPos < nSize; ++nPos )
2168  {
2169  rxSupbook = maSupbookList.GetRecord( nPos );
2170  if( rxSupbook->IsUrlLink( rUrl ) )
2171  {
2172  rnIndex = ulimit_cast< sal_uInt16 >( nPos );
2173  return true;
2174  }
2175  }
2176  return false;
2177 }
2178 
2179 bool XclExpSupbookBuffer::GetSupbookDde( XclExpSupbookRef& rxSupbook,
2180  sal_uInt16& rnIndex, std::u16string_view rApplic, std::u16string_view rTopic ) const
2181 {
2182  for( size_t nPos = 0, nSize = maSupbookList.GetSize(); nPos < nSize; ++nPos )
2183  {
2184  rxSupbook = maSupbookList.GetRecord( nPos );
2185  if( rxSupbook->IsDdeLink( rApplic, rTopic ) )
2186  {
2187  rnIndex = ulimit_cast< sal_uInt16 >( nPos );
2188  return true;
2189  }
2190  }
2191  return false;
2192 }
2193 
2194 sal_uInt16 XclExpSupbookBuffer::Append( XclExpSupbookRef const & xSupbook )
2195 {
2196  maSupbookList.AppendRecord( xSupbook );
2197  return ulimit_cast< sal_uInt16 >( maSupbookList.GetSize() - 1 );
2198 }
2199 
2200 // Export link manager ========================================================
2201 
2203  XclExpRoot( rRoot )
2204 {
2205 }
2206 
2207 XclExpLinkManagerImpl5::XclExpLinkManagerImpl5( const XclExpRoot& rRoot ) :
2208  XclExpLinkManagerImpl( rRoot )
2209 {
2210 }
2211 
2212 void XclExpLinkManagerImpl5::FindExtSheet(
2213  sal_uInt16& rnExtSheet, sal_uInt16& rnFirstXclTab, sal_uInt16& rnLastXclTab,
2214  SCTAB nFirstScTab, SCTAB nLastScTab, XclExpRefLogEntry* pRefLogEntry )
2215 {
2216  FindInternal( rnExtSheet, rnFirstXclTab, nFirstScTab );
2217  if( (rnFirstXclTab == EXC_TAB_DELETED) || (nFirstScTab == nLastScTab) )
2218  {
2219  rnLastXclTab = rnFirstXclTab;
2220  }
2221  else
2222  {
2223  sal_uInt16 nDummyExtSheet;
2224  FindInternal( nDummyExtSheet, rnLastXclTab, nLastScTab );
2225  }
2226 
2227  OSL_ENSURE( !pRefLogEntry, "XclExpLinkManagerImpl5::FindExtSheet - fill reflog entry not implemented" );
2228 }
2229 
2230 sal_uInt16 XclExpLinkManagerImpl5::FindExtSheet( sal_Unicode cCode )
2231 {
2232  sal_uInt16 nExtSheet;
2233  FindInternal( nExtSheet, cCode );
2234  return nExtSheet;
2235 }
2236 
2237 void XclExpLinkManagerImpl5::FindExtSheet(
2238  sal_uInt16 /*nFileId*/, const OUString& /*rTabName*/, sal_uInt16 /*nXclTabSpan*/,
2239  sal_uInt16& /*rnExtSheet*/, sal_uInt16& /*rnFirstSBTab*/, sal_uInt16& /*rnLastSBTab*/,
2240  XclExpRefLogEntry* /*pRefLogEntry*/ )
2241 {
2242  // not implemented
2243 }
2244 
2245 void XclExpLinkManagerImpl5::StoreCellRange( const ScSingleRefData& /*rRef1*/, const ScSingleRefData& /*rRef2*/, const ScAddress& /*rPos*/ )
2246 {
2247  // not implemented
2248 }
2249 
2250 void XclExpLinkManagerImpl5::StoreCell( sal_uInt16 /*nFileId*/, const OUString& /*rTabName*/, const ScAddress& /*rPos*/ )
2251 {
2252  // not implemented
2253 }
2254 
2255 void XclExpLinkManagerImpl5::StoreCellRange( sal_uInt16 /*nFileId*/, const OUString& /*rTabName*/, const ScRange& /*rRange*/ )
2256 {
2257  // not implemented
2258 }
2259 
2260 bool XclExpLinkManagerImpl5::InsertAddIn(
2261  sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rName )
2262 {
2263  XclExpExtSheetRef xExtSheet = FindInternal( rnExtSheet, EXC_EXTSH_ADDIN );
2264  if( xExtSheet )
2265  {
2266  rnExtName = xExtSheet->InsertAddIn( rName );
2267  return rnExtName > 0;
2268  }
2269  return false;
2270 }
2271 
2272 bool XclExpLinkManagerImpl5::InsertEuroTool(
2273  sal_uInt16& /*rnExtSheet*/, sal_uInt16& /*rnExtName*/, const OUString& /*rName*/ )
2274 {
2275  return false;
2276 }
2277 
2278 bool XclExpLinkManagerImpl5::InsertDde(
2279  sal_uInt16& /*rnExtSheet*/, sal_uInt16& /*rnExtName*/,
2280  const OUString& /*rApplic*/, const OUString& /*rTopic*/, const OUString& /*rItem*/ )
2281 {
2282  // not implemented
2283  return false;
2284 }
2285 
2286 bool XclExpLinkManagerImpl5::InsertExtName(
2287  sal_uInt16& /*rnExtSheet*/, sal_uInt16& /*rnExtName*/, const OUString& /*rUrl*/,
2288  const OUString& /*rName*/, const ScExternalRefCache::TokenArrayRef& /*rArray*/ )
2289 {
2290  // not implemented
2291  return false;
2292 }
2293 
2294 void XclExpLinkManagerImpl5::Save( XclExpStream& rStrm )
2295 {
2296  if( sal_uInt16 nExtSheetCount = GetExtSheetCount() )
2297  {
2298  // EXTERNCOUNT record
2299  XclExpUInt16Record( EXC_ID_EXTERNCOUNT, nExtSheetCount ).Save( rStrm );
2300  // list of EXTERNSHEET records with EXTERNNAME, XCT, CRN records
2301  maExtSheetList.Save( rStrm );
2302  }
2303 }
2304 
2305 void XclExpLinkManagerImpl5::SaveXml( XclExpXmlStream& /*rStrm*/ )
2306 {
2307  // not applicable
2308 }
2309 
2310 sal_uInt16 XclExpLinkManagerImpl5::GetExtSheetCount() const
2311 {
2312  return static_cast< sal_uInt16 >( maExtSheetList.GetSize() );
2313 }
2314 
2315 sal_uInt16 XclExpLinkManagerImpl5::AppendInternal( XclExpExtSheetRef const & xExtSheet )
2316 {
2317  if( GetExtSheetCount() < 0x7FFF )
2318  {
2319  maExtSheetList.AppendRecord( xExtSheet );
2320  // return negated one-based EXTERNSHEET index (i.e. 0xFFFD for 3rd record)
2321  return static_cast< sal_uInt16 >( -GetExtSheetCount() );
2322  }
2323  return 0;
2324 }
2325 
2326 void XclExpLinkManagerImpl5::CreateInternal()
2327 {
2328  if( !maIntTabMap.empty() )
2329  return;
2330 
2331  // create EXTERNSHEET records for all internal exported sheets
2332  XclExpTabInfo& rTabInfo = GetTabInfo();
2333  for( SCTAB nScTab = 0, nScCnt = rTabInfo.GetScTabCount(); nScTab < nScCnt; ++nScTab )
2334  {
2335  if( rTabInfo.IsExportTab( nScTab ) )
2336  {
2337  XclExpExtSheetRef xRec;
2338  if( nScTab == GetCurrScTab() )
2339  xRec = new XclExpExternSheet( GetRoot(), EXC_EXTSH_OWNTAB );
2340  else
2341  xRec = new XclExpExternSheet( GetRoot(), rTabInfo.GetScTabName( nScTab ) );
2342  maIntTabMap[ nScTab ] = AppendInternal( xRec );
2343  }
2344  }
2345 }
2346 
2347 XclExpLinkManagerImpl5::XclExpExtSheetRef XclExpLinkManagerImpl5::GetInternal( sal_uInt16 nExtSheet )
2348 {
2349  return maExtSheetList.GetRecord( static_cast< sal_uInt16 >( -nExtSheet - 1 ) );
2350 }
2351 
2352 XclExpLinkManagerImpl5::XclExpExtSheetRef XclExpLinkManagerImpl5::FindInternal(
2353  sal_uInt16& rnExtSheet, sal_uInt16& rnXclTab, SCTAB nScTab )
2354 {
2355  // create internal EXTERNSHEET records on demand
2356  CreateInternal();
2357 
2358  // try to find an EXTERNSHEET record - if not, return a "deleted sheet" reference
2359  XclExpExtSheetRef xExtSheet;
2360  XclExpIntTabMap::const_iterator aIt = maIntTabMap.find( nScTab );
2361  if( aIt == maIntTabMap.end() )
2362  {
2363  xExtSheet = FindInternal( rnExtSheet, EXC_EXTSH_OWNDOC );
2364  rnXclTab = EXC_TAB_DELETED;
2365  }
2366  else
2367  {
2368  rnExtSheet = aIt->second;
2369  xExtSheet = GetInternal( rnExtSheet );
2370  rnXclTab = GetTabInfo().GetXclTab( nScTab );
2371  }
2372  return xExtSheet;
2373 }
2374 
2375 XclExpLinkManagerImpl5::XclExpExtSheetRef XclExpLinkManagerImpl5::FindInternal(
2376  sal_uInt16& rnExtSheet, sal_Unicode cCode )
2377 {
2378  XclExpExtSheetRef xExtSheet;
2379  XclExpCodeMap::const_iterator aIt = maCodeMap.find( cCode );
2380  if( aIt == maCodeMap.end() )
2381  {
2382  xExtSheet = new XclExpExternSheet( GetRoot(), cCode );
2383  rnExtSheet = maCodeMap[ cCode ] = AppendInternal( xExtSheet );
2384  }
2385  else
2386  {
2387  rnExtSheet = aIt->second;
2388  xExtSheet = GetInternal( rnExtSheet );
2389  }
2390  return xExtSheet;
2391 }
2392 
2393 XclExpLinkManagerImpl8::XclExpLinkManagerImpl8( const XclExpRoot& rRoot ) :
2394  XclExpLinkManagerImpl( rRoot ),
2395  maSBBuffer( rRoot )
2396 {
2397 }
2398 
2399 void XclExpLinkManagerImpl8::FindExtSheet(
2400  sal_uInt16& rnExtSheet, sal_uInt16& rnFirstXclTab, sal_uInt16& rnLastXclTab,
2401  SCTAB nFirstScTab, SCTAB nLastScTab, XclExpRefLogEntry* pRefLogEntry )
2402 {
2403  XclExpTabInfo& rTabInfo = GetTabInfo();
2404  rnFirstXclTab = rTabInfo.GetXclTab( nFirstScTab );
2405  rnLastXclTab = rTabInfo.GetXclTab( nLastScTab );
2406  rnExtSheet = InsertXti( maSBBuffer.GetXti( rnFirstXclTab, rnLastXclTab, pRefLogEntry ) );
2407 }
2408 
2409 sal_uInt16 XclExpLinkManagerImpl8::FindExtSheet( sal_Unicode cCode )
2410 {
2411  OSL_ENSURE( (cCode == EXC_EXTSH_OWNDOC) || (cCode == EXC_EXTSH_ADDIN),
2412  "XclExpLinkManagerImpl8::FindExtSheet - unknown externsheet code" );
2413  return InsertXti( maSBBuffer.GetXti( EXC_TAB_EXTERNAL, EXC_TAB_EXTERNAL ) );
2414 }
2415 
2416 void XclExpLinkManagerImpl8::FindExtSheet(
2417  sal_uInt16 nFileId, const OUString& rTabName, sal_uInt16 nXclTabSpan,
2418  sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
2419  XclExpRefLogEntry* pRefLogEntry )
2420 {
2421  XclExpXti aXti = maSBBuffer.GetXti(nFileId, rTabName, nXclTabSpan, pRefLogEntry);
2422  rnExtSheet = InsertXti(aXti);
2423  rnFirstSBTab = aXti.mnFirstSBTab;
2424  rnLastSBTab = aXti.mnLastSBTab;
2425 }
2426 
2427 void XclExpLinkManagerImpl8::StoreCellRange( const ScSingleRefData& rRef1, const ScSingleRefData& rRef2, const ScAddress& rPos )
2428 {
2429  ScAddress aAbs1 = rRef1.toAbs(GetRoot().GetDoc(), rPos);
2430  ScAddress aAbs2 = rRef2.toAbs(GetRoot().GetDoc(), rPos);
2431  if (!(!rRef1.IsDeleted() && !rRef2.IsDeleted() && (aAbs1.Tab() >= 0) && (aAbs2.Tab() >= 0)))
2432  return;
2433 
2434  const XclExpTabInfo& rTabInfo = GetTabInfo();
2435  SCTAB nFirstScTab = aAbs1.Tab();
2436  SCTAB nLastScTab = aAbs2.Tab();
2437  ScRange aRange(aAbs1.Col(), aAbs1.Row(), 0, aAbs2.Col(), aAbs2.Row(), 0);
2438  for (SCTAB nScTab = nFirstScTab; nScTab <= nLastScTab; ++nScTab)
2439  {
2440  if( rTabInfo.IsExternalTab( nScTab ) )
2441  {
2442  aRange.aStart.SetTab( nScTab );
2443  aRange.aEnd.SetTab( nScTab );
2444  maSBBuffer.StoreCellRange( aRange );
2445  }
2446  }
2447 }
2448 
2449 void XclExpLinkManagerImpl8::StoreCell( sal_uInt16 nFileId, const OUString& rTabName, const ScAddress& rPos )
2450 {
2451  maSBBuffer.StoreCell(nFileId, rTabName, rPos);
2452 }
2453 
2454 void XclExpLinkManagerImpl8::StoreCellRange( sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange )
2455 {
2456  maSBBuffer.StoreCellRange(nFileId, rTabName, rRange);
2457 }
2458 
2459 bool XclExpLinkManagerImpl8::InsertAddIn(
2460  sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rName )
2461 {
2462  sal_uInt16 nSupbook;
2463  if( maSBBuffer.InsertAddIn( nSupbook, rnExtName, rName ) )
2464  {
2465  rnExtSheet = InsertXti( XclExpXti( nSupbook, EXC_TAB_EXTERNAL, EXC_TAB_EXTERNAL ) );
2466  return true;
2467  }
2468  return false;
2469 }
2470 
2471 bool XclExpLinkManagerImpl8::InsertEuroTool(
2472  sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rName )
2473 {
2474  sal_uInt16 nSupbook;
2475  if( maSBBuffer.InsertEuroTool( nSupbook, rnExtName, rName ) )
2476  {
2477  rnExtSheet = InsertXti( XclExpXti( nSupbook, EXC_TAB_EXTERNAL, EXC_TAB_EXTERNAL ) );
2478  return true;
2479  }
2480  return false;
2481 }
2482 
2483 bool XclExpLinkManagerImpl8::InsertDde(
2484  sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
2485  const OUString& rApplic, const OUString& rTopic, const OUString& rItem )
2486 {
2487  sal_uInt16 nSupbook;
2488  if( maSBBuffer.InsertDde( nSupbook, rnExtName, rApplic, rTopic, rItem ) )
2489  {
2490  rnExtSheet = InsertXti( XclExpXti( nSupbook, EXC_TAB_EXTERNAL, EXC_TAB_EXTERNAL ) );
2491  return true;
2492  }
2493  return false;
2494 }
2495 
2496 bool XclExpLinkManagerImpl8::InsertExtName( sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
2497  const OUString& rUrl, const OUString& rName, const ScExternalRefCache::TokenArrayRef& rArray )
2498 {
2499  sal_uInt16 nSupbook;
2500  if( maSBBuffer.InsertExtName( nSupbook, rnExtName, rUrl, rName, rArray ) )
2501  {
2502  rnExtSheet = InsertXti( XclExpXti( nSupbook, EXC_TAB_EXTERNAL, EXC_TAB_EXTERNAL ) );
2503  return true;
2504  }
2505  return false;
2506 }
2507 
2508 void XclExpLinkManagerImpl8::Save( XclExpStream& rStrm )
2509 {
2510  if( maXtiVec.empty() )
2511  return;
2512 
2513  // SUPBOOKs, XCTs, CRNs, EXTERNNAMEs
2514  maSBBuffer.Save( rStrm );
2515 
2516  // EXTERNSHEET
2517  sal_uInt16 nCount = ulimit_cast< sal_uInt16 >( maXtiVec.size() );
2518  rStrm.StartRecord( EXC_ID_EXTERNSHEET, 2 + 6 * nCount );
2519  rStrm << nCount;
2520  rStrm.SetSliceSize( 6 );
2521  for( const auto& rXti : maXtiVec )
2522  rXti.Save( rStrm );
2523  rStrm.EndRecord();
2524 }
2525 
2526 void XclExpLinkManagerImpl8::SaveXml( XclExpXmlStream& rStrm )
2527 {
2528  if (maSBBuffer.HasExternalReferences())
2529  {
2530  sax_fastparser::FSHelperPtr pWorkbook = rStrm.GetCurrentStream();
2531  pWorkbook->startElement(XML_externalReferences);
2532 
2533  // externalLink, externalBook, sheetNames, sheetDataSet, externalName
2534  maSBBuffer.SaveXml( rStrm );
2535 
2536  pWorkbook->endElement( XML_externalReferences);
2537  }
2538 
2539  // TODO: equivalent for EXTERNSHEET in OOXML?
2540 #if 0
2541  if( !maXtiVec.empty() )
2542  {
2543  for( const auto& rXti : maXtiVec )
2544  rXti.SaveXml( rStrm );
2545  }
2546 #endif
2547 }
2548 
2549 sal_uInt16 XclExpLinkManagerImpl8::InsertXti( const XclExpXti& rXti )
2550 {
2551  auto aIt = std::find(maXtiVec.begin(), maXtiVec.end(), rXti);
2552  if (aIt != maXtiVec.end())
2553  return ulimit_cast< sal_uInt16 >( std::distance(maXtiVec.begin(), aIt) );
2554  maXtiVec.push_back( rXti );
2555  return ulimit_cast< sal_uInt16 >( maXtiVec.size() - 1 );
2556 }
2557 
2559  XclExpRoot( rRoot )
2560 {
2561  switch( GetBiff() )
2562  {
2563  case EXC_BIFF5:
2564  mxImpl = std::make_shared<XclExpLinkManagerImpl5>( rRoot );
2565  break;
2566  case EXC_BIFF8:
2567  mxImpl = std::make_shared<XclExpLinkManagerImpl8>( rRoot );
2568  break;
2569  default:
2570  DBG_ERROR_BIFF();
2571  }
2572 }
2573 
2575 {
2576 }
2577 
2579  sal_uInt16& rnExtSheet, sal_uInt16& rnXclTab,
2580  SCTAB nScTab, XclExpRefLogEntry* pRefLogEntry )
2581 {
2582  mxImpl->FindExtSheet( rnExtSheet, rnXclTab, rnXclTab, nScTab, nScTab, pRefLogEntry );
2583 }
2584 
2586  sal_uInt16& rnExtSheet, sal_uInt16& rnFirstXclTab, sal_uInt16& rnLastXclTab,
2587  SCTAB nFirstScTab, SCTAB nLastScTab, XclExpRefLogEntry* pRefLogEntry )
2588 {
2589  mxImpl->FindExtSheet( rnExtSheet, rnFirstXclTab, rnLastXclTab, nFirstScTab, nLastScTab, pRefLogEntry );
2590 }
2591 
2593 {
2594  return mxImpl->FindExtSheet( cCode );
2595 }
2596 
2597 void XclExpLinkManager::FindExtSheet( sal_uInt16 nFileId, const OUString& rTabName, sal_uInt16 nXclTabSpan,
2598  sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
2599  XclExpRefLogEntry* pRefLogEntry )
2600 {
2601  mxImpl->FindExtSheet( nFileId, rTabName, nXclTabSpan, rnExtSheet, rnFirstSBTab, rnLastSBTab, pRefLogEntry );
2602 }
2603 
2605 {
2606  mxImpl->StoreCellRange(rRef, rRef, rPos);
2607 }
2608 
2610 {
2611  mxImpl->StoreCellRange(rRef.Ref1, rRef.Ref2, rPos);
2612 }
2613 
2614 void XclExpLinkManager::StoreCell( sal_uInt16 nFileId, const OUString& rTabName, const ScAddress& rPos )
2615 {
2616  mxImpl->StoreCell(nFileId, rTabName, rPos);
2617 }
2618 
2619 void XclExpLinkManager::StoreCellRange( sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange )
2620 {
2621  mxImpl->StoreCellRange(nFileId, rTabName, rRange);
2622 }
2623 
2625  sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rName )
2626 {
2627  return mxImpl->InsertAddIn( rnExtSheet, rnExtName, rName );
2628 }
2629 
2631  sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rName )
2632 {
2633  return mxImpl->InsertEuroTool( rnExtSheet, rnExtName, rName );
2634 }
2635 
2637  sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
2638  const OUString& rApplic, const OUString& rTopic, const OUString& rItem )
2639 {
2640  return mxImpl->InsertDde( rnExtSheet, rnExtName, rApplic, rTopic, rItem );
2641 }
2642 
2644  sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rUrl, const OUString& rName,
2645  const ScExternalRefCache::TokenArrayRef& rArray )
2646 {
2647  return mxImpl->InsertExtName(rnExtSheet, rnExtName, rUrl, rName, rArray);
2648 }
2649 
2651 {
2652  mxImpl->Save( rStrm );
2653 }
2654 
2656 {
2657  mxImpl->SaveXml( rStrm );
2658 }
2659 
2660 /* 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:709
sal_Int32 nIndex
OUString getString() const
void CalcXclIndexes()
Searches for sheets not to be exported.
Definition: xelink.cxx:842
ScAddress aStart
Definition: address.hxx:497
A list of Excel record objects.
Definition: xerecord.hxx:321
bool IsSelectedTab(SCTAB nScTab) const
Returns true, if the specified Calc sheet is selected and will be exported.
Definition: xelink.cxx: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:2630
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:274
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:29
static OUString ToOUString(const char *s)
Definition: xestream.cxx:785
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:498
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:2578
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:285
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:2655
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:315
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:918
SC_DLLPUBLIC ScExternalRefManager * GetExternalRefManager() const
Definition: documen3.cxx:627
svDouble
SCTAB Tab() const
Definition: address.hxx:283
sal_uInt16 mnFirstVisXclTab
Displayed (active) sheet.
Definition: xelink.hxx:134
Base class for all Excel records.
Definition: xerecord.hxx:38
bool IsColRel() const
Definition: refdata.hxx:65
const sal_uInt8 SC_DDE_IGNOREMODE
Definition: document.hxx:303
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
virtual OUString GetName() const override
sax_fastparser::FSHelperPtr & GetCurrentStream()
Definition: xestream.cxx:912
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:2604
void PopStream()
Definition: xestream.cxx:923
const sal_uInt8 EXC_ERR_REF
Definition: xlconst.hxx:107
void SetSliceSize(sal_uInt16 nSize)
Sets data slice length.
Definition: xestream.cxx:134
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:2624
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:295
T * get() const
virtual void Save(XclExpStream &rStrm) override
Writes the entire Link table.
Definition: xelink.cxx:2650
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:2636
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:428
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:941
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:125
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:75
XclExpLinkManager(const XclExpRoot &rRoot)
Definition: xelink.cxx:2558
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:279
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:247
static OUString GetStreamName(const char *sStreamDir, const char *sStream, sal_Int32 nId)
Definition: xestream.cxx:694
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:2643
void StoreCellRange(const ScComplexRefData &rRef, const ScAddress &rPos)
Stores all cells in the given range in a CRN record list.
Definition: xelink.cxx:2609
#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:1055
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:989
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:113
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:911
#define SAL_WARN(area, stream)
void(* f)(TrueTypeTable *)
virtual ~XclExpLinkManager() override
Definition: xelink.cxx:2574
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:877
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:2202
SC_DLLPUBLIC bool GetName(SCTAB nTab, OUString &rName) const
Definition: document.cxx:215
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:142
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:261
OUString sId