Files
libreoffice/sc/source/core/tool/dbdata.cxx

1004 lines
30 KiB
C++
Raw Normal View History

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
re-base on ALv2 code. Includes: Patches contributed by Herbert Duerr i#118735 prevent endless loop if vlookup/hlookup doesn't find anything http://svn.apache.org/viewvc?view=revision&revision=1239673 Patches contributed by Andre Fischer remove lp_solver http://svn.apache.org/viewvc?view=revision&revision=1199180 i#118160: Added external CoinMP library. http://svn.apache.org/viewvc?view=revision&revision=1233909 Patches contributed by Armin Le-Grand i#118485 - Styles for OLEs are not saved. http://svn.apache.org/viewvc?view=revision&revision=1182166 i#118524: apply patch, followup fixes to 118485 http://svn.apache.org/viewvc?view=revision&revision=1186077 Patches contributed by lihuiibm i#108860 - Fix range validation. http://svn.apache.org/viewvc?view=revision&revision=1242846 i#118954 Chart data will lost after copy to different file http://svn.apache.org/viewvc?view=revision&revision=1301345 Patches contributed by Ariel Constenla-Haile Fix Linux build breaker: extra qualification on member http://svn.apache.org/viewvc?view=revision&revision=1301591 i#118696 - i#118697 - Fix some Sheet Tab Color API issues http://svn.apache.org/viewvc?view=revision&revision=1225428 i#118697 - Fix uninitialized variable http://svn.apache.org/viewvc?view=revision&revision=1225859 i#118771 - ScUndoImportTab should preserve tab background color http://svn.apache.org/viewvc?view=revision&revision=1230356 i#118921 - Repaint linked sheet tab background color after updating link http://svn.apache.org/viewvc?view=revision&revision=1245177 i#118927 - Undo/Redo "Update Link" does not reset sheet tab color http://svn.apache.org/viewvc?view=revision&revision=1245241 i#118747 - Copy tab color when transferring sheets across documents http://svn.apache.org/viewvc?view=revision&revision=1230355 Patch contributed by Oliver Rainer-Wittman i#118012 - methods <ScBroadcastAreaSlot::AreaBroadcast(..)> and <ScBroadcastAreaSlot::AreaBroadcastInRange(..)> adapt stl-container iteration in order to avoid destroyed iterators during iteration. http://svn.apache.org/viewvc?view=revision&revision=1297916 Patches contributed by Mathias Bauer gnumake4 work variously http://svn.apache.org/viewvc?view=revision&revision=1394707 http://svn.apache.org/viewvc?view=revision&revision=1394326 http://svn.apache.org/viewvc?view=revision&revision=1396797 http://svn.apache.org/viewvc?view=revision&revision=1397315 Patch contributed by Daniel Rentz calc69: #i116936# fix VBA symbol Cells http://svn.apache.org/viewvc?view=revision&revision=1172135 Patches contributed by leiw: i#118546 CPU 100% on switched off AutoCalculate with Conditional Formatting on date values http://svn.apache.org/viewvc?view=revision&revision=1301380 Re-add new function documentation. Many various cleanups. Add missing calc66: #o11817313# also look at formula result number format, remove redundant binaries.
2012-11-30 12:23:25 +00:00
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* 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 .
*/
2000-09-18 23:16:46 +00:00
#include <unotools/transliterationwrapper.hxx>
2000-09-18 23:16:46 +00:00
#include "dbdata.hxx"
#include "globalnames.hxx"
2000-09-18 23:16:46 +00:00
#include "refupdat.hxx"
#include "rechead.hxx"
#include "document.hxx"
#include "queryparam.hxx"
#include "queryentry.hxx"
2000-09-18 23:16:46 +00:00
#include "globstr.hrc"
#include "subtotalparam.hxx"
#include "sortparam.hxx"
2000-09-18 23:16:46 +00:00
#include <memory>
using ::std::auto_ptr;
using ::std::unary_function;
using ::std::for_each;
using ::std::find_if;
using ::std::remove_if;
using ::std::pair;
bool ScDBData::less::operator() (const ScDBData& left, const ScDBData& right) const
{
return ScGlobal::GetpTransliteration()->compareString(left.GetUpperName(), right.GetUpperName()) < 0;
}
ScDBData::ScDBData( const OUString& rName,
SCTAB nTab,
SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
2011-04-01 00:32:19 -04:00
bool bByR, bool bHasH) :
mpSortParam(new ScSortParam),
mpQueryParam(new ScQueryParam),
mpSubTotal(new ScSubTotalParam),
mpImportParam(new ScImportParam),
2000-09-18 23:16:46 +00:00
aName (rName),
aUpper (rName),
2000-09-18 23:16:46 +00:00
nTable (nTab),
nStartCol (nCol1),
nStartRow (nRow1),
nEndCol (nCol2),
nEndRow (nRow2),
bByRow (bByR),
bHasHeader (bHasH),
bDoSize (false),
bKeepFmt (false),
bStripData (false),
bIsAdvanced (false),
bDBSelection(false),
2000-09-18 23:16:46 +00:00
nIndex (0),
bAutoFilter (false),
bModified (false)
2000-09-18 23:16:46 +00:00
{
aUpper = ScGlobal::pCharClass->uppercase(aUpper);
2000-09-18 23:16:46 +00:00
}
ScDBData::ScDBData( const ScDBData& rData ) :
ScRefreshTimer ( rData ),
mpSortParam(new ScSortParam(*rData.mpSortParam)),
mpQueryParam(new ScQueryParam(*rData.mpQueryParam)),
mpSubTotal(new ScSubTotalParam(*rData.mpSubTotal)),
mpImportParam(new ScImportParam(*rData.mpImportParam)),
2000-09-18 23:16:46 +00:00
aName (rData.aName),
aUpper (rData.aUpper),
2000-09-18 23:16:46 +00:00
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),
bIsAdvanced (rData.bIsAdvanced),
aAdvSource (rData.aAdvSource),
bDBSelection (rData.bDBSelection),
nIndex (rData.nIndex),
bAutoFilter (rData.bAutoFilter),
bModified (rData.bModified)
{
}
ScDBData::ScDBData( const OUString& rName, const ScDBData& rData ) :
ScRefreshTimer ( rData ),
mpSortParam(new ScSortParam(*rData.mpSortParam)),
mpQueryParam(new ScQueryParam(*rData.mpQueryParam)),
mpSubTotal(new ScSubTotalParam(*rData.mpSubTotal)),
mpImportParam(new ScImportParam(*rData.mpImportParam)),
aName (rName),
aUpper (rName),
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),
bIsAdvanced (rData.bIsAdvanced),
aAdvSource (rData.aAdvSource),
bDBSelection (rData.bDBSelection),
nIndex (rData.nIndex),
bAutoFilter (rData.bAutoFilter),
bModified (rData.bModified)
{
aUpper = ScGlobal::pCharClass->uppercase(aUpper);
}
2000-09-18 23:16:46 +00:00
ScDBData& ScDBData::operator= (const ScDBData& rData)
{
// Don't modify the name. The name is not mutable as it is used as a key
// in the container to keep the db ranges sorted by the name.
ScRefreshTimer::operator=( rData );
mpSortParam.reset(new ScSortParam(*rData.mpSortParam));
mpQueryParam.reset(new ScQueryParam(*rData.mpQueryParam));
mpSubTotal.reset(new ScSubTotalParam(*rData.mpSubTotal));
mpImportParam.reset(new ScImportParam(*rData.mpImportParam));
2000-09-18 23:16:46 +00:00
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;
bIsAdvanced = rData.bIsAdvanced;
aAdvSource = rData.aAdvSource;
bDBSelection = rData.bDBSelection;
nIndex = rData.nIndex;
bAutoFilter = rData.bAutoFilter;
2000-09-18 23:16:46 +00:00
return *this;
}
2011-04-01 00:32:19 -04:00
bool ScDBData::operator== (const ScDBData& rData) const
2000-09-18 23:16:46 +00:00
{
// 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;
2000-09-18 23:16:46 +00:00
if ( bIsAdvanced && aAdvSource != rData.aAdvSource )
return false;
2000-09-18 23:16:46 +00:00
ScSortParam aSort1, aSort2;
GetSortParam(aSort1);
rData.GetSortParam(aSort2);
if (!(aSort1 == aSort2))
return false;
2000-09-18 23:16:46 +00:00
ScQueryParam aQuery1, aQuery2;
GetQueryParam(aQuery1);
rData.GetQueryParam(aQuery2);
if (!(aQuery1 == aQuery2))
return false;
2000-09-18 23:16:46 +00:00
ScSubTotalParam aSubTotal1, aSubTotal2;
GetSubTotalParam(aSubTotal1);
rData.GetSubTotalParam(aSubTotal2);
if (!(aSubTotal1 == aSubTotal2))
return false;
2000-09-18 23:16:46 +00:00
ScImportParam aImport1, aImport2;
GetImportParam(aImport1);
rData.GetImportParam(aImport2);
if (!(aImport1 == aImport2))
return false;
2000-09-18 23:16:46 +00:00
2011-04-01 00:32:19 -04:00
return true;
2000-09-18 23:16:46 +00:00
}
ScDBData::~ScDBData()
{
StopRefreshTimer();
2000-09-18 23:16:46 +00:00
}
OUString ScDBData::GetSourceString() const
2000-09-18 23:16:46 +00:00
{
OUStringBuffer aBuf;
if (mpImportParam->bImport)
2000-09-18 23:16:46 +00:00
{
aBuf.append(mpImportParam->aDBName);
aBuf.append('/');
aBuf.append(mpImportParam->aStatement);
2000-09-18 23:16:46 +00:00
}
return aBuf.makeStringAndClear();
2000-09-18 23:16:46 +00:00
}
OUString ScDBData::GetOperations() const
2000-09-18 23:16:46 +00:00
{
OUStringBuffer aBuf;
if (mpQueryParam->GetEntryCount())
{
const ScQueryEntry& rEntry = mpQueryParam->GetEntry(0);
if (rEntry.bDoQuery)
aBuf.append(ScGlobal::GetRscString(STR_OPERATION_FILTER));
}
2000-09-18 23:16:46 +00:00
if (mpSortParam->maKeyState[0].bDoSort)
2000-09-18 23:16:46 +00:00
{
if (!aBuf.isEmpty())
aBuf.append(", ");
aBuf.append(ScGlobal::GetRscString(STR_OPERATION_SORT));
2000-09-18 23:16:46 +00:00
}
if (mpSubTotal->bGroupActive[0] && !mpSubTotal->bRemoveOnly)
2000-09-18 23:16:46 +00:00
{
if (!aBuf.isEmpty())
aBuf.append(", ");
aBuf.append(ScGlobal::GetRscString(STR_OPERATION_SUBTOTAL));
2000-09-18 23:16:46 +00:00
}
if (aBuf.isEmpty())
aBuf.append(ScGlobal::GetRscString(STR_OPERATION_NONE));
2000-09-18 23:16:46 +00:00
return aBuf.makeStringAndClear();
2000-09-18 23:16:46 +00:00
}
void ScDBData::GetArea(SCTAB& rTab, SCCOL& rCol1, SCROW& rRow1, SCCOL& rCol2, SCROW& rRow2) const
2000-09-18 23:16:46 +00:00
{
rTab = nTable;
rCol1 = nStartCol;
rRow1 = nStartRow;
rCol2 = nEndCol;
rRow2 = nEndRow;
2000-09-18 23:16:46 +00:00
}
void ScDBData::GetArea(ScRange& rRange) const
2000-09-18 23:16:46 +00:00
{
SCROW nNewEndRow = nEndRow;
rRange = ScRange( nStartCol, nStartRow, nTable, nEndCol, nNewEndRow, nTable );
2000-09-18 23:16:46 +00:00
}
void ScDBData::SetArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
2000-09-18 23:16:46 +00:00
{
nTable = nTab;
nStartCol = nCol1;
nStartRow = nRow1;
nEndCol = nCol2;
nEndRow = nRow2;
}
void ScDBData::MoveTo(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
2000-09-18 23:16:46 +00:00
{
sal_uInt16 i;
long nDifX = ((long) nCol1) - ((long) nStartCol);
long nDifY = ((long) nRow1) - ((long) nStartRow);
2000-09-18 23:16:46 +00:00
long nSortDif = bByRow ? nDifX : nDifY;
long nSortEnd = bByRow ? static_cast<long>(nCol2) : static_cast<long>(nRow2);
2000-09-18 23:16:46 +00:00
for (i=0; i<mpSortParam->GetSortKeyCount(); i++)
2000-09-18 23:16:46 +00:00
{
mpSortParam->maKeyState[i].nField += nSortDif;
if (mpSortParam->maKeyState[i].nField > nSortEnd)
2000-09-18 23:16:46 +00:00
{
mpSortParam->maKeyState[i].nField = 0;
mpSortParam->maKeyState[i].bDoSort = false;
2000-09-18 23:16:46 +00:00
}
}
SCSIZE nCount = mpQueryParam->GetEntryCount();
for (i = 0; i < nCount; ++i)
2000-09-18 23:16:46 +00:00
{
ScQueryEntry& rEntry = mpQueryParam->GetEntry(i);
rEntry.nField += nDifX;
if (rEntry.nField > nCol2)
2000-09-18 23:16:46 +00:00
{
rEntry.nField = 0;
rEntry.bDoQuery = false;
2000-09-18 23:16:46 +00:00
}
}
for (i=0; i<MAXSUBTOTAL; i++)
{
mpSubTotal->nField[i] = sal::static_int_cast<SCCOL>( mpSubTotal->nField[i] + nDifX );
if (mpSubTotal->nField[i] > nCol2)
2000-09-18 23:16:46 +00:00
{
mpSubTotal->nField[i] = 0;
mpSubTotal->bGroupActive[i] = false;
2000-09-18 23:16:46 +00:00
}
}
SetArea( nTab, nCol1, nRow1, nCol2, nRow2 );
}
void ScDBData::GetSortParam( ScSortParam& rSortParam ) const
{
rSortParam = *mpSortParam;
2000-09-18 23:16:46 +00:00
rSortParam.nCol1 = nStartCol;
rSortParam.nRow1 = nStartRow;
rSortParam.nCol2 = nEndCol;
rSortParam.nRow2 = nEndRow;
rSortParam.bByRow = bByRow;
rSortParam.bHasHeader = bHasHeader;
}
void ScDBData::SetSortParam( const ScSortParam& rSortParam )
{
mpSortParam.reset(new ScSortParam(rSortParam));
bByRow = rSortParam.bByRow;
2000-09-18 23:16:46 +00:00
}
void ScDBData::GetQueryParam( ScQueryParam& rQueryParam ) const
{
rQueryParam = *mpQueryParam;
2000-09-18 23:16:46 +00:00
rQueryParam.nCol1 = nStartCol;
rQueryParam.nRow1 = nStartRow;
rQueryParam.nCol2 = nEndCol;
rQueryParam.nRow2 = nEndRow;
rQueryParam.nTab = nTable;
rQueryParam.bByRow = bByRow;
rQueryParam.bHasHeader = bHasHeader;
}
void ScDBData::SetQueryParam(const ScQueryParam& rQueryParam)
{
mpQueryParam.reset(new ScQueryParam(rQueryParam));
2011-04-01 00:32:19 -04:00
// set bIsAdvanced to false for everything that is not from the
2000-09-18 23:16:46 +00:00
// advanced filter dialog
bIsAdvanced = false;
2000-09-18 23:16:46 +00:00
}
void ScDBData::SetAdvancedQuerySource(const ScRange* pSource)
{
if (pSource)
{
aAdvSource = *pSource;
2011-04-01 00:32:19 -04:00
bIsAdvanced = true;
2000-09-18 23:16:46 +00:00
}
else
bIsAdvanced = false;
2000-09-18 23:16:46 +00:00
}
2011-04-01 00:32:19 -04:00
bool ScDBData::GetAdvancedQuerySource(ScRange& rSource) const
2000-09-18 23:16:46 +00:00
{
rSource = aAdvSource;
return bIsAdvanced;
}
void ScDBData::GetSubTotalParam(ScSubTotalParam& rSubTotalParam) const
{
rSubTotalParam = *mpSubTotal;
2000-09-18 23:16:46 +00:00
// Share the data range with the parent db data. The range in the subtotal
// param struct is not used.
2000-09-18 23:16:46 +00:00
rSubTotalParam.nCol1 = nStartCol;
rSubTotalParam.nRow1 = nStartRow;
rSubTotalParam.nCol2 = nEndCol;
rSubTotalParam.nRow2 = nEndRow;
}
void ScDBData::SetSubTotalParam(const ScSubTotalParam& rSubTotalParam)
{
mpSubTotal.reset(new ScSubTotalParam(rSubTotalParam));
2000-09-18 23:16:46 +00:00
}
void ScDBData::GetImportParam(ScImportParam& rImportParam) const
{
rImportParam = *mpImportParam;
// set the range.
2000-09-18 23:16:46 +00:00
rImportParam.nCol1 = nStartCol;
rImportParam.nRow1 = nStartRow;
rImportParam.nCol2 = nEndCol;
rImportParam.nRow2 = nEndRow;
}
void ScDBData::SetImportParam(const ScImportParam& rImportParam)
{
// the range is ignored.
mpImportParam.reset(new ScImportParam(rImportParam));
2000-09-18 23:16:46 +00:00
}
2011-04-01 00:32:19 -04:00
bool ScDBData::IsDBAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, bool bStartOnly) const
2000-09-18 23:16:46 +00:00
{
if (nTab == nTable)
{
if ( bStartOnly )
return ( nCol == nStartCol && nRow == nStartRow );
else
return ( nCol >= nStartCol && nCol <= nEndCol &&
nRow >= nStartRow && nRow <= nEndRow );
}
return false;
2000-09-18 23:16:46 +00:00
}
2011-04-01 00:32:19 -04:00
bool ScDBData::IsDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) const
2000-09-18 23:16:46 +00:00
{
2011-04-01 00:32:19 -04:00
return (bool)((nTab == nTable)
2000-09-18 23:16:46 +00:00
&& (nCol1 == nStartCol) && (nRow1 == nStartRow)
&& (nCol2 == nEndCol) && (nRow2 == nEndRow));
}
bool ScDBData::HasImportParam() const
{
return mpImportParam && mpImportParam->bImport;
}
bool ScDBData::HasQueryParam() const
{
if (!mpQueryParam)
return false;
if (!mpQueryParam->GetEntryCount())
return false;
return mpQueryParam->GetEntry(0).bDoQuery;
}
bool ScDBData::HasSortParam() const
{
return mpSortParam &&
!mpSortParam->maKeyState.empty() &&
mpSortParam->maKeyState[0].bDoSort;
}
bool ScDBData::HasSubTotalParam() const
{
return mpSubTotal && mpSubTotal->bGroupActive[0];
}
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;
}
2011-04-01 00:32:19 -04:00
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;
2011-04-01 00:32:19 -04:00
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 );
2011-04-01 00:32:19 -04:00
bDoUpdate = true; // DBData is modified
}
}
SetModified(bDoUpdate);
//! Testen, ob mitten aus dem Bereich geloescht/eingefuegt wurde !!!
}
2011-04-07 14:33:04 -04:00
void ScDBData::ExtendDataArea(ScDocument* pDoc)
{
// Extend the DB area to include data rows immediately below.
// or shrink it if all cells are empty
pDoc->GetDataArea(nTable, nStartCol, nStartRow, nEndCol, nEndRow, false, true);
}
namespace {
class FindByTable : public 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());
}
};
class FindByIndex : public unary_function<ScDBData, bool>
{
sal_uInt16 mnIndex;
public:
FindByIndex(sal_uInt16 nIndex) : mnIndex(nIndex) {}
bool operator() (const ScDBData& r) const
{
return r.GetIndex() == mnIndex;
}
};
class FindByUpperName : public unary_function<ScDBData, bool>
{
const OUString& mrName;
public:
FindByUpperName(const OUString& rName) : mrName(rName) {}
bool operator() (const ScDBData& r) const
{
return r.GetUpperName() == mrName;
}
};
2000-09-18 23:16:46 +00:00
}
ScDBCollection::NamedDBs::NamedDBs(ScDBCollection& rParent, ScDocument& rDoc) :
mrParent(rParent), mrDoc(rDoc) {}
ScDBCollection::NamedDBs::NamedDBs(const NamedDBs& r) :
maDBs(r.maDBs), mrParent(r.mrParent), mrDoc(r.mrDoc) {}
ScDBCollection::NamedDBs::iterator ScDBCollection::NamedDBs::begin()
{
return maDBs.begin();
}
ScDBCollection::NamedDBs::iterator ScDBCollection::NamedDBs::end()
{
return maDBs.end();
}
ScDBCollection::NamedDBs::const_iterator ScDBCollection::NamedDBs::begin() const
{
return maDBs.begin();
}
ScDBCollection::NamedDBs::const_iterator ScDBCollection::NamedDBs::end() const
{
return maDBs.end();
}
ScDBData* ScDBCollection::NamedDBs::findByIndex(sal_uInt16 nIndex)
{
DBsType::iterator itr = find_if(
maDBs.begin(), maDBs.end(), FindByIndex(nIndex));
return itr == maDBs.end() ? NULL : &(*itr);
}
ScDBData* ScDBCollection::NamedDBs::findByUpperName(const OUString& rName)
{
DBsType::iterator itr = find_if(
maDBs.begin(), maDBs.end(), FindByUpperName(rName));
return itr == maDBs.end() ? NULL : &(*itr);
}
bool ScDBCollection::NamedDBs::insert(ScDBData* p)
{
SAL_WNODEPRECATED_DECLARATIONS_PUSH
auto_ptr<ScDBData> pData(p);
SAL_WNODEPRECATED_DECLARATIONS_POP
if (!pData->GetIndex())
pData->SetIndex(mrParent.nEntryIndex++);
pair<DBsType::iterator, bool> r = maDBs.insert(pData);
if (r.second && p->HasImportParam() && !p->HasImportSelection())
{
p->SetRefreshHandler(mrParent.GetRefreshHandler());
p->SetRefreshControl(mrDoc.GetRefreshTimerControlAddress());
}
return r.second;
}
void ScDBCollection::NamedDBs::erase(iterator itr)
{
maDBs.erase(itr);
}
void ScDBCollection::NamedDBs::erase(const ScDBData& r)
{
maDBs.erase(r);
}
bool ScDBCollection::NamedDBs::empty() const
{
return maDBs.empty();
}
size_t ScDBCollection::NamedDBs::size() const
{
return maDBs.size();
}
bool ScDBCollection::NamedDBs::operator== (const NamedDBs& r) const
{
return maDBs == r.maDBs;
}
ScDBCollection::AnonDBs::iterator ScDBCollection::AnonDBs::begin()
{
return maDBs.begin();
}
ScDBCollection::AnonDBs::iterator ScDBCollection::AnonDBs::end()
{
return maDBs.end();
}
ScDBCollection::AnonDBs::const_iterator ScDBCollection::AnonDBs::begin() const
{
return maDBs.begin();
}
ScDBCollection::AnonDBs::const_iterator ScDBCollection::AnonDBs::end() const
{
return maDBs.end();
}
const ScDBData* ScDBCollection::AnonDBs::findAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, bool bStartOnly) const
{
DBsType::const_iterator itr = find_if(
maDBs.begin(), maDBs.end(), FindByCursor(nCol, nRow, nTab, bStartOnly));
return itr == maDBs.end() ? NULL : &(*itr);
}
const ScDBData* ScDBCollection::AnonDBs::findByRange(const ScRange& rRange) const
{
DBsType::const_iterator itr = find_if(
maDBs.begin(), maDBs.end(), FindByRange(rRange));
return itr == maDBs.end() ? NULL : &(*itr);
}
ScDBData* ScDBCollection::AnonDBs::getByRange(const ScRange& rRange)
{
const ScDBData* pData = findByRange(rRange);
if (!pData)
{
// Insert a new db data. They all have identical names.
OUString aName(STR_DB_GLOBAL_NONAME);
SAL_WNODEPRECATED_DECLARATIONS_PUSH
::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));
SAL_WNODEPRECATED_DECLARATIONS_POP
pData = pNew.get();
maDBs.push_back(pNew);
}
return const_cast<ScDBData*>(pData);
}
void ScDBCollection::AnonDBs::insert(ScDBData* p)
{
SAL_WNODEPRECATED_DECLARATIONS_PUSH
::std::auto_ptr<ScDBData> pNew(p);
SAL_WNODEPRECATED_DECLARATIONS_POP
maDBs.push_back(pNew);
}
bool ScDBCollection::AnonDBs::empty() const
{
return maDBs.empty();
}
bool ScDBCollection::AnonDBs::operator== (const AnonDBs& r) const
{
return maDBs == r.maDBs;
}
ScDBCollection::ScDBCollection(ScDocument* pDocument) :
pDoc(pDocument), nEntryIndex(SC_START_INDEX_DB_COLL), maNamedDBs(*this, *pDocument) {}
ScDBCollection::ScDBCollection(const ScDBCollection& r) :
pDoc(r.pDoc), nEntryIndex(r.nEntryIndex), maNamedDBs(r.maNamedDBs), maAnonDBs(r.maAnonDBs) {}
ScDBCollection::NamedDBs& ScDBCollection::getNamedDBs()
{
return maNamedDBs;
}
const ScDBCollection::NamedDBs& ScDBCollection::getNamedDBs() const
{
return maNamedDBs;
}
ScDBCollection::AnonDBs& ScDBCollection::getAnonDBs()
{
return maAnonDBs;
}
const ScDBCollection::AnonDBs& ScDBCollection::getAnonDBs() const
{
return maAnonDBs;
}
const ScDBData* ScDBCollection::GetDBAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, bool bStartOnly) const
2000-09-18 23:16:46 +00:00
{
// First, search the global named db ranges.
NamedDBs::DBsType::const_iterator itr = find_if(
maNamedDBs.begin(), maNamedDBs.end(), FindByCursor(nCol, nRow, nTab, bStartOnly));
if (itr != maNamedDBs.end())
return &(*itr);
// Check for the sheet-local anonymous db range.
const ScDBData* pNoNameData = pDoc->GetAnonymousDBData(nTab);
if (pNoNameData)
if (pNoNameData->IsDBAtCursor(nCol,nRow,nTab,bStartOnly))
return pNoNameData;
// Check the global anonymous db ranges.
const ScDBData* pData = getAnonDBs().findAtCursor(nCol, nRow, nTab, bStartOnly);
if (pData)
return pData;
return NULL;
2000-09-18 23:16:46 +00:00
}
ScDBData* ScDBCollection::GetDBAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, bool bStartOnly)
{
// First, search the global named db ranges.
NamedDBs::DBsType::iterator itr = find_if(
maNamedDBs.begin(), maNamedDBs.end(), FindByCursor(nCol, nRow, nTab, bStartOnly));
if (itr != maNamedDBs.end())
return &(*itr);
// Check for the sheet-local anonymous db range.
ScDBData* pNoNameData = pDoc->GetAnonymousDBData(nTab);
if (pNoNameData)
if (pNoNameData->IsDBAtCursor(nCol,nRow,nTab,bStartOnly))
return pNoNameData;
// Check the global anonymous db ranges.
const ScDBData* pData = getAnonDBs().findAtCursor(nCol, nRow, nTab, bStartOnly);
if (pData)
return const_cast<ScDBData*>(pData);
return NULL;
}
const ScDBData* ScDBCollection::GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) const
2000-09-18 23:16:46 +00:00
{
// First, search the global named db ranges.
ScRange aRange(nCol1, nRow1, nTab, nCol2, nRow2, nTab);
NamedDBs::DBsType::const_iterator itr = find_if(
maNamedDBs.begin(), maNamedDBs.end(), FindByRange(aRange));
if (itr != maNamedDBs.end())
return &(*itr);
// Check for the sheet-local anonymous db range.
ScDBData* pNoNameData = pDoc->GetAnonymousDBData(nTab);
if (pNoNameData)
if (pNoNameData->IsDBAtArea(nTab, nCol1, nRow1, nCol2, nRow2))
return pNoNameData;
// Lastly, check the global anonymous db ranges.
return maAnonDBs.findByRange(aRange);
}
ScDBData* ScDBCollection::GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
{
// First, search the global named db ranges.
ScRange aRange(nCol1, nRow1, nTab, nCol2, nRow2, nTab);
NamedDBs::DBsType::iterator itr = find_if(
maNamedDBs.begin(), maNamedDBs.end(), FindByRange(aRange));
if (itr != maNamedDBs.end())
return &(*itr);
// Check for the sheet-local anonymous db range.
ScDBData* pNoNameData = pDoc->GetAnonymousDBData(nTab);
if (pNoNameData)
if (pNoNameData->IsDBAtArea(nTab, nCol1, nRow1, nCol2, nRow2))
return pNoNameData;
// Lastly, check the global anonymous db ranges.
const ScDBData* pData = getAnonDBs().findByRange(aRange);
if (pData)
return const_cast<ScDBData*>(pData);
return NULL;
2000-09-18 23:16:46 +00:00
}
void ScDBCollection::DeleteOnTab( SCTAB nTab )
{
FindByTable func(nTab);
// First, collect the positions of all items that need to be deleted.
::std::vector<NamedDBs::DBsType::iterator> v;
{
NamedDBs::DBsType::iterator itr = maNamedDBs.begin(), itrEnd = maNamedDBs.end();
for (; itr != itrEnd; ++itr)
{
if (func(*itr))
v.push_back(itr);
}
}
// Delete them all.
::std::vector<NamedDBs::DBsType::iterator>::iterator itr = v.begin(), itrEnd = v.end();
for (; itr != itrEnd; ++itr)
maNamedDBs.erase(*itr);
remove_if(maAnonDBs.begin(), maAnonDBs.end(), func);
}
2000-09-18 23:16:46 +00:00
void ScDBCollection::UpdateReference(UpdateRefMode eUpdateRefMode,
SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
2000-09-18 23:16:46 +00:00
{
ScDBData* pData = pDoc->GetAnonymousDBData(nTab1);
if (pData)
{
if (nTab1 == nTab2 && nDz == 0)
2000-09-18 23:16:46 +00:00
{
pData->UpdateReference(
pDoc, eUpdateRefMode,
nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz);
}
else
{
//this will perhabs break undo
2000-09-18 23:16:46 +00:00
}
}
UpdateRefFunc func(pDoc, eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz);
for_each(maNamedDBs.begin(), maNamedDBs.end(), func);
for_each(maAnonDBs.begin(), maAnonDBs.end(), func);
2000-09-18 23:16:46 +00:00
}
void ScDBCollection::UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos )
2000-09-18 23:16:46 +00:00
{
UpdateMoveTabFunc func(nOldPos, nNewPos);
for_each(maNamedDBs.begin(), maNamedDBs.end(), func);
for_each(maAnonDBs.begin(), maAnonDBs.end(), func);
2000-09-18 23:16:46 +00:00
}
ScDBData* ScDBCollection::GetDBNearCursor(SCCOL nCol, SCROW nRow, SCTAB nTab )
{
ScDBData* pNearData = NULL;
NamedDBs::DBsType::iterator itr = maNamedDBs.begin(), itrEnd = maNamedDBs.end();
for (; itr != itrEnd; ++itr)
{
SCTAB nAreaTab;
SCCOL nStartCol, nEndCol;
SCROW nStartRow, nEndRow;
itr->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 = &(*itr); // ersten angrenzenden Bereich merken
}
else
return &(*itr); // 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
}
2000-09-18 23:16:46 +00:00
bool ScDBCollection::empty() const
{
return maNamedDBs.empty() && maAnonDBs.empty();
}
bool ScDBCollection::operator== (const ScDBCollection& r) const
{
return maNamedDBs == r.maNamedDBs && maAnonDBs == r.maAnonDBs &&
nEntryIndex == r.nEntryIndex && pDoc == r.pDoc && aRefreshHandler == r.aRefreshHandler;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */