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