1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "document.hxx"
22 #include "formulacell.hxx"
23 #include "scextopt.hxx"
24 #include "tablink.hxx"
25 #include "xistream.hxx"
26 #include "xihelper.hxx"
28 #include "excform.hxx"
29 #include "tokenarray.hxx"
30 #include "externalrefmgr.hxx"
31 #include "scmatrix.hxx"
32 #include <svl/sharedstringpool.hxx>
35 #include <boost/ptr_container/ptr_vector.hpp>
39 // *** Helper classes ***
41 // Cached external cells ======================================================
44 * Contains the address and value of an external referenced cell.
45 * Note that this is non-copyable, so cannot be used in most stl/boost containers.
47 class XclImpCrn
: public XclImpCachedValue
50 /** Reads a cached value and stores it with its cell address. */
51 explicit XclImpCrn( XclImpStream
& rStrm
, const XclAddress
& rXclPos
);
53 const XclAddress
& GetAddress() const { return maXclPos
;}
56 XclAddress maXclPos
; /// Excel position of the cached cell.
59 // Sheet in an external document ==============================================
61 /** Contains the name and sheet index of one sheet in an external document. */
62 class XclImpSupbookTab
65 /** Stores the sheet name and marks the sheet index as invalid.
66 The sheet index is set while creating the Calc sheet with CreateTable(). */
67 explicit XclImpSupbookTab( const OUString
& rTabName
);
70 inline const OUString
& GetTabName() const { return maTabName
; }
72 /** Reads a CRN record (external referenced cell) at the specified address. */
73 void ReadCrn( XclImpStream
& rStrm
, const XclAddress
& rXclPos
);
75 void LoadCachedValues(ScExternalRefCache::TableTypeRef pCacheTable
);
78 typedef boost::shared_ptr
< XclImpCrn
> XclImpCrnRef
;
79 typedef std::vector
< XclImpCrnRef
> XclImpCrnList
;
81 XclImpCrnList maCrnList
; /// List of CRN records (cached cell values).
82 OUString maTabName
; /// Name of the external sheet.
85 // External document (SUPBOOK) ================================================
87 /** This class represents an external linked document (record SUPBOOK).
88 @descr Contains a list of all referenced sheets in the document. */
89 class XclImpSupbook
: protected XclImpRoot
92 /** Reads the SUPBOOK record from stream. */
93 explicit XclImpSupbook( XclImpStream
& rStrm
);
95 /** Reads an XCT record (count of following CRNs and current sheet). */
96 void ReadXct( XclImpStream
& rStrm
);
97 /** Reads a CRN record (external referenced cell). */
98 void ReadCrn( XclImpStream
& rStrm
);
99 /** Reads an EXTERNNAME record. */
100 void ReadExternname( XclImpStream
& rStrm
, ExcelToSc
* pFormulaConv
= NULL
);
102 /** Returns the SUPBOOK record type. */
103 inline XclSupbookType
GetType() const { return meType
; }
105 /** Returns the URL of the external document. */
106 inline const OUString
& GetXclUrl() const { return maXclUrl
; }
108 /** Returns the external name specified by an index from the Excel document (one-based). */
109 const XclImpExtName
* GetExternName( sal_uInt16 nXclIndex
) const;
110 /** Tries to decode the URL to OLE or DDE link components.
111 @descr For DDE links: Decodes to application name and topic.
112 For OLE object links: Decodes to class name and document URL.
113 @return true = decoding was successful, returned strings are valid (not empty). */
114 bool GetLinkData( OUString
& rApplic
, OUString
& rDoc
) const;
115 /** Returns the specified macro name (1-based) or an empty string on error. */
116 const OUString
& GetMacroName( sal_uInt16 nXclNameIdx
) const;
118 const OUString
& GetTabName( sal_uInt16 nXtiTab
) const;
120 sal_uInt16
GetTabCount() const;
122 void LoadCachedValues();
124 svl::SharedStringPool
& GetSharedStringPool();
127 typedef boost::ptr_vector
< XclImpSupbookTab
> XclImpSupbookTabList
;
128 typedef boost::ptr_vector
< XclImpExtName
> XclImpExtNameList
;
130 XclImpSupbookTabList maSupbTabList
; /// All sheet names of the document.
131 XclImpExtNameList maExtNameList
; /// All external names of the document.
132 OUString maXclUrl
; /// URL of the external document (Excel mode).
133 XclSupbookType meType
; /// Type of the supbook record.
134 sal_uInt16 mnSBTab
; /// Current Excel sheet index from SUPBOOK for XCT/CRN records.
137 // Import link manager ========================================================
139 /** Contains the SUPBOOK index and sheet indexes of an external link.
140 @descr It is possible to enter a formula like =SUM(Sheet1:Sheet3!A1),
141 therefore here occurs a sheet range. */
144 sal_uInt16 mnSupbook
; /// Index to SUPBOOK record.
145 sal_uInt16 mnSBTabFirst
; /// Index to the first sheet of the range in the SUPBOOK.
146 sal_uInt16 mnSBTabLast
; /// Index to the last sheet of the range in the SUPBOOK.
147 inline explicit XclImpXti() : mnSupbook( SAL_MAX_UINT16
), mnSBTabFirst( SAL_MAX_UINT16
), mnSBTabLast( SAL_MAX_UINT16
) {}
150 inline XclImpStream
& operator>>( XclImpStream
& rStrm
, XclImpXti
& rXti
)
152 rXti
.mnSupbook
= rStrm
.ReaduInt16();
153 rXti
.mnSBTabFirst
= rStrm
.ReaduInt16();
154 rXti
.mnSBTabLast
= rStrm
.ReaduInt16();
158 /** Implementation of the link manager. */
159 class XclImpLinkManagerImpl
: protected XclImpRoot
162 explicit XclImpLinkManagerImpl( const XclImpRoot
& rRoot
);
164 /** Reads the EXTERNSHEET record. */
165 void ReadExternsheet( XclImpStream
& rStrm
);
166 /** Reads a SUPBOOK record. */
167 void ReadSupbook( XclImpStream
& rStrm
);
168 /** Reads an XCT record and appends it to the current SUPBOOK. */
169 void ReadXct( XclImpStream
& rStrm
);
170 /** Reads a CRN record and appends it to the current SUPBOOK. */
171 void ReadCrn( XclImpStream
& rStrm
);
172 /** Reads an EXTERNNAME record and appends it to the current SUPBOOK. */
173 void ReadExternname( XclImpStream
& rStrm
, ExcelToSc
* pFormulaConv
= NULL
);
175 /** Returns true, if the specified XTI entry contains an internal reference. */
176 bool IsSelfRef( sal_uInt16 nXtiIndex
) const;
177 /** Returns the Calc sheet index range of the specified XTI entry.
178 @return true = XTI data found, returned sheet index range is valid. */
180 SCTAB
& rnFirstScTab
, SCTAB
& rnLastScTab
,
181 sal_uInt16 nXtiIndex
) const;
182 /** Returns the specified external name or 0 on error. */
183 const XclImpExtName
* GetExternName( sal_uInt16 nXtiIndex
, sal_uInt16 nExtName
) const;
185 /** Returns the absolute file URL of a supporting workbook specified by
187 const OUString
* GetSupbookUrl( sal_uInt16 nXtiIndex
) const;
189 const OUString
& GetSupbookTabName( sal_uInt16 nXti
, sal_uInt16 nXtiTab
) const;
191 /** Tries to decode the URL of the specified XTI entry to OLE or DDE link components.
192 @descr For DDE links: Decodes to application name and topic.
193 For OLE object links: Decodes to class name and document URL.
194 @return true = decoding was successful, returned strings are valid (not empty). */
195 bool GetLinkData( OUString
& rApplic
, OUString
& rTopic
, sal_uInt16 nXtiIndex
) const;
196 /** Returns the specified macro name or an empty string on error. */
197 const OUString
& GetMacroName( sal_uInt16 nExtSheet
, sal_uInt16 nExtName
) const;
200 /** Returns the specified XTI (link entry from BIFF8 EXTERNSHEET record). */
201 const XclImpXti
* GetXti( sal_uInt16 nXtiIndex
) const;
202 /** Returns the specified SUPBOOK (external document). */
203 const XclImpSupbook
* GetSupbook( sal_uInt16 nXtiIndex
) const;
205 void LoadCachedValues();
208 typedef ::std::vector
< XclImpXti
> XclImpXtiVector
;
209 typedef boost::ptr_vector
< XclImpSupbook
> XclImpSupbookList
;
211 XclImpXtiVector maXtiList
; /// List of all XTI structures.
212 XclImpSupbookList maSupbookList
; /// List of external documents.
215 // *** Implementation ***
217 // Excel sheet indexes ========================================================
219 // original Excel sheet names -------------------------------------------------
221 void XclImpTabInfo::AppendXclTabName( const OUString
& rXclTabName
, SCTAB nScTab
)
223 maTabNames
[ rXclTabName
] = nScTab
;
226 void XclImpTabInfo::InsertScTab( SCTAB nScTab
)
228 for( XclTabNameMap::iterator aIt
= maTabNames
.begin(), aEnd
= maTabNames
.end(); aIt
!= aEnd
; ++aIt
)
229 if( aIt
->second
>= nScTab
)
233 SCTAB
XclImpTabInfo::GetScTabFromXclName( const OUString
& rXclTabName
) const
235 XclTabNameMap::const_iterator aIt
= maTabNames
.find( rXclTabName
);
236 return (aIt
!= maTabNames
.end()) ? aIt
->second
: SCTAB_INVALID
;
239 // record creation order - TABID record ---------------------------------------
241 void XclImpTabInfo::ReadTabid( XclImpStream
& rStrm
)
243 OSL_ENSURE_BIFF( rStrm
.GetRoot().GetBiff() == EXC_BIFF8
);
244 if( rStrm
.GetRoot().GetBiff() == EXC_BIFF8
)
246 rStrm
.EnableDecryption();
247 sal_Size nReadCount
= rStrm
.GetRecLeft() / 2;
248 OSL_ENSURE( nReadCount
<= 0xFFFF, "XclImpTabInfo::ReadTabid - record too long" );
250 maTabIdVec
.reserve( nReadCount
);
251 for( sal_Size nIndex
= 0; rStrm
.IsValid() && (nIndex
< nReadCount
); ++nIndex
)
252 // zero index is not allowed in BIFF8, but it seems that it occurs in real life
253 maTabIdVec
.push_back( rStrm
.ReaduInt16() );
257 sal_uInt16
XclImpTabInfo::GetCurrentIndex( sal_uInt16 nCreatedId
, sal_uInt16 nMaxTabId
) const
259 sal_uInt16 nReturn
= 0;
260 for( ScfUInt16Vec::const_iterator aIt
= maTabIdVec
.begin(), aEnd
= maTabIdVec
.end(); aIt
!= aEnd
; ++aIt
)
262 sal_uInt16 nValue
= *aIt
;
263 if( nValue
== nCreatedId
)
265 if( nValue
<= nMaxTabId
)
271 // External names =============================================================
273 XclImpExtName::MOper::MOper(svl::SharedStringPool
& rPool
, XclImpStream
& rStrm
) :
274 mxCached(new ScMatrix(0,0))
276 SCSIZE nLastCol
= rStrm
.ReaduInt8();
277 SCSIZE nLastRow
= rStrm
.ReaduInt16();
279 //assuming worse case scenario of nOp + one byte unistring len
280 const size_t nMinRecordSize
= 2;
281 const size_t nMaxRows
= rStrm
.GetRecLeft() / (nMinRecordSize
* (nLastCol
+1));
282 if (nLastRow
>= nMaxRows
)
284 SAL_WARN("sc", "Parsing error: " << nMaxRows
<<
285 " max possible rows, but " << nLastRow
<< " index claimed, truncating");
286 nLastRow
= nMaxRows
-1;
289 mxCached
->Resize(nLastCol
+1, nLastRow
+1);
290 for (SCSIZE nRow
= 0; nRow
<= nLastRow
; ++nRow
)
292 for (SCSIZE nCol
= 0; nCol
<= nLastCol
; ++nCol
)
295 nOp
= rStrm
.ReaduInt8();
300 double fVal
= rStrm
.ReadDouble();
301 mxCached
->PutDouble(fVal
, nCol
, nRow
);
306 OUString aStr
= rStrm
.ReadUniString();
307 mxCached
->PutString(rPool
.intern(aStr
), nCol
, nRow
);
312 bool bVal
= rStrm
.ReaduInt8();
313 mxCached
->PutBoolean(bVal
, nCol
, nRow
);
319 sal_uInt8 nErr
= rStrm
.ReaduInt8();
320 // TODO: Map the error code from xls to calc.
321 mxCached
->PutError(nErr
, nCol
, nRow
);
332 const ScMatrix
& XclImpExtName::MOper::GetCache() const
337 XclImpExtName::XclImpExtName( XclImpSupbook
& rSupbook
, XclImpStream
& rStrm
, XclSupbookType eSubType
, ExcelToSc
* pFormulaConv
)
341 sal_uInt16
nFlags(0);
344 nFlags
= rStrm
.ReaduInt16();
345 mnStorageId
= rStrm
.ReaduInt32();
346 nLen
= rStrm
.ReaduInt8();
347 maName
= rStrm
.ReadUniString( nLen
);
348 if( ::get_flag( nFlags
, EXC_EXTN_BUILTIN
) || !::get_flag( nFlags
, EXC_EXTN_OLE_OR_DDE
) )
350 if( eSubType
== EXC_SBTYPE_ADDIN
)
353 maName
= XclImpRoot::GetScAddInName( maName
);
355 else if ( (eSubType
== EXC_SBTYPE_EUROTOOL
) &&
356 maName
.equalsIgnoreAsciiCase( "EUROCONVERT" ) )
357 meType
= xlExtEuroConvert
;
361 maName
= ScfTools::ConvertToScDefinedName( maName
);
366 meType
= ::get_flagvalue( nFlags
, EXC_EXTN_OLE
, xlExtOLE
, xlExtDDE
);
372 if (rStrm
.GetRecLeft() > 1)
373 mxDdeMatrix
.reset(new XclImpCachedMatrix(rStrm
));
376 // TODO: For now, only global external names are supported. In future
377 // we should extend this to supporting per-sheet external names.
378 if (mnStorageId
== 0)
382 const ScTokenArray
* pArray
= NULL
;
384 nFmlaLen
= rStrm
.ReaduInt16();
385 vector
<OUString
> aTabNames
;
386 sal_uInt16 nCount
= rSupbook
.GetTabCount();
387 aTabNames
.reserve(nCount
);
388 for (sal_uInt16 i
= 0; i
< nCount
; ++i
)
389 aTabNames
.push_back(rSupbook
.GetTabName(i
));
391 pFormulaConv
->ConvertExternName(pArray
, rStrm
, nFmlaLen
, rSupbook
.GetXclUrl(), aTabNames
);
393 mxArray
.reset(pArray
->Clone());
398 mpMOper
= new MOper(rSupbook
.GetSharedStringPool(), rStrm
);
405 XclImpExtName::~XclImpExtName()
410 void XclImpExtName::CreateDdeData( ScDocument
& rDoc
, const OUString
& rApplic
, const OUString
& rTopic
) const
412 ScMatrixRef xResults
;
413 if( mxDdeMatrix
.get() )
414 xResults
= mxDdeMatrix
->CreateScMatrix(rDoc
.GetSharedStringPool());
415 rDoc
.CreateDdeLink( rApplic
, rTopic
, maName
, SC_DDE_DEFAULT
, xResults
);
418 void XclImpExtName::CreateExtNameData( ScDocument
& rDoc
, sal_uInt16 nFileId
) const
423 ScExternalRefManager
* pRefMgr
= rDoc
.GetExternalRefManager();
424 pRefMgr
->storeRangeNameTokens(nFileId
, maName
, *mxArray
);
430 * Decompose the name into sheet name and range name. An OLE link name is
431 * always formatted like this [ !Sheet1!R1C1:R5C2 ] and it always uses R1C1
434 bool extractSheetAndRange(const OUString
& rName
, OUString
& rSheet
, OUString
& rRange
)
436 sal_Int32 n
= rName
.getLength();
437 const sal_Unicode
* p
= rName
.getStr();
439 bool bInSheet
= true;
440 for (sal_Int32 i
= 0; i
< n
; ++i
, ++p
)
444 // first character must be '!'.
452 // sheet name to range separator.
455 rSheet
= aBuf
.makeStringAndClear();
463 rRange
= aBuf
.makeStringAndClear();
469 bool XclImpExtName::CreateOleData(ScDocument
& rDoc
, const OUString
& rUrl
,
470 sal_uInt16
& rFileId
, OUString
& rTabName
, ScRange
& rRange
) const
475 OUString aSheet
, aRangeStr
;
476 if (!extractSheetAndRange(maName
, aSheet
, aRangeStr
))
480 sal_uInt16 nRes
= aRange
.ParseAny(aRangeStr
, &rDoc
, formula::FormulaGrammar::CONV_XL_R1C1
);
481 if ((nRes
& SCA_VALID
) != SCA_VALID
)
484 if (aRange
.aStart
.Tab() != aRange
.aEnd
.Tab())
485 // We don't support multi-sheet range for this.
488 const ScMatrix
& rCache
= mpMOper
->GetCache();
490 rCache
.GetDimensions(nC
, nR
);
492 // cache matrix is empty.
495 ScExternalRefManager
* pRefMgr
= rDoc
.GetExternalRefManager();
496 sal_uInt16 nFileId
= pRefMgr
->getExternalFileId(rUrl
);
497 ScExternalRefCache::TableTypeRef xTab
= pRefMgr
->getCacheTable(nFileId
, aSheet
, true, NULL
);
499 // cache table creation failed.
502 xTab
->setWholeTableCached();
503 for (SCSIZE i
= 0; i
< nR
; ++i
)
505 for (SCSIZE j
= 0; j
< nC
; ++j
)
507 SCCOL nCol
= aRange
.aStart
.Col() + j
;
508 SCROW nRow
= aRange
.aStart
.Row() + i
;
510 ScMatrixValue aVal
= rCache
.Get(j
, i
);
513 case SC_MATVAL_BOOLEAN
:
515 bool b
= aVal
.GetBoolean();
516 ScExternalRefCache::TokenRef
pToken(new formula::FormulaDoubleToken(b
? 1.0 : 0.0));
517 xTab
->setCell(nCol
, nRow
, pToken
, 0, false);
520 case SC_MATVAL_VALUE
:
522 ScExternalRefCache::TokenRef
pToken(new formula::FormulaDoubleToken(aVal
.fVal
));
523 xTab
->setCell(nCol
, nRow
, pToken
, 0, false);
526 case SC_MATVAL_STRING
:
528 const svl::SharedString
aStr( aVal
.GetString());
529 ScExternalRefCache::TokenRef
pToken(new formula::FormulaStringToken(aStr
));
530 xTab
->setCell(nCol
, nRow
, pToken
, 0, false);
545 bool XclImpExtName::HasFormulaTokens() const
547 return (mxArray
.get() != NULL
);
550 // Cached external cells ======================================================
552 XclImpCrn::XclImpCrn( XclImpStream
& rStrm
, const XclAddress
& rXclPos
) :
553 XclImpCachedValue( rStrm
),
558 // Sheet in an external document ==============================================
560 XclImpSupbookTab::XclImpSupbookTab( const OUString
& rTabName
) :
561 maTabName( rTabName
)
565 XclImpSupbookTab::~XclImpSupbookTab()
569 void XclImpSupbookTab::ReadCrn( XclImpStream
& rStrm
, const XclAddress
& rXclPos
)
571 XclImpCrnRef
crnRef( new XclImpCrn(rStrm
, rXclPos
) );
572 maCrnList
.push_back( crnRef
);
575 void XclImpSupbookTab::LoadCachedValues(ScExternalRefCache::TableTypeRef pCacheTable
)
577 if (maCrnList
.empty())
580 for (XclImpCrnList::iterator itCrnRef
= maCrnList
.begin(); itCrnRef
!= maCrnList
.end(); ++itCrnRef
)
582 const XclImpCrn
* const pCrn
= itCrnRef
->get();
583 const XclAddress
& rAddr
= pCrn
->GetAddress();
584 switch (pCrn
->GetType())
586 case EXC_CACHEDVAL_BOOL
:
588 bool b
= pCrn
->GetBool();
589 ScExternalRefCache::TokenRef
pToken(new formula::FormulaDoubleToken(b
? 1.0 : 0.0));
590 pCacheTable
->setCell(rAddr
.mnCol
, rAddr
.mnRow
, pToken
, 0, false);
593 case EXC_CACHEDVAL_DOUBLE
:
595 double f
= pCrn
->GetValue();
596 ScExternalRefCache::TokenRef
pToken(new formula::FormulaDoubleToken(f
));
597 pCacheTable
->setCell(rAddr
.mnCol
, rAddr
.mnRow
, pToken
, 0, false);
600 case EXC_CACHEDVAL_ERROR
:
602 double fError
= XclTools::ErrorToDouble( pCrn
->GetXclError() );
603 ScExternalRefCache::TokenRef
pToken(new formula::FormulaDoubleToken(fError
));
604 pCacheTable
->setCell(rAddr
.mnCol
, rAddr
.mnRow
, pToken
, 0, false);
607 case EXC_CACHEDVAL_STRING
:
609 const OUString
& rStr
= pCrn
->GetString();
610 ScExternalRefCache::TokenRef
pToken(new formula::FormulaStringToken(rStr
));
611 pCacheTable
->setCell(rAddr
.mnCol
, rAddr
.mnRow
, pToken
, 0, false);
620 // External document (SUPBOOK) ================================================
622 XclImpSupbook::XclImpSupbook( XclImpStream
& rStrm
) :
623 XclImpRoot( rStrm
.GetRoot() ),
624 meType( EXC_SBTYPE_UNKNOWN
),
625 mnSBTab( EXC_TAB_DELETED
)
627 sal_uInt16 nSBTabCnt
;
628 nSBTabCnt
= rStrm
.ReaduInt16();
630 if( rStrm
.GetRecLeft() == 2 )
632 switch( rStrm
.ReaduInt16() )
634 case EXC_SUPB_SELF
: meType
= EXC_SBTYPE_SELF
; break;
635 case EXC_SUPB_ADDIN
: meType
= EXC_SBTYPE_ADDIN
; break;
636 default: OSL_FAIL( "XclImpSupbook::XclImpSupbook - unknown special SUPBOOK type" );
641 OUString
aEncUrl( rStrm
.ReadUniString() );
643 XclImpUrlHelper::DecodeUrl( maXclUrl
, bSelf
, GetRoot(), aEncUrl
);
645 if( maXclUrl
.equalsIgnoreAsciiCase( "\010EUROTOOL.XLA" ) )
647 meType
= EXC_SBTYPE_EUROTOOL
;
648 maSupbTabList
.push_back( new XclImpSupbookTab( maXclUrl
) );
652 meType
= EXC_SBTYPE_EXTERN
;
654 //assuming all empty strings with just len header of 0
655 const size_t nMinRecordSize
= sizeof(sal_Int16
);
656 const size_t nMaxRecords
= rStrm
.GetRecLeft() / nMinRecordSize
;
657 if (nSBTabCnt
> nMaxRecords
)
659 SAL_WARN("sc", "Parsing error: " << nMaxRecords
<<
660 " max possible entries, but " << nSBTabCnt
<< " claimed, truncating");
661 nSBTabCnt
= nMaxRecords
;
664 for( sal_uInt16 nSBTab
= 0; nSBTab
< nSBTabCnt
; ++nSBTab
)
666 OUString
aTabName( rStrm
.ReadUniString() );
667 maSupbTabList
.push_back( new XclImpSupbookTab( aTabName
) );
672 meType
= EXC_SBTYPE_SPECIAL
;
673 // create dummy list entry
674 maSupbTabList
.push_back( new XclImpSupbookTab( maXclUrl
) );
678 void XclImpSupbook::ReadXct( XclImpStream
& rStrm
)
681 mnSBTab
= rStrm
.ReaduInt16();
684 void XclImpSupbook::ReadCrn( XclImpStream
& rStrm
)
686 if (mnSBTab
>= maSupbTabList
.size())
688 XclImpSupbookTab
& rSbTab
= maSupbTabList
[mnSBTab
];
689 sal_uInt8 nXclColLast
, nXclColFirst
;
691 nXclColLast
= rStrm
.ReaduInt8();
692 nXclColFirst
= rStrm
.ReaduInt8();
693 nXclRow
= rStrm
.ReaduInt16();
695 for( sal_uInt8 nXclCol
= nXclColFirst
; (nXclCol
<= nXclColLast
) && (rStrm
.GetRecLeft() > 1); ++nXclCol
)
696 rSbTab
.ReadCrn( rStrm
, XclAddress( nXclCol
, nXclRow
) );
699 void XclImpSupbook::ReadExternname( XclImpStream
& rStrm
, ExcelToSc
* pFormulaConv
)
701 maExtNameList
.push_back( new XclImpExtName( *this, rStrm
, meType
, pFormulaConv
) );
704 const XclImpExtName
* XclImpSupbook::GetExternName( sal_uInt16 nXclIndex
) const
708 SAL_WARN("sc", "XclImpSupbook::GetExternName - index must be >0");
711 if (meType
== EXC_SBTYPE_SELF
|| nXclIndex
> maExtNameList
.size())
713 return &maExtNameList
[nXclIndex
-1];
716 bool XclImpSupbook::GetLinkData( OUString
& rApplic
, OUString
& rTopic
) const
718 return (meType
== EXC_SBTYPE_SPECIAL
) && XclImpUrlHelper::DecodeLink( rApplic
, rTopic
, maXclUrl
);
721 const OUString
& XclImpSupbook::GetMacroName( sal_uInt16 nXclNameIdx
) const
723 OSL_ENSURE( nXclNameIdx
> 0, "XclImpSupbook::GetMacroName - index must be >0" );
724 const XclImpName
* pName
= (meType
== EXC_SBTYPE_SELF
) ? GetNameManager().GetName( nXclNameIdx
) : 0;
725 return (pName
&& pName
->IsVBName()) ? pName
->GetScName() : EMPTY_OUSTRING
;
728 const OUString
& XclImpSupbook::GetTabName( sal_uInt16 nXtiTab
) const
730 if (nXtiTab
>= maSupbTabList
.size())
731 return EMPTY_OUSTRING
;
732 return maSupbTabList
[nXtiTab
].GetTabName();
735 sal_uInt16
XclImpSupbook::GetTabCount() const
737 return ulimit_cast
<sal_uInt16
>(maSupbTabList
.size());
740 void XclImpSupbook::LoadCachedValues()
742 if (meType
!= EXC_SBTYPE_EXTERN
|| GetExtDocOptions().GetDocSettings().mnLinkCnt
> 0 || !GetDocShell())
745 OUString
aAbsUrl( ScGlobal::GetAbsDocName(maXclUrl
, GetDocShell()) );
747 ScExternalRefManager
* pRefMgr
= GetRoot().GetDoc().GetExternalRefManager();
748 sal_uInt16 nFileId
= pRefMgr
->getExternalFileId(aAbsUrl
);
750 for (XclImpSupbookTabList::iterator itTab
= maSupbTabList
.begin(); itTab
!= maSupbTabList
.end(); ++itTab
)
752 const OUString
& rTabName
= itTab
->GetTabName();
753 ScExternalRefCache::TableTypeRef pCacheTable
= pRefMgr
->getCacheTable(nFileId
, rTabName
, true);
754 itTab
->LoadCachedValues(pCacheTable
);
755 pCacheTable
->setWholeTableCached();
759 svl::SharedStringPool
& XclImpSupbook::GetSharedStringPool()
761 return GetDoc().GetSharedStringPool();
764 // Import link manager ========================================================
766 XclImpLinkManagerImpl::XclImpLinkManagerImpl( const XclImpRoot
& rRoot
) :
771 void XclImpLinkManagerImpl::ReadExternsheet( XclImpStream
& rStrm
)
773 sal_uInt16 nXtiCount
;
774 nXtiCount
= rStrm
.ReaduInt16();
775 OSL_ENSURE( static_cast< sal_Size
>( nXtiCount
* 6 ) == rStrm
.GetRecLeft(), "XclImpLinkManagerImpl::ReadExternsheet - invalid count" );
776 nXtiCount
= static_cast< sal_uInt16
>( ::std::min
< sal_Size
>( nXtiCount
, rStrm
.GetRecLeft() / 6 ) );
778 /* #i104057# A weird external XLS generator writes multiple EXTERNSHEET
779 records instead of only one as expected. Surprisingly, Excel seems to
780 insert the entries of the second record before the entries of the first
782 XclImpXtiVector
aNewEntries( nXtiCount
);
783 for( XclImpXtiVector::iterator aIt
= aNewEntries
.begin(), aEnd
= aNewEntries
.end(); rStrm
.IsValid() && (aIt
!= aEnd
); ++aIt
)
785 maXtiList
.insert( maXtiList
.begin(), aNewEntries
.begin(), aNewEntries
.end() );
790 void XclImpLinkManagerImpl::ReadSupbook( XclImpStream
& rStrm
)
792 maSupbookList
.push_back( new XclImpSupbook( rStrm
) );
795 void XclImpLinkManagerImpl::ReadXct( XclImpStream
& rStrm
)
797 if( !maSupbookList
.empty() )
798 maSupbookList
.back().ReadXct( rStrm
);
801 void XclImpLinkManagerImpl::ReadCrn( XclImpStream
& rStrm
)
803 if( !maSupbookList
.empty() )
804 maSupbookList
.back().ReadCrn( rStrm
);
807 void XclImpLinkManagerImpl::ReadExternname( XclImpStream
& rStrm
, ExcelToSc
* pFormulaConv
)
809 if( !maSupbookList
.empty() )
810 maSupbookList
.back().ReadExternname( rStrm
, pFormulaConv
);
813 bool XclImpLinkManagerImpl::IsSelfRef( sal_uInt16 nXtiIndex
) const
815 const XclImpSupbook
* pSupbook
= GetSupbook( nXtiIndex
);
816 return pSupbook
&& (pSupbook
->GetType() == EXC_SBTYPE_SELF
);
819 bool XclImpLinkManagerImpl::GetScTabRange(
820 SCTAB
& rnFirstScTab
, SCTAB
& rnLastScTab
, sal_uInt16 nXtiIndex
) const
822 if( const XclImpXti
* pXti
= GetXti( nXtiIndex
) )
824 if (!maSupbookList
.empty() && (pXti
->mnSupbook
< maSupbookList
.size()) )
826 rnFirstScTab
= pXti
->mnSBTabFirst
;
827 rnLastScTab
= pXti
->mnSBTabLast
;
834 const XclImpExtName
* XclImpLinkManagerImpl::GetExternName( sal_uInt16 nXtiIndex
, sal_uInt16 nExtName
) const
836 const XclImpSupbook
* pSupbook
= GetSupbook( nXtiIndex
);
837 return pSupbook
? pSupbook
->GetExternName( nExtName
) : 0;
840 const OUString
* XclImpLinkManagerImpl::GetSupbookUrl( sal_uInt16 nXtiIndex
) const
842 const XclImpSupbook
* p
= GetSupbook( nXtiIndex
);
845 return &p
->GetXclUrl();
848 const OUString
& XclImpLinkManagerImpl::GetSupbookTabName( sal_uInt16 nXti
, sal_uInt16 nXtiTab
) const
850 const XclImpSupbook
* p
= GetSupbook(nXti
);
851 return p
? p
->GetTabName(nXtiTab
) : EMPTY_OUSTRING
;
854 bool XclImpLinkManagerImpl::GetLinkData( OUString
& rApplic
, OUString
& rTopic
, sal_uInt16 nXtiIndex
) const
856 const XclImpSupbook
* pSupbook
= GetSupbook( nXtiIndex
);
857 return pSupbook
&& pSupbook
->GetLinkData( rApplic
, rTopic
);
860 const OUString
& XclImpLinkManagerImpl::GetMacroName( sal_uInt16 nExtSheet
, sal_uInt16 nExtName
) const
862 const XclImpSupbook
* pSupbook
= GetSupbook( nExtSheet
);
863 return pSupbook
? pSupbook
->GetMacroName( nExtName
) : EMPTY_OUSTRING
;
866 const XclImpXti
* XclImpLinkManagerImpl::GetXti( sal_uInt16 nXtiIndex
) const
868 return (nXtiIndex
< maXtiList
.size()) ? &maXtiList
[ nXtiIndex
] : 0;
871 const XclImpSupbook
* XclImpLinkManagerImpl::GetSupbook( sal_uInt16 nXtiIndex
) const
873 if ( maSupbookList
.empty() )
875 const XclImpXti
* pXti
= GetXti( nXtiIndex
);
876 if (!pXti
|| pXti
->mnSupbook
>= maSupbookList
.size())
878 return &(maSupbookList
.at( pXti
->mnSupbook
));
881 void XclImpLinkManagerImpl::LoadCachedValues()
883 // Read all CRN records which can be accessed via XclImpSupbook, and store
884 // the cached values to the external reference manager.
885 for (XclImpSupbookList::iterator itSupbook
= maSupbookList
.begin(); itSupbook
!= maSupbookList
.end(); ++itSupbook
)
886 itSupbook
->LoadCachedValues();
889 XclImpLinkManager::XclImpLinkManager( const XclImpRoot
& rRoot
) :
891 mxImpl( new XclImpLinkManagerImpl( rRoot
) )
895 XclImpLinkManager::~XclImpLinkManager()
899 void XclImpLinkManager::ReadExternsheet( XclImpStream
& rStrm
)
901 mxImpl
->ReadExternsheet( rStrm
);
904 void XclImpLinkManager::ReadSupbook( XclImpStream
& rStrm
)
906 mxImpl
->ReadSupbook( rStrm
);
909 void XclImpLinkManager::ReadXct( XclImpStream
& rStrm
)
911 mxImpl
->ReadXct( rStrm
);
914 void XclImpLinkManager::ReadCrn( XclImpStream
& rStrm
)
916 mxImpl
->ReadCrn( rStrm
);
919 void XclImpLinkManager::ReadExternname( XclImpStream
& rStrm
, ExcelToSc
* pFormulaConv
)
921 mxImpl
->ReadExternname( rStrm
, pFormulaConv
);
924 bool XclImpLinkManager::IsSelfRef( sal_uInt16 nXtiIndex
) const
926 return mxImpl
->IsSelfRef( nXtiIndex
);
929 bool XclImpLinkManager::GetScTabRange(
930 SCTAB
& rnFirstScTab
, SCTAB
& rnLastScTab
, sal_uInt16 nXtiIndex
) const
932 return mxImpl
->GetScTabRange( rnFirstScTab
, rnLastScTab
, nXtiIndex
);
935 const XclImpExtName
* XclImpLinkManager::GetExternName( sal_uInt16 nXtiIndex
, sal_uInt16 nExtName
) const
937 return mxImpl
->GetExternName( nXtiIndex
, nExtName
);
940 const OUString
* XclImpLinkManager::GetSupbookUrl( sal_uInt16 nXtiIndex
) const
942 return mxImpl
->GetSupbookUrl(nXtiIndex
);
945 const OUString
& XclImpLinkManager::GetSupbookTabName( sal_uInt16 nXti
, sal_uInt16 nXtiTab
) const
947 return mxImpl
->GetSupbookTabName(nXti
, nXtiTab
);
950 bool XclImpLinkManager::GetLinkData( OUString
& rApplic
, OUString
& rTopic
, sal_uInt16 nXtiIndex
) const
952 return mxImpl
->GetLinkData( rApplic
, rTopic
, nXtiIndex
);
955 const OUString
& XclImpLinkManager::GetMacroName( sal_uInt16 nExtSheet
, sal_uInt16 nExtName
) const
957 return mxImpl
->GetMacroName( nExtSheet
, nExtName
);
960 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */