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