1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "excimp8.hxx"
22 #include <boost/bind.hpp>
24 #include <scitems.hxx>
25 #include <comphelper/processfactory.hxx>
26 #include <comphelper/mediadescriptor.hxx>
27 #include <unotools/fltrcfg.hxx>
29 #include <vcl/wmf.hxx>
31 #include <editeng/eeitem.hxx>
33 #include <sfx2/docfile.hxx>
34 #include <sfx2/objsh.hxx>
35 #include <sfx2/request.hxx>
36 #include <sfx2/app.hxx>
37 #include <sfx2/docinf.hxx>
38 #include <sfx2/frame.hxx>
40 #include <editeng/brshitem.hxx>
41 #include <editeng/editdata.hxx>
42 #include <editeng/editeng.hxx>
43 #include <editeng/editobj.hxx>
44 #include <editeng/editstat.hxx>
45 #include <editeng/colritem.hxx>
46 #include <editeng/udlnitem.hxx>
47 #include <editeng/wghtitem.hxx>
48 #include <editeng/postitem.hxx>
49 #include <editeng/crsditem.hxx>
50 #include <editeng/flditem.hxx>
51 #include <svx/xflclit.hxx>
53 #include <vcl/graph.hxx>
54 #include <vcl/bmpacc.hxx>
55 #include <sot/exchange.hxx>
57 #include <svl/stritem.hxx>
59 #include <tools/string.hxx>
60 #include <rtl/math.hxx>
61 #include <unotools/localedatawrapper.hxx>
62 #include <unotools/charclass.hxx>
63 #include <drwlayer.hxx>
65 #include <boost/scoped_array.hpp>
68 #include "document.hxx"
69 #include "patattr.hxx"
70 #include "docpool.hxx"
72 #include "conditio.hxx"
74 #include "globalnames.hxx"
75 #include "editutil.hxx"
76 #include "markdata.hxx"
77 #include "rangenam.hxx"
78 #include "docoptio.hxx"
79 #include "globstr.hrc"
80 #include "fprogressbar.hxx"
81 #include "xltracer.hxx"
82 #include "xihelper.hxx"
84 #include "xicontent.hxx"
86 #include "xiescher.hxx"
87 #include "xipivot.hxx"
89 #include "excform.hxx"
90 #include "scextopt.hxx"
91 #include "stlpool.hxx"
92 #include "stlsheet.hxx"
93 #include "detfunc.hxx"
94 #include "macromgr.hxx"
95 #include "queryentry.hxx"
97 #include <com/sun/star/document/XDocumentProperties.hpp>
98 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
99 #include <com/sun/star/script/ModuleInfo.hpp>
100 #include <com/sun/star/container/XIndexContainer.hpp>
101 #include <cppuhelper/component_context.hxx>
102 #include "xltoolbar.hxx"
103 #include <oox/ole/vbaproject.hxx>
104 #include <oox/ole/olestorage.hxx>
105 #include <unotools/streamwrap.hxx>
106 #include <comphelper/processfactory.hxx>
108 using namespace com::sun::star
;
109 using namespace ::comphelper
;
110 using ::rtl::OUString
;
112 //OleNameOverrideContainer
114 typedef ::cppu::WeakImplHelper1
< container::XNameContainer
> OleNameOverrideContainer_BASE
;
116 class OleNameOverrideContainer
: public OleNameOverrideContainer_BASE
119 typedef boost::unordered_map
< rtl::OUString
, uno::Reference
< container::XIndexContainer
>, ::rtl::OUStringHash
,
120 ::std::equal_to
< ::rtl::OUString
> > NamedIndexToOleName
;
121 NamedIndexToOleName IdToOleNameHash
;
122 ::osl::Mutex m_aMutex
;
125 virtual uno::Type SAL_CALL
getElementType( ) throw (uno::RuntimeException
) { return container::XIndexContainer::static_type(0); }
126 virtual ::sal_Bool SAL_CALL
hasElements( ) throw (uno::RuntimeException
)
128 ::osl::MutexGuard
aGuard( m_aMutex
);
129 return ( IdToOleNameHash
.size() > 0 );
132 virtual uno::Any SAL_CALL
getByName( const ::rtl::OUString
& aName
) throw (container::NoSuchElementException
, lang::WrappedTargetException
, uno::RuntimeException
)
134 ::osl::MutexGuard
aGuard( m_aMutex
);
135 if ( !hasByName(aName
) )
136 throw container::NoSuchElementException();
137 return uno::makeAny( IdToOleNameHash
[ aName
] );
139 virtual uno::Sequence
< ::rtl::OUString
> SAL_CALL
getElementNames( ) throw (uno::RuntimeException
)
141 ::osl::MutexGuard
aGuard( m_aMutex
);
142 uno::Sequence
< ::rtl::OUString
> aResult( IdToOleNameHash
.size() );
143 NamedIndexToOleName::iterator it
= IdToOleNameHash
.begin();
144 NamedIndexToOleName::iterator it_end
= IdToOleNameHash
.end();
145 rtl::OUString
* pName
= aResult
.getArray();
146 for (; it
!= it_end
; ++it
, ++pName
)
150 virtual ::sal_Bool SAL_CALL
hasByName( const ::rtl::OUString
& aName
) throw (uno::RuntimeException
)
152 ::osl::MutexGuard
aGuard( m_aMutex
);
153 return ( IdToOleNameHash
.find( aName
) != IdToOleNameHash
.end() );
157 virtual ::sal_Int32 SAL_CALL
getCount( ) throw (uno::RuntimeException
)
159 ::osl::MutexGuard
aGuard( m_aMutex
);
160 return IdToOleNameHash
.size();
163 virtual void SAL_CALL
insertByName( const ::rtl::OUString
& aName
, const uno::Any
& aElement
) throw(lang::IllegalArgumentException
, container::ElementExistException
, lang::WrappedTargetException
, uno::RuntimeException
)
165 ::osl::MutexGuard
aGuard( m_aMutex
);
166 if ( hasByName( aName
) )
167 throw container::ElementExistException();
168 uno::Reference
< container::XIndexContainer
> xElement
;
169 if ( ! ( aElement
>>= xElement
) )
170 throw lang::IllegalArgumentException();
171 IdToOleNameHash
[ aName
] = xElement
;
173 virtual void SAL_CALL
removeByName( const ::rtl::OUString
& aName
) throw(container::NoSuchElementException
, lang::WrappedTargetException
, uno::RuntimeException
)
175 ::osl::MutexGuard
aGuard( m_aMutex
);
176 if ( !hasByName( aName
) )
177 throw container::NoSuchElementException();
178 IdToOleNameHash
.erase( IdToOleNameHash
.find( aName
) );
180 virtual void SAL_CALL
replaceByName( const ::rtl::OUString
& aName
, const uno::Any
& aElement
) throw(lang::IllegalArgumentException
, container::NoSuchElementException
, lang::WrappedTargetException
, uno::RuntimeException
)
182 ::osl::MutexGuard
aGuard( m_aMutex
);
183 if ( !hasByName( aName
) )
184 throw container::NoSuchElementException();
185 uno::Reference
< container::XIndexContainer
> xElement
;
186 if ( ! ( aElement
>>= xElement
) )
187 throw lang::IllegalArgumentException();
188 IdToOleNameHash
[ aName
] = xElement
;
192 ImportExcel8::ImportExcel8( XclImpRootData
& rImpData
, SvStream
& rStrm
) :
193 ImportExcel( rImpData
, rStrm
)
195 // replace BIFF2-BIFF5 formula importer with BIFF8 formula importer
197 pFormConv
= pExcRoot
->pFmlaConverter
= new ExcelToSc8( GetRoot() );
201 ImportExcel8::~ImportExcel8()
206 void ImportExcel8::Calccount( void )
208 ScDocOptions aOpt
= pD
->GetDocOptions();
209 aOpt
.SetIterCount( aIn
.ReaduInt16() );
210 pD
->SetDocOptions( aOpt
);
214 void ImportExcel8::Precision( void )
216 ScDocOptions aOpt
= pD
->GetDocOptions();
217 aOpt
.SetCalcAsShown( aIn
.ReaduInt16() == 0 );
218 pD
->SetDocOptions( aOpt
);
222 void ImportExcel8::Delta( void )
224 ScDocOptions aOpt
= pD
->GetDocOptions();
225 aOpt
.SetIterEps( aIn
.ReadDouble() );
226 pD
->SetDocOptions( aOpt
);
230 void ImportExcel8::Iteration( void )
232 ScDocOptions aOpt
= pD
->GetDocOptions();
233 aOpt
.SetIter( aIn
.ReaduInt16() == 1 );
234 pD
->SetDocOptions( aOpt
);
238 void ImportExcel8::Boundsheet( void )
243 aIn
.DisableDecryption();
244 maSheetOffsets
.push_back( aIn
.ReaduInt32() );
245 aIn
.EnableDecryption();
246 aIn
>> nGrbit
>> nLen
;
248 rtl::OUString
aName( aIn
.ReadUniString( nLen
) );
249 GetTabInfo().AppendXclTabName( aName
, nBdshtTab
);
251 SCTAB nScTab
= static_cast< SCTAB
>( nBdshtTab
);
254 OSL_ENSURE( !pD
->HasTable( nScTab
), "ImportExcel8::Boundsheet - sheet exists already" );
255 pD
->MakeTable( nScTab
);
258 if( ( nGrbit
& 0x0001 ) || ( nGrbit
& 0x0002 ) )
259 pD
->SetVisible( nScTab
, false );
261 if( !pD
->RenameTab( nScTab
, aName
) )
263 pD
->CreateValidTabName( aName
);
264 pD
->RenameTab( nScTab
, aName
);
271 void ImportExcel8::Scenman( void )
273 sal_uInt16 nLastDispl
;
278 maScenList
.nLastScenario
= nLastDispl
;
282 void ImportExcel8::Scenario( void )
284 maScenList
.aEntries
.push_back( new ExcScenario( aIn
, *pExcRoot
) );
288 void ImportExcel8::Labelsst( void )
294 aIn
>> aXclPos
>> nXF
>> nSst
;
296 ScAddress
aScPos( ScAddress::UNINITIALIZED
);
297 if( GetAddressConverter().ConvertAddress( aScPos
, aXclPos
, GetCurrScTab(), true ) )
299 GetXFRangeBuffer().SetXF( aScPos
, nXF
);
300 if( ScBaseCell
* pCell
= GetSst().CreateCell( nSst
, nXF
) )
301 GetDoc().PutCell( aScPos
.Col(), aScPos
.Row(), aScPos
.Tab(), pCell
);
306 void ImportExcel8::SheetProtection( void )
308 GetSheetProtectBuffer().ReadOptions( aIn
, GetCurrScTab() );
311 void ImportExcel8::ReadBasic( void )
313 SfxObjectShell
* pShell
= GetDocShell();
314 SotStorageRef xRootStrg
= GetRootStorage();
315 const SvtFilterOptions
& rFilterOpt
= SvtFilterOptions::Get();
316 if( pShell
&& xRootStrg
.Is() ) try
318 // #FIXME need to get rid of this, we can also do this from within oox
319 // via the "ooo.vba.VBAGlobals" service
320 if( ( rFilterOpt
.IsLoadExcelBasicCode() ||
321 rFilterOpt
.IsLoadExcelBasicStorage() ) &&
322 rFilterOpt
.IsLoadExcelBasicExecutable() )
324 // see if we have the XCB stream
325 SvStorageStreamRef xXCB
= xRootStrg
->OpenSotStream( String( RTL_CONSTASCII_USTRINGPARAM( "XCB" ) ), STREAM_STD_READ
| STREAM_NOCREATE
);
326 if ( xXCB
.Is()|| SVSTREAM_OK
== xXCB
->GetError() )
328 ScCTBWrapper wrapper
;
329 if ( wrapper
.Read( *xXCB
) )
331 #if OSL_DEBUG_LEVEL > 1
332 wrapper
.Print( stderr
);
334 wrapper
.ImportCustomToolBar( *pShell
);
340 uno::Reference
< uno::XComponentContext
> aCtx( ::comphelper::getProcessComponentContext() );
341 SfxMedium
& rMedium
= GetMedium();
342 uno::Reference
< io::XInputStream
> xIn
= rMedium
.GetInputStream();
343 oox::ole::OleStorage
root( aCtx
, xIn
, false );
344 oox::StorageRef vbaStg
= root
.openSubStorage( "_VBA_PROJECT_CUR", false );
347 oox::ole::VbaProject
aVbaPrj( aCtx
, pShell
->GetModel(), "Calc" );
348 // collect names of embedded form controls, as specified in the VBA project
349 uno::Reference
< container::XNameContainer
> xOleNameOverrideSink( new OleNameOverrideContainer
);
350 aVbaPrj
.setOleOverridesSink( xOleNameOverrideSink
);
351 aVbaPrj
.importVbaProject( *vbaStg
);
352 GetObjectManager().SetOleNameOverrideInfo( xOleNameOverrideSink
);
355 catch( uno::Exception
& )
359 catch( uno::Exception
& )
365 void ImportExcel8::EndSheet( void )
367 ImportExcel::EndSheet();
368 GetCondFormatManager().Apply();
369 GetValidationManager().Apply();
373 void ImportExcel8::PostDocLoad( void )
375 #ifndef DISABLE_SCRIPTING
376 // reading basic has been delayed until sheet objects (codenames etc.) are read
380 // #i11776# filtered ranges before outlines and hidden rows
381 if( pExcRoot
->pAutoFilterBuffer
)
382 pExcRoot
->pAutoFilterBuffer
->Apply();
384 GetWebQueryBuffer().Apply(); //! test if extant
385 GetSheetProtectBuffer().Apply();
386 GetDocProtectBuffer().Apply();
388 ImportExcel::PostDocLoad();
390 // Scenarien bemachen! ACHTUNG: Hier wird Tabellen-Anzahl im Dokument erhoeht!!
391 if( !pD
->IsClipboard() && maScenList
.aEntries
.size() )
393 pD
->UpdateChartListenerCollection(); // references in charts must be updated
395 maScenList
.Apply( GetRoot() );
398 // read doc info (no docshell while pasting from clipboard)
399 LoadDocumentProperties();
401 // #i45843# Pivot tables are now handled outside of PostDocLoad, so they are available
402 // when formula cells are calculated, for the GETPIVOTDATA function.
405 void ImportExcel8::LoadDocumentProperties()
407 // no docshell while pasting from clipboard
408 if( SfxObjectShell
* pShell
= GetDocShell() )
410 // BIFF5+ without storage is possible
411 SotStorageRef xRootStrg
= GetRootStorage();
412 if( xRootStrg
.Is() ) try
414 uno::Reference
< document::XDocumentPropertiesSupplier
> xDPS( pShell
->GetModel(), uno::UNO_QUERY_THROW
);
415 uno::Reference
< document::XDocumentProperties
> xDocProps( xDPS
->getDocumentProperties(), uno::UNO_SET_THROW
);
416 sfx2::LoadOlePropertySet( xDocProps
, xRootStrg
);
418 catch( uno::Exception
& )
424 //___________________________________________________________________
427 void ImportExcel8::FilterMode( void )
429 // The FilterMode record exists: if either the AutoFilter
430 // record exists or an Advanced Filter is saved and stored
431 // in the sheet. Thus if the FilterMode records only exists
432 // then the latter is true..
433 if( !pExcRoot
->pAutoFilterBuffer
) return;
435 XclImpAutoFilterData
* pData
= pExcRoot
->pAutoFilterBuffer
->GetByTab( GetCurrScTab() );
437 pData
->SetAutoOrAdvanced();
440 void ImportExcel8::AutoFilterInfo( void )
442 if( !pExcRoot
->pAutoFilterBuffer
) return;
444 XclImpAutoFilterData
* pData
= pExcRoot
->pAutoFilterBuffer
->GetByTab( GetCurrScTab() );
447 pData
->SetAdvancedRange( NULL
);
452 void ImportExcel8::AutoFilter( void )
454 if( !pExcRoot
->pAutoFilterBuffer
) return;
456 XclImpAutoFilterData
* pData
= pExcRoot
->pAutoFilterBuffer
->GetByTab( GetCurrScTab() );
458 pData
->ReadAutoFilter( aIn
);
463 XclImpAutoFilterData::XclImpAutoFilterData( RootData
* pRoot
, const ScRange
& rRange
) :
468 bAutoOrAdvanced(false)
470 aParam
.nCol1
= rRange
.aStart
.Col();
471 aParam
.nRow1
= rRange
.aStart
.Row();
472 aParam
.nTab
= rRange
.aStart
.Tab();
473 aParam
.nCol2
= rRange
.aEnd
.Col();
474 aParam
.nRow2
= rRange
.aEnd
.Row();
476 aParam
.bInplace
= sal_True
;
480 void XclImpAutoFilterData::CreateFromDouble( rtl::OUString
& rStr
, double fVal
)
482 rStr
+= ::rtl::math::doubleToUString(fVal
,
483 rtl_math_StringFormat_Automatic
, rtl_math_DecimalPlaces_Max
,
484 ScGlobal::pLocaleData
->getNumDecimalSep()[0], true);
487 void XclImpAutoFilterData::SetCellAttribs()
489 ScDocument
& rDoc
= pExcRoot
->pIR
->GetDoc();
490 for ( SCCOL nCol
= StartCol(); nCol
<= EndCol(); nCol
++ )
492 sal_Int16 nFlag
= ((ScMergeFlagAttr
*) rDoc
.GetAttr( nCol
, StartRow(), Tab(), ATTR_MERGE_FLAG
))->GetValue();
493 rDoc
.ApplyAttr( nCol
, StartRow(), Tab(), ScMergeFlagAttr( nFlag
| SC_MF_AUTO
) );
497 void XclImpAutoFilterData::InsertQueryParam()
502 sal_Bool bHasAdv
= pCurrDBData
->GetAdvancedQuerySource( aAdvRange
);
504 pExcRoot
->pIR
->GetDoc().CreateQueryParam( aAdvRange
.aStart
.Col(),
505 aAdvRange
.aStart
.Row(), aAdvRange
.aEnd
.Col(), aAdvRange
.aEnd
.Row(),
506 aAdvRange
.aStart
.Tab(), aParam
);
508 pCurrDBData
->SetQueryParam( aParam
);
510 pCurrDBData
->SetAdvancedQuerySource( &aAdvRange
);
513 pCurrDBData
->SetAutoFilter( sal_True
);
519 static void ExcelQueryToOooQuery( ScQueryEntry
& rEntry
)
521 if (rEntry
.eOp
!= SC_EQUAL
&& rEntry
.eOp
!= SC_NOT_EQUAL
)
524 String aStr
= rEntry
.GetQueryItem().maString
;
525 xub_StrLen nLen
= aStr
.Len();
526 sal_Unicode nStart
= aStr
.GetChar( 0 );
527 sal_Unicode nEnd
= aStr
.GetChar( nLen
-1 );
528 if( nLen
>2 && nStart
== '*' && nEnd
== '*' )
530 aStr
.Erase( nLen
-1, 1 );
532 rEntry
.eOp
= ( rEntry
.eOp
== SC_EQUAL
) ? SC_CONTAINS
: SC_DOES_NOT_CONTAIN
;
534 else if( nLen
> 1 && nStart
== '*' && nEnd
!= '*' )
537 rEntry
.eOp
= ( rEntry
.eOp
== SC_EQUAL
) ? SC_ENDS_WITH
: SC_DOES_NOT_END_WITH
;
539 else if( nLen
> 1 && nStart
!= '*' && nEnd
== '*' )
541 aStr
.Erase( nLen
-1, 1 );
542 rEntry
.eOp
= ( rEntry
.eOp
== SC_EQUAL
) ? SC_BEGINS_WITH
: SC_DOES_NOT_BEGIN_WITH
;
544 else if( nLen
== 2 && nStart
== '*' && nEnd
== '*' )
548 rEntry
.GetQueryItem().maString
= aStr
;
551 void XclImpAutoFilterData::ReadAutoFilter( XclImpStream
& rStrm
)
553 sal_uInt16 nCol
, nFlags
;
554 rStrm
>> nCol
>> nFlags
;
556 ScQueryConnect eConn
= ::get_flagvalue( nFlags
, EXC_AFFLAG_ANDORMASK
, SC_OR
, SC_AND
);
557 bool bSimple1
= ::get_flag(nFlags
, EXC_AFFLAG_SIMPLE1
);
558 bool bSimple2
= ::get_flag(nFlags
, EXC_AFFLAG_SIMPLE2
);
559 bool bTop10
= ::get_flag(nFlags
, EXC_AFFLAG_TOP10
);
560 bool bTopOfTop10
= ::get_flag(nFlags
, EXC_AFFLAG_TOP10TOP
);
561 bool bPercent
= ::get_flag(nFlags
, EXC_AFFLAG_TOP10PERC
);
562 sal_uInt16 nCntOfTop10
= nFlags
>> 7;
566 ScQueryEntry
& aEntry
= aParam
.AppendEntry();
567 ScQueryEntry::Item
& rItem
= aEntry
.GetQueryItem();
568 aEntry
.bDoQuery
= true;
569 aEntry
.nField
= static_cast<SCCOLROW
>(StartCol() + static_cast<SCCOL
>(nCol
));
570 aEntry
.eOp
= bTopOfTop10
?
571 (bPercent
? SC_TOPPERC
: SC_TOPVAL
) : (bPercent
? SC_BOTPERC
: SC_BOTVAL
);
572 aEntry
.eConnect
= SC_AND
;
574 rItem
.meType
= ScQueryEntry::ByString
;
575 rItem
.maString
= rtl::OUString::valueOf(static_cast<sal_Int32
>(nCntOfTop10
));
581 sal_uInt8 nType
, nOper
, nBoolErr
, nVal
;
586 sal_uInt8 nStrLen
[2] = { 0, 0 };
587 ScQueryEntry aEntries
[2];
589 for (size_t nE
= 0; nE
< 2; ++nE
)
591 ScQueryEntry
& rEntry
= aEntries
[nE
];
592 ScQueryEntry::Item
& rItem
= rEntry
.GetQueryItem();
595 rStrm
>> nType
>> nOper
;
598 case EXC_AFOPER_LESS
:
599 rEntry
.eOp
= SC_LESS
;
601 case EXC_AFOPER_EQUAL
:
602 rEntry
.eOp
= SC_EQUAL
;
604 case EXC_AFOPER_LESSEQUAL
:
605 rEntry
.eOp
= SC_LESS_EQUAL
;
607 case EXC_AFOPER_GREATER
:
608 rEntry
.eOp
= SC_GREATER
;
610 case EXC_AFOPER_NOTEQUAL
:
611 rEntry
.eOp
= SC_NOT_EQUAL
;
613 case EXC_AFOPER_GREATEREQUAL
:
614 rEntry
.eOp
= SC_GREATER_EQUAL
;
617 rEntry
.eOp
= SC_EQUAL
;
628 rItem
.maString
, XclTools::GetDoubleFromRK(nRK
));
630 case EXC_AFTYPE_DOUBLE
:
632 CreateFromDouble(rItem
.maString
, fVal
);
634 case EXC_AFTYPE_STRING
:
636 rStrm
>> nStrLen
[ nE
];
638 rItem
.maString
= rtl::OUString();
640 case EXC_AFTYPE_BOOLERR
:
641 rStrm
>> nBoolErr
>> nVal
;
643 rItem
.maString
= rtl::OUString::valueOf(static_cast<sal_Int32
>(nVal
));
644 bIgnore
= (nBoolErr
!= 0);
646 case EXC_AFTYPE_EMPTY
:
647 rEntry
.SetQueryByEmpty();
649 case EXC_AFTYPE_NOTEMPTY
:
650 rEntry
.SetQueryByNonEmpty();
659 rEntry
.bDoQuery
= true;
660 rItem
.meType
= ScQueryEntry::ByString
;
661 rEntry
.nField
= static_cast<SCCOLROW
>(StartCol() + static_cast<SCCOL
>(nCol
));
662 rEntry
.eConnect
= nE
? eConn
: SC_AND
;
668 for (size_t nE
= 0; nE
< 2; ++nE
)
670 if (nStrLen
[nE
] && aEntries
[nE
].bDoQuery
)
672 aEntries
[nE
].GetQueryItem().maString
= rStrm
.ReadUniString(nStrLen
[nE
]);
673 ExcelQueryToOooQuery(aEntries
[nE
]);
674 aParam
.AppendEntry() = aEntries
[nE
];
680 OSL_ASSERT(eConn
== SC_OR
);
681 // Import only when both conditions are for simple equality, else
682 // import only the 1st condition due to conflict with the ordering of
683 // conditions. #i39464#.
685 // Example: Let A1 be a condition of column A, and B1 and B2
686 // conditions of column B, connected with OR. Excel performs 'A1 AND
687 // (B1 OR B2)' in this case, but Calc would do '(A1 AND B1) OR B2'
690 if (bSimple1
&& bSimple2
&& nStrLen
[0] && nStrLen
[1])
692 // Two simple OR'ed equal conditions. We can import this correctly.
693 ScQueryEntry
& rEntry
= aParam
.AppendEntry();
694 rEntry
.bDoQuery
= true;
695 rEntry
.eOp
= SC_EQUAL
;
696 rEntry
.eConnect
= SC_AND
;
697 ScQueryEntry::QueryItemsType aItems
;
699 ScQueryEntry::Item aItem1
, aItem2
;
700 aItem1
.maString
= rStrm
.ReadUniString(nStrLen
[0]);
701 aItem1
.meType
= ScQueryEntry::ByString
;
702 aItem2
.maString
= rStrm
.ReadUniString(nStrLen
[1]);
703 aItem2
.meType
= ScQueryEntry::ByString
;
704 aItems
.push_back(aItem1
);
705 aItems
.push_back(aItem2
);
706 rEntry
.GetQueryItems().swap(aItems
);
708 else if (nStrLen
[0] && aEntries
[0].bDoQuery
)
710 // Due to conflict, we can import only the first condition.
711 aEntries
[0].GetQueryItem().maString
= rStrm
.ReadUniString(nStrLen
[0]);
712 ExcelQueryToOooQuery(aEntries
[0]);
713 aParam
.AppendEntry() = aEntries
[0];
718 void XclImpAutoFilterData::SetAdvancedRange( const ScRange
* pRange
)
722 aCriteriaRange
= *pRange
;
729 void XclImpAutoFilterData::SetExtractPos( const ScAddress
& rAddr
)
731 aParam
.nDestCol
= rAddr
.Col();
732 aParam
.nDestRow
= rAddr
.Row();
733 aParam
.nDestTab
= rAddr
.Tab();
734 aParam
.bInplace
= false;
735 aParam
.bDestPers
= sal_True
;
738 void XclImpAutoFilterData::Apply()
746 // #i38093# rows hidden by filter need extra flag, but CR_FILTERED is not set here yet
747 // SCROW nRow1 = StartRow();
748 // SCROW nRow2 = EndRow();
749 // size_t nRows = nRow2 - nRow1 + 1;
750 // boost::scoped_array<sal_uInt8> pFlags( new sal_uInt8[nRows]);
751 // pExcRoot->pDoc->GetRowFlagsArray( Tab()).FillDataArray( nRow1, nRow2,
753 // for (size_t j=0; j<nRows; ++j)
755 // if ((pFlags[j] & CR_HIDDEN) && !(pFlags[j] & CR_FILTERED))
756 // pExcRoot->pDoc->SetRowFlags( nRow1 + j, Tab(),
757 // pFlags[j] | CR_FILTERED );
762 void XclImpAutoFilterData::CreateScDBData()
765 // Create the ScDBData() object if the AutoFilter is activated
766 // or if we need to create the Advanced Filter.
767 if( bActive
|| bCriteria
)
769 ScDocument
* pDoc
= pExcRoot
->pIR
->GetDocPtr();
770 String aNewName
= rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(STR_DB_LOCAL_NONAME
));
771 pCurrDBData
= new ScDBData(aNewName
, Tab(),
772 StartCol(),StartRow(), EndCol(),EndRow() );
775 EnableRemoveFilter();
777 pCurrDBData
->SetQueryParam( aParam
);
778 pCurrDBData
->SetAdvancedQuerySource(&aCriteriaRange
);
781 pCurrDBData
->SetAdvancedQuerySource(NULL
);
782 pDoc
->SetAnonymousDBData(Tab(), pCurrDBData
);
787 void XclImpAutoFilterData::EnableRemoveFilter()
789 // only if this is a saved Advanced filter
790 if( !bActive
&& bAutoOrAdvanced
)
792 ScQueryEntry
& aEntry
= aParam
.AppendEntry();
793 aEntry
.bDoQuery
= true;
796 // TBD: force the automatic activation of the
797 // "Remove Filter" by setting a virtual mouse click
798 // inside the advanced range
801 void XclImpAutoFilterBuffer::Insert( RootData
* pRoot
, const ScRange
& rRange
)
803 if( !GetByTab( rRange
.aStart
.Tab() ) )
804 maFilters
.push_back( new XclImpAutoFilterData( pRoot
, rRange
) );
807 void XclImpAutoFilterBuffer::AddAdvancedRange( const ScRange
& rRange
)
809 XclImpAutoFilterData
* pData
= GetByTab( rRange
.aStart
.Tab() );
811 pData
->SetAdvancedRange( &rRange
);
814 void XclImpAutoFilterBuffer::AddExtractPos( const ScRange
& rRange
)
816 XclImpAutoFilterData
* pData
= GetByTab( rRange
.aStart
.Tab() );
818 pData
->SetExtractPos( rRange
.aStart
);
821 void XclImpAutoFilterBuffer::Apply()
823 std::for_each(maFilters
.begin(),maFilters
.end(),
824 boost::bind(&XclImpAutoFilterData::Apply
,_1
));
827 XclImpAutoFilterData
* XclImpAutoFilterBuffer::GetByTab( SCTAB nTab
)
829 boost::ptr_vector
<XclImpAutoFilterData
>::iterator it
;
830 for( it
= maFilters
.begin(); it
!= maFilters
.end(); ++it
)
832 if( it
->Tab() == nTab
)
833 return const_cast<XclImpAutoFilterData
*>(&(*it
));
838 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */