diff options
Diffstat (limited to 'sc/source/core/tool/rangeutl.cxx')
-rw-r--r-- | sc/source/core/tool/rangeutl.cxx | 1054 |
1 files changed, 1054 insertions, 0 deletions
diff --git a/sc/source/core/tool/rangeutl.cxx b/sc/source/core/tool/rangeutl.cxx new file mode 100644 index 000000000000..9f6526a54cf6 --- /dev/null +++ b/sc/source/core/tool/rangeutl.cxx @@ -0,0 +1,1054 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +#include <tools/debug.hxx> + +#include "rangeutl.hxx" +#include "document.hxx" +#include "global.hxx" +#include "dbcolect.hxx" +#include "rangenam.hxx" +#include "scresid.hxx" +#include "globstr.hrc" +#include "convuno.hxx" +#include "externalrefmgr.hxx" +#include "compiler.hxx" + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using ::formula::FormulaGrammar; +using namespace ::com::sun::star; + +//------------------------------------------------------------------------ + +BOOL ScRangeUtil::MakeArea( const String& rAreaStr, + ScArea& rArea, + ScDocument* pDoc, + SCTAB nTab, + ScAddress::Details const & rDetails ) const +{ + // Eingabe in rAreaStr: "$Tabelle1.$A1:$D17" + + // BROKEN BROKEN BROKEN + // but it is only used in the consolidate dialog. Ignore for now. + + BOOL nSuccess = FALSE; + USHORT nPointPos = rAreaStr.Search('.'); + USHORT nColonPos = rAreaStr.Search(':'); + String aStrArea( rAreaStr ); + ScRefAddress startPos; + ScRefAddress endPos; + + if ( nColonPos == STRING_NOTFOUND ) + if ( nPointPos != STRING_NOTFOUND ) + { + aStrArea += ':'; + aStrArea += rAreaStr.Copy( nPointPos+1 ); // '.' nicht mitkopieren + } + + nSuccess = ConvertDoubleRef( pDoc, aStrArea, nTab, startPos, endPos, rDetails ); + + if ( nSuccess ) + rArea = ScArea( startPos.Tab(), + startPos.Col(), startPos.Row(), + endPos.Col(), endPos.Row() ); + + return nSuccess; +} + +//------------------------------------------------------------------------ + +void ScRangeUtil::CutPosString( const String& theAreaStr, + String& thePosStr ) const +{ + String aPosStr; + // BROKEN BROKEN BROKEN + // but it is only used in the consolidate dialog. Ignore for now. + + USHORT nColonPos = theAreaStr.Search(':'); + + if ( nColonPos != STRING_NOTFOUND ) + aPosStr = theAreaStr.Copy( 0, nColonPos ); // ':' nicht mitkopieren + else + aPosStr = theAreaStr; + + thePosStr = aPosStr; +} + +//------------------------------------------------------------------------ + +BOOL ScRangeUtil::IsAbsTabArea( const String& rAreaStr, + ScDocument* pDoc, + ScArea*** pppAreas, + USHORT* pAreaCount, + BOOL /* bAcceptCellRef */, + ScAddress::Details const & rDetails ) const +{ + DBG_ASSERT( pDoc, "Kein Dokument uebergeben!" ); + if ( !pDoc ) + return FALSE; + + // BROKEN BROKEN BROKEN + // but it is only used in the consolidate dialog. Ignore for now. + + /* + * Erwartet wird ein String der Form + * "$Tabelle1.$A$1:$Tabelle3.$D$17" + * Wenn bAcceptCellRef == TRUE ist, wird auch ein String der Form + * "$Tabelle1.$A$1" + * akzeptiert. + * + * als Ergebnis wird ein ScArea-Array angelegt, + * welches ueber ppAreas bekannt gegeben wird und auch + * wieder geloescht werden muss! + */ + + BOOL bStrOk = FALSE; + String aTempAreaStr(rAreaStr); + String aStartPosStr; + String aEndPosStr; + + if ( STRING_NOTFOUND == aTempAreaStr.Search(':') ) + { + aTempAreaStr.Append(':'); + aTempAreaStr.Append(rAreaStr); + } + + USHORT nColonPos = aTempAreaStr.Search(':'); + + if ( STRING_NOTFOUND != nColonPos + && STRING_NOTFOUND != aTempAreaStr.Search('.') ) + { + ScRefAddress aStartPos; + ScRefAddress aEndPos; + + aStartPosStr = aTempAreaStr.Copy( 0, nColonPos ); + aEndPosStr = aTempAreaStr.Copy( nColonPos+1, STRING_LEN ); + + if ( ConvertSingleRef( pDoc, aStartPosStr, 0, aStartPos, rDetails ) ) + { + if ( ConvertSingleRef( pDoc, aEndPosStr, aStartPos.Tab(), aEndPos, rDetails ) ) + { + aStartPos.SetRelCol( FALSE ); + aStartPos.SetRelRow( FALSE ); + aStartPos.SetRelTab( FALSE ); + aEndPos.SetRelCol( FALSE ); + aEndPos.SetRelRow( FALSE ); + aEndPos.SetRelTab( FALSE ); + + bStrOk = TRUE; + + if ( pppAreas && pAreaCount ) // Array zurueckgegeben? + { + SCTAB nStartTab = aStartPos.Tab(); + SCTAB nEndTab = aEndPos.Tab(); + USHORT nTabCount = static_cast<USHORT>(nEndTab-nStartTab+1); + ScArea** theAreas = new ScArea*[nTabCount]; + SCTAB nTab = 0; + USHORT i = 0; + ScArea theArea( 0, aStartPos.Col(), aStartPos.Row(), + aEndPos.Col(), aEndPos.Row() ); + + nTab = nStartTab; + for ( i=0; i<nTabCount; i++ ) + { + theAreas[i] = new ScArea( theArea ); + theAreas[i]->nTab = nTab; + nTab++; + } + *pppAreas = theAreas; + *pAreaCount = nTabCount; + } + } + } + } + + return bStrOk; +} + +//------------------------------------------------------------------------ + +BOOL ScRangeUtil::IsAbsArea( const String& rAreaStr, + ScDocument* pDoc, + SCTAB nTab, + String* pCompleteStr, + ScRefAddress* pStartPos, + ScRefAddress* pEndPos, + ScAddress::Details const & rDetails ) const +{ + BOOL bIsAbsArea = FALSE; + ScRefAddress startPos; + ScRefAddress endPos; + + bIsAbsArea = ConvertDoubleRef( pDoc, rAreaStr, nTab, startPos, endPos, rDetails ); + + if ( bIsAbsArea ) + { + startPos.SetRelCol( FALSE ); + startPos.SetRelRow( FALSE ); + startPos.SetRelTab( FALSE ); + endPos .SetRelCol( FALSE ); + endPos .SetRelRow( FALSE ); + endPos .SetRelTab( FALSE ); + + if ( pCompleteStr ) + { + *pCompleteStr = startPos.GetRefString( pDoc, MAXTAB+1, rDetails ); + *pCompleteStr += ':'; + *pCompleteStr += endPos .GetRefString( pDoc, nTab, rDetails ); + } + + if ( pStartPos && pEndPos ) + { + *pStartPos = startPos; + *pEndPos = endPos; + } + } + + return bIsAbsArea; +} + +//------------------------------------------------------------------------ + +BOOL ScRangeUtil::IsAbsPos( const String& rPosStr, + ScDocument* pDoc, + SCTAB nTab, + String* pCompleteStr, + ScRefAddress* pPosTripel, + ScAddress::Details const & rDetails ) const +{ + BOOL bIsAbsPos = FALSE; + ScRefAddress thePos; + + bIsAbsPos = ConvertSingleRef( pDoc, rPosStr, nTab, thePos, rDetails ); + thePos.SetRelCol( FALSE ); + thePos.SetRelRow( FALSE ); + thePos.SetRelTab( FALSE ); + + if ( bIsAbsPos ) + { + if ( pPosTripel ) + *pPosTripel = thePos; + if ( pCompleteStr ) + *pCompleteStr = thePos.GetRefString( pDoc, MAXTAB+1, rDetails ); + } + + return bIsAbsPos; +} + +//------------------------------------------------------------------------ + +BOOL ScRangeUtil::MakeRangeFromName ( + const String& rName, + ScDocument* pDoc, + SCTAB nCurTab, + ScRange& rRange, + RutlNameScope eScope, + ScAddress::Details const & rDetails ) const +{ + BOOL bResult=FALSE; + ScRangeUtil aRangeUtil; + SCTAB nTab = 0; + SCCOL nColStart = 0; + SCCOL nColEnd = 0; + SCROW nRowStart = 0; + SCROW nRowEnd = 0; + + if( eScope==RUTL_NAMES ) + { + ScRangeName& rRangeNames = *(pDoc->GetRangeName()); + USHORT nAt = 0; + + if ( rRangeNames.SearchName( rName, nAt ) ) + { + ScRangeData* pData = rRangeNames[nAt]; + String aStrArea; + ScRefAddress aStartPos; + ScRefAddress aEndPos; + + pData->GetSymbol( aStrArea ); + + if ( IsAbsArea( aStrArea, pDoc, nCurTab, + NULL, &aStartPos, &aEndPos, rDetails ) ) + { + nTab = aStartPos.Tab(); + nColStart = aStartPos.Col(); + nRowStart = aStartPos.Row(); + nColEnd = aEndPos.Col(); + nRowEnd = aEndPos.Row(); + bResult = TRUE; + } + else + { + CutPosString( aStrArea, aStrArea ); + + if ( IsAbsPos( aStrArea, pDoc, nCurTab, + NULL, &aStartPos, rDetails ) ) + { + nTab = aStartPos.Tab(); + nColStart = nColEnd = aStartPos.Col(); + nRowStart = nRowEnd = aStartPos.Row(); + bResult = TRUE; + } + } + } + } + else if( eScope==RUTL_DBASE ) + { + ScDBCollection& rDbNames = *(pDoc->GetDBCollection()); + USHORT nAt = 0; + + if ( rDbNames.SearchName( rName, nAt ) ) + { + ScDBData* pData = rDbNames[nAt]; + + pData->GetArea( nTab, nColStart, nRowStart, + nColEnd, nRowEnd ); + bResult = TRUE; + } + } + else + { + DBG_ERROR( "ScRangeUtil::MakeRangeFromName" ); + } + + if( bResult ) + { + rRange = ScRange( nColStart, nRowStart, nTab, nColEnd, nRowEnd, nTab ); + } + + return bResult; +} + +//======================================================================== + +void ScRangeStringConverter::AssignString( + OUString& rString, + const OUString& rNewStr, + sal_Bool bAppendStr, + sal_Unicode cSeperator) +{ + if( bAppendStr ) + { + if( rNewStr.getLength() ) + { + if( rString.getLength() ) + rString += rtl::OUString(cSeperator); + rString += rNewStr; + } + } + else + rString = rNewStr; +} + +sal_Int32 ScRangeStringConverter::IndexOf( + const OUString& rString, + sal_Unicode cSearchChar, + sal_Int32 nOffset, + sal_Unicode cQuote ) +{ + sal_Int32 nLength = rString.getLength(); + sal_Int32 nIndex = nOffset; + sal_Bool bQuoted = sal_False; + sal_Bool bExitLoop = sal_False; + + while( !bExitLoop && (nIndex < nLength) ) + { + sal_Unicode cCode = rString[ nIndex ]; + bExitLoop = (cCode == cSearchChar) && !bQuoted; + bQuoted = (bQuoted != (cCode == cQuote)); + if( !bExitLoop ) + nIndex++; + } + return (nIndex < nLength) ? nIndex : -1; +} + +sal_Int32 ScRangeStringConverter::IndexOfDifferent( + const OUString& rString, + sal_Unicode cSearchChar, + sal_Int32 nOffset ) +{ + sal_Int32 nLength = rString.getLength(); + sal_Int32 nIndex = nOffset; + sal_Bool bExitLoop = sal_False; + + while( !bExitLoop && (nIndex < nLength) ) + { + bExitLoop = (rString[ nIndex ] != cSearchChar); + if( !bExitLoop ) + nIndex++; + } + return (nIndex < nLength) ? nIndex : -1; +} + +void ScRangeStringConverter::GetTokenByOffset( + OUString& rToken, + const OUString& rString, + sal_Int32& nOffset, + sal_Unicode cSeperator, + sal_Unicode cQuote) +{ + sal_Int32 nLength = rString.getLength(); + if( nOffset >= nLength ) + { + rToken = OUString(); + nOffset = -1; + } + else + { + sal_Int32 nTokenEnd = IndexOf( rString, cSeperator, nOffset, cQuote ); + if( nTokenEnd < 0 ) + nTokenEnd = nLength; + rToken = rString.copy( nOffset, nTokenEnd - nOffset ); + + sal_Int32 nNextBegin = IndexOfDifferent( rString, cSeperator, nTokenEnd ); + nOffset = (nNextBegin < 0) ? nLength : nNextBegin; + } +} + +void ScRangeStringConverter::AppendTableName(OUStringBuffer& rBuf, const OUString& rTabName, sal_Unicode /* cQuote */) +{ + // quote character is always "'" + String aQuotedTab(rTabName); + ScCompiler::CheckTabQuotes(aQuotedTab, ::formula::FormulaGrammar::CONV_OOO); + rBuf.append(aQuotedTab); +} + +sal_Int32 ScRangeStringConverter::GetTokenCount( const OUString& rString, sal_Unicode cSeperator, sal_Unicode cQuote ) +{ + OUString sToken; + sal_Int32 nCount = 0; + sal_Int32 nOffset = 0; + while( nOffset >= 0 ) + { + GetTokenByOffset( sToken, rString, nOffset, cQuote, cSeperator ); + if( nOffset >= 0 ) + nCount++; + } + return nCount; +} + +//___________________________________________________________________ + +sal_Bool ScRangeStringConverter::GetAddressFromString( + ScAddress& rAddress, + const OUString& rAddressStr, + const ScDocument* pDocument, + FormulaGrammar::AddressConvention eConv, + sal_Int32& nOffset, + sal_Unicode cSeperator, + sal_Unicode cQuote ) +{ + OUString sToken; + GetTokenByOffset( sToken, rAddressStr, nOffset, cSeperator, cQuote ); + if( nOffset >= 0 ) + { + if ((rAddress.Parse( sToken, const_cast<ScDocument*>(pDocument), eConv ) & SCA_VALID) == SCA_VALID) + return true; + } + return sal_False; +} + +sal_Bool ScRangeStringConverter::GetRangeFromString( + ScRange& rRange, + const OUString& rRangeStr, + const ScDocument* pDocument, + FormulaGrammar::AddressConvention eConv, + sal_Int32& nOffset, + sal_Unicode cSeperator, + sal_Unicode cQuote ) +{ + OUString sToken; + sal_Bool bResult(sal_False); + GetTokenByOffset( sToken, rRangeStr, nOffset, cSeperator, cQuote ); + if( nOffset >= 0 ) + { + sal_Int32 nIndex = IndexOf( sToken, ':', 0, cQuote ); + String aUIString(sToken); + + if( nIndex < 0 ) + { + if ( aUIString.GetChar(0) == (sal_Unicode) '.' ) + aUIString.Erase( 0, 1 ); + bResult = ((rRange.aStart.Parse( aUIString, const_cast<ScDocument*> (pDocument), eConv) & SCA_VALID) == SCA_VALID); + rRange.aEnd = rRange.aStart; + } + else + { + if ( aUIString.GetChar(0) == (sal_Unicode) '.' ) + { + aUIString.Erase( 0, 1 ); + --nIndex; + } + + if ( nIndex < aUIString.Len() - 1 && + aUIString.GetChar((xub_StrLen)nIndex + 1) == (sal_Unicode) '.' ) + aUIString.Erase( (xub_StrLen)nIndex + 1, 1 ); + + bResult = ((rRange.Parse(aUIString, const_cast<ScDocument*> (pDocument), eConv) & SCA_VALID) == SCA_VALID); + + // #i77703# chart ranges in the file format contain both sheet names, even for an external reference sheet. + // This isn't parsed by ScRange, so try to parse the two Addresses then. + if (!bResult) + { + bResult = ((rRange.aStart.Parse( aUIString.Copy(0, (xub_StrLen)nIndex), const_cast<ScDocument*>(pDocument), + eConv) & SCA_VALID) == SCA_VALID) && + ((rRange.aEnd.Parse( aUIString.Copy((xub_StrLen)nIndex+1), const_cast<ScDocument*>(pDocument), + eConv) & SCA_VALID) == SCA_VALID); + } + } + } + return bResult; +} + +sal_Bool ScRangeStringConverter::GetRangeListFromString( + ScRangeList& rRangeList, + const OUString& rRangeListStr, + const ScDocument* pDocument, + FormulaGrammar::AddressConvention eConv, + sal_Unicode cSeperator, + sal_Unicode cQuote ) +{ + sal_Bool bRet = sal_True; + DBG_ASSERT( rRangeListStr.getLength(), "ScXMLConverter::GetRangeListFromString - empty string!" ); + sal_Int32 nOffset = 0; + while( nOffset >= 0 ) + { + ScRange* pRange = new ScRange; + if( GetRangeFromString( *pRange, rRangeListStr, pDocument, eConv, nOffset, cSeperator, cQuote ) && (nOffset >= 0) ) + rRangeList.Insert( pRange, LIST_APPEND ); + else if (nOffset > -1) + bRet = sal_False; + } + return bRet; +} + + +//___________________________________________________________________ + +sal_Bool ScRangeStringConverter::GetAreaFromString( + ScArea& rArea, + const OUString& rRangeStr, + const ScDocument* pDocument, + FormulaGrammar::AddressConvention eConv, + sal_Int32& nOffset, + sal_Unicode cSeperator, + sal_Unicode cQuote ) +{ + ScRange aScRange; + sal_Bool bResult(sal_False); + if( GetRangeFromString( aScRange, rRangeStr, pDocument, eConv, nOffset, cSeperator, cQuote ) && (nOffset >= 0) ) + { + rArea.nTab = aScRange.aStart.Tab(); + rArea.nColStart = aScRange.aStart.Col(); + rArea.nRowStart = aScRange.aStart.Row(); + rArea.nColEnd = aScRange.aEnd.Col(); + rArea.nRowEnd = aScRange.aEnd.Row(); + bResult = sal_True; + } + return bResult; +} + + +//___________________________________________________________________ + +sal_Bool ScRangeStringConverter::GetAddressFromString( + table::CellAddress& rAddress, + const OUString& rAddressStr, + const ScDocument* pDocument, + FormulaGrammar::AddressConvention eConv, + sal_Int32& nOffset, + sal_Unicode cSeperator, + sal_Unicode cQuote ) +{ + ScAddress aScAddress; + sal_Bool bResult(sal_False); + if( GetAddressFromString( aScAddress, rAddressStr, pDocument, eConv, nOffset, cSeperator, cQuote ) && (nOffset >= 0) ) + { + ScUnoConversion::FillApiAddress( rAddress, aScAddress ); + bResult = sal_True; + } + return bResult; +} + +sal_Bool ScRangeStringConverter::GetRangeFromString( + table::CellRangeAddress& rRange, + const OUString& rRangeStr, + const ScDocument* pDocument, + FormulaGrammar::AddressConvention eConv, + sal_Int32& nOffset, + sal_Unicode cSeperator, + sal_Unicode cQuote ) +{ + ScRange aScRange; + sal_Bool bResult(sal_False); + if( GetRangeFromString( aScRange, rRangeStr, pDocument, eConv, nOffset, cSeperator, cQuote ) && (nOffset >= 0) ) + { + ScUnoConversion::FillApiRange( rRange, aScRange ); + bResult = sal_True; + } + return bResult; +} + +sal_Bool ScRangeStringConverter::GetRangeListFromString( + uno::Sequence< table::CellRangeAddress >& rRangeSeq, + const OUString& rRangeListStr, + const ScDocument* pDocument, + FormulaGrammar::AddressConvention eConv, + sal_Unicode cSeperator, + sal_Unicode cQuote ) +{ + sal_Bool bRet = sal_True; + DBG_ASSERT( rRangeListStr.getLength(), "ScXMLConverter::GetRangeListFromString - empty string!" ); + table::CellRangeAddress aRange; + sal_Int32 nOffset = 0; + while( nOffset >= 0 ) + { + if( GetRangeFromString( aRange, rRangeListStr, pDocument, eConv, nOffset, cSeperator, cQuote ) && (nOffset >= 0) ) + { + rRangeSeq.realloc( rRangeSeq.getLength() + 1 ); + rRangeSeq[ rRangeSeq.getLength() - 1 ] = aRange; + } + else + bRet = sal_False; + } + return bRet; +} + + +//___________________________________________________________________ + +void ScRangeStringConverter::GetStringFromAddress( + OUString& rString, + const ScAddress& rAddress, + const ScDocument* pDocument, + FormulaGrammar::AddressConvention eConv, + sal_Unicode cSeperator, + sal_Bool bAppendStr, + sal_uInt16 nFormatFlags ) +{ + if (pDocument && pDocument->HasTable(rAddress.Tab())) + { + String sAddress; + rAddress.Format( sAddress, nFormatFlags, (ScDocument*) pDocument, eConv ); + AssignString( rString, sAddress, bAppendStr, cSeperator ); + } +} + +void ScRangeStringConverter::GetStringFromRange( + OUString& rString, + const ScRange& rRange, + const ScDocument* pDocument, + FormulaGrammar::AddressConvention eConv, + sal_Unicode cSeperator, + sal_Bool bAppendStr, + sal_uInt16 nFormatFlags ) +{ + if (pDocument && pDocument->HasTable(rRange.aStart.Tab())) + { + ScAddress aStartAddress( rRange.aStart ); + ScAddress aEndAddress( rRange.aEnd ); + String sStartAddress; + String sEndAddress; + aStartAddress.Format( sStartAddress, nFormatFlags, (ScDocument*) pDocument, eConv ); + aEndAddress.Format( sEndAddress, nFormatFlags, (ScDocument*) pDocument, eConv ); + OUString sOUStartAddress( sStartAddress ); + sOUStartAddress += OUString(':'); + sOUStartAddress += OUString( sEndAddress ); + AssignString( rString, sOUStartAddress, bAppendStr, cSeperator ); + } +} + +void ScRangeStringConverter::GetStringFromRangeList( + OUString& rString, + const ScRangeList* pRangeList, + const ScDocument* pDocument, + FormulaGrammar::AddressConvention eConv, + sal_Unicode cSeperator, + sal_uInt16 nFormatFlags ) +{ + OUString sRangeListStr; + if( pRangeList ) + { + sal_Int32 nCount = pRangeList->Count(); + for( sal_Int32 nIndex = 0; nIndex < nCount; nIndex++ ) + { + const ScRange* pRange = pRangeList->GetObject( nIndex ); + if( pRange ) + GetStringFromRange( sRangeListStr, *pRange, pDocument, eConv, cSeperator, sal_True, nFormatFlags ); + } + } + rString = sRangeListStr; +} + + +//___________________________________________________________________ + +void ScRangeStringConverter::GetStringFromArea( + OUString& rString, + const ScArea& rArea, + const ScDocument* pDocument, + FormulaGrammar::AddressConvention eConv, + sal_Unicode cSeperator, + sal_Bool bAppendStr, + sal_uInt16 nFormatFlags ) +{ + ScRange aRange( rArea.nColStart, rArea.nRowStart, rArea.nTab, rArea.nColEnd, rArea.nRowEnd, rArea.nTab ); + GetStringFromRange( rString, aRange, pDocument, eConv, cSeperator, bAppendStr, nFormatFlags ); +} + + +//___________________________________________________________________ + +void ScRangeStringConverter::GetStringFromAddress( + OUString& rString, + const table::CellAddress& rAddress, + const ScDocument* pDocument, + FormulaGrammar::AddressConvention eConv, + sal_Unicode cSeperator, + sal_Bool bAppendStr, + sal_uInt16 nFormatFlags ) +{ + ScAddress aScAddress( static_cast<SCCOL>(rAddress.Column), static_cast<SCROW>(rAddress.Row), rAddress.Sheet ); + GetStringFromAddress( rString, aScAddress, pDocument, eConv, cSeperator, bAppendStr, nFormatFlags ); +} + +void ScRangeStringConverter::GetStringFromRange( + OUString& rString, + const table::CellRangeAddress& rRange, + const ScDocument* pDocument, + FormulaGrammar::AddressConvention eConv, + sal_Unicode cSeperator, + sal_Bool bAppendStr, + sal_uInt16 nFormatFlags ) +{ + ScRange aScRange( static_cast<SCCOL>(rRange.StartColumn), static_cast<SCROW>(rRange.StartRow), rRange.Sheet, + static_cast<SCCOL>(rRange.EndColumn), static_cast<SCROW>(rRange.EndRow), rRange.Sheet ); + GetStringFromRange( rString, aScRange, pDocument, eConv, cSeperator, bAppendStr, nFormatFlags ); +} + +void ScRangeStringConverter::GetStringFromRangeList( + OUString& rString, + const uno::Sequence< table::CellRangeAddress >& rRangeSeq, + const ScDocument* pDocument, + FormulaGrammar::AddressConvention eConv, + sal_Unicode cSeperator, + sal_uInt16 nFormatFlags ) +{ + OUString sRangeListStr; + sal_Int32 nCount = rRangeSeq.getLength(); + for( sal_Int32 nIndex = 0; nIndex < nCount; nIndex++ ) + { + const table::CellRangeAddress& rRange = rRangeSeq[ nIndex ]; + GetStringFromRange( sRangeListStr, rRange, pDocument, eConv, cSeperator, sal_True, nFormatFlags ); + } + rString = sRangeListStr; +} + +static void lcl_appendCellAddress( + rtl::OUStringBuffer& rBuf, ScDocument* pDoc, const ScAddress& rCell, + const ScAddress::ExternalInfo& rExtInfo) +{ + if (rExtInfo.mbExternal) + { + ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager(); + const String* pFilePath = pRefMgr->getExternalFileName(rExtInfo.mnFileId, true); + if (!pFilePath) + return; + + sal_Unicode cQuote = '\''; + rBuf.append(cQuote); + rBuf.append(*pFilePath); + rBuf.append(cQuote); + rBuf.append(sal_Unicode('#')); + rBuf.append(sal_Unicode('$')); + ScRangeStringConverter::AppendTableName(rBuf, rExtInfo.maTabName); + rBuf.append(sal_Unicode('.')); + + String aAddr; + rCell.Format(aAddr, SCA_ABS, NULL, ::formula::FormulaGrammar::CONV_OOO); + rBuf.append(aAddr); + } + else + { + String aAddr; + rCell.Format(aAddr, SCA_ABS_3D, pDoc, ::formula::FormulaGrammar::CONV_OOO); + rBuf.append(aAddr); + } +} + +static void lcl_appendCellRangeAddress( + rtl::OUStringBuffer& rBuf, ScDocument* pDoc, const ScAddress& rCell1, const ScAddress& rCell2, + const ScAddress::ExternalInfo& rExtInfo1, const ScAddress::ExternalInfo& rExtInfo2) +{ + if (rExtInfo1.mbExternal) + { + DBG_ASSERT(rExtInfo2.mbExternal, "2nd address is not external!?"); + DBG_ASSERT(rExtInfo1.mnFileId == rExtInfo2.mnFileId, "File IDs do not match between 1st and 2nd addresses."); + + ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager(); + const String* pFilePath = pRefMgr->getExternalFileName(rExtInfo1.mnFileId, true); + if (!pFilePath) + return; + + sal_Unicode cQuote = '\''; + rBuf.append(cQuote); + rBuf.append(*pFilePath); + rBuf.append(cQuote); + rBuf.append(sal_Unicode('#')); + rBuf.append(sal_Unicode('$')); + ScRangeStringConverter::AppendTableName(rBuf, rExtInfo1.maTabName); + rBuf.append(sal_Unicode('.')); + + String aAddr; + rCell1.Format(aAddr, SCA_ABS, NULL, ::formula::FormulaGrammar::CONV_OOO); + rBuf.append(aAddr); + + rBuf.appendAscii(":"); + + if (rExtInfo1.maTabName != rExtInfo2.maTabName) + { + rBuf.append(sal_Unicode('$')); + ScRangeStringConverter::AppendTableName(rBuf, rExtInfo2.maTabName); + rBuf.append(sal_Unicode('.')); + } + + rCell2.Format(aAddr, SCA_ABS, NULL, ::formula::FormulaGrammar::CONV_OOO); + rBuf.append(aAddr); + } + else + { + ScRange aRange; + aRange.aStart = rCell1; + aRange.aEnd = rCell2; + String aAddr; + aRange.Format(aAddr, SCR_ABS_3D, pDoc, ::formula::FormulaGrammar::CONV_OOO); + rBuf.append(aAddr); + } +} + +void ScRangeStringConverter::GetStringFromXMLRangeString( OUString& rString, const OUString& rXMLRange, ScDocument* pDoc ) +{ + const sal_Unicode cSep = ' '; + const sal_Unicode cQuote = '\''; + + OUStringBuffer aRetStr; + sal_Int32 nOffset = 0; + bool bFirst = true; + + while (nOffset >= 0) + { + OUString aToken; + GetTokenByOffset(aToken, rXMLRange, nOffset, cSep, cQuote); + if (nOffset < 0) + break; + + sal_Int32 nSepPos = IndexOf(aToken, ':', 0, cQuote); + if (nSepPos >= 0) + { + // Cell range + OUString aBeginCell = aToken.copy(0, nSepPos); + OUString aEndCell = aToken.copy(nSepPos+1); + + if (!aBeginCell.getLength() || !aEndCell.getLength()) + // both cell addresses must exist for this to work. + continue; + + sal_Int32 nEndCellDotPos = aEndCell.indexOf('.'); + if (nEndCellDotPos <= 0) + { + // initialize buffer with table name... + sal_Int32 nDotPos = IndexOf(aBeginCell, sal_Unicode('.'), 0, cQuote); + OUStringBuffer aBuf = aBeginCell.copy(0, nDotPos); + + if (nEndCellDotPos == 0) + { + // workaround for old syntax (probably pre-chart2 age?) + // e.g. Sheet1.A1:.B2 + aBuf.append(aEndCell); + } + else if (nEndCellDotPos < 0) + { + // sheet name in the end cell is omitted (e.g. Sheet2.A1:B2). + aBuf.append(sal_Unicode('.')); + aBuf.append(aEndCell); + } + aEndCell = aBuf.makeStringAndClear(); + } + + ScAddress::ExternalInfo aExtInfo1, aExtInfo2; + ScAddress aCell1, aCell2; + rtl::OUString aBuf; + USHORT nRet = aCell1.Parse(aBeginCell, pDoc, FormulaGrammar::CONV_OOO, &aExtInfo1); + if ((nRet & SCA_VALID) != SCA_VALID) + // first cell is invalid. + continue; + + nRet = aCell2.Parse(aEndCell, pDoc, FormulaGrammar::CONV_OOO, &aExtInfo2); + if ((nRet & SCA_VALID) != SCA_VALID) + // second cell is invalid. + continue; + + if (aExtInfo1.mnFileId != aExtInfo2.mnFileId || aExtInfo1.mbExternal != aExtInfo2.mbExternal) + // external info inconsistency. + continue; + + // All looks good! + + if (bFirst) + bFirst = false; + else + aRetStr.appendAscii(";"); + + lcl_appendCellRangeAddress(aRetStr, pDoc, aCell1, aCell2, aExtInfo1, aExtInfo2); + } + else + { + // Chart always saves ranges using CONV_OOO convention. + ScAddress::ExternalInfo aExtInfo; + ScAddress aCell; + USHORT nRet = aCell.Parse(aToken, pDoc, ::formula::FormulaGrammar::CONV_OOO, &aExtInfo); + if ((nRet & SCA_VALID) != SCA_VALID) + continue; + + // Looks good! + + if (bFirst) + bFirst = false; + else + aRetStr.appendAscii(";"); + + lcl_appendCellAddress(aRetStr, pDoc, aCell, aExtInfo); + } + } + + rString = aRetStr.makeStringAndClear(); +} + +//======================================================================== + +ScArea::ScArea( SCTAB tab, + SCCOL colStart, SCROW rowStart, + SCCOL colEnd, SCROW rowEnd ) : + nTab ( tab ), + nColStart( colStart ), nRowStart( rowStart ), + nColEnd ( colEnd ), nRowEnd ( rowEnd ) +{ +} + +//------------------------------------------------------------------------ + +ScArea::ScArea( const ScArea& r ) : + nTab ( r.nTab ), + nColStart( r.nColStart ), nRowStart( r.nRowStart ), + nColEnd ( r.nColEnd ), nRowEnd ( r.nRowEnd ) +{ +} + +//------------------------------------------------------------------------ + +ScArea& ScArea::operator=( const ScArea& r ) +{ + nTab = r.nTab; + nColStart = r.nColStart; + nRowStart = r.nRowStart; + nColEnd = r.nColEnd; + nRowEnd = r.nRowEnd; + return *this; +} + +//------------------------------------------------------------------------ + +BOOL ScArea::operator==( const ScArea& r ) const +{ + return ( (nTab == r.nTab) + && (nColStart == r.nColStart) + && (nRowStart == r.nRowStart) + && (nColEnd == r.nColEnd) + && (nRowEnd == r.nRowEnd) ); +} + +//------------------------------------------------------------------------ + +ScAreaNameIterator::ScAreaNameIterator( ScDocument* pDoc ) : + aStrNoName( ScGlobal::GetRscString(STR_DB_NONAME) ) +{ + pRangeName = pDoc->GetRangeName(); + pDBCollection = pDoc->GetDBCollection(); + nPos = 0; + bFirstPass = TRUE; +} + +BOOL ScAreaNameIterator::Next( String& rName, ScRange& rRange ) +{ + for (;;) + { + if ( bFirstPass ) // erst Bereichsnamen + { + if ( pRangeName && nPos < pRangeName->GetCount() ) + { + ScRangeData* pData = (*pRangeName)[nPos++]; + if ( pData && pData->IsValidReference(rRange) ) + { + rName = pData->GetName(); + return TRUE; // gefunden + } + } + else + { + bFirstPass = FALSE; + nPos = 0; + } + } + if ( !bFirstPass ) // dann DB-Bereiche + { + if ( pDBCollection && nPos < pDBCollection->GetCount() ) + { + ScDBData* pData = (*pDBCollection)[nPos++]; + if (pData && pData->GetName() != aStrNoName) + { + pData->GetArea( rRange ); + rName = pData->GetName(); + return TRUE; // gefunden + } + } + else + return FALSE; // gibt nichts mehr + } + } +} + + + + |