diff options
Diffstat (limited to 'sc/source/core/tool/dbcolect.cxx')
-rw-r--r-- | sc/source/core/tool/dbcolect.cxx | 1025 |
1 files changed, 1025 insertions, 0 deletions
diff --git a/sc/source/core/tool/dbcolect.cxx b/sc/source/core/tool/dbcolect.cxx new file mode 100644 index 000000000000..d5fe2701f459 --- /dev/null +++ b/sc/source/core/tool/dbcolect.cxx @@ -0,0 +1,1025 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 <tools/debug.hxx> +#include <unotools/transliterationwrapper.hxx> + +#include "dbcolect.hxx" +#include "global.hxx" +#include "globalnames.hxx" +#include "refupdat.hxx" +#include "rechead.hxx" +#include "document.hxx" +#include "queryparam.hxx" +#include "globstr.hrc" +#include "subtotalparam.hxx" + +#include <memory> + +using ::std::unary_function; +using ::std::for_each; +using ::std::find_if; +using ::std::remove_if; + +//--------------------------------------------------------------------------------------- + +ScDBData::ScDBData( const String& rName, + SCTAB nTab, + SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, + bool bByR, bool bHasH) : + aName (rName), + nTable (nTab), + nStartCol (nCol1), + nStartRow (nRow1), + nEndCol (nCol2), + nEndRow (nRow2), + bByRow (bByR), + bHasHeader (bHasH), + bDoSize (false), + bKeepFmt (false), + bStripData (false), + bIsAdvanced (false), + bDBSelection(false), + nIndex (0), + bAutoFilter (false), + bModified (false) +{ + sal_uInt16 i; + + ScSortParam aSortParam; + ScQueryParam aQueryParam; + ScImportParam aImportParam; + + for (i=0; i<MAXQUERY; i++) + pQueryStr[i] = new String; + + SetSortParam( aSortParam ); + SetQueryParam( aQueryParam ); + SetImportParam( aImportParam ); +} + +ScDBData::ScDBData( const ScDBData& rData ) : + ScDataObject(), + ScRefreshTimer ( rData ), + aName (rData.aName), + nTable (rData.nTable), + nStartCol (rData.nStartCol), + nStartRow (rData.nStartRow), + nEndCol (rData.nEndCol), + nEndRow (rData.nEndRow), + bByRow (rData.bByRow), + bHasHeader (rData.bHasHeader), + bDoSize (rData.bDoSize), + bKeepFmt (rData.bKeepFmt), + bStripData (rData.bStripData), + bSortCaseSens (rData.bSortCaseSens), + bSortNaturalSort (rData.bSortNaturalSort), + bIncludePattern (rData.bIncludePattern), + bSortInplace (rData.bSortInplace), + bSortUserDef (rData.bSortUserDef), + nSortUserIndex (rData.nSortUserIndex), + nSortDestTab (rData.nSortDestTab), + nSortDestCol (rData.nSortDestCol), + nSortDestRow (rData.nSortDestRow), + aSortLocale (rData.aSortLocale), + aSortAlgorithm (rData.aSortAlgorithm), + bQueryInplace (rData.bQueryInplace), + bQueryCaseSens (rData.bQueryCaseSens), + bQueryRegExp (rData.bQueryRegExp), + bQueryDuplicate (rData.bQueryDuplicate), + nQueryDestTab (rData.nQueryDestTab), + nQueryDestCol (rData.nQueryDestCol), + nQueryDestRow (rData.nQueryDestRow), + bIsAdvanced (rData.bIsAdvanced), + aAdvSource (rData.aAdvSource), + maSubTotal (rData.maSubTotal), + bDBImport (rData.bDBImport), + aDBName (rData.aDBName), + aDBStatement (rData.aDBStatement), + bDBNative (rData.bDBNative), + bDBSelection (rData.bDBSelection), + bDBSql (rData.bDBSql), + nDBType (rData.nDBType), + nIndex (rData.nIndex), + bAutoFilter (rData.bAutoFilter), + bModified (rData.bModified) +{ + sal_uInt16 i; + + for (i=0; i<MAXSORT; i++) + { + bDoSort[i] = rData.bDoSort[i]; + nSortField[i] = rData.nSortField[i]; + bAscending[i] = rData.bAscending[i]; + } + for (i=0; i<MAXQUERY; i++) + { + bDoQuery[i] = rData.bDoQuery[i]; + nQueryField[i] = rData.nQueryField[i]; + eQueryOp[i] = rData.eQueryOp[i]; + bQueryByString[i] = rData.bQueryByString[i]; + bQueryByDate[i] = rData.bQueryByDate[i]; + pQueryStr[i] = new String( *(rData.pQueryStr[i]) ); + nQueryVal[i] = rData.nQueryVal[i]; + eQueryConnect[i] = rData.eQueryConnect[i]; + } +} + +ScDBData& ScDBData::operator= (const ScDBData& rData) +{ + sal_uInt16 i; + + ScRefreshTimer::operator=( rData ); + aName = rData.aName; + nTable = rData.nTable; + nStartCol = rData.nStartCol; + nStartRow = rData.nStartRow; + nEndCol = rData.nEndCol; + nEndRow = rData.nEndRow; + bByRow = rData.bByRow; + bHasHeader = rData.bHasHeader; + bDoSize = rData.bDoSize; + bKeepFmt = rData.bKeepFmt; + bStripData = rData.bStripData; + bSortCaseSens = rData.bSortCaseSens; + bSortNaturalSort = rData.bSortNaturalSort; + bIncludePattern = rData.bIncludePattern; + bSortInplace = rData.bSortInplace; + nSortDestTab = rData.nSortDestTab; + nSortDestCol = rData.nSortDestCol; + nSortDestRow = rData.nSortDestRow; + bSortUserDef = rData.bSortUserDef; + nSortUserIndex = rData.nSortUserIndex; + aSortLocale = rData.aSortLocale; + aSortAlgorithm = rData.aSortAlgorithm; + bQueryInplace = rData.bQueryInplace; + bQueryCaseSens = rData.bQueryCaseSens; + bQueryRegExp = rData.bQueryRegExp; + bQueryDuplicate = rData.bQueryDuplicate; + nQueryDestTab = rData.nQueryDestTab; + nQueryDestCol = rData.nQueryDestCol; + nQueryDestRow = rData.nQueryDestRow; + bIsAdvanced = rData.bIsAdvanced; + maSubTotal = rData.maSubTotal; + aAdvSource = rData.aAdvSource; + bDBImport = rData.bDBImport; + aDBName = rData.aDBName; + aDBStatement = rData.aDBStatement; + bDBNative = rData.bDBNative; + bDBSelection = rData.bDBSelection; + bDBSql = rData.bDBSql; + nDBType = rData.nDBType; + nIndex = rData.nIndex; + bAutoFilter = rData.bAutoFilter; + + for (i=0; i<MAXSORT; i++) + { + bDoSort[i] = rData.bDoSort[i]; + nSortField[i] = rData.nSortField[i]; + bAscending[i] = rData.bAscending[i]; + } + for (i=0; i<MAXQUERY; i++) + { + bDoQuery[i] = rData.bDoQuery[i]; + nQueryField[i] = rData.nQueryField[i]; + eQueryOp[i] = rData.eQueryOp[i]; + bQueryByString[i] = rData.bQueryByString[i]; + bQueryByDate[i] = rData.bQueryByDate[i]; + *pQueryStr[i] = *rData.pQueryStr[i]; + nQueryVal[i] = rData.nQueryVal[i]; + eQueryConnect[i] = rData.eQueryConnect[i]; + } + + return *this; +} + +SCTAB ScDBData::GetTable() const +{ + return nTable; +} + +bool ScDBData::operator== (const ScDBData& rData) const +{ + // Daten, die nicht in den Params sind + + if ( nTable != rData.nTable || + bDoSize != rData.bDoSize || + bKeepFmt != rData.bKeepFmt || + bIsAdvanced!= rData.bIsAdvanced|| + bStripData != rData.bStripData || +// SAB: I think this should be here, but I don't want to break something +// bAutoFilter!= rData.bAutoFilter|| + ScRefreshTimer::operator!=( rData ) + ) + return false; + + if ( bIsAdvanced && aAdvSource != rData.aAdvSource ) + return false; + + ScSortParam aSort1, aSort2; + GetSortParam(aSort1); + rData.GetSortParam(aSort2); + if (!(aSort1 == aSort2)) + return false; + + ScQueryParam aQuery1, aQuery2; + GetQueryParam(aQuery1); + rData.GetQueryParam(aQuery2); + if (!(aQuery1 == aQuery2)) + return false; + + ScSubTotalParam aSubTotal1, aSubTotal2; + GetSubTotalParam(aSubTotal1); + rData.GetSubTotalParam(aSubTotal2); + if (!(aSubTotal1 == aSubTotal2)) + return false; + + ScImportParam aImport1, aImport2; + GetImportParam(aImport1); + rData.GetImportParam(aImport2); + if (!(aImport1 == aImport2)) + return false; + + return true; +} + +ScDBData::~ScDBData() +{ + StopRefreshTimer(); + sal_uInt16 i; + + for (i=0; i<MAXQUERY; i++) + delete pQueryStr[i]; +} + + +String ScDBData::GetSourceString() const +{ + String aVal; + if (bDBImport) + { + aVal = aDBName; + aVal += '/'; + aVal += aDBStatement; + } + return aVal; +} + +String ScDBData::GetOperations() const +{ + String aVal; + if (bDoQuery[0]) + aVal = ScGlobal::GetRscString(STR_OPERATION_FILTER); + + if (bDoSort[0]) + { + if (aVal.Len()) + aVal.AppendAscii( RTL_CONSTASCII_STRINGPARAM(", ") ); + aVal += ScGlobal::GetRscString(STR_OPERATION_SORT); + } + + if (maSubTotal.bGroupActive[0] && !maSubTotal.bRemoveOnly) + { + if (aVal.Len()) + aVal.AppendAscii( RTL_CONSTASCII_STRINGPARAM(", ") ); + aVal += ScGlobal::GetRscString(STR_OPERATION_SUBTOTAL); + } + + if (!aVal.Len()) + aVal = ScGlobal::GetRscString(STR_OPERATION_NONE); + + return aVal; +} + +void ScDBData::GetArea(SCTAB& rTab, SCCOL& rCol1, SCROW& rRow1, SCCOL& rCol2, SCROW& rRow2) const +{ + rTab = nTable; + rCol1 = nStartCol; + rRow1 = nStartRow; + rCol2 = nEndCol; + rRow2 = nEndRow; +} + +void ScDBData::GetArea(ScRange& rRange) const +{ + SCROW nNewEndRow = nEndRow; + rRange = ScRange( nStartCol, nStartRow, nTable, nEndCol, nNewEndRow, nTable ); +} + +void ScDBData::SetArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) +{ + nTable = nTab; + nStartCol = nCol1; + nStartRow = nRow1; + nEndCol = nCol2; + nEndRow = nRow2; +} + +void ScDBData::MoveTo(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) +{ + sal_uInt16 i; + long nDifX = ((long) nCol1) - ((long) nStartCol); + long nDifY = ((long) nRow1) - ((long) nStartRow); + + long nSortDif = bByRow ? nDifX : nDifY; + long nSortEnd = bByRow ? static_cast<long>(nCol2) : static_cast<long>(nRow2); + + for (i=0; i<MAXSORT; i++) + { + nSortField[i] += nSortDif; + if (nSortField[i] > nSortEnd) + { + nSortField[i] = 0; + bDoSort[i] = false; + } + } + for (i=0; i<MAXQUERY; i++) + { + nQueryField[i] += nDifX; + if (nQueryField[i] > nCol2) + { + nQueryField[i] = 0; + bDoQuery[i] = false; + } + } + for (i=0; i<MAXSUBTOTAL; i++) + { + maSubTotal.nField[i] = sal::static_int_cast<SCCOL>( maSubTotal.nField[i] + nDifX ); + if (maSubTotal.nField[i] > nCol2) + { + maSubTotal.nField[i] = 0; + maSubTotal.bGroupActive[i] = false; + } + } + + SetArea( nTab, nCol1, nRow1, nCol2, nRow2 ); +} + +void ScDBData::GetSortParam( ScSortParam& rSortParam ) const +{ + rSortParam.nCol1 = nStartCol; + rSortParam.nRow1 = nStartRow; + rSortParam.nCol2 = nEndCol; + rSortParam.nRow2 = nEndRow; + rSortParam.bByRow = bByRow; + rSortParam.bHasHeader = bHasHeader; + rSortParam.bCaseSens = bSortCaseSens; + rSortParam.bNaturalSort = bSortNaturalSort; + rSortParam.bInplace = bSortInplace; + rSortParam.nDestTab = nSortDestTab; + rSortParam.nDestCol = nSortDestCol; + rSortParam.nDestRow = nSortDestRow; + rSortParam.bIncludePattern = bIncludePattern; + rSortParam.bUserDef = bSortUserDef; + rSortParam.nUserIndex = nSortUserIndex; + for (sal_uInt16 i=0; i<MAXSORT; i++) + { + rSortParam.bDoSort[i] = bDoSort[i]; + rSortParam.nField[i] = nSortField[i]; + rSortParam.bAscending[i] = bAscending[i]; + } + rSortParam.aCollatorLocale = aSortLocale; + rSortParam.aCollatorAlgorithm = aSortAlgorithm; +} + +void ScDBData::SetSortParam( const ScSortParam& rSortParam ) +{ + bSortCaseSens = rSortParam.bCaseSens; + bSortNaturalSort = rSortParam.bNaturalSort; + bIncludePattern = rSortParam.bIncludePattern; + bSortInplace = rSortParam.bInplace; + nSortDestTab = rSortParam.nDestTab; + nSortDestCol = rSortParam.nDestCol; + nSortDestRow = rSortParam.nDestRow; + bSortUserDef = rSortParam.bUserDef; + nSortUserIndex = rSortParam.nUserIndex; + for (sal_uInt16 i=0; i<MAXSORT; i++) + { + bDoSort[i] = rSortParam.bDoSort[i]; + nSortField[i] = rSortParam.nField[i]; + bAscending[i] = rSortParam.bAscending[i]; + } + aSortLocale = rSortParam.aCollatorLocale; + aSortAlgorithm = rSortParam.aCollatorAlgorithm; + + //#98317#; set the orientation + bByRow = rSortParam.bByRow; +} + +void ScDBData::GetQueryParam( ScQueryParam& rQueryParam ) const +{ + rQueryParam.nCol1 = nStartCol; + rQueryParam.nRow1 = nStartRow; + rQueryParam.nCol2 = nEndCol; + rQueryParam.nRow2 = nEndRow; + rQueryParam.nTab = nTable; + rQueryParam.bByRow = bByRow; + rQueryParam.bHasHeader = bHasHeader; + rQueryParam.bInplace = bQueryInplace; + rQueryParam.bCaseSens = bQueryCaseSens; + rQueryParam.bRegExp = bQueryRegExp; + rQueryParam.bDuplicate = bQueryDuplicate; + rQueryParam.nDestTab = nQueryDestTab; + rQueryParam.nDestCol = nQueryDestCol; + rQueryParam.nDestRow = nQueryDestRow; + + rQueryParam.Resize( MAXQUERY ); + for (SCSIZE i=0; i<MAXQUERY; i++) + { + ScQueryEntry& rEntry = rQueryParam.GetEntry(i); + + rEntry.bDoQuery = bDoQuery[i]; + rEntry.nField = nQueryField[i]; + rEntry.eOp = eQueryOp[i]; + rEntry.bQueryByString = bQueryByString[i]; + rEntry.bQueryByDate = bQueryByDate[i]; + *rEntry.pStr = *pQueryStr[i]; + rEntry.nVal = nQueryVal[i]; + rEntry.eConnect = eQueryConnect[i]; + } +} + +void ScDBData::SetQueryParam(const ScQueryParam& rQueryParam) +{ + DBG_ASSERT( rQueryParam.GetEntryCount() <= MAXQUERY || + !rQueryParam.GetEntry(MAXQUERY).bDoQuery, + "zuviele Eintraege bei ScDBData::SetQueryParam" ); + + // set bIsAdvanced to false for everything that is not from the + // advanced filter dialog + bIsAdvanced = false; + + bQueryInplace = rQueryParam.bInplace; + bQueryCaseSens = rQueryParam.bCaseSens; + bQueryRegExp = rQueryParam.bRegExp; + bQueryDuplicate = rQueryParam.bDuplicate; + nQueryDestTab = rQueryParam.nDestTab; + nQueryDestCol = rQueryParam.nDestCol; + nQueryDestRow = rQueryParam.nDestRow; + for (SCSIZE i=0; i<MAXQUERY; i++) + { + ScQueryEntry& rEntry = rQueryParam.GetEntry(i); + + bDoQuery[i] = rEntry.bDoQuery; + nQueryField[i] = rEntry.nField; + eQueryOp[i] = rEntry.eOp; + bQueryByString[i] = rEntry.bQueryByString; + bQueryByDate[i] = rEntry.bQueryByDate; + *pQueryStr[i] = *rEntry.pStr; + nQueryVal[i] = rEntry.nVal; + eQueryConnect[i] = rEntry.eConnect; + } +} + +void ScDBData::SetAdvancedQuerySource(const ScRange* pSource) +{ + if (pSource) + { + aAdvSource = *pSource; + bIsAdvanced = true; + } + else + bIsAdvanced = false; +} + +bool ScDBData::GetAdvancedQuerySource(ScRange& rSource) const +{ + rSource = aAdvSource; + return bIsAdvanced; +} + +void ScDBData::GetSubTotalParam(ScSubTotalParam& rSubTotalParam) const +{ + rSubTotalParam = maSubTotal; + + // Share the data range with the parent db data. The range in the subtotal + // param struct is not used. + rSubTotalParam.nCol1 = nStartCol; + rSubTotalParam.nRow1 = nStartRow; + rSubTotalParam.nCol2 = nEndCol; + rSubTotalParam.nRow2 = nEndRow; +} + +void ScDBData::SetSubTotalParam(const ScSubTotalParam& rSubTotalParam) +{ + maSubTotal = rSubTotalParam; +} + +void ScDBData::GetImportParam(ScImportParam& rImportParam) const +{ + rImportParam.nCol1 = nStartCol; + rImportParam.nRow1 = nStartRow; + rImportParam.nCol2 = nEndCol; + rImportParam.nRow2 = nEndRow; + + rImportParam.bImport = bDBImport; + rImportParam.aDBName = aDBName; + rImportParam.aStatement = aDBStatement; + rImportParam.bNative = bDBNative; + rImportParam.bSql = bDBSql; + rImportParam.nType = nDBType; +} + +void ScDBData::SetImportParam(const ScImportParam& rImportParam) +{ + bDBImport = rImportParam.bImport; + aDBName = rImportParam.aDBName; + aDBStatement = rImportParam.aStatement; + bDBNative = rImportParam.bNative; + bDBSql = rImportParam.bSql; + nDBType = rImportParam.nType; +} + +bool ScDBData::IsDBAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, bool bStartOnly) const +{ + if (nTab == nTable) + { + if ( bStartOnly ) + return ( nCol == nStartCol && nRow == nStartRow ); + else + return ( nCol >= nStartCol && nCol <= nEndCol && + nRow >= nStartRow && nRow <= nEndRow ); + } + + return false; +} + +bool ScDBData::IsDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) const +{ + return (bool)((nTab == nTable) + && (nCol1 == nStartCol) && (nRow1 == nStartRow) + && (nCol2 == nEndCol) && (nRow2 == nEndRow)); +} + +ScDataObject* ScDBData::Clone() const +{ + return new ScDBData(*this); +} + +void ScDBData::UpdateMoveTab(SCTAB nOldPos, SCTAB nNewPos) +{ + ScRange aRange; + GetArea( aRange ); + SCTAB nTab = aRange.aStart.Tab(); // hat nur eine Tabelle + + // anpassen wie die aktuelle Tabelle bei ScTablesHint (tabvwsh5.cxx) + + if ( nTab == nOldPos ) // verschobene Tabelle + nTab = nNewPos; + else if ( nOldPos < nNewPos ) // nach hinten verschoben + { + if ( nTab > nOldPos && nTab <= nNewPos ) // nachrueckender Bereich + --nTab; + } + else // nach vorne verschoben + { + if ( nTab >= nNewPos && nTab < nOldPos ) // nachrueckender Bereich + ++nTab; + } + + bool bChanged = ( nTab != aRange.aStart.Tab() ); + if (bChanged) + SetArea( nTab, aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aEnd.Col(),aRange.aEnd .Row() ); + + // MoveTo ist nicht noetig, wenn nur die Tabelle geaendert ist + + SetModified(bChanged); + +} + +void ScDBData::UpdateReference(ScDocument* pDoc, UpdateRefMode eUpdateRefMode, + SCCOL nCol1, SCROW nRow1, SCTAB nTab1, + SCCOL nCol2, SCROW nRow2, SCTAB nTab2, + SCsCOL nDx, SCsROW nDy, SCsTAB nDz) +{ + SCCOL theCol1; + SCROW theRow1; + SCTAB theTab1; + SCCOL theCol2; + SCROW theRow2; + SCTAB theTab2; + GetArea( theTab1, theCol1, theRow1, theCol2, theRow2 ); + theTab2 = theTab1; + + bool bDoUpdate = ScRefUpdate::Update( pDoc, eUpdateRefMode, + nCol1,nRow1,nTab1, nCol2,nRow2,nTab2, nDx,nDy,nDz, + theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 ) != UR_NOTHING; + if (bDoUpdate) + MoveTo( theTab1, theCol1, theRow1, theCol2, theRow2 ); + + ScRange aRangeAdvSource; + if ( GetAdvancedQuerySource(aRangeAdvSource) ) + { + aRangeAdvSource.GetVars( theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 ); + if ( ScRefUpdate::Update( pDoc, eUpdateRefMode, + nCol1,nRow1,nTab1, nCol2,nRow2,nTab2, nDx,nDy,nDz, + theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 ) ) + { + aRangeAdvSource.aStart.Set( theCol1,theRow1,theTab1 ); + aRangeAdvSource.aEnd.Set( theCol2,theRow2,theTab2 ); + SetAdvancedQuerySource( &aRangeAdvSource ); + + bDoUpdate = true; // DBData is modified + } + } + + SetModified(bDoUpdate); + + //! Testen, ob mitten aus dem Bereich geloescht/eingefuegt wurde !!! +} + +void ScDBData::ExtendDataArea(ScDocument* pDoc) +{ + // Extend the DB area to include data rows immediately below. + SCCOL nCol1a = nStartCol, nCol2a = nEndCol; + SCROW nRow1a = nStartRow, nRow2a = nEndRow; + pDoc->GetDataArea(nTable, nCol1a, nRow1a, nCol2a, nRow2a, false, false); + nEndRow = nRow2a; +} + +namespace { + +class FindByTable : public ::std::unary_function<ScDBData, bool> +{ + SCTAB mnTab; +public: + FindByTable(SCTAB nTab) : mnTab(nTab) {} + + bool operator() (const ScDBData& r) const + { + ScRange aRange; + r.GetArea(aRange); + return aRange.aStart.Tab() == mnTab; + } +}; + +class UpdateRefFunc : public unary_function<ScDBData, void> +{ + ScDocument* mpDoc; + UpdateRefMode meMode; + SCCOL mnCol1; + SCROW mnRow1; + SCTAB mnTab1; + SCCOL mnCol2; + SCROW mnRow2; + SCTAB mnTab2; + SCsCOL mnDx; + SCsROW mnDy; + SCsTAB mnDz; + +public: + UpdateRefFunc(ScDocument* pDoc, UpdateRefMode eMode, + SCCOL nCol1, SCROW nRow1, SCTAB nTab1, + SCCOL nCol2, SCROW nRow2, SCTAB nTab2, + SCsCOL nDx, SCsROW nDy, SCsTAB nDz) : + mpDoc(pDoc), meMode(eMode), + mnCol1(nCol1), mnRow1(nRow1), mnTab1(nTab1), + mnCol2(nCol2), mnRow2(nRow2), mnTab2(nTab2), + mnDx(nDx), mnDy(nDy), mnDz(nDz) {} + + void operator() (ScDBData& r) + { + r.UpdateReference(mpDoc, meMode, mnCol1, mnRow1, mnTab1, mnCol2, mnRow2, mnTab2, mnDx, mnDy, mnDz); + } +}; + +class UpdateMoveTabFunc : public unary_function<ScDBData, void> +{ + SCTAB mnOldTab; + SCTAB mnNewTab; +public: + UpdateMoveTabFunc(SCTAB nOld, SCTAB nNew) : mnOldTab(nOld), mnNewTab(nNew) {} + void operator() (ScDBData& r) + { + r.UpdateMoveTab(mnOldTab, mnNewTab); + } +}; + +class FindByCursor : public unary_function<ScDBData, bool> +{ + SCCOL mnCol; + SCROW mnRow; + SCTAB mnTab; + bool mbStartOnly; +public: + FindByCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, bool bStartOnly) : + mnCol(nCol), mnRow(nRow), mnTab(nTab), mbStartOnly(bStartOnly) {} + + bool operator() (const ScDBData& r) + { + return r.IsDBAtCursor(mnCol, mnRow, mnTab, mbStartOnly); + } +}; + +class FindByRange : public unary_function<ScDBData, bool> +{ + const ScRange& mrRange; +public: + FindByRange(const ScRange& rRange) : mrRange(rRange) {} + + bool operator() (const ScDBData& r) + { + return r.IsDBAtArea( + mrRange.aStart.Tab(), mrRange.aStart.Col(), mrRange.aStart.Row(), mrRange.aEnd.Col(), mrRange.aEnd.Row()); + } +}; + +} + +ScDBCollection::ScDBCollection(const ScDBCollection& r) : + ScSortedCollection(r), pDoc(r.pDoc), nEntryIndex(r.nEntryIndex), maAnonDBs(r.maAnonDBs) +{} + +short ScDBCollection::Compare(ScDataObject* pKey1, ScDataObject* pKey2) const +{ + const String& rStr1 = ((ScDBData*)pKey1)->GetName(); + const String& rStr2 = ((ScDBData*)pKey2)->GetName(); + return (short) ScGlobal::GetpTransliteration()->compareString( rStr1, rStr2 ); +} + +// IsEqual - alles gleich + +sal_Bool ScDBCollection::IsEqual(ScDataObject* pKey1, ScDataObject* pKey2) const +{ + return *(ScDBData*)pKey1 == *(ScDBData*)pKey2; +} + +ScDBData* ScDBCollection::GetDBAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, sal_Bool bStartOnly) const +{ + ScDBData* pNoNameData = pDoc->GetAnonymousDBData(nTab); + if (pItems) + { + for (sal_uInt16 i = 0; i < nCount; i++) + { + if (((ScDBData*)pItems[i])->IsDBAtCursor(nCol, nRow, nTab, bStartOnly)) + { + ScDBData* pDB = (ScDBData*)pItems[i]; + return pDB; //return AnonymousDBData only if nothing else was found + } + } + } + if (pNoNameData) + if (pNoNameData->IsDBAtCursor(nCol,nRow,nTab,bStartOnly)) + return pNoNameData; + + // Check the anonymous db ranges. + const ScDBData* pData = findAnonAtCursor(nCol, nRow, nTab, bStartOnly); + if (pData) + return const_cast<ScDBData*>(pData); + + return NULL; +} + +ScDBData* ScDBCollection::GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) const +{ + ScDBData* pNoNameData = pDoc->GetAnonymousDBData(nTab); + if (pItems) + { + for (sal_uInt16 i = 0; i < nCount; i++) + if (((ScDBData*)pItems[i])->IsDBAtArea(nTab, nCol1, nRow1, nCol2, nRow2)) + { + ScDBData* pDB = (ScDBData*)pItems[i]; + return pDB; //return AnonymousDBData only if nothing else was found + } + } + if (pNoNameData) + if (pNoNameData->IsDBAtArea(nTab, nCol1, nRow1, nCol2, nRow2)) + return pNoNameData; + + // Check the anonymous db ranges. + ScRange aRange(nCol1, nRow1, nTab, nCol2, nRow2, nTab); + const ScDBData* pData = findAnonByRange(aRange); + if (pData) + return const_cast<ScDBData*>(pData); + + return NULL; +} + +ScDBData* ScDBCollection::GetFilterDBAtTable(SCTAB nTab) const +{ + ScDBData* pAnonData = pDoc->GetAnonymousDBData(nTab); + + if (pItems) + { + for (sal_uInt16 i = 0; i < nCount; i++) + { + ScDBData* pDBTemp = (ScDBData*)pItems[i]; + if ( pDBTemp->GetTable() == nTab ) + { + sal_Bool bFilter = pDBTemp->HasAutoFilter() || pDBTemp->HasQueryParam(); + + if ( bFilter ) + return pDBTemp; + } + } + } + + if (pAnonData) + { + if ( pAnonData->HasAutoFilter() || pAnonData->HasQueryParam()) + return pAnonData; + } + + return NULL; +} + +sal_Bool ScDBCollection::SearchName( const String& rName, sal_uInt16& rIndex ) const +{ + if (rtl::OUString(rName)==rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(STR_DB_LOCAL_NONAME))) + DBG_ASSERT(false,"search for noname string"); + ScDBData aDataObj( rName, 0,0,0,0,0 ); + return Search( &aDataObj, rIndex ); +} + +void ScDBCollection::DeleteOnTab( SCTAB nTab ) +{ + sal_uInt16 nPos = 0; + while ( nPos < nCount ) + { + // look for output positions on the deleted sheet + + SCCOL nEntryCol1, nEntryCol2; + SCROW nEntryRow1, nEntryRow2; + SCTAB nEntryTab; + static_cast<const ScDBData*>(At(nPos))->GetArea( nEntryTab, nEntryCol1, nEntryRow1, nEntryCol2, nEntryRow2 ); + if ( nEntryTab == nTab ) + AtFree(nPos); + else + ++nPos; + } + + remove_if(maAnonDBs.begin(), maAnonDBs.end(), FindByTable(nTab)); +} + +void ScDBCollection::UpdateReference(UpdateRefMode eUpdateRefMode, + SCCOL nCol1, SCROW nRow1, SCTAB nTab1, + SCCOL nCol2, SCROW nRow2, SCTAB nTab2, + SCsCOL nDx, SCsROW nDy, SCsTAB nDz ) +{ + for (sal_uInt16 i=0; i<nCount; i++) + { + ((ScDBData*)pItems[i])->UpdateReference( + pDoc, eUpdateRefMode, + nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz); + } + ScDBData* pData = pDoc->GetAnonymousDBData(nTab1); + if (pData) + { + if (nTab1 == nTab2 && nDz == 0) + { + pData->UpdateReference( + pDoc, eUpdateRefMode, + nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz); + } + else + { + //this will perhabs break undo + } + } + + UpdateRefFunc func(pDoc, eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz); + for_each(maAnonDBs.begin(), maAnonDBs.end(), func); +} + + +void ScDBCollection::UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos ) +{ + // wenn nOldPos vor nNewPos liegt, ist nNewPos schon angepasst + + for (sal_uInt16 i=0; i<nCount; i++) + { + ScDBData* pData = (ScDBData*)pItems[i]; + pData->UpdateMoveTab(nOldPos, nNewPos); + } + + UpdateMoveTabFunc func(nOldPos, nNewPos); + for_each(maAnonDBs.begin(), maAnonDBs.end(), func); +} + + +ScDBData* ScDBCollection::FindIndex(sal_uInt16 nIndex) +{ + sal_uInt16 i = 0; + while (i < nCount) + { + if ((*this)[i]->GetIndex() == nIndex) + return (*this)[i]; + i++; + } + return NULL; +} + +sal_Bool ScDBCollection::Insert(ScDataObject* pScDataObject) +{ + ScDBData* pData = (ScDBData*) pScDataObject; + if (!pData->GetIndex()) // schon gesetzt? + pData->SetIndex(nEntryIndex++); + sal_Bool bInserted = ScSortedCollection::Insert(pScDataObject); + if ( bInserted && pData->HasImportParam() && !pData->HasImportSelection() ) + { + pData->SetRefreshHandler( GetRefreshHandler() ); + pData->SetRefreshControl( pDoc->GetRefreshTimerControlAddress() ); + } + return bInserted; +} + +ScDBData* ScDBCollection::GetDBNearCursor(SCCOL nCol, SCROW nRow, SCTAB nTab ) +{ + ScDBData* pNearData = NULL; + SCTAB nAreaTab; + SCCOL nStartCol, nEndCol; + SCROW nStartRow, nEndRow; + for (sal_uInt16 i = 0; i < nCount; i++) + { + ScDBData* pDB = (ScDBData*)pItems[i]; + pDB->GetArea( nAreaTab, nStartCol, nStartRow, nEndCol, nEndRow ); + if ( nTab == nAreaTab && nCol+1 >= nStartCol && nCol <= nEndCol+1 && + nRow+1 >= nStartRow && nRow <= nEndRow+1 ) + { + if ( nCol < nStartCol || nCol > nEndCol || nRow < nStartRow || nRow > nEndRow ) + { + if (!pNearData) + pNearData = pDB; // ersten angrenzenden Bereich merken + } + else + return pDB; // nicht "unbenannt" und Cursor steht wirklich drin + } + } + if (pNearData) + return pNearData; // angrenzender, wenn nichts direkt getroffen + return pDoc->GetAnonymousDBData(nTab); // "unbenannt" nur zurueck, wenn sonst nichts gefunden +} + +const ScDBData* ScDBCollection::findAnonAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, bool bStartOnly) const +{ + AnonDBsType::const_iterator itr = find_if( + maAnonDBs.begin(), maAnonDBs.end(), FindByCursor(nCol, nRow, nTab, bStartOnly)); + return itr == maAnonDBs.end() ? NULL : &(*itr); +} + +const ScDBData* ScDBCollection::findAnonByRange(const ScRange& rRange) const +{ + AnonDBsType::const_iterator itr = find_if( + maAnonDBs.begin(), maAnonDBs.end(), FindByRange(rRange)); + return itr == maAnonDBs.end() ? NULL : &(*itr); +} + +ScDBData* ScDBCollection::getAnonByRange(const ScRange& rRange) +{ + const ScDBData* pData = findAnonByRange(rRange); + if (!pData) + { + // Insert a new db data. They all have identical names. + rtl::OUString aName(RTL_CONSTASCII_USTRINGPARAM(STR_DB_GLOBAL_NONAME)); + ::std::auto_ptr<ScDBData> pNew(new ScDBData( + aName, rRange.aStart.Tab(), rRange.aStart.Col(), rRange.aStart.Row(), + rRange.aEnd.Col(), rRange.aEnd.Row(), true, false)); + pData = pNew.get(); + maAnonDBs.push_back(pNew); + } + return const_cast<ScDBData*>(pData); +} + +void ScDBCollection::insertAnonRange(ScDBData* pData) +{ + rtl::OUString aName(RTL_CONSTASCII_USTRINGPARAM(STR_DB_GLOBAL_NONAME)); + ::std::auto_ptr<ScDBData> pNew(pData); + maAnonDBs.push_back(pNew); +} + +const ScDBCollection::AnonDBsType& ScDBCollection::getAnonRanges() const +{ + return maAnonDBs; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |