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 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_sc.hxx" 26 27 28 29 // INCLUDE --------------------------------------------------------------- 30 31 #include <tools/debug.hxx> 32 33 #include "rangeutl.hxx" 34 #include "document.hxx" 35 #include "global.hxx" 36 #include "dbcolect.hxx" 37 #include "rangenam.hxx" 38 #include "scresid.hxx" 39 #include "globstr.hrc" 40 #include "convuno.hxx" 41 #include "externalrefmgr.hxx" 42 #include "compiler.hxx" 43 44 using ::rtl::OUString; 45 using ::rtl::OUStringBuffer; 46 using ::formula::FormulaGrammar; 47 using namespace ::com::sun::star; 48 49 //------------------------------------------------------------------------ 50 51 sal_Bool ScRangeUtil::MakeArea( const String& rAreaStr, 52 ScArea& rArea, 53 ScDocument* pDoc, 54 SCTAB nTab, 55 ScAddress::Details const & rDetails ) const 56 { 57 // Eingabe in rAreaStr: "$Tabelle1.$A1:$D17" 58 59 // BROKEN BROKEN BROKEN 60 // but it is only used in the consolidate dialog. Ignore for now. 61 62 sal_Bool nSuccess = sal_False; 63 sal_uInt16 nPointPos = rAreaStr.Search('.'); 64 sal_uInt16 nColonPos = rAreaStr.Search(':'); 65 String aStrArea( rAreaStr ); 66 ScRefAddress startPos; 67 ScRefAddress endPos; 68 69 if ( nColonPos == STRING_NOTFOUND ) 70 if ( nPointPos != STRING_NOTFOUND ) 71 { 72 aStrArea += ':'; 73 aStrArea += rAreaStr.Copy( nPointPos+1 ); // '.' nicht mitkopieren 74 } 75 76 nSuccess = ConvertDoubleRef( pDoc, aStrArea, nTab, startPos, endPos, rDetails ); 77 78 if ( nSuccess ) 79 rArea = ScArea( startPos.Tab(), 80 startPos.Col(), startPos.Row(), 81 endPos.Col(), endPos.Row() ); 82 83 return nSuccess; 84 } 85 86 //------------------------------------------------------------------------ 87 88 void ScRangeUtil::CutPosString( const String& theAreaStr, 89 String& thePosStr ) const 90 { 91 String aPosStr; 92 // BROKEN BROKEN BROKEN 93 // but it is only used in the consolidate dialog. Ignore for now. 94 95 sal_uInt16 nColonPos = theAreaStr.Search(':'); 96 97 if ( nColonPos != STRING_NOTFOUND ) 98 aPosStr = theAreaStr.Copy( 0, nColonPos ); // ':' nicht mitkopieren 99 else 100 aPosStr = theAreaStr; 101 102 thePosStr = aPosStr; 103 } 104 105 //------------------------------------------------------------------------ 106 107 sal_Bool ScRangeUtil::IsAbsTabArea( const String& rAreaStr, 108 ScDocument* pDoc, 109 ScArea*** pppAreas, 110 sal_uInt16* pAreaCount, 111 sal_Bool /* bAcceptCellRef */, 112 ScAddress::Details const & rDetails ) const 113 { 114 DBG_ASSERT( pDoc, "Kein Dokument uebergeben!" ); 115 if ( !pDoc ) 116 return sal_False; 117 118 // BROKEN BROKEN BROKEN 119 // but it is only used in the consolidate dialog. Ignore for now. 120 121 /* 122 * Erwartet wird ein String der Form 123 * "$Tabelle1.$A$1:$Tabelle3.$D$17" 124 * Wenn bAcceptCellRef == sal_True ist, wird auch ein String der Form 125 * "$Tabelle1.$A$1" 126 * akzeptiert. 127 * 128 * als Ergebnis wird ein ScArea-Array angelegt, 129 * welches ueber ppAreas bekannt gegeben wird und auch 130 * wieder geloescht werden muss! 131 */ 132 133 sal_Bool bStrOk = sal_False; 134 String aTempAreaStr(rAreaStr); 135 String aStartPosStr; 136 String aEndPosStr; 137 138 if ( STRING_NOTFOUND == aTempAreaStr.Search(':') ) 139 { 140 aTempAreaStr.Append(':'); 141 aTempAreaStr.Append(rAreaStr); 142 } 143 144 sal_uInt16 nColonPos = aTempAreaStr.Search(':'); 145 146 if ( STRING_NOTFOUND != nColonPos 147 && STRING_NOTFOUND != aTempAreaStr.Search('.') ) 148 { 149 ScRefAddress aStartPos; 150 ScRefAddress aEndPos; 151 152 aStartPosStr = aTempAreaStr.Copy( 0, nColonPos ); 153 aEndPosStr = aTempAreaStr.Copy( nColonPos+1, STRING_LEN ); 154 155 if ( ConvertSingleRef( pDoc, aStartPosStr, 0, aStartPos, rDetails ) ) 156 { 157 if ( ConvertSingleRef( pDoc, aEndPosStr, aStartPos.Tab(), aEndPos, rDetails ) ) 158 { 159 aStartPos.SetRelCol( sal_False ); 160 aStartPos.SetRelRow( sal_False ); 161 aStartPos.SetRelTab( sal_False ); 162 aEndPos.SetRelCol( sal_False ); 163 aEndPos.SetRelRow( sal_False ); 164 aEndPos.SetRelTab( sal_False ); 165 166 bStrOk = sal_True; 167 168 if ( pppAreas && pAreaCount ) // Array zurueckgegeben? 169 { 170 SCTAB nStartTab = aStartPos.Tab(); 171 SCTAB nEndTab = aEndPos.Tab(); 172 sal_uInt16 nTabCount = static_cast<sal_uInt16>(nEndTab-nStartTab+1); 173 ScArea** theAreas = new ScArea*[nTabCount]; 174 SCTAB nTab = 0; 175 sal_uInt16 i = 0; 176 ScArea theArea( 0, aStartPos.Col(), aStartPos.Row(), 177 aEndPos.Col(), aEndPos.Row() ); 178 179 nTab = nStartTab; 180 for ( i=0; i<nTabCount; i++ ) 181 { 182 theAreas[i] = new ScArea( theArea ); 183 theAreas[i]->nTab = nTab; 184 nTab++; 185 } 186 *pppAreas = theAreas; 187 *pAreaCount = nTabCount; 188 } 189 } 190 } 191 } 192 193 return bStrOk; 194 } 195 196 //------------------------------------------------------------------------ 197 198 sal_Bool ScRangeUtil::IsAbsArea( const String& rAreaStr, 199 ScDocument* pDoc, 200 SCTAB nTab, 201 String* pCompleteStr, 202 ScRefAddress* pStartPos, 203 ScRefAddress* pEndPos, 204 ScAddress::Details const & rDetails ) const 205 { 206 sal_Bool bIsAbsArea = sal_False; 207 ScRefAddress startPos; 208 ScRefAddress endPos; 209 210 bIsAbsArea = ConvertDoubleRef( pDoc, rAreaStr, nTab, startPos, endPos, rDetails ); 211 212 if ( bIsAbsArea ) 213 { 214 startPos.SetRelCol( sal_False ); 215 startPos.SetRelRow( sal_False ); 216 startPos.SetRelTab( sal_False ); 217 endPos .SetRelCol( sal_False ); 218 endPos .SetRelRow( sal_False ); 219 endPos .SetRelTab( sal_False ); 220 221 if ( pCompleteStr ) 222 { 223 *pCompleteStr = startPos.GetRefString( pDoc, MAXTAB+1, rDetails ); 224 *pCompleteStr += ':'; 225 *pCompleteStr += endPos .GetRefString( pDoc, nTab, rDetails ); 226 } 227 228 if ( pStartPos && pEndPos ) 229 { 230 *pStartPos = startPos; 231 *pEndPos = endPos; 232 } 233 } 234 235 return bIsAbsArea; 236 } 237 238 //------------------------------------------------------------------------ 239 240 sal_Bool ScRangeUtil::IsAbsPos( const String& rPosStr, 241 ScDocument* pDoc, 242 SCTAB nTab, 243 String* pCompleteStr, 244 ScRefAddress* pPosTripel, 245 ScAddress::Details const & rDetails ) const 246 { 247 sal_Bool bIsAbsPos = sal_False; 248 ScRefAddress thePos; 249 250 bIsAbsPos = ConvertSingleRef( pDoc, rPosStr, nTab, thePos, rDetails ); 251 thePos.SetRelCol( sal_False ); 252 thePos.SetRelRow( sal_False ); 253 thePos.SetRelTab( sal_False ); 254 255 if ( bIsAbsPos ) 256 { 257 if ( pPosTripel ) 258 *pPosTripel = thePos; 259 if ( pCompleteStr ) 260 *pCompleteStr = thePos.GetRefString( pDoc, MAXTAB+1, rDetails ); 261 } 262 263 return bIsAbsPos; 264 } 265 266 //------------------------------------------------------------------------ 267 268 sal_Bool ScRangeUtil::MakeRangeFromName ( 269 const String& rName, 270 ScDocument* pDoc, 271 SCTAB nCurTab, 272 ScRange& rRange, 273 RutlNameScope eScope, 274 ScAddress::Details const & rDetails ) const 275 { 276 sal_Bool bResult=sal_False; 277 ScRangeUtil aRangeUtil; 278 SCTAB nTab = 0; 279 SCCOL nColStart = 0; 280 SCCOL nColEnd = 0; 281 SCROW nRowStart = 0; 282 SCROW nRowEnd = 0; 283 284 if( eScope==RUTL_NAMES ) 285 { 286 ScRangeName& rRangeNames = *(pDoc->GetRangeName()); 287 sal_uInt16 nAt = 0; 288 289 if ( rRangeNames.SearchName( rName, nAt ) ) 290 { 291 ScRangeData* pData = rRangeNames[nAt]; 292 String aStrArea; 293 ScRefAddress aStartPos; 294 ScRefAddress aEndPos; 295 296 pData->GetSymbol( aStrArea ); 297 298 if ( IsAbsArea( aStrArea, pDoc, nCurTab, 299 NULL, &aStartPos, &aEndPos, rDetails ) ) 300 { 301 nTab = aStartPos.Tab(); 302 nColStart = aStartPos.Col(); 303 nRowStart = aStartPos.Row(); 304 nColEnd = aEndPos.Col(); 305 nRowEnd = aEndPos.Row(); 306 bResult = sal_True; 307 } 308 else 309 { 310 CutPosString( aStrArea, aStrArea ); 311 312 if ( IsAbsPos( aStrArea, pDoc, nCurTab, 313 NULL, &aStartPos, rDetails ) ) 314 { 315 nTab = aStartPos.Tab(); 316 nColStart = nColEnd = aStartPos.Col(); 317 nRowStart = nRowEnd = aStartPos.Row(); 318 bResult = sal_True; 319 } 320 } 321 } 322 } 323 else if( eScope==RUTL_DBASE ) 324 { 325 ScDBCollection& rDbNames = *(pDoc->GetDBCollection()); 326 sal_uInt16 nAt = 0; 327 328 if ( rDbNames.SearchName( rName, nAt ) ) 329 { 330 ScDBData* pData = rDbNames[nAt]; 331 332 pData->GetArea( nTab, nColStart, nRowStart, 333 nColEnd, nRowEnd ); 334 bResult = sal_True; 335 } 336 } 337 else 338 { 339 DBG_ERROR( "ScRangeUtil::MakeRangeFromName" ); 340 } 341 342 if( bResult ) 343 { 344 rRange = ScRange( nColStart, nRowStart, nTab, nColEnd, nRowEnd, nTab ); 345 } 346 347 return bResult; 348 } 349 350 //======================================================================== 351 352 void ScRangeStringConverter::AssignString( 353 OUString& rString, 354 const OUString& rNewStr, 355 sal_Bool bAppendStr, 356 sal_Unicode cSeperator) 357 { 358 if( bAppendStr ) 359 { 360 if( rNewStr.getLength() ) 361 { 362 if( rString.getLength() ) 363 rString += rtl::OUString(cSeperator); 364 rString += rNewStr; 365 } 366 } 367 else 368 rString = rNewStr; 369 } 370 371 sal_Int32 ScRangeStringConverter::IndexOf( 372 const OUString& rString, 373 sal_Unicode cSearchChar, 374 sal_Int32 nOffset, 375 sal_Unicode cQuote ) 376 { 377 sal_Int32 nLength = rString.getLength(); 378 sal_Int32 nIndex = nOffset; 379 sal_Bool bQuoted = sal_False; 380 sal_Bool bExitLoop = sal_False; 381 382 while( !bExitLoop && (nIndex < nLength) ) 383 { 384 sal_Unicode cCode = rString[ nIndex ]; 385 bExitLoop = (cCode == cSearchChar) && !bQuoted; 386 bQuoted = (bQuoted != (cCode == cQuote)); 387 if( !bExitLoop ) 388 nIndex++; 389 } 390 return (nIndex < nLength) ? nIndex : -1; 391 } 392 393 sal_Int32 ScRangeStringConverter::IndexOfDifferent( 394 const OUString& rString, 395 sal_Unicode cSearchChar, 396 sal_Int32 nOffset ) 397 { 398 sal_Int32 nLength = rString.getLength(); 399 sal_Int32 nIndex = nOffset; 400 sal_Bool bExitLoop = sal_False; 401 402 while( !bExitLoop && (nIndex < nLength) ) 403 { 404 bExitLoop = (rString[ nIndex ] != cSearchChar); 405 if( !bExitLoop ) 406 nIndex++; 407 } 408 return (nIndex < nLength) ? nIndex : -1; 409 } 410 411 void ScRangeStringConverter::GetTokenByOffset( 412 OUString& rToken, 413 const OUString& rString, 414 sal_Int32& nOffset, 415 sal_Unicode cSeperator, 416 sal_Unicode cQuote) 417 { 418 sal_Int32 nLength = rString.getLength(); 419 if( nOffset >= nLength ) 420 { 421 rToken = OUString(); 422 nOffset = -1; 423 } 424 else 425 { 426 sal_Int32 nTokenEnd = IndexOf( rString, cSeperator, nOffset, cQuote ); 427 if( nTokenEnd < 0 ) 428 nTokenEnd = nLength; 429 rToken = rString.copy( nOffset, nTokenEnd - nOffset ); 430 431 sal_Int32 nNextBegin = IndexOfDifferent( rString, cSeperator, nTokenEnd ); 432 nOffset = (nNextBegin < 0) ? nLength : nNextBegin; 433 } 434 } 435 436 void ScRangeStringConverter::AppendTableName(OUStringBuffer& rBuf, const OUString& rTabName, sal_Unicode /* cQuote */) 437 { 438 // quote character is always "'" 439 String aQuotedTab(rTabName); 440 ScCompiler::CheckTabQuotes(aQuotedTab, ::formula::FormulaGrammar::CONV_OOO); 441 rBuf.append(aQuotedTab); 442 } 443 444 sal_Int32 ScRangeStringConverter::GetTokenCount( const OUString& rString, sal_Unicode cSeperator, sal_Unicode cQuote ) 445 { 446 OUString sToken; 447 sal_Int32 nCount = 0; 448 sal_Int32 nOffset = 0; 449 while( nOffset >= 0 ) 450 { 451 GetTokenByOffset( sToken, rString, nOffset, cQuote, cSeperator ); 452 if( nOffset >= 0 ) 453 nCount++; 454 } 455 return nCount; 456 } 457 458 //___________________________________________________________________ 459 460 sal_Bool ScRangeStringConverter::GetAddressFromString( 461 ScAddress& rAddress, 462 const OUString& rAddressStr, 463 const ScDocument* pDocument, 464 FormulaGrammar::AddressConvention eConv, 465 sal_Int32& nOffset, 466 sal_Unicode cSeperator, 467 sal_Unicode cQuote ) 468 { 469 OUString sToken; 470 GetTokenByOffset( sToken, rAddressStr, nOffset, cSeperator, cQuote ); 471 if( nOffset >= 0 ) 472 { 473 if ((rAddress.Parse( sToken, const_cast<ScDocument*>(pDocument), eConv ) & SCA_VALID) == SCA_VALID) 474 return true; 475 } 476 return sal_False; 477 } 478 479 sal_Bool ScRangeStringConverter::GetRangeFromString( 480 ScRange& rRange, 481 const OUString& rRangeStr, 482 const ScDocument* pDocument, 483 FormulaGrammar::AddressConvention eConv, 484 sal_Int32& nOffset, 485 sal_Unicode cSeperator, 486 sal_Unicode cQuote ) 487 { 488 OUString sToken; 489 sal_Bool bResult(sal_False); 490 GetTokenByOffset( sToken, rRangeStr, nOffset, cSeperator, cQuote ); 491 if( nOffset >= 0 ) 492 { 493 sal_Int32 nIndex = IndexOf( sToken, ':', 0, cQuote ); 494 String aUIString(sToken); 495 496 if( nIndex < 0 ) 497 { 498 if ( aUIString.GetChar(0) == (sal_Unicode) '.' ) 499 aUIString.Erase( 0, 1 ); 500 bResult = ((rRange.aStart.Parse( aUIString, const_cast<ScDocument*> (pDocument), eConv) & SCA_VALID) == SCA_VALID); 501 rRange.aEnd = rRange.aStart; 502 } 503 else 504 { 505 if ( aUIString.GetChar(0) == (sal_Unicode) '.' ) 506 { 507 aUIString.Erase( 0, 1 ); 508 --nIndex; 509 } 510 511 if ( nIndex < aUIString.Len() - 1 && 512 aUIString.GetChar((xub_StrLen)nIndex + 1) == (sal_Unicode) '.' ) 513 aUIString.Erase( (xub_StrLen)nIndex + 1, 1 ); 514 515 bResult = ((rRange.Parse(aUIString, const_cast<ScDocument*> (pDocument), eConv) & SCA_VALID) == SCA_VALID); 516 517 // #i77703# chart ranges in the file format contain both sheet names, even for an external reference sheet. 518 // This isn't parsed by ScRange, so try to parse the two Addresses then. 519 if (!bResult) 520 { 521 bResult = ((rRange.aStart.Parse( aUIString.Copy(0, (xub_StrLen)nIndex), const_cast<ScDocument*>(pDocument), 522 eConv) & SCA_VALID) == SCA_VALID) && 523 ((rRange.aEnd.Parse( aUIString.Copy((xub_StrLen)nIndex+1), const_cast<ScDocument*>(pDocument), 524 eConv) & SCA_VALID) == SCA_VALID); 525 } 526 } 527 } 528 return bResult; 529 } 530 531 sal_Bool ScRangeStringConverter::GetRangeListFromString( 532 ScRangeList& rRangeList, 533 const OUString& rRangeListStr, 534 const ScDocument* pDocument, 535 FormulaGrammar::AddressConvention eConv, 536 sal_Unicode cSeperator, 537 sal_Unicode cQuote ) 538 { 539 sal_Bool bRet = sal_True; 540 DBG_ASSERT( rRangeListStr.getLength(), "ScXMLConverter::GetRangeListFromString - empty string!" ); 541 sal_Int32 nOffset = 0; 542 while( nOffset >= 0 ) 543 { 544 ScRange* pRange = new ScRange; 545 if( GetRangeFromString( *pRange, rRangeListStr, pDocument, eConv, nOffset, cSeperator, cQuote ) && (nOffset >= 0) ) 546 rRangeList.Insert( pRange, LIST_APPEND ); 547 else if (nOffset > -1) 548 bRet = sal_False; 549 } 550 return bRet; 551 } 552 553 554 //___________________________________________________________________ 555 556 sal_Bool ScRangeStringConverter::GetAreaFromString( 557 ScArea& rArea, 558 const OUString& rRangeStr, 559 const ScDocument* pDocument, 560 FormulaGrammar::AddressConvention eConv, 561 sal_Int32& nOffset, 562 sal_Unicode cSeperator, 563 sal_Unicode cQuote ) 564 { 565 ScRange aScRange; 566 sal_Bool bResult(sal_False); 567 if( GetRangeFromString( aScRange, rRangeStr, pDocument, eConv, nOffset, cSeperator, cQuote ) && (nOffset >= 0) ) 568 { 569 rArea.nTab = aScRange.aStart.Tab(); 570 rArea.nColStart = aScRange.aStart.Col(); 571 rArea.nRowStart = aScRange.aStart.Row(); 572 rArea.nColEnd = aScRange.aEnd.Col(); 573 rArea.nRowEnd = aScRange.aEnd.Row(); 574 bResult = sal_True; 575 } 576 return bResult; 577 } 578 579 580 //___________________________________________________________________ 581 582 sal_Bool ScRangeStringConverter::GetAddressFromString( 583 table::CellAddress& rAddress, 584 const OUString& rAddressStr, 585 const ScDocument* pDocument, 586 FormulaGrammar::AddressConvention eConv, 587 sal_Int32& nOffset, 588 sal_Unicode cSeperator, 589 sal_Unicode cQuote ) 590 { 591 ScAddress aScAddress; 592 sal_Bool bResult(sal_False); 593 if( GetAddressFromString( aScAddress, rAddressStr, pDocument, eConv, nOffset, cSeperator, cQuote ) && (nOffset >= 0) ) 594 { 595 ScUnoConversion::FillApiAddress( rAddress, aScAddress ); 596 bResult = sal_True; 597 } 598 return bResult; 599 } 600 601 sal_Bool ScRangeStringConverter::GetRangeFromString( 602 table::CellRangeAddress& rRange, 603 const OUString& rRangeStr, 604 const ScDocument* pDocument, 605 FormulaGrammar::AddressConvention eConv, 606 sal_Int32& nOffset, 607 sal_Unicode cSeperator, 608 sal_Unicode cQuote ) 609 { 610 ScRange aScRange; 611 sal_Bool bResult(sal_False); 612 if( GetRangeFromString( aScRange, rRangeStr, pDocument, eConv, nOffset, cSeperator, cQuote ) && (nOffset >= 0) ) 613 { 614 ScUnoConversion::FillApiRange( rRange, aScRange ); 615 bResult = sal_True; 616 } 617 return bResult; 618 } 619 620 sal_Bool ScRangeStringConverter::GetRangeListFromString( 621 uno::Sequence< table::CellRangeAddress >& rRangeSeq, 622 const OUString& rRangeListStr, 623 const ScDocument* pDocument, 624 FormulaGrammar::AddressConvention eConv, 625 sal_Unicode cSeperator, 626 sal_Unicode cQuote ) 627 { 628 sal_Bool bRet = sal_True; 629 DBG_ASSERT( rRangeListStr.getLength(), "ScXMLConverter::GetRangeListFromString - empty string!" ); 630 table::CellRangeAddress aRange; 631 sal_Int32 nOffset = 0; 632 while( nOffset >= 0 ) 633 { 634 if( GetRangeFromString( aRange, rRangeListStr, pDocument, eConv, nOffset, cSeperator, cQuote ) && (nOffset >= 0) ) 635 { 636 rRangeSeq.realloc( rRangeSeq.getLength() + 1 ); 637 rRangeSeq[ rRangeSeq.getLength() - 1 ] = aRange; 638 } 639 else 640 bRet = sal_False; 641 } 642 return bRet; 643 } 644 645 646 //___________________________________________________________________ 647 648 void ScRangeStringConverter::GetStringFromAddress( 649 OUString& rString, 650 const ScAddress& rAddress, 651 const ScDocument* pDocument, 652 FormulaGrammar::AddressConvention eConv, 653 sal_Unicode cSeperator, 654 sal_Bool bAppendStr, 655 sal_uInt16 nFormatFlags ) 656 { 657 if (pDocument && pDocument->HasTable(rAddress.Tab())) 658 { 659 String sAddress; 660 rAddress.Format( sAddress, nFormatFlags, (ScDocument*) pDocument, eConv ); 661 AssignString( rString, sAddress, bAppendStr, cSeperator ); 662 } 663 } 664 665 void ScRangeStringConverter::GetStringFromRange( 666 OUString& rString, 667 const ScRange& rRange, 668 const ScDocument* pDocument, 669 FormulaGrammar::AddressConvention eConv, 670 sal_Unicode cSeperator, 671 sal_Bool bAppendStr, 672 sal_uInt16 nFormatFlags ) 673 { 674 if (pDocument && pDocument->HasTable(rRange.aStart.Tab())) 675 { 676 ScAddress aStartAddress( rRange.aStart ); 677 ScAddress aEndAddress( rRange.aEnd ); 678 String sStartAddress; 679 String sEndAddress; 680 aStartAddress.Format( sStartAddress, nFormatFlags, (ScDocument*) pDocument, eConv ); 681 aEndAddress.Format( sEndAddress, nFormatFlags, (ScDocument*) pDocument, eConv ); 682 OUString sOUStartAddress( sStartAddress ); 683 sOUStartAddress += OUString(':'); 684 sOUStartAddress += OUString( sEndAddress ); 685 AssignString( rString, sOUStartAddress, bAppendStr, cSeperator ); 686 } 687 } 688 689 void ScRangeStringConverter::GetStringFromRangeList( 690 OUString& rString, 691 const ScRangeList* pRangeList, 692 const ScDocument* pDocument, 693 FormulaGrammar::AddressConvention eConv, 694 sal_Unicode cSeperator, 695 sal_uInt16 nFormatFlags ) 696 { 697 OUString sRangeListStr; 698 if( pRangeList ) 699 { 700 sal_Int32 nCount = pRangeList->Count(); 701 for( sal_Int32 nIndex = 0; nIndex < nCount; nIndex++ ) 702 { 703 const ScRange* pRange = pRangeList->GetObject( nIndex ); 704 if( pRange ) 705 GetStringFromRange( sRangeListStr, *pRange, pDocument, eConv, cSeperator, sal_True, nFormatFlags ); 706 } 707 } 708 rString = sRangeListStr; 709 } 710 711 712 //___________________________________________________________________ 713 714 void ScRangeStringConverter::GetStringFromArea( 715 OUString& rString, 716 const ScArea& rArea, 717 const ScDocument* pDocument, 718 FormulaGrammar::AddressConvention eConv, 719 sal_Unicode cSeperator, 720 sal_Bool bAppendStr, 721 sal_uInt16 nFormatFlags ) 722 { 723 ScRange aRange( rArea.nColStart, rArea.nRowStart, rArea.nTab, rArea.nColEnd, rArea.nRowEnd, rArea.nTab ); 724 GetStringFromRange( rString, aRange, pDocument, eConv, cSeperator, bAppendStr, nFormatFlags ); 725 } 726 727 728 //___________________________________________________________________ 729 730 void ScRangeStringConverter::GetStringFromAddress( 731 OUString& rString, 732 const table::CellAddress& rAddress, 733 const ScDocument* pDocument, 734 FormulaGrammar::AddressConvention eConv, 735 sal_Unicode cSeperator, 736 sal_Bool bAppendStr, 737 sal_uInt16 nFormatFlags ) 738 { 739 ScAddress aScAddress( static_cast<SCCOL>(rAddress.Column), static_cast<SCROW>(rAddress.Row), rAddress.Sheet ); 740 GetStringFromAddress( rString, aScAddress, pDocument, eConv, cSeperator, bAppendStr, nFormatFlags ); 741 } 742 743 void ScRangeStringConverter::GetStringFromRange( 744 OUString& rString, 745 const table::CellRangeAddress& rRange, 746 const ScDocument* pDocument, 747 FormulaGrammar::AddressConvention eConv, 748 sal_Unicode cSeperator, 749 sal_Bool bAppendStr, 750 sal_uInt16 nFormatFlags ) 751 { 752 ScRange aScRange( static_cast<SCCOL>(rRange.StartColumn), static_cast<SCROW>(rRange.StartRow), rRange.Sheet, 753 static_cast<SCCOL>(rRange.EndColumn), static_cast<SCROW>(rRange.EndRow), rRange.Sheet ); 754 GetStringFromRange( rString, aScRange, pDocument, eConv, cSeperator, bAppendStr, nFormatFlags ); 755 } 756 757 void ScRangeStringConverter::GetStringFromRangeList( 758 OUString& rString, 759 const uno::Sequence< table::CellRangeAddress >& rRangeSeq, 760 const ScDocument* pDocument, 761 FormulaGrammar::AddressConvention eConv, 762 sal_Unicode cSeperator, 763 sal_uInt16 nFormatFlags ) 764 { 765 OUString sRangeListStr; 766 sal_Int32 nCount = rRangeSeq.getLength(); 767 for( sal_Int32 nIndex = 0; nIndex < nCount; nIndex++ ) 768 { 769 const table::CellRangeAddress& rRange = rRangeSeq[ nIndex ]; 770 GetStringFromRange( sRangeListStr, rRange, pDocument, eConv, cSeperator, sal_True, nFormatFlags ); 771 } 772 rString = sRangeListStr; 773 } 774 775 static void lcl_appendCellAddress( 776 rtl::OUStringBuffer& rBuf, ScDocument* pDoc, const ScAddress& rCell, 777 const ScAddress::ExternalInfo& rExtInfo) 778 { 779 if (rExtInfo.mbExternal) 780 { 781 ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager(); 782 const String* pFilePath = pRefMgr->getExternalFileName(rExtInfo.mnFileId, true); 783 if (!pFilePath) 784 return; 785 786 sal_Unicode cQuote = '\''; 787 rBuf.append(cQuote); 788 rBuf.append(*pFilePath); 789 rBuf.append(cQuote); 790 rBuf.append(sal_Unicode('#')); 791 rBuf.append(sal_Unicode('$')); 792 ScRangeStringConverter::AppendTableName(rBuf, rExtInfo.maTabName); 793 rBuf.append(sal_Unicode('.')); 794 795 String aAddr; 796 rCell.Format(aAddr, SCA_ABS, NULL, ::formula::FormulaGrammar::CONV_OOO); 797 rBuf.append(aAddr); 798 } 799 else 800 { 801 String aAddr; 802 rCell.Format(aAddr, SCA_ABS_3D, pDoc, ::formula::FormulaGrammar::CONV_OOO); 803 rBuf.append(aAddr); 804 } 805 } 806 807 static void lcl_appendCellRangeAddress( 808 rtl::OUStringBuffer& rBuf, ScDocument* pDoc, const ScAddress& rCell1, const ScAddress& rCell2, 809 const ScAddress::ExternalInfo& rExtInfo1, const ScAddress::ExternalInfo& rExtInfo2) 810 { 811 if (rExtInfo1.mbExternal) 812 { 813 DBG_ASSERT(rExtInfo2.mbExternal, "2nd address is not external!?"); 814 DBG_ASSERT(rExtInfo1.mnFileId == rExtInfo2.mnFileId, "File IDs do not match between 1st and 2nd addresses."); 815 816 ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager(); 817 const String* pFilePath = pRefMgr->getExternalFileName(rExtInfo1.mnFileId, true); 818 if (!pFilePath) 819 return; 820 821 sal_Unicode cQuote = '\''; 822 rBuf.append(cQuote); 823 rBuf.append(*pFilePath); 824 rBuf.append(cQuote); 825 rBuf.append(sal_Unicode('#')); 826 rBuf.append(sal_Unicode('$')); 827 ScRangeStringConverter::AppendTableName(rBuf, rExtInfo1.maTabName); 828 rBuf.append(sal_Unicode('.')); 829 830 String aAddr; 831 rCell1.Format(aAddr, SCA_ABS, NULL, ::formula::FormulaGrammar::CONV_OOO); 832 rBuf.append(aAddr); 833 834 rBuf.appendAscii(":"); 835 836 if (rExtInfo1.maTabName != rExtInfo2.maTabName) 837 { 838 rBuf.append(sal_Unicode('$')); 839 ScRangeStringConverter::AppendTableName(rBuf, rExtInfo2.maTabName); 840 rBuf.append(sal_Unicode('.')); 841 } 842 843 rCell2.Format(aAddr, SCA_ABS, NULL, ::formula::FormulaGrammar::CONV_OOO); 844 rBuf.append(aAddr); 845 } 846 else 847 { 848 ScRange aRange; 849 aRange.aStart = rCell1; 850 aRange.aEnd = rCell2; 851 String aAddr; 852 aRange.Format(aAddr, SCR_ABS_3D, pDoc, ::formula::FormulaGrammar::CONV_OOO); 853 rBuf.append(aAddr); 854 } 855 } 856 857 void ScRangeStringConverter::GetStringFromXMLRangeString( OUString& rString, const OUString& rXMLRange, ScDocument* pDoc ) 858 { 859 const sal_Unicode cSep = ' '; 860 const sal_Unicode cQuote = '\''; 861 862 OUStringBuffer aRetStr; 863 sal_Int32 nOffset = 0; 864 bool bFirst = true; 865 866 while (nOffset >= 0) 867 { 868 OUString aToken; 869 GetTokenByOffset(aToken, rXMLRange, nOffset, cSep, cQuote); 870 if (nOffset < 0) 871 break; 872 873 sal_Int32 nSepPos = IndexOf(aToken, ':', 0, cQuote); 874 if (nSepPos >= 0) 875 { 876 // Cell range 877 OUString aBeginCell = aToken.copy(0, nSepPos); 878 OUString aEndCell = aToken.copy(nSepPos+1); 879 880 if (!aBeginCell.getLength() || !aEndCell.getLength()) 881 // both cell addresses must exist for this to work. 882 continue; 883 884 sal_Int32 nEndCellDotPos = aEndCell.indexOf('.'); 885 if (nEndCellDotPos <= 0) 886 { 887 // initialize buffer with table name... 888 sal_Int32 nDotPos = IndexOf(aBeginCell, sal_Unicode('.'), 0, cQuote); 889 OUStringBuffer aBuf = aBeginCell.copy(0, nDotPos); 890 891 if (nEndCellDotPos == 0) 892 { 893 // workaround for old syntax (probably pre-chart2 age?) 894 // e.g. Sheet1.A1:.B2 895 aBuf.append(aEndCell); 896 } 897 else if (nEndCellDotPos < 0) 898 { 899 // sheet name in the end cell is omitted (e.g. Sheet2.A1:B2). 900 aBuf.append(sal_Unicode('.')); 901 aBuf.append(aEndCell); 902 } 903 aEndCell = aBuf.makeStringAndClear(); 904 } 905 906 ScAddress::ExternalInfo aExtInfo1, aExtInfo2; 907 ScAddress aCell1, aCell2; 908 rtl::OUString aBuf; 909 sal_uInt16 nRet = aCell1.Parse(aBeginCell, pDoc, FormulaGrammar::CONV_OOO, &aExtInfo1); 910 if ((nRet & SCA_VALID) != SCA_VALID) 911 // first cell is invalid. 912 continue; 913 914 nRet = aCell2.Parse(aEndCell, pDoc, FormulaGrammar::CONV_OOO, &aExtInfo2); 915 if ((nRet & SCA_VALID) != SCA_VALID) 916 // second cell is invalid. 917 continue; 918 919 if (aExtInfo1.mnFileId != aExtInfo2.mnFileId || aExtInfo1.mbExternal != aExtInfo2.mbExternal) 920 // external info inconsistency. 921 continue; 922 923 // All looks good! 924 925 if (bFirst) 926 bFirst = false; 927 else 928 aRetStr.appendAscii(";"); 929 930 lcl_appendCellRangeAddress(aRetStr, pDoc, aCell1, aCell2, aExtInfo1, aExtInfo2); 931 } 932 else 933 { 934 // Chart always saves ranges using CONV_OOO convention. 935 ScAddress::ExternalInfo aExtInfo; 936 ScAddress aCell; 937 sal_uInt16 nRet = aCell.Parse(aToken, pDoc, ::formula::FormulaGrammar::CONV_OOO, &aExtInfo); 938 if ((nRet & SCA_VALID) != SCA_VALID) 939 continue; 940 941 // Looks good! 942 943 if (bFirst) 944 bFirst = false; 945 else 946 aRetStr.appendAscii(";"); 947 948 lcl_appendCellAddress(aRetStr, pDoc, aCell, aExtInfo); 949 } 950 } 951 952 rString = aRetStr.makeStringAndClear(); 953 } 954 955 //======================================================================== 956 957 ScArea::ScArea( SCTAB tab, 958 SCCOL colStart, SCROW rowStart, 959 SCCOL colEnd, SCROW rowEnd ) : 960 nTab ( tab ), 961 nColStart( colStart ), nRowStart( rowStart ), 962 nColEnd ( colEnd ), nRowEnd ( rowEnd ) 963 { 964 } 965 966 //------------------------------------------------------------------------ 967 968 ScArea::ScArea( const ScArea& r ) : 969 nTab ( r.nTab ), 970 nColStart( r.nColStart ), nRowStart( r.nRowStart ), 971 nColEnd ( r.nColEnd ), nRowEnd ( r.nRowEnd ) 972 { 973 } 974 975 //------------------------------------------------------------------------ 976 977 ScArea& ScArea::operator=( const ScArea& r ) 978 { 979 nTab = r.nTab; 980 nColStart = r.nColStart; 981 nRowStart = r.nRowStart; 982 nColEnd = r.nColEnd; 983 nRowEnd = r.nRowEnd; 984 return *this; 985 } 986 987 //------------------------------------------------------------------------ 988 989 sal_Bool ScArea::operator==( const ScArea& r ) const 990 { 991 return ( (nTab == r.nTab) 992 && (nColStart == r.nColStart) 993 && (nRowStart == r.nRowStart) 994 && (nColEnd == r.nColEnd) 995 && (nRowEnd == r.nRowEnd) ); 996 } 997 998 //------------------------------------------------------------------------ 999 1000 ScAreaNameIterator::ScAreaNameIterator( ScDocument* pDoc ) : 1001 aStrNoName( ScGlobal::GetRscString(STR_DB_NONAME) ) 1002 { 1003 pRangeName = pDoc->GetRangeName(); 1004 pDBCollection = pDoc->GetDBCollection(); 1005 nPos = 0; 1006 bFirstPass = sal_True; 1007 } 1008 1009 sal_Bool ScAreaNameIterator::Next( String& rName, ScRange& rRange ) 1010 { 1011 for (;;) 1012 { 1013 if ( bFirstPass ) // erst Bereichsnamen 1014 { 1015 if ( pRangeName && nPos < pRangeName->GetCount() ) 1016 { 1017 ScRangeData* pData = (*pRangeName)[nPos++]; 1018 if ( pData && pData->IsValidReference(rRange) ) 1019 { 1020 rName = pData->GetName(); 1021 return sal_True; // gefunden 1022 } 1023 } 1024 else 1025 { 1026 bFirstPass = sal_False; 1027 nPos = 0; 1028 } 1029 } 1030 if ( !bFirstPass ) // dann DB-Bereiche 1031 { 1032 if ( pDBCollection && nPos < pDBCollection->GetCount() ) 1033 { 1034 ScDBData* pData = (*pDBCollection)[nPos++]; 1035 // if (pData && pData->GetName() != aStrNoName) 1036 if (pData && !pData->IsBuildin()) 1037 { 1038 pData->GetArea( rRange ); 1039 rName = pData->GetName(); 1040 return sal_True; // gefunden 1041 } 1042 } 1043 else 1044 return sal_False; // gibt nichts mehr 1045 } 1046 } 1047 } 1048 1049 1050 1051 1052