diff options
Diffstat (limited to 'sc/source/filter/oox/workbookhelper.cxx')
-rw-r--r-- | sc/source/filter/oox/workbookhelper.cxx | 1036 |
1 files changed, 1036 insertions, 0 deletions
diff --git a/sc/source/filter/oox/workbookhelper.cxx b/sc/source/filter/oox/workbookhelper.cxx new file mode 100644 index 000000000..1f07567f1 --- /dev/null +++ b/sc/source/filter/oox/workbookhelper.cxx @@ -0,0 +1,1036 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <workbookhelper.hxx> + +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/lang/IndexOutOfBoundsException.hpp> +#include <com/sun/star/sheet/XDatabaseRanges.hpp> +#include <com/sun/star/sheet/XSpreadsheet.hpp> +#include <com/sun/star/sheet/XSpreadsheetDocument.hpp> +#include <com/sun/star/sheet/NamedRangeFlag.hpp> +#include <com/sun/star/style/XStyleFamiliesSupplier.hpp> +#include <com/sun/star/document/XDocumentProperties.hpp> +#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> +#include <com/sun/star/document/XViewDataSupplier.hpp> +#include <o3tl/any.hxx> +#include <osl/thread.h> +#include <osl/diagnose.h> +#include <oox/helper/progressbar.hxx> +#include <oox/helper/propertyset.hxx> +#include <oox/ole/vbaproject.hxx> +#include <oox/token/properties.hxx> +#include <addressconverter.hxx> +#include <connectionsbuffer.hxx> +#include <defnamesbuffer.hxx> +#include <excelchartconverter.hxx> +#include <excelfilter.hxx> +#include <externallinkbuffer.hxx> +#include <formulaparser.hxx> +#include <pagesettings.hxx> +#include <pivotcachebuffer.hxx> +#include <pivottablebuffer.hxx> +#include <scenariobuffer.hxx> +#include <sharedstringsbuffer.hxx> +#include <stylesbuffer.hxx> +#include <tablebuffer.hxx> +#include <themebuffer.hxx> +#include <unitconverter.hxx> +#include <viewsettings.hxx> +#include <workbooksettings.hxx> +#include <worksheetbuffer.hxx> +#include <docsh.hxx> +#include <document.hxx> +#include <docuno.hxx> +#include <rangenam.hxx> +#include <tokenarray.hxx> +#include <tokenuno.hxx> +#include <dbdata.hxx> +#include <datauno.hxx> +#include <globalnames.hxx> +#include <documentimport.hxx> +#include <drwlayer.hxx> +#include <globstr.hrc> +#include <scresid.hxx> + +#include <formulabuffer.hxx> +#include <editutil.hxx> +#include <editeng/editstat.hxx> +#include <unotools/charclass.hxx> +#include <o3tl/string_view.hxx> +#include <ViewSettingsSequenceDefines.hxx> + +#include <memory> + +namespace oox::xls { + +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::document; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::sheet; +using namespace ::com::sun::star::style; +using namespace ::com::sun::star::table; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; + +using ::oox::core::FilterBase; +using ::oox::core::FragmentHandler; +using ::oox::core::XmlFilterBase; + +bool IgnoreCaseCompare::operator()( std::u16string_view rName1, std::u16string_view rName2 ) const +{ + // TODO: compare with collator + return o3tl::compareToIgnoreAsciiCase(rName1, rName2 ) < 0; +} + +class WorkbookGlobals +{ +public: + // noncopyable ------------------------------------------------------------ + + WorkbookGlobals(const WorkbookGlobals&) = delete; + const WorkbookGlobals& operator=(const WorkbookGlobals&) = delete; + + explicit WorkbookGlobals( ExcelFilter& rFilter ); + ~WorkbookGlobals(); + + /** Returns true, if this helper refers to a valid document. */ + bool isValid() const { return mxDoc.is(); } + + // filter ----------------------------------------------------------------- + + /** Returns the base filter object (base class of all filters). */ + FilterBase& getBaseFilter() const { return mrBaseFilter; } + /** Returns the filter progress bar. */ + SegmentProgressBar& getProgressBar() const { return *mxProgressBar; } + /** Returns the VBA project storage. */ + const StorageRef& getVbaProjectStorage() const { return mxVbaPrjStrg; } + /** Returns the index of the current Calc sheet, if filter currently processes a sheet. */ + sal_Int16 getCurrentSheetIndex() const { return mnCurrSheet; } + /** Returns true when reading a file generated by a known good generator. */ + bool isGeneratorKnownGood() const { return mbGeneratorKnownGood; } + + /** Sets the VBA project storage used to import VBA source code and forms. */ + void setVbaProjectStorage( const StorageRef& rxVbaPrjStrg ) { mxVbaPrjStrg = rxVbaPrjStrg; } + /** Sets the index of the current Calc sheet, if filter currently processes a sheet. */ + void setCurrentSheetIndex( SCTAB nSheet ) { mnCurrSheet = nSheet; } + + // document model --------------------------------------------------------- + + ScEditEngineDefaulter& getEditEngine() const + { + return *mxEditEngine; + } + + ScDocument& getScDocument() { return *mpDoc; } + + ScDocumentImport& getDocImport(); + + /** Returns a reference to the source/target spreadsheet document model. */ + const Reference< XSpreadsheetDocument >& getDocument() const { return mxDoc; } + /** Returns the cell or page styles container from the Calc document. */ + Reference< XNameContainer > getStyleFamily( bool bPageStyles ) const; + /** Returns the specified cell or page style from the Calc document. */ + Reference< XStyle > getStyleObject( const OUString& rStyleName, bool bPageStyle ) const; + /** Creates and returns a defined name on-the-fly in the Calc document. */ + WorkbookHelper::RangeDataRet createNamedRangeObject( OUString& orName, const Sequence< FormulaToken>& rTokens, sal_Int32 nIndex, sal_Int32 nNameFlags, bool bHidden ); + /** Creates and returns a defined name on the-fly in the correct Calc sheet. */ + WorkbookHelper::RangeDataRet createLocalNamedRangeObject( OUString& orName, const Sequence< FormulaToken>& rTokens, sal_Int32 nIndex, sal_Int32 nNameFlags, sal_Int32 nTab, bool bHidden ); + /** Creates and returns a database range on-the-fly in the Calc document. */ + Reference< XDatabaseRange > createDatabaseRangeObject( OUString& orName, const ScRange& rRangeAddr ); + /** Creates and returns an unnamed database range on-the-fly in the Calc document. */ + Reference< XDatabaseRange > createUnnamedDatabaseRangeObject( const ScRange& rRangeAddr ); + /** Finds the (already existing) database range of the given formula token index. */ + ScDBData* findDatabaseRangeByIndex( sal_uInt16 nIndex ); + /** Creates and returns a com.sun.star.style.Style object for cells or pages. */ + Reference< XStyle > createStyleObject( OUString& orStyleName, bool bPageStyle ); + /** Helper to switch chart data table - specifically for xlsx imports */ + void useInternalChartDataTable( bool bInternal ); + + // buffers ---------------------------------------------------------------- + + FormulaBuffer& getFormulaBuffer() const { return *mxFormulaBuffer; } + /** Returns the global workbook settings object. */ + WorkbookSettings& getWorkbookSettings() const { return *mxWorkbookSettings; } + /** Returns the workbook and sheet view settings object. */ + ViewSettings& getViewSettings() const { return *mxViewSettings; } + /** Returns the worksheet buffer containing sheet names and properties. */ + WorksheetBuffer& getWorksheets() const { return *mxWorksheets; } + /** Returns the office theme object read from the theme substorage. */ + ThemeBuffer& getTheme() const { return *mxTheme; } + /** Returns all cell formatting objects read from the styles substream. */ + StylesBuffer& getStyles() const { return *mxStyles; } + /** Returns the shared strings read from the shared strings substream. */ + SharedStringsBuffer& getSharedStrings() const { return *mxSharedStrings; } + /** Returns the external links read from the external links substream. */ + ExternalLinkBuffer& getExternalLinks() const { return *mxExtLinks; } + /** Returns the defined names read from the workbook globals. */ + DefinedNamesBuffer& getDefinedNames() const { return *mxDefNames; } + /** Returns the tables collection (equivalent to Calc's database ranges). */ + TableBuffer& getTables() const { return *mxTables; } + /** Returns the scenarios collection. */ + ScenarioBuffer& getScenarios() const { return *mxScenarios; } + /** Returns the collection of external data connections. */ + ConnectionsBuffer& getConnections() const { return *mxConnections; } + /** Returns the collection of pivot caches. */ + PivotCacheBuffer& getPivotCaches() const { return *mxPivotCaches; } + /** Returns the collection of pivot tables. */ + PivotTableBuffer& getPivotTables() { return *mxPivotTables; } + + // converters ------------------------------------------------------------- + + /** Returns a shared import formula parser. */ + FormulaParser& getFormulaParser() const { return *mxFmlaParser; } + /** Returns an unshared import formula parser. */ + FormulaParser* createFormulaParser() { return new FormulaParser(*this); } + /** Returns the measurement unit converter. */ + UnitConverter& getUnitConverter() const { return *mxUnitConverter; } + /** Returns the converter for string to cell address/range conversion. */ + AddressConverter& getAddressConverter() const { return *mxAddrConverter; } + /** Returns the chart object converter. */ + oox::drawingml::chart::ChartConverter* getChartConverter() const { return mxChartConverter.get(); } + /** Returns the page/print settings converter. */ + PageSettingsConverter& getPageSettingsConverter() const { return *mxPageSettConverter; } + + // OOXML/BIFF12 specific -------------------------------------------------- + + /** Returns the base OOXML/BIFF12 filter object. */ + XmlFilterBase& getOoxFilter() const { return *mpOoxFilter; } + + // BIFF2-BIFF8 specific --------------------------------------------------- + + /** Returns the text encoding used to import/export byte strings. */ + rtl_TextEncoding getTextEncoding() const { return meTextEnc; } + +private: + /** Initializes some basic members and sets needed document properties. */ + void initialize(); + /** Finalizes the filter process (sets some needed document properties). */ + void finalize(); + +private: + typedef ::std::unique_ptr< ScEditEngineDefaulter > EditEngineDefaulterPtr; + typedef ::std::unique_ptr< FormulaBuffer > FormulaBufferPtr; + typedef ::std::unique_ptr< SegmentProgressBar > ProgressBarPtr; + typedef ::std::unique_ptr< WorkbookSettings > WorkbookSettPtr; + typedef ::std::unique_ptr< ViewSettings > ViewSettingsPtr; + typedef ::std::unique_ptr< WorksheetBuffer > WorksheetBfrPtr; + typedef ::std::shared_ptr< ThemeBuffer > ThemeBfrRef; + typedef ::std::unique_ptr< StylesBuffer > StylesBfrPtr; + typedef ::std::unique_ptr< SharedStringsBuffer > SharedStrBfrPtr; + typedef ::std::unique_ptr< ExternalLinkBuffer > ExtLinkBfrPtr; + typedef ::std::unique_ptr< DefinedNamesBuffer > DefNamesBfrPtr; + typedef ::std::unique_ptr< TableBuffer > TableBfrPtr; + typedef ::std::unique_ptr< ScenarioBuffer > ScenarioBfrPtr; + typedef ::std::unique_ptr< ConnectionsBuffer > ConnectionsBfrPtr; + typedef ::std::unique_ptr< PivotCacheBuffer > PivotCacheBfrPtr; + typedef ::std::unique_ptr< PivotTableBuffer > PivotTableBfrPtr; + typedef ::std::unique_ptr< FormulaParser > FormulaParserPtr; + typedef ::std::unique_ptr< UnitConverter > UnitConvPtr; + typedef ::std::unique_ptr< AddressConverter > AddressConvPtr; + typedef ::std::unique_ptr< oox::drawingml::chart::ChartConverter > ExcelChartConvPtr; + typedef ::std::unique_ptr< PageSettingsConverter > PageSettConvPtr; + + OUString maCellStyles; /// Style family name for cell styles. + OUString maPageStyles; /// Style family name for page styles. + OUString maCellStyleServ; /// Service name for a cell style. + OUString maPageStyleServ; /// Service name for a page style. + Reference< XSpreadsheetDocument > mxDoc; /// Document model. + FilterBase& mrBaseFilter; /// Base filter object. + ExcelFilter& mrExcelFilter; /// Base object for registration of this structure. + ProgressBarPtr mxProgressBar; /// The progress bar. + StorageRef mxVbaPrjStrg; /// Storage containing the VBA project. + sal_Int16 mnCurrSheet; /// Current sheet index in Calc document. + bool mbGeneratorKnownGood; /// Whether reading a file generated by Excel or Calc. + + // buffers + FormulaBufferPtr mxFormulaBuffer; + WorkbookSettPtr mxWorkbookSettings; /// Global workbook settings. + ViewSettingsPtr mxViewSettings; /// Workbook and sheet view settings. + WorksheetBfrPtr mxWorksheets; /// Sheet info buffer. + ThemeBfrRef mxTheme; /// Formatting theme from theme substream. + StylesBfrPtr mxStyles; /// All cell style objects from styles substream. + SharedStrBfrPtr mxSharedStrings; /// All strings from shared strings substream. + ExtLinkBfrPtr mxExtLinks; /// All external links. + DefNamesBfrPtr mxDefNames; /// All defined names. + TableBfrPtr mxTables; /// All tables (database ranges). + ScenarioBfrPtr mxScenarios; /// All scenarios. + ConnectionsBfrPtr mxConnections; /// All external data connections. + PivotCacheBfrPtr mxPivotCaches; /// All pivot caches in the document. + PivotTableBfrPtr mxPivotTables; /// All pivot tables in the document. + + // converters + FormulaParserPtr mxFmlaParser; /// Import formula parser. + UnitConvPtr mxUnitConverter; /// General unit converter. + AddressConvPtr mxAddrConverter; /// Cell address and cell range address converter. + ExcelChartConvPtr mxChartConverter; /// Chart object converter. + PageSettConvPtr mxPageSettConverter; /// Page/print settings converter. + + EditEngineDefaulterPtr mxEditEngine; + + // OOXML/BIFF12 specific + XmlFilterBase* mpOoxFilter; /// Base OOXML/BIFF12 filter object. + + // BIFF2-BIFF8 specific + rtl_TextEncoding meTextEnc; /// BIFF byte string text encoding. + ScDocument* mpDoc; + ScDocShell* mpDocShell; + std::unique_ptr<ScDocumentImport> mxDocImport; +}; + +WorkbookGlobals::WorkbookGlobals( ExcelFilter& rFilter ) : + mrBaseFilter( rFilter ), + mrExcelFilter( rFilter ), + mpOoxFilter( &rFilter ), + mpDoc(nullptr), + mpDocShell(nullptr) +{ + // register at the filter, needed for virtual callbacks (even during construction) + mrExcelFilter.registerWorkbookGlobals( *this ); + initialize(); +} + +WorkbookGlobals::~WorkbookGlobals() +{ + finalize(); + mrExcelFilter.unregisterWorkbookGlobals(); +} + +ScDocumentImport& WorkbookGlobals::getDocImport() +{ + return *mxDocImport; +} + +Reference< XNameContainer > WorkbookGlobals::getStyleFamily( bool bPageStyles ) const +{ + Reference< XNameContainer > xStylesNC; + try + { + Reference< XStyleFamiliesSupplier > xFamiliesSup( mxDoc, UNO_QUERY_THROW ); + Reference< XNameAccess > xFamiliesNA( xFamiliesSup->getStyleFamilies(), UNO_SET_THROW ); + xStylesNC.set( xFamiliesNA->getByName( bPageStyles ? maPageStyles : maCellStyles ), UNO_QUERY ); + } + catch( Exception& ) + { + } + OSL_ENSURE( xStylesNC.is(), "WorkbookGlobals::getStyleFamily - cannot access style family" ); + return xStylesNC; +} + +Reference< XStyle > WorkbookGlobals::getStyleObject( const OUString& rStyleName, bool bPageStyle ) const +{ + Reference< XStyle > xStyle; + try + { + Reference< XNameContainer > xStylesNC( getStyleFamily( bPageStyle ), UNO_SET_THROW ); + xStyle.set( xStylesNC->getByName( rStyleName ), UNO_QUERY ); + } + catch( Exception& ) + { + } + OSL_ENSURE( xStyle.is(), "WorkbookGlobals::getStyleObject - cannot access style object" ); + return xStyle; +} + +namespace { + +WorkbookHelper::RangeDataRet lcl_addNewByNameAndTokens( ScDocument& rDoc, ScRangeName* pNames, const OUString& rName, const Sequence<FormulaToken>& rTokens, sal_Int16 nIndex, sal_Int32 nUnoType, bool bHidden ) +{ + bool bDone = false; + ScRangeData::Type nNewType = ScRangeData::Type::Name; + if ( nUnoType & NamedRangeFlag::FILTER_CRITERIA ) nNewType |= ScRangeData::Type::Criteria; + if ( nUnoType & NamedRangeFlag::PRINT_AREA ) nNewType |= ScRangeData::Type::PrintArea; + if ( nUnoType & NamedRangeFlag::COLUMN_HEADER ) nNewType |= ScRangeData::Type::ColHeader; + if ( nUnoType & NamedRangeFlag::ROW_HEADER ) nNewType |= ScRangeData::Type::RowHeader; + ScTokenArray aTokenArray(rDoc); + (void)ScTokenConversion::ConvertToTokenArray( rDoc, aTokenArray, rTokens ); + ScRangeData* pNew = new ScRangeData( rDoc, rName, aTokenArray, ScAddress(), nNewType ); + pNew->GuessPosition(); + if ( nIndex ) + pNew->SetIndex( nIndex ); + // create but not insert hidden FILTER_CRITERIA named ranges to ScRangeName + if ( bHidden && nNewType == ScRangeData::Type::Criteria ) + { + return WorkbookHelper::RangeDataRet(pNew, true); + } + if ( pNames->insert(pNew) ) + bDone = true; + if (!bDone) + { + delete pNew; + throw RuntimeException(); + } + return WorkbookHelper::RangeDataRet(pNew, false); +} + +OUString findUnusedName( const ScRangeName* pRangeName, const OUString& rSuggestedName ) +{ + OUString aNewName = rSuggestedName; + sal_Int32 nIndex = 0; + while(pRangeName->findByUpperName(ScGlobal::getCharClass().uppercase(aNewName))) + aNewName = rSuggestedName + OUStringChar('_') + OUString::number( nIndex++ ); + + return aNewName; +} + +} + +WorkbookHelper::RangeDataRet WorkbookGlobals::createNamedRangeObject( + OUString& orName, const Sequence< FormulaToken>& rTokens, sal_Int32 nIndex, sal_Int32 nNameFlags, bool bHidden ) +{ + // create the name and insert it into the Calc document + WorkbookHelper::RangeDataRet aScRangeData(nullptr, false); + if( !orName.isEmpty() ) + { + ScDocument& rDoc = getScDocument(); + ScRangeName* pNames = rDoc.GetRangeName(); + // find an unused name + orName = findUnusedName( pNames, orName ); + // create the named range + aScRangeData = lcl_addNewByNameAndTokens( rDoc, pNames, orName, rTokens, nIndex, nNameFlags, bHidden ); + } + return aScRangeData; +} + +WorkbookHelper::RangeDataRet WorkbookGlobals::createLocalNamedRangeObject( + OUString& orName, const Sequence< FormulaToken >& rTokens, sal_Int32 nIndex, sal_Int32 nNameFlags, sal_Int32 nTab, bool bHidden ) +{ + // create the name and insert it into the Calc document + WorkbookHelper::RangeDataRet aScRangeData(nullptr, false); + if( !orName.isEmpty() ) + { + ScDocument& rDoc = getScDocument(); + ScRangeName* pNames = rDoc.GetRangeName( nTab ); + if(!pNames) + throw RuntimeException("invalid sheet index used"); + // find an unused name + orName = findUnusedName( pNames, orName ); + // create the named range + aScRangeData = lcl_addNewByNameAndTokens( rDoc, pNames, orName, rTokens, nIndex, nNameFlags, bHidden ); + } + return aScRangeData; +} + +Reference< XDatabaseRange > WorkbookGlobals::createDatabaseRangeObject( OUString& orName, const ScRange& rRangeAddr ) +{ + // validate cell range + ScRange aDestRange = rRangeAddr; + bool bValidRange = getAddressConverter().validateCellRange( aDestRange, true, true ); + + // create database range and insert it into the Calc document + Reference< XDatabaseRange > xDatabaseRange; + if( bValidRange && !orName.isEmpty() ) try + { + // find an unused name + PropertySet aDocProps( mxDoc ); + Reference< XDatabaseRanges > xDatabaseRanges( aDocProps.getAnyProperty( PROP_DatabaseRanges ), UNO_QUERY_THROW ); + orName = ContainerHelper::getUnusedName( xDatabaseRanges, orName, '_' ); + // create the database range + CellRangeAddress aApiRange( aDestRange.aStart.Tab(), aDestRange.aStart.Col(), aDestRange.aStart.Row(), + aDestRange.aEnd.Col(), aDestRange.aEnd.Row() ); + xDatabaseRanges->addNewByName( orName, aApiRange ); + xDatabaseRange.set( xDatabaseRanges->getByName( orName ), UNO_QUERY ); + } + catch( Exception& ) + { + } + OSL_ENSURE( xDatabaseRange.is(), "WorkbookGlobals::createDatabaseRangeObject - cannot create database range" ); + return xDatabaseRange; +} + +Reference< XDatabaseRange > WorkbookGlobals::createUnnamedDatabaseRangeObject( const ScRange& rRangeAddr ) +{ + // validate cell range + ScRange aDestRange = rRangeAddr; + bool bValidRange = getAddressConverter().validateCellRange( aDestRange, true, true ); + + // create database range and insert it into the Calc document + Reference< XDatabaseRange > xDatabaseRange; + if( bValidRange ) try + { + ScDocument& rDoc = getScDocument(); + if( rDoc.GetTableCount() <= aDestRange.aStart.Tab() ) + throw css::lang::IndexOutOfBoundsException(); + std::unique_ptr<ScDBData> pNewDBData(new ScDBData( STR_DB_LOCAL_NONAME, aDestRange.aStart.Tab(), + aDestRange.aStart.Col(), aDestRange.aStart.Row(), + aDestRange.aEnd.Col(), aDestRange.aEnd.Row() )); + rDoc.SetAnonymousDBData( aDestRange.aStart.Tab() , std::move(pNewDBData) ); + ScDocShell* pDocSh = static_cast< ScDocShell* >(rDoc.GetDocumentShell()); + xDatabaseRange.set(new ScDatabaseRangeObj(pDocSh, aDestRange.aStart.Tab())); + } + catch( Exception& ) + { + } + OSL_ENSURE( xDatabaseRange.is(), "WorkbookData::createDatabaseRangeObject - cannot create database range" ); + return xDatabaseRange; +} + +ScDBData* WorkbookGlobals::findDatabaseRangeByIndex( sal_uInt16 nIndex ) +{ + ScDBCollection* pDBCollection = getScDocument().GetDBCollection(); + if (!pDBCollection) + return nullptr; + return pDBCollection->getNamedDBs().findByIndex( nIndex ); +} + +Reference< XStyle > WorkbookGlobals::createStyleObject( OUString& orStyleName, bool bPageStyle ) +{ + Reference< XStyle > xStyle; + try + { + Reference< XNameContainer > xStylesNC( getStyleFamily( bPageStyle ), UNO_SET_THROW ); + xStyle.set( mrBaseFilter.getModelFactory()->createInstance( bPageStyle ? maPageStyleServ : maCellStyleServ ), UNO_QUERY_THROW ); + orStyleName = ContainerHelper::insertByUnusedName( xStylesNC, orStyleName, ' ', Any( xStyle ) ); + } + catch( Exception& ) + { + } + OSL_ENSURE( xStyle.is(), "WorkbookGlobals::createStyleObject - cannot create style" ); + return xStyle; +} + +void WorkbookGlobals::useInternalChartDataTable( bool bInternal ) +{ + if( bInternal ) + mxChartConverter.reset( new oox::drawingml::chart::ChartConverter() ); + else + mxChartConverter.reset( new ExcelChartConverter( *this ) ); +} + +// BIFF specific -------------------------------------------------------------- + +// private -------------------------------------------------------------------- + +void WorkbookGlobals::initialize() +{ + maCellStyles = "CellStyles"; + maPageStyles = "PageStyles"; + maCellStyleServ = "com.sun.star.style.CellStyle"; + maPageStyleServ = "com.sun.star.style.PageStyle"; + mnCurrSheet = -1; + mbGeneratorKnownGood = false; + meTextEnc = osl_getThreadTextEncoding(); + + // the spreadsheet document + mxDoc.set( mrBaseFilter.getModel(), UNO_QUERY ); + OSL_ENSURE( mxDoc.is(), "WorkbookGlobals::initialize - no spreadsheet document" ); + + if (mxDoc) + { + ScModelObj* pModel = dynamic_cast<ScModelObj*>(mxDoc.get()); + if (pModel) + mpDocShell = static_cast<ScDocShell*>(pModel->GetEmbeddedObject()); + if (mpDocShell) + mpDoc = &mpDocShell->GetDocument(); + } + + if (!mpDoc) + throw RuntimeException("Workbookhelper::getScDocument(): Failed to access ScDocument from model"); + + Reference< XDocumentPropertiesSupplier > xPropSupplier( mxDoc, UNO_QUERY); + Reference< XDocumentProperties > xDocProps = xPropSupplier->getDocumentProperties(); + const OUString aGenerator( xDocProps->getGenerator()); + + if (aGenerator.startsWithIgnoreAsciiCase("Microsoft")) + { + mbGeneratorKnownGood = true; + ScCalcConfig aCalcConfig = mpDoc->GetCalcConfig(); + aCalcConfig.SetStringRefSyntax( formula::FormulaGrammar::CONV_XL_A1 ) ; + mpDoc->SetCalcConfig(aCalcConfig); + } + else if (aGenerator.startsWithIgnoreAsciiCase("LibreOffice")) + { + mbGeneratorKnownGood = true; + } + + mxDocImport.reset(new ScDocumentImport(*mpDoc)); + + mxFormulaBuffer.reset( new FormulaBuffer( *this ) ); + mxWorkbookSettings.reset( new WorkbookSettings( *this ) ); + mxViewSettings.reset( new ViewSettings( *this ) ); + mxWorksheets.reset( new WorksheetBuffer( *this ) ); + mxTheme = std::make_shared<ThemeBuffer>( *this ); + mxStyles.reset( new StylesBuffer( *this ) ); + mxSharedStrings.reset( new SharedStringsBuffer( *this ) ); + mxExtLinks.reset( new ExternalLinkBuffer( *this ) ); + mxDefNames.reset( new DefinedNamesBuffer( *this ) ); + mxTables.reset( new TableBuffer( *this ) ); + mxScenarios.reset( new ScenarioBuffer( *this ) ); + mxConnections.reset( new ConnectionsBuffer( *this ) ); + mxPivotCaches.reset( new PivotCacheBuffer( *this ) ); + mxPivotTables.reset( new PivotTableBuffer( *this ) ); + + mxUnitConverter.reset( new UnitConverter( *this ) ); + mxAddrConverter.reset( new AddressConverter( *this ) ); + mxChartConverter.reset( new ExcelChartConverter( *this ) ); + mxPageSettConverter.reset( new PageSettingsConverter( *this ) ); + + // initialise edit engine + ScDocument& rDoc = getScDocument(); + mxEditEngine.reset( new ScEditEngineDefaulter( rDoc.GetEnginePool() ) ); + mxEditEngine->SetRefMapMode(MapMode(MapUnit::Map100thMM)); + mxEditEngine->SetEditTextObjectPool( rDoc.GetEditPool() ); + mxEditEngine->SetUpdateLayout( false ); + mxEditEngine->EnableUndo( false ); + mxEditEngine->SetControlWord( mxEditEngine->GetControlWord() & ~EEControlBits::ALLOWBIGOBJS ); + + // set some document properties needed during import + if( mrBaseFilter.isImportFilter() ) + { + // enable editing read-only documents (e.g. from read-only files) + mpDoc->EnableChangeReadOnly(true); + // #i76026# disable Undo while loading the document + mpDoc->EnableUndo(false); + // #i79826# disable calculating automatic row height while loading the document + mpDoc->LockAdjustHeight(); + // disable automatic update of linked sheets and DDE links + mpDoc->EnableExecuteLink(false); + + mxProgressBar.reset( new SegmentProgressBar( mrBaseFilter.getStatusIndicator(), ScResId(STR_LOAD_DOC) ) ); + mxFmlaParser.reset( createFormulaParser() ); + + //prevent unnecessary broadcasts and "half way listeners" as + //is done in ScDocShell::BeforeXMLLoading() for ods + mpDoc->SetInsertingFromOtherDoc(true); + } + else if( mrBaseFilter.isExportFilter() ) + { + mxProgressBar.reset( new SegmentProgressBar( mrBaseFilter.getStatusIndicator(), ScResId(STR_SAVE_DOC) ) ); + } +} + +void WorkbookGlobals::finalize() +{ + // set some document properties needed after import + if( !mrBaseFilter.isImportFilter() ) + return; + + // #i74668# do not insert default sheets + mpDocShell->SetEmpty(false); + // enable automatic update of linked sheets and DDE links + mpDoc->EnableExecuteLink(true); + // #i79826# enable updating automatic row height after loading the document + mpDoc->UnlockAdjustHeight(); + + // #i76026# enable Undo after loading the document + mpDoc->EnableUndo(true); + + // disable editing read-only documents (e.g. from read-only files) + mpDoc->EnableChangeReadOnly(false); + // #111099# open forms in alive mode (has no effect, if no controls in document) + ScDrawLayer* pModel = mpDoc->GetDrawLayer(); + if (pModel) + pModel->SetOpenInDesignMode(false); +} + + +WorkbookHelper::~WorkbookHelper() +{ +} + +/*static*/ WorkbookGlobalsRef WorkbookHelper::constructGlobals( ExcelFilter& rFilter ) +{ + WorkbookGlobalsRef xBookGlob = std::make_shared<WorkbookGlobals>( rFilter ); + if( !xBookGlob->isValid() ) + xBookGlob.reset(); + return xBookGlob; +} + +// filter --------------------------------------------------------------------- + +FilterBase& WorkbookHelper::getBaseFilter() const +{ + return mrBookGlob.getBaseFilter(); +} + +SegmentProgressBar& WorkbookHelper::getProgressBar() const +{ + return mrBookGlob.getProgressBar(); +} + +sal_Int16 WorkbookHelper::getCurrentSheetIndex() const +{ + return mrBookGlob.getCurrentSheetIndex(); +} + +bool WorkbookHelper::isGeneratorKnownGood() const +{ + return mrBookGlob.isGeneratorKnownGood(); +} + +void WorkbookHelper::setVbaProjectStorage( const StorageRef& rxVbaPrjStrg ) +{ + mrBookGlob.setVbaProjectStorage( rxVbaPrjStrg ); +} + +void WorkbookHelper::setCurrentSheetIndex( SCTAB nSheet ) +{ + mrBookGlob.setCurrentSheetIndex( nSheet ); +} + +void WorkbookHelper::finalizeWorkbookImport() +{ + // workbook settings, document and sheet view settings + mrBookGlob.getWorkbookSettings().finalizeImport(); + mrBookGlob.getViewSettings().finalizeImport(); + + // Import the VBA project (after finalizing workbook settings which + // contains the workbook code name). Do it before processing formulas in + // order to correctly resolve VBA custom function names. + StorageRef xVbaPrjStrg = mrBookGlob.getVbaProjectStorage(); + if( xVbaPrjStrg && xVbaPrjStrg->isStorage() ) + getBaseFilter().getVbaProject().importModulesAndForms( *xVbaPrjStrg, getBaseFilter().getGraphicHelper() ); + + // need to import formulas before scenarios + mrBookGlob.getFormulaBuffer().finalizeImport(); + + // Insert all pivot tables. Must be done after loading all sheets and + // formulas, because data pilots expect existing source data on + // creation. + getPivotTables().finalizeImport(); + + /* Insert scenarios after all sheet processing is done, because new hidden + sheets are created for scenarios which would confuse code that relies + on certain sheet indexes. Must be done after pivot tables too. */ + mrBookGlob.getScenarios().finalizeImport(); + + /* Set 'Default' page style to automatic page numbering (default is manual + number 1). Otherwise hidden sheets (e.g. for scenarios) which have + 'Default' page style will break automatic page numbering for following + sheets. Automatic numbering is set by passing the value 0. */ + PropertySet aDefPageStyle( getStyleObject( "Default", true ) ); + aDefPageStyle.setProperty< sal_Int16 >( PROP_FirstPageNumber, 0 ); + + // Has any string ref syntax been imported? + // If not, we need to take action + ScCalcConfig aCalcConfig = getScDocument().GetCalcConfig(); + + if ( !aCalcConfig.mbHasStringRefSyntax ) + { + aCalcConfig.meStringRefAddressSyntax = formula::FormulaGrammar::CONV_A1_XL_A1; + getScDocument().SetCalcConfig(aCalcConfig); + } + + // set selected sheet and positionleft/positiontop for OLE objects + Reference<XViewDataSupplier> xViewDataSupplier(getDocument(), UNO_QUERY); + if (!xViewDataSupplier.is()) + return; + + Reference<XIndexAccess> xIndexAccess(xViewDataSupplier->getViewData()); + if (!(xIndexAccess.is() && xIndexAccess->getCount() > 0)) + return; + + Sequence< PropertyValue > aSeq; + if (!(xIndexAccess->getByIndex(0) >>= aSeq)) + return; + + OUString sTabName; + Reference< XNameAccess > xSheetsNC; + for (const auto& rProp : std::as_const(aSeq)) + { + OUString sName(rProp.Name); + if (sName == SC_ACTIVETABLE) + { + if(rProp.Value >>= sTabName) + { + SCTAB nTab(0); + if (getScDocument().GetTable(sTabName, nTab)) + getScDocument().SetVisibleTab(nTab); + } + } + else if (sName == SC_TABLES) + { + rProp.Value >>= xSheetsNC; + } + } + if (!(xSheetsNC.is() && xSheetsNC->hasByName(sTabName))) + return; + + Sequence<PropertyValue> aProperties; + Any aAny = xSheetsNC->getByName(sTabName); + if ( !(aAny >>= aProperties) ) + return; + + for (const auto& rProp : std::as_const(aProperties)) + { + OUString sName(rProp.Name); + if (sName == SC_POSITIONLEFT) + { + SCCOL nPosLeft = *o3tl::doAccess<SCCOL>(rProp.Value); + getScDocument().SetPosLeft(nPosLeft); + } + else if (sName == SC_POSITIONTOP) + { + SCROW nPosTop = *o3tl::doAccess<SCROW>(rProp.Value); + getScDocument().SetPosTop(nPosTop); + } + } +} + +// document model ------------------------------------------------------------- + +ScDocument& WorkbookHelper::getScDocument() +{ + return mrBookGlob.getScDocument(); +} + +const ScDocument& WorkbookHelper::getScDocument() const +{ + return mrBookGlob.getScDocument(); +} + +ScDocumentImport& WorkbookHelper::getDocImport() +{ + return mrBookGlob.getDocImport(); +} + +const ScDocumentImport& WorkbookHelper::getDocImport() const +{ + return mrBookGlob.getDocImport(); +} + +ScEditEngineDefaulter& WorkbookHelper::getEditEngine() const +{ + return mrBookGlob.getEditEngine(); +} + +const Reference< XSpreadsheetDocument > & WorkbookHelper::getDocument() const +{ + return mrBookGlob.getDocument(); +} + +Reference< XSpreadsheet > WorkbookHelper::getSheetFromDoc( sal_Int32 nSheet ) const +{ + Reference< XSpreadsheet > xSheet; + try + { + Reference< XIndexAccess > xSheetsIA( getDocument()->getSheets(), UNO_QUERY_THROW ); + xSheet.set( xSheetsIA->getByIndex( nSheet ), UNO_QUERY_THROW ); + } + catch( Exception& ) + { + } + return xSheet; +} + +Reference< XSpreadsheet > WorkbookHelper::getSheetFromDoc( const OUString& rSheet ) const +{ + Reference< XSpreadsheet > xSheet; + try + { + Reference< XNameAccess > xSheetsNA( getDocument()->getSheets(), UNO_QUERY_THROW ); + xSheet.set( xSheetsNA->getByName( rSheet ), UNO_QUERY ); + } + catch( Exception& ) + { + } + return xSheet; +} + +Reference< XCellRange > WorkbookHelper::getCellRangeFromDoc( const ScRange& rRange ) const +{ + Reference< XCellRange > xRange; + try + { + Reference< XSpreadsheet > xSheet( getSheetFromDoc( rRange.aStart.Tab() ), UNO_SET_THROW ); + xRange = xSheet->getCellRangeByPosition( rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row() ); + } + catch( Exception& ) + { + } + return xRange; +} + +Reference< XNameContainer > WorkbookHelper::getCellStyleFamily() const +{ + return mrBookGlob.getStyleFamily( false/*bPageStyles*/ ); +} + +Reference< XStyle > WorkbookHelper::getStyleObject( const OUString& rStyleName, bool bPageStyle ) const +{ + return mrBookGlob.getStyleObject( rStyleName, bPageStyle ); +} + +WorkbookHelper::RangeDataRet WorkbookHelper::createNamedRangeObject( OUString& orName, const Sequence< FormulaToken>& rTokens, sal_Int32 nIndex, sal_Int32 nNameFlags, bool bHidden ) const +{ + return mrBookGlob.createNamedRangeObject( orName, rTokens, nIndex, nNameFlags, bHidden ); +} + +WorkbookHelper::RangeDataRet WorkbookHelper::createLocalNamedRangeObject( OUString& orName, const Sequence< FormulaToken>& rTokens, sal_Int32 nIndex, sal_Int32 nNameFlags, sal_Int32 nTab, bool bHidden ) const +{ + return mrBookGlob.createLocalNamedRangeObject( orName, rTokens, nIndex, nNameFlags, nTab, bHidden ); +} + +Reference< XDatabaseRange > WorkbookHelper::createDatabaseRangeObject( OUString& orName, const ScRange& rRangeAddr ) const +{ + return mrBookGlob.createDatabaseRangeObject( orName, rRangeAddr ); +} + +Reference< XDatabaseRange > WorkbookHelper::createUnnamedDatabaseRangeObject( const ScRange& rRangeAddr ) const +{ + return mrBookGlob.createUnnamedDatabaseRangeObject( rRangeAddr ); +} + +ScDBData* WorkbookHelper::findDatabaseRangeByIndex( sal_uInt16 nIndex ) const +{ + return mrBookGlob.findDatabaseRangeByIndex( nIndex ); +} + +Reference< XStyle > WorkbookHelper::createStyleObject( OUString& orStyleName, bool bPageStyle ) const +{ + return mrBookGlob.createStyleObject( orStyleName, bPageStyle ); +} + +// buffers -------------------------------------------------------------------- + +FormulaBuffer& WorkbookHelper::getFormulaBuffer() const +{ + return mrBookGlob.getFormulaBuffer(); +} + +WorkbookSettings& WorkbookHelper::getWorkbookSettings() const +{ + return mrBookGlob.getWorkbookSettings(); +} + +ViewSettings& WorkbookHelper::getViewSettings() const +{ + return mrBookGlob.getViewSettings(); +} + +WorksheetBuffer& WorkbookHelper::getWorksheets() const +{ + return mrBookGlob.getWorksheets(); +} + +ThemeBuffer& WorkbookHelper::getTheme() const +{ + return mrBookGlob.getTheme(); +} + +StylesBuffer& WorkbookHelper::getStyles() const +{ + return mrBookGlob.getStyles(); +} + +SharedStringsBuffer& WorkbookHelper::getSharedStrings() const +{ + return mrBookGlob.getSharedStrings(); +} + +ExternalLinkBuffer& WorkbookHelper::getExternalLinks() const +{ + return mrBookGlob.getExternalLinks(); +} + +DefinedNamesBuffer& WorkbookHelper::getDefinedNames() const +{ + return mrBookGlob.getDefinedNames(); +} + +TableBuffer& WorkbookHelper::getTables() const +{ + return mrBookGlob.getTables(); +} + +ScenarioBuffer& WorkbookHelper::getScenarios() const +{ + return mrBookGlob.getScenarios(); +} + +ConnectionsBuffer& WorkbookHelper::getConnections() const +{ + return mrBookGlob.getConnections(); +} + +PivotCacheBuffer& WorkbookHelper::getPivotCaches() const +{ + return mrBookGlob.getPivotCaches(); +} + +PivotTableBuffer& WorkbookHelper::getPivotTables() const +{ + return mrBookGlob.getPivotTables(); +} + +// converters ----------------------------------------------------------------- + +FormulaParser& WorkbookHelper::getFormulaParser() const +{ + return mrBookGlob.getFormulaParser(); +} + +FormulaParser* WorkbookHelper::createFormulaParser() const +{ + return mrBookGlob.createFormulaParser(); +} + +UnitConverter& WorkbookHelper::getUnitConverter() const +{ + return mrBookGlob.getUnitConverter(); +} + +AddressConverter& WorkbookHelper::getAddressConverter() const +{ + return mrBookGlob.getAddressConverter(); +} + +oox::drawingml::chart::ChartConverter* WorkbookHelper::getChartConverter() const +{ + return mrBookGlob.getChartConverter(); +} + +void WorkbookHelper::useInternalChartDataTable( bool bInternal ) +{ + mrBookGlob.useInternalChartDataTable( bInternal ); +} + +PageSettingsConverter& WorkbookHelper::getPageSettingsConverter() const +{ + return mrBookGlob.getPageSettingsConverter(); +} + +// OOXML/BIFF12 specific ------------------------------------------------------ + +XmlFilterBase& WorkbookHelper::getOoxFilter() const +{ + return mrBookGlob.getOoxFilter(); +} + +bool WorkbookHelper::importOoxFragment( const rtl::Reference<FragmentHandler>& rxHandler ) +{ + return getOoxFilter().importFragment( rxHandler ); +} + +bool WorkbookHelper::importOoxFragment( const rtl::Reference<FragmentHandler>& rxHandler, oox::core::FastParser& rParser ) +{ + return getOoxFilter().importFragment(rxHandler, rParser); +} + +// BIFF specific -------------------------------------------------------------- + +rtl_TextEncoding WorkbookHelper::getTextEncoding() const +{ + return mrBookGlob.getTextEncoding(); +} + +} // namespace oox + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |