/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_sc.hxx" // INCLUDE --------------------------------------------------------------- #include #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; //------------------------------------------------------------------------ sal_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. sal_Bool nSuccess = sal_False; sal_uInt16 nPointPos = rAreaStr.Search('.'); sal_uInt16 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. sal_uInt16 nColonPos = theAreaStr.Search(':'); if ( nColonPos != STRING_NOTFOUND ) aPosStr = theAreaStr.Copy( 0, nColonPos ); // ':' nicht mitkopieren else aPosStr = theAreaStr; thePosStr = aPosStr; } //------------------------------------------------------------------------ sal_Bool ScRangeUtil::IsAbsTabArea( const String& rAreaStr, ScDocument* pDoc, ScArea*** pppAreas, sal_uInt16* pAreaCount, sal_Bool /* bAcceptCellRef */, ScAddress::Details const & rDetails ) const { DBG_ASSERT( pDoc, "Kein Dokument uebergeben!" ); if ( !pDoc ) return sal_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 == sal_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! */ sal_Bool bStrOk = sal_False; String aTempAreaStr(rAreaStr); String aStartPosStr; String aEndPosStr; if ( STRING_NOTFOUND == aTempAreaStr.Search(':') ) { aTempAreaStr.Append(':'); aTempAreaStr.Append(rAreaStr); } sal_uInt16 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( sal_False ); aStartPos.SetRelRow( sal_False ); aStartPos.SetRelTab( sal_False ); aEndPos.SetRelCol( sal_False ); aEndPos.SetRelRow( sal_False ); aEndPos.SetRelTab( sal_False ); bStrOk = sal_True; if ( pppAreas && pAreaCount ) // Array zurueckgegeben? { SCTAB nStartTab = aStartPos.Tab(); SCTAB nEndTab = aEndPos.Tab(); sal_uInt16 nTabCount = static_cast(nEndTab-nStartTab+1); ScArea** theAreas = new ScArea*[nTabCount]; SCTAB nTab = 0; sal_uInt16 i = 0; ScArea theArea( 0, aStartPos.Col(), aStartPos.Row(), aEndPos.Col(), aEndPos.Row() ); nTab = nStartTab; for ( i=0; inTab = nTab; nTab++; } *pppAreas = theAreas; *pAreaCount = nTabCount; } } } } return bStrOk; } //------------------------------------------------------------------------ sal_Bool ScRangeUtil::IsAbsArea( const String& rAreaStr, ScDocument* pDoc, SCTAB nTab, String* pCompleteStr, ScRefAddress* pStartPos, ScRefAddress* pEndPos, ScAddress::Details const & rDetails ) const { sal_Bool bIsAbsArea = sal_False; ScRefAddress startPos; ScRefAddress endPos; bIsAbsArea = ConvertDoubleRef( pDoc, rAreaStr, nTab, startPos, endPos, rDetails ); if ( bIsAbsArea ) { startPos.SetRelCol( sal_False ); startPos.SetRelRow( sal_False ); startPos.SetRelTab( sal_False ); endPos .SetRelCol( sal_False ); endPos .SetRelRow( sal_False ); endPos .SetRelTab( sal_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; } //------------------------------------------------------------------------ sal_Bool ScRangeUtil::IsAbsPos( const String& rPosStr, ScDocument* pDoc, SCTAB nTab, String* pCompleteStr, ScRefAddress* pPosTripel, ScAddress::Details const & rDetails ) const { sal_Bool bIsAbsPos = sal_False; ScRefAddress thePos; bIsAbsPos = ConvertSingleRef( pDoc, rPosStr, nTab, thePos, rDetails ); thePos.SetRelCol( sal_False ); thePos.SetRelRow( sal_False ); thePos.SetRelTab( sal_False ); if ( bIsAbsPos ) { if ( pPosTripel ) *pPosTripel = thePos; if ( pCompleteStr ) *pCompleteStr = thePos.GetRefString( pDoc, MAXTAB+1, rDetails ); } return bIsAbsPos; } //------------------------------------------------------------------------ sal_Bool ScRangeUtil::MakeRangeFromName ( const String& rName, ScDocument* pDoc, SCTAB nCurTab, ScRange& rRange, RutlNameScope eScope, ScAddress::Details const & rDetails ) const { sal_Bool bResult=sal_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()); sal_uInt16 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 = sal_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 = sal_True; } } } } else if( eScope==RUTL_DBASE ) { ScDBCollection& rDbNames = *(pDoc->GetDBCollection()); sal_uInt16 nAt = 0; if ( rDbNames.SearchName( rName, nAt ) ) { ScDBData* pData = rDbNames[nAt]; pData->GetArea( nTab, nColStart, nRowStart, nColEnd, nRowEnd ); bResult = sal_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(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 (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 (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(pDocument), eConv) & SCA_VALID) == SCA_VALID) && ((rRange.aEnd.Parse( aUIString.Copy((xub_StrLen)nIndex+1), const_cast(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(rAddress.Column), static_cast(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(rRange.StartColumn), static_cast(rRange.StartRow), rRange.Sheet, static_cast(rRange.EndColumn), static_cast(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; sal_uInt16 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; sal_uInt16 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; } //------------------------------------------------------------------------ sal_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 ) { pRangeName = pDoc->GetRangeName(); pDBCollection = pDoc->GetDBCollection(); nPos = 0; bFirstPass = sal_True; } sal_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 sal_True; // gefunden } } else { bFirstPass = sal_False; nPos = 0; } } if ( !bFirstPass ) // dann DB-Bereiche { if ( pDBCollection && nPos < pDBCollection->GetCount() ) { ScDBData* pData = (*pDBCollection)[nPos++]; if ( pData && !pData->IsInternalUnnamed() && !pData->IsInternalForAutoFilter() ) { pData->GetArea( rRange ); rName = pData->GetName(); return sal_True; // gefunden } } else return sal_False; // gibt nichts mehr } } }