fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / filter / excel / xelink.cxx
bloba936f457c61d3cbf6bb1848881f1559576cc16f9
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"
30 #include "xecontent.hxx"
32 #include <vector>
33 #include <memory>
35 using ::std::unique_ptr;
36 using ::std::vector;
37 using ::com::sun::star::uno::Any;
39 using namespace oox;
41 // *** Helper classes ***
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 OUString& rName, sal_uInt16 nFlags = 0 );
53 virtual ~XclExpExtNameBase();
55 /** Returns the name string of the external name. */
56 inline const OUString& 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 ) SAL_OVERRIDE;
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 protected:
66 OUString 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 /** Represents an EXTERNNAME record for an add-in function name. */
72 class XclExpExtNameAddIn : public XclExpExtNameBase
74 public:
75 explicit XclExpExtNameAddIn( const XclExpRoot& rRoot, const OUString& rName );
77 private:
78 /** Writes additional record contents. */
79 virtual void WriteAddData( XclExpStream& rStrm ) SAL_OVERRIDE;
82 /** Represents an EXTERNNAME record for a DDE link. */
83 class XclExpExtNameDde : public XclExpExtNameBase
85 public:
86 explicit XclExpExtNameDde( const XclExpRoot& rRoot, const OUString& rName,
87 sal_uInt16 nFlags, const ScMatrix* pResults = 0 );
89 private:
90 /** Writes additional record contents. */
91 virtual void WriteAddData( XclExpStream& rStrm ) SAL_OVERRIDE;
93 private:
94 typedef boost::shared_ptr< XclExpCachedMatrix > XclExpCachedMatRef;
95 XclExpCachedMatRef mxMatrix; /// Cached results of the DDE link.
98 class XclExpSupbook;
100 class XclExpExtName : public XclExpExtNameBase
102 public:
103 explicit XclExpExtName( const XclExpRoot& rRoot, const XclExpSupbook& rSupbook, const OUString& rName,
104 const ScExternalRefCache::TokenArrayRef& rArray );
106 virtual void SaveXml(XclExpXmlStream& rStrm) SAL_OVERRIDE;
108 private:
109 /** Writes additional record contents. */
110 virtual void WriteAddData( XclExpStream& rStrm ) SAL_OVERRIDE;
112 private:
113 const XclExpSupbook& mrSupbook;
114 unique_ptr<ScTokenArray> mpArray;
117 // List of external names =====================================================
119 /** List of all external names of a sheet. */
120 class XclExpExtNameBuffer : public XclExpRecordBase, protected XclExpRoot
122 public:
123 explicit XclExpExtNameBuffer( const XclExpRoot& rRoot );
125 /** Inserts an add-in function name
126 @return The 1-based (Excel-like) list index of the name. */
127 sal_uInt16 InsertAddIn( const OUString& rName );
128 /** InsertEuroTool */
129 sal_uInt16 InsertEuroTool( const OUString& rName );
130 /** Inserts a DDE link.
131 @return The 1-based (Excel-like) list index of the DDE link. */
132 sal_uInt16 InsertDde( const OUString& rApplic, const OUString& rTopic, const OUString& rItem );
134 sal_uInt16 InsertExtName( const XclExpSupbook& rSupbook, const OUString& rName, const ScExternalRefCache::TokenArrayRef& rArray );
136 /** Writes the EXTERNNAME record list. */
137 virtual void Save( XclExpStream& rStrm ) SAL_OVERRIDE;
139 virtual void SaveXml(XclExpXmlStream& rStrm) SAL_OVERRIDE;
141 private:
142 typedef XclExpRecordList< XclExpExtNameBase > XclExpExtNameList;
143 typedef XclExpExtNameList::RecordRefType XclExpExtNameRef;
145 private:
146 /** Returns the 1-based (Excel-like) list index of the external name or 0, if not found. */
147 sal_uInt16 GetIndex( const OUString& rName ) const;
148 /** Appends the passed newly crested external name.
149 @return The 1-based (Excel-like) list index of the appended name. */
150 sal_uInt16 AppendNew( XclExpExtNameBase* pExtName );
152 private:
153 XclExpExtNameList maNameList; /// The list with all EXTERNNAME records.
156 // Cached external cells ======================================================
158 /** Stores the contents of a consecutive row of external cells (record CRN). */
159 class XclExpCrn : public XclExpRecord
161 public:
162 explicit XclExpCrn( SCCOL nScCol, SCROW nScRow, const Any& rValue );
164 /** Returns true, if the passed value could be appended to this record. */
165 bool InsertValue( SCCOL nScCol, SCROW nScRow, const Any& rValue );
167 /** Writes the row and child elements. */
168 virtual void SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
170 private:
171 virtual void WriteBody( XclExpStream& rStrm ) SAL_OVERRIDE;
173 static void WriteBool( XclExpStream& rStrm, bool bValue );
174 static void WriteDouble( XclExpStream& rStrm, double fValue );
175 static void WriteString( XclExpStream& rStrm, const OUString& rValue );
176 static void WriteError( XclExpStream& rStrm, sal_uInt8 nErrCode );
177 static void WriteEmpty( XclExpStream& rStrm );
179 private:
180 typedef ::std::vector< Any > CachedValues;
182 CachedValues maValues; /// All cached values.
183 SCCOL mnScCol; /// Column index of the first external cell.
184 SCROW mnScRow; /// Row index of the external cells.
187 namespace { class XclExpCrnList; }
189 /** Represents the record XCT which is the header record of a CRN record list.
191 class XclExpXct : public XclExpRecordBase, protected XclExpRoot
193 public:
194 explicit XclExpXct( const XclExpRoot& rRoot,
195 const OUString& rTabName, sal_uInt16 nSBTab,
196 ScExternalRefCache::TableTypeRef xCacheTable );
198 /** Returns the external sheet name. */
199 inline const XclExpString& GetTabName() const { return maTabName; }
201 /** Stores all cells in the given range in the CRN list. */
202 void StoreCellRange( const ScRange& rRange );
204 void StoreCell( const ScAddress& rCell, const ::formula::FormulaToken& rToken );
205 void StoreCellRange( const ScRange& rRange, const ::formula::FormulaToken& rToken );
207 /** Writes the XCT and all CRN records. */
208 virtual void Save( XclExpStream& rStrm ) SAL_OVERRIDE;
210 /** Writes the sheetDataSet and child elements. */
211 virtual void SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
213 private:
214 ScExternalRefCache::TableTypeRef mxCacheTable;
215 ScMarkData maUsedCells; /// Contains addresses of all stored cells.
216 ScRange maBoundRange; /// Bounding box of maUsedCells.
217 XclExpString maTabName; /// Sheet name of the external sheet.
218 sal_uInt16 mnSBTab; /// Referred sheet index in SUPBOOK record.
220 /** Build the internal representation of records to be saved as BIFF or OOXML. */
221 bool BuildCrnList( XclExpCrnList& rCrnRecs );
224 // External documents (EXTERNSHEET/SUPBOOK), base class =======================
226 /** Base class for records representing external sheets/documents.
228 In BIFF5/BIFF7, this record is the EXTERNSHEET record containing one sheet
229 of the own or an external document. In BIFF8, this record is the SUPBOOK
230 record representing the entire own or external document with all referenced
231 sheets.
233 class XclExpExternSheetBase : public XclExpRecord, protected XclExpRoot
235 public:
236 explicit XclExpExternSheetBase( const XclExpRoot& rRoot,
237 sal_uInt16 nRecId, sal_uInt32 nRecSize = 0 );
239 protected:
240 /** Creates and returns the list of EXTERNNAME records. */
241 XclExpExtNameBuffer& GetExtNameBuffer();
242 /** Writes the list of EXTERNNAME records. */
243 void WriteExtNameBuffer( XclExpStream& rStrm );
244 /** Writes the list of externalName elements. */
245 void WriteExtNameBufferXml( XclExpXmlStream& rStrm );
247 protected:
248 typedef boost::shared_ptr< XclExpExtNameBuffer > XclExpExtNameBfrRef;
249 XclExpExtNameBfrRef mxExtNameBfr; /// List of EXTERNNAME records.
252 // External documents (EXTERNSHEET, BIFF5/BIFF7) ==============================
254 /** Represents an EXTERNSHEET record containing the URL and sheet name of a sheet.
255 @descr This class is used up to BIFF7 only, writing a BIFF8 EXTERNSHEET
256 record is implemented directly in the link manager. */
257 class XclExpExternSheet : public XclExpExternSheetBase
259 public:
260 /** Creates an EXTERNSHEET record containing a special code (i.e. own document or sheet). */
261 explicit XclExpExternSheet( const XclExpRoot& rRoot, sal_Unicode cCode );
262 /** Creates an EXTERNSHEET record referring to an internal sheet. */
263 explicit XclExpExternSheet( const XclExpRoot& rRoot, const OUString& rTabName );
265 /** Finds or inserts an EXTERNNAME record for add-ins.
266 @return The 1-based EXTERNNAME record index; or 0, if the record list is full. */
267 sal_uInt16 InsertAddIn( const OUString& rName );
269 /** Writes the EXTERNSHEET and all EXTERNNAME, XCT and CRN records. */
270 virtual void Save( XclExpStream& rStrm ) SAL_OVERRIDE;
272 private:
273 /** Initializes the record data with the passed encoded URL. */
274 void Init( const OUString& rEncUrl );
275 /** Writes the contents of the EXTERNSHEET record. */
276 virtual void WriteBody( XclExpStream& rStrm ) SAL_OVERRIDE;
278 private:
279 XclExpString maTabName; /// The name of the sheet.
282 // External documents (SUPBOOK, BIFF8) ========================================
284 /** The SUPBOOK record contains data for an external document (URL, sheet names, external values). */
285 class XclExpSupbook : public XclExpExternSheetBase
287 public:
288 /** Creates a SUPBOOK record for internal references. */
289 explicit XclExpSupbook( const XclExpRoot& rRoot, sal_uInt16 nXclTabCount );
290 /** Creates a SUPBOOK record for add-in functions. */
291 explicit XclExpSupbook( const XclExpRoot& rRoot );
292 /** EUROTOOL SUPBOOK */
293 explicit XclExpSupbook( const XclExpRoot& rRoot, const OUString& rUrl, XclSupbookType );
294 /** Creates a SUPBOOK record for an external document. */
295 explicit XclExpSupbook( const XclExpRoot& rRoot, const OUString& rUrl );
296 /** Creates a SUPBOOK record for a DDE link. */
297 explicit XclExpSupbook( const XclExpRoot& rRoot, const OUString& rApplic, const OUString& rTopic );
299 /** Returns true, if this SUPBOOK contains the passed URL of an external document. */
300 bool IsUrlLink( const OUString& rUrl ) const;
301 /** Returns true, if this SUPBOOK contains the passed DDE link. */
302 bool IsDdeLink( const OUString& rApplic, const OUString& rTopic ) const;
303 /** Fills the passed reference log entry with the URL and sheet names. */
304 void FillRefLogEntry( XclExpRefLogEntry& rRefLogEntry,
305 sal_uInt16 nFirstSBTab, sal_uInt16 nLastSBTab ) const;
307 /** Stores all cells in the given range in the CRN list of the specified SUPBOOK sheet. */
308 void StoreCellRange( const ScRange& rRange, sal_uInt16 nSBTab );
310 void StoreCell( sal_uInt16 nSBTab, const ScAddress& rCell, const ::formula::FormulaToken& rToken );
311 void StoreCellRange( sal_uInt16 nSBTab, const ScRange& rRange, const ::formula::FormulaToken& rToken );
313 sal_uInt16 GetTabIndex( const OUString& rTabName ) const;
314 sal_uInt16 GetTabCount() const;
316 /** Inserts a new sheet name into the SUPBOOK and returns the SUPBOOK internal sheet index. */
317 sal_uInt16 InsertTabName( const OUString& rTabName, ScExternalRefCache::TableTypeRef xCacheTable );
318 /** Finds or inserts an EXTERNNAME record for add-ins.
319 @return The 1-based EXTERNNAME record index; or 0, if the record list is full. */
320 sal_uInt16 InsertAddIn( const OUString& rName );
321 /** InsertEuroTool */
322 sal_uInt16 InsertEuroTool( const OUString& rName );
323 /** Finds or inserts an EXTERNNAME record for DDE links.
324 @return The 1-based EXTERNNAME record index; or 0, if the record list is full. */
325 sal_uInt16 InsertDde( const OUString& rItem );
327 sal_uInt16 InsertExtName( const OUString& rName, const ScExternalRefCache::TokenArrayRef& rArray );
329 /** Get the type of record. */
330 XclSupbookType GetType() const;
332 /** For references to an external document, 1-based OOXML file ID. */
333 sal_uInt16 GetFileId() const;
335 /** For references to an external document. */
336 const OUString& GetUrl() const;
338 /** Writes the SUPBOOK and all EXTERNNAME, XCT and CRN records. */
339 virtual void Save( XclExpStream& rStrm ) SAL_OVERRIDE;
341 /** Writes the externalBook and all child elements. */
342 virtual void SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
344 private:
345 /** Returns the sheet name inside of this SUPBOOK. */
346 const XclExpString* GetTabName( sal_uInt16 nSBTab ) const;
348 /** Writes the SUPBOOK record contents. */
349 virtual void WriteBody( XclExpStream& rStrm ) SAL_OVERRIDE;
351 private:
352 typedef XclExpRecordList< XclExpXct > XclExpXctList;
353 typedef XclExpXctList::RecordRefType XclExpXctRef;
355 XclExpXctList maXctList; /// List of XCT records (which contain CRN records).
356 OUString maUrl; /// URL of the external document or application name for DDE.
357 OUString maDdeTopic; /// Topic of an DDE link.
358 XclExpString maUrlEncoded; /// Document name encoded for Excel.
359 XclSupbookType meType; /// Type of this SUPBOOK record.
360 sal_uInt16 mnXclTabCount; /// Number of internal sheets.
361 sal_uInt16 mnFileId; /// 1-based external reference file ID for OOXML
364 // All SUPBOOKS in a document =================================================
366 /** This struct contains a sheet index range for 3D references.
367 @descr This reference consists of an index to a SUPBOOK record and indexes
368 to SUPBOOK sheet names. */
369 struct XclExpXti
371 sal_uInt16 mnSupbook; /// Index to SUPBOOK record.
372 sal_uInt16 mnFirstSBTab; /// Index to the first sheet of the range in the SUPBOOK.
373 sal_uInt16 mnLastSBTab; /// Index to the last sheet of the range in the SUPBOOK.
375 inline explicit XclExpXti() : mnSupbook( 0 ), mnFirstSBTab( 0 ), mnLastSBTab( 0 ) {}
376 inline explicit XclExpXti( sal_uInt16 nSupbook, sal_uInt16 nFirstSBTab, sal_uInt16 nLastSBTab ) :
377 mnSupbook( nSupbook ), mnFirstSBTab( nFirstSBTab ), mnLastSBTab( nLastSBTab ) {}
379 /** Writes this XTI structure (inside of the EXTERNSHEET record). */
380 inline void Save( XclExpStream& rStrm ) const
381 { rStrm << mnSupbook << mnFirstSBTab << mnLastSBTab; }
384 inline bool operator==( const XclExpXti& rLeft, const XclExpXti& rRight )
386 return
387 (rLeft.mnSupbook == rRight.mnSupbook) &&
388 (rLeft.mnFirstSBTab == rRight.mnFirstSBTab) &&
389 (rLeft.mnLastSBTab == rRight.mnLastSBTab);
392 /** Contains a list of all SUPBOOK records and index arrays of external sheets. */
393 class XclExpSupbookBuffer : public XclExpRecordBase, protected XclExpRoot
395 public:
396 explicit XclExpSupbookBuffer( const XclExpRoot& rRoot );
398 /** Finds SUPBOOK index and SUPBOOK sheet range from given Excel sheet range.
399 @return An XTI structure containing SUPBOOK and sheet indexes. */
400 XclExpXti GetXti( sal_uInt16 nFirstXclTab, sal_uInt16 nLastXclTab,
401 XclExpRefLogEntry* pRefLogEntry = 0 ) const;
403 /** Stores all cells in the given range in a CRN record list. */
404 void StoreCellRange( const ScRange& rRange );
406 void StoreCell( sal_uInt16 nFileId, const OUString& rTabName, const ScAddress& rCell );
407 void StoreCellRange( sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange );
409 /** Finds or inserts an EXTERNNAME record for an add-in function name.
410 @param rnSupbook Returns the index of the SUPBOOK record which contains the add-in function name.
411 @param rnExtName Returns the 1-based EXTERNNAME record index. */
412 bool InsertAddIn(
413 sal_uInt16& rnSupbook, sal_uInt16& rnExtName,
414 const OUString& rName );
415 /** InsertEuroTool */
416 bool InsertEuroTool(
417 sal_uInt16& rnSupbook, sal_uInt16& rnExtName,
418 const OUString& rName );
419 /** Finds or inserts an EXTERNNAME record for DDE links.
420 @param rnSupbook Returns the index of the SUPBOOK record which contains the DDE link.
421 @param rnExtName Returns the 1-based EXTERNNAME record index. */
422 bool InsertDde(
423 sal_uInt16& rnSupbook, sal_uInt16& rnExtName,
424 const OUString& rApplic, const OUString& rTopic, const OUString& rItem );
426 bool InsertExtName(
427 sal_uInt16& rnSupbook, sal_uInt16& rnExtName, const OUString& rUrl,
428 const OUString& rName, const ScExternalRefCache::TokenArrayRef& rArray );
430 XclExpXti GetXti( sal_uInt16 nFileId, const OUString& rTabName, sal_uInt16 nXclTabSpan,
431 XclExpRefLogEntry* pRefLogEntry = NULL );
433 /** Writes all SUPBOOK records with their sub records. */
434 virtual void Save( XclExpStream& rStrm ) SAL_OVERRIDE;
436 /** Writes all externalBook elements with their child elements to OOXML. */
437 virtual void SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
439 /** Whether we need to write externalReferences or not. */
440 bool HasExternalReferences() const;
442 struct XclExpSBIndex
444 sal_uInt16 mnSupbook; /// SUPBOOK index for an Excel sheet.
445 sal_uInt16 mnSBTab; /// Sheet name index in SUPBOOK for an Excel sheet.
446 inline void Set( sal_uInt16 nSupbook, sal_uInt16 nSBTab )
447 { mnSupbook = nSupbook; mnSBTab = nSBTab; }
449 typedef ::std::vector< XclExpSBIndex > XclExpSBIndexVec;
451 private:
452 typedef XclExpRecordList< XclExpSupbook > XclExpSupbookList;
453 typedef XclExpSupbookList::RecordRefType XclExpSupbookRef;
455 private:
456 /** Searches for the SUPBOOK record containing the passed document URL.
457 @param rxSupbook (out-param) Returns a reference to the SUPBOOK record, or 0.
458 @param rnIndex (out-param) Returns the list index, if the SUPBOOK exists.
459 @return True, if the SUPBOOK record exists (out-parameters are valid). */
460 bool GetSupbookUrl( XclExpSupbookRef& rxSupbook, sal_uInt16& rnIndex,
461 const OUString& rUrl ) const;
462 /** Searches for the SUPBOOK record containing the passed DDE link.
463 @param rxSupbook (out-param) Returns a reference to the SUPBOOK record, or 0.
464 @param rnIndex (out-param) Returns the list index, if the SUPBOOK exists.
465 @return True, if the SUPBOOK record exists (out-parameters are valid). */
466 bool GetSupbookDde( XclExpSupbookRef& rxSupbook, sal_uInt16& rnIndex,
467 const OUString& rApplic, const OUString& rTopic ) const;
469 /** Appends a new SUPBOOK to the list.
470 @return The list index of the SUPBOOK record. */
471 sal_uInt16 Append( XclExpSupbookRef xSupbook );
473 private:
474 XclExpSupbookList maSupbookList; /// List of all SUPBOOK records.
475 XclExpSBIndexVec maSBIndexVec; /// SUPBOOK and sheet name index for each Excel sheet.
476 sal_uInt16 mnOwnDocSB; /// Index to SUPBOOK for own document.
477 sal_uInt16 mnAddInSB; /// Index to add-in SUPBOOK.
480 // Export link manager ========================================================
482 /** Abstract base class for implementation classes of the link manager. */
483 class XclExpLinkManagerImpl : protected XclExpRoot
485 public:
486 /** Derived classes search for an EXTSHEET structure for the given Calc sheet range. */
487 virtual void FindExtSheet( sal_uInt16& rnExtSheet,
488 sal_uInt16& rnFirstXclTab, sal_uInt16& rnLastXclTab,
489 SCTAB nFirstScTab, SCTAB nLastScTab,
490 XclExpRefLogEntry* pRefLogEntry ) = 0;
491 /** Derived classes search for a special EXTERNSHEET index for the own document. */
492 virtual sal_uInt16 FindExtSheet( sal_Unicode cCode ) = 0;
494 virtual void FindExtSheet( sal_uInt16 nFileId, const OUString& rTabName, sal_uInt16 nXclTabSpan,
495 sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
496 XclExpRefLogEntry* pRefLogEntry ) = 0;
498 /** Derived classes store all cells in the given range in a CRN record list. */
499 virtual void StoreCellRange( const ScSingleRefData& rRef1, const ScSingleRefData& rRef2, const ScAddress& rPos ) = 0;
501 virtual void StoreCell( sal_uInt16 nFileId, const OUString& rTabName, const ScAddress& rPos ) = 0;
502 virtual void StoreCellRange( sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange ) = 0;
504 /** Derived classes find or insert an EXTERNNAME record for an add-in function name. */
505 virtual bool InsertAddIn(
506 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
507 const OUString& rName ) = 0;
508 /** InsertEuroTool */
509 virtual bool InsertEuroTool(
510 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
511 const OUString& rName ) = 0;
513 /** Derived classes find or insert an EXTERNNAME record for DDE links. */
514 virtual bool InsertDde(
515 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
516 const OUString& rApplic, const OUString& rTopic, const OUString& rItem ) = 0;
518 virtual bool InsertExtName(
519 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rUrl,
520 const OUString& rName, const ScExternalRefCache::TokenArrayRef& rArray ) = 0;
522 /** Derived classes write the entire link table to the passed stream. */
523 virtual void Save( XclExpStream& rStrm ) = 0;
525 /** Derived classes write the entire link table to the passed OOXML stream. */
526 virtual void SaveXml( XclExpXmlStream& rStrm ) = 0;
528 protected:
529 explicit XclExpLinkManagerImpl( const XclExpRoot& rRoot );
532 /** Implementation of the link manager for BIFF5/BIFF7. */
533 class XclExpLinkManagerImpl5 : public XclExpLinkManagerImpl
535 public:
536 explicit XclExpLinkManagerImpl5( const XclExpRoot& rRoot );
538 virtual void FindExtSheet( sal_uInt16& rnExtSheet,
539 sal_uInt16& rnFirstXclTab, sal_uInt16& rnLastXclTab,
540 SCTAB nFirstScTab, SCTAB nLastScTab,
541 XclExpRefLogEntry* pRefLogEntry ) SAL_OVERRIDE;
542 virtual sal_uInt16 FindExtSheet( sal_Unicode cCode ) SAL_OVERRIDE;
544 virtual void FindExtSheet( sal_uInt16 nFileId, const OUString& rTabName, sal_uInt16 nXclTabSpan,
545 sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
546 XclExpRefLogEntry* pRefLogEntry ) SAL_OVERRIDE;
548 virtual void StoreCellRange( const ScSingleRefData& rRef1, const ScSingleRefData& rRef2, const ScAddress& rPos ) SAL_OVERRIDE;
550 virtual void StoreCell( sal_uInt16 nFileId, const OUString& rTabName, const ScAddress& rPos ) SAL_OVERRIDE;
551 virtual void StoreCellRange( sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange ) SAL_OVERRIDE;
553 virtual bool InsertAddIn(
554 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
555 const OUString& rName ) SAL_OVERRIDE;
557 /** InsertEuroTool */
558 virtual bool InsertEuroTool(
559 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
560 const OUString& rName ) SAL_OVERRIDE;
562 virtual bool InsertDde(
563 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
564 const OUString& rApplic, const OUString& rTopic, const OUString& rItem ) SAL_OVERRIDE;
566 virtual bool InsertExtName(
567 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rUrl,
568 const OUString& rName, const ScExternalRefCache::TokenArrayRef& rArray ) SAL_OVERRIDE;
570 virtual void Save( XclExpStream& rStrm ) SAL_OVERRIDE;
572 virtual void SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
574 private:
575 typedef XclExpRecordList< XclExpExternSheet > XclExpExtSheetList;
576 typedef XclExpExtSheetList::RecordRefType XclExpExtSheetRef;
577 typedef ::std::map< SCTAB, sal_uInt16 > XclExpIntTabMap;
578 typedef ::std::map< sal_Unicode, sal_uInt16 > XclExpCodeMap;
580 private:
581 /** Returns the number of EXTERNSHEET records. */
582 sal_uInt16 GetExtSheetCount() const;
584 /** Appends an internal EXTERNSHEET record and returns the one-based index. */
585 sal_uInt16 AppendInternal( XclExpExtSheetRef xExtSheet );
586 /** Creates all EXTERNSHEET records for internal sheets on first call. */
587 void CreateInternal();
589 /** Returns the specified internal EXTERNSHEET record. */
590 XclExpExtSheetRef GetInternal( sal_uInt16 nExtSheet );
591 /** Returns the EXTERNSHEET index of an internal Calc sheet, or a deleted reference. */
592 XclExpExtSheetRef FindInternal( sal_uInt16& rnExtSheet, sal_uInt16& rnXclTab, SCTAB nScTab );
593 /** Finds or creates the EXTERNSHEET index of an internal special EXTERNSHEET. */
594 XclExpExtSheetRef FindInternal( sal_uInt16& rnExtSheet, sal_Unicode cCode );
596 private:
597 XclExpExtSheetList maExtSheetList; /// List with EXTERNSHEET records.
598 XclExpIntTabMap maIntTabMap; /// Maps internal Calc sheets to EXTERNSHEET records.
599 XclExpCodeMap maCodeMap; /// Maps special external codes to EXTERNSHEET records.
602 /** Implementation of the link manager for BIFF8 and OOXML. */
603 class XclExpLinkManagerImpl8 : public XclExpLinkManagerImpl
605 public:
606 explicit XclExpLinkManagerImpl8( const XclExpRoot& rRoot );
608 virtual void FindExtSheet( sal_uInt16& rnExtSheet,
609 sal_uInt16& rnFirstXclTab, sal_uInt16& rnLastXclTab,
610 SCTAB nFirstScTab, SCTAB nLastScTab,
611 XclExpRefLogEntry* pRefLogEntry ) SAL_OVERRIDE;
612 virtual sal_uInt16 FindExtSheet( sal_Unicode cCode ) SAL_OVERRIDE;
614 virtual void FindExtSheet( sal_uInt16 nFileId, const OUString& rTabName, sal_uInt16 nXclTabSpan,
615 sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
616 XclExpRefLogEntry* pRefLogEntry ) SAL_OVERRIDE;
618 virtual void StoreCellRange( const ScSingleRefData& rRef1, const ScSingleRefData& rRef2, const ScAddress& rPos ) SAL_OVERRIDE;
620 virtual void StoreCell( sal_uInt16 nFileId, const OUString& rTabName, const ScAddress& rPos ) SAL_OVERRIDE;
621 virtual void StoreCellRange( sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange ) SAL_OVERRIDE;
623 virtual bool InsertAddIn(
624 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
625 const OUString& rName ) SAL_OVERRIDE;
626 /** InsertEuroTool */
627 virtual bool InsertEuroTool(
628 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
629 const OUString& rName ) SAL_OVERRIDE;
631 virtual bool InsertDde(
632 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
633 const OUString& rApplic, const OUString& rTopic, const OUString& rItem ) SAL_OVERRIDE;
635 virtual bool InsertExtName(
636 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rUrl,
637 const OUString& rName, const ScExternalRefCache::TokenArrayRef& rArray ) SAL_OVERRIDE;
639 virtual void Save( XclExpStream& rStrm ) SAL_OVERRIDE;
641 virtual void SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
643 private:
644 /** Searches for or inserts a new XTI structure.
645 @return The 0-based list index of the XTI structure. */
646 sal_uInt16 InsertXti( const XclExpXti& rXti );
648 private:
649 typedef ::std::vector< XclExpXti > XclExpXtiVec;
651 XclExpSupbookBuffer maSBBuffer; /// List of all SUPBOOK records.
652 XclExpXtiVec maXtiVec; /// List of XTI structures for the EXTERNSHEET record.
655 // *** Implementation ***
657 // Excel sheet indexes ========================================================
659 const sal_uInt8 EXC_TABBUF_IGNORE = 0x01; /// Sheet will be ignored completely.
660 const sal_uInt8 EXC_TABBUF_EXTERN = 0x02; /// Sheet is linked externally.
661 const sal_uInt8 EXC_TABBUF_SKIPMASK = 0x0F; /// Sheet will be skipped, if any flag is set.
662 const sal_uInt8 EXC_TABBUF_VISIBLE = 0x10; /// Sheet is visible.
663 const sal_uInt8 EXC_TABBUF_SELECTED = 0x20; /// Sheet is selected.
664 const sal_uInt8 EXC_TABBUF_MIRRORED = 0x40; /// Sheet is mirrored (right-to-left).
666 XclExpTabInfo::XclExpTabInfo( const XclExpRoot& rRoot ) :
667 XclExpRoot( rRoot ),
668 mnScCnt( 0 ),
669 mnXclCnt( 0 ),
670 mnXclExtCnt( 0 ),
671 mnXclSelCnt( 0 ),
672 mnDisplXclTab( 0 ),
673 mnFirstVisXclTab( 0 )
675 ScDocument& rDoc = GetDoc();
676 ScExtDocOptions& rDocOpt = GetExtDocOptions();
678 mnScCnt = rDoc.GetTableCount();
680 SCTAB nScTab;
681 SCTAB nFirstVisScTab = SCTAB_INVALID; // first visible sheet
682 SCTAB nFirstExpScTab = SCTAB_INVALID; // first exported sheet
684 // --- initialize the flags in the index buffer ---
686 maTabInfoVec.resize( mnScCnt );
687 for( nScTab = 0; nScTab < mnScCnt; ++nScTab )
689 // ignored sheets (skipped by export, with invalid Excel sheet index)
690 if( rDoc.IsScenario( nScTab ) )
692 SetFlag( nScTab, EXC_TABBUF_IGNORE );
695 // external sheets (skipped, but with valid Excel sheet index for ref's)
696 else if( rDoc.GetLinkMode( nScTab ) == SC_LINK_VALUE )
698 SetFlag( nScTab, EXC_TABBUF_EXTERN );
701 // exported sheets
702 else
704 // sheet name
705 rDoc.GetName( nScTab, maTabInfoVec[ nScTab ].maScName );
707 // remember first exported sheet
708 if( nFirstExpScTab == SCTAB_INVALID )
709 nFirstExpScTab = nScTab;
710 // remember first visible exported sheet
711 if( (nFirstVisScTab == SCTAB_INVALID) && rDoc.IsVisible( nScTab ) )
712 nFirstVisScTab = nScTab;
714 // sheet visible (only exported sheets)
715 SetFlag( nScTab, EXC_TABBUF_VISIBLE, rDoc.IsVisible( nScTab ) );
717 // sheet selected (only exported sheets)
718 if( const ScExtTabSettings* pTabSett = rDocOpt.GetTabSettings( nScTab ) )
719 SetFlag( nScTab, EXC_TABBUF_SELECTED, pTabSett->mbSelected );
721 // sheet mirrored (only exported sheets)
722 SetFlag( nScTab, EXC_TABBUF_MIRRORED, rDoc.IsLayoutRTL( nScTab ) );
726 // --- visible/selected sheets ---
728 SCTAB nDisplScTab = rDocOpt.GetDocSettings().mnDisplTab;
730 // find first visible exported sheet
731 if( (nFirstVisScTab == SCTAB_INVALID) || !IsExportTab( nFirstVisScTab ) )
733 // no exportable visible sheet -> use first exportable sheet
734 nFirstVisScTab = nFirstExpScTab;
735 if( (nFirstVisScTab == SCTAB_INVALID) || !IsExportTab( nFirstVisScTab ) )
737 // no exportable sheet at all -> use active sheet and export it
738 nFirstVisScTab = nDisplScTab;
739 SetFlag( nFirstVisScTab, EXC_TABBUF_SKIPMASK, false ); // clear skip flags
741 SetFlag( nFirstVisScTab, EXC_TABBUF_VISIBLE ); // must be visible, even if originally hidden
744 // find currently displayed sheet
745 if( !IsExportTab( nDisplScTab ) ) // selected sheet not exported (i.e. scenario) -> use first visible
746 nDisplScTab = nFirstVisScTab;
747 SetFlag( nDisplScTab, EXC_TABBUF_VISIBLE | EXC_TABBUF_SELECTED );
749 // number of selected sheets
750 for( nScTab = 0; nScTab < mnScCnt; ++nScTab )
751 if( IsSelectedTab( nScTab ) )
752 ++mnXclSelCnt;
754 // --- calculate resulting Excel sheet indexes ---
756 CalcXclIndexes();
757 mnFirstVisXclTab = GetXclTab( nFirstVisScTab );
758 mnDisplXclTab = GetXclTab( nDisplScTab );
760 // --- sorted vectors for index lookup ---
762 CalcSortedIndexes();
765 bool XclExpTabInfo::IsExportTab( SCTAB nScTab ) const
767 /* Check sheet index before to avoid assertion in GetFlag(). */
768 return (nScTab < mnScCnt && nScTab >= 0) && !GetFlag( nScTab, EXC_TABBUF_SKIPMASK );
771 bool XclExpTabInfo::IsExternalTab( SCTAB nScTab ) const
773 /* Check sheet index before to avoid assertion (called from formula
774 compiler also for deleted references). */
775 return (nScTab < mnScCnt && nScTab >= 0) && GetFlag( nScTab, EXC_TABBUF_EXTERN );
778 bool XclExpTabInfo::IsVisibleTab( SCTAB nScTab ) const
780 return GetFlag( nScTab, EXC_TABBUF_VISIBLE );
783 bool XclExpTabInfo::IsSelectedTab( SCTAB nScTab ) const
785 return GetFlag( nScTab, EXC_TABBUF_SELECTED );
788 bool XclExpTabInfo::IsDisplayedTab( SCTAB nScTab ) const
790 OSL_ENSURE( nScTab < mnScCnt && nScTab >= 0, "XclExpTabInfo::IsActiveTab - sheet out of range" );
791 return GetXclTab( nScTab ) == mnDisplXclTab;
794 bool XclExpTabInfo::IsMirroredTab( SCTAB nScTab ) const
796 return GetFlag( nScTab, EXC_TABBUF_MIRRORED );
799 OUString XclExpTabInfo::GetScTabName( SCTAB nScTab ) const
801 OSL_ENSURE( nScTab < mnScCnt && nScTab >= 0, "XclExpTabInfo::IsActiveTab - sheet out of range" );
802 return (nScTab < mnScCnt && nScTab >= 0) ? maTabInfoVec[ nScTab ].maScName : OUString();
805 sal_uInt16 XclExpTabInfo::GetXclTab( SCTAB nScTab ) const
807 return (nScTab < mnScCnt && nScTab >= 0) ? maTabInfoVec[ nScTab ].mnXclTab : EXC_TAB_DELETED;
810 SCTAB XclExpTabInfo::GetRealScTab( SCTAB nSortedScTab ) const
812 OSL_ENSURE( nSortedScTab < mnScCnt && nSortedScTab >= 0, "XclExpTabInfo::GetRealScTab - sheet out of range" );
813 return (nSortedScTab < mnScCnt && nSortedScTab >= 0) ? maFromSortedVec[ nSortedScTab ] : SCTAB_INVALID;
816 bool XclExpTabInfo::GetFlag( SCTAB nScTab, sal_uInt8 nFlags ) const
818 OSL_ENSURE( nScTab < mnScCnt && nScTab >= 0, "XclExpTabInfo::GetFlag - sheet out of range" );
819 return (nScTab < mnScCnt && nScTab >= 0) && ::get_flag( maTabInfoVec[ nScTab ].mnFlags, nFlags );
822 void XclExpTabInfo::SetFlag( SCTAB nScTab, sal_uInt8 nFlags, bool bSet )
824 OSL_ENSURE( nScTab < mnScCnt && nScTab >= 0, "XclExpTabInfo::SetFlag - sheet out of range" );
825 if( nScTab < mnScCnt && nScTab >= 0 )
826 ::set_flag( maTabInfoVec[ nScTab ].mnFlags, nFlags, bSet );
829 void XclExpTabInfo::CalcXclIndexes()
831 sal_uInt16 nXclTab = 0;
832 SCTAB nScTab = 0;
834 // --- pass 1: process regular sheets ---
835 for( nScTab = 0; nScTab < mnScCnt; ++nScTab )
837 if( IsExportTab( nScTab ) )
839 maTabInfoVec[ nScTab ].mnXclTab = nXclTab;
840 ++nXclTab;
842 else
843 maTabInfoVec[ nScTab ].mnXclTab = EXC_TAB_DELETED;
845 mnXclCnt = nXclTab;
847 // --- pass 2: process external sheets (nXclTab continues) ---
848 for( nScTab = 0; nScTab < mnScCnt; ++nScTab )
850 if( IsExternalTab( nScTab ) )
852 maTabInfoVec[ nScTab ].mnXclTab = nXclTab;
853 ++nXclTab;
854 ++mnXclExtCnt;
858 // result: first occur all exported sheets, followed by all external sheets
861 typedef ::std::pair< OUString, SCTAB > XclExpTabName;
862 typedef ::std::vector< XclExpTabName > XclExpTabNameVec;
864 struct XclExpTabNameSort {
865 bool operator ()( const XclExpTabName& rArg1, const XclExpTabName& rArg2 )
867 // compare the sheet names only
868 return ScGlobal::GetCollator()->compareString( rArg1.first, rArg2.first ) < 0;
872 void XclExpTabInfo::CalcSortedIndexes()
874 ScDocument& rDoc = GetDoc();
875 XclExpTabNameVec aVec( mnScCnt );
876 SCTAB nScTab;
878 // fill with sheet names
879 for( nScTab = 0; nScTab < mnScCnt; ++nScTab )
881 rDoc.GetName( nScTab, aVec[ nScTab ].first );
882 aVec[ nScTab ].second = nScTab;
884 ::std::sort( aVec.begin(), aVec.end(), XclExpTabNameSort() );
886 // fill index vectors from sorted sheet name vector
887 maFromSortedVec.resize( mnScCnt );
888 maToSortedVec.resize( mnScCnt );
889 for( nScTab = 0; nScTab < mnScCnt; ++nScTab )
891 maFromSortedVec[ nScTab ] = aVec[ nScTab ].second;
892 maToSortedVec[ aVec[ nScTab ].second ] = nScTab;
896 // External names =============================================================
898 XclExpExtNameBase::XclExpExtNameBase(
899 const XclExpRoot& rRoot, const OUString& rName, sal_uInt16 nFlags ) :
900 XclExpRecord( EXC_ID_EXTERNNAME ),
901 XclExpRoot( rRoot ),
902 maName( rName ),
903 mxName( XclExpStringHelper::CreateString( rRoot, rName, EXC_STR_8BITLENGTH ) ),
904 mnFlags( nFlags )
906 OSL_ENSURE( maName.getLength() <= 255, "XclExpExtNameBase::XclExpExtNameBase - string too long" );
907 SetRecSize( 6 + mxName->GetSize() );
910 XclExpExtNameBase::~XclExpExtNameBase()
914 void XclExpExtNameBase::WriteBody( XclExpStream& rStrm )
916 rStrm << mnFlags
917 << sal_uInt32( 0 )
918 << *mxName;
919 WriteAddData( rStrm );
922 void XclExpExtNameBase::WriteAddData( XclExpStream& /*rStrm*/ )
926 XclExpExtNameAddIn::XclExpExtNameAddIn( const XclExpRoot& rRoot, const OUString& rName ) :
927 XclExpExtNameBase( rRoot, rName )
929 AddRecSize( 4 );
932 void XclExpExtNameAddIn::WriteAddData( XclExpStream& rStrm )
934 // write a #REF! error formula
935 rStrm << sal_uInt16( 2 ) << EXC_TOKID_ERR << EXC_ERR_REF;
938 XclExpExtNameDde::XclExpExtNameDde( const XclExpRoot& rRoot,
939 const OUString& rName, sal_uInt16 nFlags, const ScMatrix* pResults ) :
940 XclExpExtNameBase( rRoot, rName, nFlags )
942 if( pResults )
944 mxMatrix.reset( new XclExpCachedMatrix( *pResults ) );
945 AddRecSize( mxMatrix->GetSize() );
949 void XclExpExtNameDde::WriteAddData( XclExpStream& rStrm )
951 if( mxMatrix )
952 mxMatrix->Save( rStrm );
955 XclExpExtName::XclExpExtName( const XclExpRoot& rRoot, const XclExpSupbook& rSupbook,
956 const OUString& rName, const ScExternalRefCache::TokenArrayRef& rArray ) :
957 XclExpExtNameBase( rRoot, rName ),
958 mrSupbook(rSupbook),
959 mpArray(rArray->Clone())
963 void XclExpExtName::WriteAddData( XclExpStream& rStrm )
965 // Write only if it only has a single token that is either a cell or cell
966 // range address. Excel just writes '02 00 1C 17' for all the other types
967 // of external names.
969 using namespace ::formula;
972 if (mpArray->GetLen() != 1)
973 break;
975 const formula::FormulaToken* p = mpArray->First();
976 if (!p->IsExternalRef())
977 break;
979 switch (p->GetType())
981 case svExternalSingleRef:
983 const ScSingleRefData& rRef = *p->GetSingleRef();
984 if (rRef.IsTabRel())
985 break;
987 bool bColRel = rRef.IsColRel();
988 bool bRowRel = rRef.IsRowRel();
989 sal_uInt16 nCol = static_cast<sal_uInt16>(rRef.Col());
990 sal_uInt16 nRow = static_cast<sal_uInt16>(rRef.Row());
991 if (bColRel) nCol |= 0x4000;
992 if (bRowRel) nCol |= 0x8000;
994 OUString aTabName = p->GetString().getString();
995 sal_uInt16 nSBTab = mrSupbook.GetTabIndex(aTabName);
997 // size is always 9
998 rStrm << static_cast<sal_uInt16>(9);
999 // operator token (3A for cell reference)
1000 rStrm << static_cast<sal_uInt8>(0x3A);
1001 // cell address (Excel's address has 2 sheet IDs.)
1002 rStrm << nSBTab << nSBTab << nRow << nCol;
1003 return;
1005 case svExternalDoubleRef:
1007 const ScComplexRefData& rRef = *p->GetDoubleRef();
1008 const ScSingleRefData& r1 = rRef.Ref1;
1009 const ScSingleRefData& r2 = rRef.Ref2;
1010 if (r1.IsTabRel() || r2.IsTabRel())
1011 break;
1013 sal_uInt16 nTab1 = r1.Tab();
1014 sal_uInt16 nTab2 = r2.Tab();
1015 bool bCol1Rel = r1.IsColRel();
1016 bool bRow1Rel = r1.IsRowRel();
1017 bool bCol2Rel = r2.IsColRel();
1018 bool bRow2Rel = r2.IsRowRel();
1020 sal_uInt16 nCol1 = static_cast<sal_uInt16>(r1.Col());
1021 sal_uInt16 nCol2 = static_cast<sal_uInt16>(r2.Col());
1022 sal_uInt16 nRow1 = static_cast<sal_uInt16>(r1.Row());
1023 sal_uInt16 nRow2 = static_cast<sal_uInt16>(r2.Row());
1024 if (bCol1Rel) nCol1 |= 0x4000;
1025 if (bRow1Rel) nCol1 |= 0x8000;
1026 if (bCol2Rel) nCol2 |= 0x4000;
1027 if (bRow2Rel) nCol2 |= 0x8000;
1029 OUString aTabName = p->GetString().getString();
1030 sal_uInt16 nSBTab = mrSupbook.GetTabIndex(aTabName);
1032 // size is always 13 (0x0D)
1033 rStrm << static_cast<sal_uInt16>(13);
1034 // operator token (3B for area reference)
1035 rStrm << static_cast<sal_uInt8>(0x3B);
1036 // range (area) address
1037 sal_uInt16 nSBTab2 = nSBTab + nTab2 - nTab1;
1038 rStrm << nSBTab << nSBTab2 << nRow1 << nRow2 << nCol1 << nCol2;
1039 return;
1041 default:
1042 ; // nothing
1045 while (false);
1047 // special value for #REF! (02 00 1C 17)
1048 rStrm << static_cast<sal_uInt16>(2) << EXC_TOKID_ERR << EXC_ERR_REF;
1051 void XclExpExtName::SaveXml(XclExpXmlStream& rStrm)
1053 sax_fastparser::FSHelperPtr pExternalLink = rStrm.GetCurrentStream();
1055 pExternalLink->startElement(XML_definedName,
1056 XML_name, XclXmlUtils::ToOString(maName).getStr(),
1057 XML_refersTo, NULL,
1058 XML_sheetId, NULL,
1059 FSEND);
1061 pExternalLink->endElement(XML_definedName);
1064 // List of external names =====================================================
1066 XclExpExtNameBuffer::XclExpExtNameBuffer( const XclExpRoot& rRoot ) :
1067 XclExpRoot( rRoot )
1071 sal_uInt16 XclExpExtNameBuffer::InsertAddIn( const OUString& rName )
1073 sal_uInt16 nIndex = GetIndex( rName );
1074 return nIndex ? nIndex : AppendNew( new XclExpExtNameAddIn( GetRoot(), rName ) );
1077 sal_uInt16 XclExpExtNameBuffer::InsertEuroTool( const OUString& rName )
1079 sal_uInt16 nIndex = GetIndex( rName );
1080 return nIndex ? nIndex : AppendNew( new XclExpExtNameBase( GetRoot(), rName ) );
1083 sal_uInt16 XclExpExtNameBuffer::InsertDde(
1084 const OUString& rApplic, const OUString& rTopic, const OUString& rItem )
1086 sal_uInt16 nIndex = GetIndex( rItem );
1087 if( nIndex == 0 )
1089 size_t nPos;
1090 if( GetDoc().FindDdeLink( rApplic, rTopic, rItem, SC_DDE_IGNOREMODE, nPos ) )
1092 // create the leading 'StdDocumentName' EXTERNNAME record
1093 if( maNameList.IsEmpty() )
1094 AppendNew( new XclExpExtNameDde(
1095 GetRoot(), OUString("StdDocumentName"), EXC_EXTN_EXPDDE_STDDOC ) );
1097 // try to find DDE result array, but create EXTERNNAME record without them too
1098 const ScMatrix* pScMatrix = GetDoc().GetDdeLinkResultMatrix( nPos );
1099 nIndex = AppendNew( new XclExpExtNameDde( GetRoot(), rItem, EXC_EXTN_EXPDDE, pScMatrix ) );
1102 return nIndex;
1105 sal_uInt16 XclExpExtNameBuffer::InsertExtName( const XclExpSupbook& rSupbook,
1106 const OUString& rName, const ScExternalRefCache::TokenArrayRef& rArray )
1108 sal_uInt16 nIndex = GetIndex( rName );
1109 return nIndex ? nIndex : AppendNew( new XclExpExtName( GetRoot(), rSupbook, rName, rArray ) );
1112 void XclExpExtNameBuffer::Save( XclExpStream& rStrm )
1114 maNameList.Save( rStrm );
1117 void XclExpExtNameBuffer::SaveXml(XclExpXmlStream& rStrm)
1119 maNameList.SaveXml(rStrm);
1122 sal_uInt16 XclExpExtNameBuffer::GetIndex( const OUString& rName ) const
1124 for( size_t nPos = 0, nSize = maNameList.GetSize(); nPos < nSize; ++nPos )
1125 if( maNameList.GetRecord( nPos )->GetName() == rName )
1126 return static_cast< sal_uInt16 >( nPos + 1 );
1127 return 0;
1130 sal_uInt16 XclExpExtNameBuffer::AppendNew( XclExpExtNameBase* pExtName )
1132 XclExpExtNameRef xExtName( pExtName );
1133 size_t nSize = maNameList.GetSize();
1134 if( nSize < 0x7FFF )
1136 maNameList.AppendRecord( xExtName );
1137 return static_cast< sal_uInt16 >( nSize + 1 );
1139 return 0;
1142 // Cached external cells ======================================================
1144 XclExpCrn::XclExpCrn( SCCOL nScCol, SCROW nScRow, const Any& rValue ) :
1145 XclExpRecord( EXC_ID_CRN, 4 ),
1146 mnScCol( nScCol ),
1147 mnScRow( nScRow )
1149 maValues.push_back( rValue );
1152 bool XclExpCrn::InsertValue( SCCOL nScCol, SCROW nScRow, const Any& rValue )
1154 if( (nScRow != mnScRow) || (nScCol != static_cast< SCCOL >( mnScCol + maValues.size() )) )
1155 return false;
1156 maValues.push_back( rValue );
1157 return true;
1160 void XclExpCrn::WriteBody( XclExpStream& rStrm )
1162 rStrm << static_cast< sal_uInt8 >( mnScCol + maValues.size() - 1 )
1163 << static_cast< sal_uInt8 >( mnScCol )
1164 << static_cast< sal_uInt16 >( mnScRow );
1165 for( CachedValues::iterator aIt = maValues.begin(), aEnd = maValues.end(); aIt != aEnd; ++aIt )
1167 if( aIt->has< bool >() )
1168 WriteBool( rStrm, aIt->get< bool >() );
1169 else if( aIt->has< double >() )
1170 WriteDouble( rStrm, aIt->get< double >() );
1171 else if( aIt->has< OUString >() )
1172 WriteString( rStrm, aIt->get< OUString >() );
1173 else
1174 WriteEmpty( rStrm );
1178 void XclExpCrn::WriteBool( XclExpStream& rStrm, bool bValue )
1180 rStrm << EXC_CACHEDVAL_BOOL << sal_uInt8( bValue ? 1 : 0);
1181 rStrm.WriteZeroBytes( 7 );
1184 void XclExpCrn::WriteDouble( XclExpStream& rStrm, double fValue )
1186 if( ::rtl::math::isNan( fValue ) )
1188 sal_uInt16 nScError = static_cast< sal_uInt16 >( reinterpret_cast< const sal_math_Double* >( &fValue )->nan_parts.fraction_lo );
1189 WriteError( rStrm, XclTools::GetXclErrorCode( nScError ) );
1191 else
1193 rStrm << EXC_CACHEDVAL_DOUBLE << fValue;
1197 void XclExpCrn::WriteString( XclExpStream& rStrm, const OUString& rValue )
1199 rStrm << EXC_CACHEDVAL_STRING << XclExpString( rValue );
1202 void XclExpCrn::WriteError( XclExpStream& rStrm, sal_uInt8 nErrCode )
1204 rStrm << EXC_CACHEDVAL_ERROR << nErrCode;
1205 rStrm.WriteZeroBytes( 7 );
1208 void XclExpCrn::WriteEmpty( XclExpStream& rStrm )
1210 rStrm << EXC_CACHEDVAL_EMPTY;
1211 rStrm.WriteZeroBytes( 8 );
1214 void XclExpCrn::SaveXml( XclExpXmlStream& rStrm )
1216 sax_fastparser::FSHelperPtr pFS = rStrm.GetCurrentStream();
1218 pFS->startElement( XML_row,
1219 XML_r, OString::number( mnScRow + 1 ).getStr(),
1220 FSEND);
1222 ScAddress aAdr( mnScCol, mnScRow, 0); // Tab number doesn't matter
1223 for( CachedValues::iterator aIt = maValues.begin(), aEnd = maValues.end(); aIt != aEnd; ++aIt, aAdr.IncCol() )
1225 if( aIt->has< double >() )
1227 double fVal = aIt->get< double >();
1228 if (rtl::math::isFinite( fVal))
1230 // t='n' is omitted
1231 pFS->startElement( XML_cell,
1232 XML_r, XclXmlUtils::ToOString( aAdr),
1233 FSEND);
1234 pFS->startElement( XML_v, FSEND );
1235 pFS->write( fVal );
1237 else
1239 pFS->startElement( XML_cell,
1240 XML_r, XclXmlUtils::ToOString( aAdr),
1241 XML_t, "e",
1242 FSEND);
1243 pFS->startElement( XML_v, FSEND );
1244 pFS->write( "#VALUE!" ); // OOXTODO: support other error values
1247 else if( aIt->has< OUString >() )
1249 pFS->startElement( XML_cell,
1250 XML_r, XclXmlUtils::ToOString( aAdr),
1251 XML_t, "str",
1252 FSEND);
1253 pFS->startElement( XML_v, FSEND );
1254 pFS->write( aIt->get< OUString >() );
1256 else if( aIt->has< bool >() )
1258 pFS->startElement( XML_cell,
1259 XML_r, XclXmlUtils::ToOString( aAdr),
1260 XML_t, "b",
1261 FSEND);
1262 pFS->startElement( XML_v, FSEND );
1263 pFS->write( aIt->get< bool >() ? "1" : "0" );
1265 // OOXTODO: error type cell t='e'
1266 else
1268 // Empty/blank cell not stored, only aAdr is incremented.
1270 pFS->endElement( XML_v );
1271 pFS->endElement( XML_cell);
1274 pFS->endElement( XML_row);
1277 // Cached cells of a sheet ====================================================
1279 XclExpXct::XclExpXct( const XclExpRoot& rRoot, const OUString& rTabName,
1280 sal_uInt16 nSBTab, ScExternalRefCache::TableTypeRef xCacheTable ) :
1281 XclExpRoot( rRoot ),
1282 mxCacheTable( xCacheTable ),
1283 maBoundRange( ScAddress::INITIALIZE_INVALID ),
1284 maTabName( rTabName ),
1285 mnSBTab( nSBTab )
1289 void XclExpXct::StoreCellRange( const ScRange& rRange )
1291 // #i70418# restrict size of external range to prevent memory overflow
1292 if( (rRange.aEnd.Col() - rRange.aStart.Col()) * (rRange.aEnd.Row() - rRange.aStart.Row()) > 1024 )
1293 return;
1295 maUsedCells.SetMultiMarkArea( rRange );
1296 maBoundRange.ExtendTo( rRange );
1299 void XclExpXct::StoreCell( const ScAddress& rCell, const ::formula::FormulaToken& rToken )
1301 maUsedCells.SetMultiMarkArea( ScRange( rCell ) );
1302 maBoundRange.ExtendTo( ScRange( rCell ) );
1303 (void)rToken;
1306 void XclExpXct::StoreCellRange( const ScRange& rRange, const ::formula::FormulaToken& rToken )
1308 maUsedCells.SetMultiMarkArea( rRange );
1309 maBoundRange.ExtendTo( rRange );
1310 (void)rToken;
1313 namespace {
1315 class XclExpCrnList : public XclExpRecordList< XclExpCrn >
1317 public:
1318 /** Inserts the passed value into an existing or new CRN record.
1319 @return True = value inserted successfully, false = CRN list is full. */
1320 bool InsertValue( SCCOL nScCol, SCROW nScRow, const Any& rValue );
1323 bool XclExpCrnList::InsertValue( SCCOL nScCol, SCROW nScRow, const Any& rValue )
1325 RecordRefType xLastRec = GetLastRecord();
1326 if( xLastRec && xLastRec->InsertValue( nScCol, nScRow, rValue ) )
1327 return true;
1328 if( GetSize() == SAL_MAX_UINT16 )
1329 return false;
1330 AppendNewRecord( new XclExpCrn( nScCol, nScRow, rValue ) );
1331 return true;
1334 } // namespace
1336 bool XclExpXct::BuildCrnList( XclExpCrnList& rCrnRecs )
1338 if( !mxCacheTable )
1339 return false;
1341 /* Get the range of used rows in the cache table. This may help to
1342 optimize building the CRN record list if the cache table does not
1343 contain all referred cells, e.g. if big empty ranges are used in the
1344 formulas. */
1345 ::std::pair< SCROW, SCROW > aRowRange = mxCacheTable->getRowRange();
1346 if( aRowRange.first >= aRowRange.second )
1347 return false;
1349 /* Crop the bounding range of used cells in this table to Excel limits.
1350 Return if there is no external cell inside these limits. */
1351 if( !GetAddressConverter().ValidateRange( maBoundRange, false ) )
1352 return false;
1354 /* Find the resulting row range that needs to be processed. */
1355 SCROW nScRow1 = ::std::max( aRowRange.first, maBoundRange.aStart.Row() );
1356 SCROW nScRow2 = ::std::min( aRowRange.second - 1, maBoundRange.aEnd.Row() );
1357 if( nScRow1 > nScRow2 )
1358 return false;
1360 /* Build and collect all CRN records before writing the XCT record. This
1361 is needed to determine the total number of CRN records which must be
1362 known when writing the XCT record (possibly encrypted, so seeking the
1363 output strem back after writing the CRN records is not an option). */
1364 SvNumberFormatter& rFormatter = GetFormatter();
1365 bool bValid = true;
1366 for( SCROW nScRow = nScRow1; bValid && (nScRow <= nScRow2); ++nScRow )
1368 ::std::pair< SCCOL, SCCOL > aColRange = mxCacheTable->getColRange( nScRow );
1369 const SCCOL nScEnd = ::std::min( aColRange.second, MAXCOLCOUNT );
1370 for( SCCOL nScCol = aColRange.first; bValid && (nScCol < nScEnd); ++nScCol )
1372 if( maUsedCells.IsCellMarked( nScCol, nScRow, true ) )
1374 sal_uInt32 nScNumFmt = 0;
1375 ScExternalRefCache::TokenRef xToken = mxCacheTable->getCell( nScCol, nScRow, &nScNumFmt );
1376 using namespace ::formula;
1377 if( xToken.get() ) switch( xToken->GetType() )
1379 case svDouble:
1380 bValid = (rFormatter.GetType( nScNumFmt ) == css::util::NumberFormat::LOGICAL) ?
1381 rCrnRecs.InsertValue( nScCol, nScRow, Any( xToken->GetDouble() != 0 ) ) :
1382 rCrnRecs.InsertValue( nScCol, nScRow, Any( xToken->GetDouble() ) );
1383 break;
1384 case svString:
1385 // do not save empty strings (empty cells) to cache
1386 if( !xToken->GetString().isEmpty() )
1387 bValid = rCrnRecs.InsertValue( nScCol, nScRow, Any( xToken->GetString().getString() ) );
1388 break;
1389 default:
1390 break;
1395 return true;
1398 void XclExpXct::Save( XclExpStream& rStrm )
1400 XclExpCrnList aCrnRecs;
1401 if (!BuildCrnList( aCrnRecs))
1402 return;
1404 // write the XCT record and the list of CRN records
1405 rStrm.StartRecord( EXC_ID_XCT, 4 );
1406 rStrm << static_cast< sal_uInt16 >( aCrnRecs.GetSize() ) << mnSBTab;
1407 rStrm.EndRecord();
1408 aCrnRecs.Save( rStrm );
1411 void XclExpXct::SaveXml( XclExpXmlStream& rStrm )
1413 XclExpCrnList aCrnRecs;
1415 sax_fastparser::FSHelperPtr pFS = rStrm.GetCurrentStream();
1417 bool bValid = BuildCrnList( aCrnRecs);
1418 pFS->startElement( XML_sheetData,
1419 XML_sheetId, OString::number( mnSBTab).getStr(),
1420 FSEND);
1421 if (bValid)
1423 // row elements
1424 aCrnRecs.SaveXml( rStrm );
1426 pFS->endElement( XML_sheetData);
1429 // External documents (EXTERNSHEET/SUPBOOK), base class =======================
1431 XclExpExternSheetBase::XclExpExternSheetBase( const XclExpRoot& rRoot, sal_uInt16 nRecId, sal_uInt32 nRecSize ) :
1432 XclExpRecord( nRecId, nRecSize ),
1433 XclExpRoot( rRoot )
1437 XclExpExtNameBuffer& XclExpExternSheetBase::GetExtNameBuffer()
1439 if( !mxExtNameBfr )
1440 mxExtNameBfr.reset( new XclExpExtNameBuffer( GetRoot() ) );
1441 return *mxExtNameBfr;
1444 void XclExpExternSheetBase::WriteExtNameBuffer( XclExpStream& rStrm )
1446 if( mxExtNameBfr )
1447 mxExtNameBfr->Save( rStrm );
1450 void XclExpExternSheetBase::WriteExtNameBufferXml( XclExpXmlStream& rStrm )
1452 if( mxExtNameBfr )
1453 mxExtNameBfr->SaveXml( rStrm );
1456 // External documents (EXTERNSHEET, BIFF5/BIFF7) ==============================
1458 XclExpExternSheet::XclExpExternSheet( const XclExpRoot& rRoot, sal_Unicode cCode ) :
1459 XclExpExternSheetBase( rRoot, EXC_ID_EXTERNSHEET )
1461 Init( OUString(cCode) );
1464 XclExpExternSheet::XclExpExternSheet( const XclExpRoot& rRoot, const OUString& rTabName ) :
1465 XclExpExternSheetBase( rRoot, EXC_ID_EXTERNSHEET )
1467 // reference to own sheet: \03<sheetname>
1468 Init(OUStringLiteral1<EXC_EXTSH_TABNAME>() + rTabName);
1471 void XclExpExternSheet::Save( XclExpStream& rStrm )
1473 // EXTERNSHEET record
1474 XclExpRecord::Save( rStrm );
1475 // EXTERNNAME records
1476 WriteExtNameBuffer( rStrm );
1479 void XclExpExternSheet::Init( const OUString& rEncUrl )
1481 OSL_ENSURE_BIFF( GetBiff() <= EXC_BIFF5 );
1482 maTabName.AssignByte( rEncUrl, GetTextEncoding(), EXC_STR_8BITLENGTH );
1483 SetRecSize( maTabName.GetSize() );
1486 sal_uInt16 XclExpExternSheet::InsertAddIn( const OUString& rName )
1488 return GetExtNameBuffer().InsertAddIn( rName );
1491 void XclExpExternSheet::WriteBody( XclExpStream& rStrm )
1493 sal_uInt8 nNameSize = static_cast< sal_uInt8 >( maTabName.Len() );
1494 // special case: reference to own sheet (starting with '\03') needs wrong string length
1495 if( maTabName.GetChar( 0 ) == EXC_EXTSH_TABNAME )
1496 --nNameSize;
1497 rStrm << nNameSize;
1498 maTabName.WriteBuffer( rStrm );
1501 // External document (SUPBOOK, BIFF8) =========================================
1503 XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, sal_uInt16 nXclTabCount ) :
1504 XclExpExternSheetBase( rRoot, EXC_ID_SUPBOOK, 4 ),
1505 meType( EXC_SBTYPE_SELF ),
1506 mnXclTabCount( nXclTabCount ),
1507 mnFileId( 0 )
1511 XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot ) :
1512 XclExpExternSheetBase( rRoot, EXC_ID_SUPBOOK, 4 ),
1513 meType( EXC_SBTYPE_ADDIN ),
1514 mnXclTabCount( 1 ),
1515 mnFileId( 0 )
1519 XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, const OUString& rUrl, XclSupbookType ) :
1520 XclExpExternSheetBase( rRoot, EXC_ID_SUPBOOK ),
1521 maUrl( rUrl ),
1522 maUrlEncoded( rUrl ),
1523 meType( EXC_SBTYPE_EUROTOOL ),
1524 mnXclTabCount( 0 ),
1525 mnFileId( 0 )
1527 SetRecSize( 2 + maUrlEncoded.GetSize() );
1530 XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, const OUString& rUrl ) :
1531 XclExpExternSheetBase( rRoot, EXC_ID_SUPBOOK ),
1532 maUrl( rUrl ),
1533 maUrlEncoded( XclExpUrlHelper::EncodeUrl( rRoot, rUrl ) ),
1534 meType( EXC_SBTYPE_EXTERN ),
1535 mnXclTabCount( 0 ),
1536 mnFileId( 0 )
1538 SetRecSize( 2 + maUrlEncoded.GetSize() );
1540 // We need to create all tables up front to ensure the correct table order.
1541 ScExternalRefManager* pRefMgr = rRoot.GetDoc().GetExternalRefManager();
1542 sal_uInt16 nFileId = pRefMgr->getExternalFileId( rUrl );
1543 mnFileId = nFileId + 1;
1544 ScfStringVec aTabNames;
1545 pRefMgr->getAllCachedTableNames( nFileId, aTabNames );
1546 for( ScfStringVec::const_iterator aBeg = aTabNames.begin(), aIt = aBeg, aEnd = aTabNames.end(); aIt != aEnd; ++aIt )
1547 InsertTabName( *aIt, pRefMgr->getCacheTable( nFileId, aIt - aBeg ) );
1550 XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, const OUString& rApplic, const OUString& rTopic ) :
1551 XclExpExternSheetBase( rRoot, EXC_ID_SUPBOOK, 4 ),
1552 maUrl( rApplic ),
1553 maDdeTopic( rTopic ),
1554 maUrlEncoded( XclExpUrlHelper::EncodeDde( rApplic, rTopic ) ),
1555 meType( EXC_SBTYPE_SPECIAL ),
1556 mnXclTabCount( 0 ),
1557 mnFileId( 0 )
1559 SetRecSize( 2 + maUrlEncoded.GetSize() );
1562 bool XclExpSupbook::IsUrlLink( const OUString& rUrl ) const
1564 return (meType == EXC_SBTYPE_EXTERN || meType == EXC_SBTYPE_EUROTOOL) && (maUrl == rUrl);
1567 bool XclExpSupbook::IsDdeLink( const OUString& rApplic, const OUString& rTopic ) const
1569 return (meType == EXC_SBTYPE_SPECIAL) && (maUrl == rApplic) && (maDdeTopic == rTopic);
1572 void XclExpSupbook::FillRefLogEntry( XclExpRefLogEntry& rRefLogEntry,
1573 sal_uInt16 nFirstSBTab, sal_uInt16 nLastSBTab ) const
1575 rRefLogEntry.mpUrl = maUrlEncoded.IsEmpty() ? 0 : &maUrlEncoded;
1576 rRefLogEntry.mpFirstTab = GetTabName( nFirstSBTab );
1577 rRefLogEntry.mpLastTab = GetTabName( nLastSBTab );
1580 void XclExpSupbook::StoreCellRange( const ScRange& rRange, sal_uInt16 nSBTab )
1582 if( XclExpXct* pXct = maXctList.GetRecord( nSBTab ).get() )
1583 pXct->StoreCellRange( rRange );
1586 void XclExpSupbook::StoreCell( sal_uInt16 nSBTab, const ScAddress& rCell, const formula::FormulaToken& rToken )
1588 if( XclExpXct* pXct = maXctList.GetRecord( nSBTab ).get() )
1589 pXct->StoreCell( rCell, rToken );
1592 void XclExpSupbook::StoreCellRange( sal_uInt16 nSBTab, const ScRange& rRange, const formula::FormulaToken& rToken )
1594 // multi-table range is not allowed!
1595 if( rRange.aStart.Tab() == rRange.aEnd.Tab() )
1596 if( XclExpXct* pXct = maXctList.GetRecord( nSBTab ).get() )
1597 pXct->StoreCellRange( rRange, rToken );
1600 sal_uInt16 XclExpSupbook::GetTabIndex( const OUString& rTabName ) const
1602 XclExpString aXclName(rTabName);
1603 size_t nSize = maXctList.GetSize();
1604 for (size_t i = 0; i < nSize; ++i)
1606 XclExpXctRef aRec = maXctList.GetRecord(i);
1607 if (aXclName == aRec->GetTabName())
1608 return ulimit_cast<sal_uInt16>(i);
1610 return EXC_NOTAB;
1613 sal_uInt16 XclExpSupbook::GetTabCount() const
1615 return ulimit_cast<sal_uInt16>(maXctList.GetSize());
1618 sal_uInt16 XclExpSupbook::InsertTabName( const OUString& rTabName, ScExternalRefCache::TableTypeRef xCacheTable )
1620 OSL_ENSURE( meType == EXC_SBTYPE_EXTERN, "XclExpSupbook::InsertTabName - don't insert sheet names here" );
1621 sal_uInt16 nSBTab = ulimit_cast< sal_uInt16 >( maXctList.GetSize() );
1622 XclExpXctRef xXct( new XclExpXct( GetRoot(), rTabName, nSBTab, xCacheTable ) );
1623 AddRecSize( xXct->GetTabName().GetSize() );
1624 maXctList.AppendRecord( xXct );
1625 return nSBTab;
1628 sal_uInt16 XclExpSupbook::InsertAddIn( const OUString& rName )
1630 return GetExtNameBuffer().InsertAddIn( rName );
1633 sal_uInt16 XclExpSupbook::InsertEuroTool( const OUString& rName )
1635 return GetExtNameBuffer().InsertEuroTool( rName );
1638 sal_uInt16 XclExpSupbook::InsertDde( const OUString& rItem )
1640 return GetExtNameBuffer().InsertDde( maUrl, maDdeTopic, rItem );
1643 sal_uInt16 XclExpSupbook::InsertExtName( const OUString& rName, const ScExternalRefCache::TokenArrayRef& rArray )
1645 return GetExtNameBuffer().InsertExtName(*this, rName, rArray);
1648 XclSupbookType XclExpSupbook::GetType() const
1650 return meType;
1653 sal_uInt16 XclExpSupbook::GetFileId() const
1655 return mnFileId;
1658 const OUString& XclExpSupbook::GetUrl() const
1660 return maUrl;
1663 void XclExpSupbook::Save( XclExpStream& rStrm )
1665 // SUPBOOK record
1666 XclExpRecord::Save( rStrm );
1667 // XCT record, CRN records
1668 maXctList.Save( rStrm );
1669 // EXTERNNAME records
1670 WriteExtNameBuffer( rStrm );
1673 void XclExpSupbook::SaveXml( XclExpXmlStream& rStrm )
1675 sax_fastparser::FSHelperPtr pExternalLink = rStrm.GetCurrentStream();
1677 // Add relation for this stream, e.g. xl/externalLinks/_rels/externalLink1.xml.rels
1678 sal_uInt16 nLevel = 0;
1679 bool bRel = true;
1680 OUString sId = rStrm.addRelation( pExternalLink->getOutputStream(),
1681 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/externalLinkPath",
1682 XclExpHyperlink::BuildFileName( nLevel, bRel, maUrl, GetRoot(), true),
1683 true );
1685 pExternalLink->startElement( XML_externalLink,
1686 XML_xmlns, "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
1687 FSEND);
1689 pExternalLink->startElement( XML_externalBook,
1690 FSNS(XML_xmlns, XML_r), "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
1691 FSNS(XML_r, XML_id), XclXmlUtils::ToOString( sId ).getStr(),
1692 FSEND);
1694 if (!maXctList.IsEmpty())
1696 pExternalLink->startElement( XML_sheetNames, FSEND);
1697 for (size_t nPos = 0, nSize = maXctList.GetSize(); nPos < nSize; ++nPos)
1699 pExternalLink->singleElement( XML_sheetName,
1700 XML_val, XclXmlUtils::ToOString( maXctList.GetRecord( nPos )->GetTabName()).getStr(),
1701 FSEND);
1703 pExternalLink->endElement( XML_sheetNames);
1707 if (mxExtNameBfr)
1709 pExternalLink->startElement(XML_definedNames, FSEND);
1710 // externalName elements
1711 WriteExtNameBufferXml( rStrm );
1712 pExternalLink->endElement(XML_definedNames);
1715 if (!maXctList.IsEmpty())
1717 pExternalLink->startElement( XML_sheetDataSet, FSEND);
1719 // sheetData elements
1720 maXctList.SaveXml( rStrm );
1722 pExternalLink->endElement( XML_sheetDataSet);
1725 pExternalLink->endElement( XML_externalBook);
1726 pExternalLink->endElement( XML_externalLink);
1729 const XclExpString* XclExpSupbook::GetTabName( sal_uInt16 nSBTab ) const
1731 XclExpXctRef xXct = maXctList.GetRecord( nSBTab );
1732 return xXct ? &xXct->GetTabName() : 0;
1735 void XclExpSupbook::WriteBody( XclExpStream& rStrm )
1737 switch( meType )
1739 case EXC_SBTYPE_SELF:
1740 rStrm << mnXclTabCount << EXC_SUPB_SELF;
1741 break;
1742 case EXC_SBTYPE_EXTERN:
1743 case EXC_SBTYPE_SPECIAL:
1744 case EXC_SBTYPE_EUROTOOL:
1746 sal_uInt16 nCount = ulimit_cast< sal_uInt16 >( maXctList.GetSize() );
1747 rStrm << nCount << maUrlEncoded;
1749 for( size_t nPos = 0, nSize = maXctList.GetSize(); nPos < nSize; ++nPos )
1750 rStrm << maXctList.GetRecord( nPos )->GetTabName();
1752 break;
1753 case EXC_SBTYPE_ADDIN:
1754 rStrm << mnXclTabCount << EXC_SUPB_ADDIN;
1755 break;
1756 default:
1757 OSL_FAIL( "XclExpSupbook::WriteBody - unknown SUPBOOK type" );
1761 // All SUPBOOKS in a document =================================================
1763 XclExpSupbookBuffer::XclExpSupbookBuffer( const XclExpRoot& rRoot ) :
1764 XclExpRoot( rRoot ),
1765 mnOwnDocSB( SAL_MAX_UINT16 ),
1766 mnAddInSB( SAL_MAX_UINT16 )
1768 XclExpTabInfo& rTabInfo = GetTabInfo();
1769 sal_uInt16 nXclCnt = rTabInfo.GetXclTabCount();
1770 sal_uInt16 nCodeCnt = static_cast< sal_uInt16 >( GetExtDocOptions().GetCodeNameCount() );
1771 size_t nCount = nXclCnt + rTabInfo.GetXclExtTabCount();
1773 OSL_ENSURE( nCount > 0, "XclExpSupbookBuffer::XclExpSupbookBuffer - no sheets to export" );
1774 if( nCount )
1776 maSBIndexVec.resize( nCount );
1778 // self-ref SUPBOOK first of list
1779 XclExpSupbookRef xSupbook( new XclExpSupbook( GetRoot(), ::std::max( nXclCnt, nCodeCnt ) ) );
1780 mnOwnDocSB = Append( xSupbook );
1781 for( sal_uInt16 nXclTab = 0; nXclTab < nXclCnt; ++nXclTab )
1782 maSBIndexVec[ nXclTab ].Set( mnOwnDocSB, nXclTab );
1786 XclExpXti XclExpSupbookBuffer::GetXti( sal_uInt16 nFirstXclTab, sal_uInt16 nLastXclTab,
1787 XclExpRefLogEntry* pRefLogEntry ) const
1789 XclExpXti aXti;
1790 size_t nSize = maSBIndexVec.size();
1791 if( (nFirstXclTab < nSize) && (nLastXclTab < nSize) )
1793 // index of the SUPBOOK record
1794 aXti.mnSupbook = maSBIndexVec[ nFirstXclTab ].mnSupbook;
1796 // all sheets in the same supbook?
1797 bool bSameSB = true;
1798 for( sal_uInt16 nXclTab = nFirstXclTab + 1; bSameSB && (nXclTab <= nLastXclTab); ++nXclTab )
1800 bSameSB = maSBIndexVec[ nXclTab ].mnSupbook == aXti.mnSupbook;
1801 if( !bSameSB )
1802 nLastXclTab = nXclTab - 1;
1804 aXti.mnFirstSBTab = maSBIndexVec[ nFirstXclTab ].mnSBTab;
1805 aXti.mnLastSBTab = maSBIndexVec[ nLastXclTab ].mnSBTab;
1807 // fill external reference log entry (for change tracking)
1808 if( pRefLogEntry )
1810 pRefLogEntry->mnFirstXclTab = nFirstXclTab;
1811 pRefLogEntry->mnLastXclTab = nLastXclTab;
1812 XclExpSupbookRef xSupbook = maSupbookList.GetRecord( aXti.mnSupbook );
1813 if( xSupbook )
1814 xSupbook->FillRefLogEntry( *pRefLogEntry, aXti.mnFirstSBTab, aXti.mnLastSBTab );
1817 else
1819 // special range, i.e. for deleted sheets or add-ins
1820 aXti.mnSupbook = mnOwnDocSB;
1821 aXti.mnFirstSBTab = nFirstXclTab;
1822 aXti.mnLastSBTab = nLastXclTab;
1825 return aXti;
1828 void XclExpSupbookBuffer::StoreCellRange( const ScRange& rRange )
1830 sal_uInt16 nXclTab = GetTabInfo().GetXclTab( rRange.aStart.Tab() );
1831 if( nXclTab < maSBIndexVec.size() )
1833 const XclExpSBIndex& rSBIndex = maSBIndexVec[ nXclTab ];
1834 XclExpSupbookRef xSupbook = maSupbookList.GetRecord( rSBIndex.mnSupbook );
1835 OSL_ENSURE( xSupbook , "XclExpSupbookBuffer::StoreCellRange - missing SUPBOOK record" );
1836 if( xSupbook )
1837 xSupbook->StoreCellRange( rRange, rSBIndex.mnSBTab );
1841 namespace {
1843 class FindSBIndexEntry
1845 public:
1846 explicit FindSBIndexEntry(sal_uInt16 nSupbookId, sal_uInt16 nTabId) :
1847 mnSupbookId(nSupbookId), mnTabId(nTabId) {}
1849 bool operator()(const XclExpSupbookBuffer::XclExpSBIndex& r) const
1851 return mnSupbookId == r.mnSupbook && mnTabId == r.mnSBTab;
1854 private:
1855 sal_uInt16 mnSupbookId;
1856 sal_uInt16 mnTabId;
1861 void XclExpSupbookBuffer::StoreCell( sal_uInt16 nFileId, const OUString& rTabName, const ScAddress& rCell )
1863 ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager();
1864 const OUString* pUrl = pRefMgr->getExternalFileName(nFileId);
1865 if (!pUrl)
1866 return;
1868 XclExpSupbookRef xSupbook;
1869 sal_uInt16 nSupbookId;
1870 if (!GetSupbookUrl(xSupbook, nSupbookId, *pUrl))
1872 xSupbook.reset(new XclExpSupbook(GetRoot(), *pUrl));
1873 nSupbookId = Append(xSupbook);
1876 ScExternalRefCache::TokenRef pToken = pRefMgr->getSingleRefToken(nFileId, rTabName, rCell, NULL, NULL);
1877 if (!pToken.get())
1878 return;
1880 sal_uInt16 nSheetId = xSupbook->GetTabIndex(rTabName);
1881 if (nSheetId == EXC_NOTAB)
1882 // specified table name not found in this SUPBOOK.
1883 return;
1885 FindSBIndexEntry f(nSupbookId, nSheetId);
1886 if (::std::none_of(maSBIndexVec.begin(), maSBIndexVec.end(), f))
1888 maSBIndexVec.push_back(XclExpSBIndex());
1889 XclExpSBIndex& r = maSBIndexVec.back();
1890 r.mnSupbook = nSupbookId;
1891 r.mnSBTab = nSheetId;
1894 xSupbook->StoreCell(nSheetId, rCell, *pToken);
1897 void XclExpSupbookBuffer::StoreCellRange( sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange )
1899 ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager();
1900 const OUString* pUrl = pRefMgr->getExternalFileName(nFileId);
1901 if (!pUrl)
1902 return;
1904 XclExpSupbookRef xSupbook;
1905 sal_uInt16 nSupbookId;
1906 if (!GetSupbookUrl(xSupbook, nSupbookId, *pUrl))
1908 xSupbook.reset(new XclExpSupbook(GetRoot(), *pUrl));
1909 nSupbookId = Append(xSupbook);
1912 SCTAB nTabCount = rRange.aEnd.Tab() - rRange.aStart.Tab() + 1;
1914 // If this is a multi-table range, get token for each table.
1915 using namespace ::formula;
1916 vector<FormulaToken*> aMatrixList;
1917 aMatrixList.reserve(nTabCount);
1919 // This is a new'ed instance, so we must manage its life cycle here.
1920 ScExternalRefCache::TokenArrayRef pArray = pRefMgr->getDoubleRefTokens(nFileId, rTabName, rRange, NULL);
1921 if (!pArray.get())
1922 return;
1924 for (FormulaToken* p = pArray->First(); p; p = pArray->Next())
1926 if (p->GetType() == svMatrix)
1927 aMatrixList.push_back(p);
1928 else if (p->GetOpCode() != ocSep)
1930 // This is supposed to be ocSep!!!
1931 return;
1935 if (aMatrixList.size() != static_cast<size_t>(nTabCount))
1937 // matrix size mis-match !
1938 return;
1941 sal_uInt16 nFirstSheetId = xSupbook->GetTabIndex(rTabName);
1943 ScRange aRange(rRange);
1944 aRange.aStart.SetTab(0);
1945 aRange.aEnd.SetTab(0);
1946 for (SCTAB nTab = 0; nTab < nTabCount; ++nTab)
1948 sal_uInt16 nSheetId = nFirstSheetId + static_cast<sal_uInt16>(nTab);
1949 FindSBIndexEntry f(nSupbookId, nSheetId);
1950 if (::std::none_of(maSBIndexVec.begin(), maSBIndexVec.end(), f))
1952 maSBIndexVec.push_back(XclExpSBIndex());
1953 XclExpSBIndex& r = maSBIndexVec.back();
1954 r.mnSupbook = nSupbookId;
1955 r.mnSBTab = nSheetId;
1958 xSupbook->StoreCellRange(nSheetId, aRange, *aMatrixList[nTab]);
1962 bool XclExpSupbookBuffer::InsertAddIn(
1963 sal_uInt16& rnSupbook, sal_uInt16& rnExtName, const OUString& rName )
1965 XclExpSupbookRef xSupbook;
1966 if( mnAddInSB == SAL_MAX_UINT16 )
1968 xSupbook.reset( new XclExpSupbook( GetRoot() ) );
1969 mnAddInSB = Append( xSupbook );
1971 else
1972 xSupbook = maSupbookList.GetRecord( mnAddInSB );
1973 OSL_ENSURE( xSupbook, "XclExpSupbookBuffer::InsertAddin - missing add-in supbook" );
1974 rnSupbook = mnAddInSB;
1975 rnExtName = xSupbook->InsertAddIn( rName );
1976 return rnExtName > 0;
1979 bool XclExpSupbookBuffer::InsertEuroTool(
1980 sal_uInt16& rnSupbook, sal_uInt16& rnExtName, const OUString& rName )
1982 XclExpSupbookRef xSupbook;
1983 OUString aUrl( "\001\010EUROTOOL.XLA" );
1984 if( !GetSupbookUrl( xSupbook, rnSupbook, aUrl ) )
1986 xSupbook.reset( new XclExpSupbook( GetRoot(), aUrl, EXC_SBTYPE_EUROTOOL ) );
1987 rnSupbook = Append( xSupbook );
1989 rnExtName = xSupbook->InsertEuroTool( rName );
1990 return rnExtName > 0;
1993 bool XclExpSupbookBuffer::InsertDde(
1994 sal_uInt16& rnSupbook, sal_uInt16& rnExtName,
1995 const OUString& rApplic, const OUString& rTopic, const OUString& rItem )
1997 XclExpSupbookRef xSupbook;
1998 if( !GetSupbookDde( xSupbook, rnSupbook, rApplic, rTopic ) )
2000 xSupbook.reset( new XclExpSupbook( GetRoot(), rApplic, rTopic ) );
2001 rnSupbook = Append( xSupbook );
2003 rnExtName = xSupbook->InsertDde( rItem );
2004 return rnExtName > 0;
2007 bool XclExpSupbookBuffer::InsertExtName(
2008 sal_uInt16& rnSupbook, sal_uInt16& rnExtName, const OUString& rUrl,
2009 const OUString& rName, const ScExternalRefCache::TokenArrayRef& rArray )
2011 XclExpSupbookRef xSupbook;
2012 if (!GetSupbookUrl(xSupbook, rnSupbook, rUrl))
2014 xSupbook.reset( new XclExpSupbook(GetRoot(), rUrl) );
2015 rnSupbook = Append(xSupbook);
2017 rnExtName = xSupbook->InsertExtName(rName, rArray);
2018 return rnExtName > 0;
2021 XclExpXti XclExpSupbookBuffer::GetXti( sal_uInt16 nFileId, const OUString& rTabName, sal_uInt16 nXclTabSpan,
2022 XclExpRefLogEntry* pRefLogEntry )
2024 XclExpXti aXti(0, EXC_NOTAB, EXC_NOTAB);
2025 ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager();
2026 const OUString* pUrl = pRefMgr->getExternalFileName(nFileId);
2027 if (!pUrl)
2028 return aXti;
2030 XclExpSupbookRef xSupbook;
2031 sal_uInt16 nSupbookId;
2032 if (!GetSupbookUrl(xSupbook, nSupbookId, *pUrl))
2034 xSupbook.reset(new XclExpSupbook(GetRoot(), *pUrl));
2035 nSupbookId = Append(xSupbook);
2037 aXti.mnSupbook = nSupbookId;
2039 sal_uInt16 nFirstSheetId = xSupbook->GetTabIndex(rTabName);
2040 if (nFirstSheetId == EXC_NOTAB)
2042 // first sheet not found in SUPBOOK.
2043 return aXti;
2045 sal_uInt16 nSheetCount = xSupbook->GetTabCount();
2046 for (sal_uInt16 i = 0; i < nXclTabSpan; ++i)
2048 sal_uInt16 nSheetId = nFirstSheetId + i;
2049 if (nSheetId >= nSheetCount)
2050 return aXti;
2052 FindSBIndexEntry f(nSupbookId, nSheetId);
2053 if (::std::none_of(maSBIndexVec.begin(), maSBIndexVec.end(), f))
2055 maSBIndexVec.push_back(XclExpSBIndex());
2056 XclExpSBIndex& r = maSBIndexVec.back();
2057 r.mnSupbook = nSupbookId;
2058 r.mnSBTab = nSheetId;
2060 if (i == 0)
2061 aXti.mnFirstSBTab = nSheetId;
2062 if (i == nXclTabSpan - 1)
2063 aXti.mnLastSBTab = nSheetId;
2066 if (pRefLogEntry)
2068 pRefLogEntry->mnFirstXclTab = 0;
2069 pRefLogEntry->mnLastXclTab = 0;
2070 if (xSupbook)
2071 xSupbook->FillRefLogEntry(*pRefLogEntry, aXti.mnFirstSBTab, aXti.mnLastSBTab);
2074 return aXti;
2077 void XclExpSupbookBuffer::Save( XclExpStream& rStrm )
2079 maSupbookList.Save( rStrm );
2082 void XclExpSupbookBuffer::SaveXml( XclExpXmlStream& rStrm )
2084 ::std::map< sal_uInt16, OUString > aMap;
2085 for (size_t nPos = 0, nSize = maSupbookList.GetSize(); nPos < nSize; ++nPos)
2087 XclExpSupbookRef xRef( maSupbookList.GetRecord( nPos));
2088 if (xRef->GetType() != EXC_SBTYPE_EXTERN)
2089 continue; // handle only external reference (for now?)
2091 sal_uInt16 nId = xRef->GetFileId();
2092 const OUString& rUrl = xRef->GetUrl();
2093 ::std::pair< ::std::map< sal_uInt16, OUString >::iterator, bool > xInsert(
2094 aMap.insert( ::std::make_pair( nId, rUrl)));
2095 if (!xInsert.second)
2097 SAL_WARN( "sc.filter", "XclExpSupbookBuffer::SaveXml: file ID already used: " << nId <<
2098 " wanted for " << rUrl << " and is " << (*xInsert.first).second <<
2099 (rUrl == (*xInsert.first).second ? " multiple Supbook not supported" : ""));
2100 continue;
2103 OUString sId;
2104 sax_fastparser::FSHelperPtr pExternalLink = rStrm.CreateOutputStream(
2105 XclXmlUtils::GetStreamName( "xl/", "externalLinks/externalLink", nId),
2106 XclXmlUtils::GetStreamName( NULL, "externalLinks/externalLink", nId),
2107 rStrm.GetCurrentStream()->getOutputStream(),
2108 "application/vnd.openxmlformats-officedocument.spreadsheetml.externalLink+xml",
2109 CREATE_OFFICEDOC_RELATION_TYPE("externalLink"),
2110 &sId );
2112 // externalReference entry in workbook externalReferences
2113 rStrm.GetCurrentStream()->singleElement( XML_externalReference,
2114 FSNS( XML_r, XML_id ), XclXmlUtils::ToOString( sId ).getStr(),
2115 FSEND );
2117 // Each externalBook in a separate stream.
2118 rStrm.PushStream( pExternalLink );
2119 xRef->SaveXml( rStrm );
2120 rStrm.PopStream();
2124 bool XclExpSupbookBuffer::HasExternalReferences() const
2126 for (size_t nPos = 0, nSize = maSupbookList.GetSize(); nPos < nSize; ++nPos)
2128 if (maSupbookList.GetRecord( nPos)->GetType() == EXC_SBTYPE_EXTERN)
2129 return true;
2131 return false;
2134 bool XclExpSupbookBuffer::GetSupbookUrl(
2135 XclExpSupbookRef& rxSupbook, sal_uInt16& rnIndex, const OUString& rUrl ) const
2137 for( size_t nPos = 0, nSize = maSupbookList.GetSize(); nPos < nSize; ++nPos )
2139 rxSupbook = maSupbookList.GetRecord( nPos );
2140 if( rxSupbook->IsUrlLink( rUrl ) )
2142 rnIndex = ulimit_cast< sal_uInt16 >( nPos );
2143 return true;
2146 return false;
2149 bool XclExpSupbookBuffer::GetSupbookDde( XclExpSupbookRef& rxSupbook,
2150 sal_uInt16& rnIndex, const OUString& rApplic, const OUString& rTopic ) const
2152 for( size_t nPos = 0, nSize = maSupbookList.GetSize(); nPos < nSize; ++nPos )
2154 rxSupbook = maSupbookList.GetRecord( nPos );
2155 if( rxSupbook->IsDdeLink( rApplic, rTopic ) )
2157 rnIndex = ulimit_cast< sal_uInt16 >( nPos );
2158 return true;
2161 return false;
2164 sal_uInt16 XclExpSupbookBuffer::Append( XclExpSupbookRef xSupbook )
2166 maSupbookList.AppendRecord( xSupbook );
2167 return ulimit_cast< sal_uInt16 >( maSupbookList.GetSize() - 1 );
2170 // Export link manager ========================================================
2172 XclExpLinkManagerImpl::XclExpLinkManagerImpl( const XclExpRoot& rRoot ) :
2173 XclExpRoot( rRoot )
2177 XclExpLinkManagerImpl5::XclExpLinkManagerImpl5( const XclExpRoot& rRoot ) :
2178 XclExpLinkManagerImpl( rRoot )
2182 void XclExpLinkManagerImpl5::FindExtSheet(
2183 sal_uInt16& rnExtSheet, sal_uInt16& rnFirstXclTab, sal_uInt16& rnLastXclTab,
2184 SCTAB nFirstScTab, SCTAB nLastScTab, XclExpRefLogEntry* pRefLogEntry )
2186 FindInternal( rnExtSheet, rnFirstXclTab, nFirstScTab );
2187 if( (rnFirstXclTab == EXC_TAB_DELETED) || (nFirstScTab == nLastScTab) )
2189 rnLastXclTab = rnFirstXclTab;
2191 else
2193 sal_uInt16 nDummyExtSheet;
2194 FindInternal( nDummyExtSheet, rnLastXclTab, nLastScTab );
2197 (void)pRefLogEntry; // avoid compiler warning
2198 OSL_ENSURE( !pRefLogEntry, "XclExpLinkManagerImpl5::FindExtSheet - fill reflog entry not implemented" );
2201 sal_uInt16 XclExpLinkManagerImpl5::FindExtSheet( sal_Unicode cCode )
2203 sal_uInt16 nExtSheet;
2204 FindInternal( nExtSheet, cCode );
2205 return nExtSheet;
2208 void XclExpLinkManagerImpl5::FindExtSheet(
2209 sal_uInt16 /*nFileId*/, const OUString& /*rTabName*/, sal_uInt16 /*nXclTabSpan*/,
2210 sal_uInt16& /*rnExtSheet*/, sal_uInt16& /*rnFirstSBTab*/, sal_uInt16& /*rnLastSBTab*/,
2211 XclExpRefLogEntry* /*pRefLogEntry*/ )
2213 // not implemented
2216 void XclExpLinkManagerImpl5::StoreCellRange( const ScSingleRefData& /*rRef1*/, const ScSingleRefData& /*rRef2*/, const ScAddress& /*rPos*/ )
2218 // not implemented
2221 void XclExpLinkManagerImpl5::StoreCell( sal_uInt16 /*nFileId*/, const OUString& /*rTabName*/, const ScAddress& /*rPos*/ )
2223 // not implemented
2226 void XclExpLinkManagerImpl5::StoreCellRange( sal_uInt16 /*nFileId*/, const OUString& /*rTabName*/, const ScRange& /*rRange*/ )
2228 // not implemented
2231 bool XclExpLinkManagerImpl5::InsertAddIn(
2232 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rName )
2234 XclExpExtSheetRef xExtSheet = FindInternal( rnExtSheet, EXC_EXTSH_ADDIN );
2235 if( xExtSheet )
2237 rnExtName = xExtSheet->InsertAddIn( rName );
2238 return rnExtName > 0;
2240 return false;
2243 bool XclExpLinkManagerImpl5::InsertEuroTool(
2244 sal_uInt16& /*rnExtSheet*/, sal_uInt16& /*rnExtName*/, const OUString& /*rName*/ )
2246 return false;
2249 bool XclExpLinkManagerImpl5::InsertDde(
2250 sal_uInt16& /*rnExtSheet*/, sal_uInt16& /*rnExtName*/,
2251 const OUString& /*rApplic*/, const OUString& /*rTopic*/, const OUString& /*rItem*/ )
2253 // not implemented
2254 return false;
2257 bool XclExpLinkManagerImpl5::InsertExtName(
2258 sal_uInt16& /*rnExtSheet*/, sal_uInt16& /*rnExtName*/, const OUString& /*rUrl*/,
2259 const OUString& /*rName*/, const ScExternalRefCache::TokenArrayRef& /*rArray*/ )
2261 // not implemented
2262 return false;
2265 void XclExpLinkManagerImpl5::Save( XclExpStream& rStrm )
2267 if( sal_uInt16 nExtSheetCount = GetExtSheetCount() )
2269 // EXTERNCOUNT record
2270 XclExpUInt16Record( EXC_ID_EXTERNCOUNT, nExtSheetCount ).Save( rStrm );
2271 // list of EXTERNSHEET records with EXTERNNAME, XCT, CRN records
2272 maExtSheetList.Save( rStrm );
2276 void XclExpLinkManagerImpl5::SaveXml( XclExpXmlStream& /*rStrm*/ )
2278 // not applicable
2281 sal_uInt16 XclExpLinkManagerImpl5::GetExtSheetCount() const
2283 return static_cast< sal_uInt16 >( maExtSheetList.GetSize() );
2286 sal_uInt16 XclExpLinkManagerImpl5::AppendInternal( XclExpExtSheetRef xExtSheet )
2288 if( GetExtSheetCount() < 0x7FFF )
2290 maExtSheetList.AppendRecord( xExtSheet );
2291 // return negated one-based EXTERNSHEET index (i.e. 0xFFFD for 3rd record)
2292 return static_cast< sal_uInt16 >( -GetExtSheetCount() );
2294 return 0;
2297 void XclExpLinkManagerImpl5::CreateInternal()
2299 if( maIntTabMap.empty() )
2301 // create EXTERNSHEET records for all internal exported sheets
2302 XclExpTabInfo& rTabInfo = GetTabInfo();
2303 for( SCTAB nScTab = 0, nScCnt = rTabInfo.GetScTabCount(); nScTab < nScCnt; ++nScTab )
2305 if( rTabInfo.IsExportTab( nScTab ) )
2307 XclExpExtSheetRef xRec;
2308 if( nScTab == GetCurrScTab() )
2309 xRec.reset( new XclExpExternSheet( GetRoot(), EXC_EXTSH_OWNTAB ) );
2310 else
2311 xRec.reset( new XclExpExternSheet( GetRoot(), rTabInfo.GetScTabName( nScTab ) ) );
2312 maIntTabMap[ nScTab ] = AppendInternal( xRec );
2318 XclExpLinkManagerImpl5::XclExpExtSheetRef XclExpLinkManagerImpl5::GetInternal( sal_uInt16 nExtSheet )
2320 return maExtSheetList.GetRecord( static_cast< sal_uInt16 >( -nExtSheet - 1 ) );
2323 XclExpLinkManagerImpl5::XclExpExtSheetRef XclExpLinkManagerImpl5::FindInternal(
2324 sal_uInt16& rnExtSheet, sal_uInt16& rnXclTab, SCTAB nScTab )
2326 // create internal EXTERNSHEET records on demand
2327 CreateInternal();
2329 // try to find an EXTERNSHEET record - if not, return a "deleted sheet" reference
2330 XclExpExtSheetRef xExtSheet;
2331 XclExpIntTabMap::const_iterator aIt = maIntTabMap.find( nScTab );
2332 if( aIt == maIntTabMap.end() )
2334 xExtSheet = FindInternal( rnExtSheet, EXC_EXTSH_OWNDOC );
2335 rnXclTab = EXC_TAB_DELETED;
2337 else
2339 rnExtSheet = aIt->second;
2340 xExtSheet = GetInternal( rnExtSheet );
2341 rnXclTab = GetTabInfo().GetXclTab( nScTab );
2343 return xExtSheet;
2346 XclExpLinkManagerImpl5::XclExpExtSheetRef XclExpLinkManagerImpl5::FindInternal(
2347 sal_uInt16& rnExtSheet, sal_Unicode cCode )
2349 XclExpExtSheetRef xExtSheet;
2350 XclExpCodeMap::const_iterator aIt = maCodeMap.find( cCode );
2351 if( aIt == maCodeMap.end() )
2353 xExtSheet.reset( new XclExpExternSheet( GetRoot(), cCode ) );
2354 rnExtSheet = maCodeMap[ cCode ] = AppendInternal( xExtSheet );
2356 else
2358 rnExtSheet = aIt->second;
2359 xExtSheet = GetInternal( rnExtSheet );
2361 return xExtSheet;
2364 XclExpLinkManagerImpl8::XclExpLinkManagerImpl8( const XclExpRoot& rRoot ) :
2365 XclExpLinkManagerImpl( rRoot ),
2366 maSBBuffer( rRoot )
2370 void XclExpLinkManagerImpl8::FindExtSheet(
2371 sal_uInt16& rnExtSheet, sal_uInt16& rnFirstXclTab, sal_uInt16& rnLastXclTab,
2372 SCTAB nFirstScTab, SCTAB nLastScTab, XclExpRefLogEntry* pRefLogEntry )
2374 XclExpTabInfo& rTabInfo = GetTabInfo();
2375 rnFirstXclTab = rTabInfo.GetXclTab( nFirstScTab );
2376 rnLastXclTab = rTabInfo.GetXclTab( nLastScTab );
2377 rnExtSheet = InsertXti( maSBBuffer.GetXti( rnFirstXclTab, rnLastXclTab, pRefLogEntry ) );
2380 sal_uInt16 XclExpLinkManagerImpl8::FindExtSheet( sal_Unicode cCode )
2382 (void)cCode; // avoid compiler warning
2383 OSL_ENSURE( (cCode == EXC_EXTSH_OWNDOC) || (cCode == EXC_EXTSH_ADDIN),
2384 "XclExpLinkManagerImpl8::FindExtSheet - unknown externsheet code" );
2385 return InsertXti( maSBBuffer.GetXti( EXC_TAB_EXTERNAL, EXC_TAB_EXTERNAL ) );
2388 void XclExpLinkManagerImpl8::FindExtSheet(
2389 sal_uInt16 nFileId, const OUString& rTabName, sal_uInt16 nXclTabSpan,
2390 sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
2391 XclExpRefLogEntry* pRefLogEntry )
2393 XclExpXti aXti = maSBBuffer.GetXti(nFileId, rTabName, nXclTabSpan, pRefLogEntry);
2394 rnExtSheet = InsertXti(aXti);
2395 rnFirstSBTab = aXti.mnFirstSBTab;
2396 rnLastSBTab = aXti.mnLastSBTab;
2399 void XclExpLinkManagerImpl8::StoreCellRange( const ScSingleRefData& rRef1, const ScSingleRefData& rRef2, const ScAddress& rPos )
2401 ScAddress aAbs1 = rRef1.toAbs(rPos);
2402 ScAddress aAbs2 = rRef2.toAbs(rPos);
2403 if (!rRef1.IsDeleted() && !rRef2.IsDeleted() && (aAbs1.Tab() >= 0) && (aAbs2.Tab() >= 0))
2405 const XclExpTabInfo& rTabInfo = GetTabInfo();
2406 SCTAB nFirstScTab = aAbs1.Tab();
2407 SCTAB nLastScTab = aAbs2.Tab();
2408 ScRange aRange(aAbs1.Col(), aAbs1.Row(), 0, aAbs2.Col(), aAbs2.Row(), 0);
2409 for (SCTAB nScTab = nFirstScTab; nScTab <= nLastScTab; ++nScTab)
2411 if( rTabInfo.IsExternalTab( nScTab ) )
2413 aRange.aStart.SetTab( nScTab );
2414 aRange.aEnd.SetTab( nScTab );
2415 maSBBuffer.StoreCellRange( aRange );
2421 void XclExpLinkManagerImpl8::StoreCell( sal_uInt16 nFileId, const OUString& rTabName, const ScAddress& rPos )
2423 maSBBuffer.StoreCell(nFileId, rTabName, rPos);
2426 void XclExpLinkManagerImpl8::StoreCellRange( sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange )
2428 maSBBuffer.StoreCellRange(nFileId, rTabName, rRange);
2431 bool XclExpLinkManagerImpl8::InsertAddIn(
2432 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rName )
2434 sal_uInt16 nSupbook;
2435 if( maSBBuffer.InsertAddIn( nSupbook, rnExtName, rName ) )
2437 rnExtSheet = InsertXti( XclExpXti( nSupbook, EXC_TAB_EXTERNAL, EXC_TAB_EXTERNAL ) );
2438 return true;
2440 return false;
2443 bool XclExpLinkManagerImpl8::InsertEuroTool(
2444 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rName )
2446 sal_uInt16 nSupbook;
2447 if( maSBBuffer.InsertEuroTool( nSupbook, rnExtName, rName ) )
2449 rnExtSheet = InsertXti( XclExpXti( nSupbook, EXC_TAB_EXTERNAL, EXC_TAB_EXTERNAL ) );
2450 return true;
2452 return false;
2455 bool XclExpLinkManagerImpl8::InsertDde(
2456 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
2457 const OUString& rApplic, const OUString& rTopic, const OUString& rItem )
2459 sal_uInt16 nSupbook;
2460 if( maSBBuffer.InsertDde( nSupbook, rnExtName, rApplic, rTopic, rItem ) )
2462 rnExtSheet = InsertXti( XclExpXti( nSupbook, EXC_TAB_EXTERNAL, EXC_TAB_EXTERNAL ) );
2463 return true;
2465 return false;
2468 bool XclExpLinkManagerImpl8::InsertExtName( sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
2469 const OUString& rName, const OUString& rUrl, const ScExternalRefCache::TokenArrayRef& rArray )
2471 sal_uInt16 nSupbook;
2472 if( maSBBuffer.InsertExtName( nSupbook, rnExtName, rUrl, rName, rArray ) )
2474 rnExtSheet = InsertXti( XclExpXti( nSupbook, EXC_TAB_EXTERNAL, EXC_TAB_EXTERNAL ) );
2475 return true;
2477 return false;
2480 void XclExpLinkManagerImpl8::Save( XclExpStream& rStrm )
2482 if( !maXtiVec.empty() )
2484 // SUPBOOKs, XCTs, CRNs, EXTERNNAMEs
2485 maSBBuffer.Save( rStrm );
2487 // EXTERNSHEET
2488 sal_uInt16 nCount = ulimit_cast< sal_uInt16 >( maXtiVec.size() );
2489 rStrm.StartRecord( EXC_ID_EXTERNSHEET, 2 + 6 * nCount );
2490 rStrm << nCount;
2491 rStrm.SetSliceSize( 6 );
2492 for( XclExpXtiVec::const_iterator aIt = maXtiVec.begin(), aEnd = maXtiVec.end(); aIt != aEnd; ++aIt )
2493 aIt->Save( rStrm );
2494 rStrm.EndRecord();
2498 void XclExpLinkManagerImpl8::SaveXml( XclExpXmlStream& rStrm )
2500 if (maSBBuffer.HasExternalReferences())
2502 sax_fastparser::FSHelperPtr pWorkbook = rStrm.GetCurrentStream();
2503 pWorkbook->startElement( XML_externalReferences, FSEND);
2505 // externalLink, externalBook, sheetNames, sheetDataSet, externalName
2506 maSBBuffer.SaveXml( rStrm );
2508 pWorkbook->endElement( XML_externalReferences);
2511 // TODO: equivalent for EXTERNSHEET in OOXML?
2512 #if 0
2513 if( !maXtiVec.empty() )
2515 for( XclExpXtiVec::const_iterator aIt = maXtiVec.begin(), aEnd = maXtiVec.end(); aIt != aEnd; ++aIt )
2516 aIt->SaveXml( rStrm );
2518 #endif
2521 sal_uInt16 XclExpLinkManagerImpl8::InsertXti( const XclExpXti& rXti )
2523 for( XclExpXtiVec::const_iterator aIt = maXtiVec.begin(), aEnd = maXtiVec.end(); aIt != aEnd; ++aIt )
2524 if( *aIt == rXti )
2525 return ulimit_cast< sal_uInt16 >( aIt - maXtiVec.begin() );
2526 maXtiVec.push_back( rXti );
2527 return ulimit_cast< sal_uInt16 >( maXtiVec.size() - 1 );
2530 XclExpLinkManager::XclExpLinkManager( const XclExpRoot& rRoot ) :
2531 XclExpRoot( rRoot )
2533 switch( GetBiff() )
2535 case EXC_BIFF5:
2536 mxImpl.reset( new XclExpLinkManagerImpl5( rRoot ) );
2537 break;
2538 case EXC_BIFF8:
2539 mxImpl.reset( new XclExpLinkManagerImpl8( rRoot ) );
2540 break;
2541 default:
2542 DBG_ERROR_BIFF();
2546 XclExpLinkManager::~XclExpLinkManager()
2550 void XclExpLinkManager::FindExtSheet(
2551 sal_uInt16& rnExtSheet, sal_uInt16& rnXclTab,
2552 SCTAB nScTab, XclExpRefLogEntry* pRefLogEntry )
2554 mxImpl->FindExtSheet( rnExtSheet, rnXclTab, rnXclTab, nScTab, nScTab, pRefLogEntry );
2557 void XclExpLinkManager::FindExtSheet(
2558 sal_uInt16& rnExtSheet, sal_uInt16& rnFirstXclTab, sal_uInt16& rnLastXclTab,
2559 SCTAB nFirstScTab, SCTAB nLastScTab, XclExpRefLogEntry* pRefLogEntry )
2561 mxImpl->FindExtSheet( rnExtSheet, rnFirstXclTab, rnLastXclTab, nFirstScTab, nLastScTab, pRefLogEntry );
2564 sal_uInt16 XclExpLinkManager::FindExtSheet( sal_Unicode cCode )
2566 return mxImpl->FindExtSheet( cCode );
2569 void XclExpLinkManager::FindExtSheet( sal_uInt16 nFileId, const OUString& rTabName, sal_uInt16 nXclTabSpan,
2570 sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
2571 XclExpRefLogEntry* pRefLogEntry )
2573 mxImpl->FindExtSheet( nFileId, rTabName, nXclTabSpan, rnExtSheet, rnFirstSBTab, rnLastSBTab, pRefLogEntry );
2576 void XclExpLinkManager::StoreCell( const ScSingleRefData& rRef, const ScAddress& rPos )
2578 mxImpl->StoreCellRange(rRef, rRef, rPos);
2581 void XclExpLinkManager::StoreCellRange( const ScComplexRefData& rRef, const ScAddress& rPos )
2583 mxImpl->StoreCellRange(rRef.Ref1, rRef.Ref2, rPos);
2586 void XclExpLinkManager::StoreCell( sal_uInt16 nFileId, const OUString& rTabName, const ScAddress& rPos )
2588 mxImpl->StoreCell(nFileId, rTabName, rPos);
2591 void XclExpLinkManager::StoreCellRange( sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange )
2593 mxImpl->StoreCellRange(nFileId, rTabName, rRange);
2596 bool XclExpLinkManager::InsertAddIn(
2597 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rName )
2599 return mxImpl->InsertAddIn( rnExtSheet, rnExtName, rName );
2602 bool XclExpLinkManager::InsertEuroTool(
2603 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rName )
2605 return mxImpl->InsertEuroTool( rnExtSheet, rnExtName, rName );
2608 bool XclExpLinkManager::InsertDde(
2609 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
2610 const OUString& rApplic, const OUString& rTopic, const OUString& rItem )
2612 return mxImpl->InsertDde( rnExtSheet, rnExtName, rApplic, rTopic, rItem );
2615 bool XclExpLinkManager::InsertExtName(
2616 sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rName, const OUString& rUrl,
2617 const ScExternalRefCache::TokenArrayRef& rArray )
2619 return mxImpl->InsertExtName(rnExtSheet, rnExtName, rUrl, rName, rArray);
2622 void XclExpLinkManager::Save( XclExpStream& rStrm )
2624 mxImpl->Save( rStrm );
2627 void XclExpLinkManager::SaveXml( XclExpXmlStream& rStrm )
2629 mxImpl->SaveXml( rStrm );
2632 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */