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