diff options
author | Noel Power <noel.power@suse.com> | 2013-06-04 15:24:29 +0100 |
---|---|---|
committer | Noel Power <noel.power@suse.com> | 2013-06-04 15:29:45 +0100 |
commit | 25bb9d13b259dbfb73f1412506f0d051b3670089 (patch) | |
tree | c560d5d66e20b8f473eafbc54be374375d4a1489 | |
parent | 78775f1ad9b3f394896179898db984e139d5b5cc (diff) |
fix for fdo#53042 fix ole object macro bindings ( for xlsm )
A number of fixes needed here
a) make sure convert properties of control model is done before inserting
control model into formcontainer, need to do that to ensure that
GenerateVBAEvents is set ( so the fake VBA event generation can be
triggered )
b) remove the IsAlieanExcel check in servuno.cxx ( it's too strict and
additionally seems there is confusion over the media type to check )
c) split the vba import so that we can ensure the VBA mode is set (if
we have modules to import ) before sheets are imported and defer further
processing ( actual assigning of the modules and associated objects )
until later
Change-Id: I8fdbe788b400d7e41d4cc4b51b15f692bd7b0ecc
-rw-r--r-- | include/oox/ole/vbaproject.hxx | 11 | ||||
-rw-r--r-- | oox/source/ole/axcontrol.cxx | 10 | ||||
-rw-r--r-- | oox/source/ole/vbaproject.cxx | 79 | ||||
-rw-r--r-- | sc/source/filter/oox/workbookfragment.cxx | 23 | ||||
-rw-r--r-- | sc/source/filter/oox/workbookhelper.cxx | 2 | ||||
-rw-r--r-- | sc/source/ui/unoobj/servuno.cxx | 2 |
6 files changed, 80 insertions, 47 deletions
diff --git a/include/oox/ole/vbaproject.hxx b/include/oox/ole/vbaproject.hxx index f742138756b5..55ac3a8b280a 100644 --- a/include/oox/ole/vbaproject.hxx +++ b/include/oox/ole/vbaproject.hxx @@ -25,6 +25,7 @@ #include "oox/helper/refvector.hxx" #include "oox/helper/storagebase.hxx" #include "oox/dllapi.h" +#include "oox/ole/vbamodule.hxx" namespace com { namespace sun { namespace star { namespace container { class XNameContainer; } @@ -126,7 +127,12 @@ public: bool importVbaProject( StorageBase& rVbaPrjStrg ); - /** Registers a macro atatcher object. For details, see description of the + /** Reads vba module related information from the project streams */ + void readVbaModules( StorageBase& rVbaPrjStrg ); + /** Imports (and creates) vba modules and user forms from the vba project records previously read. + Note: ( expects that readVbaModules was already called ) */ + void importModulesAndForms( StorageBase& rVbaPrjStrg, const GraphicHelper& rGraphicHelper, bool bDefaultColorBgr = true ); + /** Registers a macro attacher object. For details, see description of the VbaMacroAttacherBase class. */ void registerMacroAttacher( const VbaMacroAttacherRef& rxAttacher ); @@ -194,6 +200,9 @@ private: OUString maPrjName; ///< Name of the VBA project. ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer > mxOleOverridesSink; + typedef RefMap< rtl::OUString, VbaModule > VbaModuleMap; + VbaModuleMap maModules; + VbaModuleMap maModulesByStrm; }; // ============================================================================ diff --git a/oox/source/ole/axcontrol.cxx b/oox/source/ole/axcontrol.cxx index d5303a4eea7e..23f08e37bd4a 100644 --- a/oox/source/ole/axcontrol.cxx +++ b/oox/source/ole/axcontrol.cxx @@ -2704,6 +2704,7 @@ EmbeddedForm::EmbeddedForm( const Reference< XModel >& rxDocModel, Reference< XControlModel > EmbeddedForm::convertAndInsert( const EmbeddedControl& rControl, sal_Int32& rnCtrlIndex ) { + Reference< XControlModel > xRet; if( mxModelFactory.is() && rControl.hasModel() ) try { // create the UNO control model @@ -2711,20 +2712,19 @@ Reference< XControlModel > EmbeddedForm::convertAndInsert( const EmbeddedControl Reference< XFormComponent > xFormComp( mxModelFactory->createInstance( aServiceName ), UNO_QUERY_THROW ); Reference< XControlModel > xCtrlModel( xFormComp, UNO_QUERY_THROW ); + // convert the control properties + if( rControl.convertProperties( xCtrlModel, maControlConv ) ) + xRet = xCtrlModel; // insert the control into the form Reference< XIndexContainer > xFormIC( createXForm(), UNO_SET_THROW ); rnCtrlIndex = xFormIC->getCount(); xFormIC->insertByIndex( rnCtrlIndex, Any( xFormComp ) ); - - // convert the control properties - if( rControl.convertProperties( xCtrlModel, maControlConv ) ) - return xCtrlModel; } catch (const Exception& e) { SAL_WARN("oox", "exception creating Control: " << e.Message); } - return Reference< XControlModel >(); + return xRet; } Reference< XIndexContainer > EmbeddedForm::createXForm() diff --git a/oox/source/ole/vbaproject.cxx b/oox/source/ole/vbaproject.cxx index 91be35621d3d..b58710d0efcc 100644 --- a/oox/source/ole/vbaproject.cxx +++ b/oox/source/ole/vbaproject.cxx @@ -264,8 +264,14 @@ Reference< XNameContainer > VbaProject::createDialogLibrary() void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGraphicHelper, bool bDefaultColorBgr ) { + readVbaModules( rVbaPrjStrg ); + importModulesAndForms(rVbaPrjStrg, rGraphicHelper, bDefaultColorBgr ); +} + +void VbaProject::readVbaModules( StorageBase& rVbaPrjStrg ) +{ StorageRef xVbaStrg = rVbaPrjStrg.openSubStorage( "VBA", false ); - OSL_ENSURE( xVbaStrg.get(), "VbaProject::importVba - cannot open 'VBA' substorage" ); + OSL_ENSURE( xVbaStrg.get(), "VbaProject::readVbaModules - cannot open 'VBA' substorage" ); if( !xVbaStrg ) return; @@ -288,8 +294,6 @@ void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGrap sal_uInt16 nModuleCount = 0; bool bExecutable = isImportVbaExecutable(); - typedef RefMap< OUString, VbaModule > VbaModuleMap; - VbaModuleMap aModules, aModulesByStrm; sal_uInt16 nRecId = 0; StreamDataSequence aRecData; @@ -304,7 +308,7 @@ void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGrap case VBA_ID_PROJECTCODEPAGE: { OOX_ENSURE_RECORDSIZE( nRecSize == 2 ); - OSL_ENSURE( aModules.empty(), "VbaProject::importVba - unexpected PROJECTCODEPAGE record" ); + OSL_ENSURE( maModules.empty(), "VbaProject::importVba - unexpected PROJECTCODEPAGE record" ); rtl_TextEncoding eNewTextEnc = rtl_getTextEncodingFromWindowsCodePage( aRecStrm.readuInt16() ); OSL_ENSURE( eNewTextEnc != RTL_TEXTENCODING_DONTKNOW, "VbaProject::importVba - unknown text encoding" ); if( eNewTextEnc != RTL_TEXTENCODING_DONTKNOW ) @@ -321,26 +325,26 @@ void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGrap break; case VBA_ID_PROJECTMODULES: OOX_ENSURE_RECORDSIZE( nRecSize == 2 ); - OSL_ENSURE( aModules.empty(), "VbaProject::importVba - unexpected PROJECTMODULES record" ); + OSL_ENSURE( maModules.empty(), "VbaProject::importVba - unexpected PROJECTMODULES record" ); aRecStrm >> nModuleCount; break; case VBA_ID_MODULENAME: { OUString aName = aRecStrm.readCharArrayUC( nRecSize, eTextEnc ); OSL_ENSURE( !aName.isEmpty(), "VbaProject::importVba - invalid module name" ); - OSL_ENSURE( !aModules.has( aName ), "VbaProject::importVba - multiple modules with the same name" ); - VbaModuleMap::mapped_type& rxModule = aModules[ aName ]; + OSL_ENSURE( !maModules.has( aName ), "VbaProject::importVba - multiple modules with the same name" ); + VbaModuleMap::mapped_type& rxModule = maModules[ aName ]; rxModule.reset( new VbaModule( mxContext, mxDocModel, aName, eTextEnc, bExecutable ) ); // read all remaining records until the MODULEEND record rxModule->importDirRecords( aDirStrm ); - OSL_ENSURE( !aModulesByStrm.has( rxModule->getStreamName() ), "VbaProject::importVba - multiple modules with the same stream name" ); - aModulesByStrm[ rxModule->getStreamName() ] = rxModule; + OSL_ENSURE( !maModulesByStrm.has( rxModule->getStreamName() ), "VbaProject::importVba - multiple modules with the same stream name" ); + maModulesByStrm[ rxModule->getStreamName() ] = rxModule; } break; #undef OOX_ENSURE_RECORDSIZE } } - OSL_ENSURE( nModuleCount == aModules.size(), "VbaProject::importVba - invalid module count" ); + OSL_ENSURE( nModuleCount == maModules.size(), "VbaProject::importVba - invalid module count" ); /* The directory does not contain the real type of the modules, it distinguishes only between 'procedural' and 'document' (the latter @@ -397,19 +401,48 @@ void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGrap if( (nType != ModuleType::UNKNOWN) && !aValue.isEmpty() ) { - OSL_ENSURE( aModules.has( aValue ), "VbaProject::importVba - module not found" ); - if( VbaModule* pModule = aModules.get( aValue ).get() ) + OSL_ENSURE( maModules.has( aValue ), "VbaProject::importVba - module not found" ); + if( VbaModule* pModule = maModules.get( aValue ).get() ) pModule->setType( nType ); } } } } + if( !maModules.empty() ) try + { + /* Set library container to VBA compatibility mode. This will create + the VBA Globals object and store it in the Basic manager of the + document. */ + try + { + Reference< XVBACompatibility > xVBACompat( getLibraryContainer( PROP_BasicLibraries ), UNO_QUERY_THROW ); + xVBACompat->setVBACompatibilityMode( sal_True ); + xVBACompat->setProjectName( maPrjName ); + + } + catch(const Exception& ) + { + } + } + catch(const Exception& ) + { + } +} + +void VbaProject::importModulesAndForms( StorageBase& rVbaPrjStrg, const GraphicHelper& rGraphicHelper, bool bDefaultColorBgr ) +{ + StorageRef xVbaStrg = rVbaPrjStrg.openSubStorage( "VBA", false ); + OSL_ENSURE( xVbaStrg.get(), "VbaProject::importModulesAndForms - cannot open 'VBA' substorage" ); + if( !xVbaStrg ) + return; + rtl_TextEncoding eTextEnc = RTL_TEXTENCODING_MS_1252; + bool bExecutable = isImportVbaExecutable(); // create empty dummy modules VbaModuleMap aDummyModules; for( DummyModuleMap::iterator aIt = maDummyModules.begin(), aEnd = maDummyModules.end(); aIt != aEnd; ++aIt ) { - OSL_ENSURE( !aModules.has( aIt->first ) && !aDummyModules.has( aIt->first ), "VbaProject::importVba - multiple modules with the same name" ); + OSL_ENSURE( !maModules.has( aIt->first ) && !aDummyModules.has( aIt->first ), "VbaProject::importVba - multiple modules with the same name" ); VbaModuleMap::mapped_type& rxModule = aDummyModules[ aIt->first ]; rxModule.reset( new VbaModule( mxContext, mxDocModel, aIt->first, eTextEnc, bExecutable ) ); rxModule->setType( aIt->second ); @@ -419,26 +452,12 @@ void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGrap into the Basic library of the document specified by the 'maPrjName' member. Do not create the Basic library, if there are no modules specified. */ - if( !aModules.empty() || !aDummyModules.empty() ) try + if( !maModules.empty() || !aDummyModules.empty() ) try { // get the model factory and the basic library Reference< XMultiServiceFactory > xModelFactory( mxDocModel, UNO_QUERY_THROW ); Reference< XNameContainer > xBasicLib( createBasicLibrary(), UNO_SET_THROW ); - /* Set library container to VBA compatibility mode. This will create - the VBA Globals object and store it in the Basic manager of the - document. */ - try - { - Reference< XVBACompatibility > xVBACompat( getLibraryContainer( PROP_BasicLibraries ), UNO_QUERY_THROW ); - xVBACompat->setVBACompatibilityMode( sal_True ); - xVBACompat->setProjectName( maPrjName ); - - } - catch(const Exception& ) - { - } - // try to get access to document objects related to code modules Reference< XNameAccess > xDocObjectNA; try @@ -454,7 +473,7 @@ void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGrap { // #TODO cater for mxOleOverridesSink, like I used to before // call Basic source code import for each module, boost::[c]ref enforces pass-by-ref - aModules.forEachMem( &VbaModule::createAndImportModule, + maModules.forEachMem( &VbaModule::createAndImportModule, ::boost::ref( *xVbaStrg ), ::boost::cref( xBasicLib ), ::boost::cref( xDocObjectNA ) ); @@ -482,7 +501,7 @@ void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGrap if( xSubStrg.get() ) try { // resolve module name from storage name (which equals the module stream name) - VbaModule* pModule = aModulesByStrm.get( *aIt ).get(); + VbaModule* pModule = maModulesByStrm.get( *aIt ).get(); OSL_ENSURE( pModule && (pModule->getType() == ModuleType::FORM), "VbaProject::importVba - form substorage without form module" ); OUString aModuleName; diff --git a/sc/source/filter/oox/workbookfragment.cxx b/sc/source/filter/oox/workbookfragment.cxx index 5fad0fd6af25..6907d93d4b50 100644 --- a/sc/source/filter/oox/workbookfragment.cxx +++ b/sc/source/filter/oox/workbookfragment.cxx @@ -51,6 +51,7 @@ #include <comphelper/processfactory.hxx> #include <officecfg/Office/Calc.hxx> +#include "oox/ole/vbaproject.hxx" namespace oox { namespace xls { @@ -299,6 +300,19 @@ void WorkbookFragment::finalizeImport() // create all defined names and database ranges getDefinedNames().finalizeImport(); getTables().finalizeImport(); + // open the VBA project storage + OUString aVbaFragmentPath = getFragmentPathFromFirstType( CREATE_MSOFFICE_RELATION_TYPE( "vbaProject" ) ); + if( !aVbaFragmentPath.isEmpty() ) + { + Reference< XInputStream > xInStrm = getBaseFilter().openInputStream( aVbaFragmentPath ); + if( xInStrm.is() ) + { + StorageRef xPrjStrg( new ::oox::ole::OleStorage( getBaseFilter().getComponentContext(), xInStrm, false ) ); + setVbaProjectStorage( xPrjStrg ); + getBaseFilter().getVbaProject().readVbaModules( *xPrjStrg ); + } + } + // load all worksheets for( SheetFragmentVector::iterator aIt = aSheetFragments.begin(), aEnd = aSheetFragments.end(); aIt != aEnd; ++aIt ) { @@ -318,15 +332,6 @@ void WorkbookFragment::finalizeImport() aIt->first.reset(); } - // open the VBA project storage - OUString aVbaFragmentPath = getFragmentPathFromFirstType( CREATE_MSOFFICE_RELATION_TYPE( "vbaProject" ) ); - if( !aVbaFragmentPath.isEmpty() ) - { - Reference< XInputStream > xInStrm = getBaseFilter().openInputStream( aVbaFragmentPath ); - if( xInStrm.is() ) - setVbaProjectStorage( StorageRef( new ::oox::ole::OleStorage( getBaseFilter().getComponentContext(), xInStrm, false ) ) ); - } - // final conversions, e.g. calculation settings and view settings finalizeWorkbookImport(); diff --git a/sc/source/filter/oox/workbookhelper.cxx b/sc/source/filter/oox/workbookhelper.cxx index 51fd4266aafc..5e9b39f16d1c 100644 --- a/sc/source/filter/oox/workbookhelper.cxx +++ b/sc/source/filter/oox/workbookhelper.cxx @@ -710,7 +710,7 @@ void WorkbookHelper::finalizeWorkbookImport() contains the workbook code name). */ StorageRef xVbaPrjStrg = mrBookGlob.getVbaProjectStorage(); if( xVbaPrjStrg.get() && xVbaPrjStrg->isStorage() ) - getBaseFilter().getVbaProject().importVbaProject( *xVbaPrjStrg, getBaseFilter().getGraphicHelper() ); + getBaseFilter().getVbaProject().importModulesAndForms( *xVbaPrjStrg, getBaseFilter().getGraphicHelper() ); } // document model ------------------------------------------------------------- diff --git a/sc/source/ui/unoobj/servuno.cxx b/sc/source/ui/unoobj/servuno.cxx index e36f967fd447..3938908e36c5 100644 --- a/sc/source/ui/unoobj/servuno.cxx +++ b/sc/source/ui/unoobj/servuno.cxx @@ -618,7 +618,7 @@ uno::Reference<uno::XInterface> ScServiceProvider::MakeInstance( } break; case SC_SERVICE_VBACODENAMEPROVIDER: - if ( pDocShell && ooo::vba::isAlienExcelDoc( *pDocShell ) && isInVBAMode( *pDocShell ) ) + if ( pDocShell && isInVBAMode( *pDocShell ) ) { OSL_TRACE("**** creating VBA Object provider"); xRet.set(static_cast<document::XCodeNameQuery*>(new ScVbaCodeNameProvider(*pDocShell))); |