bump product version to 4.1.6.2
[LibreOffice.git] / sc / source / filter / excel / xelink.cxx
blob5b6e37ab8115f23b7cb64babc2e0b331b425eedc
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "xelink.hxx"
22 #include <algorithm>
23 #include <unotools/collatorwrapper.hxx>
24 #include <svl/zforlist.hxx>
25 #include "document.hxx"
26 #include "formulacell.hxx"
27 #include "scextopt.hxx"
28 #include "externalrefmgr.hxx"
29 #include "tokenarray.hxx"
31 #include <vector>
32 #include <memory>
34 using ::std::auto_ptr;
35 using ::std::find_if;
36 using ::std::vector;
37 using ::com::sun::star::uno::Any;
39 // ============================================================================
40 // *** Helper classes ***
41 // ============================================================================
43 // External names =============================================================
45 /** This is a base class for any external name (i.e. add-in names or DDE links).
46 @descr Derived classes implement creation and export of the external names. */
47 class XclExpExtNameBase : public XclExpRecord, protected XclExpRoot
49 public:
50 /** @param nFlags The flags to export. */
51 explicit XclExpExtNameBase( const XclExpRoot& rRoot,
52 const String& rName, sal_uInt16 nFlags = 0 );
53 virtual ~XclExpExtNameBase();
55 /** Returns the name string of the external name. */
56 inline const String& GetName() const { return maName; }
58 private:
59 /** Writes the start of the record that is equal in all EXTERNNAME records and calls WriteAddData(). */
60 virtual void WriteBody( XclExpStream& rStrm );
61 /** Called to write additional data following the common record contents.
62 @descr Derived classes should overwrite this function to write their data. */
63 virtual void WriteAddData( XclExpStream& rStrm );
65 private:
66 String maName; /// Calc name (title) of the external name.
67 XclExpStringRef mxName; /// Excel name (title) of the external name.
68 sal_uInt16 mnFlags; /// Flags for record export.
71 // ----------------------------------------------------------------------------
73 /** Represents an EXTERNNAME record for an add-in function name. */
74 class XclExpExtNameAddIn : public XclExpExtNameBase
76 public:
77 explicit XclExpExtNameAddIn( const XclExpRoot& rRoot, const String& rName );
79 private:
80 /** Writes additional record contents. */
81 virtual void WriteAddData( XclExpStream& rStrm );
84 // ----------------------------------------------------------------------------
86 /** Represents an EXTERNNAME record for a DDE link. */
87 class XclExpExtNameDde : public XclExpExtNameBase
89 public:
90 explicit XclExpExtNameDde( const XclExpRoot& rRoot, const String& rName,
91 sal_uInt16 nFlags, const ScMatrix* pResults = 0 );
93 private:
94 /** Writes additional record contents. */
95 virtual void WriteAddData( XclExpStream& rStrm );
97 private:
98 typedef boost::shared_ptr< XclExpCachedMatrix > XclExpCachedMatRef;
99 XclExpCachedMatRef mxMatrix; /// Cached results of the DDE link.
102 // ----------------------------------------------------------------------------
104 class XclExpSupbook;
106 class XclExpExtName : public XclExpExtNameBase
108 public:
109 explicit XclExpExtName( const XclExpRoot& rRoot, const XclExpSupbook& rSupbook, const String& rName,
110 const ScExternalRefCache::TokenArrayRef pArray );
112 private:
113 /** Writes additional record contents. */
114 virtual void WriteAddData( XclExpStream& rStrm );
116 private:
117 const XclExpSupbook& mrSupbook;
118 auto_ptr<ScTokenArray> mpArray;
121 // List of external names =====================================================
123 /** List of all external names of a sheet. */
124 class XclExpExtNameBuffer : public XclExpRecordBase, protected XclExpRoot
126 public:
127 explicit XclExpExtNameBuffer( const XclExpRoot& rRoot );
129 /** Inserts an add-in function name
130 @return The 1-based (Excel-like) list index of the name. */
131 sal_uInt16 InsertAddIn( const String& rName );
132 /** InsertEuroTool */
133 sal_uInt16 InsertEuroTool( const String& rName );
134 /** Inserts a DDE link.
135 @return The 1-based (Excel-like) list index of the DDE link. */
136 sal_uInt16 InsertDde( const String& rApplic, const String& rTopic, const String& rItem );
138 sal_uInt16 InsertExtName( const XclExpSupbook& rSupbook, const String& rName, const ScExternalRefCache::TokenArrayRef pArray );
140 /** Writes the EXTERNNAME record list. */
141 virtual void Save( XclExpStream& rStrm );
143 private:
144 typedef XclExpRecordList< XclExpExtNameBase > XclExpExtNameList;
145 typedef XclExpExtNameList::RecordRefType XclExpExtNameRef;
147 private:
148 /** Returns the 1-based (Excel-like) list index of the external name or 0, if not found. */
149 sal_uInt16 GetIndex( const String& rName ) const;
150 /** Appends the passed newly crested external name.
151 @return The 1-based (Excel-like) list index of the appended name. */
152 sal_uInt16 AppendNew( XclExpExtNameBase* pExtName );
154 private:
155 XclExpExtNameList maNameList; /// The list with all EXTERNNAME records.
158 // Cached external cells ======================================================
160 /** Stores the contents of a consecutive row of external cells (record CRN). */
161 class XclExpCrn : public XclExpRecord
163 public:
164 explicit XclExpCrn( SCCOL nScCol, SCROW nScRow, const Any& rValue );
166 /** Returns true, if the passed value could be appended to this record. */
167 bool InsertValue( SCCOL nScCol, SCROW nScRow, const Any& rValue );
169 private:
170 virtual void WriteBody( XclExpStream& rStrm );
172 void WriteBool( XclExpStream& rStrm, bool bValue );
173 void WriteDouble( XclExpStream& rStrm, double fValue );
174 void WriteString( XclExpStream& rStrm, const OUString& rValue );
175 void WriteError( XclExpStream& rStrm, sal_uInt8 nErrCode );
176 void WriteEmpty( XclExpStream& rStrm );
178 private:
179 typedef ::std::vector< Any > CachedValues;
181 CachedValues maValues; /// All cached values.
182 SCCOL mnScCol; /// Column index of the first external cell.
183 SCROW mnScRow; /// Row index of the external cells.
186 // ----------------------------------------------------------------------------
188 /** Represents the record XCT which is the header record of a CRN record list.
190 class XclExpXct : public XclExpRecordBase, protected XclExpRoot
192 public:
193 explicit XclExpXct( const XclExpRoot& rRoot,
194 const String& rTabName, sal_uInt16 nSBTab,
195 ScExternalRefCache::TableTypeRef xCacheTable );
197 /** Returns the external sheet name. */
198 inline const XclExpString& GetTabName() const { return maTabName; }
200 /** Stores all cells in the given range in the CRN list. */
201 void StoreCellRange( const ScRange& rRange );
203 void StoreCell( const ScAddress& rCell, const ::formula::FormulaToken& rToken );
204 void StoreCellRange( const ScRange& rRange, const ::formula::FormulaToken& rToken );
206 /** Writes the XCT and all CRN records. */
207 virtual void Save( XclExpStream& rStrm );
209 private:
210 ScExternalRefCache::TableTypeRef mxCacheTable;
211 ScMarkData maUsedCells; /// Contains addresses of all stored cells.
212 ScRange maBoundRange; /// Bounding box of maUsedCells.
213 XclExpString maTabName; /// Sheet name of the external sheet.
214 sal_uInt16 mnSBTab; /// Referred sheet index in SUPBOOK record.
217 // External documents (EXTERNSHEET/SUPBOOK), base class =======================
219 /** Base class for records representing external sheets/documents.
221 In BIFF5/BIFF7, this record is the EXTERNSHEET record containing one sheet
222 of the own or an external document. In BIFF8, this record is the SUPBOOK
223 record representing the entire own or external document with all referenced
224 sheets.
226 class XclExpExternSheetBase : public XclExpRecord, protected XclExpRoot
228 public:
229 explicit XclExpExternSheetBase( const XclExpRoot& rRoot,
230 sal_uInt16 nRecId, sal_uInt32 nRecSize = 0 );
232 protected:
233 /** Creates and returns the list of EXTERNNAME records. */
234 XclExpExtNameBuffer& GetExtNameBuffer();
235 /** Creates and returns the list of EXTERNNAME records. */
236 void WriteExtNameBuffer( XclExpStream& rStrm );
238 private:
239 typedef boost::shared_ptr< XclExpExtNameBuffer > XclExpExtNameBfrRef;
240 XclExpExtNameBfrRef mxExtNameBfr; /// List of EXTERNNAME records.
243 // External documents (EXTERNSHEET, BIFF5/BIFF7) ==============================
245 /** Represents an EXTERNSHEET record containing the URL and sheet name of a sheet.
246 @descr This class is used up to BIFF7 only, writing a BIFF8 EXTERNSHEET
247 record is implemented directly in the link manager. */
248 class XclExpExternSheet : public XclExpExternSheetBase
250 public:
251 /** Creates an EXTERNSHEET record containing a special code (i.e. own document or sheet). */
252 explicit XclExpExternSheet( const XclExpRoot& rRoot, sal_Unicode cCode );
253 /** Creates an EXTERNSHEET record referring to an internal sheet. */
254 explicit XclExpExternSheet( const XclExpRoot& rRoot, const String& rTabName );
256 /** Finds or inserts an EXTERNNAME record for add-ins.
257 @return The 1-based EXTERNNAME record index; or 0, if the record list is full. */
258 sal_uInt16 InsertAddIn( const String& rName );
260 /** Writes the EXTERNSHEET and all EXTERNNAME, XCT and CRN records. */
261 virtual void Save( XclExpStream& rStrm );
263 private:
264 /** Initializes the record data with the passed encoded URL. */
265 void Init( const String& rEncUrl );
266 /** Writes the contents of the EXTERNSHEET record. */
267 virtual void WriteBody( XclExpStream& rStrm );
269 private:
270 XclExpString maTabName; /// The name of the sheet.
273 // External documents (SUPBOOK, BIFF8) ========================================
275 /** The SUPBOOK record contains data for an external document (URL, sheet names, external values). */
276 class XclExpSupbook : public XclExpExternSheetBase
278 public:
279 /** Creates a SUPBOOK record for internal references. */
280 explicit XclExpSupbook( const XclExpRoot& rRoot, sal_uInt16 nXclTabCount );
281 /** Creates a SUPBOOK record for add-in functions. */
282 explicit XclExpSupbook( const XclExpRoot& rRoot );
283 /** EUROTOOL SUPBOOK */
284 explicit XclExpSupbook( const XclExpRoot& rRoot, const String& rUrl, XclSupbookType );
285 /** Creates a SUPBOOK record for an external document. */
286 explicit XclExpSupbook( const XclExpRoot& rRoot, const String& rUrl );
287 /** Creates a SUPBOOK record for a DDE link. */
288 explicit XclExpSupbook( const XclExpRoot& rRoot, const String& rApplic, const String& rTopic );
290 /** Returns true, if this SUPBOOK contains the passed URL of an external document. */
291 bool IsUrlLink( const String& rUrl ) const;
292 /** Returns true, if this SUPBOOK contains the passed DDE link. */
293 bool IsDdeLink( const String& rApplic, const String& rTopic ) const;
294 /** Fills the passed reference log entry with the URL and sheet names. */
295 void FillRefLogEntry( XclExpRefLogEntry& rRefLogEntry,
296 sal_uInt16 nFirstSBTab, sal_uInt16 nLastSBTab ) const;
298 /** Stores all cells in the given range in the CRN list of the specified SUPBOOK sheet. */
299 void StoreCellRange( const ScRange& rRange, sal_uInt16 nSBTab );
301 void StoreCell( sal_uInt16 nSBTab, const ScAddress& rCell, const ::formula::FormulaToken& rToken );
302 void StoreCellRange( sal_uInt16 nSBTab, const ScRange& rRange, const ::formula::FormulaToken& rToken );
304 sal_uInt16 GetTabIndex( const String& rTabName ) const;
305 sal_uInt16 GetTabCount() const;
307 /** Inserts a new sheet name into the SUPBOOK and returns the SUPBOOK internal sheet index. */
308 sal_uInt16 InsertTabName( const String& rTabName, ScExternalRefCache::TableTypeRef xCacheTable );
309 /** Finds or inserts an EXTERNNAME record for add-ins.
310 @return The 1-based EXTERNNAME record index; or 0, if the record list is full. */
311 sal_uInt16 InsertAddIn( const String& rName );
312 /** InsertEuroTool */
313 sal_uInt16 InsertEuroTool( const String& rName );
314 /** Finds or inserts an EXTERNNAME record for DDE links.
315 @return The 1-based EXTERNNAME record index; or 0, if the record list is full. */
316 sal_uInt16 InsertDde( const String& rItem );
318 sal_uInt16 InsertExtName( const String& rName, const ScExternalRefCache::TokenArrayRef pArray );
320 /** Writes the SUPBOOK and all EXTERNNAME, XCT and CRN records. */
321 virtual void Save( XclExpStream& rStrm );
323 private:
324 /** Returns the sheet name inside of this SUPBOOK. */
325 const XclExpString* GetTabName( sal_uInt16 nSBTab ) const;
327 /** Writes the SUPBOOK record contents. */
328 virtual void WriteBody( XclExpStream& rStrm );
330 private:
331 typedef XclExpRecordList< XclExpXct > XclExpXctList;
332 typedef XclExpXctList::RecordRefType XclExpXctRef;
334 XclExpXctList maXctList; /// List of XCT records (which contain CRN records).
335 String maUrl; /// URL of the external document or application name for DDE.
336 String maDdeTopic; /// Topic of an DDE link.
337 XclExpString maUrlEncoded; /// Document name encoded for Excel.
338 XclSupbookType meType; /// Type of this SUPBOOK record.
339 sal_uInt16 mnXclTabCount; /// Number of internal sheets.
342 // All SUPBOOKS in a document =================================================
344 /** This struct contains a sheet index range for 3D references.
345 @descr This reference consists of an index to a SUPBOOK record and indexes
346 to SUPBOOK sheet names. */
347 struct XclExpXti
349 sal_uInt16 mnSupbook; /// Index to SUPBOOK record.
350 sal_uInt16 mnFirstSBTab; /// Index to the first sheet of the range in the SUPBOOK.
351 sal_uInt16 mnLastSBTab; /// Index to the last sheet of the range in the SUPBOOK.
353 inline explicit XclExpXti() : mnSupbook( 0 ), mnFirstSBTab( 0 ), mnLastSBTab( 0 ) {}
354 inline explicit XclExpXti( sal_uInt16 nSupbook, sal_uInt16 nFirstSBTab, sal_uInt16 nLastSBTab ) :
355 mnSupbook( nSupbook ), mnFirstSBTab( nFirstSBTab ), mnLastSBTab( nLastSBTab ) {}
357 /** Writes this XTI structure (inside of the EXTERNSHEET record). */
358 inline void Save( XclExpStream& rStrm ) const
359 { rStrm << mnSupbook << mnFirstSBTab << mnLastSBTab; }
362 inline bool operator==( const XclExpXti& rLeft, const XclExpXti& rRight )
364 return
365 (rLeft.mnSupbook == rRight.mnSupbook) &&
366 (rLeft.mnFirstSBTab == rRight.mnFirstSBTab) &&
367 (rLeft.mnLastSBTab == rRight.mnLastSBTab);
370 // ----------------------------------------------------------------------------
372 /** Contains a list of all SUPBOOK records and index arrays of external sheets. */
373 class XclExpSupbookBuffer : public XclExpRecordBase, protected XclExpRoot
375 public:
376 explicit XclExpSupbookBuffer( const XclExpRoot& rRoot );
378 /** Finds SUPBOOK index and SUPBOOK sheet range from given Excel sheet range.
379 @return An XTI structure containing SUPBOOK and sheet indexes. */
380 XclExpXti GetXti( sal_uInt16 nFirstXclTab, sal_uInt16 nLastXclTab,
381 XclExpRefLogEntry* pRefLogEntry = 0 ) const;
383 /** Stores all cells in the given range in a CRN record list. */
384 void StoreCellRange( const ScRange& rRange );
386 void StoreCell( sal_uInt16 nFileId, const String& rTabName, const ScAddress& rCell );
387 void StoreCellRange( sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange );
389 /** Finds or inserts an EXTERNNAME record for an add-in function name.
390 @param rnSupbook Returns the index of the SUPBOOK record which contains the add-in function name.
391 @param rnExtName Returns the 1-based EXTERNNAME record index. */
392 bool InsertAddIn(
393 sal_uInt16& rnSupbook, sal_uInt16& rnExtName,
394 const String& rName );
395 /** InsertEuroTool */
396 bool InsertEuroTool(
397 sal_uInt16& rnSupbook, sal_uInt16& rnExtName,
398 const String& rName );
399 /** Finds or inserts an EXTERNNAME record for DDE links.
400 @param rnSupbook Returns the index of the SUPBOOK record which contains the DDE link.
401 @param rnExtName Returns the 1-based EXTERNNAME record index. */
402 bool InsertDde(
403 sal_uInt16& rnSupbook, sal_uInt16& rnExtName,
404 const String& rApplic, const String& rTopic, const String& rItem );
406 bool InsertExtName(
407 sal_uInt16& rnSupbook, sal_uInt16& rnExtName, const String& rUrl,
408 const String& rName, const ScExternalRefCache::TokenArrayRef pArray );
410 XclExpXti GetXti( sal_uInt16 nFileId, const String& rTabName, sal_uInt16 nXclTabSpan,
411 XclExpRefLogEntry* pRefLogEntry = NULL );
413 /** Writes all SUPBOOK records with their sub records. */
414 virtual void Save( XclExpStream& rStrm );
416 struct XclExpSBIndex
418 sal_uInt16 mnSupbook; /// SUPBOOK index for an Excel sheet.
419 sal_uInt16 mnSBTab; /// Sheet name index in SUPBOOK for an Excel sheet.
420 inline void Set( sal_uInt16 nSupbook, sal_uInt16 nSBTab )
421 { mnSupbook = nSupbook; mnSBTab = nSBTab; }
423 typedef ::std::vector< XclExpSBIndex > XclExpSBIndexVec;
425 private:
426 typedef XclExpRecordList< XclExpSupbook > XclExpSupbookList;
427 typedef XclExpSupbookList::RecordRefType XclExpSupbookRef;
429 private:
430 /** Searches for the SUPBOOK record containing the passed document URL.
431 @param rxSupbook (out-param) Returns a reference to the SUPBOOK record, or 0.
432 @param rnIndex (out-param) Returns the list index, if the SUPBOOK exists.
433 @return True, if the SUPBOOK record exists (out-parameters are valid). */
434 bool GetSupbookUrl( XclExpSupbookRef& rxSupbook, sal_uInt16& rnIndex,
435 const String& rUrl ) const;
436 /** Searches for the SUPBOOK record containing the passed DDE link.
437 @param rxSupbook (out-param) Returns a reference to the SUPBOOK record, or 0.
438 @param rnIndex (out-param) Returns the list index, if the SUPBOOK exists.
439 @return True, if the SUPBOOK record exists (out-parameters are valid). */
440 bool GetSupbookDde( XclExpSupbookRef& rxSupbook, sal_uInt16& rnIndex,
441 const String& rApplic, const String& rTopic ) const;
443 /** Appends a new SUPBOOK to the list.
444 @return The list index of the SUPBOOK record. */
445 sal_uInt16 Append( XclExpSupbookRef xSupbook );
447 private:
448 XclExpSupbookList maSupbookList; /// List of all SUPBOOK records.
449 XclExpSBIndexVec maSBIndexVec; /// SUPBOOK and sheet name index for each Excel sheet.
450 sal_uInt16 mnOwnDocSB; /// Index to SUPBOOK for own document.
451 sal_uInt16 mnAddInSB; /// Index to add-in SUPBOOK.
454 // Export link manager ========================================================
456 /** Abstract base class for implementation classes of the link manager. */
457 class XclExpLinkManagerImpl : protected XclExpRoot
459 public:
460 /** Derived classes search for an EXTSHEET structure for the given Calc sheet range. */
461 virtual void FindExtSheet( sal_uInt16& rnExtSheet,
462 sal_uInt16& rnFirstXclTab, sal_uInt16& rnLastXclTab,
463 SCTAB nFirstScTab, SCTAB nLastScTab,
464 XclExpRefLogEntry* pRefLogEntry ) = 0;
465 /** Derived classes search for a special EXTERNSHEET index for the own document. */
466 virtual sal_uInt16 FindExtSheet( sal_Unicode cCode ) = 0;
468 virtual void FindExtSheet( sal_uInt16 nFileId, const String& rTabName, sal_uInt16 nXclTabSpan,
469 sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
470 XclExpRefLogEntry* pRefLogEntry ) = 0;
472 /** Derived classes store all cells in the given range in a CRN record list. */
473 virtual void StoreCellRange( const ScSingleRefData& rRef1, const ScSingleRefData& rRef2 ) = 0;
475 virtual void StoreCell( sal_uInt16 nFileId, const String& rTabName, const ScSingleRefData& rRef ) = 0;
476 virtual void StoreCellRange( sal_uInt16 nFileId, const String& rTabName, const ScSingleRefData& rRef1, const ScSingleRefData& rRef2 ) = 0;
478 /** Derived classes find or insert an EXTERNNAME record for an add-in function name. */
479 virtual bool InsertAddIn(
480 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
481 const String& rName ) = 0;
482 /** InsertEuroTool */
483 virtual bool InsertEuroTool(
484 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
485 const String& rName ) = 0;
487 /** Derived classes find or insert an EXTERNNAME record for DDE links. */
488 virtual bool InsertDde(
489 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
490 const String& rApplic, const String& rTopic, const String& rItem ) = 0;
492 virtual bool InsertExtName(
493 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const String& rUrl,
494 const String& rName, const ScExternalRefCache::TokenArrayRef pArray ) = 0;
496 /** Derived classes write the entire link table to the passed stream. */
497 virtual void Save( XclExpStream& rStrm ) = 0;
499 protected:
500 explicit XclExpLinkManagerImpl( const XclExpRoot& rRoot );
503 // ----------------------------------------------------------------------------
505 /** Implementation of the link manager for BIFF5/BIFF7. */
506 class XclExpLinkManagerImpl5 : public XclExpLinkManagerImpl
508 public:
509 explicit XclExpLinkManagerImpl5( const XclExpRoot& rRoot );
511 virtual void FindExtSheet( sal_uInt16& rnExtSheet,
512 sal_uInt16& rnFirstXclTab, sal_uInt16& rnLastXclTab,
513 SCTAB nFirstScTab, SCTAB nLastScTab,
514 XclExpRefLogEntry* pRefLogEntry );
515 virtual sal_uInt16 FindExtSheet( sal_Unicode cCode );
517 virtual void FindExtSheet( sal_uInt16 nFileId, const String& rTabName, sal_uInt16 nXclTabSpan,
518 sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
519 XclExpRefLogEntry* pRefLogEntry );
521 virtual void StoreCellRange( const ScSingleRefData& rRef1, const ScSingleRefData& rRef2 );
523 virtual void StoreCell( sal_uInt16 nFileId, const String& rTabName, const ScSingleRefData& rRef );
524 virtual void StoreCellRange( sal_uInt16 nFileId, const String& rTabName, const ScSingleRefData& rRef1, const ScSingleRefData& rRef2 );
526 virtual bool InsertAddIn(
527 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
528 const String& rName );
530 /** InsertEuroTool */
531 virtual bool InsertEuroTool(
532 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
533 const String& rName );
535 virtual bool InsertDde(
536 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
537 const String& rApplic, const String& rTopic, const String& rItem );
539 virtual bool InsertExtName(
540 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const String& rUrl,
541 const String& rName, const ScExternalRefCache::TokenArrayRef pArray );
543 virtual void Save( XclExpStream& rStrm );
545 private:
546 typedef XclExpRecordList< XclExpExternSheet > XclExpExtSheetList;
547 typedef XclExpExtSheetList::RecordRefType XclExpExtSheetRef;
548 typedef ::std::map< SCTAB, sal_uInt16 > XclExpIntTabMap;
549 typedef ::std::map< sal_Unicode, sal_uInt16 > XclExpCodeMap;
551 private:
552 /** Returns the number of EXTERNSHEET records. */
553 sal_uInt16 GetExtSheetCount() const;
555 /** Appends an internal EXTERNSHEET record and returns the one-based index. */
556 sal_uInt16 AppendInternal( XclExpExtSheetRef xExtSheet );
557 /** Creates all EXTERNSHEET records for internal sheets on first call. */
558 void CreateInternal();
560 /** Returns the specified internal EXTERNSHEET record. */
561 XclExpExtSheetRef GetInternal( sal_uInt16 nExtSheet );
562 /** Returns the EXTERNSHEET index of an internal Calc sheet, or a deleted reference. */
563 XclExpExtSheetRef FindInternal( sal_uInt16& rnExtSheet, sal_uInt16& rnXclTab, SCTAB nScTab );
564 /** Finds or creates the EXTERNSHEET index of an internal special EXTERNSHEET. */
565 XclExpExtSheetRef FindInternal( sal_uInt16& rnExtSheet, sal_Unicode cCode );
567 private:
568 XclExpExtSheetList maExtSheetList; /// List with EXTERNSHEET records.
569 XclExpIntTabMap maIntTabMap; /// Maps internal Calc sheets to EXTERNSHEET records.
570 XclExpCodeMap maCodeMap; /// Maps special external codes to EXTERNSHEET records.
573 // ----------------------------------------------------------------------------
575 /** Implementation of the link manager for BIFF8. */
576 class XclExpLinkManagerImpl8 : public XclExpLinkManagerImpl
578 public:
579 explicit XclExpLinkManagerImpl8( const XclExpRoot& rRoot );
581 virtual void FindExtSheet( sal_uInt16& rnExtSheet,
582 sal_uInt16& rnFirstXclTab, sal_uInt16& rnLastXclTab,
583 SCTAB nFirstScTab, SCTAB nLastScTab,
584 XclExpRefLogEntry* pRefLogEntry );
585 virtual sal_uInt16 FindExtSheet( sal_Unicode cCode );
587 virtual void FindExtSheet( sal_uInt16 nFileId, const String& rTabName, sal_uInt16 nXclTabSpan,
588 sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
589 XclExpRefLogEntry* pRefLogEntry );
591 virtual void StoreCellRange( const ScSingleRefData& rRef1, const ScSingleRefData& rRef2 );
593 virtual void StoreCell( sal_uInt16 nFileId, const String& rTabName, const ScSingleRefData& rRef );
594 virtual void StoreCellRange( sal_uInt16 nFileId, const String& rTabName, const ScSingleRefData& rRef1, const ScSingleRefData& rRef2 );
596 virtual bool InsertAddIn(
597 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
598 const String& rName );
599 /** InsertEuroTool */
600 virtual bool InsertEuroTool(
601 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
602 const String& rName );
604 virtual bool InsertDde(
605 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
606 const String& rApplic, const String& rTopic, const String& rItem );
608 virtual bool InsertExtName(
609 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const String& rUrl,
610 const String& rName, const ScExternalRefCache::TokenArrayRef pArray );
612 virtual void Save( XclExpStream& rStrm );
614 private:
615 /** Searches for or inserts a new XTI structure.
616 @return The 0-based list index of the XTI structure. */
617 sal_uInt16 InsertXti( const XclExpXti& rXti );
619 private:
620 typedef ::std::vector< XclExpXti > XclExpXtiVec;
622 XclExpSupbookBuffer maSBBuffer; /// List of all SUPBOOK records.
623 XclExpXtiVec maXtiVec; /// List of XTI structures for the EXTERNSHEET record.
626 // ============================================================================
627 // *** Implementation ***
628 // ============================================================================
630 // Excel sheet indexes ========================================================
632 const sal_uInt8 EXC_TABBUF_IGNORE = 0x01; /// Sheet will be ignored completely.
633 const sal_uInt8 EXC_TABBUF_EXTERN = 0x02; /// Sheet is linked externally.
634 const sal_uInt8 EXC_TABBUF_SKIPMASK = 0x0F; /// Sheet will be skipped, if any flag is set.
635 const sal_uInt8 EXC_TABBUF_VISIBLE = 0x10; /// Sheet is visible.
636 const sal_uInt8 EXC_TABBUF_SELECTED = 0x20; /// Sheet is selected.
637 const sal_uInt8 EXC_TABBUF_MIRRORED = 0x40; /// Sheet is mirrored (right-to-left).
639 // ----------------------------------------------------------------------------
641 XclExpTabInfo::XclExpTabInfo( const XclExpRoot& rRoot ) :
642 XclExpRoot( rRoot ),
643 mnScCnt( 0 ),
644 mnXclCnt( 0 ),
645 mnXclExtCnt( 0 ),
646 mnXclSelCnt( 0 ),
647 mnDisplXclTab( 0 ),
648 mnFirstVisXclTab( 0 )
650 ScDocument& rDoc = GetDoc();
651 ScExtDocOptions& rDocOpt = GetExtDocOptions();
653 mnScCnt = rDoc.GetTableCount();
655 SCTAB nScTab;
656 SCTAB nFirstVisScTab = SCTAB_INVALID; // first visible sheet
657 SCTAB nFirstExpScTab = SCTAB_INVALID; // first exported sheet
659 // --- initialize the flags in the index buffer ---
661 maTabInfoVec.resize( mnScCnt );
662 for( nScTab = 0; nScTab < mnScCnt; ++nScTab )
664 // ignored sheets (skipped by export, with invalid Excel sheet index)
665 if( rDoc.IsScenario( nScTab ) )
667 SetFlag( nScTab, EXC_TABBUF_IGNORE );
670 // external sheets (skipped, but with valid Excel sheet index for ref's)
671 else if( rDoc.GetLinkMode( nScTab ) == SC_LINK_VALUE )
673 SetFlag( nScTab, EXC_TABBUF_EXTERN );
676 // exported sheets
677 else
679 // sheet name
680 rDoc.GetName( nScTab, maTabInfoVec[ nScTab ].maScName );
682 // remember first exported sheet
683 if( nFirstExpScTab == SCTAB_INVALID )
684 nFirstExpScTab = nScTab;
685 // remember first visible exported sheet
686 if( (nFirstVisScTab == SCTAB_INVALID) && rDoc.IsVisible( nScTab ) )
687 nFirstVisScTab = nScTab;
689 // sheet visible (only exported sheets)
690 SetFlag( nScTab, EXC_TABBUF_VISIBLE, rDoc.IsVisible( nScTab ) );
692 // sheet selected (only exported sheets)
693 if( const ScExtTabSettings* pTabSett = rDocOpt.GetTabSettings( nScTab ) )
694 SetFlag( nScTab, EXC_TABBUF_SELECTED, pTabSett->mbSelected );
696 // sheet mirrored (only exported sheets)
697 SetFlag( nScTab, EXC_TABBUF_MIRRORED, rDoc.IsLayoutRTL( nScTab ) );
701 // --- visible/selected sheets ---
703 SCTAB nDisplScTab = rDocOpt.GetDocSettings().mnDisplTab;
705 // find first visible exported sheet
706 if( (nFirstVisScTab == SCTAB_INVALID) || !IsExportTab( nFirstVisScTab ) )
708 // no exportable visible sheet -> use first exportable sheet
709 nFirstVisScTab = nFirstExpScTab;
710 if( (nFirstVisScTab == SCTAB_INVALID) || !IsExportTab( nFirstVisScTab ) )
712 // no exportable sheet at all -> use active sheet and export it
713 nFirstVisScTab = nDisplScTab;
714 SetFlag( nFirstVisScTab, EXC_TABBUF_SKIPMASK, false ); // clear skip flags
716 SetFlag( nFirstVisScTab, EXC_TABBUF_VISIBLE ); // must be visible, even if originally hidden
719 // find currently displayed sheet
720 if( !IsExportTab( nDisplScTab ) ) // selected sheet not exported (i.e. scenario) -> use first visible
721 nDisplScTab = nFirstVisScTab;
722 SetFlag( nDisplScTab, EXC_TABBUF_VISIBLE | EXC_TABBUF_SELECTED );
724 // number of selected sheets
725 for( nScTab = 0; nScTab < mnScCnt; ++nScTab )
726 if( IsSelectedTab( nScTab ) )
727 ++mnXclSelCnt;
729 // --- calculate resulting Excel sheet indexes ---
731 CalcXclIndexes();
732 mnFirstVisXclTab = GetXclTab( nFirstVisScTab );
733 mnDisplXclTab = GetXclTab( nDisplScTab );
735 // --- sorted vectors for index lookup ---
737 CalcSortedIndexes();
740 bool XclExpTabInfo::IsExportTab( SCTAB nScTab ) const
742 /* Check sheet index before to avoid assertion in GetFlag(). */
743 return (nScTab < mnScCnt) && !GetFlag( nScTab, EXC_TABBUF_SKIPMASK );
746 bool XclExpTabInfo::IsExternalTab( SCTAB nScTab ) const
748 /* Check sheet index before to avoid assertion (called from formula
749 compiler also for deleted references). */
750 return (nScTab < mnScCnt) && GetFlag( nScTab, EXC_TABBUF_EXTERN );
753 bool XclExpTabInfo::IsVisibleTab( SCTAB nScTab ) const
755 return GetFlag( nScTab, EXC_TABBUF_VISIBLE );
758 bool XclExpTabInfo::IsSelectedTab( SCTAB nScTab ) const
760 return GetFlag( nScTab, EXC_TABBUF_SELECTED );
763 bool XclExpTabInfo::IsDisplayedTab( SCTAB nScTab ) const
765 OSL_ENSURE( nScTab < mnScCnt, "XclExpTabInfo::IsActiveTab - sheet out of range" );
766 return GetXclTab( nScTab ) == mnDisplXclTab;
769 bool XclExpTabInfo::IsMirroredTab( SCTAB nScTab ) const
771 return GetFlag( nScTab, EXC_TABBUF_MIRRORED );
774 OUString XclExpTabInfo::GetScTabName( SCTAB nScTab ) const
776 OSL_ENSURE( nScTab < mnScCnt, "XclExpTabInfo::IsActiveTab - sheet out of range" );
777 return (nScTab < mnScCnt) ? maTabInfoVec[ nScTab ].maScName : OUString();
780 sal_uInt16 XclExpTabInfo::GetXclTab( SCTAB nScTab ) const
782 return (nScTab < mnScCnt) ? maTabInfoVec[ nScTab ].mnXclTab : EXC_TAB_DELETED;
785 SCTAB XclExpTabInfo::GetRealScTab( SCTAB nSortedScTab ) const
787 OSL_ENSURE( nSortedScTab < mnScCnt, "XclExpTabInfo::GetRealScTab - sheet out of range" );
788 return (nSortedScTab < mnScCnt) ? maFromSortedVec[ nSortedScTab ] : SCTAB_INVALID;
791 bool XclExpTabInfo::GetFlag( SCTAB nScTab, sal_uInt8 nFlags ) const
793 OSL_ENSURE( nScTab < mnScCnt, "XclExpTabInfo::GetFlag - sheet out of range" );
794 return (nScTab < mnScCnt) && ::get_flag( maTabInfoVec[ nScTab ].mnFlags, nFlags );
797 void XclExpTabInfo::SetFlag( SCTAB nScTab, sal_uInt8 nFlags, bool bSet )
799 OSL_ENSURE( nScTab < mnScCnt, "XclExpTabInfo::SetFlag - sheet out of range" );
800 if( nScTab < mnScCnt )
801 ::set_flag( maTabInfoVec[ nScTab ].mnFlags, nFlags, bSet );
804 void XclExpTabInfo::CalcXclIndexes()
806 sal_uInt16 nXclTab = 0;
807 SCTAB nScTab = 0;
809 // --- pass 1: process regular sheets ---
810 for( nScTab = 0; nScTab < mnScCnt; ++nScTab )
812 if( IsExportTab( nScTab ) )
814 maTabInfoVec[ nScTab ].mnXclTab = nXclTab;
815 ++nXclTab;
817 else
818 maTabInfoVec[ nScTab ].mnXclTab = EXC_TAB_DELETED;
820 mnXclCnt = nXclTab;
822 // --- pass 2: process external sheets (nXclTab continues) ---
823 for( nScTab = 0; nScTab < mnScCnt; ++nScTab )
825 if( IsExternalTab( nScTab ) )
827 maTabInfoVec[ nScTab ].mnXclTab = nXclTab;
828 ++nXclTab;
829 ++mnXclExtCnt;
833 // result: first occur all exported sheets, followed by all external sheets
836 typedef ::std::pair< OUString, SCTAB > XclExpTabName;
837 typedef ::std::vector< XclExpTabName > XclExpTabNameVec;
839 inline bool operator<( const XclExpTabName& rArg1, const XclExpTabName& rArg2 )
841 // compare the sheet names only
842 return ScGlobal::GetCollator()->compareString( rArg1.first, rArg2.first ) == COMPARE_LESS;
845 void XclExpTabInfo::CalcSortedIndexes()
847 ScDocument& rDoc = GetDoc();
848 XclExpTabNameVec aVec( mnScCnt );
849 SCTAB nScTab;
851 // fill with sheet names
852 for( nScTab = 0; nScTab < mnScCnt; ++nScTab )
854 rDoc.GetName( nScTab, aVec[ nScTab ].first );
855 aVec[ nScTab ].second = nScTab;
857 ::std::sort( aVec.begin(), aVec.end() );
859 // fill index vectors from sorted sheet name vector
860 maFromSortedVec.resize( mnScCnt );
861 maToSortedVec.resize( mnScCnt );
862 for( nScTab = 0; nScTab < mnScCnt; ++nScTab )
864 maFromSortedVec[ nScTab ] = aVec[ nScTab ].second;
865 maToSortedVec[ aVec[ nScTab ].second ] = nScTab;
869 // External names =============================================================
871 XclExpExtNameBase::XclExpExtNameBase(
872 const XclExpRoot& rRoot, const String& rName, sal_uInt16 nFlags ) :
873 XclExpRecord( EXC_ID_EXTERNNAME ),
874 XclExpRoot( rRoot ),
875 maName( rName ),
876 mxName( XclExpStringHelper::CreateString( rRoot, rName, EXC_STR_8BITLENGTH ) ),
877 mnFlags( nFlags )
879 OSL_ENSURE( maName.Len() <= 255, "XclExpExtNameBase::XclExpExtNameBase - string too long" );
880 SetRecSize( 6 + mxName->GetSize() );
883 XclExpExtNameBase::~XclExpExtNameBase()
887 void XclExpExtNameBase::WriteBody( XclExpStream& rStrm )
889 rStrm << mnFlags
890 << sal_uInt32( 0 )
891 << *mxName;
892 WriteAddData( rStrm );
895 void XclExpExtNameBase::WriteAddData( XclExpStream& /*rStrm*/ )
899 // ----------------------------------------------------------------------------
901 XclExpExtNameAddIn::XclExpExtNameAddIn( const XclExpRoot& rRoot, const String& rName ) :
902 XclExpExtNameBase( rRoot, rName )
904 AddRecSize( 4 );
907 void XclExpExtNameAddIn::WriteAddData( XclExpStream& rStrm )
909 // write a #REF! error formula
910 rStrm << sal_uInt16( 2 ) << EXC_TOKID_ERR << EXC_ERR_REF;
913 // ----------------------------------------------------------------------------
915 XclExpExtNameDde::XclExpExtNameDde( const XclExpRoot& rRoot,
916 const String& rName, sal_uInt16 nFlags, const ScMatrix* pResults ) :
917 XclExpExtNameBase( rRoot, rName, nFlags )
919 if( pResults )
921 mxMatrix.reset( new XclExpCachedMatrix( *pResults ) );
922 AddRecSize( mxMatrix->GetSize() );
926 void XclExpExtNameDde::WriteAddData( XclExpStream& rStrm )
928 if( mxMatrix )
929 mxMatrix->Save( rStrm );
932 // ----------------------------------------------------------------------------
934 XclExpExtName::XclExpExtName( const XclExpRoot& rRoot, const XclExpSupbook& rSupbook,
935 const String& rName, const ScExternalRefCache::TokenArrayRef pArray ) :
936 XclExpExtNameBase( rRoot, rName ),
937 mrSupbook(rSupbook),
938 mpArray(pArray->Clone())
942 void XclExpExtName::WriteAddData( XclExpStream& rStrm )
944 // Write only if it only has a single token that is either a cell or cell
945 // range address. Excel just writes '02 00 1C 17' for all the other types
946 // of external names.
948 using namespace ::formula;
951 if (mpArray->GetLen() != 1)
952 break;
954 const ScToken* p = static_cast<const ScToken*>(mpArray->First());
955 if (!p->IsExternalRef())
956 break;
958 switch (p->GetType())
960 case svExternalSingleRef:
962 const ScSingleRefData& rRef = p->GetSingleRef();
963 if (rRef.IsTabRel())
964 break;
966 bool bColRel = rRef.IsColRel();
967 bool bRowRel = rRef.IsRowRel();
968 sal_uInt16 nCol = static_cast< sal_uInt16 >( bColRel ? rRef.nRelCol : rRef.nCol );
969 sal_uInt16 nRow = static_cast< sal_uInt16 >( bRowRel ? rRef.nRelRow : rRef.nRow );
970 if (bColRel) nCol |= 0x4000;
971 if (bRowRel) nCol |= 0x8000;
973 const String& rTabName = p->GetString();
974 sal_uInt16 nSBTab = mrSupbook.GetTabIndex(rTabName);
976 // size is always 9
977 rStrm << static_cast<sal_uInt16>(9);
978 // operator token (3A for cell reference)
979 rStrm << static_cast<sal_uInt8>(0x3A);
980 // cell address (Excel's address has 2 sheet IDs.)
981 rStrm << nSBTab << nSBTab << nRow << nCol;
982 return;
984 case svExternalDoubleRef:
986 const ScComplexRefData& rRef = p->GetDoubleRef();
987 const ScSingleRefData& r1 = rRef.Ref1;
988 const ScSingleRefData& r2 = rRef.Ref2;
989 if (r1.IsTabRel() || r2.IsTabRel())
990 break;
992 sal_uInt16 nTab1 = r1.nTab;
993 sal_uInt16 nTab2 = r2.nTab;
994 bool bCol1Rel = r1.IsColRel();
995 bool bRow1Rel = r1.IsRowRel();
996 bool bCol2Rel = r2.IsColRel();
997 bool bRow2Rel = r2.IsRowRel();
999 sal_uInt16 nCol1 = static_cast< sal_uInt16 >( bCol1Rel ? r1.nRelCol : r1.nCol );
1000 sal_uInt16 nCol2 = static_cast< sal_uInt16 >( bCol2Rel ? r2.nRelCol : r2.nCol );
1001 sal_uInt16 nRow1 = static_cast< sal_uInt16 >( bRow1Rel ? r1.nRelRow : r1.nRow );
1002 sal_uInt16 nRow2 = static_cast< sal_uInt16 >( bRow2Rel ? r2.nRelRow : r2.nRow );
1003 if (bCol1Rel) nCol1 |= 0x4000;
1004 if (bRow1Rel) nCol1 |= 0x8000;
1005 if (bCol2Rel) nCol2 |= 0x4000;
1006 if (bRow2Rel) nCol2 |= 0x8000;
1008 const String& rTabName = p->GetString();
1009 sal_uInt16 nSBTab = mrSupbook.GetTabIndex(rTabName);
1011 // size is always 13 (0x0D)
1012 rStrm << static_cast<sal_uInt16>(13);
1013 // operator token (3B for area reference)
1014 rStrm << static_cast<sal_uInt8>(0x3B);
1015 // range (area) address
1016 sal_uInt16 nSBTab2 = nSBTab + nTab2 - nTab1;
1017 rStrm << nSBTab << nSBTab2 << nRow1 << nRow2 << nCol1 << nCol2;
1018 return;
1020 default:
1021 ; // nothing
1024 while (false);
1026 // special value for #REF! (02 00 1C 17)
1027 rStrm << static_cast<sal_uInt16>(2) << EXC_TOKID_ERR << EXC_ERR_REF;
1030 // List of external names =====================================================
1032 XclExpExtNameBuffer::XclExpExtNameBuffer( const XclExpRoot& rRoot ) :
1033 XclExpRoot( rRoot )
1037 sal_uInt16 XclExpExtNameBuffer::InsertAddIn( const String& rName )
1039 sal_uInt16 nIndex = GetIndex( rName );
1040 return nIndex ? nIndex : AppendNew( new XclExpExtNameAddIn( GetRoot(), rName ) );
1043 sal_uInt16 XclExpExtNameBuffer::InsertEuroTool( const String& rName )
1045 sal_uInt16 nIndex = GetIndex( rName );
1046 return nIndex ? nIndex : AppendNew( new XclExpExtNameBase( GetRoot(), rName ) );
1049 sal_uInt16 XclExpExtNameBuffer::InsertDde(
1050 const String& rApplic, const String& rTopic, const String& rItem )
1052 sal_uInt16 nIndex = GetIndex( rItem );
1053 if( nIndex == 0 )
1055 sal_uInt16 nPos;
1056 if( GetDoc().FindDdeLink( rApplic, rTopic, rItem, SC_DDE_IGNOREMODE, nPos ) )
1058 // create the leading 'StdDocumentName' EXTERNNAME record
1059 if( maNameList.IsEmpty() )
1060 AppendNew( new XclExpExtNameDde(
1061 GetRoot(), String("StdDocumentName"), EXC_EXTN_EXPDDE_STDDOC ) );
1063 // try to find DDE result array, but create EXTERNNAME record without them too
1064 const ScMatrix* pScMatrix = GetDoc().GetDdeLinkResultMatrix( nPos );
1065 nIndex = AppendNew( new XclExpExtNameDde( GetRoot(), rItem, EXC_EXTN_EXPDDE, pScMatrix ) );
1068 return nIndex;
1071 sal_uInt16 XclExpExtNameBuffer::InsertExtName( const XclExpSupbook& rSupbook,
1072 const String& rName, const ScExternalRefCache::TokenArrayRef pArray )
1074 sal_uInt16 nIndex = GetIndex( rName );
1075 return nIndex ? nIndex : AppendNew( new XclExpExtName( GetRoot(), rSupbook, rName, pArray ) );
1078 void XclExpExtNameBuffer::Save( XclExpStream& rStrm )
1080 maNameList.Save( rStrm );
1083 sal_uInt16 XclExpExtNameBuffer::GetIndex( const String& rName ) const
1085 for( size_t nPos = 0, nSize = maNameList.GetSize(); nPos < nSize; ++nPos )
1086 if( maNameList.GetRecord( nPos )->GetName() == rName )
1087 return static_cast< sal_uInt16 >( nPos + 1 );
1088 return 0;
1091 sal_uInt16 XclExpExtNameBuffer::AppendNew( XclExpExtNameBase* pExtName )
1093 XclExpExtNameRef xExtName( pExtName );
1094 size_t nSize = maNameList.GetSize();
1095 if( nSize < 0x7FFF )
1097 maNameList.AppendRecord( xExtName );
1098 return static_cast< sal_uInt16 >( nSize + 1 );
1100 return 0;
1103 // Cached external cells ======================================================
1105 XclExpCrn::XclExpCrn( SCCOL nScCol, SCROW nScRow, const Any& rValue ) :
1106 XclExpRecord( EXC_ID_CRN, 4 ),
1107 mnScCol( nScCol ),
1108 mnScRow( nScRow )
1110 maValues.push_back( rValue );
1113 bool XclExpCrn::InsertValue( SCCOL nScCol, SCROW nScRow, const Any& rValue )
1115 if( (nScRow != mnScRow) || (nScCol != static_cast< SCCOL >( mnScCol + maValues.size() )) )
1116 return false;
1117 maValues.push_back( rValue );
1118 return true;
1121 void XclExpCrn::WriteBody( XclExpStream& rStrm )
1123 rStrm << static_cast< sal_uInt8 >( mnScCol + maValues.size() - 1 )
1124 << static_cast< sal_uInt8 >( mnScCol )
1125 << static_cast< sal_uInt16 >( mnScRow );
1126 for( CachedValues::iterator aIt = maValues.begin(), aEnd = maValues.end(); aIt != aEnd; ++aIt )
1128 if( aIt->has< bool >() )
1129 WriteBool( rStrm, aIt->get< bool >() );
1130 else if( aIt->has< double >() )
1131 WriteDouble( rStrm, aIt->get< double >() );
1132 else if( aIt->has< OUString >() )
1133 WriteString( rStrm, aIt->get< OUString >() );
1134 else
1135 WriteEmpty( rStrm );
1139 void XclExpCrn::WriteBool( XclExpStream& rStrm, bool bValue )
1141 rStrm << EXC_CACHEDVAL_BOOL << sal_uInt8( bValue ? 1 : 0);
1142 rStrm.WriteZeroBytes( 7 );
1145 void XclExpCrn::WriteDouble( XclExpStream& rStrm, double fValue )
1147 if( ::rtl::math::isNan( fValue ) )
1149 sal_uInt16 nScError = static_cast< sal_uInt16 >( reinterpret_cast< const sal_math_Double* >( &fValue )->nan_parts.fraction_lo );
1150 WriteError( rStrm, XclTools::GetXclErrorCode( nScError ) );
1152 else
1154 rStrm << EXC_CACHEDVAL_DOUBLE << fValue;
1158 void XclExpCrn::WriteString( XclExpStream& rStrm, const OUString& rValue )
1160 rStrm << EXC_CACHEDVAL_STRING << XclExpString( rValue );
1163 void XclExpCrn::WriteError( XclExpStream& rStrm, sal_uInt8 nErrCode )
1165 rStrm << EXC_CACHEDVAL_ERROR << nErrCode;
1166 rStrm.WriteZeroBytes( 7 );
1169 void XclExpCrn::WriteEmpty( XclExpStream& rStrm )
1171 rStrm << EXC_CACHEDVAL_EMPTY;
1172 rStrm.WriteZeroBytes( 8 );
1175 // Cached cells of a sheet ====================================================
1177 XclExpXct::XclExpXct( const XclExpRoot& rRoot, const String& rTabName,
1178 sal_uInt16 nSBTab, ScExternalRefCache::TableTypeRef xCacheTable ) :
1179 XclExpRoot( rRoot ),
1180 mxCacheTable( xCacheTable ),
1181 maBoundRange( ScAddress::INITIALIZE_INVALID ),
1182 maTabName( rTabName ),
1183 mnSBTab( nSBTab )
1187 void XclExpXct::StoreCellRange( const ScRange& rRange )
1189 // #i70418# restrict size of external range to prevent memory overflow
1190 if( (rRange.aEnd.Col() - rRange.aStart.Col()) * (rRange.aEnd.Row() - rRange.aStart.Row()) > 1024 )
1191 return;
1193 maUsedCells.SetMultiMarkArea( rRange );
1194 maBoundRange.ExtendTo( rRange );
1197 void XclExpXct::StoreCell( const ScAddress& rCell, const ::formula::FormulaToken& rToken )
1199 maUsedCells.SetMultiMarkArea( ScRange( rCell ) );
1200 maBoundRange.ExtendTo( ScRange( rCell ) );
1201 (void)rToken;
1204 void XclExpXct::StoreCellRange( const ScRange& rRange, const ::formula::FormulaToken& rToken )
1206 maUsedCells.SetMultiMarkArea( rRange );
1207 maBoundRange.ExtendTo( rRange );
1208 (void)rToken;
1211 namespace {
1213 class XclExpCrnList : public XclExpRecordList< XclExpCrn >
1215 public:
1216 /** Inserts the passed value into an existing or new CRN record.
1217 @return True = value inserted successfully, false = CRN list is full. */
1218 bool InsertValue( SCCOL nScCol, SCROW nScRow, const Any& rValue );
1221 bool XclExpCrnList::InsertValue( SCCOL nScCol, SCROW nScRow, const Any& rValue )
1223 RecordRefType xLastRec = GetLastRecord();
1224 if( xLastRec && xLastRec->InsertValue( nScCol, nScRow, rValue ) )
1225 return true;
1226 if( GetSize() == SAL_MAX_UINT16 )
1227 return false;
1228 AppendNewRecord( new XclExpCrn( nScCol, nScRow, rValue ) );
1229 return true;
1232 } // namespace
1234 void XclExpXct::Save( XclExpStream& rStrm )
1236 if( !mxCacheTable )
1237 return;
1239 /* Get the range of used rows in the cache table. This may help to
1240 optimize building the CRN record list if the cache table does not
1241 contain all referred cells, e.g. if big empty ranges are used in the
1242 formulas. */
1243 ::std::pair< SCROW, SCROW > aRowRange = mxCacheTable->getRowRange();
1244 if( aRowRange.first >= aRowRange.second )
1245 return;
1247 /* Crop the bounding range of used cells in this table to Excel limits.
1248 Return if there is no external cell inside these limits. */
1249 if( !GetAddressConverter().ValidateRange( maBoundRange, false ) )
1250 return;
1252 /* Find the resulting row range that needs to be processed. */
1253 SCROW nScRow1 = ::std::max( aRowRange.first, maBoundRange.aStart.Row() );
1254 SCROW nScRow2 = ::std::min( aRowRange.second - 1, maBoundRange.aEnd.Row() );
1255 if( nScRow1 > nScRow2 )
1256 return;
1258 /* Build and collect all CRN records before writing the XCT record. This
1259 is needed to determine the total number of CRN records which must be
1260 known when writing the XCT record (possibly encrypted, so seeking the
1261 output strem back after writing the CRN records is not an option). */
1262 XclExpCrnList aCrnRecs;
1263 SvNumberFormatter& rFormatter = GetFormatter();
1264 bool bValid = true;
1265 for( SCROW nScRow = nScRow1; bValid && (nScRow <= nScRow2); ++nScRow )
1267 ::std::pair< SCCOL, SCCOL > aColRange = mxCacheTable->getColRange( nScRow );
1268 for( SCCOL nScCol = aColRange.first; bValid && (nScCol < aColRange.second); ++nScCol )
1270 if( maUsedCells.IsCellMarked( nScCol, nScRow, sal_True ) )
1272 sal_uInt32 nScNumFmt = 0;
1273 ScExternalRefCache::TokenRef xToken = mxCacheTable->getCell( nScCol, nScRow, &nScNumFmt );
1274 using namespace ::formula;
1275 if( xToken.get() ) switch( xToken->GetType() )
1277 case svDouble:
1278 bValid = (rFormatter.GetType( nScNumFmt ) == NUMBERFORMAT_LOGICAL) ?
1279 aCrnRecs.InsertValue( nScCol, nScRow, Any( xToken->GetDouble() != 0 ) ) :
1280 aCrnRecs.InsertValue( nScCol, nScRow, Any( xToken->GetDouble() ) );
1281 break;
1282 case svString:
1283 // do not save empty strings (empty cells) to cache
1284 if( xToken->GetString().Len() > 0 )
1285 bValid = aCrnRecs.InsertValue( nScCol, nScRow, Any( OUString( xToken->GetString() ) ) );
1286 break;
1287 default:
1288 break;
1294 // write the XCT record and the list of CRN records
1295 rStrm.StartRecord( EXC_ID_XCT, 4 );
1296 rStrm << static_cast< sal_uInt16 >( aCrnRecs.GetSize() ) << mnSBTab;
1297 rStrm.EndRecord();
1298 aCrnRecs.Save( rStrm );
1301 // External documents (EXTERNSHEET/SUPBOOK), base class =======================
1303 XclExpExternSheetBase::XclExpExternSheetBase( const XclExpRoot& rRoot, sal_uInt16 nRecId, sal_uInt32 nRecSize ) :
1304 XclExpRecord( nRecId, nRecSize ),
1305 XclExpRoot( rRoot )
1309 XclExpExtNameBuffer& XclExpExternSheetBase::GetExtNameBuffer()
1311 if( !mxExtNameBfr )
1312 mxExtNameBfr.reset( new XclExpExtNameBuffer( GetRoot() ) );
1313 return *mxExtNameBfr;
1316 void XclExpExternSheetBase::WriteExtNameBuffer( XclExpStream& rStrm )
1318 if( mxExtNameBfr )
1319 mxExtNameBfr->Save( rStrm );
1322 // External documents (EXTERNSHEET, BIFF5/BIFF7) ==============================
1324 XclExpExternSheet::XclExpExternSheet( const XclExpRoot& rRoot, sal_Unicode cCode ) :
1325 XclExpExternSheetBase( rRoot, EXC_ID_EXTERNSHEET )
1327 Init( OUString(cCode) );
1330 XclExpExternSheet::XclExpExternSheet( const XclExpRoot& rRoot, const String& rTabName ) :
1331 XclExpExternSheetBase( rRoot, EXC_ID_EXTERNSHEET )
1333 // reference to own sheet: \03<sheetname>
1334 Init(OUString(EXC_EXTSH_TABNAME) + rTabName);
1337 void XclExpExternSheet::Save( XclExpStream& rStrm )
1339 // EXTERNSHEET record
1340 XclExpRecord::Save( rStrm );
1341 // EXTERNNAME records
1342 WriteExtNameBuffer( rStrm );
1345 void XclExpExternSheet::Init( const String& rEncUrl )
1347 OSL_ENSURE_BIFF( GetBiff() <= EXC_BIFF5 );
1348 maTabName.AssignByte( rEncUrl, GetTextEncoding(), EXC_STR_8BITLENGTH );
1349 SetRecSize( maTabName.GetSize() );
1352 sal_uInt16 XclExpExternSheet::InsertAddIn( const String& rName )
1354 return GetExtNameBuffer().InsertAddIn( rName );
1357 void XclExpExternSheet::WriteBody( XclExpStream& rStrm )
1359 sal_uInt8 nNameSize = static_cast< sal_uInt8 >( maTabName.Len() );
1360 // special case: reference to own sheet (starting with '\03') needs wrong string length
1361 if( maTabName.GetChar( 0 ) == EXC_EXTSH_TABNAME )
1362 --nNameSize;
1363 rStrm << nNameSize;
1364 maTabName.WriteBuffer( rStrm );
1367 // External document (SUPBOOK, BIFF8) =========================================
1369 XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, sal_uInt16 nXclTabCount ) :
1370 XclExpExternSheetBase( rRoot, EXC_ID_SUPBOOK, 4 ),
1371 meType( EXC_SBTYPE_SELF ),
1372 mnXclTabCount( nXclTabCount )
1376 XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot ) :
1377 XclExpExternSheetBase( rRoot, EXC_ID_SUPBOOK, 4 ),
1378 meType( EXC_SBTYPE_ADDIN ),
1379 mnXclTabCount( 1 )
1383 XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, const String& rUrl, XclSupbookType ) :
1384 XclExpExternSheetBase( rRoot, EXC_ID_SUPBOOK ),
1385 maUrl( rUrl ),
1386 maUrlEncoded( rUrl ),
1387 meType( EXC_SBTYPE_EUROTOOL ),
1388 mnXclTabCount( 0 )
1390 SetRecSize( 2 + maUrlEncoded.GetSize() );
1394 XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, const String& rUrl ) :
1395 XclExpExternSheetBase( rRoot, EXC_ID_SUPBOOK ),
1396 maUrl( rUrl ),
1397 maUrlEncoded( XclExpUrlHelper::EncodeUrl( rRoot, rUrl ) ),
1398 meType( EXC_SBTYPE_EXTERN ),
1399 mnXclTabCount( 0 )
1401 SetRecSize( 2 + maUrlEncoded.GetSize() );
1403 // We need to create all tables up front to ensure the correct table order.
1404 ScExternalRefManager* pRefMgr = rRoot.GetDoc().GetExternalRefManager();
1405 sal_uInt16 nFileId = pRefMgr->getExternalFileId( rUrl );
1406 ScfStringVec aTabNames;
1407 pRefMgr->getAllCachedTableNames( nFileId, aTabNames );
1408 for( ScfStringVec::const_iterator aBeg = aTabNames.begin(), aIt = aBeg, aEnd = aTabNames.end(); aIt != aEnd; ++aIt )
1409 InsertTabName( *aIt, pRefMgr->getCacheTable( nFileId, aIt - aBeg ) );
1412 XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, const String& rApplic, const String& rTopic ) :
1413 XclExpExternSheetBase( rRoot, EXC_ID_SUPBOOK, 4 ),
1414 maUrl( rApplic ),
1415 maDdeTopic( rTopic ),
1416 maUrlEncoded( XclExpUrlHelper::EncodeDde( rApplic, rTopic ) ),
1417 meType( EXC_SBTYPE_SPECIAL ),
1418 mnXclTabCount( 0 )
1420 SetRecSize( 2 + maUrlEncoded.GetSize() );
1423 bool XclExpSupbook::IsUrlLink( const String& rUrl ) const
1425 return (meType == EXC_SBTYPE_EXTERN || meType == EXC_SBTYPE_EUROTOOL) && (maUrl == rUrl);
1428 bool XclExpSupbook::IsDdeLink( const String& rApplic, const String& rTopic ) const
1430 return (meType == EXC_SBTYPE_SPECIAL) && (maUrl == rApplic) && (maDdeTopic == rTopic);
1433 void XclExpSupbook::FillRefLogEntry( XclExpRefLogEntry& rRefLogEntry,
1434 sal_uInt16 nFirstSBTab, sal_uInt16 nLastSBTab ) const
1436 rRefLogEntry.mpUrl = maUrlEncoded.IsEmpty() ? 0 : &maUrlEncoded;
1437 rRefLogEntry.mpFirstTab = GetTabName( nFirstSBTab );
1438 rRefLogEntry.mpLastTab = GetTabName( nLastSBTab );
1441 void XclExpSupbook::StoreCellRange( const ScRange& rRange, sal_uInt16 nSBTab )
1443 if( XclExpXct* pXct = maXctList.GetRecord( nSBTab ).get() )
1444 pXct->StoreCellRange( rRange );
1447 void XclExpSupbook::StoreCell( sal_uInt16 nSBTab, const ScAddress& rCell, const formula::FormulaToken& rToken )
1449 if( XclExpXct* pXct = maXctList.GetRecord( nSBTab ).get() )
1450 pXct->StoreCell( rCell, rToken );
1453 void XclExpSupbook::StoreCellRange( sal_uInt16 nSBTab, const ScRange& rRange, const formula::FormulaToken& rToken )
1455 // multi-table range is not allowed!
1456 if( rRange.aStart.Tab() == rRange.aEnd.Tab() )
1457 if( XclExpXct* pXct = maXctList.GetRecord( nSBTab ).get() )
1458 pXct->StoreCellRange( rRange, rToken );
1461 sal_uInt16 XclExpSupbook::GetTabIndex( const String& rTabName ) const
1463 XclExpString aXclName(rTabName);
1464 size_t nSize = maXctList.GetSize();
1465 for (size_t i = 0; i < nSize; ++i)
1467 XclExpXctRef aRec = maXctList.GetRecord(i);
1468 if (aXclName == aRec->GetTabName())
1469 return ulimit_cast<sal_uInt16>(i);
1471 return EXC_NOTAB;
1474 sal_uInt16 XclExpSupbook::GetTabCount() const
1476 return ulimit_cast<sal_uInt16>(maXctList.GetSize());
1479 sal_uInt16 XclExpSupbook::InsertTabName( const String& rTabName, ScExternalRefCache::TableTypeRef xCacheTable )
1481 OSL_ENSURE( meType == EXC_SBTYPE_EXTERN, "XclExpSupbook::InsertTabName - don't insert sheet names here" );
1482 sal_uInt16 nSBTab = ulimit_cast< sal_uInt16 >( maXctList.GetSize() );
1483 XclExpXctRef xXct( new XclExpXct( GetRoot(), rTabName, nSBTab, xCacheTable ) );
1484 AddRecSize( xXct->GetTabName().GetSize() );
1485 maXctList.AppendRecord( xXct );
1486 return nSBTab;
1489 sal_uInt16 XclExpSupbook::InsertAddIn( const String& rName )
1491 return GetExtNameBuffer().InsertAddIn( rName );
1494 sal_uInt16 XclExpSupbook::InsertEuroTool( const String& rName )
1496 return GetExtNameBuffer().InsertEuroTool( rName );
1499 sal_uInt16 XclExpSupbook::InsertDde( const String& rItem )
1501 return GetExtNameBuffer().InsertDde( maUrl, maDdeTopic, rItem );
1504 sal_uInt16 XclExpSupbook::InsertExtName( const String& rName, const ScExternalRefCache::TokenArrayRef pArray )
1506 return GetExtNameBuffer().InsertExtName(*this, rName, pArray);
1509 void XclExpSupbook::Save( XclExpStream& rStrm )
1511 // SUPBOOK record
1512 XclExpRecord::Save( rStrm );
1513 // XCT record, CRN records
1514 maXctList.Save( rStrm );
1515 // EXTERNNAME records
1516 WriteExtNameBuffer( rStrm );
1519 const XclExpString* XclExpSupbook::GetTabName( sal_uInt16 nSBTab ) const
1521 XclExpXctRef xXct = maXctList.GetRecord( nSBTab );
1522 return xXct ? &xXct->GetTabName() : 0;
1525 void XclExpSupbook::WriteBody( XclExpStream& rStrm )
1527 switch( meType )
1529 case EXC_SBTYPE_SELF:
1530 rStrm << mnXclTabCount << EXC_SUPB_SELF;
1531 break;
1532 case EXC_SBTYPE_EXTERN:
1533 case EXC_SBTYPE_SPECIAL:
1534 case EXC_SBTYPE_EUROTOOL:
1536 sal_uInt16 nCount = ulimit_cast< sal_uInt16 >( maXctList.GetSize() );
1537 rStrm << nCount << maUrlEncoded;
1539 for( size_t nPos = 0, nSize = maXctList.GetSize(); nPos < nSize; ++nPos )
1540 rStrm << maXctList.GetRecord( nPos )->GetTabName();
1542 break;
1543 case EXC_SBTYPE_ADDIN:
1544 rStrm << mnXclTabCount << EXC_SUPB_ADDIN;
1545 break;
1546 default:
1547 OSL_FAIL( "XclExpSupbook::WriteBody - unknown SUPBOOK type" );
1551 // All SUPBOOKS in a document =================================================
1553 XclExpSupbookBuffer::XclExpSupbookBuffer( const XclExpRoot& rRoot ) :
1554 XclExpRoot( rRoot ),
1555 mnOwnDocSB( SAL_MAX_UINT16 ),
1556 mnAddInSB( SAL_MAX_UINT16 )
1558 XclExpTabInfo& rTabInfo = GetTabInfo();
1559 sal_uInt16 nXclCnt = rTabInfo.GetXclTabCount();
1560 sal_uInt16 nCodeCnt = static_cast< sal_uInt16 >( GetExtDocOptions().GetCodeNameCount() );
1561 size_t nCount = nXclCnt + rTabInfo.GetXclExtTabCount();
1563 OSL_ENSURE( nCount > 0, "XclExpSupbookBuffer::XclExpSupbookBuffer - no sheets to export" );
1564 if( nCount )
1566 maSBIndexVec.resize( nCount );
1568 // self-ref SUPBOOK first of list
1569 XclExpSupbookRef xSupbook( new XclExpSupbook( GetRoot(), ::std::max( nXclCnt, nCodeCnt ) ) );
1570 mnOwnDocSB = Append( xSupbook );
1571 for( sal_uInt16 nXclTab = 0; nXclTab < nXclCnt; ++nXclTab )
1572 maSBIndexVec[ nXclTab ].Set( mnOwnDocSB, nXclTab );
1576 XclExpXti XclExpSupbookBuffer::GetXti( sal_uInt16 nFirstXclTab, sal_uInt16 nLastXclTab,
1577 XclExpRefLogEntry* pRefLogEntry ) const
1579 XclExpXti aXti;
1580 size_t nSize = maSBIndexVec.size();
1581 if( (nFirstXclTab < nSize) && (nLastXclTab < nSize) )
1583 // index of the SUPBOOK record
1584 aXti.mnSupbook = maSBIndexVec[ nFirstXclTab ].mnSupbook;
1586 // all sheets in the same supbook?
1587 bool bSameSB = true;
1588 for( sal_uInt16 nXclTab = nFirstXclTab + 1; bSameSB && (nXclTab <= nLastXclTab); ++nXclTab )
1590 bSameSB = maSBIndexVec[ nXclTab ].mnSupbook == aXti.mnSupbook;
1591 if( !bSameSB )
1592 nLastXclTab = nXclTab - 1;
1594 aXti.mnFirstSBTab = maSBIndexVec[ nFirstXclTab ].mnSBTab;
1595 aXti.mnLastSBTab = maSBIndexVec[ nLastXclTab ].mnSBTab;
1597 // fill external reference log entry (for change tracking)
1598 if( pRefLogEntry )
1600 pRefLogEntry->mnFirstXclTab = nFirstXclTab;
1601 pRefLogEntry->mnLastXclTab = nLastXclTab;
1602 XclExpSupbookRef xSupbook = maSupbookList.GetRecord( aXti.mnSupbook );
1603 if( xSupbook )
1604 xSupbook->FillRefLogEntry( *pRefLogEntry, aXti.mnFirstSBTab, aXti.mnLastSBTab );
1607 else
1609 // special range, i.e. for deleted sheets or add-ins
1610 aXti.mnSupbook = mnOwnDocSB;
1611 aXti.mnFirstSBTab = nFirstXclTab;
1612 aXti.mnLastSBTab = nLastXclTab;
1615 return aXti;
1618 void XclExpSupbookBuffer::StoreCellRange( const ScRange& rRange )
1620 sal_uInt16 nXclTab = GetTabInfo().GetXclTab( rRange.aStart.Tab() );
1621 if( nXclTab < maSBIndexVec.size() )
1623 const XclExpSBIndex& rSBIndex = maSBIndexVec[ nXclTab ];
1624 XclExpSupbookRef xSupbook = maSupbookList.GetRecord( rSBIndex.mnSupbook );
1625 OSL_ENSURE( xSupbook , "XclExpSupbookBuffer::StoreCellRange - missing SUPBOOK record" );
1626 if( xSupbook )
1627 xSupbook->StoreCellRange( rRange, rSBIndex.mnSBTab );
1631 namespace {
1633 class FindSBIndexEntry
1635 public:
1636 explicit FindSBIndexEntry(sal_uInt16 nSupbookId, sal_uInt16 nTabId) :
1637 mnSupbookId(nSupbookId), mnTabId(nTabId) {}
1639 bool operator()(const XclExpSupbookBuffer::XclExpSBIndex& r) const
1641 return mnSupbookId == r.mnSupbook && mnTabId == r.mnSBTab;
1644 private:
1645 sal_uInt16 mnSupbookId;
1646 sal_uInt16 mnTabId;
1651 void XclExpSupbookBuffer::StoreCell( sal_uInt16 nFileId, const String& rTabName, const ScAddress& rCell )
1653 ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager();
1654 const OUString* pUrl = pRefMgr->getExternalFileName(nFileId);
1655 if (!pUrl)
1656 return;
1658 XclExpSupbookRef xSupbook;
1659 sal_uInt16 nSupbookId;
1660 if (!GetSupbookUrl(xSupbook, nSupbookId, *pUrl))
1662 xSupbook.reset(new XclExpSupbook(GetRoot(), *pUrl));
1663 nSupbookId = Append(xSupbook);
1666 ScExternalRefCache::TokenRef pToken = pRefMgr->getSingleRefToken(nFileId, rTabName, rCell, NULL, NULL);
1667 if (!pToken.get())
1668 return;
1670 sal_uInt16 nSheetId = xSupbook->GetTabIndex(rTabName);
1671 if (nSheetId == EXC_NOTAB)
1672 // specified table name not found in this SUPBOOK.
1673 return;
1675 FindSBIndexEntry f(nSupbookId, nSheetId);
1676 XclExpSBIndexVec::iterator itrEnd = maSBIndexVec.end();
1677 XclExpSBIndexVec::const_iterator itr = find_if(maSBIndexVec.begin(), itrEnd, f);
1678 if (itr == itrEnd)
1680 maSBIndexVec.push_back(XclExpSBIndex());
1681 XclExpSBIndex& r = maSBIndexVec.back();
1682 r.mnSupbook = nSupbookId;
1683 r.mnSBTab = nSheetId;
1686 xSupbook->StoreCell(nSheetId, rCell, *pToken);
1689 void XclExpSupbookBuffer::StoreCellRange( sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange )
1691 ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager();
1692 const OUString* pUrl = pRefMgr->getExternalFileName(nFileId);
1693 if (!pUrl)
1694 return;
1696 XclExpSupbookRef xSupbook;
1697 sal_uInt16 nSupbookId;
1698 if (!GetSupbookUrl(xSupbook, nSupbookId, *pUrl))
1700 xSupbook.reset(new XclExpSupbook(GetRoot(), *pUrl));
1701 nSupbookId = Append(xSupbook);
1704 SCTAB nTabCount = rRange.aEnd.Tab() - rRange.aStart.Tab() + 1;
1706 // If this is a multi-table range, get token for each table.
1707 using namespace ::formula;
1708 vector<FormulaToken*> aMatrixList;
1709 aMatrixList.reserve(nTabCount);
1711 // This is a new'ed instance, so we must manage its life cycle here.
1712 ScExternalRefCache::TokenArrayRef pArray = pRefMgr->getDoubleRefTokens(nFileId, rTabName, rRange, NULL);
1713 if (!pArray.get())
1714 return;
1716 for (FormulaToken* p = pArray->First(); p; p = pArray->Next())
1718 if (p->GetType() == svMatrix)
1719 aMatrixList.push_back(p);
1720 else if (p->GetOpCode() != ocSep)
1722 // This is supposed to be ocSep!!!
1723 return;
1727 if (aMatrixList.size() != static_cast<size_t>(nTabCount))
1729 // matrix size mis-match !
1730 return;
1733 sal_uInt16 nFirstSheetId = xSupbook->GetTabIndex(rTabName);
1735 ScRange aRange(rRange);
1736 aRange.aStart.SetTab(0);
1737 aRange.aEnd.SetTab(0);
1738 for (SCTAB nTab = 0; nTab < nTabCount; ++nTab)
1740 sal_uInt16 nSheetId = nFirstSheetId + static_cast<sal_uInt16>(nTab);
1741 FindSBIndexEntry f(nSupbookId, nSheetId);
1742 XclExpSBIndexVec::iterator itrEnd = maSBIndexVec.end();
1743 XclExpSBIndexVec::const_iterator itr = find_if(maSBIndexVec.begin(), itrEnd, f);
1744 if (itr == itrEnd)
1746 maSBIndexVec.push_back(XclExpSBIndex());
1747 XclExpSBIndex& r = maSBIndexVec.back();
1748 r.mnSupbook = nSupbookId;
1749 r.mnSBTab = nSheetId;
1752 xSupbook->StoreCellRange(nSheetId, aRange, *aMatrixList[nTab]);
1756 bool XclExpSupbookBuffer::InsertAddIn(
1757 sal_uInt16& rnSupbook, sal_uInt16& rnExtName, const String& rName )
1759 XclExpSupbookRef xSupbook;
1760 if( mnAddInSB == SAL_MAX_UINT16 )
1762 xSupbook.reset( new XclExpSupbook( GetRoot() ) );
1763 mnAddInSB = Append( xSupbook );
1765 else
1766 xSupbook = maSupbookList.GetRecord( mnAddInSB );
1767 OSL_ENSURE( xSupbook, "XclExpSupbookBuffer::InsertAddin - missing add-in supbook" );
1768 rnSupbook = mnAddInSB;
1769 rnExtName = xSupbook->InsertAddIn( rName );
1770 return rnExtName > 0;
1773 bool XclExpSupbookBuffer::InsertEuroTool(
1774 sal_uInt16& rnSupbook, sal_uInt16& rnExtName, const String& rName )
1776 XclExpSupbookRef xSupbook;
1777 String aUrl( RTL_CONSTASCII_USTRINGPARAM("\001\010EUROTOOL.XLA"));
1778 if( !GetSupbookUrl( xSupbook, rnSupbook, aUrl ) )
1780 xSupbook.reset( new XclExpSupbook( GetRoot(), aUrl, EXC_SBTYPE_EUROTOOL ) );
1781 rnSupbook = Append( xSupbook );
1783 rnExtName = xSupbook->InsertEuroTool( rName );
1784 return rnExtName > 0;
1787 bool XclExpSupbookBuffer::InsertDde(
1788 sal_uInt16& rnSupbook, sal_uInt16& rnExtName,
1789 const String& rApplic, const String& rTopic, const String& rItem )
1791 XclExpSupbookRef xSupbook;
1792 if( !GetSupbookDde( xSupbook, rnSupbook, rApplic, rTopic ) )
1794 xSupbook.reset( new XclExpSupbook( GetRoot(), rApplic, rTopic ) );
1795 rnSupbook = Append( xSupbook );
1797 rnExtName = xSupbook->InsertDde( rItem );
1798 return rnExtName > 0;
1801 bool XclExpSupbookBuffer::InsertExtName(
1802 sal_uInt16& rnSupbook, sal_uInt16& rnExtName, const String& rUrl,
1803 const String& rName, const ScExternalRefCache::TokenArrayRef pArray )
1805 XclExpSupbookRef xSupbook;
1806 if (!GetSupbookUrl(xSupbook, rnSupbook, rUrl))
1808 xSupbook.reset( new XclExpSupbook(GetRoot(), rUrl) );
1809 rnSupbook = Append(xSupbook);
1811 rnExtName = xSupbook->InsertExtName(rName, pArray);
1812 return rnExtName > 0;
1815 XclExpXti XclExpSupbookBuffer::GetXti( sal_uInt16 nFileId, const String& rTabName, sal_uInt16 nXclTabSpan,
1816 XclExpRefLogEntry* pRefLogEntry )
1818 XclExpXti aXti(0, EXC_NOTAB, EXC_NOTAB);
1819 ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager();
1820 const OUString* pUrl = pRefMgr->getExternalFileName(nFileId);
1821 if (!pUrl)
1822 return aXti;
1824 XclExpSupbookRef xSupbook;
1825 sal_uInt16 nSupbookId;
1826 if (!GetSupbookUrl(xSupbook, nSupbookId, *pUrl))
1828 xSupbook.reset(new XclExpSupbook(GetRoot(), *pUrl));
1829 nSupbookId = Append(xSupbook);
1831 aXti.mnSupbook = nSupbookId;
1833 sal_uInt16 nFirstSheetId = xSupbook->GetTabIndex(rTabName);
1834 if (nFirstSheetId == EXC_NOTAB)
1836 // first sheet not found in SUPBOOK.
1837 return aXti;
1839 sal_uInt16 nSheetCount = xSupbook->GetTabCount();
1840 for (sal_uInt16 i = 0; i < nXclTabSpan; ++i)
1842 sal_uInt16 nSheetId = nFirstSheetId + i;
1843 if (nSheetId >= nSheetCount)
1844 return aXti;
1846 FindSBIndexEntry f(nSupbookId, nSheetId);
1847 XclExpSBIndexVec::iterator itrEnd = maSBIndexVec.end();
1848 XclExpSBIndexVec::const_iterator itr = find_if(maSBIndexVec.begin(), itrEnd, f);
1849 if (itr == itrEnd)
1851 maSBIndexVec.push_back(XclExpSBIndex());
1852 XclExpSBIndex& r = maSBIndexVec.back();
1853 r.mnSupbook = nSupbookId;
1854 r.mnSBTab = nSheetId;
1856 if (i == 0)
1857 aXti.mnFirstSBTab = nSheetId;
1858 if (i == nXclTabSpan - 1)
1859 aXti.mnLastSBTab = nSheetId;
1862 if (pRefLogEntry)
1864 pRefLogEntry->mnFirstXclTab = 0;
1865 pRefLogEntry->mnLastXclTab = 0;
1866 if (xSupbook)
1867 xSupbook->FillRefLogEntry(*pRefLogEntry, aXti.mnFirstSBTab, aXti.mnLastSBTab);
1870 return aXti;
1873 void XclExpSupbookBuffer::Save( XclExpStream& rStrm )
1875 maSupbookList.Save( rStrm );
1878 bool XclExpSupbookBuffer::GetSupbookUrl(
1879 XclExpSupbookRef& rxSupbook, sal_uInt16& rnIndex, const String& rUrl ) const
1881 for( size_t nPos = 0, nSize = maSupbookList.GetSize(); nPos < nSize; ++nPos )
1883 rxSupbook = maSupbookList.GetRecord( nPos );
1884 if( rxSupbook->IsUrlLink( rUrl ) )
1886 rnIndex = ulimit_cast< sal_uInt16 >( nPos );
1887 return true;
1890 return false;
1893 bool XclExpSupbookBuffer::GetSupbookDde( XclExpSupbookRef& rxSupbook,
1894 sal_uInt16& rnIndex, const String& rApplic, const String& rTopic ) const
1896 for( size_t nPos = 0, nSize = maSupbookList.GetSize(); nPos < nSize; ++nPos )
1898 rxSupbook = maSupbookList.GetRecord( nPos );
1899 if( rxSupbook->IsDdeLink( rApplic, rTopic ) )
1901 rnIndex = ulimit_cast< sal_uInt16 >( nPos );
1902 return true;
1905 return false;
1908 sal_uInt16 XclExpSupbookBuffer::Append( XclExpSupbookRef xSupbook )
1910 maSupbookList.AppendRecord( xSupbook );
1911 return ulimit_cast< sal_uInt16 >( maSupbookList.GetSize() - 1 );
1914 // Export link manager ========================================================
1916 XclExpLinkManagerImpl::XclExpLinkManagerImpl( const XclExpRoot& rRoot ) :
1917 XclExpRoot( rRoot )
1921 // ----------------------------------------------------------------------------
1923 XclExpLinkManagerImpl5::XclExpLinkManagerImpl5( const XclExpRoot& rRoot ) :
1924 XclExpLinkManagerImpl( rRoot )
1928 void XclExpLinkManagerImpl5::FindExtSheet(
1929 sal_uInt16& rnExtSheet, sal_uInt16& rnFirstXclTab, sal_uInt16& rnLastXclTab,
1930 SCTAB nFirstScTab, SCTAB nLastScTab, XclExpRefLogEntry* pRefLogEntry )
1932 FindInternal( rnExtSheet, rnFirstXclTab, nFirstScTab );
1933 if( (rnFirstXclTab == EXC_TAB_DELETED) || (nFirstScTab == nLastScTab) )
1935 rnLastXclTab = rnFirstXclTab;
1937 else
1939 sal_uInt16 nDummyExtSheet;
1940 FindInternal( nDummyExtSheet, rnLastXclTab, nLastScTab );
1943 (void)pRefLogEntry; // avoid compiler warning
1944 OSL_ENSURE( !pRefLogEntry, "XclExpLinkManagerImpl5::FindExtSheet - fill reflog entry not implemented" );
1947 sal_uInt16 XclExpLinkManagerImpl5::FindExtSheet( sal_Unicode cCode )
1949 sal_uInt16 nExtSheet;
1950 FindInternal( nExtSheet, cCode );
1951 return nExtSheet;
1954 void XclExpLinkManagerImpl5::FindExtSheet(
1955 sal_uInt16 /*nFileId*/, const String& /*rTabName*/, sal_uInt16 /*nXclTabSpan*/,
1956 sal_uInt16& /*rnExtSheet*/, sal_uInt16& /*rnFirstSBTab*/, sal_uInt16& /*rnLastSBTab*/,
1957 XclExpRefLogEntry* /*pRefLogEntry*/ )
1959 // not implemented
1962 void XclExpLinkManagerImpl5::StoreCellRange( const ScSingleRefData& /*rRef1*/, const ScSingleRefData& /*rRef2*/ )
1964 // not implemented
1967 void XclExpLinkManagerImpl5::StoreCell( sal_uInt16 /*nFileId*/, const String& /*rTabName*/, const ScSingleRefData& /*rRef*/ )
1969 // not implemented
1972 void XclExpLinkManagerImpl5::StoreCellRange( sal_uInt16 /*nFileId*/, const String& /*rTabName*/, const ScSingleRefData& /*rRef1*/, const ScSingleRefData& /*rRef2*/ )
1974 // not implemented
1977 bool XclExpLinkManagerImpl5::InsertAddIn(
1978 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const String& rName )
1980 XclExpExtSheetRef xExtSheet = FindInternal( rnExtSheet, EXC_EXTSH_ADDIN );
1981 if( xExtSheet )
1983 rnExtName = xExtSheet->InsertAddIn( rName );
1984 return rnExtName > 0;
1986 return false;
1989 bool XclExpLinkManagerImpl5::InsertEuroTool(
1990 sal_uInt16& /*rnExtSheet*/, sal_uInt16& /*rnExtName*/, const String& /*rName*/ )
1992 return false;
1996 bool XclExpLinkManagerImpl5::InsertDde(
1997 sal_uInt16& /*rnExtSheet*/, sal_uInt16& /*rnExtName*/,
1998 const String& /*rApplic*/, const String& /*rTopic*/, const String& /*rItem*/ )
2000 // not implemented
2001 return false;
2004 bool XclExpLinkManagerImpl5::InsertExtName(
2005 sal_uInt16& /*rnExtSheet*/, sal_uInt16& /*rnExtName*/, const String& /*rUrl*/,
2006 const String& /*rName*/, const ScExternalRefCache::TokenArrayRef /*pArray*/ )
2008 // not implemented
2009 return false;
2012 void XclExpLinkManagerImpl5::Save( XclExpStream& rStrm )
2014 if( sal_uInt16 nExtSheetCount = GetExtSheetCount() )
2016 // EXTERNCOUNT record
2017 XclExpUInt16Record( EXC_ID_EXTERNCOUNT, nExtSheetCount ).Save( rStrm );
2018 // list of EXTERNSHEET records with EXTERNNAME, XCT, CRN records
2019 maExtSheetList.Save( rStrm );
2023 sal_uInt16 XclExpLinkManagerImpl5::GetExtSheetCount() const
2025 return static_cast< sal_uInt16 >( maExtSheetList.GetSize() );
2028 sal_uInt16 XclExpLinkManagerImpl5::AppendInternal( XclExpExtSheetRef xExtSheet )
2030 if( GetExtSheetCount() < 0x7FFF )
2032 maExtSheetList.AppendRecord( xExtSheet );
2033 // return negated one-based EXTERNSHEET index (i.e. 0xFFFD for 3rd record)
2034 return static_cast< sal_uInt16 >( -GetExtSheetCount() );
2036 return 0;
2039 void XclExpLinkManagerImpl5::CreateInternal()
2041 if( maIntTabMap.empty() )
2043 // create EXTERNSHEET records for all internal exported sheets
2044 XclExpTabInfo& rTabInfo = GetTabInfo();
2045 for( SCTAB nScTab = 0, nScCnt = rTabInfo.GetScTabCount(); nScTab < nScCnt; ++nScTab )
2047 if( rTabInfo.IsExportTab( nScTab ) )
2049 XclExpExtSheetRef xRec;
2050 if( nScTab == GetCurrScTab() )
2051 xRec.reset( new XclExpExternSheet( GetRoot(), EXC_EXTSH_OWNTAB ) );
2052 else
2053 xRec.reset( new XclExpExternSheet( GetRoot(), rTabInfo.GetScTabName( nScTab ) ) );
2054 maIntTabMap[ nScTab ] = AppendInternal( xRec );
2060 XclExpLinkManagerImpl5::XclExpExtSheetRef XclExpLinkManagerImpl5::GetInternal( sal_uInt16 nExtSheet )
2062 return maExtSheetList.GetRecord( static_cast< sal_uInt16 >( -nExtSheet - 1 ) );
2065 XclExpLinkManagerImpl5::XclExpExtSheetRef XclExpLinkManagerImpl5::FindInternal(
2066 sal_uInt16& rnExtSheet, sal_uInt16& rnXclTab, SCTAB nScTab )
2068 // create internal EXTERNSHEET records on demand
2069 CreateInternal();
2071 // try to find an EXTERNSHEET record - if not, return a "deleted sheet" reference
2072 XclExpExtSheetRef xExtSheet;
2073 XclExpIntTabMap::const_iterator aIt = maIntTabMap.find( nScTab );
2074 if( aIt == maIntTabMap.end() )
2076 xExtSheet = FindInternal( rnExtSheet, EXC_EXTSH_OWNDOC );
2077 rnXclTab = EXC_TAB_DELETED;
2079 else
2081 rnExtSheet = aIt->second;
2082 xExtSheet = GetInternal( rnExtSheet );
2083 rnXclTab = GetTabInfo().GetXclTab( nScTab );
2085 return xExtSheet;
2088 XclExpLinkManagerImpl5::XclExpExtSheetRef XclExpLinkManagerImpl5::FindInternal(
2089 sal_uInt16& rnExtSheet, sal_Unicode cCode )
2091 XclExpExtSheetRef xExtSheet;
2092 XclExpCodeMap::const_iterator aIt = maCodeMap.find( cCode );
2093 if( aIt == maCodeMap.end() )
2095 xExtSheet.reset( new XclExpExternSheet( GetRoot(), cCode ) );
2096 rnExtSheet = maCodeMap[ cCode ] = AppendInternal( xExtSheet );
2098 else
2100 rnExtSheet = aIt->second;
2101 xExtSheet = GetInternal( rnExtSheet );
2103 return xExtSheet;
2106 // ----------------------------------------------------------------------------
2108 XclExpLinkManagerImpl8::XclExpLinkManagerImpl8( const XclExpRoot& rRoot ) :
2109 XclExpLinkManagerImpl( rRoot ),
2110 maSBBuffer( rRoot )
2114 void XclExpLinkManagerImpl8::FindExtSheet(
2115 sal_uInt16& rnExtSheet, sal_uInt16& rnFirstXclTab, sal_uInt16& rnLastXclTab,
2116 SCTAB nFirstScTab, SCTAB nLastScTab, XclExpRefLogEntry* pRefLogEntry )
2118 XclExpTabInfo& rTabInfo = GetTabInfo();
2119 rnFirstXclTab = rTabInfo.GetXclTab( nFirstScTab );
2120 rnLastXclTab = rTabInfo.GetXclTab( nLastScTab );
2121 rnExtSheet = InsertXti( maSBBuffer.GetXti( rnFirstXclTab, rnLastXclTab, pRefLogEntry ) );
2124 sal_uInt16 XclExpLinkManagerImpl8::FindExtSheet( sal_Unicode cCode )
2126 (void)cCode; // avoid compiler warning
2127 OSL_ENSURE( (cCode == EXC_EXTSH_OWNDOC) || (cCode == EXC_EXTSH_ADDIN),
2128 "XclExpLinkManagerImpl8::FindExtSheet - unknown externsheet code" );
2129 return InsertXti( maSBBuffer.GetXti( EXC_TAB_EXTERNAL, EXC_TAB_EXTERNAL ) );
2132 void XclExpLinkManagerImpl8::FindExtSheet(
2133 sal_uInt16 nFileId, const String& rTabName, sal_uInt16 nXclTabSpan,
2134 sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
2135 XclExpRefLogEntry* pRefLogEntry )
2137 XclExpXti aXti = maSBBuffer.GetXti(nFileId, rTabName, nXclTabSpan, pRefLogEntry);
2138 rnExtSheet = InsertXti(aXti);
2139 rnFirstSBTab = aXti.mnFirstSBTab;
2140 rnLastSBTab = aXti.mnLastSBTab;
2143 void XclExpLinkManagerImpl8::StoreCellRange( const ScSingleRefData& rRef1, const ScSingleRefData& rRef2 )
2145 if( !rRef1.IsDeleted() && !rRef2.IsDeleted() && (rRef1.nTab >= 0) && (rRef2.nTab >= 0) )
2147 const XclExpTabInfo& rTabInfo = GetTabInfo();
2148 SCTAB nFirstScTab = static_cast< SCTAB >( rRef1.nTab );
2149 SCTAB nLastScTab = static_cast< SCTAB >( rRef2.nTab );
2150 ScRange aRange(
2151 static_cast< SCCOL >( rRef1.nCol ), static_cast< SCROW >( rRef1.nRow ), 0,
2152 static_cast< SCCOL >( rRef2.nCol ), static_cast< SCROW >( rRef2.nRow ), 0 );
2153 for( SCTAB nScTab = nFirstScTab; nScTab <= nLastScTab; ++nScTab )
2155 if( rTabInfo.IsExternalTab( nScTab ) )
2157 aRange.aStart.SetTab( nScTab );
2158 aRange.aEnd.SetTab( nScTab );
2159 maSBBuffer.StoreCellRange( aRange );
2165 void XclExpLinkManagerImpl8::StoreCell( sal_uInt16 nFileId, const String& rTabName, const ScSingleRefData& rRef )
2167 ScAddress aAddr(rRef.nCol, rRef.nRow, rRef.nTab);
2168 maSBBuffer.StoreCell(nFileId, rTabName, aAddr);
2171 void XclExpLinkManagerImpl8::StoreCellRange( sal_uInt16 nFileId, const String& rTabName, const ScSingleRefData& rRef1, const ScSingleRefData& rRef2 )
2173 ScRange aRange(static_cast<SCCOL>(rRef1.nCol), static_cast<SCROW>(rRef1.nRow), static_cast<SCTAB>(rRef1.nTab),
2174 static_cast<SCCOL>(rRef2.nCol), static_cast<SCROW>(rRef2.nRow), static_cast<SCTAB>(rRef2.nTab));
2175 maSBBuffer.StoreCellRange(nFileId, rTabName, aRange);
2178 bool XclExpLinkManagerImpl8::InsertAddIn(
2179 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const String& rName )
2181 sal_uInt16 nSupbook;
2182 if( maSBBuffer.InsertAddIn( nSupbook, rnExtName, rName ) )
2184 rnExtSheet = InsertXti( XclExpXti( nSupbook, EXC_TAB_EXTERNAL, EXC_TAB_EXTERNAL ) );
2185 return true;
2187 return false;
2190 bool XclExpLinkManagerImpl8::InsertEuroTool(
2191 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const String& rName )
2193 sal_uInt16 nSupbook;
2194 if( maSBBuffer.InsertEuroTool( nSupbook, rnExtName, rName ) )
2196 rnExtSheet = InsertXti( XclExpXti( nSupbook, EXC_TAB_EXTERNAL, EXC_TAB_EXTERNAL ) );
2197 return true;
2199 return false;
2203 bool XclExpLinkManagerImpl8::InsertDde(
2204 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
2205 const String& rApplic, const String& rTopic, const String& rItem )
2207 sal_uInt16 nSupbook;
2208 if( maSBBuffer.InsertDde( nSupbook, rnExtName, rApplic, rTopic, rItem ) )
2210 rnExtSheet = InsertXti( XclExpXti( nSupbook, EXC_TAB_EXTERNAL, EXC_TAB_EXTERNAL ) );
2211 return true;
2213 return false;
2216 bool XclExpLinkManagerImpl8::InsertExtName( sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
2217 const String& rName, const String& rUrl, const ScExternalRefCache::TokenArrayRef pArray )
2219 sal_uInt16 nSupbook;
2220 if( maSBBuffer.InsertExtName( nSupbook, rnExtName, rUrl, rName, pArray ) )
2222 rnExtSheet = InsertXti( XclExpXti( nSupbook, EXC_TAB_EXTERNAL, EXC_TAB_EXTERNAL ) );
2223 return true;
2225 return false;
2228 void XclExpLinkManagerImpl8::Save( XclExpStream& rStrm )
2230 if( !maXtiVec.empty() )
2232 // SUPBOOKs, XCTs, CRNs, EXTERNNAMEs
2233 maSBBuffer.Save( rStrm );
2235 // EXTERNSHEET
2236 sal_uInt16 nCount = ulimit_cast< sal_uInt16 >( maXtiVec.size() );
2237 rStrm.StartRecord( EXC_ID_EXTERNSHEET, 2 + 6 * nCount );
2238 rStrm << nCount;
2239 rStrm.SetSliceSize( 6 );
2240 for( XclExpXtiVec::const_iterator aIt = maXtiVec.begin(), aEnd = maXtiVec.end(); aIt != aEnd; ++aIt )
2241 aIt->Save( rStrm );
2242 rStrm.EndRecord();
2246 sal_uInt16 XclExpLinkManagerImpl8::InsertXti( const XclExpXti& rXti )
2248 for( XclExpXtiVec::const_iterator aIt = maXtiVec.begin(), aEnd = maXtiVec.end(); aIt != aEnd; ++aIt )
2249 if( *aIt == rXti )
2250 return ulimit_cast< sal_uInt16 >( aIt - maXtiVec.begin() );
2251 maXtiVec.push_back( rXti );
2252 return ulimit_cast< sal_uInt16 >( maXtiVec.size() - 1 );
2255 // ============================================================================
2257 XclExpLinkManager::XclExpLinkManager( const XclExpRoot& rRoot ) :
2258 XclExpRoot( rRoot )
2260 switch( GetBiff() )
2262 case EXC_BIFF5:
2263 mxImpl.reset( new XclExpLinkManagerImpl5( rRoot ) );
2264 break;
2265 case EXC_BIFF8:
2266 mxImpl.reset( new XclExpLinkManagerImpl8( rRoot ) );
2267 break;
2268 default:
2269 DBG_ERROR_BIFF();
2273 XclExpLinkManager::~XclExpLinkManager()
2277 void XclExpLinkManager::FindExtSheet(
2278 sal_uInt16& rnExtSheet, sal_uInt16& rnXclTab,
2279 SCTAB nScTab, XclExpRefLogEntry* pRefLogEntry )
2281 mxImpl->FindExtSheet( rnExtSheet, rnXclTab, rnXclTab, nScTab, nScTab, pRefLogEntry );
2284 void XclExpLinkManager::FindExtSheet(
2285 sal_uInt16& rnExtSheet, sal_uInt16& rnFirstXclTab, sal_uInt16& rnLastXclTab,
2286 SCTAB nFirstScTab, SCTAB nLastScTab, XclExpRefLogEntry* pRefLogEntry )
2288 mxImpl->FindExtSheet( rnExtSheet, rnFirstXclTab, rnLastXclTab, nFirstScTab, nLastScTab, pRefLogEntry );
2291 sal_uInt16 XclExpLinkManager::FindExtSheet( sal_Unicode cCode )
2293 return mxImpl->FindExtSheet( cCode );
2296 void XclExpLinkManager::FindExtSheet( sal_uInt16 nFileId, const String& rTabName, sal_uInt16 nXclTabSpan,
2297 sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
2298 XclExpRefLogEntry* pRefLogEntry )
2300 mxImpl->FindExtSheet( nFileId, rTabName, nXclTabSpan, rnExtSheet, rnFirstSBTab, rnLastSBTab, pRefLogEntry );
2303 void XclExpLinkManager::StoreCell( const ScSingleRefData& rRef )
2305 mxImpl->StoreCellRange( rRef, rRef );
2308 void XclExpLinkManager::StoreCellRange( const ScComplexRefData& rRef )
2310 mxImpl->StoreCellRange( rRef.Ref1, rRef.Ref2 );
2313 void XclExpLinkManager::StoreCell( sal_uInt16 nFileId, const String& rTabName, const ScSingleRefData& rRef )
2315 mxImpl->StoreCell( nFileId, rTabName, rRef );
2318 void XclExpLinkManager::StoreCellRange( sal_uInt16 nFileId, const String& rTabName, const ScComplexRefData& rRef )
2320 mxImpl->StoreCellRange( nFileId, rTabName, rRef.Ref1, rRef.Ref2 );
2323 bool XclExpLinkManager::InsertAddIn(
2324 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const String& rName )
2326 return mxImpl->InsertAddIn( rnExtSheet, rnExtName, rName );
2329 bool XclExpLinkManager::InsertEuroTool(
2330 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const String& rName )
2332 return mxImpl->InsertEuroTool( rnExtSheet, rnExtName, rName );
2335 bool XclExpLinkManager::InsertDde(
2336 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
2337 const String& rApplic, const String& rTopic, const String& rItem )
2339 return mxImpl->InsertDde( rnExtSheet, rnExtName, rApplic, rTopic, rItem );
2342 bool XclExpLinkManager::InsertExtName(
2343 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const String& rName, const String& rUrl,
2344 const ScExternalRefCache::TokenArrayRef pArray )
2346 return mxImpl->InsertExtName( rnExtSheet, rnExtName, rUrl, rName, pArray );
2349 void XclExpLinkManager::Save( XclExpStream& rStrm )
2351 mxImpl->Save( rStrm );
2354 // ============================================================================
2356 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */