22 #include <com/sun/star/beans/XPropertySet.hpp>
23 #include <com/sun/star/document/XStorageBasedDocument.hpp>
24 #include <com/sun/star/embed/ElementModes.hpp>
25 #include <com/sun/star/embed/XTransactedObject.hpp>
26 #include <com/sun/star/frame/XModel.hpp>
27 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
28 #include <com/sun/star/script/ModuleType.hpp>
29 #include <com/sun/star/script/XLibraryContainer.hpp>
30 #include <com/sun/star/script/vba/XVBACompatibility.hpp>
31 #include <com/sun/star/script/vba/XVBAMacroResolver.hpp>
32 #include <com/sun/star/uno/XComponentContext.hpp>
36 #include <osl/diagnose.h>
37 #include <rtl/tencinfo.h>
47 #include <oox/token/properties.hxx>
62 using ::comphelper::ConfigurationHelper;
66 bool lclReadConfigItem(
const Reference< XInterface >& rxConfigAccess,
const OUString& rItemName )
71 Any aItem = ConfigurationHelper::readRelativeKey( rxConfigAccess,
"Filter/Import/VBA", rItemName );
72 return aItem.has<
bool >() && aItem.get<
bool >();
74 catch(
const Exception& )
84 OSL_ENSURE( rxContext.is(),
"VbaFilterConfig::VbaFilterConfig - missing component context" );
85 if( rxContext.is() )
try
87 OSL_ENSURE( !rConfigCompName.empty(),
"VbaFilterConfig::VbaFilterConfig - invalid configuration component name" );
88 OUString aConfigPackage = OUString::Concat(
"org.openoffice.Office.") + rConfigCompName;
94 OSL_ENSURE(
mxConfigAccess.is(),
"VbaFilterConfig::VbaFilterConfig - cannot open configuration" );
117 maMacroName( rMacroName )
119 OSL_ENSURE( !
maMacroName.isEmpty(),
"VbaMacroAttacherBase::VbaMacroAttacherBase - empty macro name" );
138 const Reference< XModel >& rxDocModel, std::u16string_view rConfigCompName ) :
141 mxDocModel( rxDocModel ),
142 maPrjName(
"Standard" )
144 OSL_ENSURE(
mxContext.is(),
"VbaProject::VbaProject - missing component context" );
145 OSL_ENSURE( mxDocModel.is(),
"VbaProject::VbaProject - missing document model" );
155 Reference< css::frame::XFrame >
xFrame;
159 xFrame = xController.is() ? xController->getFrame() :
nullptr;
178 importVba( rVbaPrjStrg, rGraphicHelper );
187 uno::Reference<document::XStorageBasedDocument> xStorageBasedDoc(
mxDocModel, uno::UNO_QUERY);
188 uno::Reference<embed::XStorage> xDocStorage = xStorageBasedDoc->getDocumentStorage();
190 const sal_Int32 nOpenMode = ElementModes::SEEKABLE | ElementModes::WRITE | ElementModes::TRUNCATE;
191 uno::Reference<io::XOutputStream> xDocStream(xDocStorage->openStreamElement(
"_MS_VBA_Macros_XML", nOpenMode), uno::UNO_QUERY);
194 uno::Reference<embed::XTransactedObject>(xDocStorage, uno::UNO_QUERY_THROW)->commit();
199 OSL_ENSURE( rxAttacher,
"VbaProject::registerMacroAttacher - unexpected empty reference" );
207 OSL_ENSURE( !rName.isEmpty(),
"VbaProject::addDummyModule - missing module name" );
220 Reference< XLibraryContainer > xLibContainer( aDocProp.
getAnyProperty( nPropId ), UNO_QUERY );
221 return xLibContainer;
226 Reference< XNameContainer > xLibrary;
229 Reference< XLibraryContainer > xLibContainer(
getLibraryContainer( nPropId ), UNO_SET_THROW );
230 if( !xLibContainer->hasByName(
maPrjName ) )
231 xLibContainer->createLibrary(
maPrjName );
232 xLibrary.set( xLibContainer->getByName(
maPrjName ), UNO_QUERY_THROW );
237 OSL_ENSURE( xLibrary.is(),
"VbaProject::openLibrary - cannot create library" );
266 OSL_ENSURE( xVbaStrg,
"VbaProject::readVbaModules - cannot open 'VBA' substorage" );
277 OSL_ENSURE( !aDirStrm.isEof(),
"VbaProject::importVba - cannot open 'dir' stream" );
278 if( aDirStrm.isEof() )
285 rtl_TextEncoding eTextEnc = RTL_TEXTENCODING_MS_1252;
286 sal_uInt16 nModuleCount = 0;
289 sal_uInt16 nRecId = 0;
295 sal_Int32 nRecSize = aRecData.getLength();
300 OSL_ENSURE( nRecSize == 2,
"VbaProject::importVba - invalid record size" );
301 OSL_ENSURE(
maModules.empty(),
"VbaProject::importVba - unexpected PROJECTCODEPAGE record" );
302 rtl_TextEncoding eNewTextEnc = rtl_getTextEncodingFromWindowsCodePage( aRecStrm.
readuInt16() );
303 OSL_ENSURE( eNewTextEnc != RTL_TEXTENCODING_DONTKNOW,
"VbaProject::importVba - unknown text encoding" );
304 if( eNewTextEnc != RTL_TEXTENCODING_DONTKNOW )
305 eTextEnc = eNewTextEnc;
311 OSL_ENSURE( !aPrjName.isEmpty(),
"VbaProject::importVba - invalid project name" );
312 if( !aPrjName.isEmpty() )
317 OSL_ENSURE( nRecSize == 2,
"VbaProject::importVba - invalid record size" );
318 OSL_ENSURE(
maModules.empty(),
"VbaProject::importVba - unexpected PROJECTMODULES record" );
324 OSL_ENSURE( !aName.isEmpty(),
"VbaProject::importVba - invalid module name" );
325 OSL_ENSURE( !
maModules.
has( aName ),
"VbaProject::importVba - multiple modules with the same name" );
327 rxModule = std::make_shared<VbaModule>(
mxContext,
mxDocModel, aName, eTextEnc, bExecutable );
329 rxModule->importDirRecords( aDirStrm );
330 OSL_ENSURE( !
maModulesByStrm.
has( rxModule->getStreamName() ),
"VbaProject::importVba - multiple modules with the same stream name" );
336 SAL_WARN_IF( nModuleCount !=
maModules.size(),
"oox",
"VbaProject::importVba - invalid module count" );
359 OSL_ENSURE( !aPrjStrm.isEof(),
"VbaProject::importVba - cannot open 'PROJECT' stream" );
361 if( !aPrjStrm.isEof() )
364 OUString aKey, aValue;
365 bool bExitLoop =
false;
366 while( !bExitLoop && !aPrjTextStrm.
isEof() )
369 OUString aLine = aPrjTextStrm.
readLine().trim();
370 sal_Int32 nLineLen = aLine.getLength();
372 bExitLoop = (nLineLen >= 2) && (aLine[ 0 ] ==
'[') && (aLine[ nLineLen - 1 ] ==
']');
375 sal_Int32
nType = ModuleType::UNKNOWN;
376 if( aKey.equalsIgnoreAsciiCase(
"Document" ) )
378 nType = ModuleType::DOCUMENT;
380 sal_Int32 nSlashPos = aValue.indexOf(
'/' );
382 aValue = aValue.copy( 0, nSlashPos );
384 else if( aKey.equalsIgnoreAsciiCase(
"Module" ) )
385 nType = ModuleType::NORMAL;
386 else if( aKey.equalsIgnoreAsciiCase(
"Class" ) )
387 nType = ModuleType::CLASS;
388 else if( aKey.equalsIgnoreAsciiCase(
"BaseClass" ) )
389 nType = ModuleType::FORM;
391 if( (nType != ModuleType::UNKNOWN) && !aValue.isEmpty() )
393 OSL_ENSURE(
maModules.
has( aValue ),
"VbaProject::importVba - module not found" );
395 pModule->setType( nType );
411 Reference< XVBACompatibility > xVBACompat(
getLibraryContainer( PROP_BasicLibraries ), UNO_QUERY_THROW );
412 xVBACompat->setVBACompatibilityMode(
true );
415 uno::Reference<beans::XPropertySet> xProps(xVBACompat, uno::UNO_QUERY_THROW);
416 xProps->setPropertyValue(
"VBATextEncoding",
uno::Any(eTextEnc));
430 OSL_ENSURE( xVbaStrg,
"VbaProject::importModulesAndForms - cannot open 'VBA' substorage" );
433 rtl_TextEncoding eTextEnc = RTL_TEXTENCODING_MS_1252;
440 OSL_ENSURE( !
maModules.
has( dummyModule.first ) && !aDummyModules.
has( dummyModule.first ),
"VbaProject::importVba - multiple modules with the same name" );
442 rxModule = std::make_shared<VbaModule>(
mxContext,
mxDocModel, dummyModule.first, eTextEnc, bExecutable );
443 rxModule->setType( dummyModule.second );
450 if( !
maModules.empty() || !aDummyModules.empty() )
try
453 Reference< XMultiServiceFactory > xModelFactory(
mxDocModel, UNO_QUERY_THROW );
460 xDocObjectNA.set( xModelFactory->createInstance(
"ooo.vba.VBAObjectModuleObjectProvider" ), UNO_QUERY );
472 ::std::ref( *xVbaStrg ), ::std::cref( xBasicLib ),
473 ::std::cref( xDocObjectNA ) );
477 ::std::cref( xBasicLib ), ::std::cref( xDocObjectNA ) );
488 ::std::vector< OUString > aElements;
490 for (
auto const& elem : aElements)
500 OSL_ENSURE( pModule && (pModule->
getType() == ModuleType::FORM),
501 "VbaProject::importVba - form substorage without form module" );
502 OUString aModuleName;
504 aModuleName = pModule->
getName();
509 aForm.
importForm( xDialogLib, *xSubStrg, aModuleName, eTextEnc );
527 Reference< XMultiComponentFactory >
xFactory(
mxContext->getServiceManager(), UNO_SET_THROW );
529 Reference< XVBAMacroResolver > xResolver(
xFactory->createInstanceWithArgumentsAndContext(
530 "com.sun.star.script.vba.VBAMacroResolver", aArgs,
mxContext ), UNO_QUERY_THROW );
546 Reference< XStorageBasedDocument > xStorageBasedDoc(
mxDocModel, UNO_QUERY_THROW );
547 Reference< XStorage > xDocStorage( xStorageBasedDoc->getDocumentStorage(), UNO_SET_THROW );
549 const sal_Int32 nOpenMode = ElementModes::SEEKABLE | ElementModes::WRITE | ElementModes::TRUNCATE;
550 Reference< XStream > xDocStream( xDocStorage->openStreamElement(
"_MS_VBA_Macros", nOpenMode ), UNO_SET_THROW );
553 aDestStorage.commit();
555 Reference< XTransactedObject >( xDocStorage, UNO_QUERY_THROW )->commit();
void importModulesAndForms(StorageBase &rVbaPrjStrg, const GraphicHelper &rGraphicHelper)
Imports (and creates) vba modules and user forms from the vba project records previously read...
Provides helper functions for colors, device measurement conversion, graphics, and graphic objects ha...
const sal_uInt16 VBA_ID_MODULENAME
void readVbaModules(StorageBase &rVbaPrjStrg)
Reads vba module related information from the project streams.
bool isImportVba() const
Returns true, if the VBA source code and forms should be imported.
void copyStorage(StorageBase &rVbaPrjStrg)
Copies the entire VBA project storage to the passed document model.
OUString maPrjName
Name of the VBA project.
static void CopyInputToOutput(const css::uno::Reference< css::io::XInputStream > &xInput, const css::uno::Reference< css::io::XOutputStream > &xOutput)
void attachMacros()
Attaches VBA macros to objects registered via registerMacroAttacher().
void createAndImportModule(StorageBase &rVbaStrg, const css::uno::Reference< css::container::XNameContainer > &rxBasicLib, const css::uno::Reference< css::container::XNameAccess > &rxDocObjectNA)
Imports the VBA source code into the passed Basic library.
void importVba(StorageBase &rVbaPrjStrg, const GraphicHelper &rGraphicHelper)
Imports the VBA code modules and forms.
bool isStorage() const
Returns true, if the object represents a valid storage.
bool extractKeyValue(OUString &rKey, OUString &rValue, std::u16string_view rKeyValue)
Extracts a key/value pair from a string separated by an equality sign.
Reference< XFrame > xFrame
css::uno::Any getAnyProperty(sal_Int32 nPropId) const
Gets the specified property from the property set.
const OUString & getName() const
Returns the name of the module.
VbaFilterConfig(const css::uno::Reference< css::uno::XComponentContext > &rxContext, std::u16string_view rConfigCompName)
void copyStorageToStorage(StorageBase &rDestStrg)
Copies all streams of this storage and of all substorages to the passed destination.
OUString readLine()
Reads a text line from the stream.
bool isImportVbaExecutable() const
Returns true, if the VBA source code should be imported executable.
void addDummyModule(const OUString &rName, sal_Int32 nType)
Registers a dummy module that will be created when the VBA project is imported.
std::shared_ptr< StorageBase > StorageRef
virtual void attachMacro(const OUString &rScriptUrl)=0
Called after the VBA project has been imported.
Implements stream access for binary OLE storages.
VbaModuleMap maModulesByStrm
void forEachMem(FuncType pFunc) const
Calls the passed member function of ObjType on every contained object, automatically skips all elemen...
bool isExportVba() const
Returns true, if the VBA source code and forms should be exported.
Reference< XController > xController
const sal_uInt16 VBA_ID_PROJECTEND
bool has(key_type nKey) const
Returns true, if the object associated to the passed key exists.
css::uno::Reference< css::uno::XInterface > mxConfigAccess
css::uno::Reference< css::container::XNameContainer > openLibrary(sal_Int32 nPropId)
Opens a Basic or dialog library, creates missing if not found.
Base class for storage access implementations.
css::uno::Sequence< sal_Int8 > StreamDataSequence
void importVbaProject(StorageBase &rVbaPrjStrg, const GraphicHelper &rGraphicHelper)
Imports the entire VBA project from the passed storage.
void resolveAndAttachMacro(const css::uno::Reference< css::script::vba::XVBAMacroResolver > &rxResolver)
Resolves the internal macro name to the related macro URL, and attaches the macro to the object...
container_type::mapped_type mapped_type
DummyModuleMap maDummyModules
Additional empty modules created on import.
const sal_uInt16 VBA_ID_PROJECTMODULES
VbaProject(const css::uno::Reference< css::uno::XComponentContext > &rxContext, const css::uno::Reference< css::frame::XModel > &rxDocModel, std::u16string_view rConfigCompName)
virtual ~VbaMacroAttacherBase()
css::uno::Reference< css::frame::XModel > mxDocModel
Document model used to import/export the VBA project.
std::shared_ptr< VbaMacroAttacherBase > VbaMacroAttacherRef
A wrapper for a UNO property set.
css::uno::Reference< css::io::XInputStream > openInputStream(const OUString &rStreamName)
Opens and returns the specified input stream from the storage.
bool isEof() const
Returns true, if no more text is available in the stream.
css::uno::Reference< css::container::XNameContainer > mxBasicLib
The Basic library of the document used for import.
mapped_type get(key_type nKey) const
Returns a reference to the object associated to the passed key, or an empty reference on error...
VbaMacroAttacherBase(const OUString &rMacroName)
const sal_uInt16 VBA_ID_PROJECTCODEPAGE
#define SAL_WARN_IF(condition, area, stream)
css::uno::Reference< css::uno::XComponentContext > mxContext
Component context with service manager.
css::uno::Reference< css::container::XNameContainer > const & createDialogLibrary()
Creates and returns the dialog library of the document used for import.
sal_Int32 getType() const
Returns the module type (com.sun.star.script.ModuleType constant).
bool readDirRecord(sal_uInt16 &rnRecId, StreamDataSequence &rRecData, BinaryInputStream &rInStrm)
Reads the next record from the VBA directory stream 'dir'.
MacroAttacherVector maMacroAttachers
Objects that want to attach a VBA macro to an action.
Reference< XSingleServiceFactory > xFactory
const sal_uInt16 VBA_ID_PROJECTNAME
void createEmptyModule(const css::uno::Reference< css::container::XNameContainer > &rxBasicLib, const css::uno::Reference< css::container::XNameAccess > &rxDocObjectNA) const
Creates an empty Basic module in the passed Basic library.
void registerMacroAttacher(const VbaMacroAttacherRef &rxAttacher)
Registers a macro attacher object.
css::uno::Reference< css::script::XLibraryContainer > getLibraryContainer(sal_Int32 nPropId)
Returns the Basic or dialog library container.
css::uno::Reference< css::container::XNameContainer > const & createBasicLibrary()
Creates and returns the Basic library of the document used for import.
COMPHELPER_DLLPUBLIC void notifyMacroEventRead(const css::uno::Reference< css::frame::XModel > &_rxDocument)
void importVbaData(const css::uno::Reference< css::io::XInputStream > &xInputStream)
Imports VBA data for a VBA project, e.g. word/vbaData.xml.
void getElementNames(::std::vector< OUString > &orElementNames) const
Fills the passed vector with the names of all direct elements of this storage.
css::uno::Reference< css::container::XNameContainer > mxDialogLib
The dialog library of the document used for import.
void forEachMem(FuncType pFunc) const
Calls the passed member function of ObjType on every contained object, automatically skips all elemen...
StorageRef openSubStorage(const OUString &rStorageName, bool bCreateMissing)
Opens and returns the specified sub storage from the storage.
virtual void prepareImport()
Called when the import process of the VBA project has been started.