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>
48#include <oox/token/properties.hxx>
64using ::comphelper::ConfigurationHelper;
68bool lclReadConfigItem(
const Reference< XInterface >& rxConfigAccess,
const OUString& rItemName )
73 Any aItem = ConfigurationHelper::readRelativeKey( rxConfigAccess,
"Filter/Import/VBA", rItemName );
74 return aItem.has<
bool >() && aItem.get<
bool >();
76 catch(
const Exception& )
86 OSL_ENSURE( rxContext.is(),
"VbaFilterConfig::VbaFilterConfig - missing component context" );
87 if( rxContext.is() )
try
89 OSL_ENSURE( !rConfigCompName.empty(),
"VbaFilterConfig::VbaFilterConfig - invalid configuration component name" );
90 OUString aConfigPackage = OUString::Concat(
"org.openoffice.Office.") + rConfigCompName;
97 OSL_ENSURE(
mxConfigAccess.is(),
"VbaFilterConfig::VbaFilterConfig - cannot open configuration" );
120 maMacroName(
std::move( aMacroName ))
122 OSL_ENSURE( !
maMacroName.isEmpty(),
"VbaMacroAttacherBase::VbaMacroAttacherBase - empty macro name" );
142 const Reference< XModel >& rxDocModel, std::u16string_view rConfigCompName ) :
145 mxDocModel( rxDocModel ),
146 maPrjName(
"Standard" )
148 OSL_ENSURE(
mxContext.is(),
"VbaProject::VbaProject - missing component context" );
149 OSL_ENSURE( mxDocModel.is(),
"VbaProject::VbaProject - missing document model" );
159 Reference< css::frame::XFrame >
xFrame;
182 importVba( rVbaPrjStrg, rGraphicHelper );
191 uno::Reference<document::XStorageBasedDocument> xStorageBasedDoc(
mxDocModel, uno::UNO_QUERY);
192 uno::Reference<embed::XStorage> xDocStorage = xStorageBasedDoc->getDocumentStorage();
194 const sal_Int32 nOpenMode = ElementModes::SEEKABLE | ElementModes::WRITE | ElementModes::TRUNCATE;
195 uno::Reference<io::XOutputStream> xDocStream(xDocStorage->openStreamElement(
"_MS_VBA_Macros_XML", nOpenMode), uno::UNO_QUERY);
198 uno::Reference<embed::XTransactedObject>(xDocStorage, uno::UNO_QUERY_THROW)->commit();
203 OSL_ENSURE( rxAttacher,
"VbaProject::registerMacroAttacher - unexpected empty reference" );
211 OSL_ENSURE( !rName.isEmpty(),
"VbaProject::addDummyModule - missing module name" );
224 Reference< XLibraryContainer > xLibContainer( aDocProp.
getAnyProperty( nPropId ), UNO_QUERY );
225 return xLibContainer;
230 Reference< XNameContainer > xLibrary;
233 Reference< XLibraryContainer > xLibContainer(
getLibraryContainer( nPropId ), UNO_SET_THROW );
234 if( !xLibContainer->hasByName(
maPrjName ) )
235 xLibContainer->createLibrary(
maPrjName );
236 xLibrary.set( xLibContainer->getByName(
maPrjName ), UNO_QUERY_THROW );
242 OSL_ENSURE( xLibrary.is(),
"VbaProject::openLibrary - cannot create library" );
271 OSL_ENSURE( xVbaStrg,
"VbaProject::readVbaModules - cannot open 'VBA' substorage" );
282 OSL_ENSURE( !aDirStrm.
isEof(),
"VbaProject::importVba - cannot open 'dir' stream" );
283 if( aDirStrm.
isEof() )
290 rtl_TextEncoding eTextEnc = RTL_TEXTENCODING_MS_1252;
291 sal_uInt16 nModuleCount = 0;
294 sal_uInt16 nRecId = 0;
300 sal_Int32 nRecSize = aRecData.getLength();
305 OSL_ENSURE( nRecSize == 2,
"VbaProject::importVba - invalid record size" );
306 OSL_ENSURE(
maModules.empty(),
"VbaProject::importVba - unexpected PROJECTCODEPAGE record" );
307 rtl_TextEncoding eNewTextEnc = rtl_getTextEncodingFromWindowsCodePage( aRecStrm.
readuInt16() );
308 OSL_ENSURE( eNewTextEnc != RTL_TEXTENCODING_DONTKNOW,
"VbaProject::importVba - unknown text encoding" );
309 if( eNewTextEnc != RTL_TEXTENCODING_DONTKNOW )
310 eTextEnc = eNewTextEnc;
316 OSL_ENSURE( !aPrjName.isEmpty(),
"VbaProject::importVba - invalid project name" );
317 if( !aPrjName.isEmpty() )
322 OSL_ENSURE( nRecSize == 2,
"VbaProject::importVba - invalid record size" );
323 OSL_ENSURE(
maModules.empty(),
"VbaProject::importVba - unexpected PROJECTMODULES record" );
329 OSL_ENSURE( !
aName.isEmpty(),
"VbaProject::importVba - invalid module name" );
330 OSL_ENSURE( !
maModules.
has(
aName ),
"VbaProject::importVba - multiple modules with the same name" );
334 rxModule->importDirRecords( aDirStrm );
335 OSL_ENSURE( !
maModulesByStrm.
has( rxModule->getStreamName() ),
"VbaProject::importVba - multiple modules with the same stream name" );
341 SAL_WARN_IF( nModuleCount !=
maModules.size(),
"oox",
"VbaProject::importVba - invalid module count" );
364 OSL_ENSURE( !aPrjStrm.
isEof(),
"VbaProject::importVba - cannot open 'PROJECT' stream" );
366 if( !aPrjStrm.
isEof() )
369 OUString aKey, aValue;
370 bool bExitLoop =
false;
371 while( !bExitLoop && !aPrjTextStrm.
isEof() )
374 OUString aLine = aPrjTextStrm.
readLine().trim();
375 sal_Int32 nLineLen = aLine.getLength();
377 bExitLoop = (nLineLen >= 2) && (aLine[ 0 ] ==
'[') && (aLine[ nLineLen - 1 ] ==
']');
380 sal_Int32
nType = ModuleType::UNKNOWN;
381 if( aKey.equalsIgnoreAsciiCase(
"Document" ) )
383 nType = ModuleType::DOCUMENT;
385 sal_Int32 nSlashPos = aValue.indexOf(
'/' );
387 aValue = aValue.copy( 0, nSlashPos );
389 else if( aKey.equalsIgnoreAsciiCase(
"Module" ) )
390 nType = ModuleType::NORMAL;
391 else if( aKey.equalsIgnoreAsciiCase(
"Class" ) )
392 nType = ModuleType::CLASS;
393 else if( aKey.equalsIgnoreAsciiCase(
"BaseClass" ) )
394 nType = ModuleType::FORM;
396 if( (
nType != ModuleType::UNKNOWN) && !aValue.isEmpty() )
398 OSL_ENSURE(
maModules.
has( aValue ),
"VbaProject::importVba - module not found" );
400 pModule->setType(
nType );
416 Reference< XVBACompatibility > xVBACompat(
getLibraryContainer( PROP_BasicLibraries ), UNO_QUERY_THROW );
417 xVBACompat->setVBACompatibilityMode(
true );
420 uno::Reference<beans::XPropertySet> xProps(xVBACompat, uno::UNO_QUERY_THROW);
421 xProps->setPropertyValue(
"VBATextEncoding",
uno::Any(eTextEnc));
436 OSL_ENSURE( xVbaStrg,
"VbaProject::importModulesAndForms - cannot open 'VBA' substorage" );
439 rtl_TextEncoding eTextEnc = RTL_TEXTENCODING_MS_1252;
446 OSL_ENSURE( !
maModules.
has( dummyModule.first ) && !aDummyModules.
has( dummyModule.first ),
"VbaProject::importVba - multiple modules with the same name" );
448 rxModule = std::make_shared<VbaModule>(
mxContext,
mxDocModel, dummyModule.first, eTextEnc, bExecutable );
449 rxModule->setType( dummyModule.second );
456 if( !
maModules.empty() || !aDummyModules.empty() )
try
459 Reference< XMultiServiceFactory > xModelFactory(
mxDocModel, UNO_QUERY_THROW );
463 Reference< XNameAccess > xDocObjectNA;
466 xDocObjectNA.set( xModelFactory->createInstance(
"ooo.vba.VBAObjectModuleObjectProvider" ), UNO_QUERY );
478 ::std::ref( *xVbaStrg ), ::std::cref( xBasicLib ),
479 ::std::cref( xDocObjectNA ) );
483 ::std::cref( xBasicLib ), ::std::cref( xDocObjectNA ) );
494 ::std::vector< OUString > aElements;
496 for (
auto const& elem : aElements)
506 OSL_ENSURE( pModule && (pModule->
getType() == ModuleType::FORM),
507 "VbaProject::importVba - form substorage without form module" );
508 OUString aModuleName;
510 aModuleName = pModule->
getName();
515 aForm.
importForm( xDialogLib, *xSubStrg, aModuleName, eTextEnc );
534 Reference< XMultiComponentFactory >
xFactory(
mxContext->getServiceManager(), UNO_SET_THROW );
536 Reference< XVBAMacroResolver > xResolver(
xFactory->createInstanceWithArgumentsAndContext(
537 "com.sun.star.script.vba.VBAMacroResolver", aArgs,
mxContext ), UNO_QUERY_THROW );
554 Reference< XStorageBasedDocument > xStorageBasedDoc(
mxDocModel, UNO_QUERY_THROW );
555 Reference< XStorage > xDocStorage( xStorageBasedDoc->getDocumentStorage(), UNO_SET_THROW );
557 const sal_Int32 nOpenMode = ElementModes::SEEKABLE | ElementModes::WRITE | ElementModes::TRUNCATE;
558 Reference< XStream > xDocStream( xDocStorage->openStreamElement(
"_MS_VBA_Macros", nOpenMode ), UNO_SET_THROW );
563 Reference< XTransactedObject >( xDocStorage, UNO_QUERY_THROW )->commit();
static void CopyInputToOutput(const css::uno::Reference< css::io::XInputStream > &xInput, const css::uno::Reference< css::io::XOutputStream > &xOutput)
bool isEof() const
Returns true, if the stream position is invalid (EOF).
Provides helper functions for colors, device measurement conversion, graphics, and graphic objects ha...
A wrapper for a UNO property set.
css::uno::Any getAnyProperty(sal_Int32 nPropId) const
Gets the specified property from the property set.
bool has(key_type nKey) const
Returns true, if the object associated to the passed key exists.
mapped_type get(key_type nKey) const
Returns a reference to the object associated to the passed key, or an empty reference on error.
container_type::mapped_type mapped_type
void forEachMem(FuncType pFunc) const
Calls the passed member function of ObjType on every contained object, automatically skips all elemen...
void forEachMem(FuncType pFunc) const
Calls the passed member function of ObjType on every contained object, automatically skips all elemen...
Base class for storage access implementations.
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::io::XInputStream > openInputStream(const OUString &rStreamName)
Opens and returns the specified input stream from the storage.
void commit()
Commits the changes to the storage and all substorages.
void copyStorageToStorage(StorageBase &rDestStrg)
Copies all streams of this storage and of all substorages to the passed destination.
bool isStorage() const
Returns true, if the object represents a valid storage.
StorageRef openSubStorage(const OUString &rStorageName, bool bCreateMissing)
Opens and returns the specified sub storage from the storage.
bool isEof() const
Returns true, if no more text is available in the stream.
OUString readLine()
Reads a text line from the stream.
Implements stream access for binary OLE storages.
VbaFilterConfig(const css::uno::Reference< css::uno::XComponentContext > &rxContext, std::u16string_view rConfigCompName)
css::uno::Reference< css::uno::XInterface > mxConfigAccess
bool isExportVba() const
Returns true, if the VBA source code and forms should be exported.
bool isImportVba() const
Returns true, if the VBA source code and forms should be imported.
bool isImportVbaExecutable() const
Returns true, if the VBA source code should be imported executable.
virtual ~VbaMacroAttacherBase()
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.
VbaMacroAttacherBase(OUString aMacroName)
virtual void attachMacro(const OUString &rScriptUrl)=0
Called after the VBA project has been imported.
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.
const OUString & getName() const
Returns the name of the module.
sal_Int32 getType() const
Returns the module type (com.sun.star.script.ModuleType constant).
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.
css::uno::Reference< css::uno::XComponentContext > mxContext
Component context with service manager.
VbaProject(const css::uno::Reference< css::uno::XComponentContext > &rxContext, const css::uno::Reference< css::frame::XModel > &rxDocModel, std::u16string_view rConfigCompName)
DummyModuleMap maDummyModules
Additional empty modules created on import.
OUString maPrjName
Name of the VBA project.
void addDummyModule(const OUString &rName, sal_Int32 nType)
Registers a dummy module that will be created when the VBA project is imported.
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 > mxBasicLib
The Basic library of the document used for import.
css::uno::Reference< css::container::XNameContainer > const & createBasicLibrary()
Creates and returns the Basic library of the document used for import.
css::uno::Reference< css::container::XNameContainer > mxDialogLib
The dialog library of the document used for import.
VbaModuleMap maModulesByStrm
css::uno::Reference< css::frame::XModel > mxDocModel
Document model used to import/export the VBA project.
void attachMacros()
Attaches VBA macros to objects registered via registerMacroAttacher().
void copyStorage(StorageBase &rVbaPrjStrg)
Copies the entire VBA project storage to the passed document model.
MacroAttacherVector maMacroAttachers
Objects that want to attach a VBA macro to an action.
void readVbaModules(StorageBase &rVbaPrjStrg)
Reads vba module related information from the project streams.
void importVbaProject(StorageBase &rVbaPrjStrg, const GraphicHelper &rGraphicHelper)
Imports the entire VBA project from the passed storage.
void importModulesAndForms(StorageBase &rVbaPrjStrg, const GraphicHelper &rGraphicHelper)
Imports (and creates) vba modules and user forms from the vba project records previously read.
void importVbaData(const css::uno::Reference< css::io::XInputStream > &xInputStream)
Imports VBA data for a VBA project, e.g. word/vbaData.xml.
css::uno::Reference< css::container::XNameContainer > const & createDialogLibrary()
Creates and returns the dialog library of the document used for import.
virtual void prepareImport()
Called when the import process of the VBA project has been started.
void importVba(StorageBase &rVbaPrjStrg, const GraphicHelper &rGraphicHelper)
Imports the VBA code modules and forms.
css::uno::Reference< css::container::XNameContainer > openLibrary(sal_Int32 nPropId)
Opens a Basic or dialog library, creates missing if not found.
#define TOOLS_WARN_EXCEPTION(area, stream)
Reference< XSingleServiceFactory > xFactory
#define SAL_WARN_IF(condition, area, stream)
COMPHELPER_DLLPUBLIC void notifyMacroEventRead(const css::uno::Reference< css::frame::XModel > &_rxDocument)
bool readDirRecord(sal_uInt16 &rnRecId, StreamDataSequence &rRecData, BinaryInputStream &rInStrm)
Reads the next record from the VBA directory stream 'dir'.
bool extractKeyValue(OUString &rKey, OUString &rValue, std::u16string_view rKeyValue)
Extracts a key/value pair from a string separated by an equality sign.
const sal_uInt16 VBA_ID_PROJECTNAME
std::shared_ptr< VbaMacroAttacherBase > VbaMacroAttacherRef
const sal_uInt16 VBA_ID_MODULENAME
const sal_uInt16 VBA_ID_PROJECTCODEPAGE
const sal_uInt16 VBA_ID_PROJECTEND
const sal_uInt16 VBA_ID_PROJECTMODULES
std::shared_ptr< StorageBase > StorageRef
css::uno::Sequence< sal_Int8 > StreamDataSequence
Reference< XController > xController
Reference< XFrame > xFrame