1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: rangeutl.cxx,v $
10 * $Revision: 1.12.30.4 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
36 // INCLUDE ---------------------------------------------------------------
38 #include <tools/debug.hxx>
40 #include "rangeutl.hxx"
41 #include "document.hxx"
43 #include "dbcolect.hxx"
44 #include "rangenam.hxx"
45 #include "scresid.hxx"
46 #include "globstr.hrc"
47 #include "convuno.hxx"
48 #include "externalrefmgr.hxx"
49 #include "compiler.hxx"
51 using ::rtl::OUString
;
52 using ::rtl::OUStringBuffer
;
53 using ::formula::FormulaGrammar
;
54 using namespace ::com::sun::star
;
56 //------------------------------------------------------------------------
58 BOOL
ScRangeUtil::MakeArea( const String
& rAreaStr
,
62 ScAddress::Details
const & rDetails
) const
64 // Eingabe in rAreaStr: "$Tabelle1.$A1:$D17"
66 // BROKEN BROKEN BROKEN
67 // but it is only used in the consolidate dialog. Ignore for now.
69 BOOL nSuccess
= FALSE
;
70 USHORT nPointPos
= rAreaStr
.Search('.');
71 USHORT nColonPos
= rAreaStr
.Search(':');
72 String
aStrArea( rAreaStr
);
73 ScRefAddress startPos
;
76 if ( nColonPos
== STRING_NOTFOUND
)
77 if ( nPointPos
!= STRING_NOTFOUND
)
80 aStrArea
+= rAreaStr
.Copy( nPointPos
+1 ); // '.' nicht mitkopieren
83 nSuccess
= ConvertDoubleRef( pDoc
, aStrArea
, nTab
, startPos
, endPos
, rDetails
);
86 rArea
= ScArea( startPos
.Tab(),
87 startPos
.Col(), startPos
.Row(),
88 endPos
.Col(), endPos
.Row() );
93 //------------------------------------------------------------------------
95 void ScRangeUtil::CutPosString( const String
& theAreaStr
,
96 String
& thePosStr
) const
99 // BROKEN BROKEN BROKEN
100 // but it is only used in the consolidate dialog. Ignore for now.
102 USHORT nColonPos
= theAreaStr
.Search(':');
104 if ( nColonPos
!= STRING_NOTFOUND
)
105 aPosStr
= theAreaStr
.Copy( 0, nColonPos
); // ':' nicht mitkopieren
107 aPosStr
= theAreaStr
;
112 //------------------------------------------------------------------------
114 BOOL
ScRangeUtil::IsAbsTabArea( const String
& rAreaStr
,
118 BOOL
/* bAcceptCellRef */,
119 ScAddress::Details
const & rDetails
) const
121 DBG_ASSERT( pDoc
, "Kein Dokument uebergeben!" );
125 // BROKEN BROKEN BROKEN
126 // but it is only used in the consolidate dialog. Ignore for now.
129 * Erwartet wird ein String der Form
130 * "$Tabelle1.$A$1:$Tabelle3.$D$17"
131 * Wenn bAcceptCellRef == TRUE ist, wird auch ein String der Form
135 * als Ergebnis wird ein ScArea-Array angelegt,
136 * welches ueber ppAreas bekannt gegeben wird und auch
137 * wieder geloescht werden muss!
141 String
aTempAreaStr(rAreaStr
);
145 if ( STRING_NOTFOUND
== aTempAreaStr
.Search(':') )
147 aTempAreaStr
.Append(':');
148 aTempAreaStr
.Append(rAreaStr
);
151 USHORT nColonPos
= aTempAreaStr
.Search(':');
153 if ( STRING_NOTFOUND
!= nColonPos
154 && STRING_NOTFOUND
!= aTempAreaStr
.Search('.') )
156 ScRefAddress aStartPos
;
157 ScRefAddress aEndPos
;
159 aStartPosStr
= aTempAreaStr
.Copy( 0, nColonPos
);
160 aEndPosStr
= aTempAreaStr
.Copy( nColonPos
+1, STRING_LEN
);
162 if ( ConvertSingleRef( pDoc
, aStartPosStr
, 0, aStartPos
, rDetails
) )
164 if ( ConvertSingleRef( pDoc
, aEndPosStr
, aStartPos
.Tab(), aEndPos
, rDetails
) )
166 aStartPos
.SetRelCol( FALSE
);
167 aStartPos
.SetRelRow( FALSE
);
168 aStartPos
.SetRelTab( FALSE
);
169 aEndPos
.SetRelCol( FALSE
);
170 aEndPos
.SetRelRow( FALSE
);
171 aEndPos
.SetRelTab( FALSE
);
175 if ( pppAreas
&& pAreaCount
) // Array zurueckgegeben?
177 SCTAB nStartTab
= aStartPos
.Tab();
178 SCTAB nEndTab
= aEndPos
.Tab();
179 USHORT nTabCount
= static_cast<USHORT
>(nEndTab
-nStartTab
+1);
180 ScArea
** theAreas
= new ScArea
*[nTabCount
];
183 ScArea
theArea( 0, aStartPos
.Col(), aStartPos
.Row(),
184 aEndPos
.Col(), aEndPos
.Row() );
187 for ( i
=0; i
<nTabCount
; i
++ )
189 theAreas
[i
] = new ScArea( theArea
);
190 theAreas
[i
]->nTab
= nTab
;
193 *pppAreas
= theAreas
;
194 *pAreaCount
= nTabCount
;
203 //------------------------------------------------------------------------
205 BOOL
ScRangeUtil::IsAbsArea( const String
& rAreaStr
,
208 String
* pCompleteStr
,
209 ScRefAddress
* pStartPos
,
210 ScRefAddress
* pEndPos
,
211 ScAddress::Details
const & rDetails
) const
213 BOOL bIsAbsArea
= FALSE
;
214 ScRefAddress startPos
;
217 bIsAbsArea
= ConvertDoubleRef( pDoc
, rAreaStr
, nTab
, startPos
, endPos
, rDetails
);
221 startPos
.SetRelCol( FALSE
);
222 startPos
.SetRelRow( FALSE
);
223 startPos
.SetRelTab( FALSE
);
224 endPos
.SetRelCol( FALSE
);
225 endPos
.SetRelRow( FALSE
);
226 endPos
.SetRelTab( FALSE
);
230 *pCompleteStr
= startPos
.GetRefString( pDoc
, MAXTAB
+1, rDetails
);
231 *pCompleteStr
+= ':';
232 *pCompleteStr
+= endPos
.GetRefString( pDoc
, nTab
, rDetails
);
235 if ( pStartPos
&& pEndPos
)
237 *pStartPos
= startPos
;
245 //------------------------------------------------------------------------
247 BOOL
ScRangeUtil::IsAbsPos( const String
& rPosStr
,
250 String
* pCompleteStr
,
251 ScRefAddress
* pPosTripel
,
252 ScAddress::Details
const & rDetails
) const
254 BOOL bIsAbsPos
= FALSE
;
257 bIsAbsPos
= ConvertSingleRef( pDoc
, rPosStr
, nTab
, thePos
, rDetails
);
258 thePos
.SetRelCol( FALSE
);
259 thePos
.SetRelRow( FALSE
);
260 thePos
.SetRelTab( FALSE
);
265 *pPosTripel
= thePos
;
267 *pCompleteStr
= thePos
.GetRefString( pDoc
, MAXTAB
+1, rDetails
);
273 //------------------------------------------------------------------------
275 BOOL
ScRangeUtil::MakeRangeFromName (
280 RutlNameScope eScope
,
281 ScAddress::Details
const & rDetails
) const
284 ScRangeUtil aRangeUtil
;
291 if( eScope
==RUTL_NAMES
)
293 ScRangeName
& rRangeNames
= *(pDoc
->GetRangeName());
296 if ( rRangeNames
.SearchName( rName
, nAt
) )
298 ScRangeData
* pData
= rRangeNames
[nAt
];
300 ScRefAddress aStartPos
;
301 ScRefAddress aEndPos
;
303 pData
->GetSymbol( aStrArea
);
305 if ( IsAbsArea( aStrArea
, pDoc
, nCurTab
,
306 NULL
, &aStartPos
, &aEndPos
, rDetails
) )
308 nTab
= aStartPos
.Tab();
309 nColStart
= aStartPos
.Col();
310 nRowStart
= aStartPos
.Row();
311 nColEnd
= aEndPos
.Col();
312 nRowEnd
= aEndPos
.Row();
317 CutPosString( aStrArea
, aStrArea
);
319 if ( IsAbsPos( aStrArea
, pDoc
, nCurTab
,
320 NULL
, &aStartPos
, rDetails
) )
322 nTab
= aStartPos
.Tab();
323 nColStart
= nColEnd
= aStartPos
.Col();
324 nRowStart
= nRowEnd
= aStartPos
.Row();
330 else if( eScope
==RUTL_DBASE
)
332 ScDBCollection
& rDbNames
= *(pDoc
->GetDBCollection());
335 if ( rDbNames
.SearchName( rName
, nAt
) )
337 ScDBData
* pData
= rDbNames
[nAt
];
339 pData
->GetArea( nTab
, nColStart
, nRowStart
,
346 DBG_ERROR( "ScRangeUtil::MakeRangeFromName" );
351 rRange
= ScRange( nColStart
, nRowStart
, nTab
, nColEnd
, nRowEnd
, nTab
);
357 //========================================================================
359 void ScRangeStringConverter::AssignString(
361 const OUString
& rNewStr
,
363 sal_Unicode cSeperator
)
367 if( rNewStr
.getLength() )
369 if( rString
.getLength() )
370 rString
+= rtl::OUString(cSeperator
);
378 sal_Int32
ScRangeStringConverter::IndexOf(
379 const OUString
& rString
,
380 sal_Unicode cSearchChar
,
384 sal_Int32 nLength
= rString
.getLength();
385 sal_Int32 nIndex
= nOffset
;
386 sal_Bool bQuoted
= sal_False
;
387 sal_Bool bExitLoop
= sal_False
;
389 while( !bExitLoop
&& (nIndex
< nLength
) )
391 sal_Unicode cCode
= rString
[ nIndex
];
392 bExitLoop
= (cCode
== cSearchChar
) && !bQuoted
;
393 bQuoted
= (bQuoted
!= (cCode
== cQuote
));
397 return (nIndex
< nLength
) ? nIndex
: -1;
400 sal_Int32
ScRangeStringConverter::IndexOfDifferent(
401 const OUString
& rString
,
402 sal_Unicode cSearchChar
,
405 sal_Int32 nLength
= rString
.getLength();
406 sal_Int32 nIndex
= nOffset
;
407 sal_Bool bExitLoop
= sal_False
;
409 while( !bExitLoop
&& (nIndex
< nLength
) )
411 bExitLoop
= (rString
[ nIndex
] != cSearchChar
);
415 return (nIndex
< nLength
) ? nIndex
: -1;
418 void ScRangeStringConverter::GetTokenByOffset(
420 const OUString
& rString
,
422 sal_Unicode cSeperator
,
425 sal_Int32 nLength
= rString
.getLength();
426 if( nOffset
>= nLength
)
433 sal_Int32 nTokenEnd
= IndexOf( rString
, cSeperator
, nOffset
, cQuote
);
436 rToken
= rString
.copy( nOffset
, nTokenEnd
- nOffset
);
438 sal_Int32 nNextBegin
= IndexOfDifferent( rString
, cSeperator
, nTokenEnd
);
439 nOffset
= (nNextBegin
< 0) ? nLength
: nNextBegin
;
443 void ScRangeStringConverter::AppendTableName(OUStringBuffer
& rBuf
, const OUString
& rTabName
, sal_Unicode
/* cQuote */)
445 // quote character is always "'"
446 String
aQuotedTab(rTabName
);
447 ScCompiler::CheckTabQuotes(aQuotedTab
, ::formula::FormulaGrammar::CONV_OOO
);
448 rBuf
.append(aQuotedTab
);
451 sal_Int32
ScRangeStringConverter::GetTokenCount( const OUString
& rString
, sal_Unicode cSeperator
, sal_Unicode cQuote
)
454 sal_Int32 nCount
= 0;
455 sal_Int32 nOffset
= 0;
456 while( nOffset
>= 0 )
458 GetTokenByOffset( sToken
, rString
, nOffset
, cQuote
, cSeperator
);
465 //___________________________________________________________________
467 sal_Bool
ScRangeStringConverter::GetAddressFromString(
469 const OUString
& rAddressStr
,
470 const ScDocument
* pDocument
,
471 FormulaGrammar::AddressConvention eConv
,
473 sal_Unicode cSeperator
,
477 GetTokenByOffset( sToken
, rAddressStr
, nOffset
, cSeperator
, cQuote
);
480 if ((rAddress
.Parse( sToken
, const_cast<ScDocument
*>(pDocument
), eConv
) & SCA_VALID
) == SCA_VALID
)
482 #if CHART_ADDRESS_CONV_WORKAROUND
483 ::formula::FormulaGrammar::AddressConvention eConvUI
= pDocument
->GetAddressConvention();
484 if (eConv
!= eConvUI
)
485 return ((rAddress
.Parse(sToken
, const_cast<ScDocument
*>(pDocument
), eConvUI
) & SCA_VALID
) == SCA_VALID
);
491 sal_Bool
ScRangeStringConverter::GetRangeFromString(
493 const OUString
& rRangeStr
,
494 const ScDocument
* pDocument
,
495 FormulaGrammar::AddressConvention eConv
,
497 sal_Unicode cSeperator
,
501 sal_Bool
bResult(sal_False
);
502 GetTokenByOffset( sToken
, rRangeStr
, nOffset
, cSeperator
, cQuote
);
505 sal_Int32 nIndex
= IndexOf( sToken
, ':', 0, cQuote
);
506 String
aUIString(sToken
);
510 if ( aUIString
.GetChar(0) == (sal_Unicode
) '.' )
511 aUIString
.Erase( 0, 1 );
512 bResult
= ((rRange
.aStart
.Parse( aUIString
, const_cast<ScDocument
*> (pDocument
), eConv
) & SCA_VALID
) == SCA_VALID
);
513 #if CHART_ADDRESS_CONV_WORKAROUND
514 if (!bResult
&& eConv
!= eConv
)
515 bResult
= ((rRange
.aStart
.Parse(
516 aUIString
, const_cast<ScDocument
*>(pDocument
), eConv
) & SCA_VALID
) == SCA_VALID
);
518 rRange
.aEnd
= rRange
.aStart
;
522 if ( aUIString
.GetChar(0) == (sal_Unicode
) '.' )
524 aUIString
.Erase( 0, 1 );
528 if ( nIndex
< aUIString
.Len() - 1 &&
529 aUIString
.GetChar((xub_StrLen
)nIndex
+ 1) == (sal_Unicode
) '.' )
530 aUIString
.Erase( (xub_StrLen
)nIndex
+ 1, 1 );
532 bResult
= ((rRange
.Parse(aUIString
, const_cast<ScDocument
*> (pDocument
), eConv
) & SCA_VALID
) == SCA_VALID
);
534 // #i77703# chart ranges in the file format contain both sheet names, even for an external reference sheet.
535 // This isn't parsed by ScRange, so try to parse the two Addresses then.
538 bResult
= ((rRange
.aStart
.Parse( aUIString
.Copy(0, (xub_StrLen
)nIndex
), const_cast<ScDocument
*>(pDocument
),
539 eConv
) & SCA_VALID
) == SCA_VALID
) &&
540 ((rRange
.aEnd
.Parse( aUIString
.Copy((xub_StrLen
)nIndex
+1), const_cast<ScDocument
*>(pDocument
),
541 eConv
) & SCA_VALID
) == SCA_VALID
);
542 #if CHART_ADDRESS_CONV_WORKAROUND
543 if (!bResult
&& eConv
!= eConv
)
545 bResult
= ((rRange
.aStart
.Parse( aUIString
.Copy(0, (xub_StrLen
)nIndex
), const_cast<ScDocument
*>(pDocument
),
546 eConv
) & SCA_VALID
) == SCA_VALID
) &&
547 ((rRange
.aEnd
.Parse( aUIString
.Copy((xub_StrLen
)nIndex
+1), const_cast<ScDocument
*>(pDocument
),
548 eConv
) & SCA_VALID
) == SCA_VALID
);
557 sal_Bool
ScRangeStringConverter::GetRangeListFromString(
558 ScRangeList
& rRangeList
,
559 const OUString
& rRangeListStr
,
560 const ScDocument
* pDocument
,
561 FormulaGrammar::AddressConvention eConv
,
562 sal_Unicode cSeperator
,
565 sal_Bool bRet
= sal_True
;
566 DBG_ASSERT( rRangeListStr
.getLength(), "ScXMLConverter::GetRangeListFromString - empty string!" );
567 sal_Int32 nOffset
= 0;
568 while( nOffset
>= 0 )
570 ScRange
* pRange
= new ScRange
;
571 if( GetRangeFromString( *pRange
, rRangeListStr
, pDocument
, eConv
, nOffset
, cSeperator
, cQuote
) && (nOffset
>= 0) )
572 rRangeList
.Insert( pRange
, LIST_APPEND
);
573 else if (nOffset
> -1)
580 //___________________________________________________________________
582 sal_Bool
ScRangeStringConverter::GetAreaFromString(
584 const OUString
& rRangeStr
,
585 const ScDocument
* pDocument
,
586 FormulaGrammar::AddressConvention eConv
,
588 sal_Unicode cSeperator
,
592 sal_Bool
bResult(sal_False
);
593 if( GetRangeFromString( aScRange
, rRangeStr
, pDocument
, eConv
, nOffset
, cSeperator
, cQuote
) && (nOffset
>= 0) )
595 rArea
.nTab
= aScRange
.aStart
.Tab();
596 rArea
.nColStart
= aScRange
.aStart
.Col();
597 rArea
.nRowStart
= aScRange
.aStart
.Row();
598 rArea
.nColEnd
= aScRange
.aEnd
.Col();
599 rArea
.nRowEnd
= aScRange
.aEnd
.Row();
606 //___________________________________________________________________
608 sal_Bool
ScRangeStringConverter::GetAddressFromString(
609 table::CellAddress
& rAddress
,
610 const OUString
& rAddressStr
,
611 const ScDocument
* pDocument
,
612 FormulaGrammar::AddressConvention eConv
,
614 sal_Unicode cSeperator
,
617 ScAddress aScAddress
;
618 sal_Bool
bResult(sal_False
);
619 if( GetAddressFromString( aScAddress
, rAddressStr
, pDocument
, eConv
, nOffset
, cSeperator
, cQuote
) && (nOffset
>= 0) )
621 ScUnoConversion::FillApiAddress( rAddress
, aScAddress
);
627 sal_Bool
ScRangeStringConverter::GetRangeFromString(
628 table::CellRangeAddress
& rRange
,
629 const OUString
& rRangeStr
,
630 const ScDocument
* pDocument
,
631 FormulaGrammar::AddressConvention eConv
,
633 sal_Unicode cSeperator
,
637 sal_Bool
bResult(sal_False
);
638 if( GetRangeFromString( aScRange
, rRangeStr
, pDocument
, eConv
, nOffset
, cSeperator
, cQuote
) && (nOffset
>= 0) )
640 ScUnoConversion::FillApiRange( rRange
, aScRange
);
646 sal_Bool
ScRangeStringConverter::GetRangeListFromString(
647 uno::Sequence
< table::CellRangeAddress
>& rRangeSeq
,
648 const OUString
& rRangeListStr
,
649 const ScDocument
* pDocument
,
650 FormulaGrammar::AddressConvention eConv
,
651 sal_Unicode cSeperator
,
654 sal_Bool bRet
= sal_True
;
655 DBG_ASSERT( rRangeListStr
.getLength(), "ScXMLConverter::GetRangeListFromString - empty string!" );
656 table::CellRangeAddress aRange
;
657 sal_Int32 nOffset
= 0;
658 while( nOffset
>= 0 )
660 if( GetRangeFromString( aRange
, rRangeListStr
, pDocument
, eConv
, nOffset
, cSeperator
, cQuote
) && (nOffset
>= 0) )
662 rRangeSeq
.realloc( rRangeSeq
.getLength() + 1 );
663 rRangeSeq
[ rRangeSeq
.getLength() - 1 ] = aRange
;
672 //___________________________________________________________________
674 void ScRangeStringConverter::GetStringFromAddress(
676 const ScAddress
& rAddress
,
677 const ScDocument
* pDocument
,
678 FormulaGrammar::AddressConvention eConv
,
679 sal_Unicode cSeperator
,
681 sal_uInt16 nFormatFlags
)
683 if (pDocument
&& pDocument
->HasTable(rAddress
.Tab()))
686 rAddress
.Format( sAddress
, nFormatFlags
, (ScDocument
*) pDocument
, eConv
);
687 AssignString( rString
, sAddress
, bAppendStr
, cSeperator
);
691 void ScRangeStringConverter::GetStringFromRange(
693 const ScRange
& rRange
,
694 const ScDocument
* pDocument
,
695 FormulaGrammar::AddressConvention eConv
,
696 sal_Unicode cSeperator
,
698 sal_uInt16 nFormatFlags
)
700 if (pDocument
&& pDocument
->HasTable(rRange
.aStart
.Tab()))
702 ScAddress
aStartAddress( rRange
.aStart
);
703 ScAddress
aEndAddress( rRange
.aEnd
);
704 String sStartAddress
;
706 aStartAddress
.Format( sStartAddress
, nFormatFlags
, (ScDocument
*) pDocument
, eConv
);
707 aEndAddress
.Format( sEndAddress
, nFormatFlags
, (ScDocument
*) pDocument
, eConv
);
708 OUString
sOUStartAddress( sStartAddress
);
709 sOUStartAddress
+= OUString(':');
710 sOUStartAddress
+= OUString( sEndAddress
);
711 AssignString( rString
, sOUStartAddress
, bAppendStr
, cSeperator
);
715 void ScRangeStringConverter::GetStringFromRangeList(
717 const ScRangeList
* pRangeList
,
718 const ScDocument
* pDocument
,
719 FormulaGrammar::AddressConvention eConv
,
720 sal_Unicode cSeperator
,
721 sal_uInt16 nFormatFlags
)
723 OUString sRangeListStr
;
726 sal_Int32 nCount
= pRangeList
->Count();
727 for( sal_Int32 nIndex
= 0; nIndex
< nCount
; nIndex
++ )
729 const ScRange
* pRange
= pRangeList
->GetObject( nIndex
);
731 GetStringFromRange( sRangeListStr
, *pRange
, pDocument
, eConv
, cSeperator
, sal_True
, nFormatFlags
);
734 rString
= sRangeListStr
;
738 //___________________________________________________________________
740 void ScRangeStringConverter::GetStringFromArea(
743 const ScDocument
* pDocument
,
744 FormulaGrammar::AddressConvention eConv
,
745 sal_Unicode cSeperator
,
747 sal_uInt16 nFormatFlags
)
749 ScRange
aRange( rArea
.nColStart
, rArea
.nRowStart
, rArea
.nTab
, rArea
.nColEnd
, rArea
.nRowEnd
, rArea
.nTab
);
750 GetStringFromRange( rString
, aRange
, pDocument
, eConv
, cSeperator
, bAppendStr
, nFormatFlags
);
754 //___________________________________________________________________
756 void ScRangeStringConverter::GetStringFromAddress(
758 const table::CellAddress
& rAddress
,
759 const ScDocument
* pDocument
,
760 FormulaGrammar::AddressConvention eConv
,
761 sal_Unicode cSeperator
,
763 sal_uInt16 nFormatFlags
)
765 ScAddress
aScAddress( static_cast<SCCOL
>(rAddress
.Column
), static_cast<SCROW
>(rAddress
.Row
), rAddress
.Sheet
);
766 GetStringFromAddress( rString
, aScAddress
, pDocument
, eConv
, cSeperator
, bAppendStr
, nFormatFlags
);
769 void ScRangeStringConverter::GetStringFromRange(
771 const table::CellRangeAddress
& rRange
,
772 const ScDocument
* pDocument
,
773 FormulaGrammar::AddressConvention eConv
,
774 sal_Unicode cSeperator
,
776 sal_uInt16 nFormatFlags
)
778 ScRange
aScRange( static_cast<SCCOL
>(rRange
.StartColumn
), static_cast<SCROW
>(rRange
.StartRow
), rRange
.Sheet
,
779 static_cast<SCCOL
>(rRange
.EndColumn
), static_cast<SCROW
>(rRange
.EndRow
), rRange
.Sheet
);
780 GetStringFromRange( rString
, aScRange
, pDocument
, eConv
, cSeperator
, bAppendStr
, nFormatFlags
);
783 void ScRangeStringConverter::GetStringFromRangeList(
785 const uno::Sequence
< table::CellRangeAddress
>& rRangeSeq
,
786 const ScDocument
* pDocument
,
787 FormulaGrammar::AddressConvention eConv
,
788 sal_Unicode cSeperator
,
789 sal_uInt16 nFormatFlags
)
791 OUString sRangeListStr
;
792 sal_Int32 nCount
= rRangeSeq
.getLength();
793 for( sal_Int32 nIndex
= 0; nIndex
< nCount
; nIndex
++ )
795 const table::CellRangeAddress
& rRange
= rRangeSeq
[ nIndex
];
796 GetStringFromRange( sRangeListStr
, rRange
, pDocument
, eConv
, cSeperator
, sal_True
, nFormatFlags
);
798 rString
= sRangeListStr
;
801 static void lcl_appendCellAddress(
802 rtl::OUStringBuffer
& rBuf
, ScDocument
* pDoc
, const ScAddress
& rCell
,
803 const ScAddress::ExternalInfo
& rExtInfo
)
805 if (rExtInfo
.mbExternal
)
807 ScExternalRefManager
* pRefMgr
= pDoc
->GetExternalRefManager();
808 const String
* pFilePath
= pRefMgr
->getExternalFileName(rExtInfo
.mnFileId
);
812 sal_Unicode cQuote
= '\'';
814 rBuf
.append(*pFilePath
);
816 rBuf
.append(sal_Unicode('#'));
817 rBuf
.append(sal_Unicode('$'));
818 ScRangeStringConverter::AppendTableName(rBuf
, rExtInfo
.maTabName
);
819 rBuf
.append(sal_Unicode('.'));
822 rCell
.Format(aAddr
, SCA_ABS
, NULL
, ::formula::FormulaGrammar::CONV_OOO
);
828 rCell
.Format(aAddr
, SCA_ABS_3D
, pDoc
, ::formula::FormulaGrammar::CONV_OOO
);
833 static void lcl_appendCellRangeAddress(
834 rtl::OUStringBuffer
& rBuf
, ScDocument
* pDoc
, const ScAddress
& rCell1
, const ScAddress
& rCell2
,
835 const ScAddress::ExternalInfo
& rExtInfo1
, const ScAddress::ExternalInfo
& rExtInfo2
)
837 if (rExtInfo1
.mbExternal
)
839 DBG_ASSERT(rExtInfo2
.mbExternal
, "2nd address is not external!?");
840 DBG_ASSERT(rExtInfo1
.mnFileId
== rExtInfo2
.mnFileId
, "File IDs do not match between 1st and 2nd addresses.");
842 ScExternalRefManager
* pRefMgr
= pDoc
->GetExternalRefManager();
843 const String
* pFilePath
= pRefMgr
->getExternalFileName(rExtInfo1
.mnFileId
);
847 sal_Unicode cQuote
= '\'';
849 rBuf
.append(*pFilePath
);
851 rBuf
.append(sal_Unicode('#'));
852 rBuf
.append(sal_Unicode('$'));
853 ScRangeStringConverter::AppendTableName(rBuf
, rExtInfo1
.maTabName
);
854 rBuf
.append(sal_Unicode('.'));
857 rCell1
.Format(aAddr
, SCA_ABS
, NULL
, ::formula::FormulaGrammar::CONV_OOO
);
860 rBuf
.appendAscii(":");
862 if (rExtInfo1
.maTabName
!= rExtInfo2
.maTabName
)
864 rBuf
.append(sal_Unicode('$'));
865 ScRangeStringConverter::AppendTableName(rBuf
, rExtInfo2
.maTabName
);
866 rBuf
.append(sal_Unicode('.'));
869 rCell2
.Format(aAddr
, SCA_ABS
, NULL
, ::formula::FormulaGrammar::CONV_OOO
);
875 aRange
.aStart
= rCell1
;
876 aRange
.aEnd
= rCell2
;
878 aRange
.Format(aAddr
, SCR_ABS_3D
, pDoc
, ::formula::FormulaGrammar::CONV_OOO
);
883 void ScRangeStringConverter::GetStringFromXMLRangeString( OUString
& rString
, const OUString
& rXMLRange
, ScDocument
* pDoc
)
885 FormulaGrammar::AddressConvention eConv
= pDoc
->GetAddressConvention();
886 const OUString aRangeSep
= GetScCompilerNativeSymbol(ocSep
);
887 const sal_Unicode cSep
= ' ';
888 const sal_Unicode cQuote
= '\'';
890 OUStringBuffer aRetStr
;
891 sal_Int32 nOffset
= 0;
897 GetTokenByOffset(aToken
, rXMLRange
, nOffset
, cSep
, cQuote
);
901 sal_Int32 nSepPos
= IndexOf(aToken
, ':', 0, cQuote
);
905 OUString aBeginCell
= aToken
.copy(0, nSepPos
);
906 OUString aEndCell
= aToken
.copy(nSepPos
+1);
908 if (!aBeginCell
.getLength() || !aEndCell
.getLength())
909 // both cell addresses must exist for this to work.
912 sal_Int32 nEndCellDotPos
= aEndCell
.indexOf('.');
913 if (nEndCellDotPos
<= 0)
915 // initialize buffer with table name...
916 sal_Int32 nDotPos
= IndexOf(aBeginCell
, sal_Unicode('.'), 0, cQuote
);
917 OUStringBuffer aBuf
= aBeginCell
.copy(0, nDotPos
);
919 if (nEndCellDotPos
== 0)
921 // workaround for old syntax (probably pre-chart2 age?)
922 // e.g. Sheet1.A1:.B2
923 aBuf
.append(aEndCell
);
925 else if (nEndCellDotPos
< 0)
927 // sheet name in the end cell is omitted (e.g. Sheet2.A1:B2).
928 aBuf
.append(sal_Unicode('.'));
929 aBuf
.append(aEndCell
);
931 aEndCell
= aBuf
.makeStringAndClear();
934 ScAddress::ExternalInfo aExtInfo1
, aExtInfo2
;
935 ScAddress aCell1
, aCell2
;
937 USHORT nRet
= aCell1
.Parse(aBeginCell
, pDoc
, FormulaGrammar::CONV_OOO
, &aExtInfo1
);
938 if ((nRet
& SCA_VALID
) != SCA_VALID
)
940 // first cell is invalid.
941 #if CHART_ADDRESS_CONV_WORKAROUND
942 if (eConv
== FormulaGrammar::CONV_OOO
)
945 nRet
= aCell1
.Parse(aBeginCell
, pDoc
, eConv
, &aExtInfo1
);
946 if ((nRet
& SCA_VALID
) != SCA_VALID
)
947 // first cell is really invalid.
954 nRet
= aCell2
.Parse(aEndCell
, pDoc
, FormulaGrammar::CONV_OOO
, &aExtInfo2
);
955 if ((nRet
& SCA_VALID
) != SCA_VALID
)
957 // second cell is invalid.
958 #if CHART_ADDRESS_CONV_WORKAROUND
959 if (eConv
== FormulaGrammar::CONV_OOO
)
962 nRet
= aCell2
.Parse(aEndCell
, pDoc
, eConv
, &aExtInfo2
);
963 if ((nRet
& SCA_VALID
) != SCA_VALID
)
964 // second cell is really invalid.
971 if (aExtInfo1
.mnFileId
!= aExtInfo2
.mnFileId
|| aExtInfo1
.mbExternal
!= aExtInfo2
.mbExternal
)
972 // external info inconsistency.
980 aRetStr
.append(aRangeSep
);
982 lcl_appendCellRangeAddress(aRetStr
, pDoc
, aCell1
, aCell2
, aExtInfo1
, aExtInfo2
);
986 // Chart always saves ranges using CONV_OOO convention.
987 ScAddress::ExternalInfo aExtInfo
;
989 USHORT nRet
= aCell
.Parse(aToken
, pDoc
, ::formula::FormulaGrammar::CONV_OOO
, &aExtInfo
);
990 if ((nRet
& SCA_VALID
) != SCA_VALID
)
992 #if CHART_ADDRESS_CONV_WORKAROUND
993 nRet
= aCell
.Parse(aToken
, pDoc
, eConv
, &aExtInfo
);
994 if ((nRet
& SCA_VALID
) != SCA_VALID
)
1006 aRetStr
.append(aRangeSep
);
1008 lcl_appendCellAddress(aRetStr
, pDoc
, aCell
, aExtInfo
);
1012 rString
= aRetStr
.makeStringAndClear();
1015 //========================================================================
1017 ScArea::ScArea( SCTAB tab
,
1018 SCCOL colStart
, SCROW rowStart
,
1019 SCCOL colEnd
, SCROW rowEnd
) :
1021 nColStart( colStart
), nRowStart( rowStart
),
1022 nColEnd ( colEnd
), nRowEnd ( rowEnd
)
1026 //------------------------------------------------------------------------
1028 ScArea::ScArea( const ScArea
& r
) :
1030 nColStart( r
.nColStart
), nRowStart( r
.nRowStart
),
1031 nColEnd ( r
.nColEnd
), nRowEnd ( r
.nRowEnd
)
1035 //------------------------------------------------------------------------
1037 ScArea
& ScArea::operator=( const ScArea
& r
)
1040 nColStart
= r
.nColStart
;
1041 nRowStart
= r
.nRowStart
;
1042 nColEnd
= r
.nColEnd
;
1043 nRowEnd
= r
.nRowEnd
;
1047 //------------------------------------------------------------------------
1049 BOOL
ScArea::operator==( const ScArea
& r
) const
1051 return ( (nTab
== r
.nTab
)
1052 && (nColStart
== r
.nColStart
)
1053 && (nRowStart
== r
.nRowStart
)
1054 && (nColEnd
== r
.nColEnd
)
1055 && (nRowEnd
== r
.nRowEnd
) );
1058 //------------------------------------------------------------------------
1060 ScAreaNameIterator::ScAreaNameIterator( ScDocument
* pDoc
) :
1061 aStrNoName( ScGlobal::GetRscString(STR_DB_NONAME
) )
1063 pRangeName
= pDoc
->GetRangeName();
1064 pDBCollection
= pDoc
->GetDBCollection();
1069 BOOL
ScAreaNameIterator::Next( String
& rName
, ScRange
& rRange
)
1073 if ( bFirstPass
) // erst Bereichsnamen
1075 if ( pRangeName
&& nPos
< pRangeName
->GetCount() )
1077 ScRangeData
* pData
= (*pRangeName
)[nPos
++];
1078 if ( pData
&& pData
->IsValidReference(rRange
) )
1080 rName
= pData
->GetName();
1081 return TRUE
; // gefunden
1090 if ( !bFirstPass
) // dann DB-Bereiche
1092 if ( pDBCollection
&& nPos
< pDBCollection
->GetCount() )
1094 ScDBData
* pData
= (*pDBCollection
)[nPos
++];
1095 if (pData
&& pData
->GetName() != aStrNoName
)
1097 pData
->GetArea( rRange
);
1098 rName
= pData
->GetName();
1099 return TRUE
; // gefunden
1103 return FALSE
; // gibt nichts mehr