summaryrefslogtreecommitdiff
path: root/sc/source/core/data/table3.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/core/data/table3.cxx')
-rw-r--r--sc/source/core/data/table3.cxx2124
1 files changed, 0 insertions, 2124 deletions
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
deleted file mode 100644
index 6982da819..000000000
--- a/sc/source/core/data/table3.cxx
+++ /dev/null
@@ -1,2124 +0,0 @@
-/* -*- 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 <rtl/math.hxx>
-#include <unotools/textsearch.hxx>
-#include <svl/zforlist.hxx>
-#include <svl/zformat.hxx>
-#include <unotools/charclass.hxx>
-#include <unotools/collatorwrapper.hxx>
-#include <com/sun/star/i18n/CollatorOptions.hpp>
-#include <stdlib.h>
-#include <unotools/transliterationwrapper.hxx>
-
-#include "table.hxx"
-#include "scitems.hxx"
-#include "collect.hxx"
-#include "attrib.hxx"
-#include "cell.hxx"
-#include "document.hxx"
-#include "globstr.hrc"
-#include "global.hxx"
-#include "stlpool.hxx"
-#include "compiler.hxx"
-#include "patattr.hxx"
-#include "subtotal.hxx"
-#include "docoptio.hxx"
-#include "markdata.hxx"
-#include "rangelst.hxx"
-#include "attarray.hxx"
-#include "userlist.hxx"
-#include "progress.hxx"
-#include "cellform.hxx"
-#include "postit.hxx"
-#include "queryparam.hxx"
-#include "segmenttree.hxx"
-#include "subtotalparam.hxx"
-
-#include <vector>
-
-using namespace ::com::sun::star;
-
-namespace naturalsort {
-
-using namespace ::com::sun::star::i18n;
-
-/** Splits a given string into three parts: the prefix, number string, and
- the suffix.
-
- @param sWhole
- Original string to be split into pieces
-
- @param sPrefix
- Prefix string that consists of the part before the first number token
-
- @param sSuffix
- String after the last number token. This may still contain number strings.
-
- @param fNum
- Number converted from the middle number string
-
- @return Returns TRUE if a numeral element is found in a given string, or
- FALSE if no numeral element is found.
-*/
-bool SplitString( const rtl::OUString &sWhole,
- rtl::OUString &sPrefix, rtl::OUString &sSuffix, double &fNum )
-{
- i18n::LocaleDataItem aLocaleItem = ScGlobal::pLocaleData->getLocaleItem();
-
- // Get prefix element
- rtl::OUString sEmpty, sUser = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "-" ));
- ParseResult aPRPre = ScGlobal::pCharClass->parsePredefinedToken(
- KParseType::IDENTNAME, sWhole, 0,
- KParseTokens::ANY_LETTER, sUser, KParseTokens::ANY_LETTER, sUser );
- sPrefix = sWhole.copy( 0, aPRPre.EndPos );
-
- // Return FALSE if no numeral element is found
- if ( aPRPre.EndPos == sWhole.getLength() )
- return false;
-
- // Get numeral element
- sUser = aLocaleItem.decimalSeparator;
- ParseResult aPRNum = ScGlobal::pCharClass->parsePredefinedToken(
- KParseType::ANY_NUMBER, sWhole, aPRPre.EndPos,
- KParseTokens::ANY_NUMBER, sEmpty, KParseTokens::ANY_NUMBER, sUser );
-
- if ( aPRNum.EndPos == aPRPre.EndPos )
- return false;
-
- fNum = aPRNum.Value;
- sSuffix = sWhole.copy( aPRNum.EndPos );
-
- return true;
-}
-
-/** Naturally compares two given strings.
-
- This is the main function that should be called externally. It returns
- either 1, 0, or -1 depending on the comparison result of given two strings.
-
- @param sInput1
- Input string 1
-
- @param sInput2
- Input string 2
-
- @param bCaseSens
- Boolean value for case sensitivity
-
- @param pData
- Pointer to user defined sort list
-
- @param pCW
- Pointer to collator wrapper for normal string comparison
-
- @return Returnes 1 if sInput1 is greater, 0 if sInput1 == sInput2, and -1 if
- sInput2 is greater.
-*/
-short Compare( const String &sInput1, const String &sInput2,
- const sal_Bool bCaseSens, const ScUserListData* pData, const CollatorWrapper *pCW )
-{
- rtl::OUString sStr1( sInput1 ), sStr2( sInput2 ), sPre1, sSuf1, sPre2, sSuf2;
-
- do
- {
- double nNum1, nNum2;
- sal_Bool bNumFound1 = SplitString( sStr1, sPre1, sSuf1, nNum1 );
- sal_Bool bNumFound2 = SplitString( sStr2, sPre2, sSuf2, nNum2 );
-
- short nPreRes; // Prefix comparison result
- if ( pData )
- {
- if ( bCaseSens )
- {
- if ( !bNumFound1 || !bNumFound2 )
- return static_cast<short>(pData->Compare( sStr1, sStr2 ));
- else
- nPreRes = pData->Compare( sPre1, sPre2 );
- }
- else
- {
- if ( !bNumFound1 || !bNumFound2 )
- return static_cast<short>(pData->ICompare( sStr1, sStr2 ));
- else
- nPreRes = pData->ICompare( sPre1, sPre2 );
- }
- }
- else
- {
- if ( !bNumFound1 || !bNumFound2 )
- return static_cast<short>(pCW->compareString( sStr1, sStr2 ));
- else
- nPreRes = static_cast<short>(pCW->compareString( sPre1, sPre2 ));
- }
-
- // Prefix strings differ. Return immediately.
- if ( nPreRes != 0 ) return nPreRes;
-
- if ( nNum1 != nNum2 )
- {
- if ( nNum1 < nNum2 ) return -1;
- return static_cast<short>( nNum1 > nNum2 );
- }
-
- // The prefix and the first numerical elements are equal, but the suffix
- // strings may still differ. Stay in the loop.
-
- sStr1 = sSuf1;
- sStr2 = sSuf2;
-
- } while (true);
-
- return 0;
-}
-
-}
-
-// STATIC DATA -----------------------------------------------------------
-
-const sal_uInt16 nMaxSorts = 3; // maximale Anzahl Sortierkriterien in aSortParam
-
-struct ScSortInfo
-{
- ScBaseCell* pCell;
- SCCOLROW nOrg;
- DECL_FIXEDMEMPOOL_NEWDEL( ScSortInfo );
-};
-const sal_uInt16 nMemPoolSortInfo = (0x8000 - 64) / sizeof(ScSortInfo);
-IMPL_FIXEDMEMPOOL_NEWDEL( ScSortInfo, nMemPoolSortInfo, nMemPoolSortInfo )
-
-// END OF STATIC DATA -----------------------------------------------------
-
-
-class ScSortInfoArray
-{
-private:
- ScSortInfo** pppInfo[nMaxSorts];
- SCSIZE nCount;
- SCCOLROW nStart;
- sal_uInt16 nUsedSorts;
-
-public:
- ScSortInfoArray( sal_uInt16 nSorts, SCCOLROW nInd1, SCCOLROW nInd2 ) :
- nCount( nInd2 - nInd1 + 1 ), nStart( nInd1 ),
- nUsedSorts( Min( nSorts, nMaxSorts ) )
- {
- for ( sal_uInt16 nSort = 0; nSort < nUsedSorts; nSort++ )
- {
- ScSortInfo** ppInfo = new ScSortInfo* [nCount];
- for ( SCSIZE j = 0; j < nCount; j++ )
- ppInfo[j] = new ScSortInfo;
- pppInfo[nSort] = ppInfo;
- }
- }
- ~ScSortInfoArray()
- {
- for ( sal_uInt16 nSort = 0; nSort < nUsedSorts; nSort++ )
- {
- ScSortInfo** ppInfo = pppInfo[nSort];
- for ( SCSIZE j = 0; j < nCount; j++ )
- delete ppInfo[j];
- delete [] ppInfo;
- }
- }
- ScSortInfo* Get( sal_uInt16 nSort, SCCOLROW nInd )
- { return (pppInfo[nSort])[ nInd - nStart ]; }
- void Swap( SCCOLROW nInd1, SCCOLROW nInd2 )
- {
- SCSIZE n1 = static_cast<SCSIZE>(nInd1 - nStart);
- SCSIZE n2 = static_cast<SCSIZE>(nInd2 - nStart);
- for ( sal_uInt16 nSort = 0; nSort < nUsedSorts; nSort++ )
- {
- ScSortInfo** ppInfo = pppInfo[nSort];
- ScSortInfo* pTmp = ppInfo[n1];
- ppInfo[n1] = ppInfo[n2];
- ppInfo[n2] = pTmp;
- }
- }
- sal_uInt16 GetUsedSorts() const { return nUsedSorts; }
- ScSortInfo** GetFirstArray() const { return pppInfo[0]; }
- SCCOLROW GetStart() const { return nStart; }
- SCSIZE GetCount() const { return nCount; }
-};
-
-ScSortInfoArray* ScTable::CreateSortInfoArray( SCCOLROW nInd1, SCCOLROW nInd2 )
-{
- sal_uInt16 nUsedSorts = 1;
- while ( nUsedSorts < nMaxSorts && aSortParam.bDoSort[nUsedSorts] )
- nUsedSorts++;
- ScSortInfoArray* pArray = new ScSortInfoArray( nUsedSorts, nInd1, nInd2 );
- if ( aSortParam.bByRow )
- {
- for ( sal_uInt16 nSort = 0; nSort < nUsedSorts; nSort++ )
- {
- SCCOL nCol = static_cast<SCCOL>(aSortParam.nField[nSort]);
- ScColumn* pCol = &aCol[nCol];
- for ( SCROW nRow = nInd1; nRow <= nInd2; nRow++ )
- {
-//2do: FillSortInfo an ScColumn und Array abklappern statt Search in GetCell
- ScSortInfo* pInfo = pArray->Get( nSort, nRow );
- pInfo->pCell = pCol->GetCell( nRow );
- pInfo->nOrg = nRow;
- }
- }
- }
- else
- {
- for ( sal_uInt16 nSort = 0; nSort < nUsedSorts; nSort++ )
- {
- SCROW nRow = aSortParam.nField[nSort];
- for ( SCCOL nCol = static_cast<SCCOL>(nInd1);
- nCol <= static_cast<SCCOL>(nInd2); nCol++ )
- {
- ScSortInfo* pInfo = pArray->Get( nSort, nCol );
- pInfo->pCell = GetCell( nCol, nRow );
- pInfo->nOrg = nCol;
- }
- }
- }
- return pArray;
-}
-
-
-sal_Bool ScTable::IsSortCollatorGlobal() const
-{
- return pSortCollator == ScGlobal::GetCollator() ||
- pSortCollator == ScGlobal::GetCaseCollator();
-}
-
-
-void ScTable::InitSortCollator( const ScSortParam& rPar )
-{
- if ( rPar.aCollatorLocale.Language.getLength() )
- {
- if ( !pSortCollator || IsSortCollatorGlobal() )
- pSortCollator = new CollatorWrapper( pDocument->GetServiceManager() );
- pSortCollator->loadCollatorAlgorithm( rPar.aCollatorAlgorithm,
- rPar.aCollatorLocale, (rPar.bCaseSens ? 0 : SC_COLLATOR_IGNORES) );
- }
- else
- { // SYSTEM
- DestroySortCollator();
- pSortCollator = (rPar.bCaseSens ? ScGlobal::GetCaseCollator() :
- ScGlobal::GetCollator());
- }
-}
-
-
-void ScTable::DestroySortCollator()
-{
- if ( pSortCollator )
- {
- if ( !IsSortCollatorGlobal() )
- delete pSortCollator;
- pSortCollator = NULL;
- }
-}
-
-
-void ScTable::SortReorder( ScSortInfoArray* pArray, ScProgress& rProgress )
-{
- sal_Bool bByRow = aSortParam.bByRow;
- SCSIZE nCount = pArray->GetCount();
- SCCOLROW nStart = pArray->GetStart();
- ScSortInfo** ppInfo = pArray->GetFirstArray();
- ::std::vector<ScSortInfo*> aTable(nCount);
- SCSIZE nPos;
- for ( nPos = 0; nPos < nCount; nPos++ )
- aTable[ppInfo[nPos]->nOrg - nStart] = ppInfo[nPos];
-
- SCCOLROW nDest = nStart;
- for ( nPos = 0; nPos < nCount; nPos++, nDest++ )
- {
- SCCOLROW nOrg = ppInfo[nPos]->nOrg;
- if ( nDest != nOrg )
- {
- if ( bByRow )
- SwapRow( nDest, nOrg );
- else
- SwapCol( static_cast<SCCOL>(nDest), static_cast<SCCOL>(nOrg) );
- // neue Position des weggeswapten eintragen
- ScSortInfo* p = ppInfo[nPos];
- p->nOrg = nDest;
- ::std::swap(p, aTable[nDest-nStart]);
- p->nOrg = nOrg;
- ::std::swap(p, aTable[nOrg-nStart]);
- OSL_ENSURE( p == ppInfo[nPos], "SortReorder: nOrg MisMatch" );
- }
- rProgress.SetStateOnPercent( nPos );
- }
-}
-
-short ScTable::CompareCell( sal_uInt16 nSort,
- ScBaseCell* pCell1, SCCOL nCell1Col, SCROW nCell1Row,
- ScBaseCell* pCell2, SCCOL nCell2Col, SCROW nCell2Row )
-{
- short nRes = 0;
-
- CellType eType1 = CELLTYPE_NONE, eType2 = CELLTYPE_NONE;
- if (pCell1)
- {
- eType1 = pCell1->GetCellType();
- if (eType1 == CELLTYPE_NOTE)
- pCell1 = NULL;
- }
- if (pCell2)
- {
- eType2 = pCell2->GetCellType();
- if (eType2 == CELLTYPE_NOTE)
- pCell2 = NULL;
- }
-
- if (pCell1)
- {
- if (pCell2)
- {
- sal_Bool bStr1 = ( eType1 != CELLTYPE_VALUE );
- if ( eType1 == CELLTYPE_FORMULA && ((ScFormulaCell*)pCell1)->IsValue() )
- bStr1 = false;
- sal_Bool bStr2 = ( eType2 != CELLTYPE_VALUE );
- if ( eType2 == CELLTYPE_FORMULA && ((ScFormulaCell*)pCell2)->IsValue() )
- bStr2 = false;
-
- if ( bStr1 && bStr2 ) // nur Strings untereinander als String vergleichen!
- {
- String aStr1;
- String aStr2;
- if (eType1 == CELLTYPE_STRING)
- ((ScStringCell*)pCell1)->GetString(aStr1);
- else
- GetString(nCell1Col, nCell1Row, aStr1);
- if (eType2 == CELLTYPE_STRING)
- ((ScStringCell*)pCell2)->GetString(aStr2);
- else
- GetString(nCell2Col, nCell2Row, aStr2);
-
- sal_Bool bUserDef = aSortParam.bUserDef; // custom sort order
- sal_Bool bNaturalSort = aSortParam.bNaturalSort; // natural sort
- sal_Bool bCaseSens = aSortParam.bCaseSens; // case sensitivity
-
- if (bUserDef)
- {
- ScUserList* pList = ScGlobal::GetUserList();
- const ScUserListData* pData = (*pList)[aSortParam.nUserIndex];
-
- if (pData)
- {
- if ( bNaturalSort )
- nRes = naturalsort::Compare( aStr1, aStr2, bCaseSens, pData, pSortCollator );
- else
- {
- if ( bCaseSens )
- nRes = sal::static_int_cast<short>( pData->Compare(aStr1, aStr2) );
- else
- nRes = sal::static_int_cast<short>( pData->ICompare(aStr1, aStr2) );
- }
- }
- else
- bUserDef = false;
-
- }
- if (!bUserDef)
- {
- if ( bNaturalSort )
- nRes = naturalsort::Compare( aStr1, aStr2, bCaseSens, NULL, pSortCollator );
- else
- nRes = static_cast<short>( pSortCollator->compareString( aStr1, aStr2 ) );
- }
- }
- else if ( bStr1 ) // String <-> Zahl
- nRes = 1; // Zahl vorne
- else if ( bStr2 ) // Zahl <-> String
- nRes = -1; // Zahl vorne
- else // Zahlen untereinander
- {
- double nVal1;
- double nVal2;
- if (eType1 == CELLTYPE_VALUE)
- nVal1 = ((ScValueCell*)pCell1)->GetValue();
- else if (eType1 == CELLTYPE_FORMULA)
- nVal1 = ((ScFormulaCell*)pCell1)->GetValue();
- else
- nVal1 = 0;
- if (eType2 == CELLTYPE_VALUE)
- nVal2 = ((ScValueCell*)pCell2)->GetValue();
- else if (eType2 == CELLTYPE_FORMULA)
- nVal2 = ((ScFormulaCell*)pCell2)->GetValue();
- else
- nVal2 = 0;
- if (nVal1 < nVal2)
- nRes = -1;
- else if (nVal1 > nVal2)
- nRes = 1;
- }
- if ( !aSortParam.bAscending[nSort] )
- nRes = -nRes;
- }
- else
- nRes = -1;
- }
- else
- {
- if ( pCell2 )
- nRes = 1;
- else
- nRes = 0; // beide leer
- }
- return nRes;
-}
-
-short ScTable::Compare( ScSortInfoArray* pArray, SCCOLROW nIndex1, SCCOLROW nIndex2 )
-{
- short nRes;
- sal_uInt16 nSort = 0;
- do
- {
- ScSortInfo* pInfo1 = pArray->Get( nSort, nIndex1 );
- ScSortInfo* pInfo2 = pArray->Get( nSort, nIndex2 );
- if ( aSortParam.bByRow )
- nRes = CompareCell( nSort,
- pInfo1->pCell, static_cast<SCCOL>(aSortParam.nField[nSort]), pInfo1->nOrg,
- pInfo2->pCell, static_cast<SCCOL>(aSortParam.nField[nSort]), pInfo2->nOrg );
- else
- nRes = CompareCell( nSort,
- pInfo1->pCell, static_cast<SCCOL>(pInfo1->nOrg), aSortParam.nField[nSort],
- pInfo2->pCell, static_cast<SCCOL>(pInfo2->nOrg), aSortParam.nField[nSort] );
- } while ( nRes == 0 && ++nSort < pArray->GetUsedSorts() );
- if( nRes == 0 )
- {
- ScSortInfo* pInfo1 = pArray->Get( 0, nIndex1 );
- ScSortInfo* pInfo2 = pArray->Get( 0, nIndex2 );
- if( pInfo1->nOrg < pInfo2->nOrg )
- nRes = -1;
- else if( pInfo1->nOrg > pInfo2->nOrg )
- nRes = 1;
- }
- return nRes;
-}
-
-void ScTable::QuickSort( ScSortInfoArray* pArray, SCsCOLROW nLo, SCsCOLROW nHi )
-{
- if ((nHi - nLo) == 1)
- {
- if (Compare(pArray, nLo, nHi) > 0)
- pArray->Swap( nLo, nHi );
- }
- else
- {
- SCsCOLROW ni = nLo;
- SCsCOLROW nj = nHi;
- do
- {
- while ((ni <= nHi) && (Compare(pArray, ni, nLo)) < 0)
- ni++;
- while ((nj >= nLo) && (Compare(pArray, nLo, nj)) < 0)
- nj--;
- if (ni <= nj)
- {
- if (ni != nj)
- pArray->Swap( ni, nj );
- ni++;
- nj--;
- }
- } while (ni < nj);
- if ((nj - nLo) < (nHi - ni))
- {
- if (nLo < nj)
- QuickSort(pArray, nLo, nj);
- if (ni < nHi)
- QuickSort(pArray, ni, nHi);
- }
- else
- {
- if (ni < nHi)
- QuickSort(pArray, ni, nHi);
- if (nLo < nj)
- QuickSort(pArray, nLo, nj);
- }
- }
-}
-
-void ScTable::SwapCol(SCCOL nCol1, SCCOL nCol2)
-{
- for (SCROW nRow = aSortParam.nRow1; nRow <= aSortParam.nRow2; nRow++)
- {
- aCol[nCol1].SwapCell(nRow, aCol[nCol2]);
- if (aSortParam.bIncludePattern)
- {
- const ScPatternAttr* pPat1 = GetPattern(nCol1, nRow);
- const ScPatternAttr* pPat2 = GetPattern(nCol2, nRow);
- if (pPat1 != pPat2)
- {
- SetPattern(nCol1, nRow, *pPat2, sal_True);
- SetPattern(nCol2, nRow, *pPat1, sal_True);
- }
- }
- }
-}
-
-void ScTable::SwapRow(SCROW nRow1, SCROW nRow2)
-{
- for (SCCOL nCol = aSortParam.nCol1; nCol <= aSortParam.nCol2; nCol++)
- {
- aCol[nCol].SwapRow(nRow1, nRow2);
- if (aSortParam.bIncludePattern)
- {
- const ScPatternAttr* pPat1 = GetPattern(nCol, nRow1);
- const ScPatternAttr* pPat2 = GetPattern(nCol, nRow2);
- if (pPat1 != pPat2)
- {
- SetPattern(nCol, nRow1, *pPat2, sal_True);
- SetPattern(nCol, nRow2, *pPat1, sal_True);
- }
- }
- }
- if (bGlobalKeepQuery)
- {
- bool bRow1Hidden = RowHidden(nRow1);
- bool bRow2Hidden = RowHidden(nRow2);
- SetRowHidden(nRow1, nRow1, bRow2Hidden);
- SetRowHidden(nRow2, nRow2, bRow1Hidden);
-
- bool bRow1Filtered = RowFiltered(nRow1);
- bool bRow2Filtered = RowFiltered(nRow2);
- SetRowFiltered(nRow1, nRow1, bRow2Filtered);
- SetRowFiltered(nRow2, nRow2, bRow1Filtered);
- }
-}
-
-short ScTable::Compare(SCCOLROW nIndex1, SCCOLROW nIndex2)
-{
- short nRes;
- sal_uInt16 nSort = 0;
- if (aSortParam.bByRow)
- {
- do
- {
- SCCOL nCol = static_cast<SCCOL>(aSortParam.nField[nSort]);
- ScBaseCell* pCell1 = aCol[nCol].GetCell( nIndex1 );
- ScBaseCell* pCell2 = aCol[nCol].GetCell( nIndex2 );
- nRes = CompareCell( nSort, pCell1, nCol, nIndex1, pCell2, nCol, nIndex2 );
- } while ( nRes == 0 && ++nSort < nMaxSorts && aSortParam.bDoSort[nSort] );
- }
- else
- {
- do
- {
- SCROW nRow = aSortParam.nField[nSort];
- ScBaseCell* pCell1 = aCol[nIndex1].GetCell( nRow );
- ScBaseCell* pCell2 = aCol[nIndex2].GetCell( nRow );
- nRes = CompareCell( nSort, pCell1, static_cast<SCCOL>(nIndex1),
- nRow, pCell2, static_cast<SCCOL>(nIndex2), nRow );
- } while ( nRes == 0 && ++nSort < nMaxSorts && aSortParam.bDoSort[nSort] );
- }
- return nRes;
-}
-
-sal_Bool ScTable::IsSorted( SCCOLROW nStart, SCCOLROW nEnd ) // ueber aSortParam
-{
- for (SCCOLROW i=nStart; i<nEnd; i++)
- {
- if (Compare( i, i+1 ) > 0)
- return false;
- }
- return sal_True;
-}
-
-void ScTable::DecoladeRow( ScSortInfoArray* pArray, SCROW nRow1, SCROW nRow2 )
-{
- SCROW nRow;
- SCROW nMax = nRow2 - nRow1;
- for (SCROW i = nRow1; (i + 4) <= nRow2; i += 4)
- {
- nRow = rand() % nMax;
- pArray->Swap(i, nRow1 + nRow);
- }
-}
-
-void ScTable::Sort(const ScSortParam& rSortParam, sal_Bool bKeepQuery)
-{
- aSortParam = rSortParam;
- InitSortCollator( rSortParam );
- bGlobalKeepQuery = bKeepQuery;
- if (rSortParam.bByRow)
- {
- SCROW nLastRow = 0;
- for (SCCOL nCol = aSortParam.nCol1; nCol <= aSortParam.nCol2; nCol++)
- nLastRow = Max(nLastRow, aCol[nCol].GetLastDataPos());
- nLastRow = Min(nLastRow, aSortParam.nRow2);
- SCROW nRow1 = (rSortParam.bHasHeader ?
- aSortParam.nRow1 + 1 : aSortParam.nRow1);
- if (!IsSorted(nRow1, nLastRow))
- {
- ScProgress aProgress( pDocument->GetDocumentShell(),
- ScGlobal::GetRscString(STR_PROGRESS_SORTING), nLastRow - nRow1 );
- ScSortInfoArray* pArray = CreateSortInfoArray( nRow1, nLastRow );
- if ( nLastRow - nRow1 > 255 )
- DecoladeRow( pArray, nRow1, nLastRow );
- QuickSort( pArray, nRow1, nLastRow );
- SortReorder( pArray, aProgress );
- delete pArray;
- // #i59745# update position of caption objects of cell notes
- ScNoteUtil::UpdateCaptionPositions( *pDocument, ScRange( aSortParam.nCol1, nRow1, nTab, aSortParam.nCol2, nLastRow, nTab ) );
- }
- }
- else
- {
- SCCOL nLastCol;
- for (nLastCol = aSortParam.nCol2;
- (nLastCol > aSortParam.nCol1) && aCol[nLastCol].IsEmptyBlock(aSortParam.nRow1, aSortParam.nRow2); nLastCol--)
- {
- }
- SCCOL nCol1 = (rSortParam.bHasHeader ?
- aSortParam.nCol1 + 1 : aSortParam.nCol1);
- if (!IsSorted(nCol1, nLastCol))
- {
- ScProgress aProgress( pDocument->GetDocumentShell(),
- ScGlobal::GetRscString(STR_PROGRESS_SORTING), nLastCol - nCol1 );
- ScSortInfoArray* pArray = CreateSortInfoArray( nCol1, nLastCol );
- QuickSort( pArray, nCol1, nLastCol );
- SortReorder( pArray, aProgress );
- delete pArray;
- // #i59745# update position of caption objects of cell notes
- ScNoteUtil::UpdateCaptionPositions( *pDocument, ScRange( nCol1, aSortParam.nRow1, nTab, nLastCol, aSortParam.nRow2, nTab ) );
- }
- }
- DestroySortCollator();
-}
-
-
-// Testen, ob beim Loeschen von Zwischenergebnissen andere Daten mit geloescht werden
-// (fuer Hinweis-Box)
-
-sal_Bool ScTable::TestRemoveSubTotals( const ScSubTotalParam& rParam )
-{
- SCCOL nStartCol = rParam.nCol1;
- SCROW nStartRow = rParam.nRow1 + 1; // Header
- SCCOL nEndCol = rParam.nCol2;
- SCROW nEndRow = rParam.nRow2;
-
- SCCOL nCol;
- SCROW nRow;
- ScBaseCell* pCell;
-
- sal_Bool bWillDelete = false;
- for ( nCol=nStartCol; nCol<=nEndCol && !bWillDelete; nCol++ )
- {
- ScColumnIterator aIter( &aCol[nCol],nStartRow,nEndRow );
- while ( aIter.Next( nRow, pCell ) && !bWillDelete )
- {
- if ( pCell->GetCellType() == CELLTYPE_FORMULA )
- if (((ScFormulaCell*)pCell)->IsSubTotal())
- {
- for (SCCOL nTestCol=0; nTestCol<=MAXCOL; nTestCol++)
- if (nTestCol<nStartCol || nTestCol>nEndCol)
- if (aCol[nTestCol].HasDataAt(nRow))
- bWillDelete = sal_True;
- }
- }
- }
- return bWillDelete;
-}
-
-// alte Ergebnisse loeschen
-// rParam.nRow2 wird veraendert !
-
-void ScTable::RemoveSubTotals( ScSubTotalParam& rParam )
-{
- SCCOL nStartCol = rParam.nCol1;
- SCROW nStartRow = rParam.nRow1 + 1; // Header
- SCCOL nEndCol = rParam.nCol2;
- SCROW nEndRow = rParam.nRow2; // wird veraendert
-
- SCCOL nCol;
- SCROW nRow;
- ScBaseCell* pCell;
-
- for ( nCol=nStartCol; nCol<=nEndCol; nCol++ )
- {
- ScColumnIterator aIter( &aCol[nCol],nStartRow,nEndRow );
- while ( aIter.Next( nRow, pCell ) )
- {
- if ( pCell->GetCellType() == CELLTYPE_FORMULA )
- if (((ScFormulaCell*)pCell)->IsSubTotal())
- {
- RemoveRowBreak(nRow+1, false, true);
- pDocument->DeleteRow( 0,nTab, MAXCOL,nTab, nRow, 1 );
- --nEndRow;
- aIter = ScColumnIterator( &aCol[nCol],nRow,nEndRow );
- }
- }
- }
-
- rParam.nRow2 = nEndRow; // neues Ende
-}
-
-// harte Zahlenformate loeschen (fuer Ergebnisformeln)
-
-void lcl_RemoveNumberFormat( ScTable* pTab, SCCOL nCol, SCROW nRow )
-{
- const ScPatternAttr* pPattern = pTab->GetPattern( nCol, nRow );
- if ( pPattern->GetItemSet().GetItemState( ATTR_VALUE_FORMAT, false )
- == SFX_ITEM_SET )
- {
- ScPatternAttr aNewPattern( *pPattern );
- SfxItemSet& rSet = aNewPattern.GetItemSet();
- rSet.ClearItem( ATTR_VALUE_FORMAT );
- rSet.ClearItem( ATTR_LANGUAGE_FORMAT );
- pTab->SetPattern( nCol, nRow, aNewPattern, sal_True );
- }
-}
-
-
-// at least MSC needs this at linkage level to be able to use it in a template
-typedef struct lcl_ScTable_DoSubTotals_RowEntry
-{
- sal_uInt16 nGroupNo;
- SCROW nSubStartRow;
- SCROW nDestRow;
- SCROW nFuncStart;
- SCROW nFuncEnd;
-} RowEntry;
-
-// neue Zwischenergebnisse
-// rParam.nRow2 wird veraendert !
-
-sal_Bool ScTable::DoSubTotals( ScSubTotalParam& rParam )
-{
- SCCOL nStartCol = rParam.nCol1;
- SCROW nStartRow = rParam.nRow1 + 1; // Header
- SCCOL nEndCol = rParam.nCol2;
- SCROW nEndRow = rParam.nRow2; // wird veraendert
- sal_uInt16 i;
-
- // Leerzeilen am Ende weglassen,
- // damit alle Ueberlaeufe (MAXROW) bei InsertRow gefunden werden (#35180#)
- // Wenn sortiert wurde, sind alle Leerzeilen am Ende.
- SCSIZE nEmpty = GetEmptyLinesInBlock( nStartCol, nStartRow, nEndCol, nEndRow, DIR_BOTTOM );
- nEndRow -= nEmpty;
-
- sal_uInt16 nLevelCount = 0; // Anzahl Gruppierungen
- sal_Bool bDoThis = sal_True;
- for (i=0; i<MAXSUBTOTAL && bDoThis; i++)
- if (rParam.bGroupActive[i])
- nLevelCount = i+1;
- else
- bDoThis = false;
-
- if (nLevelCount==0) // nichts tun
- return sal_True;
-
- SCCOL* nGroupCol = rParam.nField; // Spalten nach denen
- // gruppiert wird
-
- // Durch (leer) als eigene Kategorie muss immer auf
- // Teilergebniszeilen aus den anderen Spalten getestet werden
- // (frueher nur, wenn eine Spalte mehrfach vorkam)
- sal_Bool bTestPrevSub = ( nLevelCount > 1 );
-
- String aSubString;
- String aOutString;
-
- sal_Bool bIgnoreCase = !rParam.bCaseSens;
-
- String *pCompString[MAXSUBTOTAL]; // Pointer wegen Compiler-Problemen
- for (i=0; i<MAXSUBTOTAL; i++)
- pCompString[i] = new String;
-
- //! sortieren?
-
- ScStyleSheet* pStyle = (ScStyleSheet*) pDocument->GetStyleSheetPool()->Find(
- ScGlobal::GetRscString(STR_STYLENAME_RESULT), SFX_STYLE_FAMILY_PARA );
-
- sal_Bool bSpaceLeft = sal_True; // Erfolg beim Einfuegen?
-
- // For performance reasons collect formula entries so their
- // references don't have to be tested for updates each time a new row is
- // inserted
- RowEntry aRowEntry;
- ::std::vector< RowEntry > aRowVector;
-
- for (sal_uInt16 nLevel=0; nLevel<=nLevelCount && bSpaceLeft; nLevel++) // incl. Gesamtergebnis
- {
- sal_Bool bTotal = ( nLevel == nLevelCount );
- aRowEntry.nGroupNo = bTotal ? 0 : (nLevelCount-nLevel-1);
-
- // how many results per level
- SCCOL nResCount = rParam.nSubTotals[aRowEntry.nGroupNo];
- // result functions
- ScSubTotalFunc* eResFunc = rParam.pFunctions[aRowEntry.nGroupNo];
-
- if (nResCount > 0) // sonst nur sortieren
- {
- for (i=0; i<=aRowEntry.nGroupNo; i++)
- {
- GetString( nGroupCol[i], nStartRow, aSubString );
- if ( bIgnoreCase )
- *pCompString[i] = ScGlobal::pCharClass->upper( aSubString );
- else
- *pCompString[i] = aSubString;
- } // aSubString bleibt auf dem letzten stehen
-
- sal_Bool bBlockVis = false; // Gruppe eingeblendet?
- aRowEntry.nSubStartRow = nStartRow;
- for (SCROW nRow=nStartRow; nRow<=nEndRow+1 && bSpaceLeft; nRow++)
- {
- sal_Bool bChanged;
- if (nRow>nEndRow)
- bChanged = sal_True;
- else
- {
- bChanged = false;
- if (!bTotal)
- {
- String aString;
- for (i=0; i<=aRowEntry.nGroupNo && !bChanged; i++)
- {
- GetString( nGroupCol[i], nRow, aString );
- if (bIgnoreCase)
- ScGlobal::pCharClass->toUpper( aString );
- // wenn sortiert, ist "leer" eine eigene Gruppe
- // sonst sind leere Zellen unten erlaubt
- bChanged = ( ( aString.Len() || rParam.bDoSort ) &&
- aString != *pCompString[i] );
- }
- if ( bChanged && bTestPrevSub )
- {
- // No group change on rows that will contain subtotal formulas
- for ( ::std::vector< RowEntry >::const_iterator
- iEntry( aRowVector.begin());
- iEntry != aRowVector.end(); ++iEntry)
- {
- if ( iEntry->nDestRow == nRow )
- {
- bChanged = false;
- break;
- }
- }
- }
- }
- }
- if ( bChanged )
- {
- aRowEntry.nDestRow = nRow;
- aRowEntry.nFuncStart = aRowEntry.nSubStartRow;
- aRowEntry.nFuncEnd = nRow-1;
-
- bSpaceLeft = pDocument->InsertRow( 0, nTab, MAXCOL, nTab,
- aRowEntry.nDestRow, 1 );
- DBShowRow( aRowEntry.nDestRow, bBlockVis );
- bBlockVis = false;
- if ( rParam.bPagebreak && nRow < MAXROW &&
- aRowEntry.nSubStartRow != nStartRow && nLevel == 0)
- SetRowBreak(aRowEntry.nSubStartRow, false, true);
-
- if (bSpaceLeft)
- {
- for ( ::std::vector< RowEntry >::iterator iMove(
- aRowVector.begin() );
- iMove != aRowVector.end(); ++iMove)
- {
- if ( aRowEntry.nDestRow <= iMove->nSubStartRow )
- ++iMove->nSubStartRow;
- if ( aRowEntry.nDestRow <= iMove->nDestRow )
- ++iMove->nDestRow;
- if ( aRowEntry.nDestRow <= iMove->nFuncStart )
- ++iMove->nFuncStart;
- if ( aRowEntry.nDestRow <= iMove->nFuncEnd )
- ++iMove->nFuncEnd;
- }
- // collect formula positions
- aRowVector.push_back( aRowEntry );
-
- if (bTotal) // "Gesamtergebnis"
- aOutString = ScGlobal::GetRscString( STR_TABLE_GESAMTERGEBNIS );
- else
- { // " Ergebnis"
- aOutString = aSubString;
- if (!aOutString.Len())
- aOutString = ScGlobal::GetRscString( STR_EMPTYDATA );
- aOutString += ' ';
- sal_uInt16 nStrId = STR_TABLE_ERGEBNIS;
- if ( nResCount == 1 )
- switch ( eResFunc[0] )
- {
- case SUBTOTAL_FUNC_AVE: nStrId = STR_FUN_TEXT_AVG; break;
- case SUBTOTAL_FUNC_CNT:
- case SUBTOTAL_FUNC_CNT2: nStrId = STR_FUN_TEXT_COUNT; break;
- case SUBTOTAL_FUNC_MAX: nStrId = STR_FUN_TEXT_MAX; break;
- case SUBTOTAL_FUNC_MIN: nStrId = STR_FUN_TEXT_MIN; break;
- case SUBTOTAL_FUNC_PROD: nStrId = STR_FUN_TEXT_PRODUCT; break;
- case SUBTOTAL_FUNC_STD:
- case SUBTOTAL_FUNC_STDP: nStrId = STR_FUN_TEXT_STDDEV; break;
- case SUBTOTAL_FUNC_SUM: nStrId = STR_FUN_TEXT_SUM; break;
- case SUBTOTAL_FUNC_VAR:
- case SUBTOTAL_FUNC_VARP: nStrId = STR_FUN_TEXT_VAR; break;
- default:
- {
- // added to avoid warnings
- }
- }
- aOutString += ScGlobal::GetRscString( nStrId );
- }
- SetString( nGroupCol[aRowEntry.nGroupNo], aRowEntry.nDestRow, nTab, aOutString );
- ApplyStyle( nGroupCol[aRowEntry.nGroupNo], aRowEntry.nDestRow, *pStyle );
-
- ++nRow;
- ++nEndRow;
- aRowEntry.nSubStartRow = nRow;
- for (i=0; i<=aRowEntry.nGroupNo; i++)
- {
- GetString( nGroupCol[i], nRow, aSubString );
- if ( bIgnoreCase )
- *pCompString[i] = ScGlobal::pCharClass->upper( aSubString );
- else
- *pCompString[i] = aSubString;
- }
- }
- }
- bBlockVis = !RowFiltered(nRow);
- }
- }
- }
-
- // now insert the formulas
- ScComplexRefData aRef;
- aRef.InitFlags();
- aRef.Ref1.nTab = nTab;
- aRef.Ref2.nTab = nTab;
- for ( ::std::vector< RowEntry >::const_iterator iEntry( aRowVector.begin());
- iEntry != aRowVector.end(); ++iEntry)
- {
- SCCOL nResCount = rParam.nSubTotals[iEntry->nGroupNo];
- SCCOL* nResCols = rParam.pSubTotals[iEntry->nGroupNo];
- ScSubTotalFunc* eResFunc = rParam.pFunctions[iEntry->nGroupNo];
- for ( SCCOL nResult=0; nResult < nResCount; ++nResult )
- {
- aRef.Ref1.nCol = nResCols[nResult];
- aRef.Ref1.nRow = iEntry->nFuncStart;
- aRef.Ref2.nCol = nResCols[nResult];
- aRef.Ref2.nRow = iEntry->nFuncEnd;
-
- ScTokenArray aArr;
- aArr.AddOpCode( ocSubTotal );
- aArr.AddOpCode( ocOpen );
- aArr.AddDouble( (double) eResFunc[nResult] );
- aArr.AddOpCode( ocSep );
- aArr.AddDoubleReference( aRef );
- aArr.AddOpCode( ocClose );
- aArr.AddOpCode( ocStop );
- ScBaseCell* pCell = new ScFormulaCell( pDocument, ScAddress(
- nResCols[nResult], iEntry->nDestRow, nTab), &aArr );
- PutCell( nResCols[nResult], iEntry->nDestRow, pCell );
-
- if ( nResCols[nResult] != nGroupCol[iEntry->nGroupNo] )
- {
- ApplyStyle( nResCols[nResult], iEntry->nDestRow, *pStyle );
-
- // Zahlformat loeschen
- lcl_RemoveNumberFormat( this, nResCols[nResult], iEntry->nDestRow );
- }
- }
-
- }
-
- //! je nach Einstellung Zwischensummen-Zeilen nach oben verschieben ?
-
- //! Outlines direkt erzeugen?
-
- if (bSpaceLeft)
- DoAutoOutline( nStartCol, nStartRow, nEndCol, nEndRow );
-
- for (i=0; i<MAXSUBTOTAL; i++)
- delete pCompString[i];
-
- rParam.nRow2 = nEndRow; // neues Ende
- return bSpaceLeft;
-}
-
-
-sal_Bool ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam,
- sal_Bool* pSpecial /* =NULL */ , ScBaseCell* pCell /* =NULL */ ,
- sal_Bool* pbTestEqualCondition /* = NULL */ )
-{
- if (!rParam.GetEntry(0).bDoQuery)
- return sal_True;
-
- //---------------------------------------------------------------
-
- const SCSIZE nFixedBools = 32;
- sal_Bool aBool[nFixedBools];
- sal_Bool aTest[nFixedBools];
- SCSIZE nEntryCount = rParam.GetEntryCount();
- sal_Bool* pPasst = ( nEntryCount <= nFixedBools ? &aBool[0] : new sal_Bool[nEntryCount] );
- sal_Bool* pTest = ( nEntryCount <= nFixedBools ? &aTest[0] : new sal_Bool[nEntryCount] );
-
- long nPos = -1;
- SCSIZE i = 0;
- sal_Bool bMatchWholeCell = pDocument->GetDocOptions().IsMatchWholeCell();
- CollatorWrapper* pCollator = (rParam.bCaseSens ? ScGlobal::GetCaseCollator() :
- ScGlobal::GetCollator());
- ::utl::TransliterationWrapper* pTransliteration = (rParam.bCaseSens ?
- ScGlobal::GetCaseTransliteration() : ScGlobal::GetpTransliteration());
-
- while ( (i < nEntryCount) && rParam.GetEntry(i).bDoQuery )
- {
- ScQueryEntry& rEntry = rParam.GetEntry(i);
- // we can only handle one single direct query
- if ( !pCell || i > 0 )
- pCell = GetCell( static_cast<SCCOL>(rEntry.nField), nRow );
-
- sal_Bool bOk = false;
- sal_Bool bTestEqual = false;
-
- if ( pSpecial && pSpecial[i] )
- {
- if (rEntry.nVal == SC_EMPTYFIELDS)
- bOk = !( aCol[rEntry.nField].HasDataAt( nRow ) );
- else // if (rEntry.nVal == SC_NONEMPTYFIELDS)
- bOk = aCol[rEntry.nField].HasDataAt( nRow );
- }
- else if ( !rEntry.bQueryByString && (pCell ? pCell->HasValueData() :
- HasValueData( static_cast<SCCOL>(rEntry.nField), nRow)))
- { // by Value
- double nCellVal;
- if ( pCell )
- {
- switch ( pCell->GetCellType() )
- {
- case CELLTYPE_VALUE :
- nCellVal = ((ScValueCell*)pCell)->GetValue();
- break;
- case CELLTYPE_FORMULA :
- nCellVal = ((ScFormulaCell*)pCell)->GetValue();
- break;
- default:
- nCellVal = 0.0;
- }
-
- }
- else
- nCellVal = GetValue( static_cast<SCCOL>(rEntry.nField), nRow );
-
- /* NOTE: lcl_PrepareQuery() prepares a filter query such that if a
- * date+time format was queried rEntry.bQueryByDate is not set. In
- * case other queries wanted to use this mechanism they should do
- * the same, in other words only if rEntry.nVal is an integer value
- * rEntry.bQueryByDate should be true and the time fraction be
- * stripped here. */
- if (rEntry.bQueryByDate)
- {
- sal_uInt32 nNumFmt = GetNumberFormat(static_cast<SCCOL>(rEntry.nField), nRow);
- const SvNumberformat* pEntry = pDocument->GetFormatTable()->GetEntry(nNumFmt);
- if (pEntry)
- {
- short nNumFmtType = pEntry->GetType();
- /* NOTE: Omitting the check for absence of
- * NUMBERFORMAT_TIME would include also date+time formatted
- * values of the same day. That may be desired in some
- * cases, querying all time values of a day, but confusing
- * in other cases. A user can always setup a standard
- * filter query for x >= date AND x < date+1 */
- if ((nNumFmtType & NUMBERFORMAT_DATE) && !(nNumFmtType & NUMBERFORMAT_TIME))
- {
- // The format is of date type. Strip off the time
- // element.
- nCellVal = ::rtl::math::approxFloor(nCellVal);
- }
- }
- }
-
- switch (rEntry.eOp)
- {
- case SC_EQUAL :
- bOk = ::rtl::math::approxEqual( nCellVal, rEntry.nVal );
- break;
- case SC_LESS :
- bOk = (nCellVal < rEntry.nVal) && !::rtl::math::approxEqual( nCellVal, rEntry.nVal );
- break;
- case SC_GREATER :
- bOk = (nCellVal > rEntry.nVal) && !::rtl::math::approxEqual( nCellVal, rEntry.nVal );
- break;
- case SC_LESS_EQUAL :
- bOk = (nCellVal < rEntry.nVal) || ::rtl::math::approxEqual( nCellVal, rEntry.nVal );
- if ( bOk && pbTestEqualCondition )
- bTestEqual = ::rtl::math::approxEqual( nCellVal, rEntry.nVal );
- break;
- case SC_GREATER_EQUAL :
- bOk = (nCellVal > rEntry.nVal) || ::rtl::math::approxEqual( nCellVal, rEntry.nVal );
- if ( bOk && pbTestEqualCondition )
- bTestEqual = ::rtl::math::approxEqual( nCellVal, rEntry.nVal );
- break;
- case SC_NOT_EQUAL :
- bOk = !::rtl::math::approxEqual( nCellVal, rEntry.nVal );
- break;
- default:
- {
- // added to avoid warnings
- }
- }
- }
- else if ( (rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL) ||
- (rEntry.eOp == SC_CONTAINS || rEntry.eOp == SC_DOES_NOT_CONTAIN ||
- rEntry.eOp == SC_BEGINS_WITH || rEntry.eOp == SC_ENDS_WITH ||
- rEntry.eOp == SC_DOES_NOT_BEGIN_WITH || rEntry.eOp == SC_DOES_NOT_END_WITH) ||
- (rEntry.bQueryByString && (pCell ? pCell->HasStringData() :
- HasStringData(
- static_cast<SCCOL>(rEntry.nField),
- nRow))))
- { // by String
- String aCellStr;
- if( rEntry.eOp == SC_CONTAINS || rEntry.eOp == SC_DOES_NOT_CONTAIN
- || rEntry.eOp == SC_BEGINS_WITH || rEntry.eOp == SC_ENDS_WITH
- || rEntry.eOp == SC_DOES_NOT_BEGIN_WITH || rEntry.eOp == SC_DOES_NOT_END_WITH )
- bMatchWholeCell = false;
- if ( pCell )
- {
- if (pCell->GetCellType() != CELLTYPE_NOTE)
- {
- sal_uLong nFormat = GetNumberFormat( static_cast<SCCOL>(rEntry.nField), nRow );
- ScCellFormat::GetInputString( pCell, nFormat, aCellStr, *(pDocument->GetFormatTable()) );
- }
- }
- else
- GetInputString( static_cast<SCCOL>(rEntry.nField), nRow, aCellStr );
-
- sal_Bool bRealRegExp = (rParam.bRegExp && ((rEntry.eOp == SC_EQUAL)
- || (rEntry.eOp == SC_NOT_EQUAL) || (rEntry.eOp == SC_CONTAINS)
- || (rEntry.eOp == SC_DOES_NOT_CONTAIN) || (rEntry.eOp == SC_BEGINS_WITH)
- || (rEntry.eOp == SC_ENDS_WITH) || (rEntry.eOp == SC_DOES_NOT_BEGIN_WITH)
- || (rEntry.eOp == SC_DOES_NOT_END_WITH)));
- sal_Bool bTestRegExp = (pbTestEqualCondition && rParam.bRegExp
- && ((rEntry.eOp == SC_LESS_EQUAL)
- || (rEntry.eOp == SC_GREATER_EQUAL)));
- if ( bRealRegExp || bTestRegExp )
- {
- xub_StrLen nStart = 0;
- xub_StrLen nEnd = aCellStr.Len();
-
- // from 614 on, nEnd is behind the found text
- sal_Bool bMatch = false;
- if ( rEntry.eOp == SC_ENDS_WITH || rEntry.eOp == SC_DOES_NOT_END_WITH )
- {
- nEnd = 0;
- nStart = aCellStr.Len();
- bMatch = (sal_Bool) rEntry.GetSearchTextPtr( rParam.bCaseSens )
- ->SearchBkwrd( aCellStr, &nStart, &nEnd );
- }
- else
- {
- bMatch = (sal_Bool) rEntry.GetSearchTextPtr( rParam.bCaseSens )
- ->SearchFrwrd( aCellStr, &nStart, &nEnd );
- }
- if ( bMatch && bMatchWholeCell
- && (nStart != 0 || nEnd != aCellStr.Len()) )
- bMatch = false; // RegExp must match entire cell string
- if ( bRealRegExp )
- switch (rEntry.eOp)
- {
- case SC_EQUAL:
- case SC_CONTAINS:
- bOk = bMatch;
- break;
- case SC_NOT_EQUAL:
- case SC_DOES_NOT_CONTAIN:
- bOk = !bMatch;
- break;
- case SC_BEGINS_WITH:
- bOk = ( bMatch && (nStart == 0) );
- break;
- case SC_DOES_NOT_BEGIN_WITH:
- bOk = !( bMatch && (nStart == 0) );
- break;
- case SC_ENDS_WITH:
- bOk = ( bMatch && (nEnd == aCellStr.Len()) );
- break;
- case SC_DOES_NOT_END_WITH:
- bOk = !( bMatch && (nEnd == aCellStr.Len()) );
- break;
- default:
- {
- // added to avoid warnings
- }
- }
- else
- bTestEqual = bMatch;
- }
- if ( !bRealRegExp )
- {
- if ( rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL
- || rEntry.eOp == SC_CONTAINS || rEntry.eOp == SC_DOES_NOT_CONTAIN
- || rEntry.eOp == SC_BEGINS_WITH || rEntry.eOp == SC_ENDS_WITH
- || rEntry.eOp == SC_DOES_NOT_BEGIN_WITH || rEntry.eOp == SC_DOES_NOT_END_WITH )
- {
- if ( !rEntry.bQueryByString && rEntry.pStr->Len() == 0 )
- {
- // #i18374# When used from functions (match, countif, sumif, vlookup, hlookup, lookup),
- // the query value is assigned directly, and the string is empty. In that case,
- // don't find any string (isEqual would find empty string results in formula cells).
- bOk = false;
- if ( rEntry.eOp == SC_NOT_EQUAL )
- bOk = !bOk;
- }
- else if ( bMatchWholeCell )
- {
- bOk = pTransliteration->isEqual( aCellStr, *rEntry.pStr );
- if ( rEntry.eOp == SC_NOT_EQUAL )
- bOk = !bOk;
- }
- else
- {
- String aCell( pTransliteration->transliterate(
- aCellStr, ScGlobal::eLnge, 0, aCellStr.Len(),
- NULL ) );
- String aQuer( pTransliteration->transliterate(
- *rEntry.pStr, ScGlobal::eLnge, 0, rEntry.pStr->Len(),
- NULL ) );
- xub_StrLen nIndex = (rEntry.eOp == SC_ENDS_WITH
- || rEntry.eOp == SC_DOES_NOT_END_WITH)? (aCell.Len()-aQuer.Len()):0;
- xub_StrLen nStrPos = aCell.Search( aQuer, nIndex );
- switch (rEntry.eOp)
- {
- case SC_EQUAL:
- case SC_CONTAINS:
- bOk = ( nStrPos != STRING_NOTFOUND );
- break;
- case SC_NOT_EQUAL:
- case SC_DOES_NOT_CONTAIN:
- bOk = ( nStrPos == STRING_NOTFOUND );
- break;
- case SC_BEGINS_WITH:
- bOk = ( nStrPos == 0 );
- break;
- case SC_DOES_NOT_BEGIN_WITH:
- bOk = ( nStrPos != 0 );
- break;
- case SC_ENDS_WITH:
- bOk = ( nStrPos + aQuer.Len() == aCell.Len() );
- break;
- case SC_DOES_NOT_END_WITH:
- bOk = ( nStrPos + aQuer.Len() != aCell.Len() );
- break;
- default:
- {
- // added to avoid warnings
- }
- }
- }
- }
- else
- { // use collator here because data was probably sorted
- sal_Int32 nCompare = pCollator->compareString(
- aCellStr, *rEntry.pStr );
- switch (rEntry.eOp)
- {
- case SC_LESS :
- bOk = (nCompare < 0);
- break;
- case SC_GREATER :
- bOk = (nCompare > 0);
- break;
- case SC_LESS_EQUAL :
- bOk = (nCompare <= 0);
- if ( bOk && pbTestEqualCondition && !bTestEqual )
- bTestEqual = (nCompare == 0);
- break;
- case SC_GREATER_EQUAL :
- bOk = (nCompare >= 0);
- if ( bOk && pbTestEqualCondition && !bTestEqual )
- bTestEqual = (nCompare == 0);
- break;
- default:
- {
- // added to avoid warnings
- }
- }
- }
- }
- }
- else if (rParam.bMixedComparison)
- {
- if (rEntry.bQueryByString &&
- (rEntry.eOp == SC_LESS || rEntry.eOp == SC_LESS_EQUAL) &&
- (pCell ? pCell->HasValueData() :
- HasValueData( static_cast<SCCOL>(rEntry.nField), nRow)))
- {
- bOk = sal_True;
- }
- else if (!rEntry.bQueryByString &&
- (rEntry.eOp == SC_GREATER || rEntry.eOp == SC_GREATER_EQUAL) &&
- (pCell ? pCell->HasStringData() :
- HasStringData( static_cast<SCCOL>(rEntry.nField), nRow)))
- {
- bOk = sal_True;
- }
- }
-
- if (nPos == -1)
- {
- nPos++;
- pPasst[nPos] = bOk;
- pTest[nPos] = bTestEqual;
- }
- else
- {
- if (rEntry.eConnect == SC_AND)
- {
- pPasst[nPos] = pPasst[nPos] && bOk;
- pTest[nPos] = pTest[nPos] && bTestEqual;
- }
- else
- {
- nPos++;
- pPasst[nPos] = bOk;
- pTest[nPos] = bTestEqual;
- }
- }
- i++;
- }
-
- for ( long j=1; j <= nPos; j++ )
- {
- pPasst[0] = pPasst[0] || pPasst[j];
- pTest[0] = pTest[0] || pTest[j];
- }
-
- sal_Bool bRet = pPasst[0];
- if ( pPasst != &aBool[0] )
- delete [] pPasst;
- if ( pbTestEqualCondition )
- *pbTestEqualCondition = pTest[0];
- if ( pTest != &aTest[0] )
- delete [] pTest;
-
- return bRet;
-}
-
-void ScTable::TopTenQuery( ScQueryParam& rParam )
-{
- sal_Bool bSortCollatorInitialized = false;
- SCSIZE nEntryCount = rParam.GetEntryCount();
- SCROW nRow1 = (rParam.bHasHeader ? rParam.nRow1 + 1 : rParam.nRow1);
- SCSIZE nCount = static_cast<SCSIZE>(rParam.nRow2 - nRow1 + 1);
- for ( SCSIZE i=0; (i<nEntryCount) && (rParam.GetEntry(i).bDoQuery); i++ )
- {
- ScQueryEntry& rEntry = rParam.GetEntry(i);
- switch ( rEntry.eOp )
- {
- case SC_TOPVAL:
- case SC_BOTVAL:
- case SC_TOPPERC:
- case SC_BOTPERC:
- {
- ScSortParam aLocalSortParam( rParam, static_cast<SCCOL>(rEntry.nField) );
- aSortParam = aLocalSortParam; // used in CreateSortInfoArray, Compare
- if ( !bSortCollatorInitialized )
- {
- bSortCollatorInitialized = sal_True;
- InitSortCollator( aLocalSortParam );
- }
- ScSortInfoArray* pArray = CreateSortInfoArray( nRow1, rParam.nRow2 );
- DecoladeRow( pArray, nRow1, rParam.nRow2 );
- QuickSort( pArray, nRow1, rParam.nRow2 );
- ScSortInfo** ppInfo = pArray->GetFirstArray();
- SCSIZE nValidCount = nCount;
- // keine Note-/Leerzellen zaehlen, sind ans Ende sortiert
- while ( nValidCount > 0 && ( ppInfo[nValidCount-1]->pCell == NULL ||
- ppInfo[nValidCount-1]->pCell->GetCellType() == CELLTYPE_NOTE ) )
- nValidCount--;
- // keine Strings zaehlen, sind zwischen Value und Leer
- while ( nValidCount > 0
- && ppInfo[nValidCount-1]->pCell->HasStringData() )
- nValidCount--;
- if ( nValidCount > 0 )
- {
- if ( rEntry.bQueryByString )
- { // dat wird nix
- rEntry.bQueryByString = false;
- rEntry.nVal = 10; // 10 bzw. 10%
- }
- SCSIZE nVal = (rEntry.nVal >= 1 ? static_cast<SCSIZE>(rEntry.nVal) : 1);
- SCSIZE nOffset = 0;
- switch ( rEntry.eOp )
- {
- case SC_TOPVAL:
- {
- rEntry.eOp = SC_GREATER_EQUAL;
- if ( nVal > nValidCount )
- nVal = nValidCount;
- nOffset = nValidCount - nVal; // 1 <= nVal <= nValidCount
- }
- break;
- case SC_BOTVAL:
- {
- rEntry.eOp = SC_LESS_EQUAL;
- if ( nVal > nValidCount )
- nVal = nValidCount;
- nOffset = nVal - 1; // 1 <= nVal <= nValidCount
- }
- break;
- case SC_TOPPERC:
- {
- rEntry.eOp = SC_GREATER_EQUAL;
- if ( nVal > 100 )
- nVal = 100;
- nOffset = nValidCount - (nValidCount * nVal / 100);
- if ( nOffset >= nValidCount )
- nOffset = nValidCount - 1;
- }
- break;
- case SC_BOTPERC:
- {
- rEntry.eOp = SC_LESS_EQUAL;
- if ( nVal > 100 )
- nVal = 100;
- nOffset = (nValidCount * nVal / 100);
- if ( nOffset >= nValidCount )
- nOffset = nValidCount - 1;
- }
- break;
- default:
- {
- // added to avoid warnings
- }
- }
- ScBaseCell* pCell = ppInfo[nOffset]->pCell;
- if ( pCell->HasValueData() )
- {
- if ( pCell->GetCellType() == CELLTYPE_VALUE )
- rEntry.nVal = ((ScValueCell*)pCell)->GetValue();
- else
- rEntry.nVal = ((ScFormulaCell*)pCell)->GetValue();
- }
- else
- {
- OSL_FAIL( "TopTenQuery: pCell kein ValueData" );
- rEntry.eOp = SC_GREATER_EQUAL;
- rEntry.nVal = 0;
- }
- }
- else
- {
- rEntry.eOp = SC_GREATER_EQUAL;
- rEntry.bQueryByString = false;
- rEntry.nVal = 0;
- }
- delete pArray;
- }
- break;
- default:
- {
- // added to avoid warnings
- }
- }
- }
- if ( bSortCollatorInitialized )
- DestroySortCollator();
-}
-
-static void lcl_PrepareQuery( ScDocument* pDoc, ScTable* pTab, ScQueryParam& rParam, sal_Bool* pSpecial )
-{
- bool bTopTen = false;
- SCSIZE nEntryCount = rParam.GetEntryCount();
-
- for ( SCSIZE i = 0; i < nEntryCount; ++i )
- {
- pSpecial[i] = false;
- ScQueryEntry& rEntry = rParam.GetEntry(i);
- if ( rEntry.bDoQuery )
- {
- if ( rEntry.bQueryByString )
- {
- sal_uInt32 nIndex = 0;
- rEntry.bQueryByString = !( pDoc->GetFormatTable()->
- IsNumberFormat( *rEntry.pStr, nIndex, rEntry.nVal ) );
- if (rEntry.bQueryByDate)
- {
- if (!rEntry.bQueryByString && ((nIndex % SV_COUNTRY_LANGUAGE_OFFSET) != 0))
- {
- const SvNumberformat* pEntry = pDoc->GetFormatTable()->GetEntry(nIndex);
- if (pEntry)
- {
- short nNumFmtType = pEntry->GetType();
- if (!((nNumFmtType & NUMBERFORMAT_DATE) && !(nNumFmtType & NUMBERFORMAT_TIME)))
- rEntry.bQueryByDate = false; // not a date only
- }
- else
- rEntry.bQueryByDate = false; // what the ... not a date
- }
- else
- rEntry.bQueryByDate = false; // not a date
- }
- }
- else
- {
- // call from UNO or second call from autofilter
- if ( rEntry.nVal == SC_EMPTYFIELDS || rEntry.nVal == SC_NONEMPTYFIELDS )
- {
- pSpecial[i] = sal_True;
- }
- }
- if ( !bTopTen )
- {
- switch ( rEntry.eOp )
- {
- case SC_TOPVAL:
- case SC_BOTVAL:
- case SC_TOPPERC:
- case SC_BOTPERC:
- {
- bTopTen = true;
- }
- break;
- default:
- {
- }
- }
- }
- }
- }
-
- if ( bTopTen )
- {
- pTab->TopTenQuery( rParam );
- }
-}
-
-SCSIZE ScTable::Query(ScQueryParam& rParamOrg, sal_Bool bKeepSub)
-{
- ScQueryParam aParam( rParamOrg );
- ScStrCollection aScStrCollection;
- StrData* pStrData = NULL;
-
- sal_Bool bStarted = false;
- sal_Bool bOldResult = sal_True;
- SCROW nOldStart = 0;
- SCROW nOldEnd = 0;
-
- SCSIZE nCount = 0;
- SCROW nOutRow = 0;
- SCROW nHeader = aParam.bHasHeader ? 1 : 0;
-
- SCSIZE nEntryCount = aParam.GetEntryCount();
- sal_Bool* pSpecial = new sal_Bool[nEntryCount];
- lcl_PrepareQuery( pDocument, this, aParam, pSpecial );
-
- if (!aParam.bInplace)
- {
- nOutRow = aParam.nDestRow + nHeader;
- if (nHeader > 0)
- CopyData( aParam.nCol1, aParam.nRow1, aParam.nCol2, aParam.nRow1,
- aParam.nDestCol, aParam.nDestRow, aParam.nDestTab );
- }
-
-
- if (aParam.bInplace)
- InitializeNoteCaptions();
-
- SCROW nRealRow2 = aParam.nRow2;
- for (SCROW j = aParam.nRow1 + nHeader; j <= nRealRow2; ++j)
- {
- sal_Bool bResult; // Filterergebnis
- sal_Bool bValid = ValidQuery(j, aParam, pSpecial);
- if (!bValid && bKeepSub) // Subtotals stehenlassen
- {
- for (SCCOL nCol=aParam.nCol1; nCol<=aParam.nCol2 && !bValid; nCol++)
- {
- ScBaseCell* pCell;
- pCell = GetCell( nCol, j );
- if ( pCell )
- if ( pCell->GetCellType() == CELLTYPE_FORMULA )
- if (((ScFormulaCell*)pCell)->IsSubTotal())
- if (RefVisible((ScFormulaCell*)pCell))
- bValid = sal_True;
- }
- }
- if (bValid)
- {
- if (aParam.bDuplicate)
- bResult = sal_True;
- else
- {
- String aStr;
- for (SCCOL k=aParam.nCol1; k <= aParam.nCol2; k++)
- {
- String aCellStr;
- GetString(k, j, aCellStr);
- aStr += aCellStr;
- aStr += (sal_Unicode)1;
- }
- pStrData = new StrData(aStr);
-
- sal_Bool bIsUnique = sal_True;
- if (pStrData)
- bIsUnique = aScStrCollection.Insert(pStrData);
- if (bIsUnique)
- bResult = sal_True;
- else
- {
- delete pStrData;
- bResult = false;
- }
- }
- }
- else
- bResult = false;
-
- if (aParam.bInplace)
- {
- if (bResult == bOldResult && bStarted)
- nOldEnd = j;
- else
- {
- if (bStarted)
- DBShowRows(nOldStart,nOldEnd, bOldResult);
- nOldStart = nOldEnd = j;
- bOldResult = bResult;
- }
- bStarted = sal_True;
- }
- else
- {
- if (bResult)
- {
- CopyData( aParam.nCol1,j, aParam.nCol2,j, aParam.nDestCol,nOutRow,aParam.nDestTab );
- ++nOutRow;
- }
- }
- if (bResult)
- ++nCount;
- }
-
- if (aParam.bInplace && bStarted)
- DBShowRows(nOldStart,nOldEnd, bOldResult);
-
- if (aParam.bInplace)
- SetDrawPageSize();
-
- delete[] pSpecial;
- return nCount;
-}
-
-sal_Bool ScTable::CreateExcelQuery(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScQueryParam& rQueryParam)
-{
- sal_Bool bValid = sal_True;
- SCCOL* pFields = new SCCOL[nCol2-nCol1+1];
- String aCellStr;
- SCCOL nCol = nCol1;
- OSL_ENSURE( rQueryParam.nTab != SCTAB_MAX, "rQueryParam.nTab no value, not bad but no good" );
- SCTAB nDBTab = (rQueryParam.nTab == SCTAB_MAX ? nTab : rQueryParam.nTab);
- SCROW nDBRow1 = rQueryParam.nRow1;
- SCCOL nDBCol2 = rQueryParam.nCol2;
- // Erste Zeile muessen Spaltenkoepfe sein
- while (bValid && (nCol <= nCol2))
- {
- String aQueryStr;
- GetUpperCellString(nCol, nRow1, aQueryStr);
- sal_Bool bFound = false;
- SCCOL i = rQueryParam.nCol1;
- while (!bFound && (i <= nDBCol2))
- {
- if ( nTab == nDBTab )
- GetUpperCellString(i, nDBRow1, aCellStr);
- else
- pDocument->GetUpperCellString(i, nDBRow1, nDBTab, aCellStr);
- bFound = (aCellStr == aQueryStr);
- if (!bFound) i++;
- }
- if (bFound)
- pFields[nCol - nCol1] = i;
- else
- bValid = false;
- nCol++;
- }
- if (bValid)
- {
- sal_uLong nVisible = 0;
- for ( nCol=nCol1; nCol<=nCol2; nCol++ )
- nVisible += aCol[nCol].VisibleCount( nRow1+1, nRow2 );
-
- if ( nVisible > SCSIZE_MAX / sizeof(void*) )
- {
- OSL_FAIL("zu viele Filterkritierien");
- nVisible = 0;
- }
-
- SCSIZE nNewEntries = nVisible;
- rQueryParam.Resize( nNewEntries );
-
- SCSIZE nIndex = 0;
- SCROW nRow = nRow1 + 1;
- while (nRow <= nRow2)
- {
- nCol = nCol1;
- while (nCol <= nCol2)
- {
- GetInputString( nCol, nRow, aCellStr );
- ScGlobal::pCharClass->toUpper( aCellStr );
- if (aCellStr.Len() > 0)
- {
- if (nIndex < nNewEntries)
- {
- rQueryParam.GetEntry(nIndex).nField = pFields[nCol - nCol1];
- rQueryParam.FillInExcelSyntax(aCellStr, nIndex);
- nIndex++;
- if (nIndex < nNewEntries)
- rQueryParam.GetEntry(nIndex).eConnect = SC_AND;
- }
- else
- bValid = false;
- }
- nCol++;
- }
- nRow++;
- if (nIndex < nNewEntries)
- rQueryParam.GetEntry(nIndex).eConnect = SC_OR;
- }
- }
- delete [] pFields;
- return bValid;
-}
-
-sal_Bool ScTable::CreateStarQuery(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScQueryParam& rQueryParam)
-{
- // A valid StarQuery must be at least 4 columns wide. To be precise it
- // should be exactly 4 columns ...
- // Additionally, if this wasn't checked, a formula pointing to a valid 1-3
- // column Excel style query range immediately left to itself would result
- // in a circular reference when the field name or operator or value (first
- // to third query range column) is obtained (#i58354#). Furthermore, if the
- // range wasn't sufficiently specified data changes wouldn't flag formula
- // cells for recalculation.
- if (nCol2 - nCol1 < 3)
- return false;
-
- sal_Bool bValid;
- sal_Bool bFound;
- String aCellStr;
- SCSIZE nIndex = 0;
- SCROW nRow = nRow1;
- OSL_ENSURE( rQueryParam.nTab != SCTAB_MAX, "rQueryParam.nTab no value, not bad but no good" );
- SCTAB nDBTab = (rQueryParam.nTab == SCTAB_MAX ? nTab : rQueryParam.nTab);
- SCROW nDBRow1 = rQueryParam.nRow1;
- SCCOL nDBCol2 = rQueryParam.nCol2;
-
- SCSIZE nNewEntries = static_cast<SCSIZE>(nRow2-nRow1+1);
- rQueryParam.Resize( nNewEntries );
-
- do
- {
- ScQueryEntry& rEntry = rQueryParam.GetEntry(nIndex);
-
- bValid = false;
- // Erste Spalte UND/ODER
- if (nIndex > 0)
- {
- GetUpperCellString(nCol1, nRow, aCellStr);
- if ( aCellStr == ScGlobal::GetRscString(STR_TABLE_UND) )
- {
- rEntry.eConnect = SC_AND;
- bValid = sal_True;
- }
- else if ( aCellStr == ScGlobal::GetRscString(STR_TABLE_ODER) )
- {
- rEntry.eConnect = SC_OR;
- bValid = sal_True;
- }
- }
- // Zweite Spalte FeldName
- if ((nIndex < 1) || bValid)
- {
- bFound = false;
- GetUpperCellString(nCol1 + 1, nRow, aCellStr);
- for (SCCOL i=rQueryParam.nCol1; (i <= nDBCol2) && (!bFound); i++)
- {
- String aFieldStr;
- if ( nTab == nDBTab )
- GetUpperCellString(i, nDBRow1, aFieldStr);
- else
- pDocument->GetUpperCellString(i, nDBRow1, nDBTab, aFieldStr);
- bFound = (aCellStr == aFieldStr);
- if (bFound)
- {
- rEntry.nField = i;
- bValid = sal_True;
- }
- else
- bValid = false;
- }
- }
- // Dritte Spalte Operator =<>...
- if (bValid)
- {
- bFound = false;
- GetUpperCellString(nCol1 + 2, nRow, aCellStr);
- if (aCellStr.GetChar(0) == '<')
- {
- if (aCellStr.GetChar(1) == '>')
- rEntry.eOp = SC_NOT_EQUAL;
- else if (aCellStr.GetChar(1) == '=')
- rEntry.eOp = SC_LESS_EQUAL;
- else
- rEntry.eOp = SC_LESS;
- }
- else if (aCellStr.GetChar(0) == '>')
- {
- if (aCellStr.GetChar(1) == '=')
- rEntry.eOp = SC_GREATER_EQUAL;
- else
- rEntry.eOp = SC_GREATER;
- }
- else if (aCellStr.GetChar(0) == '=')
- rEntry.eOp = SC_EQUAL;
-
- }
- // Vierte Spalte Wert
- if (bValid)
- {
- GetString(nCol1 + 3, nRow, *rEntry.pStr);
- rEntry.bDoQuery = sal_True;
- }
- nIndex++;
- nRow++;
- }
- while (bValid && (nRow <= nRow2) /* && (nIndex < MAXQUERY) */ );
- return bValid;
-}
-
-sal_Bool ScTable::CreateQueryParam(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScQueryParam& rQueryParam)
-{
- SCSIZE i, nCount;
- PutInOrder(nCol1, nCol2);
- PutInOrder(nRow1, nRow2);
-
- nCount = rQueryParam.GetEntryCount();
- for (i=0; i < nCount; i++)
- rQueryParam.GetEntry(i).Clear();
-
- // Standard QueryTabelle
- sal_Bool bValid = CreateStarQuery(nCol1, nRow1, nCol2, nRow2, rQueryParam);
- // Excel QueryTabelle
- if (!bValid)
- bValid = CreateExcelQuery(nCol1, nRow1, nCol2, nRow2, rQueryParam);
-
- nCount = rQueryParam.GetEntryCount();
- if (bValid)
- {
- // bQueryByString muss gesetzt sein
- for (i=0; i < nCount; i++)
- rQueryParam.GetEntry(i).bQueryByString = sal_True;
- }
- else
- {
- // nix
- for (i=0; i < nCount; i++)
- rQueryParam.GetEntry(i).Clear();
- }
- return bValid;
-}
-
-sal_Bool ScTable::HasColHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW /* nEndRow */ )
-{
- for (SCCOL nCol=nStartCol; nCol<=nEndCol; nCol++)
- {
- CellType eType = GetCellType( nCol, nStartRow );
- if (eType != CELLTYPE_STRING && eType != CELLTYPE_EDIT)
- return false;
- }
- return sal_True;
-}
-
-sal_Bool ScTable::HasRowHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL /* nEndCol */, SCROW nEndRow )
-{
- for (SCROW nRow=nStartRow; nRow<=nEndRow; nRow++)
- {
- CellType eType = GetCellType( nStartCol, nRow );
- if (eType != CELLTYPE_STRING && eType != CELLTYPE_EDIT)
- return false;
- }
- return sal_True;
-}
-
-void ScTable::GetFilterEntries(SCCOL nCol, SCROW nRow1, SCROW nRow2, TypedScStrCollection& rStrings, bool& rHasDates)
-{
- aCol[nCol].GetFilterEntries( nRow1, nRow2, rStrings, rHasDates );
-}
-
-void ScTable::GetFilteredFilterEntries(
- SCCOL nCol, SCROW nRow1, SCROW nRow2, const ScQueryParam& rParam, TypedScStrCollection& rStrings, bool& rHasDates )
-{
- // remove the entry for this column from the query parameter
- ScQueryParam aParam( rParam );
- SCSIZE nEntryCount = aParam.GetEntryCount();
- for ( SCSIZE i = 0; i < nEntryCount && aParam.GetEntry(i).bDoQuery; ++i )
- {
- ScQueryEntry& rEntry = aParam.GetEntry(i);
- if ( rEntry.nField == nCol )
- {
- aParam.DeleteQuery(i);
- break;
- }
- }
- nEntryCount = aParam.GetEntryCount();
-
- sal_Bool* pSpecial = new sal_Bool[nEntryCount];
- lcl_PrepareQuery( pDocument, this, aParam, pSpecial );
- bool bHasDates = false;
- for ( SCROW j = nRow1; j <= nRow2; ++j )
- {
- if ( ValidQuery( j, aParam, pSpecial ) )
- {
- bool bThisHasDates = false;
- aCol[nCol].GetFilterEntries( j, j, rStrings, bThisHasDates );
- bHasDates |= bThisHasDates;
- }
- }
-
- rHasDates = bHasDates;
- delete[] pSpecial;
-}
-
-sal_Bool ScTable::GetDataEntries(SCCOL nCol, SCROW nRow, TypedScStrCollection& rStrings, sal_Bool bLimit)
-{
- return aCol[nCol].GetDataEntries( nRow, rStrings, bLimit );
-}
-
-SCSIZE ScTable::GetCellCount(SCCOL nCol) const
-{
- return aCol[nCol].GetCellCount();
-}
-
-sal_uLong ScTable::GetCellCount() const
-{
- sal_uLong nCellCount = 0;
-
- for ( SCCOL nCol=0; nCol<=MAXCOL; nCol++ )
- nCellCount += aCol[nCol].GetCellCount();
-
- return nCellCount;
-}
-
-sal_uLong ScTable::GetWeightedCount() const
-{
- sal_uLong nCellCount = 0;
-
- for ( SCCOL nCol=0; nCol<=MAXCOL; nCol++ )
- if ( aCol[nCol].GetCellCount() ) // GetCellCount ist inline
- nCellCount += aCol[nCol].GetWeightedCount();
-
- return nCellCount;
-}
-
-sal_uLong ScTable::GetCodeCount() const
-{
- sal_uLong nCodeCount = 0;
-
- for ( SCCOL nCol=0; nCol<=MAXCOL; nCol++ )
- if ( aCol[nCol].GetCellCount() ) // GetCellCount ist inline
- nCodeCount += aCol[nCol].GetCodeCount();
-
- return nCodeCount;
-}
-
-sal_Int32 ScTable::GetMaxStringLen( SCCOL nCol, SCROW nRowStart,
- SCROW nRowEnd, CharSet eCharSet ) const
-{
- if ( ValidCol(nCol) )
- return aCol[nCol].GetMaxStringLen( nRowStart, nRowEnd, eCharSet );
- else
- return 0;
-}
-
-xub_StrLen ScTable::GetMaxNumberStringLen(
- sal_uInt16& nPrecision, SCCOL nCol, SCROW nRowStart, SCROW nRowEnd ) const
-{
- if ( ValidCol(nCol) )
- return aCol[nCol].GetMaxNumberStringLen( nPrecision, nRowStart, nRowEnd );
- else
- return 0;
-}
-
-void ScTable::UpdateSelectionFunction( ScFunctionData& rData,
- SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
- const ScMarkData& rMark )
-{
- // Cursor neben einer Markierung nicht beruecksichtigen:
- //! nur noch MarkData uebergeben, Cursorposition ggf. hineinselektieren!!!
- sal_Bool bSingle = ( rMark.IsMarked() || !rMark.IsMultiMarked() );
-
- // Mehrfachselektion:
-
- SCCOL nCol;
- if ( rMark.IsMultiMarked() )
- for (nCol=0; nCol<=MAXCOL && !rData.bError; nCol++)
- if ( !pColFlags || !ColHidden(nCol) )
- aCol[nCol].UpdateSelectionFunction( rMark, rData, *mpHiddenRows,
- bSingle && ( nCol >= nStartCol && nCol <= nEndCol ),
- nStartRow, nEndRow );
-
- // Einfachselektion (oder Cursor) nur wenn nicht negativ (und s.o.):
-
- if ( bSingle && !rMark.IsMarkNegative() )
- for (nCol=nStartCol; nCol<=nEndCol && !rData.bError; nCol++)
- if ( !pColFlags || !ColHidden(nCol) )
- aCol[nCol].UpdateAreaFunction( rData, *mpHiddenRows, nStartRow, nEndRow );
-}
-
-void ScTable::FindConditionalFormat( sal_uLong nKey, ScRangeList& rList )
-{
- SCROW nStartRow = 0, nEndRow = 0;
- for (SCCOL nCol=0; nCol<=MAXCOL; nCol++)
- {
- ScAttrIterator* pIter = aCol[nCol].CreateAttrIterator( 0, MAXROW );
- const ScPatternAttr* pPattern = pIter->Next( nStartRow, nEndRow );
- while (pPattern)
- {
- if (((SfxUInt32Item&)pPattern->GetItem(ATTR_CONDITIONAL)).GetValue() == nKey)
- rList.Join( ScRange(nCol,nStartRow,nTab, nCol,nEndRow,nTab) );
- pPattern = pIter->Next( nStartRow, nEndRow );
- }
- delete pIter;
- }
-}
-
-void ScTable::IncRecalcLevel()
-{
- ++nRecalcLvl;
-}
-
-void ScTable::DecRecalcLevel(bool bUpdateNoteCaptionPos)
-{
- if (!--nRecalcLvl)
- SetDrawPageSize(true, bUpdateNoteCaptionPos);
-}
-
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */