Version 4.0.2.1, tag libreoffice-4.0.2.1
[LibreOffice.git] / sc / source / filter / excel / excimp8.cxx
blob3ac521235ff518e9939552ef2a186ad106d15a6b
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 "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>
67 #include "cell.hxx"
68 #include "document.hxx"
69 #include "patattr.hxx"
70 #include "docpool.hxx"
71 #include "attrib.hxx"
72 #include "conditio.hxx"
73 #include "dbdata.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"
83 #include "xipage.hxx"
84 #include "xicontent.hxx"
85 #include "xilink.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
118 private:
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;
123 public:
124 // XElementAccess
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 );
131 // XNameAcess
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 )
147 *pName = it->first;
148 return aResult;
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() );
156 // XElementAccess
157 virtual ::sal_Int32 SAL_CALL getCount( ) throw (uno::RuntimeException)
159 ::osl::MutexGuard aGuard( m_aMutex );
160 return IdToOleNameHash.size();
162 // XNameContainer
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
196 delete pFormConv;
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 )
240 sal_uInt8 nLen;
241 sal_uInt16 nGrbit;
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 );
252 if( nScTab > 0 )
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 );
267 nBdshtTab++;
271 void ImportExcel8::Scenman( void )
273 sal_uInt16 nLastDispl;
275 aIn.Ignore( 4 );
276 aIn >> nLastDispl;
278 maScenList.nLastScenario = nLastDispl;
282 void ImportExcel8::Scenario( void )
284 maScenList.aEntries.push_back( new ExcScenario( aIn, *pExcRoot ) );
288 void ImportExcel8::Labelsst( void )
290 XclAddress aXclPos;
291 sal_uInt16 nXF;
292 sal_uInt32 nSst;
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 );
333 #endif
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 );
345 if ( vbaStg.get() )
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
377 if( HasBasic() )
378 ReadBasic();
379 #endif
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 //___________________________________________________________________
425 // autofilter
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() );
436 if( pData )
437 pData->SetAutoOrAdvanced();
440 void ImportExcel8::AutoFilterInfo( void )
442 if( !pExcRoot->pAutoFilterBuffer ) return;
444 XclImpAutoFilterData* pData = pExcRoot->pAutoFilterBuffer->GetByTab( GetCurrScTab() );
445 if( pData )
447 pData->SetAdvancedRange( NULL );
448 pData->Activate();
452 void ImportExcel8::AutoFilter( void )
454 if( !pExcRoot->pAutoFilterBuffer ) return;
456 XclImpAutoFilterData* pData = pExcRoot->pAutoFilterBuffer->GetByTab( GetCurrScTab() );
457 if( pData )
458 pData->ReadAutoFilter( aIn );
463 XclImpAutoFilterData::XclImpAutoFilterData( RootData* pRoot, const ScRange& rRange ) :
464 ExcRoot( pRoot ),
465 pCurrDBData(NULL),
466 bActive( false ),
467 bCriteria( false ),
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()
499 if (pCurrDBData)
501 ScRange aAdvRange;
502 sal_Bool bHasAdv = pCurrDBData->GetAdvancedQuerySource( aAdvRange );
503 if( bHasAdv )
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 );
509 if( bHasAdv )
510 pCurrDBData->SetAdvancedQuerySource( &aAdvRange );
511 else
513 pCurrDBData->SetAutoFilter( sal_True );
514 SetCellAttribs();
519 static void ExcelQueryToOooQuery( ScQueryEntry& rEntry )
521 if (rEntry.eOp != SC_EQUAL && rEntry.eOp != SC_NOT_EQUAL)
522 return;
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 );
531 aStr.Erase( 0, 1 );
532 rEntry.eOp = ( rEntry.eOp == SC_EQUAL ) ? SC_CONTAINS : SC_DOES_NOT_CONTAIN;
534 else if( nLen > 1 && nStart == '*' && nEnd != '*' )
536 aStr.Erase( 0, 1 );
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 == '*' )
546 aStr.Erase( 0, 1 );
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;
564 if( bTop10 )
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));
577 rStrm.Ignore(20);
578 return;
581 sal_uInt8 nType, nOper, nBoolErr, nVal;
582 sal_Int32 nRK;
583 double fVal;
584 bool bIgnore;
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();
593 bIgnore = false;
595 rStrm >> nType >> nOper;
596 switch( nOper )
598 case EXC_AFOPER_LESS:
599 rEntry.eOp = SC_LESS;
600 break;
601 case EXC_AFOPER_EQUAL:
602 rEntry.eOp = SC_EQUAL;
603 break;
604 case EXC_AFOPER_LESSEQUAL:
605 rEntry.eOp = SC_LESS_EQUAL;
606 break;
607 case EXC_AFOPER_GREATER:
608 rEntry.eOp = SC_GREATER;
609 break;
610 case EXC_AFOPER_NOTEQUAL:
611 rEntry.eOp = SC_NOT_EQUAL;
612 break;
613 case EXC_AFOPER_GREATEREQUAL:
614 rEntry.eOp = SC_GREATER_EQUAL;
615 break;
616 default:
617 rEntry.eOp = SC_EQUAL;
620 rtl::OUString aStr;
622 switch( nType )
624 case EXC_AFTYPE_RK:
625 rStrm >> nRK;
626 rStrm.Ignore( 4 );
627 CreateFromDouble(
628 rItem.maString, XclTools::GetDoubleFromRK(nRK));
629 break;
630 case EXC_AFTYPE_DOUBLE:
631 rStrm >> fVal;
632 CreateFromDouble(rItem.maString, fVal);
633 break;
634 case EXC_AFTYPE_STRING:
635 rStrm.Ignore( 4 );
636 rStrm >> nStrLen[ nE ];
637 rStrm.Ignore( 3 );
638 rItem.maString = rtl::OUString();
639 break;
640 case EXC_AFTYPE_BOOLERR:
641 rStrm >> nBoolErr >> nVal;
642 rStrm.Ignore( 6 );
643 rItem.maString = rtl::OUString::valueOf(static_cast<sal_Int32>(nVal));
644 bIgnore = (nBoolErr != 0);
645 break;
646 case EXC_AFTYPE_EMPTY:
647 rEntry.SetQueryByEmpty();
648 break;
649 case EXC_AFTYPE_NOTEMPTY:
650 rEntry.SetQueryByNonEmpty();
651 break;
652 default:
653 rStrm.Ignore( 8 );
654 bIgnore = true;
657 if (!bIgnore)
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;
666 if (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];
678 else
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'
688 // instead.
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;
698 aItems.reserve(2);
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 )
720 if (pRange)
722 aCriteriaRange = *pRange;
723 bCriteria = true;
725 else
726 bCriteria = false;
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()
740 CreateScDBData();
742 if( bActive )
744 InsertQueryParam();
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,
752 // pFlags.get());
753 // for (size_t j=0; j<nRows; ++j)
754 // {
755 // if ((pFlags[j] & CR_HIDDEN) && !(pFlags[j] & CR_FILTERED))
756 // pExcRoot->pDoc->SetRowFlags( nRow1 + j, Tab(),
757 // pFlags[j] | CR_FILTERED );
758 // }
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() );
773 if(bCriteria)
775 EnableRemoveFilter();
777 pCurrDBData->SetQueryParam( aParam );
778 pCurrDBData->SetAdvancedQuerySource(&aCriteriaRange);
780 else
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() );
810 if( pData )
811 pData->SetAdvancedRange( &rRange );
814 void XclImpAutoFilterBuffer::AddExtractPos( const ScRange& rRange )
816 XclImpAutoFilterData* pData = GetByTab( rRange.aStart.Tab() );
817 if( pData )
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));
835 return NULL;
838 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */