1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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"
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
,
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
;
52 if ( nColonPos
== -1 && nPointPos
!= -1 )
55 aStrArea
+= rAreaStr
.copy( nPointPos
+1 ); // do not include '.' in copy
58 nSuccess
= ConvertDoubleRef( pDoc
, aStrArea
, nTab
, startPos
, endPos
, rDetails
);
61 rArea
= ScArea( startPos
.Tab(),
62 startPos
.Col(), startPos
.Row(),
63 endPos
.Col(), endPos
.Row() );
68 void ScRangeUtil::CutPosString( const OUString
& theAreaStr
,
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
85 bool ScRangeUtil::IsAbsTabArea( const OUString
& rAreaStr
,
88 sal_uInt16
* pAreaCount
,
89 bool /* bAcceptCellRef */,
90 ScAddress::Details
const & rDetails
)
92 OSL_ENSURE( pDoc
, "No document given!" );
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:
105 * as result a ScArea-Array is created,
106 * which is published via ppAreas and also has to be deleted this route.
110 OUString
aTempAreaStr(rAreaStr
);
111 OUString aStartPosStr
;
114 if ( -1 == aTempAreaStr
.indexOf(':') )
117 aTempAreaStr
+= rAreaStr
;
120 sal_Int32 nColonPos
= aTempAreaStr
.indexOf(':');
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 );
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
];
152 ScArea
theArea( 0, aStartPos
.Col(), aStartPos
.Row(),
153 aEndPos
.Col(), aEndPos
.Row() );
156 for ( i
=0; i
<nTabCount
; i
++ )
158 theAreas
[i
] = new ScArea( theArea
);
159 theAreas
[i
]->nTab
= nTab
;
162 *pppAreas
= theAreas
;
163 *pAreaCount
= nTabCount
;
172 bool ScRangeUtil::IsAbsArea( const OUString
& rAreaStr
,
175 OUString
* pCompleteStr
,
176 ScRefAddress
* pStartPos
,
177 ScRefAddress
* pEndPos
,
178 ScAddress::Details
const & rDetails
)
180 ScRefAddress startPos
;
183 bool bIsAbsArea
= ConvertDoubleRef( pDoc
, rAreaStr
, nTab
, startPos
, endPos
, rDetails
);
187 startPos
.SetRelCol( false );
188 startPos
.SetRelRow( false );
189 startPos
.SetRelTab( false );
190 endPos
.SetRelCol( false );
191 endPos
.SetRelRow( false );
192 endPos
.SetRelTab( false );
196 *pCompleteStr
= startPos
.GetRefString( pDoc
, MAXTAB
+1, rDetails
);
197 *pCompleteStr
+= ":";
198 *pCompleteStr
+= endPos
.GetRefString( pDoc
, nTab
, rDetails
);
201 if ( pStartPos
&& pEndPos
)
203 *pStartPos
= startPos
;
211 bool ScRangeUtil::IsAbsPos( const OUString
& rPosStr
,
214 OUString
* pCompleteStr
,
215 ScRefAddress
* pPosTripel
,
216 ScAddress::Details
const & rDetails
)
220 bool bIsAbsPos
= ConvertSingleRef( pDoc
, rPosStr
, nTab
, thePos
, rDetails
);
221 thePos
.SetRelCol( false );
222 thePos
.SetRelRow( false );
223 thePos
.SetRelTab( false );
228 *pPosTripel
= thePos
;
230 *pCompleteStr
= thePos
.GetRefString( pDoc
, MAXTAB
+1, rDetails
);
236 bool ScRangeUtil::MakeRangeFromName (
237 const OUString
& rName
,
241 RutlNameScope eScope
,
242 ScAddress::Details
const & rDetails
)
244 bool bResult
= false;
245 ScRangeUtil aRangeUtil
;
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
);
269 //then check for local range names
270 ScRangeName
* pRangeNames
= pDoc
->GetRangeName( nTable
);
271 ScRangeData
* pData
= NULL
;
273 pData
= pRangeNames
->findByUpperName(ScGlobal::pCharClass
->uppercase(aName
));
275 pData
= pDoc
->GetRangeName()->findByUpperName(ScGlobal::pCharClass
->uppercase(aName
));
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();
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();
309 else if( eScope
==RUTL_DBASE
)
311 ScDBCollection::NamedDBs
& rDbNames
= pDoc
->GetDBCollection()->getNamedDBs();
312 ScDBData
* pData
= rDbNames
.findByUpperName(ScGlobal::pCharClass
->uppercase(rName
));
315 pData
->GetArea(nTab
, nColStart
, nRowStart
, nColEnd
, nRowEnd
);
321 OSL_FAIL( "ScRangeUtil::MakeRangeFromName" );
326 rRange
= ScRange( nColStart
, nRowStart
, nTab
, nColEnd
, nRowEnd
, nTab
);
332 void ScRangeStringConverter::AssignString(
334 const OUString
& rNewStr
,
336 sal_Unicode cSeparator
)
340 if( !rNewStr
.isEmpty() )
342 if( !rString
.isEmpty() )
343 rString
+= OUString(cSeparator
);
351 sal_Int32
ScRangeStringConverter::IndexOf(
352 const OUString
& rString
,
353 sal_Unicode cSearchChar
,
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
));
370 return (nIndex
< nLength
) ? nIndex
: -1;
373 sal_Int32
ScRangeStringConverter::IndexOfDifferent(
374 const OUString
& rString
,
375 sal_Unicode cSearchChar
,
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
);
388 return (nIndex
< nLength
) ? nIndex
: -1;
391 void ScRangeStringConverter::GetTokenByOffset(
393 const OUString
& rString
,
395 sal_Unicode cSeparator
,
398 sal_Int32 nLength
= rString
.getLength();
399 if( nOffset
== -1 || nOffset
>= nLength
)
406 sal_Int32 nTokenEnd
= IndexOf( rString
, cSeparator
, nOffset
, cQuote
);
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
)
427 sal_Int32 nCount
= 0;
428 sal_Int32 nOffset
= 0;
429 while( nOffset
>= 0 )
431 GetTokenByOffset( sToken
, rString
, nOffset
, cQuote
, cSeparator
);
438 bool ScRangeStringConverter::GetAddressFromString(
440 const OUString
& rAddressStr
,
441 const ScDocument
* pDocument
,
442 FormulaGrammar::AddressConvention eConv
,
444 sal_Unicode cSeparator
,
448 GetTokenByOffset( sToken
, rAddressStr
, nOffset
, cSeparator
, cQuote
);
451 if ((rAddress
.Parse( sToken
, const_cast<ScDocument
*>(pDocument
), eConv
) & SCA_VALID
) == SCA_VALID
)
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
);
460 bool ScRangeStringConverter::GetRangeFromString(
462 const OUString
& rRangeStr
,
463 const ScDocument
* pDocument
,
464 FormulaGrammar::AddressConvention eConv
,
466 sal_Unicode cSeparator
,
471 GetTokenByOffset( sToken
, rRangeStr
, nOffset
, cSeparator
, cQuote
);
474 sal_Int32 nIndex
= IndexOf( sToken
, ':', 0, cQuote
);
475 OUString
aUIString(sToken
);
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
;
490 if ( aUIString
[0] == '.' )
492 aUIString
= aUIString
.copy( 1 );
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.
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
);
525 bool ScRangeStringConverter::GetRangeListFromString(
526 ScRangeList
& rRangeList
,
527 const OUString
& rRangeListStr
,
528 const ScDocument
* pDocument
,
529 FormulaGrammar::AddressConvention eConv
,
530 sal_Unicode cSeparator
,
534 OSL_ENSURE( !rRangeListStr
.isEmpty(), "ScXMLConverter::GetRangeListFromString - empty string!" );
535 sal_Int32 nOffset
= 0;
536 while( nOffset
>= 0 )
538 ScRange
* pRange
= new ScRange
;
540 GetRangeFromString( *pRange
, rRangeListStr
, pDocument
, eConv
, nOffset
, cSeparator
, cQuote
) &&
544 rRangeList
.push_back( pRange
);
547 else if (nOffset
> -1)
549 //if ownership transferred to rRangeList pRange was NULLed, otherwwise
556 bool ScRangeStringConverter::GetAreaFromString(
558 const OUString
& rRangeStr
,
559 const ScDocument
* pDocument
,
560 FormulaGrammar::AddressConvention eConv
,
562 sal_Unicode cSeparator
,
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();
579 bool ScRangeStringConverter::GetAddressFromString(
580 table::CellAddress
& rAddress
,
581 const OUString
& rAddressStr
,
582 const ScDocument
* pDocument
,
583 FormulaGrammar::AddressConvention eConv
,
585 sal_Unicode cSeparator
,
588 ScAddress aScAddress
;
590 if( GetAddressFromString( aScAddress
, rAddressStr
, pDocument
, eConv
, nOffset
, cSeparator
, cQuote
) && (nOffset
>= 0) )
592 ScUnoConversion::FillApiAddress( rAddress
, aScAddress
);
598 bool ScRangeStringConverter::GetRangeFromString(
599 table::CellRangeAddress
& rRange
,
600 const OUString
& rRangeStr
,
601 const ScDocument
* pDocument
,
602 FormulaGrammar::AddressConvention eConv
,
604 sal_Unicode cSeparator
,
609 if( GetRangeFromString( aScRange
, rRangeStr
, pDocument
, eConv
, nOffset
, cSeparator
, cQuote
) && (nOffset
>= 0) )
611 ScUnoConversion::FillApiRange( rRange
, aScRange
);
617 void ScRangeStringConverter::GetStringFromAddress(
619 const ScAddress
& rAddress
,
620 const ScDocument
* pDocument
,
621 FormulaGrammar::AddressConvention eConv
,
622 sal_Unicode cSeparator
,
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(
635 const ScRange
& rRange
,
636 const ScDocument
* pDocument
,
637 FormulaGrammar::AddressConvention eConv
,
638 sal_Unicode cSeparator
,
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(
657 const ScRangeList
* pRangeList
,
658 const ScDocument
* pDocument
,
659 FormulaGrammar::AddressConvention eConv
,
660 sal_Unicode cSeparator
,
661 sal_uInt16 nFormatFlags
)
663 OUString sRangeListStr
;
666 for( size_t nIndex
= 0, nCount
= pRangeList
->size(); nIndex
< nCount
; nIndex
++ )
668 const ScRange
* pRange
= (*pRangeList
)[nIndex
];
670 GetStringFromRange( sRangeListStr
, *pRange
, pDocument
, eConv
, cSeparator
, true, nFormatFlags
);
673 rString
= sRangeListStr
;
676 void ScRangeStringConverter::GetStringFromArea(
679 const ScDocument
* pDocument
,
680 FormulaGrammar::AddressConvention eConv
,
681 sal_Unicode cSeparator
,
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(
691 const table::CellAddress
& rAddress
,
692 const ScDocument
* pDocument
,
693 FormulaGrammar::AddressConvention eConv
,
694 sal_Unicode cSeparator
,
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(
704 const table::CellRangeAddress
& rRange
,
705 const ScDocument
* pDocument
,
706 FormulaGrammar::AddressConvention eConv
,
707 sal_Unicode cSeparator
,
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(
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);
745 sal_Unicode cQuote
= '\'';
747 rBuf
.append(*pFilePath
);
751 ScRangeStringConverter::AppendTableName(rBuf
, rExtInfo
.maTabName
);
754 OUString
aAddr(rCell
.Format(SCA_ABS
, NULL
, pDoc
->GetAddressConvention()));
759 OUString
aAddr(rCell
.Format(SCA_ABS_3D
, pDoc
, pDoc
->GetAddressConvention()));
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);
778 sal_Unicode cQuote
= '\'';
780 rBuf
.append(*pFilePath
);
784 ScRangeStringConverter::AppendTableName(rBuf
, rExtInfo1
.maTabName
);
787 OUString
aAddr(rCell1
.Format(SCA_ABS
, NULL
, pDoc
->GetAddressConvention()));
790 rBuf
.appendAscii(":");
792 if (rExtInfo1
.maTabName
!= rExtInfo2
.maTabName
)
795 ScRangeStringConverter::AppendTableName(rBuf
, rExtInfo2
.maTabName
);
799 aAddr
= rCell2
.Format(SCA_ABS
, NULL
, pDoc
->GetAddressConvention());
805 aRange
.aStart
= rCell1
;
806 aRange
.aEnd
= rCell2
;
807 OUString
aAddr(aRange
.Format(SCR_ABS_3D
, pDoc
, pDoc
->GetAddressConvention()));
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;
826 GetTokenByOffset(aToken
, rXMLRange
, nOffset
, cSep
, cQuote
);
830 sal_Int32 nSepPos
= IndexOf(aToken
, ':', 0, cQuote
);
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.
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).
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
)
872 nRet
= aCell1
.Parse(aBeginCell
, pDoc
, eConv
, &aExtInfo1
);
873 if ((nRet
& SCA_VALID
) != SCA_VALID
)
874 // first cell is really invalid.
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
)
885 nRet
= aCell2
.Parse(aEndCell
, pDoc
, eConv
, &aExtInfo2
);
886 if ((nRet
& SCA_VALID
) != SCA_VALID
)
887 // second cell is really invalid.
891 if (aExtInfo1
.mnFileId
!= aExtInfo2
.mnFileId
|| aExtInfo1
.mbExternal
!= aExtInfo2
.mbExternal
)
892 // external info inconsistency.
900 aRetStr
.append(cSepNew
);
902 lcl_appendCellRangeAddress(aRetStr
, pDoc
, aCell1
, aCell2
, aExtInfo1
, aExtInfo2
);
906 // Chart always saves ranges using CONV_OOO convention.
907 ScAddress::ExternalInfo aExtInfo
;
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
)
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
);
938 pData
= pLocalRangeName
->findByUpperName(aUpperName
);
942 ScRangeName
* pGlobalRangeName
= pDoc
->GetRangeName();
943 if (pGlobalRangeName
)
945 pData
= pGlobalRangeName
->findByUpperName(aUpperName
);
951 ScArea::ScArea( SCTAB tab
,
952 SCCOL colStart
, SCROW rowStart
,
953 SCCOL colEnd
, SCROW rowEnd
) :
955 nColStart( colStart
), nRowStart( rowStart
),
956 nColEnd ( colEnd
), nRowEnd ( rowEnd
)
960 ScArea::ScArea( const ScArea
& r
) :
962 nColStart( r
.nColStart
), nRowStart( r
.nRowStart
),
963 nColEnd ( r
.nColEnd
), nRowEnd ( r
.nRowEnd
)
967 ScArea
& ScArea::operator=( const ScArea
& r
)
970 nColStart
= r
.nColStart
;
971 nRowStart
= r
.nRowStart
;
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()),
993 maRNPos
= pRangeName
->begin();
994 maRNEnd
= pRangeName
->end();
998 bool ScAreaNameIterator::Next( OUString
& rName
, ScRange
& rRange
)
1002 if ( bFirstPass
) // erst Bereichsnamen
1004 if ( pRangeName
&& maRNPos
!= maRNEnd
)
1006 const ScRangeData
& rData
= *maRNPos
->second
;
1008 bool bValid
= rData
.IsValidReference(rRange
);
1011 rName
= rData
.GetName();
1012 return true; // found
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
;
1033 rData
.GetArea(rRange
);
1034 rName
= rData
.GetName();
1035 return true; // found
1038 return false; // nothing left
1043 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */