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