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