LCOV - code coverage report
Current view: top level - sc/source/filter/excel - excimp8.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 280 434 64.5 %
Date: 2014-11-03 Functions: 37 51 72.5 %
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         168 : class OleNameOverrideContainer : public OleNameOverrideContainer_BASE
     117             : {
     118             : private:
     119             :     typedef boost::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.size() > 0 );
     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         174 :     virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
     151             :     {
     152         174 :         ::osl::MutexGuard aGuard( m_aMutex );
     153         174 :         return ( IdToOleNameHash.find( aName ) != IdToOleNameHash.end() );
     154             :     }
     155             : 
     156             :     // XElementAccess
     157           0 :     virtual ::sal_Int32 SAL_CALL getCount(  ) throw (uno::RuntimeException)
     158             :     {
     159           0 :         ::osl::MutexGuard aGuard( m_aMutex );
     160           0 :         return IdToOleNameHash.size();
     161             :     }
     162             :     // XNameContainer
     163           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
     164             :     {
     165           0 :         ::osl::MutexGuard aGuard( m_aMutex );
     166           0 :         if ( hasByName( aName ) )
     167           0 :             throw container::ElementExistException();
     168           0 :         uno::Reference< container::XIndexContainer > xElement;
     169           0 :         if ( ! ( aElement >>= xElement ) )
     170           0 :             throw lang::IllegalArgumentException();
     171           0 :        IdToOleNameHash[ aName ] = xElement;
     172           0 :     }
     173           0 :     virtual void SAL_CALL removeByName( const OUString& aName ) throw(container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException, std::exception) SAL_OVERRIDE
     174             :     {
     175           0 :         ::osl::MutexGuard aGuard( m_aMutex );
     176           0 :         if ( !hasByName( aName ) )
     177           0 :             throw container::NoSuchElementException();
     178           0 :         IdToOleNameHash.erase( IdToOleNameHash.find( aName ) );
     179           0 :     }
     180           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
     181             :     {
     182           0 :         ::osl::MutexGuard aGuard( m_aMutex );
     183           0 :         if ( !hasByName( aName ) )
     184           0 :             throw container::NoSuchElementException();
     185           0 :         uno::Reference< container::XIndexContainer > xElement;
     186           0 :         if ( ! ( aElement >>= xElement ) )
     187           0 :             throw lang::IllegalArgumentException();
     188           0 :         IdToOleNameHash[ aName ] = xElement;
     189           0 :     }
     190             : };
     191             : 
     192             : namespace {
     193             : 
     194             : /** Future Record Type header.
     195             :     @return whether read rt matches nRecordID
     196             :  */
     197         222 : bool readFrtHeader( XclImpStream& rStrm, sal_uInt16 nRecordID )
     198             : {
     199         222 :     sal_uInt16 nRt = rStrm.ReaduInt16();
     200         222 :     rStrm.Ignore(10);   // grbitFrt (2 bytes) and reserved (8 bytes)
     201         222 :     return nRt == nRecordID;
     202             : }
     203             : 
     204             : }
     205             : 
     206         142 : ImportExcel8::ImportExcel8( XclImpRootData& rImpData, SvStream& rStrm ) :
     207         142 :     ImportExcel( rImpData, rStrm )
     208             : {
     209             :     // replace BIFF2-BIFF5 formula importer with BIFF8 formula importer
     210         142 :     delete pFormConv;
     211         142 :     pFormConv = pExcRoot->pFmlaConverter = new ExcelToSc8( GetRoot() );
     212         142 : }
     213             : 
     214         284 : ImportExcel8::~ImportExcel8()
     215             : {
     216         284 : }
     217             : 
     218         332 : void ImportExcel8::Calccount( void )
     219             : {
     220         332 :     ScDocOptions    aOpt = pD->GetDocOptions();
     221         332 :     aOpt.SetIterCount( aIn.ReaduInt16() );
     222         332 :     pD->SetDocOptions( aOpt );
     223         332 : }
     224             : 
     225         134 : void ImportExcel8::Precision( void )
     226             : {
     227         134 :     ScDocOptions aOpt = pD->GetDocOptions();
     228         134 :     aOpt.SetCalcAsShown( aIn.ReaduInt16() == 0 );
     229         134 :     pD->SetDocOptions( aOpt );
     230         134 : }
     231             : 
     232         408 : void ImportExcel8::Delta( void )
     233             : {
     234         408 :     ScDocOptions    aOpt = pD->GetDocOptions();
     235         408 :     aOpt.SetIterEps( aIn.ReadDouble() );
     236         408 :     pD->SetDocOptions( aOpt );
     237         408 : }
     238             : 
     239         408 : void ImportExcel8::Iteration( void )
     240             : {
     241         408 :     ScDocOptions    aOpt = pD->GetDocOptions();
     242         408 :     aOpt.SetIter( aIn.ReaduInt16() == 1 );
     243         408 :     pD->SetDocOptions( aOpt );
     244         408 : }
     245             : 
     246         414 : void ImportExcel8::Boundsheet( void )
     247             : {
     248             :     sal_uInt8           nLen;
     249             :     sal_uInt16          nGrbit;
     250             : 
     251         414 :     aIn.DisableDecryption();
     252         414 :     maSheetOffsets.push_back( aIn.ReaduInt32() );
     253         414 :     aIn.EnableDecryption();
     254         414 :     aIn >> nGrbit >> nLen;
     255             : 
     256         414 :     OUString aName( aIn.ReadUniString( nLen ) );
     257         414 :     GetTabInfo().AppendXclTabName( aName, nBdshtTab );
     258             : 
     259         414 :     SCTAB nScTab = static_cast< SCTAB >( nBdshtTab );
     260         414 :     if( nScTab > 0 )
     261             :     {
     262             :         OSL_ENSURE( !pD->HasTable( nScTab ), "ImportExcel8::Boundsheet - sheet exists already" );
     263         276 :         pD->MakeTable( nScTab );
     264             :     }
     265             : 
     266         414 :     if( ( nGrbit & 0x0001 ) || ( nGrbit & 0x0002 ) )
     267          18 :         pD->SetVisible( nScTab, false );
     268             : 
     269         414 :     if( !pD->RenameTab( nScTab, aName ) )
     270             :     {
     271           0 :         pD->CreateValidTabName( aName );
     272           0 :         pD->RenameTab( nScTab, aName );
     273             :     }
     274             : 
     275         414 :     nBdshtTab++;
     276         414 : }
     277             : 
     278           0 : void ImportExcel8::Scenman( void )
     279             : {
     280             :     sal_uInt16              nLastDispl;
     281             : 
     282           0 :     aIn.Ignore( 4 );
     283           0 :     aIn >> nLastDispl;
     284             : 
     285           0 :     maScenList.nLastScenario = nLastDispl;
     286           0 : }
     287             : 
     288           0 : void ImportExcel8::Scenario( void )
     289             : {
     290           0 :     maScenList.aEntries.push_back( new ExcScenario( aIn, *pExcRoot ) );
     291           0 : }
     292             : 
     293       21798 : void ImportExcel8::Labelsst( void )
     294             : {
     295       21798 :     XclAddress aXclPos;
     296             :     sal_uInt16 nXF;
     297             :     sal_uInt32  nSst;
     298             : 
     299       21798 :     aIn >> aXclPos >> nXF >> nSst;
     300             : 
     301       21798 :     ScAddress aScPos( ScAddress::UNINITIALIZED );
     302       21798 :     if( GetAddressConverter().ConvertAddress( aScPos, aXclPos, GetCurrScTab(), true ) )
     303             :     {
     304       21798 :         GetXFRangeBuffer().SetXF( aScPos, nXF );
     305       21798 :         const XclImpString* pXclStr = GetSst().GetString(nSst);
     306       21798 :         if (pXclStr)
     307       21798 :             XclImpStringHelper::SetToDocument(GetDocImport(), aScPos, *this, *pXclStr, nXF);
     308             :     }
     309       21798 : }
     310             : 
     311         208 : void ImportExcel8::FeatHdr( void )
     312             : {
     313         208 :     if (!readFrtHeader( aIn, 0x0867))
     314           0 :         return;
     315             : 
     316             :     // Feature type (isf) can be EXC_ISFPROTECTION, EXC_ISFFEC2 or
     317             :     // EXC_ISFFACTOID.
     318         208 :     sal_uInt16 nFeatureType = aIn.ReaduInt16();
     319         208 :     if (nFeatureType != EXC_ISFPROTECTION)
     320             :         // We currently only support import of enhanced protection data.
     321           4 :         return;
     322             : 
     323         204 :     aIn.Ignore(1); // always 1
     324             : 
     325         204 :     GetSheetProtectBuffer().ReadOptions( aIn, GetCurrScTab() );
     326             : }
     327             : 
     328          14 : void ImportExcel8::Feat( void )
     329             : {
     330          14 :     if (!readFrtHeader( aIn, 0x0868))
     331           4 :         return;
     332             : 
     333             :     // Feature type (isf) can be EXC_ISFPROTECTION, EXC_ISFFEC2 or
     334             :     // EXC_ISFFACTOID.
     335          14 :     sal_uInt16 nFeatureType = aIn.ReaduInt16();
     336          14 :     if (nFeatureType != EXC_ISFPROTECTION)
     337             :         // We currently only support import of enhanced protection data.
     338           4 :         return;
     339             : 
     340          10 :     aIn.Ignore(5);                          // reserved1 (1 byte) and reserved2 (4 bytes)
     341             : 
     342          10 :     sal_uInt16 nCref = aIn.ReaduInt16();    // number of ref elements
     343          10 :     aIn.Ignore(4);                          // size if EXC_ISFFEC2, else 0 and to be ignored
     344          10 :     aIn.Ignore(2);                          // reserved3 (2 bytes)
     345             : 
     346          10 :     ScEnhancedProtection aProt;
     347          10 :     if (nCref)
     348             :     {
     349          10 :         XclRangeList aRefs;
     350          10 :         aRefs.Read( aIn, true, nCref);
     351          10 :         if (!aRefs.empty())
     352             :         {
     353          10 :             aProt.maRangeList = new ScRangeList;
     354          10 :             GetAddressConverter().ConvertRangeList( *aProt.maRangeList, aRefs, GetCurrScTab(), false);
     355          10 :         }
     356             :     }
     357             : 
     358             :     // FeatProtection structure follows in record.
     359             : 
     360          10 :     aProt.mnAreserved = aIn.ReaduInt32();
     361          10 :     aProt.mnPasswordVerifier = aIn.ReaduInt32();
     362          10 :     aProt.maTitle = aIn.ReadUniString();
     363          10 :     if ((aProt.mnAreserved & 0x00000001) == 0x00000001)
     364             :     {
     365           4 :         sal_uInt32 nCbSD = aIn.ReaduInt32();
     366             :         // TODO: could here be some sanity check applied to not allocate 4GB?
     367           4 :         aProt.maSecurityDescriptor.resize( nCbSD);
     368           4 :         sal_Size nRead = aIn.Read( &aProt.maSecurityDescriptor.front(), nCbSD);
     369           4 :         if (nRead < nCbSD)
     370           0 :             aProt.maSecurityDescriptor.resize( nRead);
     371             :     }
     372             : 
     373          10 :     GetSheetProtectBuffer().AppendEnhancedProtection( aProt, GetCurrScTab() );
     374             : }
     375             : 
     376          56 : void ImportExcel8::ReadBasic( void )
     377             : {
     378          56 :     SfxObjectShell* pShell = GetDocShell();
     379          56 :     SotStorageRef xRootStrg = GetRootStorage();
     380          56 :     const SvtFilterOptions& rFilterOpt = SvtFilterOptions::Get();
     381          56 :     if( pShell && xRootStrg.Is() ) try
     382             :     {
     383             :         // #FIXME need to get rid of this, we can also do this from within oox
     384             :         // via the "ooo.vba.VBAGlobals" service
     385         112 :         if( ( rFilterOpt.IsLoadExcelBasicCode() ||
     386         112 :               rFilterOpt.IsLoadExcelBasicStorage() ) &&
     387          56 :             rFilterOpt.IsLoadExcelBasicExecutable() )
     388             :         {
     389             :             // see if we have the XCB stream
     390          56 :             SvStorageStreamRef xXCB = xRootStrg->OpenSotStream( OUString("XCB"), STREAM_STD_READ | STREAM_NOCREATE  );
     391          56 :             if ( xXCB.Is()|| SVSTREAM_OK == xXCB->GetError() )
     392             :             {
     393          56 :                 ScCTBWrapper wrapper;
     394          56 :                 if ( wrapper.Read( *xXCB ) )
     395             :                 {
     396             : #if OSL_DEBUG_LEVEL > 1
     397             :                     wrapper.Print( stderr );
     398             : #endif
     399          56 :                     wrapper.ImportCustomToolBar( *pShell );
     400          56 :                 }
     401          56 :             }
     402             :         }
     403             :         try
     404             :         {
     405          56 :             uno::Reference< uno::XComponentContext > aCtx( ::comphelper::getProcessComponentContext() );
     406          56 :             SfxMedium& rMedium = GetMedium();
     407         112 :             uno::Reference< io::XInputStream > xIn = rMedium.GetInputStream();
     408         112 :             oox::ole::OleStorage root( aCtx, xIn, false );
     409         112 :             oox::StorageRef vbaStg = root.openSubStorage( "_VBA_PROJECT_CUR", false );
     410          56 :             if ( vbaStg.get() )
     411             :             {
     412          56 :                 oox::ole::VbaProject aVbaPrj( aCtx, pShell->GetModel(), "Calc" );
     413             :                 // collect names of embedded form controls, as specified in the VBA project
     414         112 :                 uno::Reference< container::XNameContainer > xOleNameOverrideSink( new OleNameOverrideContainer );
     415          56 :                 aVbaPrj.setOleOverridesSink( xOleNameOverrideSink );
     416          56 :                 aVbaPrj.importVbaProject( *vbaStg );
     417         112 :                 GetObjectManager().SetOleNameOverrideInfo( xOleNameOverrideSink );
     418          56 :             }
     419             :         }
     420           0 :         catch( uno::Exception& )
     421             :         {
     422             :         }
     423             :     }
     424           0 :     catch( uno::Exception& )
     425             :     {
     426          56 :     }
     427          56 : }
     428             : 
     429         412 : void ImportExcel8::EndSheet( void )
     430             : {
     431         412 :     ImportExcel::EndSheet();
     432         412 :     GetCondFormatManager().Apply();
     433         412 :     GetValidationManager().Apply();
     434         412 : }
     435             : 
     436         142 : void ImportExcel8::PostDocLoad( void )
     437             : {
     438             : #if HAVE_FEATURE_SCRIPTING
     439             :     // reading basic has been delayed until sheet objects (codenames etc.) are read
     440         142 :     if( HasBasic() )
     441          56 :         ReadBasic();
     442             : #endif
     443             :     // #i11776# filtered ranges before outlines and hidden rows
     444         142 :     if( pExcRoot->pAutoFilterBuffer )
     445         142 :         pExcRoot->pAutoFilterBuffer->Apply();
     446             : 
     447         142 :     GetWebQueryBuffer().Apply();    //! test if extant
     448         142 :     GetSheetProtectBuffer().Apply();
     449         142 :     GetDocProtectBuffer().Apply();
     450             : 
     451         142 :     ImportExcel::PostDocLoad();
     452             : 
     453             :     // check scenarios; Attention: This increases the table count of the document!!
     454         142 :     if( !pD->IsClipboard() && maScenList.aEntries.size() )
     455             :     {
     456           0 :         pD->UpdateChartListenerCollection();    // references in charts must be updated
     457             : 
     458           0 :         maScenList.Apply( GetRoot() );
     459             :     }
     460             : 
     461             :     // read doc info (no docshell while pasting from clipboard)
     462         142 :     LoadDocumentProperties();
     463             : 
     464             :     // #i45843# Pivot tables are now handled outside of PostDocLoad, so they are available
     465             :     // when formula cells are calculated, for the GETPIVOTDATA function.
     466         142 : }
     467             : 
     468         142 : void ImportExcel8::LoadDocumentProperties()
     469             : {
     470             :     // no docshell while pasting from clipboard
     471         142 :     if( SfxObjectShell* pShell = GetDocShell() )
     472             :     {
     473             :         // BIFF5+ without storage is possible
     474         142 :         SotStorageRef xRootStrg = GetRootStorage();
     475         142 :         if( xRootStrg.Is() ) try
     476             :         {
     477         142 :             uno::Reference< document::XDocumentPropertiesSupplier > xDPS( pShell->GetModel(), uno::UNO_QUERY_THROW );
     478         284 :             uno::Reference< document::XDocumentProperties > xDocProps( xDPS->getDocumentProperties(), uno::UNO_SET_THROW );
     479         284 :             sfx2::LoadOlePropertySet( xDocProps, xRootStrg );
     480             :         }
     481           0 :         catch( uno::Exception& )
     482             :         {
     483         142 :         }
     484             :     }
     485         142 : }
     486             : 
     487             : // autofilter
     488             : 
     489          10 : void ImportExcel8::FilterMode( void )
     490             : {
     491             :     // The FilterMode record exists: if either the AutoFilter
     492             :     // record exists or an Advanced Filter is saved and stored
     493             :     // in the sheet. Thus if the FilterMode records only exists
     494             :     // then the latter is true..
     495          20 :     if( !pExcRoot->pAutoFilterBuffer ) return;
     496             : 
     497          10 :     XclImpAutoFilterData* pData = pExcRoot->pAutoFilterBuffer->GetByTab( GetCurrScTab() );
     498          10 :     if( pData )
     499          10 :         pData->SetAutoOrAdvanced();
     500             : }
     501             : 
     502          16 : void ImportExcel8::AutoFilterInfo( void )
     503             : {
     504          32 :     if( !pExcRoot->pAutoFilterBuffer ) return;
     505             : 
     506          16 :     XclImpAutoFilterData* pData = pExcRoot->pAutoFilterBuffer->GetByTab( GetCurrScTab() );
     507          16 :     if( pData )
     508             :     {
     509          16 :         pData->SetAdvancedRange( NULL );
     510          16 :         pData->Activate();
     511             :     }
     512             : }
     513             : 
     514          10 : void ImportExcel8::AutoFilter( void )
     515             : {
     516          20 :     if( !pExcRoot->pAutoFilterBuffer ) return;
     517             : 
     518          10 :     XclImpAutoFilterData* pData = pExcRoot->pAutoFilterBuffer->GetByTab( GetCurrScTab() );
     519          10 :     if( pData )
     520          10 :         pData->ReadAutoFilter(aIn, GetDoc().GetSharedStringPool());
     521             : }
     522             : 
     523          52 : XclImpAutoFilterData::XclImpAutoFilterData( RootData* pRoot, const ScRange& rRange ) :
     524             :         ExcRoot( pRoot ),
     525             :         pCurrDBData(NULL),
     526             :         bActive( false ),
     527             :         bCriteria( false ),
     528          52 :         bAutoOrAdvanced(false)
     529             : {
     530          52 :     aParam.nCol1 = rRange.aStart.Col();
     531          52 :     aParam.nRow1 = rRange.aStart.Row();
     532          52 :     aParam.nTab = rRange.aStart.Tab();
     533          52 :     aParam.nCol2 = rRange.aEnd.Col();
     534          52 :     aParam.nRow2 = rRange.aEnd.Row();
     535             : 
     536          52 :     aParam.bInplace = true;
     537             : 
     538          52 : }
     539             : 
     540             : namespace {
     541             : 
     542           2 : OUString CreateFromDouble( double fVal )
     543             : {
     544             :     return rtl::math::doubleToUString(fVal,
     545             :                 rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max,
     546           2 :                 ScGlobal::pLocaleData->getNumDecimalSep()[0], true);
     547             : }
     548             : 
     549             : }
     550             : 
     551          16 : void XclImpAutoFilterData::SetCellAttribs()
     552             : {
     553          16 :     ScDocument& rDoc = pExcRoot->pIR->GetDoc();
     554          64 :     for ( SCCOL nCol = StartCol(); nCol <= EndCol(); nCol++ )
     555             :     {
     556          48 :         sal_Int16 nFlag = static_cast<const ScMergeFlagAttr*>( rDoc.GetAttr( nCol, StartRow(), Tab(), ATTR_MERGE_FLAG ))->GetValue();
     557          48 :         rDoc.ApplyAttr( nCol, StartRow(), Tab(), ScMergeFlagAttr( nFlag | SC_MF_AUTO) );
     558             :     }
     559          16 : }
     560             : 
     561          16 : void XclImpAutoFilterData::InsertQueryParam()
     562             : {
     563          16 :     if (pCurrDBData)
     564             :     {
     565          16 :         ScRange aAdvRange;
     566          16 :         bool    bHasAdv = pCurrDBData->GetAdvancedQuerySource( aAdvRange );
     567          16 :         if( bHasAdv )
     568           0 :             pExcRoot->pIR->GetDoc().CreateQueryParam( aAdvRange.aStart.Col(),
     569           0 :                 aAdvRange.aStart.Row(), aAdvRange.aEnd.Col(), aAdvRange.aEnd.Row(),
     570           0 :                 aAdvRange.aStart.Tab(), aParam );
     571             : 
     572          16 :         pCurrDBData->SetQueryParam( aParam );
     573          16 :         if( bHasAdv )
     574           0 :             pCurrDBData->SetAdvancedQuerySource( &aAdvRange );
     575             :         else
     576             :         {
     577          16 :             pCurrDBData->SetAutoFilter( true );
     578          16 :             SetCellAttribs();
     579             :         }
     580             :     }
     581          16 : }
     582             : 
     583           8 : static void ExcelQueryToOooQuery( OUString& aStr, ScQueryEntry& rEntry )
     584             : {
     585           8 :     if (rEntry.eOp != SC_EQUAL && rEntry.eOp != SC_NOT_EQUAL)
     586           8 :         return;
     587             : 
     588           8 :     sal_Int32   nLen = aStr.getLength();
     589           8 :     sal_Unicode nStart = aStr[0];
     590           8 :     sal_Unicode nEnd   = aStr[ nLen-1 ];
     591           8 :     if( nLen > 2 && nStart == '*' && nEnd == '*' )
     592             :     {
     593           0 :         aStr = aStr.copy( 1, nLen-2 );
     594           0 :         rEntry.eOp = ( rEntry.eOp == SC_EQUAL ) ? SC_CONTAINS : SC_DOES_NOT_CONTAIN;
     595             :     }
     596           8 :     else if( nLen > 1 && nStart == '*' && nEnd != '*' )
     597             :     {
     598           0 :         aStr = aStr.copy( 1 );
     599           0 :         rEntry.eOp = ( rEntry.eOp == SC_EQUAL ) ? SC_ENDS_WITH : SC_DOES_NOT_END_WITH;
     600             :     }
     601           8 :     else if( nLen > 1 && nStart != '*' && nEnd == '*' )
     602             :     {
     603           0 :         aStr = aStr.copy( 0, nLen-1 );
     604           0 :         rEntry.eOp = ( rEntry.eOp == SC_EQUAL ) ? SC_BEGINS_WITH : SC_DOES_NOT_BEGIN_WITH;
     605             :     }
     606           8 :     else if( nLen == 2 && nStart == '*' && nEnd == '*' )
     607             :     {
     608           0 :         aStr = aStr.copy( 1 );
     609             :     }
     610             : }
     611             : 
     612          10 : void XclImpAutoFilterData::ReadAutoFilter(
     613             :     XclImpStream& rStrm, svl::SharedStringPool& rPool )
     614             : {
     615             :     sal_uInt16 nCol, nFlags;
     616          10 :     rStrm >> nCol >> nFlags;
     617             : 
     618          10 :     ScQueryConnect eConn = ::get_flagvalue( nFlags, EXC_AFFLAG_ANDORMASK, SC_OR, SC_AND );
     619          10 :     bool bSimple1    = ::get_flag(nFlags, EXC_AFFLAG_SIMPLE1);
     620          10 :     bool bSimple2    = ::get_flag(nFlags, EXC_AFFLAG_SIMPLE2);
     621          10 :     bool bTop10      = ::get_flag(nFlags, EXC_AFFLAG_TOP10);
     622          10 :     bool bTopOfTop10 = ::get_flag(nFlags, EXC_AFFLAG_TOP10TOP);
     623          10 :     bool bPercent    = ::get_flag(nFlags, EXC_AFFLAG_TOP10PERC);
     624          10 :     sal_uInt16 nCntOfTop10 = nFlags >> 7;
     625             : 
     626          10 :     if( bTop10 )
     627             :     {
     628           0 :         ScQueryEntry& aEntry = aParam.AppendEntry();
     629           0 :         ScQueryEntry::Item& rItem = aEntry.GetQueryItem();
     630           0 :         aEntry.bDoQuery = true;
     631           0 :         aEntry.nField = static_cast<SCCOLROW>(StartCol() + static_cast<SCCOL>(nCol));
     632             :         aEntry.eOp = bTopOfTop10 ?
     633           0 :             (bPercent ? SC_TOPPERC : SC_TOPVAL) : (bPercent ? SC_BOTPERC : SC_BOTVAL);
     634           0 :         aEntry.eConnect = SC_AND;
     635             : 
     636           0 :         rItem.meType = ScQueryEntry::ByString;
     637           0 :         rItem.maString = rPool.intern(OUString::number(nCntOfTop10));
     638             : 
     639           0 :         rStrm.Ignore(20);
     640           0 :         return;
     641             :     }
     642             : 
     643             :     sal_uInt8   nType, nOper, nBoolErr, nVal;
     644             :     sal_Int32   nRK;
     645             :     double  fVal;
     646             :     bool bIgnore;
     647             : 
     648          10 :     sal_uInt8 nStrLen[2] = { 0, 0 };
     649          30 :     ScQueryEntry aEntries[2];
     650             : 
     651          30 :     for (size_t nE = 0; nE < 2; ++nE)
     652             :     {
     653          20 :         ScQueryEntry& rEntry = aEntries[nE];
     654          20 :         ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
     655          20 :         bIgnore = false;
     656             : 
     657          20 :         rStrm >> nType >> nOper;
     658          20 :         switch( nOper )
     659             :         {
     660             :             case EXC_AFOPER_LESS:
     661           0 :                 rEntry.eOp = SC_LESS;
     662           0 :             break;
     663             :             case EXC_AFOPER_EQUAL:
     664          12 :                 rEntry.eOp = SC_EQUAL;
     665          12 :             break;
     666             :             case EXC_AFOPER_LESSEQUAL:
     667           0 :                 rEntry.eOp = SC_LESS_EQUAL;
     668           0 :             break;
     669             :             case EXC_AFOPER_GREATER:
     670           0 :                 rEntry.eOp = SC_GREATER;
     671           0 :             break;
     672             :             case EXC_AFOPER_NOTEQUAL:
     673           0 :                 rEntry.eOp = SC_NOT_EQUAL;
     674           0 :             break;
     675             :             case EXC_AFOPER_GREATEREQUAL:
     676           0 :                 rEntry.eOp = SC_GREATER_EQUAL;
     677           0 :             break;
     678             :             default:
     679           8 :                 rEntry.eOp = SC_EQUAL;
     680             :         }
     681             : 
     682          20 :         switch( nType )
     683             :         {
     684             :             case EXC_AFTYPE_RK:
     685           0 :                 rStrm >> nRK;
     686           0 :                 rStrm.Ignore( 4 );
     687           0 :                 rItem.maString = rPool.intern(
     688           0 :                     CreateFromDouble(XclTools::GetDoubleFromRK(nRK)));
     689           0 :             break;
     690             :             case EXC_AFTYPE_DOUBLE:
     691           2 :                 rStrm >> fVal;
     692           2 :                 rItem.maString = rPool.intern(CreateFromDouble(fVal));
     693           2 :             break;
     694             :             case EXC_AFTYPE_STRING:
     695           8 :                 rStrm.Ignore( 4 );
     696           8 :                 rStrm >> nStrLen[ nE ];
     697           8 :                 rStrm.Ignore( 3 );
     698           8 :                 rItem.maString = svl::SharedString();
     699           8 :             break;
     700             :             case EXC_AFTYPE_BOOLERR:
     701           0 :                 rStrm >> nBoolErr >> nVal;
     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          10 :                 rStrm.Ignore( 8 );
     714          10 :                 bIgnore = true;
     715             :         }
     716             : 
     717          20 :         if (!bIgnore)
     718             :         {
     719          10 :             rEntry.bDoQuery = true;
     720          10 :             rItem.meType = ScQueryEntry::ByString;
     721          10 :             rEntry.nField = static_cast<SCCOLROW>(StartCol() + static_cast<SCCOL>(nCol));
     722          10 :             rEntry.eConnect = nE ? eConn : SC_AND;
     723             :         }
     724             :     }
     725             : 
     726          10 :     if (eConn == SC_AND)
     727             :     {
     728          30 :         for (size_t nE = 0; nE < 2; ++nE)
     729             :         {
     730          20 :             if (nStrLen[nE] && aEntries[nE].bDoQuery)
     731             :             {
     732           8 :                 OUString aStr = rStrm.ReadUniString(nStrLen[nE]);
     733           8 :                 ExcelQueryToOooQuery(aStr, aEntries[nE]);
     734           8 :                 aEntries[nE].GetQueryItem().maString = rPool.intern(aStr);
     735           8 :                 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          30 :     }
     778             : }
     779             : 
     780          16 : void XclImpAutoFilterData::SetAdvancedRange( const ScRange* pRange )
     781             : {
     782          16 :     if (pRange)
     783             :     {
     784           0 :         aCriteriaRange = *pRange;
     785           0 :         bCriteria = true;
     786             :     }
     787             :     else
     788          16 :         bCriteria = false;
     789          16 : }
     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          52 : void XclImpAutoFilterData::Apply()
     801             : {
     802          52 :     CreateScDBData();
     803             : 
     804          52 :     if( bActive )
     805             :     {
     806          16 :         InsertQueryParam();
     807             :     }
     808          52 : }
     809             : 
     810          52 : 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          52 :     if( bActive || bCriteria)
     816             :     {
     817          16 :         ScDocument* pDoc = pExcRoot->pIR->GetDocPtr();
     818          16 :         OUString aNewName(STR_DB_LOCAL_NONAME);
     819          16 :         pCurrDBData = new ScDBData(aNewName , Tab(),
     820          16 :                                 StartCol(),StartRow(), EndCol(),EndRow() );
     821          16 :         if(bCriteria)
     822             :         {
     823           0 :             EnableRemoveFilter();
     824             : 
     825           0 :             pCurrDBData->SetQueryParam( aParam );
     826           0 :             pCurrDBData->SetAdvancedQuerySource(&aCriteriaRange);
     827             :         }
     828             :         else
     829          16 :             pCurrDBData->SetAdvancedQuerySource(NULL);
     830          16 :         pDoc->SetAnonymousDBData(Tab(), pCurrDBData);
     831             :     }
     832             : 
     833          52 : }
     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          52 : void XclImpAutoFilterBuffer::Insert( RootData* pRoot, const ScRange& rRange)
     850             : {
     851          52 :     if( !GetByTab( rRange.aStart.Tab() ) )
     852          52 :         maFilters.push_back( new XclImpAutoFilterData( pRoot, rRange) );
     853          52 : }
     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         142 : void XclImpAutoFilterBuffer::Apply()
     870             : {
     871             :     std::for_each(maFilters.begin(),maFilters.end(),
     872         142 :         boost::bind(&XclImpAutoFilterData::Apply,_1));
     873         142 : }
     874             : 
     875         500 : XclImpAutoFilterData* XclImpAutoFilterBuffer::GetByTab( SCTAB nTab )
     876             : {
     877         500 :     boost::ptr_vector<XclImpAutoFilterData>::iterator it;
     878         938 :     for( it = maFilters.begin(); it != maFilters.end(); ++it )
     879             :     {
     880         526 :         if( it->Tab() == nTab )
     881          88 :             return const_cast<XclImpAutoFilterData*>(&(*it));
     882             :     }
     883         412 :     return NULL;
     884          48 : }
     885             : 
     886             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10