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 "externallinkbuffer.hxx"
21 :
22 : #include <com/sun/star/sheet/ComplexReference.hpp>
23 : #include <com/sun/star/sheet/DDELinkInfo.hpp>
24 : #include <com/sun/star/sheet/ExternalLinkType.hpp>
25 : #include <com/sun/star/sheet/ExternalReference.hpp>
26 : #include <com/sun/star/sheet/ReferenceFlags.hpp>
27 : #include <com/sun/star/sheet/SingleReference.hpp>
28 : #include <com/sun/star/sheet/XDDELinks.hpp>
29 : #include <com/sun/star/sheet/XDDELink.hpp>
30 : #include <com/sun/star/sheet/XDDELinkResults.hpp>
31 : #include <com/sun/star/sheet/XExternalDocLink.hpp>
32 : #include <com/sun/star/sheet/XExternalDocLinks.hpp>
33 : #include <rtl/strbuf.hxx>
34 : #include "oox/core/filterbase.hxx"
35 : #include "oox/helper/attributelist.hxx"
36 : #include "oox/token/properties.hxx"
37 : #include "addressconverter.hxx"
38 : #include "biffinputstream.hxx"
39 : #include "excelhandlers.hxx"
40 : #include "formulaparser.hxx"
41 : #include "worksheetbuffer.hxx"
42 :
43 : namespace oox {
44 : namespace xls {
45 :
46 : // ============================================================================
47 :
48 : using namespace ::com::sun::star::sheet;
49 : using namespace ::com::sun::star::table;
50 : using namespace ::com::sun::star::uno;
51 :
52 : using ::oox::core::Relation;
53 : using ::oox::core::Relations;
54 : using ::rtl::OString;
55 : using ::rtl::OStringBuffer;
56 : using ::rtl::OStringToOUString;
57 : using ::rtl::OUString;
58 :
59 : // ============================================================================
60 :
61 : namespace {
62 :
63 : const sal_uInt16 BIFF12_EXTERNALBOOK_BOOK = 0;
64 : const sal_uInt16 BIFF12_EXTERNALBOOK_DDE = 1;
65 : const sal_uInt16 BIFF12_EXTERNALBOOK_OLE = 2;
66 :
67 : const sal_uInt16 BIFF12_EXTNAME_AUTOMATIC = 0x0002;
68 : const sal_uInt16 BIFF12_EXTNAME_PREFERPIC = 0x0004;
69 : const sal_uInt16 BIFF12_EXTNAME_STDDOCNAME = 0x0008;
70 : const sal_uInt16 BIFF12_EXTNAME_OLEOBJECT = 0x0010;
71 : const sal_uInt16 BIFF12_EXTNAME_ICONIFIED = 0x0020;
72 :
73 : const sal_uInt16 BIFF_EXTNAME_BUILTIN = 0x0001;
74 : const sal_uInt16 BIFF_EXTNAME_AUTOMATIC = 0x0002;
75 : const sal_uInt16 BIFF_EXTNAME_PREFERPIC = 0x0004;
76 : const sal_uInt16 BIFF_EXTNAME_STDDOCNAME = 0x0008;
77 : const sal_uInt16 BIFF_EXTNAME_OLEOBJECT = 0x0010;
78 : const sal_uInt16 BIFF_EXTNAME_ICONIFIED = 0x8000;
79 :
80 : } // namespace
81 :
82 : // ============================================================================
83 :
84 0 : ExternalNameModel::ExternalNameModel() :
85 : mbBuiltIn( false ),
86 : mbNotify( false ),
87 : mbPreferPic( false ),
88 : mbStdDocName( false ),
89 : mbOleObj( false ),
90 0 : mbIconified( false )
91 : {
92 0 : }
93 :
94 : // ============================================================================
95 :
96 0 : ExternalName::ExternalName( const ExternalLink& rParentLink ) :
97 : DefinedNameBase( rParentLink ),
98 : mrParentLink( rParentLink ),
99 0 : mbDdeLinkCreated( false )
100 : {
101 0 : }
102 :
103 0 : void ExternalName::importDefinedName( const AttributeList& rAttribs )
104 : {
105 0 : maModel.maName = rAttribs.getXString( XML_name, OUString() );
106 : OSL_ENSURE( !maModel.maName.isEmpty(), "ExternalName::importDefinedName - empty name" );
107 : // zero-based index into sheet list of externalBook
108 0 : maModel.mnSheet = rAttribs.getInteger( XML_sheetId, -1 );
109 0 : }
110 :
111 0 : void ExternalName::importDdeItem( const AttributeList& rAttribs )
112 : {
113 0 : maModel.maName = rAttribs.getXString( XML_name, OUString() );
114 : OSL_ENSURE( !maModel.maName.isEmpty(), "ExternalName::importDdeItem - empty name" );
115 0 : maExtNameModel.mbOleObj = false;
116 0 : maExtNameModel.mbStdDocName = rAttribs.getBool( XML_ole, false );
117 0 : maExtNameModel.mbNotify = rAttribs.getBool( XML_advise, false );
118 0 : maExtNameModel.mbPreferPic = rAttribs.getBool( XML_preferPic, false );
119 0 : }
120 :
121 0 : void ExternalName::importValues( const AttributeList& rAttribs )
122 : {
123 0 : setResultSize( rAttribs.getInteger( XML_cols, 1 ), rAttribs.getInteger( XML_rows, 1 ) );
124 0 : }
125 :
126 0 : void ExternalName::importOleItem( const AttributeList& rAttribs )
127 : {
128 0 : maModel.maName = rAttribs.getXString( XML_name, OUString() );
129 : OSL_ENSURE( !maModel.maName.isEmpty(), "ExternalName::importOleItem - empty name" );
130 0 : maExtNameModel.mbOleObj = true;
131 0 : maExtNameModel.mbNotify = rAttribs.getBool( XML_advise, false );
132 0 : maExtNameModel.mbPreferPic = rAttribs.getBool( XML_preferPic, false );
133 0 : maExtNameModel.mbIconified = rAttribs.getBool( XML_icon, false );
134 0 : }
135 :
136 0 : void ExternalName::importExternalName( SequenceInputStream& rStrm )
137 : {
138 0 : rStrm >> maModel.maName;
139 : OSL_ENSURE( !maModel.maName.isEmpty(), "ExternalName::importExternalName - empty name" );
140 0 : }
141 :
142 0 : void ExternalName::importExternalNameFlags( SequenceInputStream& rStrm )
143 : {
144 : sal_uInt16 nFlags;
145 : sal_Int32 nSheetId;
146 0 : rStrm >> nFlags >> nSheetId;
147 : // index into sheet list of EXTSHEETNAMES (one-based in BIFF12)
148 0 : maModel.mnSheet = nSheetId - 1;
149 : // no flag for built-in names, as in OOXML...
150 0 : maExtNameModel.mbNotify = getFlag( nFlags, BIFF12_EXTNAME_AUTOMATIC );
151 0 : maExtNameModel.mbPreferPic = getFlag( nFlags, BIFF12_EXTNAME_PREFERPIC );
152 0 : maExtNameModel.mbStdDocName = getFlag( nFlags, BIFF12_EXTNAME_STDDOCNAME );
153 0 : maExtNameModel.mbOleObj = getFlag( nFlags, BIFF12_EXTNAME_OLEOBJECT );
154 0 : maExtNameModel.mbIconified = getFlag( nFlags, BIFF12_EXTNAME_ICONIFIED );
155 : OSL_ENSURE( (mrParentLink.getLinkType() == LINKTYPE_OLE) == maExtNameModel.mbOleObj,
156 : "ExternalName::importExternalNameFlags - wrong OLE flag in external name" );
157 0 : }
158 :
159 0 : void ExternalName::importDdeItemValues( SequenceInputStream& rStrm )
160 : {
161 : sal_Int32 nRows, nCols;
162 0 : rStrm >> nRows >> nCols;
163 0 : setResultSize( nCols, nRows );
164 0 : }
165 :
166 0 : void ExternalName::importDdeItemBool( SequenceInputStream& rStrm )
167 : {
168 0 : appendResultValue< double >( (rStrm.readuInt8() == 0) ? 0.0 : 1.0 );
169 0 : }
170 :
171 0 : void ExternalName::importDdeItemDouble( SequenceInputStream& rStrm )
172 : {
173 0 : appendResultValue( rStrm.readDouble() );
174 0 : }
175 :
176 0 : void ExternalName::importDdeItemError( SequenceInputStream& rStrm )
177 : {
178 0 : appendResultValue( BiffHelper::calcDoubleFromError( rStrm.readuInt8() ) );
179 0 : }
180 :
181 0 : void ExternalName::importDdeItemString( SequenceInputStream& rStrm )
182 : {
183 0 : appendResultValue( BiffHelper::readString( rStrm ) );
184 0 : }
185 :
186 : #if 0
187 : sal_Int32 ExternalName::getSheetCacheIndex() const
188 : {
189 : OSL_ENSURE( mrParentLink.getLinkType() == LINKTYPE_DDE, "ExternalName::getSheetCacheIndex - unexpected link type" );
190 : sal_Int32 nCacheIdx = -1;
191 : switch( getFilterType() )
192 : {
193 : case FILTER_OOXML:
194 : // OOXML/BIFF12: zero-based index into sheet list, -1 means global name
195 : if( maModel.mnSheet >= 0 )
196 : nCacheIdx = mrParentLink.getSheetIndex( maModel.mnSheet );
197 : break;
198 : case FILTER_BIFF:
199 : switch( getBiff() )
200 : {
201 : case BIFF2:
202 : case BIFF3:
203 : case BIFF4:
204 : break;
205 : case BIFF5:
206 : if( maModel.mnSheet > 0 )
207 : if( const ExternalLink* pExtLink = getExternalLinks().getExternalLink( maModel.mnSheet ).get() )
208 : if( pExtLink->getLinkType() == LINKTYPE_EXTERNAL )
209 : nCacheIdx = pExtLink->getSheetIndex();
210 : break;
211 : case BIFF8:
212 : if( maModel.mnSheet > 0 )
213 : nCacheIdx = mrParentLink.getSheetIndex( maModel.mnSheet - 1 );
214 : break;
215 : case BIFF_UNKNOWN:
216 : break;
217 : }
218 : break;
219 : case FILTER_UNKNOWN:
220 : break;
221 : }
222 : return nCacheIdx;
223 : }
224 : #endif
225 :
226 0 : bool ExternalName::getDdeItemInfo( DDEItemInfo& orItemInfo ) const
227 : {
228 0 : if( (mrParentLink.getLinkType() == LINKTYPE_DDE) && !maModel.maName.isEmpty() )
229 : {
230 0 : orItemInfo.Item = maModel.maName;
231 0 : orItemInfo.Results = ContainerHelper::matrixToSequenceSequence( maResults );
232 0 : return true;
233 : }
234 0 : return false;
235 : }
236 :
237 0 : bool ExternalName::getDdeLinkData( OUString& orDdeServer, OUString& orDdeTopic, OUString& orDdeItem )
238 : {
239 0 : if( (mrParentLink.getLinkType() == LINKTYPE_DDE) && !maModel.maName.isEmpty() )
240 : {
241 : // try to create a DDE link and to set the imported link results
242 0 : if( !mbDdeLinkCreated ) try
243 : {
244 0 : PropertySet aDocProps( getDocument() );
245 0 : Reference< XDDELinks > xDdeLinks( aDocProps.getAnyProperty( PROP_DDELinks ), UNO_QUERY_THROW );
246 0 : mxDdeLink = xDdeLinks->addDDELink( mrParentLink.getClassName(), mrParentLink.getTargetUrl(), maModel.maName, ::com::sun::star::sheet::DDELinkMode_DEFAULT );
247 0 : mbDdeLinkCreated = true; // ignore if setting results fails
248 0 : if( !maResults.empty() )
249 : {
250 0 : Reference< XDDELinkResults > xResults( mxDdeLink, UNO_QUERY_THROW );
251 0 : xResults->setResults( ContainerHelper::matrixToSequenceSequence( maResults ) );
252 0 : }
253 : }
254 0 : catch( Exception& )
255 : {
256 : OSL_FAIL( "ExternalName::getDdeLinkData - cannot create DDE link" );
257 : }
258 : // get link data from created DDE link
259 0 : if( mxDdeLink.is() )
260 : {
261 0 : orDdeServer = mxDdeLink->getApplication();
262 0 : orDdeTopic = mxDdeLink->getTopic();
263 0 : orDdeItem = mxDdeLink->getItem();
264 0 : return true;
265 : }
266 : }
267 0 : return false;
268 : }
269 :
270 : // private --------------------------------------------------------------------
271 :
272 0 : void ExternalName::setResultSize( sal_Int32 nColumns, sal_Int32 nRows )
273 : {
274 : OSL_ENSURE( (mrParentLink.getLinkType() == LINKTYPE_DDE) || (mrParentLink.getLinkType() == LINKTYPE_OLE) ||
275 : (mrParentLink.getLinkType() == LINKTYPE_MAYBE_DDE_OLE), "ExternalName::setResultSize - wrong link type" );
276 : OSL_ENSURE( (nRows > 0) && (nColumns > 0), "ExternalName::setResultSize - invalid matrix size" );
277 0 : const CellAddress& rMaxPos = getAddressConverter().getMaxApiAddress();
278 0 : if( (0 < nRows) && (nRows <= rMaxPos.Row + 1) && (0 < nColumns) && (nColumns <= rMaxPos.Column + 1) )
279 0 : maResults.resize( static_cast< size_t >( nColumns ), static_cast< size_t >( nRows ), Any( BiffHelper::calcDoubleFromError( BIFF_ERR_NA ) ) );
280 : else
281 0 : maResults.clear();
282 0 : maCurrIt = maResults.begin();
283 0 : }
284 :
285 : // ============================================================================
286 :
287 0 : void LinkSheetRange::setDeleted()
288 : {
289 0 : meType = LINKSHEETRANGE_INTERNAL;
290 0 : mnDocLink = mnFirst = mnLast = -1;
291 0 : }
292 :
293 0 : void LinkSheetRange::setSameSheet()
294 : {
295 0 : meType = LINKSHEETRANGE_SAMESHEET;
296 0 : mnDocLink = -1;
297 0 : mnFirst = mnLast = 0;
298 0 : }
299 :
300 0 : void LinkSheetRange::setRange( sal_Int32 nFirst, sal_Int32 nLast )
301 : {
302 0 : meType = LINKSHEETRANGE_INTERNAL;
303 0 : mnDocLink = -1;
304 0 : mnFirst = ::std::min( nFirst, nLast );
305 0 : mnLast = ::std::max( nFirst, nLast );
306 0 : }
307 :
308 0 : void LinkSheetRange::setExternalRange( sal_Int32 nDocLink, sal_Int32 nFirst, sal_Int32 nLast )
309 : {
310 0 : if( nDocLink < 0 )
311 : {
312 0 : setDeleted();
313 : }
314 : else
315 : {
316 0 : meType = LINKSHEETRANGE_EXTERNAL;
317 0 : mnDocLink = nDocLink;
318 0 : mnFirst = ::std::min( nFirst, nLast );
319 0 : mnLast = ::std::max( nFirst, nLast );
320 : }
321 0 : }
322 :
323 : // ============================================================================
324 :
325 11 : ExternalLink::ExternalLink( const WorkbookHelper& rHelper ) :
326 : WorkbookHelper( rHelper ),
327 : meLinkType( LINKTYPE_UNKNOWN ),
328 11 : meFuncLibType( FUNCLIB_UNKNOWN )
329 : {
330 11 : }
331 :
332 0 : void ExternalLink::importExternalReference( const AttributeList& rAttribs )
333 : {
334 0 : maRelId = rAttribs.getString( R_TOKEN( id ), OUString() );
335 0 : }
336 :
337 0 : void ExternalLink::importExternalBook( const Relations& rRelations, const AttributeList& rAttribs )
338 : {
339 0 : parseExternalReference( rRelations, rAttribs.getString( R_TOKEN( id ), OUString() ) );
340 0 : }
341 :
342 0 : void ExternalLink::importSheetName( const AttributeList& rAttribs )
343 : {
344 0 : insertExternalSheet( rAttribs.getXString( XML_val, OUString() ) );
345 0 : }
346 :
347 0 : void ExternalLink::importDefinedName( const AttributeList& rAttribs )
348 : {
349 0 : createExternalName()->importDefinedName( rAttribs );
350 0 : }
351 :
352 0 : void ExternalLink::importDdeLink( const AttributeList& rAttribs )
353 : {
354 0 : OUString aDdeService = rAttribs.getXString( XML_ddeService, OUString() );
355 0 : OUString aDdeTopic = rAttribs.getXString( XML_ddeTopic, OUString() );
356 0 : setDdeOleTargetUrl( aDdeService, aDdeTopic, LINKTYPE_DDE );
357 0 : }
358 :
359 0 : ExternalNameRef ExternalLink::importDdeItem( const AttributeList& rAttribs )
360 : {
361 0 : ExternalNameRef xExtName = createExternalName();
362 0 : xExtName->importDdeItem( rAttribs );
363 0 : return xExtName;
364 : }
365 :
366 0 : void ExternalLink::importOleLink( const Relations& rRelations, const AttributeList& rAttribs )
367 : {
368 0 : OUString aProgId = rAttribs.getXString( XML_progId, OUString() );
369 0 : OUString aTargetUrl = rRelations.getExternalTargetFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) );
370 0 : setDdeOleTargetUrl( aProgId, aTargetUrl, LINKTYPE_OLE );
371 0 : }
372 :
373 0 : ExternalNameRef ExternalLink::importOleItem( const AttributeList& rAttribs )
374 : {
375 0 : ExternalNameRef xExtName = createExternalName();
376 0 : xExtName->importOleItem( rAttribs );
377 0 : return xExtName;
378 : }
379 :
380 0 : void ExternalLink::importExternalRef( SequenceInputStream& rStrm )
381 : {
382 0 : rStrm >> maRelId;
383 0 : }
384 :
385 0 : void ExternalLink::importExternalSelf( SequenceInputStream& )
386 : {
387 0 : meLinkType = LINKTYPE_SELF;
388 0 : }
389 :
390 0 : void ExternalLink::importExternalSame( SequenceInputStream& )
391 : {
392 0 : meLinkType = LINKTYPE_SAME;
393 0 : }
394 :
395 0 : void ExternalLink::importExternalAddin( SequenceInputStream& )
396 : {
397 0 : meLinkType = LINKTYPE_UNKNOWN;
398 0 : }
399 :
400 0 : void ExternalLink::importExternalBook( const Relations& rRelations, SequenceInputStream& rStrm )
401 : {
402 0 : switch( rStrm.readuInt16() )
403 : {
404 : case BIFF12_EXTERNALBOOK_BOOK:
405 0 : parseExternalReference( rRelations, BiffHelper::readString( rStrm ) );
406 0 : break;
407 : case BIFF12_EXTERNALBOOK_DDE:
408 : {
409 0 : OUString aDdeService, aDdeTopic;
410 0 : rStrm >> aDdeService >> aDdeTopic;
411 0 : setDdeOleTargetUrl( aDdeService, aDdeTopic, LINKTYPE_DDE );
412 : }
413 0 : break;
414 : case BIFF12_EXTERNALBOOK_OLE:
415 : {
416 0 : OUString aTargetUrl = rRelations.getExternalTargetFromRelId( BiffHelper::readString( rStrm ) );
417 0 : OUString aProgId = BiffHelper::readString( rStrm );
418 0 : setDdeOleTargetUrl( aProgId, aTargetUrl, LINKTYPE_OLE );
419 : }
420 0 : break;
421 : default:
422 : OSL_FAIL( "ExternalLink::importExternalBook - unknown link type" );
423 : }
424 0 : }
425 :
426 0 : void ExternalLink::importExtSheetNames( SequenceInputStream& rStrm )
427 : {
428 : // load external sheet names and create the sheet caches in the Calc document
429 : OSL_ENSURE( (meLinkType == LINKTYPE_EXTERNAL) || (meLinkType == LINKTYPE_LIBRARY),
430 : "ExternalLink::importExtSheetNames - invalid link type" );
431 0 : if( meLinkType == LINKTYPE_EXTERNAL ) // ignore sheets of external libraries
432 0 : for( sal_Int32 nSheet = 0, nCount = rStrm.readInt32(); !rStrm.isEof() && (nSheet < nCount); ++nSheet )
433 0 : insertExternalSheet( BiffHelper::readString( rStrm ) );
434 0 : }
435 :
436 0 : ExternalNameRef ExternalLink::importExternalName( SequenceInputStream& rStrm )
437 : {
438 0 : ExternalNameRef xExtName = createExternalName();
439 0 : xExtName->importExternalName( rStrm );
440 0 : return xExtName;
441 : }
442 :
443 7 : ExternalLinkInfo ExternalLink::getLinkInfo() const
444 : {
445 7 : ExternalLinkInfo aLinkInfo;
446 7 : switch( meLinkType )
447 : {
448 : case LINKTYPE_SELF:
449 : case LINKTYPE_SAME:
450 : case LINKTYPE_INTERNAL:
451 7 : aLinkInfo.Type = ::com::sun::star::sheet::ExternalLinkType::SELF;
452 7 : break;
453 : case LINKTYPE_EXTERNAL:
454 0 : aLinkInfo.Type = ::com::sun::star::sheet::ExternalLinkType::DOCUMENT;
455 0 : aLinkInfo.Data <<= maTargetUrl;
456 0 : break;
457 : case LINKTYPE_LIBRARY:
458 : // parser will return library function names in OPCODE_BAD string tokens
459 0 : aLinkInfo.Type = ::com::sun::star::sheet::ExternalLinkType::SPECIAL;
460 0 : break;
461 : case LINKTYPE_DDE:
462 : {
463 0 : aLinkInfo.Type = ::com::sun::star::sheet::ExternalLinkType::DDE;
464 0 : DDELinkInfo aDdeLinkInfo;
465 0 : aDdeLinkInfo.Service = maClassName;
466 0 : aDdeLinkInfo.Topic = maTargetUrl;
467 0 : ::std::vector< DDEItemInfo > aItemInfos;
468 0 : DDEItemInfo aItemInfo;
469 0 : for( ExternalNameVector::const_iterator aIt = maExtNames.begin(), aEnd = maExtNames.end(); aIt != aEnd; ++aIt )
470 0 : if( (*aIt)->getDdeItemInfo( aItemInfo ) )
471 0 : aItemInfos.push_back( aItemInfo );
472 0 : aDdeLinkInfo.Items = ContainerHelper::vectorToSequence( aItemInfos );
473 0 : aLinkInfo.Data <<= aDdeLinkInfo;
474 : }
475 0 : break;
476 : default:
477 0 : aLinkInfo.Type = ::com::sun::star::sheet::ExternalLinkType::UNKNOWN;
478 : }
479 7 : return aLinkInfo;
480 : }
481 :
482 0 : FunctionLibraryType ExternalLink::getFuncLibraryType() const
483 : {
484 0 : return (meLinkType == LINKTYPE_LIBRARY) ? meFuncLibType : FUNCLIB_UNKNOWN;
485 : }
486 :
487 0 : sal_Int32 ExternalLink::getDocumentLinkIndex() const
488 : {
489 : OSL_ENSURE( meLinkType == LINKTYPE_EXTERNAL, "ExternalLink::getDocumentLinkIndex - invalid link type" );
490 0 : return mxDocLink.is() ? mxDocLink->getTokenIndex() : -1;
491 : }
492 :
493 0 : sal_Int32 ExternalLink::getSheetCacheIndex( sal_Int32 nTabId ) const
494 : {
495 : OSL_ENSURE( meLinkType == LINKTYPE_EXTERNAL, "ExternalLink::getSheetCacheIndex - invalid link type" );
496 : OSL_ENSURE( (nTabId == 0) || (getFilterType() == FILTER_OOXML) || (getBiff() == BIFF8),
497 : "ExternalLink::getSheetCacheIndex - invalid sheet index" );
498 0 : return ContainerHelper::getVectorElement( maSheetCaches, nTabId, -1 );
499 : }
500 :
501 0 : Reference< XExternalSheetCache > ExternalLink::getSheetCache( sal_Int32 nTabId ) const
502 : {
503 0 : sal_Int32 nCacheIdx = getSheetCacheIndex( nTabId );
504 0 : if( mxDocLink.is() && (nCacheIdx >= 0) ) try
505 : {
506 : // existing mxDocLink implies that this is an external link
507 0 : Reference< XExternalSheetCache > xSheetCache( mxDocLink->getByIndex( nCacheIdx ), UNO_QUERY_THROW );
508 0 : return xSheetCache;
509 : }
510 0 : catch( Exception& )
511 : {
512 : }
513 0 : return 0;
514 : }
515 :
516 0 : void ExternalLink::getSheetRange( LinkSheetRange& orSheetRange, sal_Int32 nTabId1, sal_Int32 nTabId2 ) const
517 : {
518 0 : switch( meLinkType )
519 : {
520 : case LINKTYPE_SAME:
521 0 : orSheetRange.setSameSheet();
522 0 : break;
523 :
524 : case LINKTYPE_SELF:
525 : case LINKTYPE_INTERNAL:
526 0 : orSheetRange.setRange( nTabId1, nTabId2 );
527 0 : break;
528 :
529 : case LINKTYPE_EXTERNAL:
530 : {
531 0 : sal_Int32 nDocLinkIdx = getDocumentLinkIndex();
532 0 : switch( getFilterType() )
533 : {
534 : case FILTER_OOXML:
535 : // BIFF12: passed indexes point into sheet list of EXTSHEETLIST
536 0 : orSheetRange.setExternalRange( nDocLinkIdx, getSheetCacheIndex( nTabId1 ), getSheetCacheIndex( nTabId2 ) );
537 0 : break;
538 : case FILTER_BIFF:
539 0 : switch( getBiff() )
540 : {
541 : case BIFF2:
542 : case BIFF3:
543 : case BIFF4:
544 0 : orSheetRange.setExternalRange( nDocLinkIdx, getSheetCacheIndex( nTabId1 ), getSheetCacheIndex( nTabId2 ) );
545 0 : break;
546 : case BIFF5:
547 : // BIFF5: first sheet from this external link, last sheet is passed in nTabId2
548 0 : if( const ExternalLink* pExtLink2 = getExternalLinks().getExternalLink( nTabId2 ).get() )
549 0 : if( (pExtLink2->getLinkType() == LINKTYPE_EXTERNAL) && (maTargetUrl == pExtLink2->getTargetUrl()) )
550 0 : orSheetRange.setExternalRange( nDocLinkIdx, getSheetCacheIndex(), pExtLink2->getSheetCacheIndex() );
551 0 : break;
552 : case BIFF8:
553 : // BIFF8: passed indexes point into sheet list of EXTERNALBOOK
554 0 : orSheetRange.setExternalRange( nDocLinkIdx, getSheetCacheIndex( nTabId1 ), getSheetCacheIndex( nTabId2 ) );
555 0 : break;
556 0 : case BIFF_UNKNOWN: break;
557 : }
558 0 : break;
559 0 : case FILTER_UNKNOWN: break;
560 : }
561 : }
562 0 : break;
563 :
564 : default:
565 : // unsupported/unexpected link type: #REF! error
566 0 : orSheetRange.setDeleted();
567 : }
568 0 : }
569 :
570 0 : ExternalNameRef ExternalLink::getNameByIndex( sal_Int32 nIndex ) const
571 : {
572 0 : return maExtNames.get( nIndex );
573 : }
574 :
575 : // private --------------------------------------------------------------------
576 :
577 : #define OOX_TARGETTYPE_EXTLINK CREATE_OFFICEDOC_RELATION_TYPE( "externalLinkPath" )
578 : #define OOX_TARGETTYPE_LIBRARY CREATE_MSOFFICE_RELATION_TYPE( "xlExternalLinkPath/xlLibrary" )
579 :
580 0 : void ExternalLink::setExternalTargetUrl( const OUString& rTargetUrl, const OUString& rTargetType )
581 : {
582 0 : meLinkType = LINKTYPE_UNKNOWN;
583 0 : if( rTargetType == OOX_TARGETTYPE_EXTLINK )
584 : {
585 0 : maTargetUrl = getBaseFilter().getAbsoluteUrl( rTargetUrl );
586 0 : if( !maTargetUrl.isEmpty() )
587 0 : meLinkType = LINKTYPE_EXTERNAL;
588 : }
589 0 : else if( rTargetType == OOX_TARGETTYPE_LIBRARY )
590 : {
591 0 : meLinkType = LINKTYPE_LIBRARY;
592 0 : meFuncLibType = getFormulaParser().getFuncLibTypeFromLibraryName( rTargetUrl );
593 : }
594 : OSL_ENSURE( meLinkType != LINKTYPE_UNKNOWN, "ExternalLink::setExternalTargetUrl - empty target URL or unknown target type" );
595 :
596 : // create the external document link API object that will contain the sheet caches
597 0 : if( meLinkType == LINKTYPE_EXTERNAL ) try
598 : {
599 0 : PropertySet aDocProps( getDocument() );
600 0 : Reference< XExternalDocLinks > xDocLinks( aDocProps.getAnyProperty( PROP_ExternalDocLinks ), UNO_QUERY_THROW );
601 0 : mxDocLink = xDocLinks->addDocLink( maTargetUrl );
602 : }
603 0 : catch( Exception& )
604 : {
605 : }
606 0 : }
607 :
608 0 : void ExternalLink::setDdeOleTargetUrl( const OUString& rClassName, const OUString& rTargetUrl, ExternalLinkType eLinkType )
609 : {
610 0 : maClassName = rClassName;
611 0 : maTargetUrl = rTargetUrl;
612 0 : meLinkType = (maClassName.isEmpty() || maTargetUrl.isEmpty()) ? LINKTYPE_UNKNOWN : eLinkType;
613 : OSL_ENSURE( meLinkType == eLinkType, "ExternalLink::setDdeOleTargetUrl - missing classname or target" );
614 0 : }
615 :
616 0 : void ExternalLink::parseExternalReference( const Relations& rRelations, const OUString& rRelId )
617 : {
618 0 : if( const Relation* pRelation = rRelations.getRelationFromRelId( rRelId ) )
619 0 : setExternalTargetUrl( pRelation->maTarget, pRelation->maType );
620 0 : }
621 :
622 0 : void ExternalLink::insertExternalSheet( const OUString& rSheetName )
623 : {
624 : OSL_ENSURE( !rSheetName.isEmpty(), "ExternalLink::insertExternalSheet - empty sheet name" );
625 0 : if( mxDocLink.is() )
626 : {
627 0 : Reference< XExternalSheetCache > xSheetCache = mxDocLink->addSheetCache( rSheetName, false );
628 0 : sal_Int32 nCacheIdx = xSheetCache.is() ? xSheetCache->getTokenIndex() : -1;
629 0 : maSheetCaches.push_back( nCacheIdx );
630 : }
631 0 : }
632 :
633 0 : ExternalNameRef ExternalLink::createExternalName()
634 : {
635 0 : ExternalNameRef xExtName( new ExternalName( *this ) );
636 0 : maExtNames.push_back( xExtName );
637 0 : return xExtName;
638 : }
639 :
640 : // ============================================================================
641 :
642 0 : RefSheetsModel::RefSheetsModel() :
643 : mnExtRefId( -1 ),
644 : mnTabId1( -1 ),
645 0 : mnTabId2( -1 )
646 : {
647 0 : }
648 :
649 0 : void RefSheetsModel::readBiff12Data( SequenceInputStream& rStrm )
650 : {
651 0 : rStrm >> mnExtRefId >> mnTabId1 >> mnTabId2;
652 0 : }
653 :
654 : // ----------------------------------------------------------------------------
655 :
656 11 : ExternalLinkBuffer::ExternalLinkBuffer( const WorkbookHelper& rHelper ) :
657 : WorkbookHelper( rHelper ),
658 11 : mxSelfRef( new ExternalLink( rHelper ) ),
659 22 : mbUseRefSheets( false )
660 : {
661 11 : mxSelfRef->setSelfLinkType();
662 11 : }
663 :
664 0 : ExternalLinkRef ExternalLinkBuffer::importExternalReference( const AttributeList& rAttribs )
665 : {
666 0 : ExternalLinkRef xExtLink = createExternalLink();
667 0 : xExtLink->importExternalReference( rAttribs );
668 0 : maExtLinks.push_back( xExtLink );
669 0 : return xExtLink;
670 : }
671 :
672 0 : ExternalLinkRef ExternalLinkBuffer::importExternalRef( SequenceInputStream& rStrm )
673 : {
674 0 : mbUseRefSheets = true;
675 0 : ExternalLinkRef xExtLink = createExternalLink();
676 0 : xExtLink->importExternalRef( rStrm );
677 0 : maExtLinks.push_back( xExtLink );
678 0 : return xExtLink;
679 : }
680 :
681 0 : void ExternalLinkBuffer::importExternalSelf( SequenceInputStream& rStrm )
682 : {
683 0 : mbUseRefSheets = true;
684 0 : createExternalLink()->importExternalSelf( rStrm );
685 0 : }
686 :
687 0 : void ExternalLinkBuffer::importExternalSame( SequenceInputStream& rStrm )
688 : {
689 0 : mbUseRefSheets = true;
690 0 : createExternalLink()->importExternalSame( rStrm );
691 0 : }
692 :
693 0 : void ExternalLinkBuffer::importExternalAddin( SequenceInputStream& rStrm )
694 : {
695 0 : mbUseRefSheets = true;
696 0 : createExternalLink()->importExternalAddin( rStrm );
697 0 : }
698 :
699 0 : void ExternalLinkBuffer::importExternalSheets( SequenceInputStream& rStrm )
700 : {
701 : OSL_ENSURE( mbUseRefSheets, "ExternalLinkBuffer::importExternalSheets - missing EXTERNALREFS records" );
702 0 : mbUseRefSheets = true;
703 : OSL_ENSURE( maRefSheets.empty(), "ExternalLinkBuffer::importExternalSheets - multiple EXTERNALSHEETS records" );
704 0 : maRefSheets.clear();
705 : sal_Int32 nRefCount;
706 0 : rStrm >> nRefCount;
707 0 : size_t nMaxCount = getLimitedValue< size_t, sal_Int64 >( nRefCount, 0, rStrm.getRemaining() / 12 );
708 0 : maRefSheets.reserve( nMaxCount );
709 0 : for( size_t nRefId = 0; !rStrm.isEof() && (nRefId < nMaxCount); ++nRefId )
710 : {
711 0 : RefSheetsModel aRefSheets;
712 0 : aRefSheets.readBiff12Data( rStrm );
713 0 : maRefSheets.push_back( aRefSheets );
714 : }
715 0 : }
716 :
717 7 : Sequence< ExternalLinkInfo > ExternalLinkBuffer::getLinkInfos() const
718 : {
719 7 : ::std::vector< ExternalLinkInfo > aLinkInfos;
720 : // XML formula parser also used in BIFF12 documents, e.g. replacement formulas in unsupported conditional formattings
721 : OSL_ENSURE( getFilterType() == FILTER_OOXML, "ExternalLinkBuffer::getLinkInfos - unexpected file format" );
722 : // add entry for implicit index 0 (self reference to this document)
723 7 : aLinkInfos.push_back( mxSelfRef->getLinkInfo() );
724 7 : for( ExternalLinkVec::const_iterator aIt = maExtLinks.begin(), aEnd = maExtLinks.end(); aIt != aEnd; ++aIt )
725 0 : aLinkInfos.push_back( (*aIt)->getLinkInfo() );
726 7 : return ContainerHelper::vectorToSequence( aLinkInfos );
727 : }
728 :
729 0 : ExternalLinkRef ExternalLinkBuffer::getExternalLink( sal_Int32 nRefId, bool bUseRefSheets ) const
730 : {
731 0 : ExternalLinkRef xExtLink;
732 0 : switch( getFilterType() )
733 : {
734 : case FILTER_OOXML:
735 : // OOXML: 0 = this document, otherwise one-based index into link list
736 0 : if( !bUseRefSheets || !mbUseRefSheets )
737 0 : xExtLink = (nRefId == 0) ? mxSelfRef : maLinks.get( nRefId - 1 );
738 : // BIFF12: zero-based index into ref-sheets list
739 0 : else if( const RefSheetsModel* pRefSheets = getRefSheets( nRefId ) )
740 0 : xExtLink = maLinks.get( pRefSheets->mnExtRefId );
741 0 : break;
742 : case FILTER_BIFF:
743 0 : switch( getBiff() )
744 : {
745 : case BIFF2:
746 : case BIFF3:
747 : case BIFF4:
748 : // one-based index to EXTERNSHEET records
749 0 : xExtLink = maLinks.get( nRefId - 1 );
750 0 : break;
751 : case BIFF5:
752 0 : if( nRefId < 0 )
753 : {
754 : // internal links in formula tokens have negative index
755 0 : xExtLink = maLinks.get( -nRefId - 1 );
756 0 : if( xExtLink.get() && !xExtLink->isInternalLink() )
757 0 : xExtLink.reset();
758 : }
759 : else
760 : {
761 : // one-based index to EXTERNSHEET records
762 0 : xExtLink = maLinks.get( nRefId - 1 );
763 : }
764 0 : break;
765 : case BIFF8:
766 : // zero-based index into REF list in EXTERNSHEET record
767 0 : if( const RefSheetsModel* pRefSheets = getRefSheets( nRefId ) )
768 0 : xExtLink = maLinks.get( pRefSheets->mnExtRefId );
769 0 : break;
770 0 : case BIFF_UNKNOWN: break;
771 : }
772 0 : break;
773 0 : case FILTER_UNKNOWN: break;
774 : }
775 0 : return xExtLink;
776 : }
777 :
778 0 : LinkSheetRange ExternalLinkBuffer::getSheetRange( sal_Int32 nRefId, sal_Int16 nTabId1, sal_Int16 nTabId2 ) const
779 : {
780 : OSL_ENSURE( getBiff() <= BIFF5, "ExternalLinkBuffer::getSheetRange - wrong BIFF version" );
781 0 : LinkSheetRange aSheetRange;
782 0 : if( const ExternalLink* pExtLink = getExternalLink( nRefId ).get() )
783 0 : pExtLink->getSheetRange( aSheetRange, nTabId1, nTabId2 );
784 0 : return aSheetRange;
785 : }
786 :
787 0 : LinkSheetRange ExternalLinkBuffer::getSheetRange( sal_Int32 nRefId ) const
788 : {
789 : OSL_ENSURE( ((getFilterType() == FILTER_OOXML) && mbUseRefSheets) || (getBiff() == BIFF8), "ExternalLinkBuffer::getSheetRange - wrong BIFF version" );
790 0 : LinkSheetRange aSheetRange;
791 0 : if( const ExternalLink* pExtLink = getExternalLink( nRefId ).get() )
792 0 : if( const RefSheetsModel* pRefSheets = getRefSheets( nRefId ) )
793 0 : pExtLink->getSheetRange( aSheetRange, pRefSheets->mnTabId1, pRefSheets->mnTabId2 );
794 0 : return aSheetRange;
795 : }
796 :
797 : // private --------------------------------------------------------------------
798 :
799 0 : ExternalLinkRef ExternalLinkBuffer::createExternalLink()
800 : {
801 0 : ExternalLinkRef xExtLink( new ExternalLink( *this ) );
802 0 : maLinks.push_back( xExtLink );
803 0 : return xExtLink;
804 : }
805 :
806 0 : const RefSheetsModel* ExternalLinkBuffer::getRefSheets( sal_Int32 nRefId ) const
807 : {
808 0 : return ((0 <= nRefId) && (static_cast< size_t >( nRefId ) < maRefSheets.size())) ?
809 0 : &maRefSheets[ static_cast< size_t >( nRefId ) ] : 0;
810 : }
811 :
812 : // ============================================================================
813 :
814 : } // namespace xls
815 9 : } // namespace oox
816 :
817 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|