Kaydet (Commit) 25bb9d13 authored tarafından Noel Power's avatar Noel Power

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
üst 78775f1a
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "oox/helper/refvector.hxx" #include "oox/helper/refvector.hxx"
#include "oox/helper/storagebase.hxx" #include "oox/helper/storagebase.hxx"
#include "oox/dllapi.h" #include "oox/dllapi.h"
#include "oox/ole/vbamodule.hxx"
namespace com { namespace sun { namespace star { namespace com { namespace sun { namespace star {
namespace container { class XNameContainer; } namespace container { class XNameContainer; }
...@@ -126,7 +127,12 @@ public: ...@@ -126,7 +127,12 @@ public:
bool importVbaProject( bool importVbaProject(
StorageBase& rVbaPrjStrg ); 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. */ VbaMacroAttacherBase class. */
void registerMacroAttacher( const VbaMacroAttacherRef& rxAttacher ); void registerMacroAttacher( const VbaMacroAttacherRef& rxAttacher );
...@@ -194,6 +200,9 @@ private: ...@@ -194,6 +200,9 @@ private:
OUString maPrjName; ///< Name of the VBA project. OUString maPrjName; ///< Name of the VBA project.
::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer > ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >
mxOleOverridesSink; mxOleOverridesSink;
typedef RefMap< rtl::OUString, VbaModule > VbaModuleMap;
VbaModuleMap maModules;
VbaModuleMap maModulesByStrm;
}; };
// ============================================================================ // ============================================================================
......
...@@ -2704,6 +2704,7 @@ EmbeddedForm::EmbeddedForm( const Reference< XModel >& rxDocModel, ...@@ -2704,6 +2704,7 @@ EmbeddedForm::EmbeddedForm( const Reference< XModel >& rxDocModel,
Reference< XControlModel > EmbeddedForm::convertAndInsert( const EmbeddedControl& rControl, sal_Int32& rnCtrlIndex ) Reference< XControlModel > EmbeddedForm::convertAndInsert( const EmbeddedControl& rControl, sal_Int32& rnCtrlIndex )
{ {
Reference< XControlModel > xRet;
if( mxModelFactory.is() && rControl.hasModel() ) try if( mxModelFactory.is() && rControl.hasModel() ) try
{ {
// create the UNO control model // create the UNO control model
...@@ -2711,20 +2712,19 @@ Reference< XControlModel > EmbeddedForm::convertAndInsert( const EmbeddedControl ...@@ -2711,20 +2712,19 @@ Reference< XControlModel > EmbeddedForm::convertAndInsert( const EmbeddedControl
Reference< XFormComponent > xFormComp( mxModelFactory->createInstance( aServiceName ), UNO_QUERY_THROW ); Reference< XFormComponent > xFormComp( mxModelFactory->createInstance( aServiceName ), UNO_QUERY_THROW );
Reference< XControlModel > xCtrlModel( xFormComp, 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 // insert the control into the form
Reference< XIndexContainer > xFormIC( createXForm(), UNO_SET_THROW ); Reference< XIndexContainer > xFormIC( createXForm(), UNO_SET_THROW );
rnCtrlIndex = xFormIC->getCount(); rnCtrlIndex = xFormIC->getCount();
xFormIC->insertByIndex( rnCtrlIndex, Any( xFormComp ) ); xFormIC->insertByIndex( rnCtrlIndex, Any( xFormComp ) );
// convert the control properties
if( rControl.convertProperties( xCtrlModel, maControlConv ) )
return xCtrlModel;
} }
catch (const Exception& e) catch (const Exception& e)
{ {
SAL_WARN("oox", "exception creating Control: " << e.Message); SAL_WARN("oox", "exception creating Control: " << e.Message);
} }
return Reference< XControlModel >(); return xRet;
} }
Reference< XIndexContainer > EmbeddedForm::createXForm() Reference< XIndexContainer > EmbeddedForm::createXForm()
......
...@@ -263,9 +263,15 @@ Reference< XNameContainer > VbaProject::createDialogLibrary() ...@@ -263,9 +263,15 @@ Reference< XNameContainer > VbaProject::createDialogLibrary()
} }
void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGraphicHelper, bool bDefaultColorBgr ) 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 ); 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 ) if( !xVbaStrg )
return; return;
...@@ -288,8 +294,6 @@ void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGrap ...@@ -288,8 +294,6 @@ void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGrap
sal_uInt16 nModuleCount = 0; sal_uInt16 nModuleCount = 0;
bool bExecutable = isImportVbaExecutable(); bool bExecutable = isImportVbaExecutable();
typedef RefMap< OUString, VbaModule > VbaModuleMap;
VbaModuleMap aModules, aModulesByStrm;
sal_uInt16 nRecId = 0; sal_uInt16 nRecId = 0;
StreamDataSequence aRecData; StreamDataSequence aRecData;
...@@ -304,7 +308,7 @@ void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGrap ...@@ -304,7 +308,7 @@ void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGrap
case VBA_ID_PROJECTCODEPAGE: case VBA_ID_PROJECTCODEPAGE:
{ {
OOX_ENSURE_RECORDSIZE( nRecSize == 2 ); 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() ); rtl_TextEncoding eNewTextEnc = rtl_getTextEncodingFromWindowsCodePage( aRecStrm.readuInt16() );
OSL_ENSURE( eNewTextEnc != RTL_TEXTENCODING_DONTKNOW, "VbaProject::importVba - unknown text encoding" ); OSL_ENSURE( eNewTextEnc != RTL_TEXTENCODING_DONTKNOW, "VbaProject::importVba - unknown text encoding" );
if( eNewTextEnc != RTL_TEXTENCODING_DONTKNOW ) if( eNewTextEnc != RTL_TEXTENCODING_DONTKNOW )
...@@ -321,26 +325,26 @@ void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGrap ...@@ -321,26 +325,26 @@ void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGrap
break; break;
case VBA_ID_PROJECTMODULES: case VBA_ID_PROJECTMODULES:
OOX_ENSURE_RECORDSIZE( nRecSize == 2 ); 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; aRecStrm >> nModuleCount;
break; break;
case VBA_ID_MODULENAME: case VBA_ID_MODULENAME:
{ {
OUString aName = aRecStrm.readCharArrayUC( nRecSize, eTextEnc ); OUString aName = aRecStrm.readCharArrayUC( nRecSize, eTextEnc );
OSL_ENSURE( !aName.isEmpty(), "VbaProject::importVba - invalid module name" ); OSL_ENSURE( !aName.isEmpty(), "VbaProject::importVba - invalid module name" );
OSL_ENSURE( !aModules.has( aName ), "VbaProject::importVba - multiple modules with the same name" ); OSL_ENSURE( !maModules.has( aName ), "VbaProject::importVba - multiple modules with the same name" );
VbaModuleMap::mapped_type& rxModule = aModules[ aName ]; VbaModuleMap::mapped_type& rxModule = maModules[ aName ];
rxModule.reset( new VbaModule( mxContext, mxDocModel, aName, eTextEnc, bExecutable ) ); rxModule.reset( new VbaModule( mxContext, mxDocModel, aName, eTextEnc, bExecutable ) );
// read all remaining records until the MODULEEND record // read all remaining records until the MODULEEND record
rxModule->importDirRecords( aDirStrm ); rxModule->importDirRecords( aDirStrm );
OSL_ENSURE( !aModulesByStrm.has( rxModule->getStreamName() ), "VbaProject::importVba - multiple modules with the same stream name" ); OSL_ENSURE( !maModulesByStrm.has( rxModule->getStreamName() ), "VbaProject::importVba - multiple modules with the same stream name" );
aModulesByStrm[ rxModule->getStreamName() ] = rxModule; maModulesByStrm[ rxModule->getStreamName() ] = rxModule;
} }
break; break;
#undef OOX_ENSURE_RECORDSIZE #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 /* The directory does not contain the real type of the modules, it
distinguishes only between 'procedural' and 'document' (the latter distinguishes only between 'procedural' and 'document' (the latter
...@@ -397,19 +401,48 @@ void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGrap ...@@ -397,19 +401,48 @@ void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGrap
if( (nType != ModuleType::UNKNOWN) && !aValue.isEmpty() ) if( (nType != ModuleType::UNKNOWN) && !aValue.isEmpty() )
{ {
OSL_ENSURE( aModules.has( aValue ), "VbaProject::importVba - module not found" ); OSL_ENSURE( maModules.has( aValue ), "VbaProject::importVba - module not found" );
if( VbaModule* pModule = aModules.get( aValue ).get() ) if( VbaModule* pModule = maModules.get( aValue ).get() )
pModule->setType( nType ); 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 // create empty dummy modules
VbaModuleMap aDummyModules; VbaModuleMap aDummyModules;
for( DummyModuleMap::iterator aIt = maDummyModules.begin(), aEnd = maDummyModules.end(); aIt != aEnd; ++aIt ) 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 ]; VbaModuleMap::mapped_type& rxModule = aDummyModules[ aIt->first ];
rxModule.reset( new VbaModule( mxContext, mxDocModel, aIt->first, eTextEnc, bExecutable ) ); rxModule.reset( new VbaModule( mxContext, mxDocModel, aIt->first, eTextEnc, bExecutable ) );
rxModule->setType( aIt->second ); rxModule->setType( aIt->second );
...@@ -419,26 +452,12 @@ void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGrap ...@@ -419,26 +452,12 @@ void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGrap
into the Basic library of the document specified by the 'maPrjName' into the Basic library of the document specified by the 'maPrjName'
member. Do not create the Basic library, if there are no modules member. Do not create the Basic library, if there are no modules
specified. */ specified. */
if( !aModules.empty() || !aDummyModules.empty() ) try if( !maModules.empty() || !aDummyModules.empty() ) try
{ {
// get the model factory and the basic library // get the model factory and the basic library
Reference< XMultiServiceFactory > xModelFactory( mxDocModel, UNO_QUERY_THROW ); Reference< XMultiServiceFactory > xModelFactory( mxDocModel, UNO_QUERY_THROW );
Reference< XNameContainer > xBasicLib( createBasicLibrary(), UNO_SET_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 // try to get access to document objects related to code modules
Reference< XNameAccess > xDocObjectNA; Reference< XNameAccess > xDocObjectNA;
try try
...@@ -454,7 +473,7 @@ void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGrap ...@@ -454,7 +473,7 @@ void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGrap
{ {
// #TODO cater for mxOleOverridesSink, like I used to before // #TODO cater for mxOleOverridesSink, like I used to before
// call Basic source code import for each module, boost::[c]ref enforces pass-by-ref // 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::ref( *xVbaStrg ), ::boost::cref( xBasicLib ),
::boost::cref( xDocObjectNA ) ); ::boost::cref( xDocObjectNA ) );
...@@ -482,7 +501,7 @@ void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGrap ...@@ -482,7 +501,7 @@ void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGrap
if( xSubStrg.get() ) try if( xSubStrg.get() ) try
{ {
// resolve module name from storage name (which equals the module stream name) // 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), OSL_ENSURE( pModule && (pModule->getType() == ModuleType::FORM),
"VbaProject::importVba - form substorage without form module" ); "VbaProject::importVba - form substorage without form module" );
OUString aModuleName; OUString aModuleName;
......
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
#include <comphelper/processfactory.hxx> #include <comphelper/processfactory.hxx>
#include <officecfg/Office/Calc.hxx> #include <officecfg/Office/Calc.hxx>
#include "oox/ole/vbaproject.hxx"
namespace oox { namespace oox {
namespace xls { namespace xls {
...@@ -299,6 +300,19 @@ void WorkbookFragment::finalizeImport() ...@@ -299,6 +300,19 @@ void WorkbookFragment::finalizeImport()
// create all defined names and database ranges // create all defined names and database ranges
getDefinedNames().finalizeImport(); getDefinedNames().finalizeImport();
getTables().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 // load all worksheets
for( SheetFragmentVector::iterator aIt = aSheetFragments.begin(), aEnd = aSheetFragments.end(); aIt != aEnd; ++aIt ) for( SheetFragmentVector::iterator aIt = aSheetFragments.begin(), aEnd = aSheetFragments.end(); aIt != aEnd; ++aIt )
{ {
...@@ -318,15 +332,6 @@ void WorkbookFragment::finalizeImport() ...@@ -318,15 +332,6 @@ void WorkbookFragment::finalizeImport()
aIt->first.reset(); 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 // final conversions, e.g. calculation settings and view settings
finalizeWorkbookImport(); finalizeWorkbookImport();
......
...@@ -710,7 +710,7 @@ void WorkbookHelper::finalizeWorkbookImport() ...@@ -710,7 +710,7 @@ void WorkbookHelper::finalizeWorkbookImport()
contains the workbook code name). */ contains the workbook code name). */
StorageRef xVbaPrjStrg = mrBookGlob.getVbaProjectStorage(); StorageRef xVbaPrjStrg = mrBookGlob.getVbaProjectStorage();
if( xVbaPrjStrg.get() && xVbaPrjStrg->isStorage() ) if( xVbaPrjStrg.get() && xVbaPrjStrg->isStorage() )
getBaseFilter().getVbaProject().importVbaProject( *xVbaPrjStrg, getBaseFilter().getGraphicHelper() ); getBaseFilter().getVbaProject().importModulesAndForms( *xVbaPrjStrg, getBaseFilter().getGraphicHelper() );
} }
// document model ------------------------------------------------------------- // document model -------------------------------------------------------------
......
...@@ -618,7 +618,7 @@ uno::Reference<uno::XInterface> ScServiceProvider::MakeInstance( ...@@ -618,7 +618,7 @@ uno::Reference<uno::XInterface> ScServiceProvider::MakeInstance(
} }
break; break;
case SC_SERVICE_VBACODENAMEPROVIDER: case SC_SERVICE_VBACODENAMEPROVIDER:
if ( pDocShell && ooo::vba::isAlienExcelDoc( *pDocShell ) && isInVBAMode( *pDocShell ) ) if ( pDocShell && isInVBAMode( *pDocShell ) )
{ {
OSL_TRACE("**** creating VBA Object provider"); OSL_TRACE("**** creating VBA Object provider");
xRet.set(static_cast<document::XCodeNameQuery*>(new ScVbaCodeNameProvider(*pDocShell))); xRet.set(static_cast<document::XCodeNameQuery*>(new ScVbaCodeNameProvider(*pDocShell)));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment