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"
33 #include <boost/ptr_container/ptr_vector.hpp>
38 // ============================================================================
39 // *** Helper classes ***
40 // ============================================================================
42 // Cached external cells ======================================================
45 * Contains the address and value of an external referenced cell.
46 * Note that this is non-copyable, so cannot be used in most stl/boost containers.
48 class XclImpCrn
: public XclImpCachedValue
51 /** Reads a cached value and stores it with its cell address. */
52 explicit XclImpCrn( XclImpStream
& rStrm
, const XclAddress
& rXclPos
);
54 const XclAddress
& GetAddress() const;
57 XclAddress maXclPos
; /// Excel position of the cached cell.
60 // Sheet in an external document ==============================================
62 /** Contains the name and sheet index of one sheet in an external document. */
63 class XclImpSupbookTab
66 /** Stores the sheet name and marks the sheet index as invalid.
67 The sheet index is set while creating the Calc sheet with CreateTable(). */
68 explicit XclImpSupbookTab( const String
& rTabName
);
71 inline const String
& GetTabName() const { return maTabName
; }
73 /** Reads a CRN record (external referenced cell) at the specified address. */
74 void ReadCrn( XclImpStream
& rStrm
, const XclAddress
& rXclPos
);
76 void LoadCachedValues(ScExternalRefCache::TableTypeRef pCacheTable
);
79 typedef boost::shared_ptr
< XclImpCrn
> XclImpCrnRef
;
80 typedef std::vector
< XclImpCrnRef
> XclImpCrnList
;
82 XclImpCrnList maCrnList
; /// List of CRN records (cached cell values).
83 String maTabName
; /// Name of the external sheet.
86 // External document (SUPBOOK) ================================================
88 /** This class represents an external linked document (record SUPBOOK).
89 @descr Contains a list of all referenced sheets in the document. */
90 class XclImpSupbook
: protected XclImpRoot
93 /** Reads the SUPBOOK record from stream. */
94 explicit XclImpSupbook( XclImpStream
& rStrm
);
96 /** Reads an XCT record (count of following CRNs and current sheet). */
97 void ReadXct( XclImpStream
& rStrm
);
98 /** Reads a CRN record (external referenced cell). */
99 void ReadCrn( XclImpStream
& rStrm
);
100 /** Reads an EXTERNNAME record. */
101 void ReadExternname( XclImpStream
& rStrm
, ExcelToSc
* pFormulaConv
= NULL
);
103 /** Returns the SUPBOOK record type. */
104 inline XclSupbookType
GetType() const { return meType
; }
106 /** Returns the URL of the external document. */
107 inline const String
& GetXclUrl() const { return maXclUrl
; }
109 /** Returns the external name specified by an index from the Excel document (one-based). */
110 const XclImpExtName
* GetExternName( sal_uInt16 nXclIndex
) const;
111 /** Tries to decode the URL to OLE or DDE link components.
112 @descr For DDE links: Decodes to application name and topic.
113 For OLE object links: Decodes to class name and document URL.
114 @return true = decoding was successful, returned strings are valid (not empty). */
115 bool GetLinkData( String
& rApplic
, String
& rDoc
) const;
116 /** Returns the specified macro name (1-based) or an empty string on error. */
117 const String
& GetMacroName( sal_uInt16 nXclNameIdx
) const;
119 const String
& GetTabName( sal_uInt16 nXtiTab
) const;
121 sal_uInt16
GetTabCount() const;
123 void LoadCachedValues();
126 typedef boost::ptr_vector
< XclImpSupbookTab
> XclImpSupbookTabList
;
127 typedef boost::ptr_vector
< XclImpExtName
> XclImpExtNameList
;
129 XclImpSupbookTabList maSupbTabList
; /// All sheet names of the document.
130 XclImpExtNameList maExtNameList
; /// All external names of the document.
131 String maXclUrl
; /// URL of the external document (Excel mode).
132 String maFilterName
; /// Detected filer name.
133 String maFilterOpt
; /// Detected filer options.
134 XclSupbookType meType
; /// Type of the supbook record.
135 sal_uInt16 mnSBTab
; /// Current Excel sheet index from SUPBOOK for XCT/CRN records.
138 // Import link manager ========================================================
140 /** Contains the SUPBOOK index and sheet indexes of an external link.
141 @descr It is possible to enter a formula like =SUM(Sheet1:Sheet3!A1),
142 therefore here occurs a sheet range. */
145 sal_uInt16 mnSupbook
; /// Index to SUPBOOK record.
146 sal_uInt16 mnSBTabFirst
; /// Index to the first sheet of the range in the SUPBOOK.
147 sal_uInt16 mnSBTabLast
; /// Index to the last sheet of the range in the SUPBOOK.
148 inline explicit XclImpXti() : mnSupbook( SAL_MAX_UINT16
), mnSBTabFirst( SAL_MAX_UINT16
), mnSBTabLast( SAL_MAX_UINT16
) {}
151 inline XclImpStream
& operator>>( XclImpStream
& rStrm
, XclImpXti
& rXti
)
153 return rStrm
>> rXti
.mnSupbook
>> rXti
.mnSBTabFirst
>> rXti
.mnSBTabLast
;
156 // ----------------------------------------------------------------------------
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 String
* GetSupbookUrl( sal_uInt16 nXtiIndex
) const;
189 const String
& 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( String
& rApplic
, String
& rTopic
, sal_uInt16 nXtiIndex
) const;
196 /** Returns the specified macro name or an empty string on error. */
197 const String
& 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 // ============================================================================
216 // *** Implementation ***
217 // ============================================================================
219 // Excel sheet indexes ========================================================
221 // original Excel sheet names -------------------------------------------------
223 void XclImpTabInfo::AppendXclTabName( const String
& rXclTabName
, SCTAB nScTab
)
225 maTabNames
[ rXclTabName
] = nScTab
;
228 void XclImpTabInfo::InsertScTab( SCTAB nScTab
)
230 for( XclTabNameMap::iterator aIt
= maTabNames
.begin(), aEnd
= maTabNames
.end(); aIt
!= aEnd
; ++aIt
)
231 if( aIt
->second
>= nScTab
)
235 SCTAB
XclImpTabInfo::GetScTabFromXclName( const String
& rXclTabName
) const
237 XclTabNameMap::const_iterator aIt
= maTabNames
.find( rXclTabName
);
238 return (aIt
!= maTabNames
.end()) ? aIt
->second
: SCTAB_INVALID
;
241 // record creation order - TABID record ---------------------------------------
243 void XclImpTabInfo::ReadTabid( XclImpStream
& rStrm
)
245 OSL_ENSURE_BIFF( rStrm
.GetRoot().GetBiff() == EXC_BIFF8
);
246 if( rStrm
.GetRoot().GetBiff() == EXC_BIFF8
)
248 rStrm
.EnableDecryption();
249 sal_Size nReadCount
= rStrm
.GetRecLeft() / 2;
250 OSL_ENSURE( nReadCount
<= 0xFFFF, "XclImpTabInfo::ReadTabid - record too long" );
252 maTabIdVec
.reserve( nReadCount
);
253 for( sal_Size nIndex
= 0; rStrm
.IsValid() && (nIndex
< nReadCount
); ++nIndex
)
254 // zero index is not allowed in BIFF8, but it seems that it occurs in real life
255 maTabIdVec
.push_back( rStrm
.ReaduInt16() );
259 sal_uInt16
XclImpTabInfo::GetCurrentIndex( sal_uInt16 nCreatedId
, sal_uInt16 nMaxTabId
) const
261 sal_uInt16 nReturn
= 0;
262 for( ScfUInt16Vec::const_iterator aIt
= maTabIdVec
.begin(), aEnd
= maTabIdVec
.end(); aIt
!= aEnd
; ++aIt
)
264 sal_uInt16 nValue
= *aIt
;
265 if( nValue
== nCreatedId
)
267 if( nValue
<= nMaxTabId
)
273 // External names =============================================================
275 XclImpExtName::MOper::MOper(XclImpStream
& rStrm
) :
276 mxCached(new ScMatrix(0,0))
278 SCSIZE nLastCol
= rStrm
.ReaduInt8();
279 SCSIZE nLastRow
= rStrm
.ReaduInt16();
280 mxCached
->Resize(nLastCol
+1, nLastRow
+1);
281 for (SCSIZE nRow
= 0; nRow
<= nLastRow
; ++nRow
)
283 for (SCSIZE nCol
= 0; nCol
<= nLastCol
; ++nCol
)
291 double fVal
= rStrm
.ReadDouble();
292 mxCached
->PutDouble(fVal
, nCol
, nRow
);
297 OUString aStr
= rStrm
.ReadUniString();
298 mxCached
->PutString(aStr
, nCol
, nRow
);
303 bool bVal
= rStrm
.ReaduInt8();
304 mxCached
->PutBoolean(bVal
, nCol
, nRow
);
310 sal_uInt8 nErr
= rStrm
.ReaduInt8();
311 // TODO: Map the error code from xls to calc.
312 mxCached
->PutError(nErr
, nCol
, nRow
);
323 const ScMatrix
& XclImpExtName::MOper::GetCache() const
328 XclImpExtName::XclImpExtName( const XclImpSupbook
& rSupbook
, XclImpStream
& rStrm
, XclSupbookType eSubType
, ExcelToSc
* pFormulaConv
) :
334 rStrm
>> nFlags
>> mnStorageId
>> nLen
;
335 maName
= rStrm
.ReadUniString( nLen
);
336 if( ::get_flag( nFlags
, EXC_EXTN_BUILTIN
) || !::get_flag( nFlags
, EXC_EXTN_OLE_OR_DDE
) )
338 if( eSubType
== EXC_SBTYPE_ADDIN
)
341 maName
= rStrm
.GetRoot().GetScAddInName( maName
);
343 else if ( (eSubType
== EXC_SBTYPE_EUROTOOL
) &&
344 maName
.EqualsIgnoreCaseAscii( "EUROCONVERT" ) )
345 meType
= xlExtEuroConvert
;
349 ScfTools::ConvertToScDefinedName( maName
);
354 meType
= ::get_flagvalue( nFlags
, EXC_EXTN_OLE
, xlExtOLE
, xlExtDDE
);
360 if (rStrm
.GetRecLeft() > 1)
361 mxDdeMatrix
.reset(new XclImpCachedMatrix(rStrm
));
364 // TODO: For now, only global external names are supported. In future
365 // we should extend this to supporting per-sheet external names.
366 if (mnStorageId
== 0)
370 const ScTokenArray
* pArray
= NULL
;
373 vector
<String
> aTabNames
;
374 sal_uInt16 nCount
= rSupbook
.GetTabCount();
375 aTabNames
.reserve(nCount
);
376 for (sal_uInt16 i
= 0; i
< nCount
; ++i
)
377 aTabNames
.push_back(rSupbook
.GetTabName(i
));
379 pFormulaConv
->ConvertExternName(pArray
, rStrm
, nFmlaLen
, rSupbook
.GetXclUrl(), aTabNames
);
381 mxArray
.reset(pArray
->Clone());
386 mpMOper
= new MOper(rStrm
);
393 XclImpExtName::~XclImpExtName()
398 void XclImpExtName::CreateDdeData( ScDocument
& rDoc
, const String
& rApplic
, const String
& rTopic
) const
400 ScMatrixRef xResults
;
401 if( mxDdeMatrix
.get() )
402 xResults
= mxDdeMatrix
->CreateScMatrix();
403 rDoc
.CreateDdeLink( rApplic
, rTopic
, maName
, SC_DDE_DEFAULT
, xResults
);
406 void XclImpExtName::CreateExtNameData( ScDocument
& rDoc
, sal_uInt16 nFileId
) const
411 ScExternalRefManager
* pRefMgr
= rDoc
.GetExternalRefManager();
412 pRefMgr
->storeRangeNameTokens(nFileId
, maName
, *mxArray
);
418 * Decompose the name into sheet name and range name. An OLE link name is
419 * always formatted like this [ !Sheet1!R1C1:R5C2 ] and it always uses R1C1
422 bool extractSheetAndRange(const OUString
& rName
, OUString
& rSheet
, OUString
& rRange
)
424 sal_Int32 n
= rName
.getLength();
425 const sal_Unicode
* p
= rName
.getStr();
427 bool bInSheet
= true;
428 for (sal_Int32 i
= 0; i
< n
; ++i
, ++p
)
432 // first character must be '!'.
440 // sheet name to range separator.
443 rSheet
= aBuf
.makeStringAndClear();
451 rRange
= aBuf
.makeStringAndClear();
457 bool XclImpExtName::CreateOleData(ScDocument
& rDoc
, const OUString
& rUrl
,
458 sal_uInt16
& rFileId
, OUString
& rTabName
, ScRange
& rRange
) const
463 OUString aSheet
, aRangeStr
;
464 if (!extractSheetAndRange(maName
, aSheet
, aRangeStr
))
468 sal_uInt16 nRes
= aRange
.ParseAny(aRangeStr
, &rDoc
, formula::FormulaGrammar::CONV_XL_R1C1
);
469 if ((nRes
& SCA_VALID
) != SCA_VALID
)
472 if (aRange
.aStart
.Tab() != aRange
.aEnd
.Tab())
473 // We don't support multi-sheet range for this.
476 const ScMatrix
& rCache
= mpMOper
->GetCache();
478 rCache
.GetDimensions(nC
, nR
);
480 // cache matrix is empty.
483 ScExternalRefManager
* pRefMgr
= rDoc
.GetExternalRefManager();
484 sal_uInt16 nFileId
= pRefMgr
->getExternalFileId(rUrl
);
485 ScExternalRefCache::TableTypeRef xTab
= pRefMgr
->getCacheTable(nFileId
, aSheet
, true, NULL
);
487 // cache table creation failed.
490 xTab
->setWholeTableCached();
491 for (SCSIZE i
= 0; i
< nR
; ++i
)
493 for (SCSIZE j
= 0; j
< nC
; ++j
)
495 SCCOL nCol
= aRange
.aStart
.Col() + j
;
496 SCROW nRow
= aRange
.aStart
.Row() + i
;
498 ScMatrixValue aVal
= rCache
.Get(j
, i
);
501 case SC_MATVAL_BOOLEAN
:
503 bool b
= aVal
.GetBoolean();
504 ScExternalRefCache::TokenRef
pToken(new formula::FormulaDoubleToken(b
? 1.0 : 0.0));
505 xTab
->setCell(nCol
, nRow
, pToken
, 0, false);
508 case SC_MATVAL_VALUE
:
510 ScExternalRefCache::TokenRef
pToken(new formula::FormulaDoubleToken(aVal
.fVal
));
511 xTab
->setCell(nCol
, nRow
, pToken
, 0, false);
514 case SC_MATVAL_STRING
:
516 const String
& rStr
= aVal
.GetString();
517 ScExternalRefCache::TokenRef
pToken(new formula::FormulaStringToken(rStr
));
518 xTab
->setCell(nCol
, nRow
, pToken
, 0, false);
533 bool XclImpExtName::HasFormulaTokens() const
535 return (mxArray
.get() != NULL
);
538 // Cached external cells ======================================================
540 XclImpCrn::XclImpCrn( XclImpStream
& rStrm
, const XclAddress
& rXclPos
) :
541 XclImpCachedValue( rStrm
),
546 const XclAddress
& XclImpCrn::GetAddress() const
551 // Sheet in an external document ==============================================
553 XclImpSupbookTab::XclImpSupbookTab( const String
& rTabName
) :
554 maTabName( rTabName
)
558 XclImpSupbookTab::~XclImpSupbookTab()
562 void XclImpSupbookTab::ReadCrn( XclImpStream
& rStrm
, const XclAddress
& rXclPos
)
564 XclImpCrnRef
crnRef( new XclImpCrn(rStrm
, rXclPos
) );
565 maCrnList
.push_back( crnRef
);
568 void XclImpSupbookTab::LoadCachedValues(ScExternalRefCache::TableTypeRef pCacheTable
)
570 if (maCrnList
.empty())
573 for (XclImpCrnList::iterator itCrnRef
= maCrnList
.begin(); itCrnRef
!= maCrnList
.end(); ++itCrnRef
)
575 const XclImpCrn
* const pCrn
= itCrnRef
->get();
576 const XclAddress
& rAddr
= pCrn
->GetAddress();
577 switch (pCrn
->GetType())
579 case EXC_CACHEDVAL_BOOL
:
581 bool b
= pCrn
->GetBool();
582 ScExternalRefCache::TokenRef
pToken(new formula::FormulaDoubleToken(b
? 1.0 : 0.0));
583 pCacheTable
->setCell(rAddr
.mnCol
, rAddr
.mnRow
, pToken
, 0, false);
586 case EXC_CACHEDVAL_DOUBLE
:
588 double f
= pCrn
->GetValue();
589 ScExternalRefCache::TokenRef
pToken(new formula::FormulaDoubleToken(f
));
590 pCacheTable
->setCell(rAddr
.mnCol
, rAddr
.mnRow
, pToken
, 0, false);
593 case EXC_CACHEDVAL_ERROR
:
595 double fError
= XclTools::ErrorToDouble( pCrn
->GetXclError() );
596 ScExternalRefCache::TokenRef
pToken(new formula::FormulaDoubleToken(fError
));
597 pCacheTable
->setCell(rAddr
.mnCol
, rAddr
.mnRow
, pToken
, 0, false);
600 case EXC_CACHEDVAL_STRING
:
602 const String
& rStr
= pCrn
->GetString();
603 ScExternalRefCache::TokenRef
pToken(new formula::FormulaStringToken(rStr
));
604 pCacheTable
->setCell(rAddr
.mnCol
, rAddr
.mnRow
, pToken
, 0, false);
613 // External document (SUPBOOK) ================================================
615 XclImpSupbook::XclImpSupbook( XclImpStream
& rStrm
) :
616 XclImpRoot( rStrm
.GetRoot() ),
617 meType( EXC_SBTYPE_UNKNOWN
),
618 mnSBTab( EXC_TAB_DELETED
)
620 sal_uInt16 nSBTabCnt
;
623 if( rStrm
.GetRecLeft() == 2 )
625 switch( rStrm
.ReaduInt16() )
627 case EXC_SUPB_SELF
: meType
= EXC_SBTYPE_SELF
; break;
628 case EXC_SUPB_ADDIN
: meType
= EXC_SBTYPE_ADDIN
; break;
629 default: OSL_FAIL( "XclImpSupbook::XclImpSupbook - unknown special SUPBOOK type" );
634 String
aEncUrl( rStrm
.ReadUniString() );
636 XclImpUrlHelper::DecodeUrl( maXclUrl
, bSelf
, GetRoot(), aEncUrl
);
638 if( maXclUrl
.EqualsIgnoreCaseAscii( "\010EUROTOOL.XLA" ) )
640 meType
= EXC_SBTYPE_EUROTOOL
;
641 maSupbTabList
.push_back( new XclImpSupbookTab( maXclUrl
) );
645 meType
= EXC_SBTYPE_EXTERN
;
646 for( sal_uInt16 nSBTab
= 0; nSBTab
< nSBTabCnt
; ++nSBTab
)
648 String
aTabName( rStrm
.ReadUniString() );
649 maSupbTabList
.push_back( new XclImpSupbookTab( aTabName
) );
654 meType
= EXC_SBTYPE_SPECIAL
;
655 // create dummy list entry
656 maSupbTabList
.push_back( new XclImpSupbookTab( maXclUrl
) );
660 void XclImpSupbook::ReadXct( XclImpStream
& rStrm
)
666 void XclImpSupbook::ReadCrn( XclImpStream
& rStrm
)
668 if (mnSBTab
>= maSupbTabList
.size())
670 XclImpSupbookTab
& rSbTab
= maSupbTabList
[mnSBTab
];
671 sal_uInt8 nXclColLast
, nXclColFirst
;
673 rStrm
>> nXclColLast
>> nXclColFirst
>> nXclRow
;
675 for( sal_uInt8 nXclCol
= nXclColFirst
; (nXclCol
<= nXclColLast
) && (rStrm
.GetRecLeft() > 1); ++nXclCol
)
676 rSbTab
.ReadCrn( rStrm
, XclAddress( nXclCol
, nXclRow
) );
679 void XclImpSupbook::ReadExternname( XclImpStream
& rStrm
, ExcelToSc
* pFormulaConv
)
681 maExtNameList
.push_back( new XclImpExtName( *this, rStrm
, meType
, pFormulaConv
) );
684 const XclImpExtName
* XclImpSupbook::GetExternName( sal_uInt16 nXclIndex
) const
686 OSL_ENSURE( nXclIndex
> 0, "XclImpSupbook::GetExternName - index must be >0" );
687 if (meType
== EXC_SBTYPE_SELF
|| nXclIndex
> maExtNameList
.size())
689 return &maExtNameList
[nXclIndex
-1];
692 bool XclImpSupbook::GetLinkData( String
& rApplic
, String
& rTopic
) const
694 return (meType
== EXC_SBTYPE_SPECIAL
) && XclImpUrlHelper::DecodeLink( rApplic
, rTopic
, maXclUrl
);
697 const String
& XclImpSupbook::GetMacroName( sal_uInt16 nXclNameIdx
) const
699 OSL_ENSURE( nXclNameIdx
> 0, "XclImpSupbook::GetMacroName - index must be >0" );
700 const XclImpName
* pName
= (meType
== EXC_SBTYPE_SELF
) ? GetNameManager().GetName( nXclNameIdx
) : 0;
701 return (pName
&& pName
->IsVBName()) ? pName
->GetScName() : EMPTY_STRING
;
704 const String
& XclImpSupbook::GetTabName( sal_uInt16 nXtiTab
) const
706 if (nXtiTab
>= maSupbTabList
.size())
708 return maSupbTabList
[nXtiTab
].GetTabName();
711 sal_uInt16
XclImpSupbook::GetTabCount() const
713 return ulimit_cast
<sal_uInt16
>(maSupbTabList
.size());
716 void XclImpSupbook::LoadCachedValues()
718 if (meType
!= EXC_SBTYPE_EXTERN
|| GetExtDocOptions().GetDocSettings().mnLinkCnt
> 0 || !GetDocShell())
721 String
aAbsUrl( ScGlobal::GetAbsDocName(maXclUrl
, GetDocShell()) );
723 ScExternalRefManager
* pRefMgr
= GetRoot().GetDoc().GetExternalRefManager();
724 sal_uInt16 nFileId
= pRefMgr
->getExternalFileId(aAbsUrl
);
726 for (XclImpSupbookTabList::iterator itTab
= maSupbTabList
.begin(); itTab
!= maSupbTabList
.end(); ++itTab
)
728 const String
& rTabName
= itTab
->GetTabName();
729 ScExternalRefCache::TableTypeRef pCacheTable
= pRefMgr
->getCacheTable(nFileId
, rTabName
, true);
730 itTab
->LoadCachedValues(pCacheTable
);
731 pCacheTable
->setWholeTableCached();
735 // Import link manager ========================================================
737 XclImpLinkManagerImpl::XclImpLinkManagerImpl( const XclImpRoot
& rRoot
) :
742 void XclImpLinkManagerImpl::ReadExternsheet( XclImpStream
& rStrm
)
744 sal_uInt16 nXtiCount
;
746 OSL_ENSURE( static_cast< sal_Size
>( nXtiCount
* 6 ) == rStrm
.GetRecLeft(), "XclImpLinkManagerImpl::ReadExternsheet - invalid count" );
747 nXtiCount
= static_cast< sal_uInt16
>( ::std::min
< sal_Size
>( nXtiCount
, rStrm
.GetRecLeft() / 6 ) );
749 /* #i104057# A weird external XLS generator writes multiple EXTERNSHEET
750 records instead of only one as expected. Surprisingly, Excel seems to
751 insert the entries of the second record before the entries of the first
753 XclImpXtiVector
aNewEntries( nXtiCount
);
754 for( XclImpXtiVector::iterator aIt
= aNewEntries
.begin(), aEnd
= aNewEntries
.end(); rStrm
.IsValid() && (aIt
!= aEnd
); ++aIt
)
756 maXtiList
.insert( maXtiList
.begin(), aNewEntries
.begin(), aNewEntries
.end() );
761 void XclImpLinkManagerImpl::ReadSupbook( XclImpStream
& rStrm
)
763 maSupbookList
.push_back( new XclImpSupbook( rStrm
) );
766 void XclImpLinkManagerImpl::ReadXct( XclImpStream
& rStrm
)
768 if( !maSupbookList
.empty() )
769 maSupbookList
.back().ReadXct( rStrm
);
772 void XclImpLinkManagerImpl::ReadCrn( XclImpStream
& rStrm
)
774 if( !maSupbookList
.empty() )
775 maSupbookList
.back().ReadCrn( rStrm
);
778 void XclImpLinkManagerImpl::ReadExternname( XclImpStream
& rStrm
, ExcelToSc
* pFormulaConv
)
780 if( !maSupbookList
.empty() )
781 maSupbookList
.back().ReadExternname( rStrm
, pFormulaConv
);
784 bool XclImpLinkManagerImpl::IsSelfRef( sal_uInt16 nXtiIndex
) const
786 const XclImpSupbook
* pSupbook
= GetSupbook( nXtiIndex
);
787 return pSupbook
&& (pSupbook
->GetType() == EXC_SBTYPE_SELF
);
790 bool XclImpLinkManagerImpl::GetScTabRange(
791 SCTAB
& rnFirstScTab
, SCTAB
& rnLastScTab
, sal_uInt16 nXtiIndex
) const
793 if( const XclImpXti
* pXti
= GetXti( nXtiIndex
) )
795 if (!maSupbookList
.empty() && (pXti
->mnSupbook
< maSupbookList
.size()) )
797 rnFirstScTab
= pXti
->mnSBTabFirst
;
798 rnLastScTab
= pXti
->mnSBTabLast
;
805 const XclImpExtName
* XclImpLinkManagerImpl::GetExternName( sal_uInt16 nXtiIndex
, sal_uInt16 nExtName
) const
807 const XclImpSupbook
* pSupbook
= GetSupbook( nXtiIndex
);
808 return pSupbook
? pSupbook
->GetExternName( nExtName
) : 0;
811 const String
* XclImpLinkManagerImpl::GetSupbookUrl( sal_uInt16 nXtiIndex
) const
813 const XclImpSupbook
* p
= GetSupbook( nXtiIndex
);
816 return &p
->GetXclUrl();
819 const String
& XclImpLinkManagerImpl::GetSupbookTabName( sal_uInt16 nXti
, sal_uInt16 nXtiTab
) const
821 const XclImpSupbook
* p
= GetSupbook(nXti
);
822 return p
? p
->GetTabName(nXtiTab
) : EMPTY_STRING
;
825 bool XclImpLinkManagerImpl::GetLinkData( String
& rApplic
, String
& rTopic
, sal_uInt16 nXtiIndex
) const
827 const XclImpSupbook
* pSupbook
= GetSupbook( nXtiIndex
);
828 return pSupbook
&& pSupbook
->GetLinkData( rApplic
, rTopic
);
831 const String
& XclImpLinkManagerImpl::GetMacroName( sal_uInt16 nExtSheet
, sal_uInt16 nExtName
) const
833 const XclImpSupbook
* pSupbook
= GetSupbook( nExtSheet
);
834 return pSupbook
? pSupbook
->GetMacroName( nExtName
) : EMPTY_STRING
;
837 const XclImpXti
* XclImpLinkManagerImpl::GetXti( sal_uInt16 nXtiIndex
) const
839 return (nXtiIndex
< maXtiList
.size()) ? &maXtiList
[ nXtiIndex
] : 0;
842 const XclImpSupbook
* XclImpLinkManagerImpl::GetSupbook( sal_uInt16 nXtiIndex
) const
844 if ( maSupbookList
.empty() )
846 const XclImpXti
* pXti
= GetXti( nXtiIndex
);
847 if (!pXti
|| pXti
->mnSupbook
>= maSupbookList
.size())
849 return &(maSupbookList
.at( pXti
->mnSupbook
));
852 void XclImpLinkManagerImpl::LoadCachedValues()
854 // Read all CRN records which can be accessed via XclImpSupbook, and store
855 // the cached values to the external reference manager.
856 for (XclImpSupbookList::iterator itSupbook
= maSupbookList
.begin(); itSupbook
!= maSupbookList
.end(); ++itSupbook
)
857 itSupbook
->LoadCachedValues();
860 // ============================================================================
862 XclImpLinkManager::XclImpLinkManager( const XclImpRoot
& rRoot
) :
864 mxImpl( new XclImpLinkManagerImpl( rRoot
) )
868 XclImpLinkManager::~XclImpLinkManager()
872 void XclImpLinkManager::ReadExternsheet( XclImpStream
& rStrm
)
874 mxImpl
->ReadExternsheet( rStrm
);
877 void XclImpLinkManager::ReadSupbook( XclImpStream
& rStrm
)
879 mxImpl
->ReadSupbook( rStrm
);
882 void XclImpLinkManager::ReadXct( XclImpStream
& rStrm
)
884 mxImpl
->ReadXct( rStrm
);
887 void XclImpLinkManager::ReadCrn( XclImpStream
& rStrm
)
889 mxImpl
->ReadCrn( rStrm
);
892 void XclImpLinkManager::ReadExternname( XclImpStream
& rStrm
, ExcelToSc
* pFormulaConv
)
894 mxImpl
->ReadExternname( rStrm
, pFormulaConv
);
897 bool XclImpLinkManager::IsSelfRef( sal_uInt16 nXtiIndex
) const
899 return mxImpl
->IsSelfRef( nXtiIndex
);
902 bool XclImpLinkManager::GetScTabRange(
903 SCTAB
& rnFirstScTab
, SCTAB
& rnLastScTab
, sal_uInt16 nXtiIndex
) const
905 return mxImpl
->GetScTabRange( rnFirstScTab
, rnLastScTab
, nXtiIndex
);
908 const XclImpExtName
* XclImpLinkManager::GetExternName( sal_uInt16 nXtiIndex
, sal_uInt16 nExtName
) const
910 return mxImpl
->GetExternName( nXtiIndex
, nExtName
);
913 const String
* XclImpLinkManager::GetSupbookUrl( sal_uInt16 nXtiIndex
) const
915 return mxImpl
->GetSupbookUrl(nXtiIndex
);
918 const String
& XclImpLinkManager::GetSupbookTabName( sal_uInt16 nXti
, sal_uInt16 nXtiTab
) const
920 return mxImpl
->GetSupbookTabName(nXti
, nXtiTab
);
923 bool XclImpLinkManager::GetLinkData( String
& rApplic
, String
& rTopic
, sal_uInt16 nXtiIndex
) const
925 return mxImpl
->GetLinkData( rApplic
, rTopic
, nXtiIndex
);
928 const String
& XclImpLinkManager::GetMacroName( sal_uInt16 nExtSheet
, sal_uInt16 nExtName
) const
930 return mxImpl
->GetMacroName( nExtSheet
, nExtName
);
933 // ============================================================================
935 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */