blob: e6ba12d39326fbe72b6467923f362907c22eabeb [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sc.hxx"
#include "excimp8.hxx"
#include <scitems.hxx>
#include <comphelper/processfactory.hxx>
#include <comphelper/mediadescriptor.hxx>
#include <unotools/fltrcfg.hxx>
#include <svtools/wmf.hxx>
#include <editeng/eeitem.hxx>
#include <sfx2/docfile.hxx>
#include <sfx2/objsh.hxx>
#include <sfx2/request.hxx>
#include <sfx2/app.hxx>
#include <sfx2/docinf.hxx>
#include <sfx2/frame.hxx>
#include <editeng/brshitem.hxx>
#include <editeng/editdata.hxx>
#include <editeng/editeng.hxx>
#include <editeng/editobj.hxx>
#include <editeng/editstat.hxx>
#include <editeng/colritem.hxx>
#include <editeng/udlnitem.hxx>
#include <editeng/wghtitem.hxx>
#include <editeng/postitem.hxx>
#include <editeng/crsditem.hxx>
#include <editeng/flditem.hxx>
#include <svx/xflclit.hxx>
#include <vcl/graph.hxx>
#include <vcl/bmpacc.hxx>
#include <sot/exchange.hxx>
#include <svl/stritem.hxx>
#include <tools/string.hxx>
#include <tools/urlobj.hxx>
#include <rtl/math.hxx>
#include <unotools/localedatawrapper.hxx>
#include <unotools/charclass.hxx>
#include <drwlayer.hxx>
#include <boost/scoped_array.hpp>
#include "cell.hxx"
#include "document.hxx"
#include "patattr.hxx"
#include "docpool.hxx"
#include "attrib.hxx"
#include "conditio.hxx"
#include "dbcolect.hxx"
#include "editutil.hxx"
#include "markdata.hxx"
#include "rangenam.hxx"
#include "docoptio.hxx"
#include "globstr.hrc"
#include "fprogressbar.hxx"
#include "xltracer.hxx"
#include "xihelper.hxx"
#include "xipage.hxx"
#include "xicontent.hxx"
#include "xilink.hxx"
#include "xiescher.hxx"
#include "xipivot.hxx"
#include "excform.hxx"
#include "scextopt.hxx"
#include "stlpool.hxx"
#include "stlsheet.hxx"
#include "detfunc.hxx"
#include <com/sun/star/document/XDocumentProperties.hpp>
#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
#include <com/sun/star/document/XFilter.hpp>
#include <com/sun/star/document/XImporter.hpp>
using namespace com::sun::star;
using namespace ::comphelper;
using ::rtl::OUString;
ImportExcel8::ImportExcel8( XclImpRootData& rImpData, SvStream& rStrm ) :
ImportExcel( rImpData, rStrm )
{
// replace BIFF2-BIFF5 formula importer with BIFF8 formula importer
delete pFormConv;
pFormConv = pExcRoot->pFmlaConverter = new ExcelToSc8( GetRoot() );
}
ImportExcel8::~ImportExcel8()
{
}
void ImportExcel8::Calccount( void )
{
ScDocOptions aOpt = pD->GetDocOptions();
aOpt.SetIterCount( aIn.ReaduInt16() );
pD->SetDocOptions( aOpt );
}
void ImportExcel8::Precision( void )
{
ScDocOptions aOpt = pD->GetDocOptions();
aOpt.SetCalcAsShown( aIn.ReaduInt16() == 0 );
pD->SetDocOptions( aOpt );
}
void ImportExcel8::Delta( void )
{
ScDocOptions aOpt = pD->GetDocOptions();
aOpt.SetIterEps( aIn.ReadDouble() );
pD->SetDocOptions( aOpt );
}
void ImportExcel8::Iteration( void )
{
ScDocOptions aOpt = pD->GetDocOptions();
aOpt.SetIter( aIn.ReaduInt16() == 1 );
pD->SetDocOptions( aOpt );
}
void ImportExcel8::Boundsheet( void )
{
sal_uInt8 nLen;
sal_uInt16 nGrbit;
aIn.DisableDecryption();
maSheetOffsets.push_back( aIn.ReaduInt32() );
aIn.EnableDecryption();
aIn >> nGrbit >> nLen;
String aName( aIn.ReadUniString( nLen ) );
GetTabInfo().AppendXclTabName( aName, nBdshtTab );
SCTAB nScTab = static_cast< SCTAB >( nBdshtTab );
if( nScTab > 0 )
{
DBG_ASSERT( !pD->HasTable( nScTab ), "ImportExcel8::Boundsheet - sheet exists already" );
pD->MakeTable( nScTab );
}
//assume pending row heights true here. Only optimize the excel8 type for now. i120586
//if the sheet contain sdrobject, will set false then.
pD->SetPendingRowHeights( nScTab, true );
//end i120586
if( ( nGrbit & 0x0001 ) || ( nGrbit & 0x0002 ) )
pD->SetVisible( nScTab, sal_False );
if( !pD->RenameTab( nScTab, aName ) )
{
pD->CreateValidTabName( aName );
pD->RenameTab( nScTab, aName );
}
nBdshtTab++;
}
void ImportExcel8::Scenman( void )
{
sal_uInt16 nLastDispl;
aIn.Ignore( 4 );
aIn >> nLastDispl;
aScenList.SetLast( nLastDispl );
}
void ImportExcel8::Scenario( void )
{
aScenList.Append( new ExcScenario( aIn, *pExcRoot ) );
}
void ImportExcel8::Labelsst( void )
{
XclAddress aXclPos;
sal_uInt16 nXF;
sal_uInt32 nSst;
aIn >> aXclPos >> nXF >> nSst;
ScAddress aScPos( ScAddress::UNINITIALIZED );
if( GetAddressConverter().ConvertAddress( aScPos, aXclPos, GetCurrScTab(), true ) )
{
GetXFRangeBuffer().SetXF( aScPos, nXF );
if( ScBaseCell* pCell = GetSst().CreateCell( nSst, nXF ) )
GetDoc().PutCell( aScPos.Col(), aScPos.Row(), aScPos.Tab(), pCell );
}
}
void ImportExcel8::SheetProtection( void )
{
GetSheetProtectBuffer().ReadOptions( aIn, GetCurrScTab() );
}
void ImportExcel8::ReadBasic( void )
{
SfxObjectShell* pShell = GetDocShell();
SotStorageRef xRootStrg = GetRootStorage();
if( pShell && xRootStrg.Is() ) try
{
uno::Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext(), uno::UNO_SET_THROW );
uno::Reference< lang::XMultiComponentFactory > xFactory( xContext->getServiceManager(), uno::UNO_SET_THROW );
uno::Sequence< beans::NamedValue > aArgSeq( 1 );
aArgSeq[ 0 ].Name = CREATE_OUSTRING( "ColorPalette" );
aArgSeq[ 0 ].Value <<= GetPalette().CreateColorSequence();
uno::Sequence< uno::Any > aArgs( 2 );
// framework calls filter objects with factory as first argument
aArgs[ 0 ] <<= xFactory;
aArgs[ 1 ] <<= aArgSeq;
uno::Reference< document::XImporter > xImporter( xFactory->createInstanceWithArgumentsAndContext(
CREATE_OUSTRING( "com.sun.star.comp.oox.xls.ExcelVbaProjectFilter" ), aArgs, xContext ), uno::UNO_QUERY_THROW );
uno::Reference< lang::XComponent > xComponent( pShell->GetModel(), uno::UNO_QUERY_THROW );
xImporter->setTargetDocument( xComponent );
MediaDescriptor aMediaDesc;
SfxMedium& rMedium = GetMedium();
SfxItemSet* pItemSet = rMedium.GetItemSet();
if( pItemSet )
{
SFX_ITEMSET_ARG( pItemSet, pFileNameItem, SfxStringItem, SID_FILE_NAME, sal_False );
if( pFileNameItem )
aMediaDesc[ MediaDescriptor::PROP_URL() ] <<= ::rtl::OUString( pFileNameItem->GetValue() );
SFX_ITEMSET_ARG( pItemSet, pPasswordItem, SfxStringItem, SID_PASSWORD, sal_False );
if( pPasswordItem )
aMediaDesc[ MediaDescriptor::PROP_PASSWORD() ] <<= ::rtl::OUString( pPasswordItem->GetValue() );
SFX_ITEMSET_ARG( pItemSet, pEncryptionDataItem, SfxUnoAnyItem, SID_ENCRYPTIONDATA, sal_False );
if( pEncryptionDataItem )
aMediaDesc[ MediaDescriptor::PROP_ENCRYPTIONDATA() ] = pEncryptionDataItem->GetValue();
}
aMediaDesc[ MediaDescriptor::PROP_INPUTSTREAM() ] <<= rMedium.GetInputStream();
aMediaDesc[ MediaDescriptor::PROP_INTERACTIONHANDLER() ] <<= rMedium.GetInteractionHandler();
// call the filter
uno::Reference< document::XFilter > xFilter( xImporter, uno::UNO_QUERY_THROW );
xFilter->filter( aMediaDesc.getAsConstPropertyValueList() );
}
catch( uno::Exception& )
{
}
}
void ImportExcel8::EndSheet( void )
{
GetCondFormatManager().Apply();
ImportExcel::EndSheet();
}
void ImportExcel8::PostDocLoad( void )
{
// reading basic has been delayed until sheet objects (codenames etc.) are read
if( HasBasic() )
ReadBasic();
// #i11776# filtered ranges before outlines and hidden rows
if( pExcRoot->pAutoFilterBuffer )
pExcRoot->pAutoFilterBuffer->Apply();
GetWebQueryBuffer().Apply(); //! test if extant
GetSheetProtectBuffer().Apply();
GetDocProtectBuffer().Apply();
ImportExcel::PostDocLoad();
// Scenarien bemachen! ACHTUNG: Hier wird Tabellen-Anzahl im Dokument erhoeht!!
if( !pD->IsClipboard() && aScenList.Count() )
{
pD->UpdateChartListenerCollection(); // references in charts must be updated
aScenList.Apply( GetRoot() );
}
// read doc info (no docshell while pasting from clipboard)
LoadDocumentProperties();
// #i45843# Pivot tables are now handled outside of PostDocLoad, so they are available
// when formula cells are calculated, for the GETPIVOTDATA function.
}
void ImportExcel8::LoadDocumentProperties()
{
// no docshell while pasting from clipboard
if( SfxObjectShell* pShell = GetDocShell() )
{
// BIFF5+ without storage is possible
SotStorageRef xRootStrg = GetRootStorage();
if( xRootStrg.Is() ) try
{
uno::Reference< document::XDocumentPropertiesSupplier > xDPS( pShell->GetModel(), uno::UNO_QUERY_THROW );
uno::Reference< document::XDocumentProperties > xDocProps( xDPS->getDocumentProperties(), uno::UNO_SET_THROW );
sfx2::LoadOlePropertySet( xDocProps, xRootStrg );
}
catch( uno::Exception& )
{
}
}
}
//___________________________________________________________________
// autofilter
void ImportExcel8::FilterMode( void )
{
// The FilterMode record exists: if either the AutoFilter
// record exists or an Advanced Filter is saved and stored
// in the sheet. Thus if the FilterMode records only exists
// then the latter is true..
if( !pExcRoot->pAutoFilterBuffer ) return;
pExcRoot->pAutoFilterBuffer->IncrementActiveAF();
XclImpAutoFilterData* pData = pExcRoot->pAutoFilterBuffer->GetByTab( GetCurrScTab() );
if( pData )
pData->SetAutoOrAdvanced();
}
void ImportExcel8::AutoFilterInfo( void )
{
if( !pExcRoot->pAutoFilterBuffer ) return;
XclImpAutoFilterData* pData = pExcRoot->pAutoFilterBuffer->GetByTab( GetCurrScTab() );
if( pData )
{
pData->SetAdvancedRange( NULL );
pData->Activate();
}
}
void ImportExcel8::AutoFilter( void )
{
if( !pExcRoot->pAutoFilterBuffer ) return;
XclImpAutoFilterData* pData = pExcRoot->pAutoFilterBuffer->GetByTab( GetCurrScTab() );
if( pData )
pData->ReadAutoFilter( aIn );
}
XclImpAutoFilterData::XclImpAutoFilterData( RootData* pRoot, const ScRange& rRange, const String& rName ) :
ExcRoot( pRoot ),
pCurrDBData(NULL),
nFirstEmpty( 0 ),
bActive( sal_False ),
bHasConflict( sal_False ),
bCriteria( sal_False ),
bAutoOrAdvanced(sal_False),
aFilterName(rName)
{
aParam.nCol1 = rRange.aStart.Col();
aParam.nRow1 = rRange.aStart.Row();
aParam.nTab = rRange.aStart.Tab();
aParam.nCol2 = rRange.aEnd.Col();
aParam.nRow2 = rRange.aEnd.Row();
aParam.bInplace = sal_True;
}
void XclImpAutoFilterData::CreateFromDouble( String& rStr, double fVal )
{
rStr += String( ::rtl::math::doubleToUString( fVal,
rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max,
ScGlobal::pLocaleData->getNumDecimalSep().GetChar(0), sal_True));
}
void XclImpAutoFilterData::SetCellAttribs()
{
ScDocument& rDoc = pExcRoot->pIR->GetDoc();
for ( SCCOL nCol = StartCol(); nCol <= EndCol(); nCol++ )
{
sal_Int16 nFlag = ((ScMergeFlagAttr*) rDoc.GetAttr( nCol, StartRow(), Tab(), ATTR_MERGE_FLAG ))->GetValue();
rDoc.ApplyAttr( nCol, StartRow(), Tab(), ScMergeFlagAttr( nFlag | SC_MF_AUTO) );
}
}
void XclImpAutoFilterData::InsertQueryParam()
{
if( pCurrDBData && !bHasConflict )
{
ScRange aAdvRange;
sal_Bool bHasAdv = pCurrDBData->GetAdvancedQuerySource( aAdvRange );
if( bHasAdv )
pExcRoot->pIR->GetDoc().CreateQueryParam( aAdvRange.aStart.Col(),
aAdvRange.aStart.Row(), aAdvRange.aEnd.Col(), aAdvRange.aEnd.Row(),
aAdvRange.aStart.Tab(), aParam );
pCurrDBData->SetQueryParam( aParam );
if( bHasAdv )
pCurrDBData->SetAdvancedQuerySource( &aAdvRange );
else
{
pCurrDBData->SetAutoFilter( sal_True );
SetCellAttribs();
}
}
}
static void ExcelQueryToOooQuery( ScQueryEntry& rEntry )
{
if( ( rEntry.eOp != SC_EQUAL && rEntry.eOp != SC_NOT_EQUAL ) || rEntry.pStr == NULL )
return;
else
{
xub_StrLen nLen = rEntry.pStr->Len();
sal_Unicode nStart = rEntry.pStr->GetChar( 0 );
sal_Unicode nEnd = rEntry.pStr->GetChar( nLen-1 );
if( nLen >2 && nStart == '*' && nEnd == '*' )
{
rEntry.pStr->Erase( nLen-1, 1 );
rEntry.pStr->Erase( 0, 1 );
rEntry.eOp = ( rEntry.eOp == SC_EQUAL ) ? SC_CONTAINS : SC_DOES_NOT_CONTAIN;
}
else if( nLen > 1 && nStart == '*' && nEnd != '*' )
{
rEntry.pStr->Erase( 0, 1 );
rEntry.eOp = ( rEntry.eOp == SC_EQUAL ) ? SC_ENDS_WITH : SC_DOES_NOT_END_WITH;
}
else if( nLen > 1 && nStart != '*' && nEnd == '*' )
{
rEntry.pStr->Erase( nLen-1, 1 );
rEntry.eOp = ( rEntry.eOp == SC_EQUAL ) ? SC_BEGINS_WITH : SC_DOES_NOT_BEGIN_WITH;
}
else if( nLen == 2 && nStart == '*' && nEnd == '*' )
{
rEntry.pStr->Erase( 0, 1 );
}
}
}
void XclImpAutoFilterData::ReadAutoFilter( XclImpStream& rStrm )
{
sal_uInt16 nCol, nFlags;
rStrm >> nCol >> nFlags;
ScQueryConnect eConn = ::get_flagvalue( nFlags, EXC_AFFLAG_ANDORMASK, SC_OR, SC_AND );
sal_Bool bTop10 = ::get_flag( nFlags, EXC_AFFLAG_TOP10 );
sal_Bool bTopOfTop10 = ::get_flag( nFlags, EXC_AFFLAG_TOP10TOP );
sal_Bool bPercent = ::get_flag( nFlags, EXC_AFFLAG_TOP10PERC );
sal_uInt16 nCntOfTop10 = nFlags >> 7;
SCSIZE nCount = aParam.GetEntryCount();
if( bTop10 )
{
if( nFirstEmpty < nCount )
{
ScQueryEntry& aEntry = aParam.GetEntry( nFirstEmpty );
aEntry.bDoQuery = sal_True;
aEntry.bQueryByString = sal_True;
aEntry.nField = static_cast<SCCOLROW>(StartCol() + static_cast<SCCOL>(nCol));
aEntry.eOp = bTopOfTop10 ?
(bPercent ? SC_TOPPERC : SC_TOPVAL) : (bPercent ? SC_BOTPERC : SC_BOTVAL);
aEntry.eConnect = SC_AND;
aEntry.pStr->Assign( String::CreateFromInt32( (sal_Int32) nCntOfTop10 ) );
rStrm.Ignore( 20 );
nFirstEmpty++;
}
}
else
{
sal_uInt8 nE, nType, nOper, nBoolErr, nVal;
sal_Int32 nRK;
double fVal;
sal_Bool bIgnore;
sal_uInt8 nStrLen[ 2 ] = { 0, 0 };
ScQueryEntry *pQueryEntries[ 2 ] = { NULL, NULL };
for( nE = 0; nE < 2; nE++ )
{
if( nFirstEmpty < nCount )
{
ScQueryEntry& aEntry = aParam.GetEntry( nFirstEmpty );
pQueryEntries[ nE ] = &aEntry;
bIgnore = sal_False;
rStrm >> nType >> nOper;
switch( nOper )
{
case EXC_AFOPER_LESS:
aEntry.eOp = SC_LESS;
break;
case EXC_AFOPER_EQUAL:
aEntry.eOp = SC_EQUAL;
break;
case EXC_AFOPER_LESSEQUAL:
aEntry.eOp = SC_LESS_EQUAL;
break;
case EXC_AFOPER_GREATER:
aEntry.eOp = SC_GREATER;
break;
case EXC_AFOPER_NOTEQUAL:
aEntry.eOp = SC_NOT_EQUAL;
break;
case EXC_AFOPER_GREATEREQUAL:
aEntry.eOp = SC_GREATER_EQUAL;
break;
default:
aEntry.eOp = SC_EQUAL;
}
switch( nType )
{
case EXC_AFTYPE_RK:
rStrm >> nRK;
rStrm.Ignore( 4 );
CreateFromDouble( *aEntry.pStr, XclTools::GetDoubleFromRK( nRK ) );
break;
case EXC_AFTYPE_DOUBLE:
rStrm >> fVal;
CreateFromDouble( *aEntry.pStr, fVal );
break;
case EXC_AFTYPE_STRING:
rStrm.Ignore( 4 );
rStrm >> nStrLen[ nE ];
rStrm.Ignore( 3 );
aEntry.pStr->Erase();
break;
case EXC_AFTYPE_BOOLERR:
rStrm >> nBoolErr >> nVal;
rStrm.Ignore( 6 );
aEntry.pStr->Assign( String::CreateFromInt32( (sal_Int32) nVal ) );
bIgnore = (sal_Bool) nBoolErr;
break;
case EXC_AFTYPE_EMPTY:
aEntry.bQueryByString = sal_False;
aEntry.nVal = SC_EMPTYFIELDS;
aEntry.eOp = SC_EQUAL;
break;
case EXC_AFTYPE_NOTEMPTY:
aEntry.bQueryByString = sal_False;
aEntry.nVal = SC_NONEMPTYFIELDS;
aEntry.eOp = SC_EQUAL;
break;
default:
rStrm.Ignore( 8 );
bIgnore = sal_True;
}
/* #i39464# conflict, if two conditions of one column are 'OR'ed,
and they follow conditions of other columns.
Example: Let A1 be a condition of column A, and B1 and B2
conditions of column B, connected with OR. Excel performs
'A1 AND (B1 OR B2)' in this case, but Calc would do
'(A1 AND B1) OR B2' instead. */
if( (nFirstEmpty > 1) && nE && (eConn == SC_OR) && !bIgnore )
bHasConflict = sal_True;
if( !bHasConflict && !bIgnore )
{
aEntry.bDoQuery = sal_True;
aEntry.bQueryByString = sal_True;
aEntry.nField = static_cast<SCCOLROW>(StartCol() + static_cast<SCCOL>(nCol));
aEntry.eConnect = nE ? eConn : SC_AND;
nFirstEmpty++;
}
}
else
rStrm.Ignore( 10 );
}
for( nE = 0; nE < 2; nE++ )
if( nStrLen[ nE ] && pQueryEntries[ nE ] )
{
pQueryEntries[ nE ]->pStr->Assign ( rStrm.ReadUniString( nStrLen[ nE ] ) );
ExcelQueryToOooQuery( *pQueryEntries[ nE ] );
}
}
}
void XclImpAutoFilterData::SetAdvancedRange( const ScRange* pRange )
{
if (pRange)
{
aCriteriaRange = *pRange;
bCriteria = sal_True;
}
else
bCriteria = sal_False;
}
void XclImpAutoFilterData::SetExtractPos( const ScAddress& rAddr )
{
aParam.nDestCol = rAddr.Col();
aParam.nDestRow = rAddr.Row();
aParam.nDestTab = rAddr.Tab();
aParam.bInplace = sal_False;
aParam.bDestPers = sal_True;
}
void XclImpAutoFilterData::Apply( const sal_Bool bUseUnNamed )
{
CreateScDBData(bUseUnNamed);
if( bActive )
{
InsertQueryParam();
// #i38093# rows hidden by filter need extra flag, but CR_FILTERED is not set here yet
// SCROW nRow1 = StartRow();
// SCROW nRow2 = EndRow();
// size_t nRows = nRow2 - nRow1 + 1;
// boost::scoped_array<sal_uInt8> pFlags( new sal_uInt8[nRows]);
// pExcRoot->pDoc->GetRowFlagsArray( Tab()).FillDataArray( nRow1, nRow2,
// pFlags.get());
// for (size_t j=0; j<nRows; ++j)
// {
// if ((pFlags[j] & CR_HIDDEN) && !(pFlags[j] & CR_FILTERED))
// pExcRoot->pDoc->SetRowFlags( nRow1 + j, Tab(),
// pFlags[j] | CR_FILTERED );
// }
}
}
void XclImpAutoFilterData::CreateScDBData( const sal_Bool bUseUnNamed )
{
// Create the ScDBData() object if the AutoFilter is activated
// or if we need to create the Advanced Filter.
if( bActive || bCriteria)
{
ScDBCollection& rColl = pExcRoot->pIR->GetDatabaseRanges();
pCurrDBData = rColl.GetDBAtArea( Tab(), StartCol(), StartRow(), EndCol(), EndRow() );
if( !pCurrDBData )
{
AmendAFName(bUseUnNamed);
pCurrDBData = new ScDBData( aFilterName, Tab(), StartCol(), StartRow(), EndCol(), EndRow() );
if( pCurrDBData )
{
if(bCriteria)
{
EnableRemoveFilter();
pCurrDBData->SetQueryParam( aParam );
pCurrDBData->SetAdvancedQuerySource(&aCriteriaRange);
}
else
pCurrDBData->SetAdvancedQuerySource(NULL);
rColl.Insert( pCurrDBData );
}
}
}
}
void XclImpAutoFilterData::EnableRemoveFilter()
{
// only if this is a saved Advanced filter
if( !bActive && bAutoOrAdvanced )
{
ScQueryEntry& aEntry = aParam.GetEntry( nFirstEmpty );
aEntry.bDoQuery = sal_True;
++nFirstEmpty;
}
// TBD: force the automatic activation of the
// "Remove Filter" by setting a virtual mouse click
// inside the advanced range
}
void XclImpAutoFilterData::AmendAFName(const sal_Bool bUseUnNamed)
{
// If-and-only-if we have one AF filter then
// use the Calc "unnamed" range name. Calc
// only supports one in total while Excel
// supports one per sheet.
if( bUseUnNamed && bAutoOrAdvanced )
aFilterName = ScGlobal::GetRscString(STR_DB_NONAME);
}
XclImpAutoFilterBuffer::XclImpAutoFilterBuffer() :
nAFActiveCount( 0 )
{
}
XclImpAutoFilterBuffer::~XclImpAutoFilterBuffer()
{
for( XclImpAutoFilterData* pData = _First(); pData; pData = _Next() )
delete pData;
}
void XclImpAutoFilterBuffer::Insert( RootData* pRoot, const ScRange& rRange,
const String& rName )
{
if( !GetByTab( rRange.aStart.Tab() ) )
Append( new XclImpAutoFilterData( pRoot, rRange, rName ) );
}
void XclImpAutoFilterBuffer::AddAdvancedRange( const ScRange& rRange )
{
XclImpAutoFilterData* pData = GetByTab( rRange.aStart.Tab() );
if( pData )
pData->SetAdvancedRange( &rRange );
}
void XclImpAutoFilterBuffer::AddExtractPos( const ScRange& rRange )
{
XclImpAutoFilterData* pData = GetByTab( rRange.aStart.Tab() );
if( pData )
pData->SetExtractPos( rRange.aStart );
}
void XclImpAutoFilterBuffer::Apply()
{
for( XclImpAutoFilterData* pData = _First(); pData; pData = _Next() )
pData->Apply(UseUnNamed());
}
XclImpAutoFilterData* XclImpAutoFilterBuffer::GetByTab( SCTAB nTab )
{
for( XclImpAutoFilterData* pData = _First(); pData; pData = _Next() )
if( pData->Tab() == nTab )
return pData;
return NULL;
}