fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / filter / excel / excimp8.cxx
blob3b91332d61acb1d208b4a128408e6383874c362d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <config_features.h>
22 #include "excimp8.hxx"
24 #include <boost/bind.hpp>
26 #include <scitems.hxx>
27 #include <comphelper/processfactory.hxx>
28 #include <unotools/fltrcfg.hxx>
30 #include <vcl/wmf.hxx>
32 #include <editeng/eeitem.hxx>
34 #include <sfx2/docfile.hxx>
35 #include <sfx2/objsh.hxx>
36 #include <sfx2/request.hxx>
37 #include <sfx2/app.hxx>
38 #include <sfx2/docinf.hxx>
39 #include <sfx2/frame.hxx>
41 #include <editeng/brushitem.hxx>
42 #include <editeng/editdata.hxx>
43 #include <editeng/editeng.hxx>
44 #include <editeng/editobj.hxx>
45 #include <editeng/editstat.hxx>
46 #include <editeng/colritem.hxx>
47 #include <editeng/udlnitem.hxx>
48 #include <editeng/wghtitem.hxx>
49 #include <editeng/postitem.hxx>
50 #include <editeng/crossedoutitem.hxx>
51 #include <editeng/flditem.hxx>
52 #include <svx/xflclit.hxx>
54 #include <vcl/graph.hxx>
55 #include <vcl/bmpacc.hxx>
56 #include <sot/exchange.hxx>
58 #include <svl/stritem.hxx>
59 #include <svl/sharedstringpool.hxx>
61 #include <rtl/math.hxx>
62 #include <rtl/ustring.hxx>
63 #include <unotools/localedatawrapper.hxx>
64 #include <unotools/charclass.hxx>
65 #include <drwlayer.hxx>
67 #include <boost/scoped_array.hpp>
69 #include "formulacell.hxx"
70 #include "document.hxx"
71 #include "patattr.hxx"
72 #include "docpool.hxx"
73 #include "attrib.hxx"
74 #include "conditio.hxx"
75 #include "dbdata.hxx"
76 #include "globalnames.hxx"
77 #include "editutil.hxx"
78 #include "markdata.hxx"
79 #include "rangenam.hxx"
80 #include "docoptio.hxx"
81 #include "globstr.hrc"
82 #include "fprogressbar.hxx"
83 #include "xltracer.hxx"
84 #include "xihelper.hxx"
85 #include "xipage.hxx"
86 #include "xicontent.hxx"
87 #include "xilink.hxx"
88 #include "xiescher.hxx"
89 #include "xipivot.hxx"
91 #include "excform.hxx"
92 #include "scextopt.hxx"
93 #include "stlpool.hxx"
94 #include "stlsheet.hxx"
95 #include "detfunc.hxx"
96 #include "macromgr.hxx"
97 #include "queryentry.hxx"
99 #include <com/sun/star/document/XDocumentProperties.hpp>
100 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
101 #include <com/sun/star/script/ModuleInfo.hpp>
102 #include <com/sun/star/container/XIndexContainer.hpp>
103 #include <cppuhelper/component_context.hxx>
104 #include "xltoolbar.hxx"
105 #include <oox/ole/vbaproject.hxx>
106 #include <oox/ole/olestorage.hxx>
107 #include <unotools/streamwrap.hxx>
109 using namespace com::sun::star;
110 using namespace ::comphelper;
112 //OleNameOverrideContainer
114 typedef ::cppu::WeakImplHelper1< container::XNameContainer > OleNameOverrideContainer_BASE;
116 class OleNameOverrideContainer : public OleNameOverrideContainer_BASE
118 private:
119 typedef std::unordered_map< OUString, uno::Reference< container::XIndexContainer >, OUStringHash,
120 std::equal_to< OUString > > NamedIndexToOleName;
121 NamedIndexToOleName IdToOleNameHash;
122 ::osl::Mutex m_aMutex;
123 public:
124 // XElementAccess
125 virtual uno::Type SAL_CALL getElementType( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE { return cppu::UnoType<container::XIndexContainer>::get(); }
126 virtual sal_Bool SAL_CALL hasElements( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
128 ::osl::MutexGuard aGuard( m_aMutex );
129 return ( !IdToOleNameHash.empty() );
131 // XNameAcess
132 virtual uno::Any SAL_CALL getByName( const OUString& aName ) throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException, std::exception) SAL_OVERRIDE
134 ::osl::MutexGuard aGuard( m_aMutex );
135 if ( !hasByName(aName) )
136 throw container::NoSuchElementException();
137 return uno::makeAny( IdToOleNameHash[ aName ] );
139 virtual uno::Sequence< OUString > SAL_CALL getElementNames( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
141 ::osl::MutexGuard aGuard( m_aMutex );
142 uno::Sequence< OUString > aResult( IdToOleNameHash.size() );
143 NamedIndexToOleName::iterator it = IdToOleNameHash.begin();
144 NamedIndexToOleName::iterator it_end = IdToOleNameHash.end();
145 OUString* pName = aResult.getArray();
146 for (; it != it_end; ++it, ++pName )
147 *pName = it->first;
148 return aResult;
150 virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
152 ::osl::MutexGuard aGuard( m_aMutex );
153 return ( IdToOleNameHash.find( aName ) != IdToOleNameHash.end() );
156 // XNameContainer
157 virtual void SAL_CALL insertByName( const OUString& aName, const uno::Any& aElement ) throw(lang::IllegalArgumentException, container::ElementExistException, lang::WrappedTargetException, uno::RuntimeException, std::exception) SAL_OVERRIDE
159 ::osl::MutexGuard aGuard( m_aMutex );
160 if ( hasByName( aName ) )
161 throw container::ElementExistException();
162 uno::Reference< container::XIndexContainer > xElement;
163 if ( ! ( aElement >>= xElement ) )
164 throw lang::IllegalArgumentException();
165 IdToOleNameHash[ aName ] = xElement;
167 virtual void SAL_CALL removeByName( const OUString& aName ) throw(container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException, std::exception) SAL_OVERRIDE
169 ::osl::MutexGuard aGuard( m_aMutex );
170 if ( !hasByName( aName ) )
171 throw container::NoSuchElementException();
172 IdToOleNameHash.erase( IdToOleNameHash.find( aName ) );
174 virtual void SAL_CALL replaceByName( const OUString& aName, const uno::Any& aElement ) throw(lang::IllegalArgumentException, container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException, std::exception) SAL_OVERRIDE
176 ::osl::MutexGuard aGuard( m_aMutex );
177 if ( !hasByName( aName ) )
178 throw container::NoSuchElementException();
179 uno::Reference< container::XIndexContainer > xElement;
180 if ( ! ( aElement >>= xElement ) )
181 throw lang::IllegalArgumentException();
182 IdToOleNameHash[ aName ] = xElement;
186 namespace {
188 /** Future Record Type header.
189 @return whether read rt matches nRecordID
191 bool readFrtHeader( XclImpStream& rStrm, sal_uInt16 nRecordID )
193 sal_uInt16 nRt = rStrm.ReaduInt16();
194 rStrm.Ignore(10); // grbitFrt (2 bytes) and reserved (8 bytes)
195 return nRt == nRecordID;
200 ImportExcel8::ImportExcel8( XclImpRootData& rImpData, SvStream& rStrm ) :
201 ImportExcel( rImpData, rStrm )
203 // replace BIFF2-BIFF5 formula importer with BIFF8 formula importer
204 delete pFormConv;
205 pFormConv = pExcRoot->pFmlaConverter = new ExcelToSc8( GetRoot() );
208 ImportExcel8::~ImportExcel8()
212 void ImportExcel8::Calccount()
214 ScDocOptions aOpt = pD->GetDocOptions();
215 aOpt.SetIterCount( aIn.ReaduInt16() );
216 pD->SetDocOptions( aOpt );
219 void ImportExcel8::Precision()
221 ScDocOptions aOpt = pD->GetDocOptions();
222 aOpt.SetCalcAsShown( aIn.ReaduInt16() == 0 );
223 pD->SetDocOptions( aOpt );
226 void ImportExcel8::Delta()
228 ScDocOptions aOpt = pD->GetDocOptions();
229 aOpt.SetIterEps( aIn.ReadDouble() );
230 pD->SetDocOptions( aOpt );
233 void ImportExcel8::Iteration()
235 ScDocOptions aOpt = pD->GetDocOptions();
236 aOpt.SetIter( aIn.ReaduInt16() == 1 );
237 pD->SetDocOptions( aOpt );
240 void ImportExcel8::Boundsheet()
242 sal_uInt8 nLen;
243 sal_uInt16 nGrbit;
245 aIn.DisableDecryption();
246 maSheetOffsets.push_back( aIn.ReaduInt32() );
247 aIn.EnableDecryption();
248 nGrbit = aIn.ReaduInt16();
249 nLen = aIn.ReaduInt8();
251 OUString aName( aIn.ReadUniString( nLen ) );
252 GetTabInfo().AppendXclTabName( aName, nBdshtTab );
254 SCTAB nScTab = static_cast< SCTAB >( nBdshtTab );
255 if( nScTab > 0 )
257 OSL_ENSURE( !pD->HasTable( nScTab ), "ImportExcel8::Boundsheet - sheet exists already" );
258 pD->MakeTable( nScTab );
261 if( ( nGrbit & 0x0001 ) || ( nGrbit & 0x0002 ) )
262 pD->SetVisible( nScTab, false );
264 if( !pD->RenameTab( nScTab, aName ) )
266 pD->CreateValidTabName( aName );
267 pD->RenameTab( nScTab, aName );
270 nBdshtTab++;
273 void ImportExcel8::Scenman()
275 sal_uInt16 nLastDispl;
277 aIn.Ignore( 4 );
278 nLastDispl = aIn.ReaduInt16();
280 maScenList.nLastScenario = nLastDispl;
283 void ImportExcel8::Scenario()
285 maScenList.aEntries.push_back( new ExcScenario( aIn, *pExcRoot ) );
288 void ImportExcel8::Labelsst()
290 XclAddress aXclPos;
291 sal_uInt16 nXF;
292 sal_uInt32 nSst;
294 aIn >> aXclPos;
295 nXF = aIn.ReaduInt16();
296 nSst = aIn.ReaduInt32( );
298 ScAddress aScPos( ScAddress::UNINITIALIZED );
299 if( GetAddressConverter().ConvertAddress( aScPos, aXclPos, GetCurrScTab(), true ) )
301 GetXFRangeBuffer().SetXF( aScPos, nXF );
302 const XclImpString* pXclStr = GetSst().GetString(nSst);
303 if (pXclStr)
304 XclImpStringHelper::SetToDocument(GetDocImport(), aScPos, *this, *pXclStr, nXF);
308 void ImportExcel8::FeatHdr()
310 if (!readFrtHeader( aIn, 0x0867))
311 return;
313 // Feature type (isf) can be EXC_ISFPROTECTION, EXC_ISFFEC2 or
314 // EXC_ISFFACTOID.
315 sal_uInt16 nFeatureType = aIn.ReaduInt16();
316 if (nFeatureType != EXC_ISFPROTECTION)
317 // We currently only support import of enhanced protection data.
318 return;
320 aIn.Ignore(1); // always 1
322 GetSheetProtectBuffer().ReadOptions( aIn, GetCurrScTab() );
325 void ImportExcel8::Feat()
327 if (!readFrtHeader( aIn, 0x0868))
328 return;
330 // Feature type (isf) can be EXC_ISFPROTECTION, EXC_ISFFEC2 or
331 // EXC_ISFFACTOID.
332 sal_uInt16 nFeatureType = aIn.ReaduInt16();
333 if (nFeatureType != EXC_ISFPROTECTION)
334 // We currently only support import of enhanced protection data.
335 return;
337 aIn.Ignore(5); // reserved1 (1 byte) and reserved2 (4 bytes)
339 sal_uInt16 nCref = aIn.ReaduInt16(); // number of ref elements
340 aIn.Ignore(4); // size if EXC_ISFFEC2, else 0 and to be ignored
341 aIn.Ignore(2); // reserved3 (2 bytes)
343 ScEnhancedProtection aProt;
344 if (nCref)
346 XclRangeList aRefs;
347 aRefs.Read( aIn, true, nCref);
348 if (!aRefs.empty())
350 aProt.maRangeList = new ScRangeList;
351 GetAddressConverter().ConvertRangeList( *aProt.maRangeList, aRefs, GetCurrScTab(), false);
355 // FeatProtection structure follows in record.
357 aProt.mnAreserved = aIn.ReaduInt32();
358 aProt.mnPasswordVerifier = aIn.ReaduInt32();
359 aProt.maTitle = aIn.ReadUniString();
360 if ((aProt.mnAreserved & 0x00000001) == 0x00000001)
362 sal_uInt32 nCbSD = aIn.ReaduInt32();
363 // TODO: could here be some sanity check applied to not allocate 4GB?
364 aProt.maSecurityDescriptor.resize( nCbSD);
365 sal_Size nRead = aIn.Read( &aProt.maSecurityDescriptor.front(), nCbSD);
366 if (nRead < nCbSD)
367 aProt.maSecurityDescriptor.resize( nRead);
370 GetSheetProtectBuffer().AppendEnhancedProtection( aProt, GetCurrScTab() );
373 void ImportExcel8::ReadBasic()
375 SfxObjectShell* pShell = GetDocShell();
376 tools::SvRef<SotStorage> xRootStrg = GetRootStorage();
377 const SvtFilterOptions& rFilterOpt = SvtFilterOptions::Get();
378 if( pShell && xRootStrg.Is() ) try
380 // #FIXME need to get rid of this, we can also do this from within oox
381 // via the "ooo.vba.VBAGlobals" service
382 if( ( rFilterOpt.IsLoadExcelBasicCode() ||
383 rFilterOpt.IsLoadExcelBasicStorage() ) &&
384 rFilterOpt.IsLoadExcelBasicExecutable() )
386 // see if we have the XCB stream
387 tools::SvRef<SotStorageStream> xXCB = xRootStrg->OpenSotStream( OUString("XCB"), STREAM_STD_READ | StreamMode::NOCREATE );
388 if ( xXCB.Is()|| SVSTREAM_OK == xXCB->GetError() )
390 ScCTBWrapper wrapper;
391 if ( wrapper.Read( *xXCB ) )
393 #if OSL_DEBUG_LEVEL > 1
394 wrapper.Print( stderr );
395 #endif
396 wrapper.ImportCustomToolBar( *pShell );
402 uno::Reference< uno::XComponentContext > aCtx( ::comphelper::getProcessComponentContext() );
403 SfxMedium& rMedium = GetMedium();
404 uno::Reference< io::XInputStream > xIn = rMedium.GetInputStream();
405 oox::ole::OleStorage root( aCtx, xIn, false );
406 oox::StorageRef vbaStg = root.openSubStorage( "_VBA_PROJECT_CUR", false );
407 if ( vbaStg.get() )
409 oox::ole::VbaProject aVbaPrj( aCtx, pShell->GetModel(), "Calc" );
410 // collect names of embedded form controls, as specified in the VBA project
411 uno::Reference< container::XNameContainer > xOleNameOverrideSink( new OleNameOverrideContainer );
412 aVbaPrj.setOleOverridesSink( xOleNameOverrideSink );
413 aVbaPrj.importVbaProject( *vbaStg );
414 GetObjectManager().SetOleNameOverrideInfo( xOleNameOverrideSink );
417 catch( uno::Exception& )
421 catch( uno::Exception& )
426 void ImportExcel8::EndSheet()
428 ImportExcel::EndSheet();
429 GetCondFormatManager().Apply();
430 GetValidationManager().Apply();
433 void ImportExcel8::PostDocLoad()
435 #if HAVE_FEATURE_SCRIPTING
436 // reading basic has been delayed until sheet objects (codenames etc.) are read
437 if( HasBasic() )
438 ReadBasic();
439 #endif
440 // #i11776# filtered ranges before outlines and hidden rows
441 if( pExcRoot->pAutoFilterBuffer )
442 pExcRoot->pAutoFilterBuffer->Apply();
444 GetWebQueryBuffer().Apply(); //TODO: test if extant
445 GetSheetProtectBuffer().Apply();
446 GetDocProtectBuffer().Apply();
448 ImportExcel::PostDocLoad();
450 // check scenarios; Attention: This increases the table count of the document!!
451 if( !pD->IsClipboard() && maScenList.aEntries.size() )
453 pD->UpdateChartListenerCollection(); // references in charts must be updated
455 maScenList.Apply( GetRoot() );
458 // read doc info (no docshell while pasting from clipboard)
459 LoadDocumentProperties();
461 // #i45843# Pivot tables are now handled outside of PostDocLoad, so they are available
462 // when formula cells are calculated, for the GETPIVOTDATA function.
465 void ImportExcel8::LoadDocumentProperties()
467 // no docshell while pasting from clipboard
468 if( SfxObjectShell* pShell = GetDocShell() )
470 // BIFF5+ without storage is possible
471 tools::SvRef<SotStorage> xRootStrg = GetRootStorage();
472 if( xRootStrg.Is() ) try
474 uno::Reference< document::XDocumentPropertiesSupplier > xDPS( pShell->GetModel(), uno::UNO_QUERY_THROW );
475 uno::Reference< document::XDocumentProperties > xDocProps( xDPS->getDocumentProperties(), uno::UNO_SET_THROW );
476 sfx2::LoadOlePropertySet( xDocProps, xRootStrg );
478 catch( uno::Exception& )
484 // autofilter
486 void ImportExcel8::FilterMode()
488 // The FilterMode record exists: if either the AutoFilter
489 // record exists or an Advanced Filter is saved and stored
490 // in the sheet. Thus if the FilterMode records only exists
491 // then the latter is true..
492 if( !pExcRoot->pAutoFilterBuffer ) return;
494 XclImpAutoFilterData* pData = pExcRoot->pAutoFilterBuffer->GetByTab( GetCurrScTab() );
495 if( pData )
496 pData->SetAutoOrAdvanced();
499 void ImportExcel8::AutoFilterInfo()
501 if( !pExcRoot->pAutoFilterBuffer ) return;
503 XclImpAutoFilterData* pData = pExcRoot->pAutoFilterBuffer->GetByTab( GetCurrScTab() );
504 if( pData )
506 pData->SetAdvancedRange( NULL );
507 pData->Activate();
511 void ImportExcel8::AutoFilter()
513 if( !pExcRoot->pAutoFilterBuffer ) return;
515 XclImpAutoFilterData* pData = pExcRoot->pAutoFilterBuffer->GetByTab( GetCurrScTab() );
516 if( pData )
517 pData->ReadAutoFilter(aIn, GetDoc().GetSharedStringPool());
520 XclImpAutoFilterData::XclImpAutoFilterData( RootData* pRoot, const ScRange& rRange ) :
521 ExcRoot( pRoot ),
522 pCurrDBData(NULL),
523 bActive( false ),
524 bCriteria( false ),
525 bAutoOrAdvanced(false)
527 aParam.nCol1 = rRange.aStart.Col();
528 aParam.nRow1 = rRange.aStart.Row();
529 aParam.nTab = rRange.aStart.Tab();
530 aParam.nCol2 = rRange.aEnd.Col();
531 aParam.nRow2 = rRange.aEnd.Row();
533 aParam.bInplace = true;
537 namespace {
539 OUString CreateFromDouble( double fVal )
541 return rtl::math::doubleToUString(fVal,
542 rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max,
543 ScGlobal::pLocaleData->getNumDecimalSep()[0], true);
548 void XclImpAutoFilterData::SetCellAttribs()
550 ScDocument& rDoc = pExcRoot->pIR->GetDoc();
551 for ( SCCOL nCol = StartCol(); nCol <= EndCol(); nCol++ )
553 sal_Int16 nFlag = static_cast<const ScMergeFlagAttr*>( rDoc.GetAttr( nCol, StartRow(), Tab(), ATTR_MERGE_FLAG ))->GetValue();
554 rDoc.ApplyAttr( nCol, StartRow(), Tab(), ScMergeFlagAttr( nFlag | SC_MF_AUTO) );
558 void XclImpAutoFilterData::InsertQueryParam()
560 if (pCurrDBData)
562 ScRange aAdvRange;
563 bool bHasAdv = pCurrDBData->GetAdvancedQuerySource( aAdvRange );
564 if( bHasAdv )
565 pExcRoot->pIR->GetDoc().CreateQueryParam( aAdvRange.aStart.Col(),
566 aAdvRange.aStart.Row(), aAdvRange.aEnd.Col(), aAdvRange.aEnd.Row(),
567 aAdvRange.aStart.Tab(), aParam );
569 pCurrDBData->SetQueryParam( aParam );
570 if( bHasAdv )
571 pCurrDBData->SetAdvancedQuerySource( &aAdvRange );
572 else
574 pCurrDBData->SetAutoFilter( true );
575 SetCellAttribs();
580 static void ExcelQueryToOooQuery( OUString& aStr, ScQueryEntry& rEntry )
582 if (rEntry.eOp != SC_EQUAL && rEntry.eOp != SC_NOT_EQUAL)
583 return;
585 sal_Int32 nLen = aStr.getLength();
586 sal_Unicode nStart = aStr[0];
587 sal_Unicode nEnd = aStr[ nLen-1 ];
588 if( nLen > 2 && nStart == '*' && nEnd == '*' )
590 aStr = aStr.copy( 1, nLen-2 );
591 rEntry.eOp = ( rEntry.eOp == SC_EQUAL ) ? SC_CONTAINS : SC_DOES_NOT_CONTAIN;
593 else if( nLen > 1 && nStart == '*' && nEnd != '*' )
595 aStr = aStr.copy( 1 );
596 rEntry.eOp = ( rEntry.eOp == SC_EQUAL ) ? SC_ENDS_WITH : SC_DOES_NOT_END_WITH;
598 else if( nLen > 1 && nStart != '*' && nEnd == '*' )
600 aStr = aStr.copy( 0, nLen-1 );
601 rEntry.eOp = ( rEntry.eOp == SC_EQUAL ) ? SC_BEGINS_WITH : SC_DOES_NOT_BEGIN_WITH;
603 else if( nLen == 2 && nStart == '*' && nEnd == '*' )
605 aStr = aStr.copy( 1 );
609 void XclImpAutoFilterData::ReadAutoFilter(
610 XclImpStream& rStrm, svl::SharedStringPool& rPool )
612 sal_uInt16 nCol, nFlags;
613 nCol = rStrm.ReaduInt16();
614 nFlags = rStrm.ReaduInt16();
616 ScQueryConnect eConn = ::get_flagvalue( nFlags, EXC_AFFLAG_ANDORMASK, SC_OR, SC_AND );
617 bool bSimple1 = ::get_flag(nFlags, EXC_AFFLAG_SIMPLE1);
618 bool bSimple2 = ::get_flag(nFlags, EXC_AFFLAG_SIMPLE2);
619 bool bTop10 = ::get_flag(nFlags, EXC_AFFLAG_TOP10);
620 bool bTopOfTop10 = ::get_flag(nFlags, EXC_AFFLAG_TOP10TOP);
621 bool bPercent = ::get_flag(nFlags, EXC_AFFLAG_TOP10PERC);
622 sal_uInt16 nCntOfTop10 = nFlags >> 7;
624 if( bTop10 )
626 ScQueryEntry& aEntry = aParam.AppendEntry();
627 ScQueryEntry::Item& rItem = aEntry.GetQueryItem();
628 aEntry.bDoQuery = true;
629 aEntry.nField = static_cast<SCCOLROW>(StartCol() + static_cast<SCCOL>(nCol));
630 aEntry.eOp = bTopOfTop10 ?
631 (bPercent ? SC_TOPPERC : SC_TOPVAL) : (bPercent ? SC_BOTPERC : SC_BOTVAL);
632 aEntry.eConnect = SC_AND;
634 rItem.meType = ScQueryEntry::ByString;
635 rItem.maString = rPool.intern(OUString::number(nCntOfTop10));
637 rStrm.Ignore(20);
638 return;
641 sal_uInt8 nType, nOper, nBoolErr, nVal;
642 sal_Int32 nRK;
643 double fVal;
644 bool bIgnore;
646 sal_uInt8 nStrLen[2] = { 0, 0 };
647 ScQueryEntry aEntries[2];
649 for (size_t nE = 0; nE < 2; ++nE)
651 ScQueryEntry& rEntry = aEntries[nE];
652 ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
653 bIgnore = false;
655 nType = rStrm.ReaduInt8();
656 nOper = rStrm.ReaduInt8();
657 switch( nOper )
659 case EXC_AFOPER_LESS:
660 rEntry.eOp = SC_LESS;
661 break;
662 case EXC_AFOPER_EQUAL:
663 rEntry.eOp = SC_EQUAL;
664 break;
665 case EXC_AFOPER_LESSEQUAL:
666 rEntry.eOp = SC_LESS_EQUAL;
667 break;
668 case EXC_AFOPER_GREATER:
669 rEntry.eOp = SC_GREATER;
670 break;
671 case EXC_AFOPER_NOTEQUAL:
672 rEntry.eOp = SC_NOT_EQUAL;
673 break;
674 case EXC_AFOPER_GREATEREQUAL:
675 rEntry.eOp = SC_GREATER_EQUAL;
676 break;
677 default:
678 rEntry.eOp = SC_EQUAL;
681 switch( nType )
683 case EXC_AFTYPE_RK:
684 nRK = rStrm.ReadInt32();
685 rStrm.Ignore( 4 );
686 rItem.maString = rPool.intern(
687 CreateFromDouble(XclTools::GetDoubleFromRK(nRK)));
688 break;
689 case EXC_AFTYPE_DOUBLE:
690 fVal = rStrm.ReadDouble();
691 rItem.maString = rPool.intern(CreateFromDouble(fVal));
692 break;
693 case EXC_AFTYPE_STRING:
694 rStrm.Ignore( 4 );
695 nStrLen[ nE ] = rStrm.ReaduInt8();
696 rStrm.Ignore( 3 );
697 rItem.maString = svl::SharedString();
698 break;
699 case EXC_AFTYPE_BOOLERR:
700 nBoolErr = rStrm.ReaduInt8();
701 nVal = rStrm.ReaduInt8();
702 rStrm.Ignore( 6 );
703 rItem.maString = rPool.intern(OUString::number(nVal));
704 bIgnore = (nBoolErr != 0);
705 break;
706 case EXC_AFTYPE_EMPTY:
707 rEntry.SetQueryByEmpty();
708 break;
709 case EXC_AFTYPE_NOTEMPTY:
710 rEntry.SetQueryByNonEmpty();
711 break;
712 default:
713 rStrm.Ignore( 8 );
714 bIgnore = true;
717 if (!bIgnore)
719 rEntry.bDoQuery = true;
720 rItem.meType = ScQueryEntry::ByString;
721 rEntry.nField = static_cast<SCCOLROW>(StartCol() + static_cast<SCCOL>(nCol));
722 rEntry.eConnect = nE ? eConn : SC_AND;
726 if (eConn == SC_AND)
728 for (size_t nE = 0; nE < 2; ++nE)
730 if (nStrLen[nE] && aEntries[nE].bDoQuery)
732 OUString aStr = rStrm.ReadUniString(nStrLen[nE]);
733 ExcelQueryToOooQuery(aStr, aEntries[nE]);
734 aEntries[nE].GetQueryItem().maString = rPool.intern(aStr);
735 aParam.AppendEntry() = aEntries[nE];
739 else
741 OSL_ASSERT(eConn == SC_OR);
742 // Import only when both conditions are for simple equality, else
743 // import only the 1st condition due to conflict with the ordering of
744 // conditions. #i39464#.
746 // Example: Let A1 be a condition of column A, and B1 and B2
747 // conditions of column B, connected with OR. Excel performs 'A1 AND
748 // (B1 OR B2)' in this case, but Calc would do '(A1 AND B1) OR B2'
749 // instead.
751 if (bSimple1 && bSimple2 && nStrLen[0] && nStrLen[1])
753 // Two simple OR'ed equal conditions. We can import this correctly.
754 ScQueryEntry& rEntry = aParam.AppendEntry();
755 rEntry.bDoQuery = true;
756 rEntry.eOp = SC_EQUAL;
757 rEntry.eConnect = SC_AND;
758 ScQueryEntry::QueryItemsType aItems;
759 aItems.reserve(2);
760 ScQueryEntry::Item aItem1, aItem2;
761 aItem1.maString = rPool.intern(rStrm.ReadUniString(nStrLen[0]));
762 aItem1.meType = ScQueryEntry::ByString;
763 aItem2.maString = rPool.intern(rStrm.ReadUniString(nStrLen[1]));
764 aItem2.meType = ScQueryEntry::ByString;
765 aItems.push_back(aItem1);
766 aItems.push_back(aItem2);
767 rEntry.GetQueryItems().swap(aItems);
769 else if (nStrLen[0] && aEntries[0].bDoQuery)
771 // Due to conflict, we can import only the first condition.
772 OUString aStr = rStrm.ReadUniString(nStrLen[0]);
773 ExcelQueryToOooQuery(aStr, aEntries[0]);
774 aEntries[0].GetQueryItem().maString = rPool.intern(aStr);
775 aParam.AppendEntry() = aEntries[0];
780 void XclImpAutoFilterData::SetAdvancedRange( const ScRange* pRange )
782 if (pRange)
784 aCriteriaRange = *pRange;
785 bCriteria = true;
787 else
788 bCriteria = false;
791 void XclImpAutoFilterData::SetExtractPos( const ScAddress& rAddr )
793 aParam.nDestCol = rAddr.Col();
794 aParam.nDestRow = rAddr.Row();
795 aParam.nDestTab = rAddr.Tab();
796 aParam.bInplace = false;
797 aParam.bDestPers = true;
800 void XclImpAutoFilterData::Apply()
802 CreateScDBData();
804 if( bActive )
806 InsertQueryParam();
810 void XclImpAutoFilterData::CreateScDBData()
813 // Create the ScDBData() object if the AutoFilter is activated
814 // or if we need to create the Advanced Filter.
815 if( bActive || bCriteria)
817 ScDocument* pDoc = pExcRoot->pIR->GetDocPtr();
818 OUString aNewName(STR_DB_LOCAL_NONAME);
819 pCurrDBData = new ScDBData(aNewName , Tab(),
820 StartCol(),StartRow(), EndCol(),EndRow() );
821 if(bCriteria)
823 EnableRemoveFilter();
825 pCurrDBData->SetQueryParam( aParam );
826 pCurrDBData->SetAdvancedQuerySource(&aCriteriaRange);
828 else
829 pCurrDBData->SetAdvancedQuerySource(NULL);
830 pDoc->SetAnonymousDBData(Tab(), pCurrDBData);
835 void XclImpAutoFilterData::EnableRemoveFilter()
837 // only if this is a saved Advanced filter
838 if( !bActive && bAutoOrAdvanced )
840 ScQueryEntry& aEntry = aParam.AppendEntry();
841 aEntry.bDoQuery = true;
844 // TBD: force the automatic activation of the
845 // "Remove Filter" by setting a virtual mouse click
846 // inside the advanced range
849 void XclImpAutoFilterBuffer::Insert( RootData* pRoot, const ScRange& rRange)
851 if( !GetByTab( rRange.aStart.Tab() ) )
852 maFilters.push_back( new XclImpAutoFilterData( pRoot, rRange) );
855 void XclImpAutoFilterBuffer::AddAdvancedRange( const ScRange& rRange )
857 XclImpAutoFilterData* pData = GetByTab( rRange.aStart.Tab() );
858 if( pData )
859 pData->SetAdvancedRange( &rRange );
862 void XclImpAutoFilterBuffer::AddExtractPos( const ScRange& rRange )
864 XclImpAutoFilterData* pData = GetByTab( rRange.aStart.Tab() );
865 if( pData )
866 pData->SetExtractPos( rRange.aStart );
869 void XclImpAutoFilterBuffer::Apply()
871 std::for_each(maFilters.begin(),maFilters.end(),
872 boost::bind(&XclImpAutoFilterData::Apply,_1));
875 XclImpAutoFilterData* XclImpAutoFilterBuffer::GetByTab( SCTAB nTab )
877 boost::ptr_vector<XclImpAutoFilterData>::iterator it;
878 for( it = maFilters.begin(); it != maFilters.end(); ++it )
880 if( it->Tab() == nTab )
881 return const_cast<XclImpAutoFilterData*>(&(*it));
883 return NULL;
886 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */