1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #include "oox/xls/externallinkbuffer.hxx" 29 30 #include <com/sun/star/sheet/ComplexReference.hpp> 31 #include <com/sun/star/sheet/DDELinkInfo.hpp> 32 #include <com/sun/star/sheet/ExternalLinkType.hpp> 33 #include <com/sun/star/sheet/ExternalReference.hpp> 34 #include <com/sun/star/sheet/ReferenceFlags.hpp> 35 #include <com/sun/star/sheet/SingleReference.hpp> 36 #include <com/sun/star/sheet/XDDELinks.hpp> 37 #include <com/sun/star/sheet/XDDELink.hpp> 38 #include <com/sun/star/sheet/XDDELinkResults.hpp> 39 #include <com/sun/star/sheet/XExternalDocLink.hpp> 40 #include <com/sun/star/sheet/XExternalDocLinks.hpp> 41 #include <rtl/strbuf.hxx> 42 #include "oox/core/filterbase.hxx" 43 #include "oox/helper/attributelist.hxx" 44 #include "oox/xls/addressconverter.hxx" 45 #include "oox/xls/biffinputstream.hxx" 46 #include "oox/xls/excelhandlers.hxx" 47 #include "oox/xls/formulaparser.hxx" 48 #include "oox/xls/worksheetbuffer.hxx" 49 50 namespace oox { 51 namespace xls { 52 53 // ============================================================================ 54 55 using namespace ::com::sun::star::sheet; 56 using namespace ::com::sun::star::table; 57 using namespace ::com::sun::star::uno; 58 59 using ::oox::core::Relation; 60 using ::oox::core::Relations; 61 using ::rtl::OString; 62 using ::rtl::OStringBuffer; 63 using ::rtl::OStringToOUString; 64 using ::rtl::OUString; 65 66 // ============================================================================ 67 68 namespace { 69 70 const sal_uInt16 BIFF12_EXTERNALBOOK_BOOK = 0; 71 const sal_uInt16 BIFF12_EXTERNALBOOK_DDE = 1; 72 const sal_uInt16 BIFF12_EXTERNALBOOK_OLE = 2; 73 74 const sal_uInt16 BIFF12_EXTNAME_AUTOMATIC = 0x0002; 75 const sal_uInt16 BIFF12_EXTNAME_PREFERPIC = 0x0004; 76 const sal_uInt16 BIFF12_EXTNAME_STDDOCNAME = 0x0008; 77 const sal_uInt16 BIFF12_EXTNAME_OLEOBJECT = 0x0010; 78 const sal_uInt16 BIFF12_EXTNAME_ICONIFIED = 0x0020; 79 80 const sal_uInt16 BIFF_EXTNAME_BUILTIN = 0x0001; 81 const sal_uInt16 BIFF_EXTNAME_AUTOMATIC = 0x0002; 82 const sal_uInt16 BIFF_EXTNAME_PREFERPIC = 0x0004; 83 const sal_uInt16 BIFF_EXTNAME_STDDOCNAME = 0x0008; 84 const sal_uInt16 BIFF_EXTNAME_OLEOBJECT = 0x0010; 85 const sal_uInt16 BIFF_EXTNAME_ICONIFIED = 0x8000; 86 87 } // namespace 88 89 // ============================================================================ 90 91 ExternalNameModel::ExternalNameModel() : 92 mbBuiltIn( false ), 93 mbNotify( false ), 94 mbPreferPic( false ), 95 mbStdDocName( false ), 96 mbOleObj( false ), 97 mbIconified( false ) 98 { 99 } 100 101 // ============================================================================ 102 103 ExternalName::ExternalName( const ExternalLink& rParentLink ) : 104 DefinedNameBase( rParentLink ), 105 mrParentLink( rParentLink ), 106 mnStorageId( 0 ), 107 mbDdeLinkCreated( false ) 108 { 109 } 110 111 void ExternalName::importDefinedName( const AttributeList& rAttribs ) 112 { 113 maModel.maName = rAttribs.getXString( XML_name, OUString() ); 114 OSL_ENSURE( maModel.maName.getLength() > 0, "ExternalName::importDefinedName - empty name" ); 115 // zero-based index into sheet list of externalBook 116 maModel.mnSheet = rAttribs.getInteger( XML_sheetId, -1 ); 117 } 118 119 void ExternalName::importDdeItem( const AttributeList& rAttribs ) 120 { 121 maModel.maName = rAttribs.getXString( XML_name, OUString() ); 122 OSL_ENSURE( maModel.maName.getLength() > 0, "ExternalName::importDdeItem - empty name" ); 123 maExtNameModel.mbOleObj = false; 124 maExtNameModel.mbStdDocName = rAttribs.getBool( XML_ole, false ); 125 maExtNameModel.mbNotify = rAttribs.getBool( XML_advise, false ); 126 maExtNameModel.mbPreferPic = rAttribs.getBool( XML_preferPic, false ); 127 } 128 129 void ExternalName::importValues( const AttributeList& rAttribs ) 130 { 131 setResultSize( rAttribs.getInteger( XML_cols, 1 ), rAttribs.getInteger( XML_rows, 1 ) ); 132 } 133 134 void ExternalName::importOleItem( const AttributeList& rAttribs ) 135 { 136 maModel.maName = rAttribs.getXString( XML_name, OUString() ); 137 OSL_ENSURE( maModel.maName.getLength() > 0, "ExternalName::importOleItem - empty name" ); 138 maExtNameModel.mbOleObj = true; 139 maExtNameModel.mbNotify = rAttribs.getBool( XML_advise, false ); 140 maExtNameModel.mbPreferPic = rAttribs.getBool( XML_preferPic, false ); 141 maExtNameModel.mbIconified = rAttribs.getBool( XML_icon, false ); 142 } 143 144 void ExternalName::importExternalName( SequenceInputStream& rStrm ) 145 { 146 rStrm >> maModel.maName; 147 OSL_ENSURE( maModel.maName.getLength() > 0, "ExternalName::importExternalName - empty name" ); 148 } 149 150 void ExternalName::importExternalNameFlags( SequenceInputStream& rStrm ) 151 { 152 sal_uInt16 nFlags; 153 sal_Int32 nSheetId; 154 rStrm >> nFlags >> nSheetId; 155 // index into sheet list of EXTSHEETNAMES (one-based in BIFF12) 156 maModel.mnSheet = nSheetId - 1; 157 // no flag for built-in names, as in OOXML... 158 maExtNameModel.mbNotify = getFlag( nFlags, BIFF12_EXTNAME_AUTOMATIC ); 159 maExtNameModel.mbPreferPic = getFlag( nFlags, BIFF12_EXTNAME_PREFERPIC ); 160 maExtNameModel.mbStdDocName = getFlag( nFlags, BIFF12_EXTNAME_STDDOCNAME ); 161 maExtNameModel.mbOleObj = getFlag( nFlags, BIFF12_EXTNAME_OLEOBJECT ); 162 maExtNameModel.mbIconified = getFlag( nFlags, BIFF12_EXTNAME_ICONIFIED ); 163 OSL_ENSURE( (mrParentLink.getLinkType() == LINKTYPE_OLE) == maExtNameModel.mbOleObj, 164 "ExternalName::importExternalNameFlags - wrong OLE flag in external name" ); 165 } 166 167 void ExternalName::importDdeItemValues( SequenceInputStream& rStrm ) 168 { 169 sal_Int32 nRows, nCols; 170 rStrm >> nRows >> nCols; 171 setResultSize( nCols, nRows ); 172 } 173 174 void ExternalName::importDdeItemBool( SequenceInputStream& rStrm ) 175 { 176 appendResultValue< double >( (rStrm.readuInt8() == 0) ? 0.0 : 1.0 ); 177 } 178 179 void ExternalName::importDdeItemDouble( SequenceInputStream& rStrm ) 180 { 181 appendResultValue( rStrm.readDouble() ); 182 } 183 184 void ExternalName::importDdeItemError( SequenceInputStream& rStrm ) 185 { 186 appendResultValue( BiffHelper::calcDoubleFromError( rStrm.readuInt8() ) ); 187 } 188 189 void ExternalName::importDdeItemString( SequenceInputStream& rStrm ) 190 { 191 appendResultValue( BiffHelper::readString( rStrm ) ); 192 } 193 194 void ExternalName::importExternalName( BiffInputStream& rStrm ) 195 { 196 sal_uInt16 nFlags = 0; 197 if( getBiff() >= BIFF3 ) 198 { 199 rStrm >> nFlags; 200 maExtNameModel.mbBuiltIn = getFlag( nFlags, BIFF_EXTNAME_BUILTIN ); 201 maExtNameModel.mbNotify = getFlag( nFlags, BIFF_EXTNAME_AUTOMATIC ); 202 maExtNameModel.mbPreferPic = getFlag( nFlags, BIFF_EXTNAME_PREFERPIC ); 203 204 // BIFF5-BIFF8: sheet index for sheet-local names, OLE settings 205 if( getBiff() >= BIFF5 ) 206 { 207 maExtNameModel.mbStdDocName = getFlag( nFlags, BIFF_EXTNAME_STDDOCNAME ); 208 maExtNameModel.mbOleObj = getFlag( nFlags, BIFF_EXTNAME_OLEOBJECT ); 209 maExtNameModel.mbIconified = getFlag( nFlags, BIFF_EXTNAME_ICONIFIED ); 210 211 if( maExtNameModel.mbOleObj ) 212 { 213 rStrm >> mnStorageId; 214 } 215 else 216 { 217 /* Import the reference ID for names that are sheet-local in 218 the external document. This index will be resolved later to 219 the index of the external sheet cache which is able to 220 provide the name of the sheet related to this defined name. 221 - BIFF5: one-based index to EXTERNSHEET record containing 222 the document and sheet name 223 - BIFF8: one-based index into EXTERNALBOOK sheet name list 224 The value zero means this external name is a global name. 225 */ 226 rStrm.skip( 2 ); 227 maModel.mnSheet = rStrm.readuInt16(); 228 } 229 } 230 } 231 232 maModel.maName = (getBiff() == BIFF8) ? 233 rStrm.readUniStringBody( rStrm.readuInt8() ) : 234 rStrm.readByteStringUC( false, getTextEncoding() ); 235 OSL_ENSURE( maModel.maName.getLength() > 0, "ExternalName::importExternalName - empty name" ); 236 237 // load cell references that are stored in hidden external names (seen in BIFF3-BIFF4) 238 bool bHiddenRef = (getBiff() <= BIFF4) && (maModel.maName.getLength() > 1) && (maModel.maName[ 0 ] == '\x01') && (rStrm.getRemaining() > 2); 239 switch( mrParentLink.getLinkType() ) 240 { 241 case LINKTYPE_INTERNAL: 242 // cell references to other internal sheets are stored in hidden external names 243 if( bHiddenRef && (getBiff() == BIFF4) && isWorkbookFile() ) 244 { 245 ApiTokenSequence aTokens = importBiffFormula( mrParentLink.getCalcSheetIndex(), rStrm ); 246 extractReference( aTokens ); 247 } 248 break; 249 250 case LINKTYPE_EXTERNAL: 251 // cell references to other documents are stored in hidden external names 252 if( bHiddenRef ) 253 { 254 ApiTokenSequence aTokens = importBiffFormula( 0, rStrm ); 255 extractExternalReference( aTokens ); 256 } 257 break; 258 259 case LINKTYPE_DDE: 260 case LINKTYPE_OLE: 261 case LINKTYPE_MAYBE_DDE_OLE: 262 // DDE/OLE link results 263 if( rStrm.getRemaining() > 3 ) 264 { 265 bool bBiff8 = getBiff() == BIFF8; 266 sal_Int32 nCols = rStrm.readuInt8(); 267 sal_Int32 nRows = rStrm.readuInt16(); 268 if( bBiff8 ) { ++nCols; ++nRows; } else if( nCols == 0 ) nCols = 256; 269 setResultSize( nCols, nRows ); 270 271 bool bLoop = true; 272 while( bLoop && !rStrm.isEof() && (maCurrIt != maResults.end()) ) 273 { 274 switch( rStrm.readuInt8() ) 275 { 276 case BIFF_DATATYPE_EMPTY: 277 appendResultValue( OUString() ); 278 rStrm.skip( 8 ); 279 break; 280 case BIFF_DATATYPE_DOUBLE: 281 appendResultValue( rStrm.readDouble() ); 282 break; 283 case BIFF_DATATYPE_STRING: 284 appendResultValue( bBiff8 ? rStrm.readUniString() : rStrm.readByteStringUC( false, getTextEncoding() ) ); 285 break; 286 case BIFF_DATATYPE_BOOL: 287 appendResultValue< double >( (rStrm.readuInt8() == 0) ? 0.0 : 1.0 ); 288 rStrm.skip( 7 ); 289 break; 290 case BIFF_DATATYPE_ERROR: 291 appendResultValue( BiffHelper::calcDoubleFromError( rStrm.readuInt8() ) ); 292 rStrm.skip( 7 ); 293 break; 294 default: 295 bLoop = false; 296 } 297 } 298 OSL_ENSURE( bLoop && !rStrm.isEof() && (maCurrIt == maResults.end()), 299 "ExternalName::importExternalName - stream error in result set" ); 300 } 301 break; 302 303 default:; 304 } 305 } 306 307 #if 0 308 sal_Int32 ExternalName::getSheetCacheIndex() const 309 { 310 OSL_ENSURE( mrParentLink.getLinkType() == LINKTYPE_DDE, "ExternalName::getSheetCacheIndex - unexpected link type" ); 311 sal_Int32 nCacheIdx = -1; 312 switch( getFilterType() ) 313 { 314 case FILTER_OOXML: 315 // OOXML/BIFF12: zero-based index into sheet list, -1 means global name 316 if( maModel.mnSheet >= 0 ) 317 nCacheIdx = mrParentLink.getSheetIndex( maModel.mnSheet ); 318 break; 319 case FILTER_BIFF: 320 switch( getBiff() ) 321 { 322 case BIFF2: 323 case BIFF3: 324 case BIFF4: 325 break; 326 case BIFF5: 327 if( maModel.mnSheet > 0 ) 328 if( const ExternalLink* pExtLink = getExternalLinks().getExternalLink( maModel.mnSheet ).get() ) 329 if( pExtLink->getLinkType() == LINKTYPE_EXTERNAL ) 330 nCacheIdx = pExtLink->getSheetIndex(); 331 break; 332 case BIFF8: 333 if( maModel.mnSheet > 0 ) 334 nCacheIdx = mrParentLink.getSheetIndex( maModel.mnSheet - 1 ); 335 break; 336 case BIFF_UNKNOWN: 337 break; 338 } 339 break; 340 case FILTER_UNKNOWN: 341 break; 342 } 343 return nCacheIdx; 344 } 345 #endif 346 347 bool ExternalName::getDdeItemInfo( DDEItemInfo& orItemInfo ) const 348 { 349 if( (mrParentLink.getLinkType() == LINKTYPE_DDE) && (maModel.maName.getLength() > 0) ) 350 { 351 orItemInfo.Item = maModel.maName; 352 orItemInfo.Results = ContainerHelper::matrixToSequenceSequence( maResults ); 353 return true; 354 } 355 return false; 356 } 357 358 bool ExternalName::getDdeLinkData( OUString& orDdeServer, OUString& orDdeTopic, OUString& orDdeItem ) 359 { 360 if( (mrParentLink.getLinkType() == LINKTYPE_DDE) && (maModel.maName.getLength() > 0) ) 361 { 362 // try to create a DDE link and to set the imported link results 363 if( !mbDdeLinkCreated ) try 364 { 365 PropertySet aDocProps( getDocument() ); 366 Reference< XDDELinks > xDdeLinks( aDocProps.getAnyProperty( PROP_DDELinks ), UNO_QUERY_THROW ); 367 mxDdeLink = xDdeLinks->addDDELink( mrParentLink.getClassName(), mrParentLink.getTargetUrl(), maModel.maName, ::com::sun::star::sheet::DDELinkMode_DEFAULT ); 368 mbDdeLinkCreated = true; // ignore if setting results fails 369 if( !maResults.empty() ) 370 { 371 Reference< XDDELinkResults > xResults( mxDdeLink, UNO_QUERY_THROW ); 372 xResults->setResults( ContainerHelper::matrixToSequenceSequence( maResults ) ); 373 } 374 } 375 catch( Exception& ) 376 { 377 OSL_ENSURE( false, "ExternalName::getDdeLinkData - cannot create DDE link" ); 378 } 379 // get link data from created DDE link 380 if( mxDdeLink.is() ) 381 { 382 orDdeServer = mxDdeLink->getApplication(); 383 orDdeTopic = mxDdeLink->getTopic(); 384 orDdeItem = mxDdeLink->getItem(); 385 return true; 386 } 387 } 388 return false; 389 } 390 391 // private -------------------------------------------------------------------- 392 393 namespace { 394 395 void lclSetSheetCacheIndex( SingleReference& orApiRef, sal_Int32 nCacheIdx ) 396 { 397 using namespace ::com::sun::star::sheet::ReferenceFlags; 398 setFlag( orApiRef.Flags, SHEET_RELATIVE, false ); 399 setFlag( orApiRef.Flags, SHEET_3D, true ); 400 orApiRef.Sheet = nCacheIdx; 401 } 402 403 } // namespace 404 405 void ExternalName::extractExternalReference( const ApiTokenSequence& rTokens ) 406 { 407 OSL_ENSURE( (getFilterType() == FILTER_BIFF) && (getBiff() <= BIFF4), "ExternalName::setExternalReference - unexpected call" ); 408 sal_Int32 nDocLinkIdx = mrParentLink.getDocumentLinkIndex(); 409 sal_Int32 nCacheIdx = mrParentLink.getSheetCacheIndex(); 410 if( (nDocLinkIdx >= 0) && (nCacheIdx >= 0) ) 411 { 412 ExternalReference aExtApiRef; 413 aExtApiRef.Index = nDocLinkIdx; 414 415 Any aRefAny = getFormulaParser().extractReference( rTokens ); 416 if( aRefAny.has< SingleReference >() ) 417 { 418 SingleReference aApiRef; 419 aRefAny >>= aApiRef; 420 lclSetSheetCacheIndex( aApiRef, nCacheIdx ); 421 aExtApiRef.Reference <<= aApiRef; 422 maRefAny <<= aExtApiRef; 423 } 424 else if( aRefAny.has< ComplexReference >() ) 425 { 426 ComplexReference aApiRef; 427 aRefAny >>= aApiRef; 428 lclSetSheetCacheIndex( aApiRef.Reference1, nCacheIdx ); 429 lclSetSheetCacheIndex( aApiRef.Reference2, nCacheIdx ); 430 aExtApiRef.Reference <<= aApiRef; 431 maRefAny <<= aExtApiRef; 432 } 433 } 434 } 435 436 void ExternalName::setResultSize( sal_Int32 nColumns, sal_Int32 nRows ) 437 { 438 OSL_ENSURE( (mrParentLink.getLinkType() == LINKTYPE_DDE) || (mrParentLink.getLinkType() == LINKTYPE_OLE) || 439 (mrParentLink.getLinkType() == LINKTYPE_MAYBE_DDE_OLE), "ExternalName::setResultSize - wrong link type" ); 440 OSL_ENSURE( (nRows > 0) && (nColumns > 0), "ExternalName::setResultSize - invalid matrix size" ); 441 const CellAddress& rMaxPos = getAddressConverter().getMaxApiAddress(); 442 if( (0 < nRows) && (nRows <= rMaxPos.Row + 1) && (0 < nColumns) && (nColumns <= rMaxPos.Column + 1) ) 443 maResults.resize( static_cast< size_t >( nColumns ), static_cast< size_t >( nRows ), Any( BiffHelper::calcDoubleFromError( BIFF_ERR_NA ) ) ); 444 else 445 maResults.clear(); 446 maCurrIt = maResults.begin(); 447 } 448 449 // ============================================================================ 450 451 void LinkSheetRange::setDeleted() 452 { 453 meType = LINKSHEETRANGE_INTERNAL; 454 mnDocLink = mnFirst = mnLast = -1; 455 } 456 457 void LinkSheetRange::setSameSheet() 458 { 459 meType = LINKSHEETRANGE_SAMESHEET; 460 mnDocLink = -1; 461 mnFirst = mnLast = 0; 462 } 463 464 void LinkSheetRange::setRange( sal_Int32 nFirst, sal_Int32 nLast ) 465 { 466 meType = LINKSHEETRANGE_INTERNAL; 467 mnDocLink = -1; 468 mnFirst = ::std::min( nFirst, nLast ); 469 mnLast = ::std::max( nFirst, nLast ); 470 } 471 472 void LinkSheetRange::setExternalRange( sal_Int32 nDocLink, sal_Int32 nFirst, sal_Int32 nLast ) 473 { 474 if( nDocLink < 0 ) 475 { 476 setDeleted(); 477 } 478 else 479 { 480 meType = LINKSHEETRANGE_EXTERNAL; 481 mnDocLink = nDocLink; 482 mnFirst = ::std::min( nFirst, nLast ); 483 mnLast = ::std::max( nFirst, nLast ); 484 } 485 } 486 487 // ============================================================================ 488 489 ExternalLink::ExternalLink( const WorkbookHelper& rHelper ) : 490 WorkbookHelper( rHelper ), 491 meLinkType( LINKTYPE_UNKNOWN ), 492 meFuncLibType( FUNCLIB_UNKNOWN ) 493 { 494 } 495 496 void ExternalLink::importExternalReference( const AttributeList& rAttribs ) 497 { 498 maRelId = rAttribs.getString( R_TOKEN( id ), OUString() ); 499 } 500 501 void ExternalLink::importExternalBook( const Relations& rRelations, const AttributeList& rAttribs ) 502 { 503 parseExternalReference( rRelations, rAttribs.getString( R_TOKEN( id ), OUString() ) ); 504 } 505 506 void ExternalLink::importSheetName( const AttributeList& rAttribs ) 507 { 508 insertExternalSheet( rAttribs.getXString( XML_val, OUString() ) ); 509 } 510 511 void ExternalLink::importDefinedName( const AttributeList& rAttribs ) 512 { 513 createExternalName()->importDefinedName( rAttribs ); 514 } 515 516 void ExternalLink::importDdeLink( const AttributeList& rAttribs ) 517 { 518 OUString aDdeService = rAttribs.getXString( XML_ddeService, OUString() ); 519 OUString aDdeTopic = rAttribs.getXString( XML_ddeTopic, OUString() ); 520 setDdeOleTargetUrl( aDdeService, aDdeTopic, LINKTYPE_DDE ); 521 } 522 523 ExternalNameRef ExternalLink::importDdeItem( const AttributeList& rAttribs ) 524 { 525 ExternalNameRef xExtName = createExternalName(); 526 xExtName->importDdeItem( rAttribs ); 527 return xExtName; 528 } 529 530 void ExternalLink::importOleLink( const Relations& rRelations, const AttributeList& rAttribs ) 531 { 532 OUString aProgId = rAttribs.getXString( XML_progId, OUString() ); 533 OUString aTargetUrl = rRelations.getExternalTargetFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) ); 534 setDdeOleTargetUrl( aProgId, aTargetUrl, LINKTYPE_OLE ); 535 } 536 537 ExternalNameRef ExternalLink::importOleItem( const AttributeList& rAttribs ) 538 { 539 ExternalNameRef xExtName = createExternalName(); 540 xExtName->importOleItem( rAttribs ); 541 return xExtName; 542 } 543 544 void ExternalLink::importExternalRef( SequenceInputStream& rStrm ) 545 { 546 rStrm >> maRelId; 547 } 548 549 void ExternalLink::importExternalSelf( SequenceInputStream& ) 550 { 551 meLinkType = LINKTYPE_SELF; 552 } 553 554 void ExternalLink::importExternalSame( SequenceInputStream& ) 555 { 556 meLinkType = LINKTYPE_SAME; 557 } 558 559 void ExternalLink::importExternalAddin( SequenceInputStream& ) 560 { 561 meLinkType = LINKTYPE_UNKNOWN; 562 } 563 564 void ExternalLink::importExternalBook( const Relations& rRelations, SequenceInputStream& rStrm ) 565 { 566 switch( rStrm.readuInt16() ) 567 { 568 case BIFF12_EXTERNALBOOK_BOOK: 569 parseExternalReference( rRelations, BiffHelper::readString( rStrm ) ); 570 break; 571 case BIFF12_EXTERNALBOOK_DDE: 572 { 573 OUString aDdeService, aDdeTopic; 574 rStrm >> aDdeService >> aDdeTopic; 575 setDdeOleTargetUrl( aDdeService, aDdeTopic, LINKTYPE_DDE ); 576 } 577 break; 578 case BIFF12_EXTERNALBOOK_OLE: 579 { 580 OUString aTargetUrl = rRelations.getExternalTargetFromRelId( BiffHelper::readString( rStrm ) ); 581 OUString aProgId = BiffHelper::readString( rStrm ); 582 setDdeOleTargetUrl( aProgId, aTargetUrl, LINKTYPE_OLE ); 583 } 584 break; 585 default: 586 OSL_ENSURE( false, "ExternalLink::importExternalBook - unknown link type" ); 587 } 588 } 589 590 void ExternalLink::importExtSheetNames( SequenceInputStream& rStrm ) 591 { 592 // load external sheet names and create the sheet caches in the Calc document 593 OSL_ENSURE( (meLinkType == LINKTYPE_EXTERNAL) || (meLinkType == LINKTYPE_LIBRARY), 594 "ExternalLink::importExtSheetNames - invalid link type" ); 595 if( meLinkType == LINKTYPE_EXTERNAL ) // ignore sheets of external libraries 596 for( sal_Int32 nSheet = 0, nCount = rStrm.readInt32(); !rStrm.isEof() && (nSheet < nCount); ++nSheet ) 597 insertExternalSheet( BiffHelper::readString( rStrm ) ); 598 } 599 600 ExternalNameRef ExternalLink::importExternalName( SequenceInputStream& rStrm ) 601 { 602 ExternalNameRef xExtName = createExternalName(); 603 xExtName->importExternalName( rStrm ); 604 return xExtName; 605 } 606 607 void ExternalLink::importExternSheet( BiffInputStream& rStrm ) 608 { 609 OStringBuffer aTargetBuffer( rStrm.readByteString( false, true ) ); 610 // references to own sheets have wrong string length field (off by 1) 611 if( (aTargetBuffer.getLength() > 0) && (aTargetBuffer[ 0 ] == 3) ) 612 aTargetBuffer.append( static_cast< sal_Char >( rStrm.readuInt8() ) ); 613 // parse the encoded URL 614 OUString aBiffTarget = OStringToOUString( aTargetBuffer.makeStringAndClear(), getTextEncoding() ); 615 OUString aSheetName = parseBiffTargetUrl( aBiffTarget ); 616 switch( meLinkType ) 617 { 618 case LINKTYPE_INTERNAL: 619 maCalcSheets.push_back( getWorksheets().getCalcSheetIndex( aSheetName ) ); 620 break; 621 case LINKTYPE_EXTERNAL: 622 insertExternalSheet( (aSheetName.getLength() > 0) ? aSheetName : WorksheetBuffer::getBaseFileName( maTargetUrl ) ); 623 break; 624 default:; 625 } 626 } 627 628 void ExternalLink::importExternalBook( BiffInputStream& rStrm ) 629 { 630 OUString aTarget; 631 sal_uInt16 nSheetCount; 632 rStrm >> nSheetCount; 633 if( rStrm.getRemaining() == 2 ) 634 { 635 if( rStrm.readuInt8() == 1 ) 636 { 637 sal_Char cChar = static_cast< sal_Char >( rStrm.readuInt8() ); 638 if( cChar != 0 ) 639 aTarget = OStringToOUString( OString( cChar ), getTextEncoding() ); 640 } 641 } 642 else if( rStrm.getRemaining() >= 3 ) 643 { 644 // NUL characters may occur 645 aTarget = rStrm.readUniString( true ); 646 } 647 648 // parse the encoded URL 649 OUString aDummySheetName = parseBiffTargetUrl( aTarget ); 650 OSL_ENSURE( aDummySheetName.getLength() == 0, "ExternalLink::importExternalBook - sheet name in encoded URL" ); 651 (void)aDummySheetName; // prevent compiler warning 652 653 // load external sheet names and create the sheet caches in the Calc document 654 if( meLinkType == LINKTYPE_EXTERNAL ) 655 for( sal_uInt16 nSheet = 0; !rStrm.isEof() && (nSheet < nSheetCount); ++nSheet ) 656 insertExternalSheet( rStrm.readUniString() ); 657 } 658 659 void ExternalLink::importExternalName( BiffInputStream& rStrm ) 660 { 661 ExternalNameRef xExtName = createExternalName(); 662 xExtName->importExternalName( rStrm ); 663 switch( meLinkType ) 664 { 665 case LINKTYPE_DDE: 666 OSL_ENSURE( !xExtName->isOleObject(), "ExternalLink::importExternalName - OLE object in DDE link" ); 667 break; 668 case LINKTYPE_OLE: 669 OSL_ENSURE( xExtName->isOleObject(), "ExternalLink::importExternalName - anything but OLE object in OLE link" ); 670 break; 671 case LINKTYPE_MAYBE_DDE_OLE: 672 meLinkType = xExtName->isOleObject() ? LINKTYPE_OLE : LINKTYPE_DDE; 673 break; 674 default: 675 OSL_ENSURE( !xExtName->isOleObject(), "ExternalLink::importExternalName - OLE object in external name" ); 676 } 677 } 678 679 ExternalLinkInfo ExternalLink::getLinkInfo() const 680 { 681 ExternalLinkInfo aLinkInfo; 682 switch( meLinkType ) 683 { 684 case LINKTYPE_SELF: 685 case LINKTYPE_SAME: 686 case LINKTYPE_INTERNAL: 687 aLinkInfo.Type = ::com::sun::star::sheet::ExternalLinkType::SELF; 688 break; 689 case LINKTYPE_EXTERNAL: 690 aLinkInfo.Type = ::com::sun::star::sheet::ExternalLinkType::DOCUMENT; 691 aLinkInfo.Data <<= maTargetUrl; 692 break; 693 case LINKTYPE_LIBRARY: 694 // parser will return library function names in OPCODE_BAD string tokens 695 aLinkInfo.Type = ::com::sun::star::sheet::ExternalLinkType::SPECIAL; 696 break; 697 case LINKTYPE_DDE: 698 { 699 aLinkInfo.Type = ::com::sun::star::sheet::ExternalLinkType::DDE; 700 DDELinkInfo aDdeLinkInfo; 701 aDdeLinkInfo.Service = maClassName; 702 aDdeLinkInfo.Topic = maTargetUrl; 703 ::std::vector< DDEItemInfo > aItemInfos; 704 DDEItemInfo aItemInfo; 705 for( ExternalNameVector::const_iterator aIt = maExtNames.begin(), aEnd = maExtNames.end(); aIt != aEnd; ++aIt ) 706 if( (*aIt)->getDdeItemInfo( aItemInfo ) ) 707 aItemInfos.push_back( aItemInfo ); 708 aDdeLinkInfo.Items = ContainerHelper::vectorToSequence( aItemInfos ); 709 aLinkInfo.Data <<= aDdeLinkInfo; 710 } 711 break; 712 default: 713 aLinkInfo.Type = ::com::sun::star::sheet::ExternalLinkType::UNKNOWN; 714 } 715 return aLinkInfo; 716 } 717 718 FunctionLibraryType ExternalLink::getFuncLibraryType() const 719 { 720 return (meLinkType == LINKTYPE_LIBRARY) ? meFuncLibType : FUNCLIB_UNKNOWN; 721 } 722 723 sal_Int16 ExternalLink::getCalcSheetIndex( sal_Int32 nTabId ) const 724 { 725 OSL_ENSURE( meLinkType == LINKTYPE_INTERNAL, "ExternalLink::getCalcSheetIndex - invalid link type" ); 726 OSL_ENSURE( (nTabId == 0) || (getFilterType() == FILTER_OOXML) || (getBiff() == BIFF8), 727 "ExternalLink::getCalcSheetIndex - invalid sheet index" ); 728 return ContainerHelper::getVectorElement( maCalcSheets, nTabId, -1 ); 729 } 730 731 sal_Int32 ExternalLink::getDocumentLinkIndex() const 732 { 733 OSL_ENSURE( meLinkType == LINKTYPE_EXTERNAL, "ExternalLink::getDocumentLinkIndex - invalid link type" ); 734 return mxDocLink.is() ? mxDocLink->getTokenIndex() : -1; 735 } 736 737 sal_Int32 ExternalLink::getSheetCacheIndex( sal_Int32 nTabId ) const 738 { 739 OSL_ENSURE( meLinkType == LINKTYPE_EXTERNAL, "ExternalLink::getSheetCacheIndex - invalid link type" ); 740 OSL_ENSURE( (nTabId == 0) || (getFilterType() == FILTER_OOXML) || (getBiff() == BIFF8), 741 "ExternalLink::getSheetCacheIndex - invalid sheet index" ); 742 return ContainerHelper::getVectorElement( maSheetCaches, nTabId, -1 ); 743 } 744 745 Reference< XExternalSheetCache > ExternalLink::getSheetCache( sal_Int32 nTabId ) const 746 { 747 sal_Int32 nCacheIdx = getSheetCacheIndex( nTabId ); 748 if( mxDocLink.is() && (nCacheIdx >= 0) ) try 749 { 750 // existing mxDocLink implies that this is an external link 751 Reference< XExternalSheetCache > xSheetCache( mxDocLink->getByIndex( nCacheIdx ), UNO_QUERY_THROW ); 752 return xSheetCache; 753 } 754 catch( Exception& ) 755 { 756 } 757 return 0; 758 } 759 760 void ExternalLink::getSheetRange( LinkSheetRange& orSheetRange, sal_Int32 nTabId1, sal_Int32 nTabId2 ) const 761 { 762 switch( meLinkType ) 763 { 764 case LINKTYPE_SAME: 765 orSheetRange.setSameSheet(); 766 break; 767 768 case LINKTYPE_SELF: 769 case LINKTYPE_INTERNAL: 770 orSheetRange.setRange( nTabId1, nTabId2 ); 771 break; 772 773 case LINKTYPE_EXTERNAL: 774 { 775 sal_Int32 nDocLinkIdx = getDocumentLinkIndex(); 776 switch( getFilterType() ) 777 { 778 case FILTER_OOXML: 779 // BIFF12: passed indexes point into sheet list of EXTSHEETLIST 780 orSheetRange.setExternalRange( nDocLinkIdx, getSheetCacheIndex( nTabId1 ), getSheetCacheIndex( nTabId2 ) ); 781 break; 782 case FILTER_BIFF: 783 switch( getBiff() ) 784 { 785 case BIFF2: 786 case BIFF3: 787 case BIFF4: 788 orSheetRange.setExternalRange( nDocLinkIdx, getSheetCacheIndex( nTabId1 ), getSheetCacheIndex( nTabId2 ) ); 789 break; 790 case BIFF5: 791 // BIFF5: first sheet from this external link, last sheet is passed in nTabId2 792 if( const ExternalLink* pExtLink2 = getExternalLinks().getExternalLink( nTabId2 ).get() ) 793 if( (pExtLink2->getLinkType() == LINKTYPE_EXTERNAL) && (maTargetUrl == pExtLink2->getTargetUrl()) ) 794 orSheetRange.setExternalRange( nDocLinkIdx, getSheetCacheIndex(), pExtLink2->getSheetCacheIndex() ); 795 break; 796 case BIFF8: 797 // BIFF8: passed indexes point into sheet list of EXTERNALBOOK 798 orSheetRange.setExternalRange( nDocLinkIdx, getSheetCacheIndex( nTabId1 ), getSheetCacheIndex( nTabId2 ) ); 799 break; 800 case BIFF_UNKNOWN: break; 801 } 802 break; 803 case FILTER_UNKNOWN: break; 804 } 805 } 806 break; 807 808 default: 809 // unsupported/unexpected link type: #REF! error 810 orSheetRange.setDeleted(); 811 } 812 } 813 814 ExternalNameRef ExternalLink::getNameByIndex( sal_Int32 nIndex ) const 815 { 816 return maExtNames.get( nIndex ); 817 } 818 819 // private -------------------------------------------------------------------- 820 821 #define OOX_TARGETTYPE_EXTLINK CREATE_OFFICEDOC_RELATION_TYPE( "externalLinkPath" ) 822 #define OOX_TARGETTYPE_LIBRARY CREATE_MSOFFICE_RELATION_TYPE( "xlExternalLinkPath/xlLibrary" ) 823 824 void ExternalLink::setExternalTargetUrl( const OUString& rTargetUrl, const OUString& rTargetType ) 825 { 826 meLinkType = LINKTYPE_UNKNOWN; 827 if( rTargetType == OOX_TARGETTYPE_EXTLINK ) 828 { 829 maTargetUrl = getBaseFilter().getAbsoluteUrl( rTargetUrl ); 830 if( maTargetUrl.getLength() > 0 ) 831 meLinkType = LINKTYPE_EXTERNAL; 832 } 833 else if( rTargetType == OOX_TARGETTYPE_LIBRARY ) 834 { 835 meLinkType = LINKTYPE_LIBRARY; 836 meFuncLibType = getFormulaParser().getFuncLibTypeFromLibraryName( rTargetUrl ); 837 } 838 OSL_ENSURE( meLinkType != LINKTYPE_UNKNOWN, "ExternalLink::setExternalTargetUrl - empty target URL or unknown target type" ); 839 840 // create the external document link API object that will contain the sheet caches 841 if( meLinkType == LINKTYPE_EXTERNAL ) try 842 { 843 PropertySet aDocProps( getDocument() ); 844 Reference< XExternalDocLinks > xDocLinks( aDocProps.getAnyProperty( PROP_ExternalDocLinks ), UNO_QUERY_THROW ); 845 mxDocLink = xDocLinks->addDocLink( maTargetUrl ); 846 } 847 catch( Exception& ) 848 { 849 } 850 } 851 852 void ExternalLink::setDdeOleTargetUrl( const OUString& rClassName, const OUString& rTargetUrl, ExternalLinkType eLinkType ) 853 { 854 maClassName = rClassName; 855 maTargetUrl = rTargetUrl; 856 meLinkType = ((maClassName.getLength() > 0) && (maTargetUrl.getLength() > 0)) ? eLinkType : LINKTYPE_UNKNOWN; 857 OSL_ENSURE( meLinkType == eLinkType, "ExternalLink::setDdeOleTargetUrl - missing classname or target" ); 858 } 859 860 void ExternalLink::parseExternalReference( const Relations& rRelations, const OUString& rRelId ) 861 { 862 if( const Relation* pRelation = rRelations.getRelationFromRelId( rRelId ) ) 863 setExternalTargetUrl( pRelation->maTarget, pRelation->maType ); 864 } 865 866 OUString ExternalLink::parseBiffTargetUrl( const OUString& rBiffTargetUrl ) 867 { 868 meLinkType = LINKTYPE_UNKNOWN; 869 870 OUString aClassName, aTargetUrl, aSheetName; 871 switch( getAddressConverter().parseBiffTargetUrl( aClassName, aTargetUrl, aSheetName, rBiffTargetUrl ) ) 872 { 873 case BIFF_TARGETTYPE_URL: 874 if( aTargetUrl.getLength() == 0 ) 875 { 876 meLinkType = (aSheetName.getLength() > 0) ? LINKTYPE_INTERNAL : LINKTYPE_SELF; 877 } 878 else if( (aTargetUrl.getLength() == 1) && (aTargetUrl[ 0 ] == ':') ) 879 { 880 if( getBiff() >= BIFF4 ) 881 meLinkType = LINKTYPE_ANALYSIS; 882 } 883 else if( (aTargetUrl.getLength() > 1) || (aTargetUrl[ 0 ] != ' ') ) 884 { 885 setExternalTargetUrl( aTargetUrl, OOX_TARGETTYPE_EXTLINK ); 886 } 887 break; 888 889 case BIFF_TARGETTYPE_SAMESHEET: 890 OSL_ENSURE( (aTargetUrl.getLength() == 0) && (aSheetName.getLength() == 0), "ExternalLink::parseBiffTargetUrl - unexpected target or sheet name" ); 891 meLinkType = LINKTYPE_SAME; 892 break; 893 894 case BIFF_TARGETTYPE_LIBRARY: 895 OSL_ENSURE( aSheetName.getLength() == 0, "ExternalLink::parseBiffTargetUrl - unexpected sheet name" ); 896 setExternalTargetUrl( aTargetUrl, OOX_TARGETTYPE_LIBRARY ); 897 break; 898 899 case BIFF_TARGETTYPE_DDE_OLE: 900 setDdeOleTargetUrl( aClassName, aTargetUrl, LINKTYPE_MAYBE_DDE_OLE ); 901 break; 902 903 case BIFF_TARGETTYPE_UNKNOWN: 904 break; 905 } 906 return aSheetName; 907 } 908 909 void ExternalLink::insertExternalSheet( const OUString& rSheetName ) 910 { 911 OSL_ENSURE( rSheetName.getLength() > 0, "ExternalLink::insertExternalSheet - empty sheet name" ); 912 if( mxDocLink.is() ) 913 { 914 Reference< XExternalSheetCache > xSheetCache = mxDocLink->addSheetCache( rSheetName, false ); 915 sal_Int32 nCacheIdx = xSheetCache.is() ? xSheetCache->getTokenIndex() : -1; 916 maSheetCaches.push_back( nCacheIdx ); 917 } 918 } 919 920 ExternalNameRef ExternalLink::createExternalName() 921 { 922 ExternalNameRef xExtName( new ExternalName( *this ) ); 923 maExtNames.push_back( xExtName ); 924 return xExtName; 925 } 926 927 // ============================================================================ 928 929 RefSheetsModel::RefSheetsModel() : 930 mnExtRefId( -1 ), 931 mnTabId1( -1 ), 932 mnTabId2( -1 ) 933 { 934 } 935 936 void RefSheetsModel::readBiff12Data( SequenceInputStream& rStrm ) 937 { 938 rStrm >> mnExtRefId >> mnTabId1 >> mnTabId2; 939 } 940 941 void RefSheetsModel::readBiff8Data( BiffInputStream& rStrm ) 942 { 943 mnExtRefId = rStrm.readuInt16(); 944 mnTabId1 = rStrm.readInt16(); 945 mnTabId2 = rStrm.readInt16(); 946 } 947 948 // ---------------------------------------------------------------------------- 949 950 ExternalLinkBuffer::ExternalLinkBuffer( const WorkbookHelper& rHelper ) : 951 WorkbookHelper( rHelper ), 952 mxSelfRef( new ExternalLink( rHelper ) ), 953 mbUseRefSheets( false ) 954 { 955 mxSelfRef->setSelfLinkType(); 956 } 957 958 ExternalLinkRef ExternalLinkBuffer::importExternalReference( const AttributeList& rAttribs ) 959 { 960 ExternalLinkRef xExtLink = createExternalLink(); 961 xExtLink->importExternalReference( rAttribs ); 962 maExtLinks.push_back( xExtLink ); 963 return xExtLink; 964 } 965 966 ExternalLinkRef ExternalLinkBuffer::importExternalRef( SequenceInputStream& rStrm ) 967 { 968 mbUseRefSheets = true; 969 ExternalLinkRef xExtLink = createExternalLink(); 970 xExtLink->importExternalRef( rStrm ); 971 maExtLinks.push_back( xExtLink ); 972 return xExtLink; 973 } 974 975 void ExternalLinkBuffer::importExternalSelf( SequenceInputStream& rStrm ) 976 { 977 mbUseRefSheets = true; 978 createExternalLink()->importExternalSelf( rStrm ); 979 } 980 981 void ExternalLinkBuffer::importExternalSame( SequenceInputStream& rStrm ) 982 { 983 mbUseRefSheets = true; 984 createExternalLink()->importExternalSame( rStrm ); 985 } 986 987 void ExternalLinkBuffer::importExternalAddin( SequenceInputStream& rStrm ) 988 { 989 mbUseRefSheets = true; 990 createExternalLink()->importExternalAddin( rStrm ); 991 } 992 993 void ExternalLinkBuffer::importExternalSheets( SequenceInputStream& rStrm ) 994 { 995 OSL_ENSURE( mbUseRefSheets, "ExternalLinkBuffer::importExternalSheets - missing EXTERNALREFS records" ); 996 mbUseRefSheets = true; 997 OSL_ENSURE( maRefSheets.empty(), "ExternalLinkBuffer::importExternalSheets - multiple EXTERNALSHEETS records" ); 998 maRefSheets.clear(); 999 sal_Int32 nRefCount; 1000 rStrm >> nRefCount; 1001 size_t nMaxCount = getLimitedValue< size_t, sal_Int64 >( nRefCount, 0, rStrm.getRemaining() / 12 ); 1002 maRefSheets.reserve( nMaxCount ); 1003 for( size_t nRefId = 0; !rStrm.isEof() && (nRefId < nMaxCount); ++nRefId ) 1004 { 1005 RefSheetsModel aRefSheets; 1006 aRefSheets.readBiff12Data( rStrm ); 1007 maRefSheets.push_back( aRefSheets ); 1008 } 1009 } 1010 1011 ExternalLinkRef ExternalLinkBuffer::importExternSheet( BiffInputStream& rStrm ) 1012 { 1013 OSL_ENSURE( getBiff() <= BIFF5, "ExternalLinkBuffer::importExternSheet - wrong BIFF version" ); 1014 ExternalLinkRef xExtLink = createExternalLink(); 1015 xExtLink->importExternSheet( rStrm ); 1016 return xExtLink; 1017 } 1018 1019 ExternalLinkRef ExternalLinkBuffer::importExternalBook( BiffInputStream& rStrm ) 1020 { 1021 ExternalLinkRef xExtLink = createExternalLink(); 1022 xExtLink->importExternalBook( rStrm ); 1023 return xExtLink; 1024 } 1025 1026 void ExternalLinkBuffer::importExternalName( BiffInputStream& rStrm ) 1027 { 1028 if( !maLinks.empty() ) 1029 maLinks.back()->importExternalName( rStrm ); 1030 } 1031 1032 void ExternalLinkBuffer::importExternSheet8( BiffInputStream& rStrm ) 1033 { 1034 OSL_ENSURE( getBiff() == BIFF8, "ExternalLinkBuffer::importExternSheet8 - wrong BIFF version" ); 1035 1036 sal_uInt16 nRefCount; 1037 rStrm >> nRefCount; 1038 OSL_ENSURE( static_cast< sal_Int64 >( nRefCount * 6 ) == rStrm.getRemaining(), "ExternalLinkBuffer::importExternSheet8 - invalid count" ); 1039 nRefCount = static_cast< sal_uInt16 >( ::std::min< sal_Int64 >( nRefCount, rStrm.getRemaining() / 6 ) ); 1040 1041 /* #i104057# A weird external XLS generator writes multiple EXTERNSHEET 1042 records instead of only one as expected. Surprisingly, Excel seems to 1043 insert the entries of the second record before the entries of the first 1044 record. */ 1045 maRefSheets.insert( maRefSheets.begin(), nRefCount, RefSheetsModel() ); 1046 for( RefSheetsModelVec::iterator aIt = maRefSheets.begin(), aEnd = aIt + nRefCount; !rStrm.isEof() && (aIt != aEnd); ++aIt ) 1047 aIt->readBiff8Data( rStrm ); 1048 } 1049 1050 Sequence< ExternalLinkInfo > ExternalLinkBuffer::getLinkInfos() const 1051 { 1052 ::std::vector< ExternalLinkInfo > aLinkInfos; 1053 // XML formula parser also used in BIFF12 documents, e.g. replacement formulas in unsupported conditional formattings 1054 OSL_ENSURE( getFilterType() == FILTER_OOXML, "ExternalLinkBuffer::getLinkInfos - unexpected file format" ); 1055 // add entry for implicit index 0 (self reference to this document) 1056 aLinkInfos.push_back( mxSelfRef->getLinkInfo() ); 1057 for( ExternalLinkVec::const_iterator aIt = maExtLinks.begin(), aEnd = maExtLinks.end(); aIt != aEnd; ++aIt ) 1058 aLinkInfos.push_back( (*aIt)->getLinkInfo() ); 1059 return ContainerHelper::vectorToSequence( aLinkInfos ); 1060 } 1061 1062 ExternalLinkRef ExternalLinkBuffer::getExternalLink( sal_Int32 nRefId, bool bUseRefSheets ) const 1063 { 1064 ExternalLinkRef xExtLink; 1065 switch( getFilterType() ) 1066 { 1067 case FILTER_OOXML: 1068 // OOXML: 0 = this document, otherwise one-based index into link list 1069 if( !bUseRefSheets || !mbUseRefSheets ) 1070 xExtLink = (nRefId == 0) ? mxSelfRef : maLinks.get( nRefId - 1 ); 1071 // BIFF12: zero-based index into ref-sheets list 1072 else if( const RefSheetsModel* pRefSheets = getRefSheets( nRefId ) ) 1073 xExtLink = maLinks.get( pRefSheets->mnExtRefId ); 1074 break; 1075 case FILTER_BIFF: 1076 switch( getBiff() ) 1077 { 1078 case BIFF2: 1079 case BIFF3: 1080 case BIFF4: 1081 // one-based index to EXTERNSHEET records 1082 xExtLink = maLinks.get( nRefId - 1 ); 1083 break; 1084 case BIFF5: 1085 if( nRefId < 0 ) 1086 { 1087 // internal links in formula tokens have negative index 1088 xExtLink = maLinks.get( -nRefId - 1 ); 1089 if( xExtLink.get() && !xExtLink->isInternalLink() ) 1090 xExtLink.reset(); 1091 } 1092 else 1093 { 1094 // one-based index to EXTERNSHEET records 1095 xExtLink = maLinks.get( nRefId - 1 ); 1096 } 1097 break; 1098 case BIFF8: 1099 // zero-based index into REF list in EXTERNSHEET record 1100 if( const RefSheetsModel* pRefSheets = getRefSheets( nRefId ) ) 1101 xExtLink = maLinks.get( pRefSheets->mnExtRefId ); 1102 break; 1103 case BIFF_UNKNOWN: break; 1104 } 1105 break; 1106 case FILTER_UNKNOWN: break; 1107 } 1108 return xExtLink; 1109 } 1110 1111 LinkSheetRange ExternalLinkBuffer::getSheetRange( sal_Int32 nRefId, sal_Int16 nTabId1, sal_Int16 nTabId2 ) const 1112 { 1113 OSL_ENSURE( getBiff() <= BIFF5, "ExternalLinkBuffer::getSheetRange - wrong BIFF version" ); 1114 LinkSheetRange aSheetRange; 1115 if( const ExternalLink* pExtLink = getExternalLink( nRefId ).get() ) 1116 pExtLink->getSheetRange( aSheetRange, nTabId1, nTabId2 ); 1117 return aSheetRange; 1118 } 1119 1120 LinkSheetRange ExternalLinkBuffer::getSheetRange( sal_Int32 nRefId ) const 1121 { 1122 OSL_ENSURE( ((getFilterType() == FILTER_OOXML) && mbUseRefSheets) || (getBiff() == BIFF8), "ExternalLinkBuffer::getSheetRange - wrong BIFF version" ); 1123 LinkSheetRange aSheetRange; 1124 if( const ExternalLink* pExtLink = getExternalLink( nRefId ).get() ) 1125 if( const RefSheetsModel* pRefSheets = getRefSheets( nRefId ) ) 1126 pExtLink->getSheetRange( aSheetRange, pRefSheets->mnTabId1, pRefSheets->mnTabId2 ); 1127 return aSheetRange; 1128 } 1129 1130 // private -------------------------------------------------------------------- 1131 1132 ExternalLinkRef ExternalLinkBuffer::createExternalLink() 1133 { 1134 ExternalLinkRef xExtLink( new ExternalLink( *this ) ); 1135 maLinks.push_back( xExtLink ); 1136 return xExtLink; 1137 } 1138 1139 const RefSheetsModel* ExternalLinkBuffer::getRefSheets( sal_Int32 nRefId ) const 1140 { 1141 return ((0 <= nRefId) && (static_cast< size_t >( nRefId ) < maRefSheets.size())) ? 1142 &maRefSheets[ static_cast< size_t >( nRefId ) ] : 0; 1143 } 1144 1145 // ============================================================================ 1146 1147 } // namespace xls 1148 } // namespace oox 1149