LCOV - code coverage report
Current view: top level - sc/source/filter/excel - excimp8.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 285 437 65.2 %
Date: 2015-06-13 12:38:46 Functions: 37 50 74.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       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/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      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 .
      18             :  */
      19             : 
      20             : #include <config_features.h>
      21             : 
      22             : #include "excimp8.hxx"
      23             : 
      24             : #include <boost/bind.hpp>
      25             : 
      26             : #include <scitems.hxx>
      27             : #include <comphelper/processfactory.hxx>
      28             : #include <unotools/fltrcfg.hxx>
      29             : 
      30             : #include <vcl/wmf.hxx>
      31             : 
      32             : #include <editeng/eeitem.hxx>
      33             : 
      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>
      40             : 
      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>
      53             : 
      54             : #include <vcl/graph.hxx>
      55             : #include <vcl/bmpacc.hxx>
      56             : #include <sot/exchange.hxx>
      57             : 
      58             : #include <svl/stritem.hxx>
      59             : #include <svl/sharedstringpool.hxx>
      60             : 
      61             : #include <rtl/math.hxx>
      62             : #include <rtl/ustring.hxx>
      63             : #include <unotools/localedatawrapper.hxx>
      64             : #include <unotools/charclass.hxx>
      65             : #include <drwlayer.hxx>
      66             : 
      67             : #include <boost/scoped_array.hpp>
      68             : 
      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"
      90             : 
      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"
      98             : 
      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>
     108             : 
     109             : using namespace com::sun::star;
     110             : using namespace ::comphelper;
     111             : 
     112             : //OleNameOverrideContainer
     113             : 
     114             : typedef ::cppu::WeakImplHelper1< container::XNameContainer > OleNameOverrideContainer_BASE;
     115             : 
     116          90 : class OleNameOverrideContainer : public OleNameOverrideContainer_BASE
     117             : {
     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           0 :     virtual uno::Type SAL_CALL getElementType(  ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE { return  cppu::UnoType<container::XIndexContainer>::get(); }
     126           0 :     virtual sal_Bool SAL_CALL hasElements(  ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
     127             :     {
     128           0 :         ::osl::MutexGuard aGuard( m_aMutex );
     129           0 :         return ( !IdToOleNameHash.empty() );
     130             :     }
     131             :     // XNameAcess
     132           0 :     virtual uno::Any SAL_CALL getByName( const OUString& aName ) throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException, std::exception) SAL_OVERRIDE
     133             :     {
     134           0 :         ::osl::MutexGuard aGuard( m_aMutex );
     135           0 :         if ( !hasByName(aName) )
     136           0 :             throw container::NoSuchElementException();
     137           0 :         return uno::makeAny( IdToOleNameHash[ aName ] );
     138             :     }
     139           0 :     virtual uno::Sequence< OUString > SAL_CALL getElementNames(  ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
     140             :     {
     141           0 :         ::osl::MutexGuard aGuard( m_aMutex );
     142           0 :         uno::Sequence< OUString > aResult( IdToOleNameHash.size() );
     143           0 :         NamedIndexToOleName::iterator it = IdToOleNameHash.begin();
     144           0 :         NamedIndexToOleName::iterator it_end = IdToOleNameHash.end();
     145           0 :         OUString* pName = aResult.getArray();
     146           0 :         for (; it != it_end; ++it, ++pName )
     147           0 :             *pName = it->first;
     148           0 :         return aResult;
     149             :     }
     150          87 :     virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
     151             :     {
     152          87 :         ::osl::MutexGuard aGuard( m_aMutex );
     153          87 :         return ( IdToOleNameHash.find( aName ) != IdToOleNameHash.end() );
     154             :     }
     155             : 
     156             :     // XNameContainer
     157           0 :     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
     158             :     {
     159           0 :         ::osl::MutexGuard aGuard( m_aMutex );
     160           0 :         if ( hasByName( aName ) )
     161           0 :             throw container::ElementExistException();
     162           0 :         uno::Reference< container::XIndexContainer > xElement;
     163           0 :         if ( ! ( aElement >>= xElement ) )
     164           0 :             throw lang::IllegalArgumentException();
     165           0 :        IdToOleNameHash[ aName ] = xElement;
     166           0 :     }
     167           0 :     virtual void SAL_CALL removeByName( const OUString& aName ) throw(container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException, std::exception) SAL_OVERRIDE
     168             :     {
     169           0 :         ::osl::MutexGuard aGuard( m_aMutex );
     170           0 :         if ( !hasByName( aName ) )
     171           0 :             throw container::NoSuchElementException();
     172           0 :         IdToOleNameHash.erase( IdToOleNameHash.find( aName ) );
     173           0 :     }
     174           0 :     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
     175             :     {
     176           0 :         ::osl::MutexGuard aGuard( m_aMutex );
     177           0 :         if ( !hasByName( aName ) )
     178           0 :             throw container::NoSuchElementException();
     179           0 :         uno::Reference< container::XIndexContainer > xElement;
     180           0 :         if ( ! ( aElement >>= xElement ) )
     181           0 :             throw lang::IllegalArgumentException();
     182           0 :         IdToOleNameHash[ aName ] = xElement;
     183           0 :     }
     184             : };
     185             : 
     186             : namespace {
     187             : 
     188             : /** Future Record Type header.
     189             :     @return whether read rt matches nRecordID
     190             :  */
     191         123 : bool readFrtHeader( XclImpStream& rStrm, sal_uInt16 nRecordID )
     192             : {
     193         123 :     sal_uInt16 nRt = rStrm.ReaduInt16();
     194         123 :     rStrm.Ignore(10);   // grbitFrt (2 bytes) and reserved (8 bytes)
     195         123 :     return nRt == nRecordID;
     196             : }
     197             : 
     198             : }
     199             : 
     200          81 : ImportExcel8::ImportExcel8( XclImpRootData& rImpData, SvStream& rStrm ) :
     201          81 :     ImportExcel( rImpData, rStrm )
     202             : {
     203             :     // replace BIFF2-BIFF5 formula importer with BIFF8 formula importer
     204          81 :     delete pFormConv;
     205          81 :     pFormConv = pExcRoot->pFmlaConverter = new ExcelToSc8( GetRoot() );
     206          81 : }
     207             : 
     208         162 : ImportExcel8::~ImportExcel8()
     209             : {
     210         162 : }
     211             : 
     212         168 : void ImportExcel8::Calccount()
     213             : {
     214         168 :     ScDocOptions    aOpt = pD->GetDocOptions();
     215         168 :     aOpt.SetIterCount( aIn.ReaduInt16() );
     216         168 :     pD->SetDocOptions( aOpt );
     217         168 : }
     218             : 
     219          77 : void ImportExcel8::Precision()
     220             : {
     221          77 :     ScDocOptions aOpt = pD->GetDocOptions();
     222          77 :     aOpt.SetCalcAsShown( aIn.ReaduInt16() == 0 );
     223          77 :     pD->SetDocOptions( aOpt );
     224          77 : }
     225             : 
     226         216 : void ImportExcel8::Delta()
     227             : {
     228         216 :     ScDocOptions    aOpt = pD->GetDocOptions();
     229         216 :     aOpt.SetIterEps( aIn.ReadDouble() );
     230         216 :     pD->SetDocOptions( aOpt );
     231         216 : }
     232             : 
     233         216 : void ImportExcel8::Iteration()
     234             : {
     235         216 :     ScDocOptions    aOpt = pD->GetDocOptions();
     236         216 :     aOpt.SetIter( aIn.ReaduInt16() == 1 );
     237         216 :     pD->SetDocOptions( aOpt );
     238         216 : }
     239             : 
     240         219 : void ImportExcel8::Boundsheet()
     241             : {
     242             :     sal_uInt8           nLen;
     243             :     sal_uInt16          nGrbit;
     244             : 
     245         219 :     aIn.DisableDecryption();
     246         219 :     maSheetOffsets.push_back( aIn.ReaduInt32() );
     247         219 :     aIn.EnableDecryption();
     248         219 :     nGrbit = aIn.ReaduInt16();
     249         219 :     nLen = aIn.ReaduInt8();
     250             : 
     251         219 :     OUString aName( aIn.ReadUniString( nLen ) );
     252         219 :     GetTabInfo().AppendXclTabName( aName, nBdshtTab );
     253             : 
     254         219 :     SCTAB nScTab = static_cast< SCTAB >( nBdshtTab );
     255         219 :     if( nScTab > 0 )
     256             :     {
     257             :         OSL_ENSURE( !pD->HasTable( nScTab ), "ImportExcel8::Boundsheet - sheet exists already" );
     258         140 :         pD->MakeTable( nScTab );
     259             :     }
     260             : 
     261         219 :     if( ( nGrbit & 0x0001 ) || ( nGrbit & 0x0002 ) )
     262           9 :         pD->SetVisible( nScTab, false );
     263             : 
     264         219 :     if( !pD->RenameTab( nScTab, aName ) )
     265             :     {
     266           0 :         pD->CreateValidTabName( aName );
     267           0 :         pD->RenameTab( nScTab, aName );
     268             :     }
     269             : 
     270         219 :     nBdshtTab++;
     271         219 : }
     272             : 
     273           0 : void ImportExcel8::Scenman()
     274             : {
     275             :     sal_uInt16              nLastDispl;
     276             : 
     277           0 :     aIn.Ignore( 4 );
     278           0 :     nLastDispl = aIn.ReaduInt16();
     279             : 
     280           0 :     maScenList.nLastScenario = nLastDispl;
     281           0 : }
     282             : 
     283           0 : void ImportExcel8::Scenario()
     284             : {
     285           0 :     maScenList.aEntries.push_back( new ExcScenario( aIn, *pExcRoot ) );
     286           0 : }
     287             : 
     288       76546 : void ImportExcel8::Labelsst()
     289             : {
     290       76546 :     XclAddress aXclPos;
     291             :     sal_uInt16 nXF;
     292             :     sal_uInt32  nSst;
     293             : 
     294       76546 :     aIn >> aXclPos;
     295       76546 :     nXF = aIn.ReaduInt16();
     296       76546 :     nSst = aIn.ReaduInt32(  );
     297             : 
     298       76546 :     ScAddress aScPos( ScAddress::UNINITIALIZED );
     299       76546 :     if( GetAddressConverter().ConvertAddress( aScPos, aXclPos, GetCurrScTab(), true ) )
     300             :     {
     301       76546 :         GetXFRangeBuffer().SetXF( aScPos, nXF );
     302       76546 :         const XclImpString* pXclStr = GetSst().GetString(nSst);
     303       76546 :         if (pXclStr)
     304       76546 :             XclImpStringHelper::SetToDocument(GetDocImport(), aScPos, *this, *pXclStr, nXF);
     305             :     }
     306       76546 : }
     307             : 
     308         116 : void ImportExcel8::FeatHdr()
     309             : {
     310         116 :     if (!readFrtHeader( aIn, 0x0867))
     311           0 :         return;
     312             : 
     313             :     // Feature type (isf) can be EXC_ISFPROTECTION, EXC_ISFFEC2 or
     314             :     // EXC_ISFFACTOID.
     315         116 :     sal_uInt16 nFeatureType = aIn.ReaduInt16();
     316         116 :     if (nFeatureType != EXC_ISFPROTECTION)
     317             :         // We currently only support import of enhanced protection data.
     318           2 :         return;
     319             : 
     320         114 :     aIn.Ignore(1); // always 1
     321             : 
     322         114 :     GetSheetProtectBuffer().ReadOptions( aIn, GetCurrScTab() );
     323             : }
     324             : 
     325           7 : void ImportExcel8::Feat()
     326             : {
     327           7 :     if (!readFrtHeader( aIn, 0x0868))
     328           2 :         return;
     329             : 
     330             :     // Feature type (isf) can be EXC_ISFPROTECTION, EXC_ISFFEC2 or
     331             :     // EXC_ISFFACTOID.
     332           7 :     sal_uInt16 nFeatureType = aIn.ReaduInt16();
     333           7 :     if (nFeatureType != EXC_ISFPROTECTION)
     334             :         // We currently only support import of enhanced protection data.
     335           2 :         return;
     336             : 
     337           5 :     aIn.Ignore(5);                          // reserved1 (1 byte) and reserved2 (4 bytes)
     338             : 
     339           5 :     sal_uInt16 nCref = aIn.ReaduInt16();    // number of ref elements
     340           5 :     aIn.Ignore(4);                          // size if EXC_ISFFEC2, else 0 and to be ignored
     341           5 :     aIn.Ignore(2);                          // reserved3 (2 bytes)
     342             : 
     343           5 :     ScEnhancedProtection aProt;
     344           5 :     if (nCref)
     345             :     {
     346           5 :         XclRangeList aRefs;
     347           5 :         aRefs.Read( aIn, true, nCref);
     348           5 :         if (!aRefs.empty())
     349             :         {
     350           5 :             aProt.maRangeList = new ScRangeList;
     351           5 :             GetAddressConverter().ConvertRangeList( *aProt.maRangeList, aRefs, GetCurrScTab(), false);
     352           5 :         }
     353             :     }
     354             : 
     355             :     // FeatProtection structure follows in record.
     356             : 
     357           5 :     aProt.mnAreserved = aIn.ReaduInt32();
     358           5 :     aProt.mnPasswordVerifier = aIn.ReaduInt32();
     359           5 :     aProt.maTitle = aIn.ReadUniString();
     360           5 :     if ((aProt.mnAreserved & 0x00000001) == 0x00000001)
     361             :     {
     362           2 :         sal_uInt32 nCbSD = aIn.ReaduInt32();
     363             :         // TODO: could here be some sanity check applied to not allocate 4GB?
     364           2 :         aProt.maSecurityDescriptor.resize( nCbSD);
     365           2 :         sal_Size nRead = aIn.Read( &aProt.maSecurityDescriptor.front(), nCbSD);
     366           2 :         if (nRead < nCbSD)
     367           0 :             aProt.maSecurityDescriptor.resize( nRead);
     368             :     }
     369             : 
     370           5 :     GetSheetProtectBuffer().AppendEnhancedProtection( aProt, GetCurrScTab() );
     371             : }
     372             : 
     373          30 : void ImportExcel8::ReadBasic()
     374             : {
     375          30 :     SfxObjectShell* pShell = GetDocShell();
     376          30 :     tools::SvRef<SotStorage> xRootStrg = GetRootStorage();
     377          30 :     const SvtFilterOptions& rFilterOpt = SvtFilterOptions::Get();
     378          30 :     if( pShell && xRootStrg.Is() ) try
     379             :     {
     380             :         // #FIXME need to get rid of this, we can also do this from within oox
     381             :         // via the "ooo.vba.VBAGlobals" service
     382          60 :         if( ( rFilterOpt.IsLoadExcelBasicCode() ||
     383          60 :               rFilterOpt.IsLoadExcelBasicStorage() ) &&
     384          30 :             rFilterOpt.IsLoadExcelBasicExecutable() )
     385             :         {
     386             :             // see if we have the XCB stream
     387          30 :             tools::SvRef<SotStorageStream> xXCB = xRootStrg->OpenSotStream( OUString("XCB"), STREAM_STD_READ | StreamMode::NOCREATE  );
     388          30 :             if ( xXCB.Is()|| SVSTREAM_OK == xXCB->GetError() )
     389             :             {
     390          30 :                 ScCTBWrapper wrapper;
     391          30 :                 if ( wrapper.Read( *xXCB ) )
     392             :                 {
     393             : #if OSL_DEBUG_LEVEL > 1
     394             :                     wrapper.Print( stderr );
     395             : #endif
     396          30 :                     wrapper.ImportCustomToolBar( *pShell );
     397          30 :                 }
     398          30 :             }
     399             :         }
     400             :         try
     401             :         {
     402          30 :             uno::Reference< uno::XComponentContext > aCtx( ::comphelper::getProcessComponentContext() );
     403          30 :             SfxMedium& rMedium = GetMedium();
     404          60 :             uno::Reference< io::XInputStream > xIn = rMedium.GetInputStream();
     405          60 :             oox::ole::OleStorage root( aCtx, xIn, false );
     406          60 :             oox::StorageRef vbaStg = root.openSubStorage( "_VBA_PROJECT_CUR", false );
     407          30 :             if ( vbaStg.get() )
     408             :             {
     409          30 :                 oox::ole::VbaProject aVbaPrj( aCtx, pShell->GetModel(), "Calc" );
     410             :                 // collect names of embedded form controls, as specified in the VBA project
     411          60 :                 uno::Reference< container::XNameContainer > xOleNameOverrideSink( new OleNameOverrideContainer );
     412          30 :                 aVbaPrj.setOleOverridesSink( xOleNameOverrideSink );
     413          30 :                 aVbaPrj.importVbaProject( *vbaStg );
     414          60 :                 GetObjectManager().SetOleNameOverrideInfo( xOleNameOverrideSink );
     415          30 :             }
     416             :         }
     417           0 :         catch( uno::Exception& )
     418             :         {
     419             :         }
     420             :     }
     421           0 :     catch( uno::Exception& )
     422             :     {
     423          30 :     }
     424          30 : }
     425             : 
     426         218 : void ImportExcel8::EndSheet()
     427             : {
     428         218 :     ImportExcel::EndSheet();
     429         218 :     GetCondFormatManager().Apply();
     430         218 :     GetValidationManager().Apply();
     431         218 : }
     432             : 
     433          81 : void ImportExcel8::PostDocLoad()
     434             : {
     435             : #if HAVE_FEATURE_SCRIPTING
     436             :     // reading basic has been delayed until sheet objects (codenames etc.) are read
     437          81 :     if( HasBasic() )
     438          30 :         ReadBasic();
     439             : #endif
     440             :     // #i11776# filtered ranges before outlines and hidden rows
     441          81 :     if( pExcRoot->pAutoFilterBuffer )
     442          81 :         pExcRoot->pAutoFilterBuffer->Apply();
     443             : 
     444          81 :     GetWebQueryBuffer().Apply();    //TODO: test if extant
     445          81 :     GetSheetProtectBuffer().Apply();
     446          81 :     GetDocProtectBuffer().Apply();
     447             : 
     448          81 :     ImportExcel::PostDocLoad();
     449             : 
     450             :     // check scenarios; Attention: This increases the table count of the document!!
     451          81 :     if( !pD->IsClipboard() && maScenList.aEntries.size() )
     452             :     {
     453           0 :         pD->UpdateChartListenerCollection();    // references in charts must be updated
     454             : 
     455           0 :         maScenList.Apply( GetRoot() );
     456             :     }
     457             : 
     458             :     // read doc info (no docshell while pasting from clipboard)
     459          81 :     LoadDocumentProperties();
     460             : 
     461             :     // #i45843# Pivot tables are now handled outside of PostDocLoad, so they are available
     462             :     // when formula cells are calculated, for the GETPIVOTDATA function.
     463          81 : }
     464             : 
     465          81 : void ImportExcel8::LoadDocumentProperties()
     466             : {
     467             :     // no docshell while pasting from clipboard
     468          81 :     if( SfxObjectShell* pShell = GetDocShell() )
     469             :     {
     470             :         // BIFF5+ without storage is possible
     471          81 :         tools::SvRef<SotStorage> xRootStrg = GetRootStorage();
     472          81 :         if( xRootStrg.Is() ) try
     473             :         {
     474          81 :             uno::Reference< document::XDocumentPropertiesSupplier > xDPS( pShell->GetModel(), uno::UNO_QUERY_THROW );
     475         162 :             uno::Reference< document::XDocumentProperties > xDocProps( xDPS->getDocumentProperties(), uno::UNO_SET_THROW );
     476         162 :             sfx2::LoadOlePropertySet( xDocProps, xRootStrg );
     477             :         }
     478           0 :         catch( uno::Exception& )
     479             :         {
     480          81 :         }
     481             :     }
     482          81 : }
     483             : 
     484             : // autofilter
     485             : 
     486           5 : void ImportExcel8::FilterMode()
     487             : {
     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          10 :     if( !pExcRoot->pAutoFilterBuffer ) return;
     493             : 
     494           5 :     XclImpAutoFilterData* pData = pExcRoot->pAutoFilterBuffer->GetByTab( GetCurrScTab() );
     495           5 :     if( pData )
     496           5 :         pData->SetAutoOrAdvanced();
     497             : }
     498             : 
     499           8 : void ImportExcel8::AutoFilterInfo()
     500             : {
     501          16 :     if( !pExcRoot->pAutoFilterBuffer ) return;
     502             : 
     503           8 :     XclImpAutoFilterData* pData = pExcRoot->pAutoFilterBuffer->GetByTab( GetCurrScTab() );
     504           8 :     if( pData )
     505             :     {
     506           8 :         pData->SetAdvancedRange( NULL );
     507           8 :         pData->Activate();
     508             :     }
     509             : }
     510             : 
     511           5 : void ImportExcel8::AutoFilter()
     512             : {
     513          10 :     if( !pExcRoot->pAutoFilterBuffer ) return;
     514             : 
     515           5 :     XclImpAutoFilterData* pData = pExcRoot->pAutoFilterBuffer->GetByTab( GetCurrScTab() );
     516           5 :     if( pData )
     517           5 :         pData->ReadAutoFilter(aIn, GetDoc().GetSharedStringPool());
     518             : }
     519             : 
     520          26 : XclImpAutoFilterData::XclImpAutoFilterData( RootData* pRoot, const ScRange& rRange ) :
     521             :         ExcRoot( pRoot ),
     522             :         pCurrDBData(NULL),
     523             :         bActive( false ),
     524             :         bCriteria( false ),
     525          26 :         bAutoOrAdvanced(false)
     526             : {
     527          26 :     aParam.nCol1 = rRange.aStart.Col();
     528          26 :     aParam.nRow1 = rRange.aStart.Row();
     529          26 :     aParam.nTab = rRange.aStart.Tab();
     530          26 :     aParam.nCol2 = rRange.aEnd.Col();
     531          26 :     aParam.nRow2 = rRange.aEnd.Row();
     532             : 
     533          26 :     aParam.bInplace = true;
     534             : 
     535          26 : }
     536             : 
     537             : namespace {
     538             : 
     539           1 : OUString CreateFromDouble( double fVal )
     540             : {
     541             :     return rtl::math::doubleToUString(fVal,
     542             :                 rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max,
     543           1 :                 ScGlobal::pLocaleData->getNumDecimalSep()[0], true);
     544             : }
     545             : 
     546             : }
     547             : 
     548           8 : void XclImpAutoFilterData::SetCellAttribs()
     549             : {
     550           8 :     ScDocument& rDoc = pExcRoot->pIR->GetDoc();
     551          32 :     for ( SCCOL nCol = StartCol(); nCol <= EndCol(); nCol++ )
     552             :     {
     553          24 :         sal_Int16 nFlag = static_cast<const ScMergeFlagAttr*>( rDoc.GetAttr( nCol, StartRow(), Tab(), ATTR_MERGE_FLAG ))->GetValue();
     554          24 :         rDoc.ApplyAttr( nCol, StartRow(), Tab(), ScMergeFlagAttr( nFlag | SC_MF_AUTO) );
     555             :     }
     556           8 : }
     557             : 
     558           8 : void XclImpAutoFilterData::InsertQueryParam()
     559             : {
     560           8 :     if (pCurrDBData)
     561             :     {
     562           8 :         ScRange aAdvRange;
     563           8 :         bool    bHasAdv = pCurrDBData->GetAdvancedQuerySource( aAdvRange );
     564           8 :         if( bHasAdv )
     565           0 :             pExcRoot->pIR->GetDoc().CreateQueryParam( aAdvRange.aStart.Col(),
     566           0 :                 aAdvRange.aStart.Row(), aAdvRange.aEnd.Col(), aAdvRange.aEnd.Row(),
     567           0 :                 aAdvRange.aStart.Tab(), aParam );
     568             : 
     569           8 :         pCurrDBData->SetQueryParam( aParam );
     570           8 :         if( bHasAdv )
     571           0 :             pCurrDBData->SetAdvancedQuerySource( &aAdvRange );
     572             :         else
     573             :         {
     574           8 :             pCurrDBData->SetAutoFilter( true );
     575           8 :             SetCellAttribs();
     576             :         }
     577             :     }
     578           8 : }
     579             : 
     580           4 : static void ExcelQueryToOooQuery( OUString& aStr, ScQueryEntry& rEntry )
     581             : {
     582           4 :     if (rEntry.eOp != SC_EQUAL && rEntry.eOp != SC_NOT_EQUAL)
     583           4 :         return;
     584             : 
     585           4 :     sal_Int32   nLen = aStr.getLength();
     586           4 :     sal_Unicode nStart = aStr[0];
     587           4 :     sal_Unicode nEnd   = aStr[ nLen-1 ];
     588           4 :     if( nLen > 2 && nStart == '*' && nEnd == '*' )
     589             :     {
     590           0 :         aStr = aStr.copy( 1, nLen-2 );
     591           0 :         rEntry.eOp = ( rEntry.eOp == SC_EQUAL ) ? SC_CONTAINS : SC_DOES_NOT_CONTAIN;
     592             :     }
     593           4 :     else if( nLen > 1 && nStart == '*' && nEnd != '*' )
     594             :     {
     595           0 :         aStr = aStr.copy( 1 );
     596           0 :         rEntry.eOp = ( rEntry.eOp == SC_EQUAL ) ? SC_ENDS_WITH : SC_DOES_NOT_END_WITH;
     597             :     }
     598           4 :     else if( nLen > 1 && nStart != '*' && nEnd == '*' )
     599             :     {
     600           0 :         aStr = aStr.copy( 0, nLen-1 );
     601           0 :         rEntry.eOp = ( rEntry.eOp == SC_EQUAL ) ? SC_BEGINS_WITH : SC_DOES_NOT_BEGIN_WITH;
     602             :     }
     603           4 :     else if( nLen == 2 && nStart == '*' && nEnd == '*' )
     604             :     {
     605           0 :         aStr = aStr.copy( 1 );
     606             :     }
     607             : }
     608             : 
     609           5 : void XclImpAutoFilterData::ReadAutoFilter(
     610             :     XclImpStream& rStrm, svl::SharedStringPool& rPool )
     611             : {
     612             :     sal_uInt16 nCol, nFlags;
     613           5 :     nCol = rStrm.ReaduInt16();
     614           5 :     nFlags = rStrm.ReaduInt16();
     615             : 
     616           5 :     ScQueryConnect eConn = ::get_flagvalue( nFlags, EXC_AFFLAG_ANDORMASK, SC_OR, SC_AND );
     617           5 :     bool bSimple1    = ::get_flag(nFlags, EXC_AFFLAG_SIMPLE1);
     618           5 :     bool bSimple2    = ::get_flag(nFlags, EXC_AFFLAG_SIMPLE2);
     619           5 :     bool bTop10      = ::get_flag(nFlags, EXC_AFFLAG_TOP10);
     620           5 :     bool bTopOfTop10 = ::get_flag(nFlags, EXC_AFFLAG_TOP10TOP);
     621           5 :     bool bPercent    = ::get_flag(nFlags, EXC_AFFLAG_TOP10PERC);
     622           5 :     sal_uInt16 nCntOfTop10 = nFlags >> 7;
     623             : 
     624           5 :     if( bTop10 )
     625             :     {
     626           0 :         ScQueryEntry& aEntry = aParam.AppendEntry();
     627           0 :         ScQueryEntry::Item& rItem = aEntry.GetQueryItem();
     628           0 :         aEntry.bDoQuery = true;
     629           0 :         aEntry.nField = static_cast<SCCOLROW>(StartCol() + static_cast<SCCOL>(nCol));
     630             :         aEntry.eOp = bTopOfTop10 ?
     631           0 :             (bPercent ? SC_TOPPERC : SC_TOPVAL) : (bPercent ? SC_BOTPERC : SC_BOTVAL);
     632           0 :         aEntry.eConnect = SC_AND;
     633             : 
     634           0 :         rItem.meType = ScQueryEntry::ByString;
     635           0 :         rItem.maString = rPool.intern(OUString::number(nCntOfTop10));
     636             : 
     637           0 :         rStrm.Ignore(20);
     638           0 :         return;
     639             :     }
     640             : 
     641             :     sal_uInt8   nType, nOper, nBoolErr, nVal;
     642             :     sal_Int32   nRK;
     643             :     double  fVal;
     644             :     bool bIgnore;
     645             : 
     646           5 :     sal_uInt8 nStrLen[2] = { 0, 0 };
     647          15 :     ScQueryEntry aEntries[2];
     648             : 
     649          15 :     for (size_t nE = 0; nE < 2; ++nE)
     650             :     {
     651          10 :         ScQueryEntry& rEntry = aEntries[nE];
     652          10 :         ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
     653          10 :         bIgnore = false;
     654             : 
     655          10 :         nType = rStrm.ReaduInt8();
     656          10 :         nOper = rStrm.ReaduInt8();
     657          10 :         switch( nOper )
     658             :         {
     659             :             case EXC_AFOPER_LESS:
     660           0 :                 rEntry.eOp = SC_LESS;
     661           0 :             break;
     662             :             case EXC_AFOPER_EQUAL:
     663           6 :                 rEntry.eOp = SC_EQUAL;
     664           6 :             break;
     665             :             case EXC_AFOPER_LESSEQUAL:
     666           0 :                 rEntry.eOp = SC_LESS_EQUAL;
     667           0 :             break;
     668             :             case EXC_AFOPER_GREATER:
     669           0 :                 rEntry.eOp = SC_GREATER;
     670           0 :             break;
     671             :             case EXC_AFOPER_NOTEQUAL:
     672           0 :                 rEntry.eOp = SC_NOT_EQUAL;
     673           0 :             break;
     674             :             case EXC_AFOPER_GREATEREQUAL:
     675           0 :                 rEntry.eOp = SC_GREATER_EQUAL;
     676           0 :             break;
     677             :             default:
     678           4 :                 rEntry.eOp = SC_EQUAL;
     679             :         }
     680             : 
     681          10 :         switch( nType )
     682             :         {
     683             :             case EXC_AFTYPE_RK:
     684           0 :                 nRK = rStrm.ReadInt32();
     685           0 :                 rStrm.Ignore( 4 );
     686           0 :                 rItem.maString = rPool.intern(
     687           0 :                     CreateFromDouble(XclTools::GetDoubleFromRK(nRK)));
     688           0 :             break;
     689             :             case EXC_AFTYPE_DOUBLE:
     690           1 :                 fVal = rStrm.ReadDouble();
     691           1 :                 rItem.maString = rPool.intern(CreateFromDouble(fVal));
     692           1 :             break;
     693             :             case EXC_AFTYPE_STRING:
     694           4 :                 rStrm.Ignore( 4 );
     695           4 :                 nStrLen[ nE ] = rStrm.ReaduInt8();
     696           4 :                 rStrm.Ignore( 3 );
     697           4 :                 rItem.maString = svl::SharedString();
     698           4 :             break;
     699             :             case EXC_AFTYPE_BOOLERR:
     700           0 :                 nBoolErr = rStrm.ReaduInt8();
     701           0 :                 nVal = rStrm.ReaduInt8();
     702           0 :                 rStrm.Ignore( 6 );
     703           0 :                 rItem.maString = rPool.intern(OUString::number(nVal));
     704           0 :                 bIgnore = (nBoolErr != 0);
     705           0 :             break;
     706             :             case EXC_AFTYPE_EMPTY:
     707           0 :                 rEntry.SetQueryByEmpty();
     708           0 :             break;
     709             :             case EXC_AFTYPE_NOTEMPTY:
     710           0 :                 rEntry.SetQueryByNonEmpty();
     711           0 :             break;
     712             :             default:
     713           5 :                 rStrm.Ignore( 8 );
     714           5 :                 bIgnore = true;
     715             :         }
     716             : 
     717          10 :         if (!bIgnore)
     718             :         {
     719           5 :             rEntry.bDoQuery = true;
     720           5 :             rItem.meType = ScQueryEntry::ByString;
     721           5 :             rEntry.nField = static_cast<SCCOLROW>(StartCol() + static_cast<SCCOL>(nCol));
     722           5 :             rEntry.eConnect = nE ? eConn : SC_AND;
     723             :         }
     724             :     }
     725             : 
     726           5 :     if (eConn == SC_AND)
     727             :     {
     728          15 :         for (size_t nE = 0; nE < 2; ++nE)
     729             :         {
     730          10 :             if (nStrLen[nE] && aEntries[nE].bDoQuery)
     731             :             {
     732           4 :                 OUString aStr = rStrm.ReadUniString(nStrLen[nE]);
     733           4 :                 ExcelQueryToOooQuery(aStr, aEntries[nE]);
     734           4 :                 aEntries[nE].GetQueryItem().maString = rPool.intern(aStr);
     735           4 :                 aParam.AppendEntry() = aEntries[nE];
     736             :             }
     737             :         }
     738             :     }
     739             :     else
     740             :     {
     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#.
     745             :         //
     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.
     750             : 
     751           0 :         if (bSimple1 && bSimple2 && nStrLen[0] && nStrLen[1])
     752             :         {
     753             :             // Two simple OR'ed equal conditions.  We can import this correctly.
     754           0 :             ScQueryEntry& rEntry = aParam.AppendEntry();
     755           0 :             rEntry.bDoQuery = true;
     756           0 :             rEntry.eOp = SC_EQUAL;
     757           0 :             rEntry.eConnect = SC_AND;
     758           0 :             ScQueryEntry::QueryItemsType aItems;
     759           0 :             aItems.reserve(2);
     760           0 :             ScQueryEntry::Item aItem1, aItem2;
     761           0 :             aItem1.maString = rPool.intern(rStrm.ReadUniString(nStrLen[0]));
     762           0 :             aItem1.meType = ScQueryEntry::ByString;
     763           0 :             aItem2.maString = rPool.intern(rStrm.ReadUniString(nStrLen[1]));
     764           0 :             aItem2.meType = ScQueryEntry::ByString;
     765           0 :             aItems.push_back(aItem1);
     766           0 :             aItems.push_back(aItem2);
     767           0 :             rEntry.GetQueryItems().swap(aItems);
     768             :         }
     769           0 :         else if (nStrLen[0] && aEntries[0].bDoQuery)
     770             :         {
     771             :             // Due to conflict, we can import only the first condition.
     772           0 :             OUString aStr = rStrm.ReadUniString(nStrLen[0]);
     773           0 :             ExcelQueryToOooQuery(aStr, aEntries[0]);
     774           0 :             aEntries[0].GetQueryItem().maString = rPool.intern(aStr);
     775           0 :             aParam.AppendEntry() = aEntries[0];
     776             :         }
     777          15 :     }
     778             : }
     779             : 
     780           8 : void XclImpAutoFilterData::SetAdvancedRange( const ScRange* pRange )
     781             : {
     782           8 :     if (pRange)
     783             :     {
     784           0 :         aCriteriaRange = *pRange;
     785           0 :         bCriteria = true;
     786             :     }
     787             :     else
     788           8 :         bCriteria = false;
     789           8 : }
     790             : 
     791           0 : void XclImpAutoFilterData::SetExtractPos( const ScAddress& rAddr )
     792             : {
     793           0 :     aParam.nDestCol = rAddr.Col();
     794           0 :     aParam.nDestRow = rAddr.Row();
     795           0 :     aParam.nDestTab = rAddr.Tab();
     796           0 :     aParam.bInplace = false;
     797           0 :     aParam.bDestPers = true;
     798           0 : }
     799             : 
     800          26 : void XclImpAutoFilterData::Apply()
     801             : {
     802          26 :     CreateScDBData();
     803             : 
     804          26 :     if( bActive )
     805             :     {
     806           8 :         InsertQueryParam();
     807             :     }
     808          26 : }
     809             : 
     810          26 : void XclImpAutoFilterData::CreateScDBData()
     811             : {
     812             : 
     813             :     // Create the ScDBData() object if the AutoFilter is activated
     814             :     // or if we need to create the Advanced Filter.
     815          26 :     if( bActive || bCriteria)
     816             :     {
     817           8 :         ScDocument* pDoc = pExcRoot->pIR->GetDocPtr();
     818           8 :         OUString aNewName(STR_DB_LOCAL_NONAME);
     819           8 :         pCurrDBData = new ScDBData(aNewName , Tab(),
     820           8 :                                 StartCol(),StartRow(), EndCol(),EndRow() );
     821           8 :         if(bCriteria)
     822             :         {
     823           0 :             EnableRemoveFilter();
     824             : 
     825           0 :             pCurrDBData->SetQueryParam( aParam );
     826           0 :             pCurrDBData->SetAdvancedQuerySource(&aCriteriaRange);
     827             :         }
     828             :         else
     829           8 :             pCurrDBData->SetAdvancedQuerySource(NULL);
     830           8 :         pDoc->SetAnonymousDBData(Tab(), pCurrDBData);
     831             :     }
     832             : 
     833          26 : }
     834             : 
     835           0 : void XclImpAutoFilterData::EnableRemoveFilter()
     836             : {
     837             :     // only if this is a saved Advanced filter
     838           0 :     if( !bActive && bAutoOrAdvanced )
     839             :     {
     840           0 :         ScQueryEntry& aEntry = aParam.AppendEntry();
     841           0 :         aEntry.bDoQuery = true;
     842             :     }
     843             : 
     844             :     // TBD: force the automatic activation of the
     845             :     // "Remove Filter" by setting a virtual mouse click
     846             :     // inside the advanced range
     847           0 : }
     848             : 
     849          26 : void XclImpAutoFilterBuffer::Insert( RootData* pRoot, const ScRange& rRange)
     850             : {
     851          26 :     if( !GetByTab( rRange.aStart.Tab() ) )
     852          26 :         maFilters.push_back( new XclImpAutoFilterData( pRoot, rRange) );
     853          26 : }
     854             : 
     855           0 : void XclImpAutoFilterBuffer::AddAdvancedRange( const ScRange& rRange )
     856             : {
     857           0 :     XclImpAutoFilterData* pData = GetByTab( rRange.aStart.Tab() );
     858           0 :     if( pData )
     859           0 :         pData->SetAdvancedRange( &rRange );
     860           0 : }
     861             : 
     862           0 : void XclImpAutoFilterBuffer::AddExtractPos( const ScRange& rRange )
     863             : {
     864           0 :     XclImpAutoFilterData* pData = GetByTab( rRange.aStart.Tab() );
     865           0 :     if( pData )
     866           0 :         pData->SetExtractPos( rRange.aStart );
     867           0 : }
     868             : 
     869          81 : void XclImpAutoFilterBuffer::Apply()
     870             : {
     871             :     std::for_each(maFilters.begin(),maFilters.end(),
     872          81 :         boost::bind(&XclImpAutoFilterData::Apply,_1));
     873          81 : }
     874             : 
     875         262 : XclImpAutoFilterData* XclImpAutoFilterBuffer::GetByTab( SCTAB nTab )
     876             : {
     877         262 :     boost::ptr_vector<XclImpAutoFilterData>::iterator it;
     878         481 :     for( it = maFilters.begin(); it != maFilters.end(); ++it )
     879             :     {
     880         263 :         if( it->Tab() == nTab )
     881          44 :             return &(*it);
     882             :     }
     883         218 :     return NULL;
     884          30 : }
     885             : 
     886             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11