LCOV - code coverage report
Current view: top level - libreoffice/sc/source/filter/oox - workbookfragment.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 87 176 49.4 %
Date: 2012-12-27 Functions: 7 15 46.7 %
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 "workbookfragment.hxx"
      21             : 
      22             : #include <com/sun/star/table/CellAddress.hpp>
      23             : #include "oox/core/filterbase.hxx"
      24             : #include "oox/drawingml/themefragmenthandler.hxx"
      25             : #include "oox/helper/attributelist.hxx"
      26             : #include "oox/helper/progressbar.hxx"
      27             : #include "oox/helper/propertyset.hxx"
      28             : #include "oox/ole/olestorage.hxx"
      29             : #include "vcl/msgbox.hxx"
      30             : 
      31             : #include "biffinputstream.hxx"
      32             : #include "chartsheetfragment.hxx"
      33             : #include "connectionsfragment.hxx"
      34             : #include "externallinkbuffer.hxx"
      35             : #include "externallinkfragment.hxx"
      36             : #include "pivotcachebuffer.hxx"
      37             : #include "sharedstringsbuffer.hxx"
      38             : #include "sharedstringsfragment.hxx"
      39             : #include "stylesfragment.hxx"
      40             : #include "tablebuffer.hxx"
      41             : #include "themebuffer.hxx"
      42             : #include "viewsettings.hxx"
      43             : #include "workbooksettings.hxx"
      44             : #include "worksheetbuffer.hxx"
      45             : #include "worksheetfragment.hxx"
      46             : 
      47             : #include "document.hxx"
      48             : #include "docsh.hxx"
      49             : #include "globstr.hrc"
      50             : #include "calcconfig.hxx"
      51             : 
      52             : #include <comphelper/processfactory.hxx>
      53             : #include <officecfg/Office/Calc.hxx>
      54             : 
      55             : namespace oox {
      56             : namespace xls {
      57             : 
      58             : // ============================================================================
      59             : 
      60             : using namespace ::com::sun::star::io;
      61             : using namespace ::com::sun::star::table;
      62             : using namespace ::com::sun::star::uno;
      63             : using namespace ::com::sun::star::sheet;
      64             : using namespace ::oox::core;
      65             : 
      66             : using ::oox::drawingml::ThemeFragmentHandler;
      67             : using ::rtl::OUString;
      68             : 
      69             : // ============================================================================
      70             : 
      71             : namespace {
      72             : 
      73             : const double PROGRESS_LENGTH_GLOBALS        = 0.1;      /// 10% of progress bar for globals import.
      74             : 
      75             : } // namespace
      76             : 
      77             : // ============================================================================
      78             : 
      79          11 : WorkbookFragment::WorkbookFragment( const WorkbookHelper& rHelper, const OUString& rFragmentPath ) :
      80          11 :     WorkbookFragmentBase( rHelper, rFragmentPath )
      81             : {
      82          11 : }
      83             : 
      84         124 : ContextHandlerRef WorkbookFragment::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
      85             : {
      86         124 :     switch( getCurrentElement() )
      87             :     {
      88             :         case XML_ROOT_CONTEXT:
      89          11 :             if( nElement == XLS_TOKEN( workbook ) ) return this;
      90           0 :         break;
      91             : 
      92             :         case XLS_TOKEN( workbook ):
      93          66 :             switch( nElement )
      94             :             {
      95             :                 case XLS_TOKEN( sheets ):
      96             :                 case XLS_TOKEN( bookViews ):
      97             :                 case XLS_TOKEN( externalReferences ):
      98             :                 case XLS_TOKEN( definedNames ):
      99          24 :                 case XLS_TOKEN( pivotCaches ):          return this;
     100             : 
     101           0 :                 case XLS_TOKEN( fileSharing ):          getWorkbookSettings().importFileSharing( rAttribs );    break;
     102          11 :                 case XLS_TOKEN( workbookPr ):           getWorkbookSettings().importWorkbookPr( rAttribs );     break;
     103          11 :                 case XLS_TOKEN( calcPr ):               getWorkbookSettings().importCalcPr( rAttribs );         break;
     104           0 :                 case XLS_TOKEN( oleSize ):              getViewSettings().importOleSize( rAttribs );            break;
     105             :             }
     106          42 :         break;
     107             : 
     108             :         case XLS_TOKEN( sheets ):
     109          25 :             if( nElement == XLS_TOKEN( sheet ) ) getWorksheets().importSheet( rAttribs );
     110          25 :         break;
     111             :         case XLS_TOKEN( bookViews ):
     112          11 :             if( nElement == XLS_TOKEN( workbookView ) ) getViewSettings().importWorkbookView( rAttribs );
     113          11 :         break;
     114             :         case XLS_TOKEN( externalReferences ):
     115           0 :             if( nElement == XLS_TOKEN( externalReference ) ) importExternalReference( rAttribs );
     116           0 :         break;
     117             :         case XLS_TOKEN( definedNames ):
     118          11 :             if( nElement == XLS_TOKEN( definedName ) ) { importDefinedName( rAttribs ); return this; } // collect formula
     119           0 :         break;
     120             :         case XLS_TOKEN( pivotCaches ):
     121           0 :             if( nElement == XLS_TOKEN( pivotCache ) ) importPivotCache( rAttribs );
     122           0 :         break;
     123             :     }
     124          78 :     return 0;
     125             : }
     126             : 
     127          11 : void WorkbookFragment::onCharacters( const OUString& rChars )
     128             : {
     129          11 :     if( isCurrentElement( XLS_TOKEN( definedName ) ) && mxCurrName.get() )
     130          11 :         mxCurrName->setFormula( rChars );
     131          11 : }
     132             : 
     133           0 : ContextHandlerRef WorkbookFragment::onCreateRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm )
     134             : {
     135           0 :     switch( getCurrentElement() )
     136             :     {
     137             :         case XML_ROOT_CONTEXT:
     138           0 :             if( nRecId == BIFF12_ID_WORKBOOK ) return this;
     139           0 :         break;
     140             : 
     141             :         case BIFF12_ID_WORKBOOK:
     142           0 :             switch( nRecId )
     143             :             {
     144             :                 case BIFF12_ID_SHEETS:
     145             :                 case BIFF12_ID_BOOKVIEWS:
     146             :                 case BIFF12_ID_EXTERNALREFS:
     147           0 :                 case BIFF12_ID_PIVOTCACHES:     return this;
     148             : 
     149           0 :                 case BIFF12_ID_FILESHARING:     getWorkbookSettings().importFileSharing( rStrm );   break;
     150           0 :                 case BIFF12_ID_WORKBOOKPR:      getWorkbookSettings().importWorkbookPr( rStrm );    break;
     151           0 :                 case BIFF12_ID_CALCPR:          getWorkbookSettings().importCalcPr( rStrm );        break;
     152           0 :                 case BIFF12_ID_OLESIZE:         getViewSettings().importOleSize( rStrm );           break;
     153           0 :                 case BIFF12_ID_DEFINEDNAME:     getDefinedNames().importDefinedName( rStrm );       break;
     154             :             }
     155           0 :         break;
     156             : 
     157             :         case BIFF12_ID_SHEETS:
     158           0 :             if( nRecId == BIFF12_ID_SHEET ) getWorksheets().importSheet( rStrm );
     159           0 :         break;
     160             :         case BIFF12_ID_BOOKVIEWS:
     161           0 :             if( nRecId == BIFF12_ID_WORKBOOKVIEW ) getViewSettings().importWorkbookView( rStrm );
     162           0 :         break;
     163             : 
     164             :         case BIFF12_ID_EXTERNALREFS:
     165           0 :             switch( nRecId )
     166             :             {
     167           0 :                 case BIFF12_ID_EXTERNALREF:     importExternalRef( rStrm );                         break;
     168           0 :                 case BIFF12_ID_EXTERNALSELF:    getExternalLinks().importExternalSelf( rStrm );     break;
     169           0 :                 case BIFF12_ID_EXTERNALSAME:    getExternalLinks().importExternalSame( rStrm );     break;
     170           0 :                 case BIFF12_ID_EXTERNALADDIN:   getExternalLinks().importExternalAddin( rStrm );    break;
     171           0 :                 case BIFF12_ID_EXTERNALSHEETS:  getExternalLinks().importExternalSheets( rStrm );   break;
     172             :             }
     173           0 :         break;
     174             : 
     175             :         case BIFF12_ID_PIVOTCACHES:
     176           0 :             if( nRecId == BIFF12_ID_PIVOTCACHE ) importPivotCache( rStrm );
     177             :     }
     178           0 :     return 0;
     179             : }
     180             : 
     181           0 : const RecordInfo* WorkbookFragment::getRecordInfos() const
     182             : {
     183             :     static const RecordInfo spRecInfos[] =
     184             :     {
     185             :         { BIFF12_ID_BOOKVIEWS,      BIFF12_ID_BOOKVIEWS + 1         },
     186             :         { BIFF12_ID_EXTERNALREFS,   BIFF12_ID_EXTERNALREFS + 1      },
     187             :         { BIFF12_ID_FUNCTIONGROUPS, BIFF12_ID_FUNCTIONGROUPS + 2    },
     188             :         { BIFF12_ID_PIVOTCACHE,     BIFF12_ID_PIVOTCACHE + 1        },
     189             :         { BIFF12_ID_PIVOTCACHES,    BIFF12_ID_PIVOTCACHES + 1       },
     190             :         { BIFF12_ID_SHEETS,         BIFF12_ID_SHEETS + 1            },
     191             :         { BIFF12_ID_WORKBOOK,       BIFF12_ID_WORKBOOK + 1          },
     192             :         { -1,                       -1                              }
     193             :     };
     194           0 :     return spRecInfos;
     195             : }
     196             : 
     197          11 : void WorkbookFragment::finalizeImport()
     198             : {
     199          11 :     ISegmentProgressBarRef xGlobalSegment = getProgressBar().createSegment( PROGRESS_LENGTH_GLOBALS );
     200             : 
     201             :     // read the theme substream
     202          11 :     OUString aThemeFragmentPath = getFragmentPathFromFirstType( CREATE_OFFICEDOC_RELATION_TYPE( "theme" ) );
     203          11 :     if( !aThemeFragmentPath.isEmpty() )
     204           4 :         importOoxFragment( new ThemeFragmentHandler( getFilter(), aThemeFragmentPath, getTheme() ) );
     205          11 :     xGlobalSegment->setPosition( 0.25 );
     206             : 
     207             :     // read the styles substream (requires finalized theme buffer)
     208          11 :     OUString aStylesFragmentPath = getFragmentPathFromFirstType( CREATE_OFFICEDOC_RELATION_TYPE( "styles" ) );
     209          11 :     if( !aStylesFragmentPath.isEmpty() )
     210          11 :         importOoxFragment( new StylesFragment( *this, aStylesFragmentPath ) );
     211          11 :     xGlobalSegment->setPosition( 0.5 );
     212             : 
     213             :     // read the shared string table substream (requires finalized styles buffer)
     214          11 :     OUString aSstFragmentPath = getFragmentPathFromFirstType( CREATE_OFFICEDOC_RELATION_TYPE( "sharedStrings" ) );
     215          11 :     if( !aSstFragmentPath.isEmpty() )
     216           9 :         importOoxFragment( new SharedStringsFragment( *this, aSstFragmentPath ) );
     217          11 :     xGlobalSegment->setPosition( 0.75 );
     218             : 
     219             :     // read the connections substream
     220          11 :     OUString aConnFragmentPath = getFragmentPathFromFirstType( CREATE_OFFICEDOC_RELATION_TYPE( "connections" ) );
     221          11 :     if( !aConnFragmentPath.isEmpty() )
     222           0 :         importOoxFragment( new ConnectionsFragment( *this, aConnFragmentPath ) );
     223          11 :     xGlobalSegment->setPosition( 1.0 );
     224             : 
     225             : 
     226             :     /*  Create fragments for all sheets, before importing them. Needed to do
     227             :         some preprocessing in the fragment constructors, e.g. loading the table
     228             :         fragments for all sheets that are needed before the cell formulas are
     229             :         loaded. Additionally, the instances of the WorkbookGlobals structures
     230             :         have to be stored for every sheet. */
     231             :     typedef ::std::pair< WorksheetGlobalsRef, FragmentHandlerRef > SheetFragmentHandler;
     232             :     typedef ::std::vector< SheetFragmentHandler > SheetFragmentVector;
     233          11 :     SheetFragmentVector aSheetFragments;
     234          11 :     WorksheetBuffer& rWorksheets = getWorksheets();
     235          11 :     sal_Int32 nWorksheetCount = rWorksheets.getWorksheetCount();
     236          36 :     for( sal_Int32 nWorksheet = 0; nWorksheet < nWorksheetCount; ++nWorksheet )
     237             :     {
     238          25 :         sal_Int16 nCalcSheet = rWorksheets.getCalcSheetIndex( nWorksheet );
     239          25 :         const Relation* pRelation = getRelations().getRelationFromRelId( rWorksheets.getWorksheetRelId( nWorksheet ) );
     240          25 :         if( (nCalcSheet >= 0) && pRelation )
     241             :         {
     242             :             // get fragment path of the sheet
     243          25 :             OUString aFragmentPath = getFragmentPathFromRelation( *pRelation );
     244             :             OSL_ENSURE( !aFragmentPath.isEmpty(), "WorkbookFragment::finalizeImport - cannot access sheet fragment" );
     245          25 :             if( !aFragmentPath.isEmpty() )
     246             :             {
     247             :                 // leave space for formula processing ( calcuate the segments as
     248             :                 // if there is an extra sheet )
     249          25 :                 double fSegmentLength = getProgressBar().getFreeLength() / (nWorksheetCount - ( nWorksheet - 1) );
     250          25 :                 ISegmentProgressBarRef xSheetSegment = getProgressBar().createSegment( fSegmentLength );
     251             : 
     252             :                 // get the sheet type according to the relations type
     253          25 :                 WorksheetType eSheetType = SHEETTYPE_EMPTYSHEET;
     254          25 :                 if( pRelation->maType == CREATE_OFFICEDOC_RELATION_TYPE( "worksheet" ) )
     255          25 :                     eSheetType = SHEETTYPE_WORKSHEET;
     256           0 :                 else if( pRelation->maType == CREATE_OFFICEDOC_RELATION_TYPE( "chartsheet" ) )
     257           0 :                     eSheetType = SHEETTYPE_CHARTSHEET;
     258           0 :                 else if( (pRelation->maType == CREATE_MSOFFICE_RELATION_TYPE( "xlMacrosheet" )) ||
     259           0 :                          (pRelation->maType == CREATE_MSOFFICE_RELATION_TYPE( "xlIntlMacrosheet" )) )
     260           0 :                     eSheetType = SHEETTYPE_MACROSHEET;
     261           0 :                 else if( pRelation->maType == CREATE_OFFICEDOC_RELATION_TYPE( "dialogsheet" ) )
     262           0 :                     eSheetType = SHEETTYPE_DIALOGSHEET;
     263             :                 OSL_ENSURE( eSheetType != SHEETTYPE_EMPTYSHEET, "WorkbookFragment::finalizeImport - unknown sheet type" );
     264          25 :                 if( eSheetType != SHEETTYPE_EMPTYSHEET )
     265             :                 {
     266             :                     // create the WorksheetGlobals object
     267          25 :                     WorksheetGlobalsRef xSheetGlob = WorksheetHelper::constructGlobals( *this, xSheetSegment, eSheetType, nCalcSheet );
     268             :                     OSL_ENSURE( xSheetGlob.get(), "WorkbookFragment::finalizeImport - missing sheet in document" );
     269          25 :                     if( xSheetGlob.get() )
     270             :                     {
     271             :                         // create the sheet fragment handler
     272          25 :                         ::rtl::Reference< WorksheetFragmentBase > xFragment;
     273          25 :                         switch( eSheetType )
     274             :                         {
     275             :                             case SHEETTYPE_WORKSHEET:
     276             :                             case SHEETTYPE_MACROSHEET:
     277             :                             case SHEETTYPE_DIALOGSHEET:
     278          25 :                                 xFragment.set( new WorksheetFragment( *xSheetGlob, aFragmentPath ) );
     279          25 :                             break;
     280             :                             case SHEETTYPE_CHARTSHEET:
     281           0 :                                 xFragment.set( new ChartsheetFragment( *xSheetGlob, aFragmentPath ) );
     282           0 :                             break;
     283             :                             default:
     284             :                                 OSL_ENSURE( false, "WorkbookFragment::finalizeImport - unexpected sheet type" );
     285             :                         }
     286             : 
     287             :                         // insert the fragment into the map
     288          25 :                         if( xFragment.is() )
     289          25 :                             aSheetFragments.push_back( SheetFragmentHandler( xSheetGlob, xFragment.get() ) );
     290          25 :                     }
     291          25 :                 }
     292          25 :             }
     293             :         }
     294             :     }
     295             : 
     296             :     // create all defined names and database ranges
     297          11 :     getDefinedNames().finalizeImport();
     298          11 :     getTables().finalizeImport();
     299             :     // load all worksheets
     300          36 :     for( SheetFragmentVector::iterator aIt = aSheetFragments.begin(), aEnd = aSheetFragments.end(); aIt != aEnd; ++aIt )
     301             :     {
     302             :         // import the sheet fragment
     303          25 :         importOoxFragment( aIt->second );
     304             :         // delete fragment object and WorkbookGlobals object, will free all allocated sheet buffers
     305          25 :         aIt->second.clear();
     306          25 :         aIt->first.reset();
     307             :     }
     308             : 
     309             :     // open the VBA project storage
     310          11 :     OUString aVbaFragmentPath = getFragmentPathFromFirstType( CREATE_MSOFFICE_RELATION_TYPE( "vbaProject" ) );
     311          11 :     if( !aVbaFragmentPath.isEmpty() )
     312             :     {
     313           0 :         Reference< XInputStream > xInStrm = getBaseFilter().openInputStream( aVbaFragmentPath );
     314           0 :         if( xInStrm.is() )
     315           0 :             setVbaProjectStorage( StorageRef( new ::oox::ole::OleStorage( getBaseFilter().getComponentContext(), xInStrm, false ) ) );
     316             :     }
     317             : 
     318             :     // final conversions, e.g. calculation settings and view settings
     319          11 :     finalizeWorkbookImport();
     320             : 
     321             :     // Recalculate formula cells.
     322          11 :     ScDocument& rDoc = getScDocument();
     323          11 :     ScDocShell* pDocSh = static_cast<ScDocShell*>(rDoc.GetDocumentShell());
     324          11 :     Reference< XComponentContext > xContext = comphelper::getProcessComponentContext();
     325             :     ScRecalcOptions nRecalcMode =
     326          11 :         static_cast<ScRecalcOptions>(officecfg::Office::Calc::Formula::Load::OOXMLRecalcMode::get(xContext));
     327          11 :     bool bHardRecalc = false;
     328          11 :     if (nRecalcMode == RECALC_ASK)
     329             :     {
     330           0 :         if (rDoc.IsUserInteractionEnabled())
     331             :         {
     332             :             // Ask the user if full re-calculation is desired.
     333             :             QueryBox aBox(
     334             :                 pDocSh->GetActiveDialogParent(), WinBits(WB_YES_NO | WB_DEF_YES),
     335           0 :                 ScGlobal::GetRscString(STR_QUERY_FORMULA_RECALC_ONLOAD_XLS));
     336           0 :             aBox.SetCheckBoxText(ScGlobal::GetRscString(STR_ALWAYS_PERFORM_SELECTED));
     337             : 
     338           0 :             sal_Int32 nRet = aBox.Execute();
     339           0 :             bHardRecalc = nRet == RET_YES;
     340             : 
     341           0 :             if (aBox.GetCheckBoxState())
     342             :             {
     343             :                 // Always perform selected action in the future.
     344           0 :                 boost::shared_ptr< comphelper::ConfigurationChanges > batch( comphelper::ConfigurationChanges::create() );
     345           0 :                 officecfg::Office::Calc::Formula::Load::OOXMLRecalcMode::set(sal_Int32(0), batch);
     346           0 :                 ScFormulaOptions aOpt = SC_MOD()->GetFormulaOptions();
     347           0 :                 aOpt.SetOOXMLRecalcOptions(bHardRecalc ? RECALC_ALWAYS : RECALC_NEVER);
     348           0 :                 SC_MOD()->SetFormulaOptions(aOpt);
     349             : 
     350           0 :                 batch->commit();
     351           0 :             }
     352             :         }
     353             :     }
     354          11 :     else if (nRecalcMode == RECALC_ALWAYS)
     355           0 :         bHardRecalc = true;
     356             : 
     357          11 :     if (bHardRecalc)
     358           0 :         pDocSh->DoHardRecalc(false);
     359             :     else
     360          11 :         rDoc.CalcFormulaTree(false, true, false);
     361          11 : }
     362             : 
     363             : // private --------------------------------------------------------------------
     364             : 
     365           0 : void WorkbookFragment::importExternalReference( const AttributeList& rAttribs )
     366             : {
     367           0 :     if( ExternalLink* pExtLink = getExternalLinks().importExternalReference( rAttribs ).get() )
     368           0 :         importExternalLinkFragment( *pExtLink );
     369           0 : }
     370             : 
     371          11 : void WorkbookFragment::importDefinedName( const AttributeList& rAttribs )
     372             : {
     373          11 :     mxCurrName = getDefinedNames().importDefinedName( rAttribs );
     374          11 : }
     375             : 
     376           0 : void WorkbookFragment::importPivotCache( const AttributeList& rAttribs )
     377             : {
     378           0 :     sal_Int32 nCacheId = rAttribs.getInteger( XML_cacheId, -1 );
     379           0 :     OUString aRelId = rAttribs.getString( R_TOKEN( id ), OUString() );
     380           0 :     importPivotCacheDefFragment( aRelId, nCacheId );
     381           0 : }
     382             : 
     383           0 : void WorkbookFragment::importExternalRef( SequenceInputStream& rStrm )
     384             : {
     385           0 :     if( ExternalLink* pExtLink = getExternalLinks().importExternalRef( rStrm ).get() )
     386           0 :         importExternalLinkFragment( *pExtLink );
     387           0 : }
     388             : 
     389           0 : void WorkbookFragment::importPivotCache( SequenceInputStream& rStrm )
     390             : {
     391           0 :     sal_Int32 nCacheId = rStrm.readInt32();
     392           0 :     OUString aRelId = BiffHelper::readString( rStrm );
     393           0 :     importPivotCacheDefFragment( aRelId, nCacheId );
     394           0 : }
     395             : 
     396           0 : void WorkbookFragment::importExternalLinkFragment( ExternalLink& rExtLink )
     397             : {
     398           0 :     OUString aFragmentPath = getFragmentPathFromRelId( rExtLink.getRelId() );
     399           0 :     if( !aFragmentPath.isEmpty() )
     400           0 :         importOoxFragment( new ExternalLinkFragment( *this, aFragmentPath, rExtLink ) );
     401           0 : }
     402             : 
     403           0 : void WorkbookFragment::importPivotCacheDefFragment( const OUString& rRelId, sal_Int32 nCacheId )
     404             : {
     405             :     // pivot caches will be imported on demand, here we just store the fragment path in the buffer
     406           0 :     getPivotCaches().registerPivotCacheFragment( nCacheId, getFragmentPathFromRelId( rRelId ) );
     407           0 : }
     408             : 
     409             : } // namespace xls
     410           9 : } // namespace oox
     411             : 
     412             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10