fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / core / tool / rangeutl.cxx
blobe101463d2d13d5448c6b953867fd6185dd9bdcf6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "rangeutl.hxx"
21 #include "document.hxx"
22 #include "global.hxx"
23 #include "dbdata.hxx"
24 #include "rangenam.hxx"
25 #include "scresid.hxx"
26 #include "globstr.hrc"
27 #include "convuno.hxx"
28 #include "externalrefmgr.hxx"
29 #include "compiler.hxx"
31 using ::formula::FormulaGrammar;
32 using namespace ::com::sun::star;
34 bool ScRangeUtil::MakeArea( const OUString& rAreaStr,
35 ScArea& rArea,
36 ScDocument* pDoc,
37 SCTAB nTab,
38 ScAddress::Details const & rDetails )
40 // Input in rAreaStr: "$Tabelle1.$A1:$D17"
42 // BROKEN BROKEN BROKEN
43 // but it is only used in the consolidate dialog. Ignore for now.
45 bool nSuccess = false;
46 sal_Int32 nPointPos = rAreaStr.indexOf('.');
47 sal_Int32 nColonPos = rAreaStr.indexOf(':');
48 OUString aStrArea( rAreaStr );
49 ScRefAddress startPos;
50 ScRefAddress endPos;
52 if ( nColonPos == -1 && nPointPos != -1 )
54 aStrArea += ":";
55 aStrArea += rAreaStr.copy( nPointPos+1 ); // do not include '.' in copy
58 nSuccess = ConvertDoubleRef( pDoc, aStrArea, nTab, startPos, endPos, rDetails );
60 if ( nSuccess )
61 rArea = ScArea( startPos.Tab(),
62 startPos.Col(), startPos.Row(),
63 endPos.Col(), endPos.Row() );
65 return nSuccess;
68 void ScRangeUtil::CutPosString( const OUString& theAreaStr,
69 OUString& thePosStr )
71 OUString aPosStr;
72 // BROKEN BROKEN BROKEN
73 // but it is only used in the consolidate dialog. Ignore for now.
75 sal_Int32 nColonPos = theAreaStr.indexOf(':');
77 if ( nColonPos != -1 )
78 aPosStr = theAreaStr.copy( 0, nColonPos ); // do not include ':' in copy
79 else
80 aPosStr = theAreaStr;
82 thePosStr = aPosStr;
85 bool ScRangeUtil::IsAbsTabArea( const OUString& rAreaStr,
86 ScDocument* pDoc,
87 ScArea*** pppAreas,
88 sal_uInt16* pAreaCount,
89 bool /* bAcceptCellRef */,
90 ScAddress::Details const & rDetails )
92 OSL_ENSURE( pDoc, "No document given!" );
93 if ( !pDoc )
94 return false;
96 // BROKEN BROKEN BROKEN
97 // but it is only used in the consolidate dialog. Ignore for now.
100 * Expects strings like:
101 * "$Tabelle1.$A$1:$Tabelle3.$D$17"
102 * If bAcceptCellRef == sal_True then also accept strings like:
103 * "$Tabelle1.$A$1"
105 * as result a ScArea-Array is created,
106 * which is published via ppAreas and also has to be deleted this route.
109 bool bStrOk = false;
110 OUString aTempAreaStr(rAreaStr);
111 OUString aStartPosStr;
112 OUString aEndPosStr;
114 if ( -1 == aTempAreaStr.indexOf(':') )
116 aTempAreaStr += ":";
117 aTempAreaStr += rAreaStr;
120 sal_Int32 nColonPos = aTempAreaStr.indexOf(':');
122 if ( -1 != nColonPos
123 && -1 != aTempAreaStr.indexOf('.') )
125 ScRefAddress aStartPos;
126 ScRefAddress aEndPos;
128 aStartPosStr = aTempAreaStr.copy( 0, nColonPos );
129 aEndPosStr = aTempAreaStr.copy( nColonPos+1 );
131 if ( ConvertSingleRef( pDoc, aStartPosStr, 0, aStartPos, rDetails ) )
133 if ( ConvertSingleRef( pDoc, aEndPosStr, aStartPos.Tab(), aEndPos, rDetails ) )
135 aStartPos.SetRelCol( false );
136 aStartPos.SetRelRow( false );
137 aStartPos.SetRelTab( false );
138 aEndPos.SetRelCol( false );
139 aEndPos.SetRelRow( false );
140 aEndPos.SetRelTab( false );
142 bStrOk = true;
144 if ( pppAreas && pAreaCount ) // Array returned ?
146 SCTAB nStartTab = aStartPos.Tab();
147 SCTAB nEndTab = aEndPos.Tab();
148 sal_uInt16 nTabCount = static_cast<sal_uInt16>(nEndTab-nStartTab+1);
149 ScArea** theAreas = new ScArea*[nTabCount];
150 SCTAB nTab = 0;
151 sal_uInt16 i = 0;
152 ScArea theArea( 0, aStartPos.Col(), aStartPos.Row(),
153 aEndPos.Col(), aEndPos.Row() );
155 nTab = nStartTab;
156 for ( i=0; i<nTabCount; i++ )
158 theAreas[i] = new ScArea( theArea );
159 theAreas[i]->nTab = nTab;
160 nTab++;
162 *pppAreas = theAreas;
163 *pAreaCount = nTabCount;
169 return bStrOk;
172 bool ScRangeUtil::IsAbsArea( const OUString& rAreaStr,
173 ScDocument* pDoc,
174 SCTAB nTab,
175 OUString* pCompleteStr,
176 ScRefAddress* pStartPos,
177 ScRefAddress* pEndPos,
178 ScAddress::Details const & rDetails )
180 ScRefAddress startPos;
181 ScRefAddress endPos;
183 bool bIsAbsArea = ConvertDoubleRef( pDoc, rAreaStr, nTab, startPos, endPos, rDetails );
185 if ( bIsAbsArea )
187 startPos.SetRelCol( false );
188 startPos.SetRelRow( false );
189 startPos.SetRelTab( false );
190 endPos .SetRelCol( false );
191 endPos .SetRelRow( false );
192 endPos .SetRelTab( false );
194 if ( pCompleteStr )
196 *pCompleteStr = startPos.GetRefString( pDoc, MAXTAB+1, rDetails );
197 *pCompleteStr += ":";
198 *pCompleteStr += endPos .GetRefString( pDoc, nTab, rDetails );
201 if ( pStartPos && pEndPos )
203 *pStartPos = startPos;
204 *pEndPos = endPos;
208 return bIsAbsArea;
211 bool ScRangeUtil::IsAbsPos( const OUString& rPosStr,
212 ScDocument* pDoc,
213 SCTAB nTab,
214 OUString* pCompleteStr,
215 ScRefAddress* pPosTripel,
216 ScAddress::Details const & rDetails )
218 ScRefAddress thePos;
220 bool bIsAbsPos = ConvertSingleRef( pDoc, rPosStr, nTab, thePos, rDetails );
221 thePos.SetRelCol( false );
222 thePos.SetRelRow( false );
223 thePos.SetRelTab( false );
225 if ( bIsAbsPos )
227 if ( pPosTripel )
228 *pPosTripel = thePos;
229 if ( pCompleteStr )
230 *pCompleteStr = thePos.GetRefString( pDoc, MAXTAB+1, rDetails );
233 return bIsAbsPos;
236 bool ScRangeUtil::MakeRangeFromName (
237 const OUString& rName,
238 ScDocument* pDoc,
239 SCTAB nCurTab,
240 ScRange& rRange,
241 RutlNameScope eScope,
242 ScAddress::Details const & rDetails )
244 bool bResult = false;
245 ScRangeUtil aRangeUtil;
246 SCTAB nTab = 0;
247 SCCOL nColStart = 0;
248 SCCOL nColEnd = 0;
249 SCROW nRowStart = 0;
250 SCROW nRowEnd = 0;
252 if( eScope==RUTL_NAMES )
254 //first handle ui names like local1 (Sheet1), which point to a local range name
255 OUString aName(rName);
256 sal_Int32 nEndPos = aName.lastIndexOf(')');
257 sal_Int32 nStartPos = aName.lastIndexOf(" (");
258 SCTAB nTable = nCurTab;
259 if (nEndPos != -1 && nStartPos != -1)
261 OUString aSheetName = aName.copy(nStartPos+2, nEndPos-nStartPos-2);
262 if (pDoc->GetTable(aSheetName, nTable))
264 aName = aName.copy(0, nStartPos);
266 else
267 nTable = nCurTab;
269 //then check for local range names
270 ScRangeName* pRangeNames = pDoc->GetRangeName( nTable );
271 ScRangeData* pData = NULL;
272 if ( pRangeNames )
273 pData = pRangeNames->findByUpperName(ScGlobal::pCharClass->uppercase(aName));
274 if (!pData)
275 pData = pDoc->GetRangeName()->findByUpperName(ScGlobal::pCharClass->uppercase(aName));
276 if (pData)
278 OUString aStrArea;
279 ScRefAddress aStartPos;
280 ScRefAddress aEndPos;
282 pData->GetSymbol( aStrArea );
284 if ( IsAbsArea( aStrArea, pDoc, nTable,
285 NULL, &aStartPos, &aEndPos, rDetails ) )
287 nTab = aStartPos.Tab();
288 nColStart = aStartPos.Col();
289 nRowStart = aStartPos.Row();
290 nColEnd = aEndPos.Col();
291 nRowEnd = aEndPos.Row();
292 bResult = true;
294 else
296 CutPosString( aStrArea, aStrArea );
298 if ( IsAbsPos( aStrArea, pDoc, nTable,
299 NULL, &aStartPos, rDetails ) )
301 nTab = aStartPos.Tab();
302 nColStart = nColEnd = aStartPos.Col();
303 nRowStart = nRowEnd = aStartPos.Row();
304 bResult = true;
309 else if( eScope==RUTL_DBASE )
311 ScDBCollection::NamedDBs& rDbNames = pDoc->GetDBCollection()->getNamedDBs();
312 ScDBData* pData = rDbNames.findByUpperName(ScGlobal::pCharClass->uppercase(rName));
313 if (pData)
315 pData->GetArea(nTab, nColStart, nRowStart, nColEnd, nRowEnd);
316 bResult = true;
319 else
321 OSL_FAIL( "ScRangeUtil::MakeRangeFromName" );
324 if( bResult )
326 rRange = ScRange( nColStart, nRowStart, nTab, nColEnd, nRowEnd, nTab );
329 return bResult;
332 void ScRangeStringConverter::AssignString(
333 OUString& rString,
334 const OUString& rNewStr,
335 bool bAppendStr,
336 sal_Unicode cSeparator)
338 if( bAppendStr )
340 if( !rNewStr.isEmpty() )
342 if( !rString.isEmpty() )
343 rString += OUString(cSeparator);
344 rString += rNewStr;
347 else
348 rString = rNewStr;
351 sal_Int32 ScRangeStringConverter::IndexOf(
352 const OUString& rString,
353 sal_Unicode cSearchChar,
354 sal_Int32 nOffset,
355 sal_Unicode cQuote )
357 sal_Int32 nLength = rString.getLength();
358 sal_Int32 nIndex = nOffset;
359 bool bQuoted = false;
360 bool bExitLoop = false;
362 while( !bExitLoop && (nIndex >= 0 && nIndex < nLength) )
364 sal_Unicode cCode = rString[ nIndex ];
365 bExitLoop = (cCode == cSearchChar) && !bQuoted;
366 bQuoted = (bQuoted != (cCode == cQuote));
367 if( !bExitLoop )
368 nIndex++;
370 return (nIndex < nLength) ? nIndex : -1;
373 sal_Int32 ScRangeStringConverter::IndexOfDifferent(
374 const OUString& rString,
375 sal_Unicode cSearchChar,
376 sal_Int32 nOffset )
378 sal_Int32 nLength = rString.getLength();
379 sal_Int32 nIndex = nOffset;
380 bool bExitLoop = false;
382 while( !bExitLoop && (nIndex >= 0 && nIndex < nLength) )
384 bExitLoop = (rString[ nIndex ] != cSearchChar);
385 if( !bExitLoop )
386 nIndex++;
388 return (nIndex < nLength) ? nIndex : -1;
391 void ScRangeStringConverter::GetTokenByOffset(
392 OUString& rToken,
393 const OUString& rString,
394 sal_Int32& nOffset,
395 sal_Unicode cSeparator,
396 sal_Unicode cQuote)
398 sal_Int32 nLength = rString.getLength();
399 if( nOffset == -1 || nOffset >= nLength )
401 rToken.clear();
402 nOffset = -1;
404 else
406 sal_Int32 nTokenEnd = IndexOf( rString, cSeparator, nOffset, cQuote );
407 if( nTokenEnd < 0 )
408 nTokenEnd = nLength;
409 rToken = rString.copy( nOffset, nTokenEnd - nOffset );
411 sal_Int32 nNextBegin = IndexOfDifferent( rString, cSeparator, nTokenEnd );
412 nOffset = (nNextBegin < 0) ? nLength : nNextBegin;
416 void ScRangeStringConverter::AppendTableName(OUStringBuffer& rBuf, const OUString& rTabName, sal_Unicode /* cQuote */)
418 // quote character is always "'"
419 OUString aQuotedTab(rTabName);
420 ScCompiler::CheckTabQuotes(aQuotedTab, ::formula::FormulaGrammar::CONV_OOO);
421 rBuf.append(aQuotedTab);
424 sal_Int32 ScRangeStringConverter::GetTokenCount( const OUString& rString, sal_Unicode cSeparator, sal_Unicode cQuote )
426 OUString sToken;
427 sal_Int32 nCount = 0;
428 sal_Int32 nOffset = 0;
429 while( nOffset >= 0 )
431 GetTokenByOffset( sToken, rString, nOffset, cQuote, cSeparator );
432 if( nOffset >= 0 )
433 nCount++;
435 return nCount;
438 bool ScRangeStringConverter::GetAddressFromString(
439 ScAddress& rAddress,
440 const OUString& rAddressStr,
441 const ScDocument* pDocument,
442 FormulaGrammar::AddressConvention eConv,
443 sal_Int32& nOffset,
444 sal_Unicode cSeparator,
445 sal_Unicode cQuote )
447 OUString sToken;
448 GetTokenByOffset( sToken, rAddressStr, nOffset, cSeparator, cQuote );
449 if( nOffset >= 0 )
451 if ((rAddress.Parse( sToken, const_cast<ScDocument*>(pDocument), eConv ) & SCA_VALID) == SCA_VALID)
452 return true;
453 ::formula::FormulaGrammar::AddressConvention eConvUI = pDocument->GetAddressConvention();
454 if (eConv != eConvUI)
455 return ((rAddress.Parse(sToken, const_cast<ScDocument*>(pDocument), eConvUI) & SCA_VALID) == SCA_VALID);
457 return false;
460 bool ScRangeStringConverter::GetRangeFromString(
461 ScRange& rRange,
462 const OUString& rRangeStr,
463 const ScDocument* pDocument,
464 FormulaGrammar::AddressConvention eConv,
465 sal_Int32& nOffset,
466 sal_Unicode cSeparator,
467 sal_Unicode cQuote )
469 OUString sToken;
470 bool bResult(false);
471 GetTokenByOffset( sToken, rRangeStr, nOffset, cSeparator, cQuote );
472 if( nOffset >= 0 )
474 sal_Int32 nIndex = IndexOf( sToken, ':', 0, cQuote );
475 OUString aUIString(sToken);
477 if( nIndex < 0 )
479 if ( aUIString[0] == '.' )
480 aUIString = aUIString.copy( 1 );
481 bResult = ((rRange.aStart.Parse( aUIString, const_cast<ScDocument*> (pDocument), eConv) & SCA_VALID) == SCA_VALID);
482 ::formula::FormulaGrammar::AddressConvention eConvUI = pDocument->GetAddressConvention();
483 if (!bResult && eConv != eConvUI)
484 bResult = ((rRange.aStart.Parse(
485 aUIString, const_cast<ScDocument*>(pDocument), eConvUI) & SCA_VALID) == SCA_VALID);
486 rRange.aEnd = rRange.aStart;
488 else
490 if ( aUIString[0] == '.' )
492 aUIString = aUIString.copy( 1 );
493 --nIndex;
496 if ( nIndex < aUIString.getLength() - 1 &&
497 aUIString[ nIndex + 1 ] == '.' )
498 aUIString = aUIString.replaceAt( nIndex + 1, 1, "" );
500 bResult = ((rRange.Parse(aUIString, const_cast<ScDocument*> (pDocument), eConv) & SCA_VALID) == SCA_VALID);
502 // #i77703# chart ranges in the file format contain both sheet names, even for an external reference sheet.
503 // This isn't parsed by ScRange, so try to parse the two Addresses then.
504 if (!bResult)
506 bResult = ((rRange.aStart.Parse( aUIString.copy(0, nIndex), const_cast<ScDocument*>(pDocument),
507 eConv) & SCA_VALID) == SCA_VALID) &&
508 ((rRange.aEnd.Parse( aUIString.copy(nIndex+1), const_cast<ScDocument*>(pDocument),
509 eConv) & SCA_VALID) == SCA_VALID);
511 ::formula::FormulaGrammar::AddressConvention eConvUI = pDocument->GetAddressConvention();
512 if (!bResult && eConv != eConvUI)
514 bResult = ((rRange.aStart.Parse( aUIString.copy(0, nIndex), const_cast<ScDocument*>(pDocument),
515 eConvUI) & SCA_VALID) == SCA_VALID) &&
516 ((rRange.aEnd.Parse( aUIString.copy(nIndex+1), const_cast<ScDocument*>(pDocument),
517 eConvUI) & SCA_VALID) == SCA_VALID);
522 return bResult;
525 bool ScRangeStringConverter::GetRangeListFromString(
526 ScRangeList& rRangeList,
527 const OUString& rRangeListStr,
528 const ScDocument* pDocument,
529 FormulaGrammar::AddressConvention eConv,
530 sal_Unicode cSeparator,
531 sal_Unicode cQuote )
533 bool bRet = true;
534 OSL_ENSURE( !rRangeListStr.isEmpty(), "ScXMLConverter::GetRangeListFromString - empty string!" );
535 sal_Int32 nOffset = 0;
536 while( nOffset >= 0 )
538 ScRange* pRange = new ScRange;
539 if (
540 GetRangeFromString( *pRange, rRangeListStr, pDocument, eConv, nOffset, cSeparator, cQuote ) &&
541 (nOffset >= 0)
544 rRangeList.push_back( pRange );
545 pRange = NULL;
547 else if (nOffset > -1)
548 bRet = false;
549 //if ownership transferred to rRangeList pRange was NULLed, otherwwise
550 //delete it
551 delete pRange;
553 return bRet;
556 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 cSeparator,
563 sal_Unicode cQuote )
565 ScRange aScRange;
566 bool bResult(false);
567 if( GetRangeFromString( aScRange, rRangeStr, pDocument, eConv, nOffset, cSeparator, cQuote ) && (nOffset >= 0) )
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 = true;
576 return bResult;
579 bool ScRangeStringConverter::GetAddressFromString(
580 table::CellAddress& rAddress,
581 const OUString& rAddressStr,
582 const ScDocument* pDocument,
583 FormulaGrammar::AddressConvention eConv,
584 sal_Int32& nOffset,
585 sal_Unicode cSeparator,
586 sal_Unicode cQuote )
588 ScAddress aScAddress;
589 bool bResult(false);
590 if( GetAddressFromString( aScAddress, rAddressStr, pDocument, eConv, nOffset, cSeparator, cQuote ) && (nOffset >= 0) )
592 ScUnoConversion::FillApiAddress( rAddress, aScAddress );
593 bResult = true;
595 return bResult;
598 bool ScRangeStringConverter::GetRangeFromString(
599 table::CellRangeAddress& rRange,
600 const OUString& rRangeStr,
601 const ScDocument* pDocument,
602 FormulaGrammar::AddressConvention eConv,
603 sal_Int32& nOffset,
604 sal_Unicode cSeparator,
605 sal_Unicode cQuote )
607 ScRange aScRange;
608 bool bResult(false);
609 if( GetRangeFromString( aScRange, rRangeStr, pDocument, eConv, nOffset, cSeparator, cQuote ) && (nOffset >= 0) )
611 ScUnoConversion::FillApiRange( rRange, aScRange );
612 bResult = true;
614 return bResult;
617 void ScRangeStringConverter::GetStringFromAddress(
618 OUString& rString,
619 const ScAddress& rAddress,
620 const ScDocument* pDocument,
621 FormulaGrammar::AddressConvention eConv,
622 sal_Unicode cSeparator,
623 bool bAppendStr,
624 sal_uInt16 nFormatFlags )
626 if (pDocument && pDocument->HasTable(rAddress.Tab()))
628 OUString sAddress(rAddress.Format(nFormatFlags, pDocument, eConv));
629 AssignString( rString, sAddress, bAppendStr, cSeparator );
633 void ScRangeStringConverter::GetStringFromRange(
634 OUString& rString,
635 const ScRange& rRange,
636 const ScDocument* pDocument,
637 FormulaGrammar::AddressConvention eConv,
638 sal_Unicode cSeparator,
639 bool bAppendStr,
640 sal_uInt16 nFormatFlags )
642 if (pDocument && pDocument->HasTable(rRange.aStart.Tab()))
644 ScAddress aStartAddress( rRange.aStart );
645 ScAddress aEndAddress( rRange.aEnd );
646 OUString sStartAddress(aStartAddress.Format(nFormatFlags, pDocument, eConv));
647 OUString sEndAddress(aEndAddress.Format(nFormatFlags, pDocument, eConv));
648 OUString sOUStartAddress( sStartAddress );
649 sOUStartAddress += OUString(':');
650 sOUStartAddress += OUString( sEndAddress );
651 AssignString( rString, sOUStartAddress, bAppendStr, cSeparator );
655 void ScRangeStringConverter::GetStringFromRangeList(
656 OUString& rString,
657 const ScRangeList* pRangeList,
658 const ScDocument* pDocument,
659 FormulaGrammar::AddressConvention eConv,
660 sal_Unicode cSeparator,
661 sal_uInt16 nFormatFlags )
663 OUString sRangeListStr;
664 if( pRangeList )
666 for( size_t nIndex = 0, nCount = pRangeList->size(); nIndex < nCount; nIndex++ )
668 const ScRange* pRange = (*pRangeList)[nIndex];
669 if( pRange )
670 GetStringFromRange( sRangeListStr, *pRange, pDocument, eConv, cSeparator, true, nFormatFlags );
673 rString = sRangeListStr;
676 void ScRangeStringConverter::GetStringFromArea(
677 OUString& rString,
678 const ScArea& rArea,
679 const ScDocument* pDocument,
680 FormulaGrammar::AddressConvention eConv,
681 sal_Unicode cSeparator,
682 bool bAppendStr,
683 sal_uInt16 nFormatFlags )
685 ScRange aRange( rArea.nColStart, rArea.nRowStart, rArea.nTab, rArea.nColEnd, rArea.nRowEnd, rArea.nTab );
686 GetStringFromRange( rString, aRange, pDocument, eConv, cSeparator, bAppendStr, nFormatFlags );
689 void ScRangeStringConverter::GetStringFromAddress(
690 OUString& rString,
691 const table::CellAddress& rAddress,
692 const ScDocument* pDocument,
693 FormulaGrammar::AddressConvention eConv,
694 sal_Unicode cSeparator,
695 bool bAppendStr,
696 sal_uInt16 nFormatFlags )
698 ScAddress aScAddress( static_cast<SCCOL>(rAddress.Column), static_cast<SCROW>(rAddress.Row), rAddress.Sheet );
699 GetStringFromAddress( rString, aScAddress, pDocument, eConv, cSeparator, bAppendStr, nFormatFlags );
702 void ScRangeStringConverter::GetStringFromRange(
703 OUString& rString,
704 const table::CellRangeAddress& rRange,
705 const ScDocument* pDocument,
706 FormulaGrammar::AddressConvention eConv,
707 sal_Unicode cSeparator,
708 bool bAppendStr,
709 sal_uInt16 nFormatFlags )
711 ScRange aScRange( static_cast<SCCOL>(rRange.StartColumn), static_cast<SCROW>(rRange.StartRow), rRange.Sheet,
712 static_cast<SCCOL>(rRange.EndColumn), static_cast<SCROW>(rRange.EndRow), rRange.Sheet );
713 GetStringFromRange( rString, aScRange, pDocument, eConv, cSeparator, bAppendStr, nFormatFlags );
716 void ScRangeStringConverter::GetStringFromRangeList(
717 OUString& rString,
718 const uno::Sequence< table::CellRangeAddress >& rRangeSeq,
719 const ScDocument* pDocument,
720 FormulaGrammar::AddressConvention eConv,
721 sal_Unicode cSeparator,
722 sal_uInt16 nFormatFlags )
724 OUString sRangeListStr;
725 sal_Int32 nCount = rRangeSeq.getLength();
726 for( sal_Int32 nIndex = 0; nIndex < nCount; nIndex++ )
728 const table::CellRangeAddress& rRange = rRangeSeq[ nIndex ];
729 GetStringFromRange( sRangeListStr, rRange, pDocument, eConv, cSeparator, true, nFormatFlags );
731 rString = sRangeListStr;
734 static void lcl_appendCellAddress(
735 OUStringBuffer& rBuf, ScDocument* pDoc, const ScAddress& rCell,
736 const ScAddress::ExternalInfo& rExtInfo)
738 if (rExtInfo.mbExternal)
740 ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
741 const OUString* pFilePath = pRefMgr->getExternalFileName(rExtInfo.mnFileId, true);
742 if (!pFilePath)
743 return;
745 sal_Unicode cQuote = '\'';
746 rBuf.append(cQuote);
747 rBuf.append(*pFilePath);
748 rBuf.append(cQuote);
749 rBuf.append('#');
750 rBuf.append('$');
751 ScRangeStringConverter::AppendTableName(rBuf, rExtInfo.maTabName);
752 rBuf.append('.');
754 OUString aAddr(rCell.Format(SCA_ABS, NULL, pDoc->GetAddressConvention()));
755 rBuf.append(aAddr);
757 else
759 OUString aAddr(rCell.Format(SCA_ABS_3D, pDoc, pDoc->GetAddressConvention()));
760 rBuf.append(aAddr);
764 static void lcl_appendCellRangeAddress(
765 OUStringBuffer& rBuf, ScDocument* pDoc, const ScAddress& rCell1, const ScAddress& rCell2,
766 const ScAddress::ExternalInfo& rExtInfo1, const ScAddress::ExternalInfo& rExtInfo2)
768 if (rExtInfo1.mbExternal)
770 OSL_ENSURE(rExtInfo2.mbExternal, "2nd address is not external!?");
771 OSL_ENSURE(rExtInfo1.mnFileId == rExtInfo2.mnFileId, "File IDs do not match between 1st and 2nd addresses.");
773 ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
774 const OUString* pFilePath = pRefMgr->getExternalFileName(rExtInfo1.mnFileId, true);
775 if (!pFilePath)
776 return;
778 sal_Unicode cQuote = '\'';
779 rBuf.append(cQuote);
780 rBuf.append(*pFilePath);
781 rBuf.append(cQuote);
782 rBuf.append('#');
783 rBuf.append('$');
784 ScRangeStringConverter::AppendTableName(rBuf, rExtInfo1.maTabName);
785 rBuf.append('.');
787 OUString aAddr(rCell1.Format(SCA_ABS, NULL, pDoc->GetAddressConvention()));
788 rBuf.append(aAddr);
790 rBuf.appendAscii(":");
792 if (rExtInfo1.maTabName != rExtInfo2.maTabName)
794 rBuf.append('$');
795 ScRangeStringConverter::AppendTableName(rBuf, rExtInfo2.maTabName);
796 rBuf.append('.');
799 aAddr = rCell2.Format(SCA_ABS, NULL, pDoc->GetAddressConvention());
800 rBuf.append(aAddr);
802 else
804 ScRange aRange;
805 aRange.aStart = rCell1;
806 aRange.aEnd = rCell2;
807 OUString aAddr(aRange.Format(SCR_ABS_3D, pDoc, pDoc->GetAddressConvention()));
808 rBuf.append(aAddr);
812 void ScRangeStringConverter::GetStringFromXMLRangeString( OUString& rString, const OUString& rXMLRange, ScDocument* pDoc )
814 FormulaGrammar::AddressConvention eConv = pDoc->GetAddressConvention();
815 const sal_Unicode cSep = ' ';
816 const sal_Unicode cSepNew = ScCompiler::GetNativeSymbolChar(ocSep);
817 const sal_Unicode cQuote = '\'';
819 OUStringBuffer aRetStr;
820 sal_Int32 nOffset = 0;
821 bool bFirst = true;
823 while (nOffset >= 0)
825 OUString aToken;
826 GetTokenByOffset(aToken, rXMLRange, nOffset, cSep, cQuote);
827 if (nOffset < 0)
828 break;
830 sal_Int32 nSepPos = IndexOf(aToken, ':', 0, cQuote);
831 if (nSepPos >= 0)
833 // Cell range
834 OUString aBeginCell = aToken.copy(0, nSepPos);
835 OUString aEndCell = aToken.copy(nSepPos+1);
837 if (aBeginCell.isEmpty() || aEndCell.isEmpty())
838 // both cell addresses must exist for this to work.
839 continue;
841 sal_Int32 nEndCellDotPos = aEndCell.indexOf('.');
842 if (nEndCellDotPos <= 0)
844 // initialize buffer with table name...
845 sal_Int32 nDotPos = IndexOf(aBeginCell, '.', 0, cQuote);
846 OUStringBuffer aBuf = aBeginCell.copy(0, nDotPos);
848 if (nEndCellDotPos == 0)
850 // workaround for old syntax (probably pre-chart2 age?)
851 // e.g. Sheet1.A1:.B2
852 aBuf.append(aEndCell);
854 else if (nEndCellDotPos < 0)
856 // sheet name in the end cell is omitted (e.g. Sheet2.A1:B2).
857 aBuf.append('.');
858 aBuf.append(aEndCell);
860 aEndCell = aBuf.makeStringAndClear();
863 ScAddress::ExternalInfo aExtInfo1, aExtInfo2;
864 ScAddress aCell1, aCell2;
865 sal_uInt16 nRet = aCell1.Parse(aBeginCell, pDoc, FormulaGrammar::CONV_OOO, &aExtInfo1);
866 if ((nRet & SCA_VALID) != SCA_VALID)
868 // first cell is invalid.
869 if (eConv == FormulaGrammar::CONV_OOO)
870 continue;
872 nRet = aCell1.Parse(aBeginCell, pDoc, eConv, &aExtInfo1);
873 if ((nRet & SCA_VALID) != SCA_VALID)
874 // first cell is really invalid.
875 continue;
878 nRet = aCell2.Parse(aEndCell, pDoc, FormulaGrammar::CONV_OOO, &aExtInfo2);
879 if ((nRet & SCA_VALID) != SCA_VALID)
881 // second cell is invalid.
882 if (eConv == FormulaGrammar::CONV_OOO)
883 continue;
885 nRet = aCell2.Parse(aEndCell, pDoc, eConv, &aExtInfo2);
886 if ((nRet & SCA_VALID) != SCA_VALID)
887 // second cell is really invalid.
888 continue;
891 if (aExtInfo1.mnFileId != aExtInfo2.mnFileId || aExtInfo1.mbExternal != aExtInfo2.mbExternal)
892 // external info inconsistency.
893 continue;
895 // All looks good!
897 if (bFirst)
898 bFirst = false;
899 else
900 aRetStr.append(cSepNew);
902 lcl_appendCellRangeAddress(aRetStr, pDoc, aCell1, aCell2, aExtInfo1, aExtInfo2);
904 else
906 // Chart always saves ranges using CONV_OOO convention.
907 ScAddress::ExternalInfo aExtInfo;
908 ScAddress aCell;
909 sal_uInt16 nRet = aCell.Parse(aToken, pDoc, ::formula::FormulaGrammar::CONV_OOO, &aExtInfo);
910 if ((nRet & SCA_VALID) != SCA_VALID)
912 nRet = aCell.Parse(aToken, pDoc, eConv, &aExtInfo);
913 if ((nRet & SCA_VALID) != SCA_VALID)
914 continue;
917 // Looks good!
919 if (bFirst)
920 bFirst = false;
921 else
922 aRetStr.append(cSepNew);
924 lcl_appendCellAddress(aRetStr, pDoc, aCell, aExtInfo);
928 rString = aRetStr.makeStringAndClear();
931 ScRangeData* ScRangeStringConverter::GetRangeDataFromString(const OUString& rString, const SCTAB nTab, const ScDocument* pDoc)
933 ScRangeName* pLocalRangeName = pDoc->GetRangeName(nTab);
934 ScRangeData* pData = NULL;
935 OUString aUpperName = ScGlobal::pCharClass->uppercase(rString);
936 if(pLocalRangeName)
938 pData = pLocalRangeName->findByUpperName(aUpperName);
940 if (!pData)
942 ScRangeName* pGlobalRangeName = pDoc->GetRangeName();
943 if (pGlobalRangeName)
945 pData = pGlobalRangeName->findByUpperName(aUpperName);
948 return pData;
951 ScArea::ScArea( SCTAB tab,
952 SCCOL colStart, SCROW rowStart,
953 SCCOL colEnd, SCROW rowEnd ) :
954 nTab ( tab ),
955 nColStart( colStart ), nRowStart( rowStart ),
956 nColEnd ( colEnd ), nRowEnd ( rowEnd )
960 ScArea::ScArea( const ScArea& r ) :
961 nTab ( r.nTab ),
962 nColStart( r.nColStart ), nRowStart( r.nRowStart ),
963 nColEnd ( r.nColEnd ), nRowEnd ( r.nRowEnd )
967 ScArea& ScArea::operator=( const ScArea& r )
969 nTab = r.nTab;
970 nColStart = r.nColStart;
971 nRowStart = r.nRowStart;
972 nColEnd = r.nColEnd;
973 nRowEnd = r.nRowEnd;
974 return *this;
977 bool ScArea::operator==( const ScArea& r ) const
979 return ( (nTab == r.nTab)
980 && (nColStart == r.nColStart)
981 && (nRowStart == r.nRowStart)
982 && (nColEnd == r.nColEnd)
983 && (nRowEnd == r.nRowEnd) );
986 ScAreaNameIterator::ScAreaNameIterator( ScDocument* pDoc ) :
987 pRangeName(pDoc->GetRangeName()),
988 pDBCollection(pDoc->GetDBCollection()),
989 bFirstPass(true)
991 if (pRangeName)
993 maRNPos = pRangeName->begin();
994 maRNEnd = pRangeName->end();
998 bool ScAreaNameIterator::Next( OUString& rName, ScRange& rRange )
1000 for (;;)
1002 if ( bFirstPass ) // erst Bereichsnamen
1004 if ( pRangeName && maRNPos != maRNEnd )
1006 const ScRangeData& rData = *maRNPos->second;
1007 ++maRNPos;
1008 bool bValid = rData.IsValidReference(rRange);
1009 if (bValid)
1011 rName = rData.GetName();
1012 return true; // found
1015 else
1017 bFirstPass = false;
1018 if (pDBCollection)
1020 const ScDBCollection::NamedDBs& rDBs = pDBCollection->getNamedDBs();
1021 maDBPos = rDBs.begin();
1022 maDBEnd = rDBs.end();
1027 if ( !bFirstPass ) // dann DB-Bereiche
1029 if (pDBCollection && maDBPos != maDBEnd)
1031 const ScDBData& rData = *maDBPos;
1032 ++maDBPos;
1033 rData.GetArea(rRange);
1034 rName = rData.GetName();
1035 return true; // found
1037 else
1038 return false; // nothing left
1043 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */