21#include <com/sun/star/container/XNameContainer.hpp>
22#include <com/sun/star/script/ModuleInfo.hpp>
23#include <com/sun/star/script/ModuleType.hpp>
24#include <com/sun/star/script/vba/XVBAModuleInfo.hpp>
25#include <com/sun/star/awt/KeyEvent.hpp>
26#include <osl/diagnose.h>
27#include <rtl/character.hxx>
44using ::com::sun::star::awt::KeyEvent;
47 const Reference< frame::XModel >& rxDocModel,
48 OUString aName, rtl_TextEncoding eTextEnc,
bool bExecutable ) :
50 mxDocModel( rxDocModel ),
52 meTextEnc( eTextEnc ),
57 mbExecutable( bExecutable )
63 sal_uInt16 nRecId = 0;
68 sal_Int32 nRecSize = aRecData.getLength();
71#define OOX_ENSURE_RECORDSIZE( cond ) OSL_ENSURE( cond, "VbaModule::importDirRecords - invalid record size" )
73 OSL_FAIL(
"VbaModule::importDirRecords - unexpected MODULENAME record" );
103 OSL_ENSURE(
mnType == script::ModuleType::UNKNOWN,
"VbaModule::importDirRecords - multiple module type records" );
104 mnType = script::ModuleType::NORMAL;
108 OSL_ENSURE(
mnType == script::ModuleType::UNKNOWN,
"VbaModule::importDirRecords - multiple module type records" );
109 mnType = script::ModuleType::DOCUMENT;
120 OSL_FAIL(
"VbaModule::importDirRecords - unknown module record" );
121#undef OOX_ENSURE_RECORDSIZE
124 OSL_ENSURE( !
maName.isEmpty(),
"VbaModule::importDirRecords - missing module name" );
125 OSL_ENSURE( !
maStreamName.isEmpty(),
"VbaModule::importDirRecords - missing module stream name" );
126 OSL_ENSURE(
mnType != script::ModuleType::UNKNOWN,
"VbaModule::importDirRecords - missing module type" );
131 const Reference< container::XNameContainer >& rxBasicLib,
132 const Reference< container::XNameAccess >& rxDocObjectNA )
135 createModule( aVBASourceCode, rxBasicLib, rxDocObjectNA );
155 const Reference< container::XNameAccess >& rxDocObjectNA )
const
162 OUStringBuffer aSourceCode(512);
163 static const char sUnmatchedRemovedTag[] =
"Rem removed unmatched Sub/End: ";
167 OSL_ENSURE( !aInStrm.
isEof(),
"VbaModule::readSourceCode - cannot open module stream" );
171 if( !aInStrm.
isEof() )
182 ProcedurePair() : bInProcedure(
false ),
nPos( 0 ) {};
185 while( !aVbaTextStrm.
isEof() )
187 OUString aCodeLine = aVbaTextStrm.
readLine();
188 if( aCodeLine.match(
"Attribute " ) )
191 int index = aCodeLine.indexOf(
".VB_ProcData.VB_Invoke_Func = " );
200 int nSpaceIndex = aCodeLine.indexOf(
' ');
201 OUString sProc = aCodeLine.copy( nSpaceIndex + 1,
index - nSpaceIndex - 1);
203 std::u16string_view sKey = aCodeLine.subView( aCodeLine.lastIndexOf(
"= ") + 3, 1 );
205 if ( rtl::isAsciiAlpha( sKey[ 0 ] ) )
209 OUString sApiKey = OUString::Concat(
"^") + sKey;
220 OUString trimLine( aCodeLine.trim() );
222 trimLine.match(
"Sub ") ||
223 trimLine.match(
"Public Sub ") ||
224 trimLine.match(
"Private Sub ") ||
225 trimLine.match(
"Static Sub ") ) )
229 if ( procInfo.bInProcedure )
232 aSourceCode.insert( procInfo.nPos, sUnmatchedRemovedTag );
234 procInfo.nPos = aSourceCode.getLength();
238 procInfo.bInProcedure =
true;
239 procInfo.nPos = aSourceCode.getLength();
245 if ( !procInfo.bInProcedure )
247 aSourceCode.append( sUnmatchedRemovedTag );
251 procInfo.bInProcedure =
false;
257 aSourceCode.append(
"Rem " );
258 aSourceCode.append( aCodeLine +
"\n" );
263 return aSourceCode.makeStringAndClear();
267 const Reference< container::XNameContainer >& rxBasicLib,
268 const Reference< container::XNameAccess >& rxDocObjectNA )
const
274 script::ModuleInfo aModuleInfo;
275 aModuleInfo.ModuleType =
mnType;
276 OUStringBuffer aSourceCode(512);
277 aSourceCode.append(
"Rem Attribute VBA_ModuleType=" );
280 case script::ModuleType::NORMAL:
281 aSourceCode.append(
"VBAModule" );
283 case script::ModuleType::CLASS:
284 aSourceCode.append(
"VBAClassModule" );
286 case script::ModuleType::FORM:
287 aSourceCode.append(
"VBAFormModule" );
289 aModuleInfo.ModuleObject.set(
mxDocModel, UNO_QUERY );
291 case script::ModuleType::DOCUMENT:
292 aSourceCode.append(
"VBADocumentModule" );
294 if( rxDocObjectNA.is() )
try
296 aModuleInfo.ModuleObject.set( rxDocObjectNA->getByName(
maName ), UNO_QUERY );
303 aSourceCode.append(
"VBAUnknown" );
305 aSourceCode.append(
'\n' );
308 aSourceCode.append(
"Option VBASupport 1\n" );
309 if(
mnType == script::ModuleType::CLASS )
310 aSourceCode.append(
"Option ClassModule\n" );
315 aSourceCode.append(
"Sub " +
maName.replace(
' ',
'_' ) +
"\n" );
319 aSourceCode.append( rVBASourceCode );
323 aSourceCode.append(
"End Sub\n" );
328 Reference< XVBAModuleInfo > xVBAModuleInfo( rxBasicLib, UNO_QUERY_THROW );
329 xVBAModuleInfo->insertModuleInfo(
maName, aModuleInfo );
338 rxBasicLib->insertByName(
maName,
Any( aSourceCode.makeStringAndClear() ) );
342 OSL_FAIL(
"VbaModule::createModule - cannot insert module into library" );
bool isEof() const
Returns true, if the stream position is invalid (EOF).
virtual void seek(sal_Int64 nPos) override
Seeks the stream to the passed position, if wrapped stream is seekable.
Base class for storage access implementations.
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.
OUString readLine()
Reads a text line from the stream.
css::uno::Reference< css::frame::XModel > mxDocModel
Document model used to import/export the VBA project.
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.
css::uno::Reference< css::uno::XComponentContext > mxContext
Component context with service manager.
rtl_TextEncoding meTextEnc
std::vector< VbaMacroKeyAndMethodBinding > maKeyBindings
Keys and VBA macro method bindings.
void registerShortcutKeys()
void createModule(std::u16string_view rVBASourceCode, const css::uno::Reference< css::container::XNameContainer > &rxBasicLib, const css::uno::Reference< css::container::XNameAccess > &rxDocObjectNA) const
Creates a new Basic module and inserts it into the passed Basic library.
void importDirRecords(BinaryInputStream &rDirStrm)
Imports all records for this module until the MODULEEND record.
VbaModule(const css::uno::Reference< css::uno::XComponentContext > &rxContext, const css::uno::Reference< css::frame::XModel > &rxDocModel, OUString aName, rtl_TextEncoding eTextEnc, bool bExecutable)
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.
OUString readSourceCode(StorageBase &rVbaStrg)
Reads and returns the VBA source code from the passed storage.
std::basic_string_view< charT, traits > trim(std::basic_string_view< charT, traits > str)
constexpr bool starts_with(std::basic_string_view< charT, traits > sv, std::basic_string_view< charT, traits > x) noexcept
awt::KeyEvent parseKeyEvent(std::u16string_view Key)
void applyShortCutKeyBinding(const uno::Reference< frame::XModel > &rxModel, const awt::KeyEvent &rKeyEvent, const OUString &rMacroName)
bool readDirRecord(sal_uInt16 &rnRecId, StreamDataSequence &rRecData, BinaryInputStream &rInStrm)
Reads the next record from the VBA directory stream 'dir'.
const sal_uInt16 VBA_ID_MODULEDOCSTRINGUNICODE
const sal_uInt16 VBA_ID_MODULEHELPCONTEXT
const sal_uInt16 VBA_ID_MODULETYPEPROCEDURAL
const sal_uInt16 VBA_ID_MODULENAME
const sal_uInt16 VBA_ID_MODULEDOCSTRING
const sal_uInt16 VBA_ID_MODULESTREAMNAMEUNICODE
const sal_uInt16 VBA_ID_MODULETYPEDOCUMENT
const sal_uInt16 VBA_ID_MODULEOFFSET
const sal_uInt16 VBA_ID_MODULECOOKIE
const sal_uInt16 VBA_ID_MODULEPRIVATE
const sal_uInt16 VBA_ID_MODULESTREAMNAME
const sal_uInt16 VBA_ID_MODULENAMEUNICODE
const sal_uInt16 VBA_ID_MODULEREADONLY
const sal_uInt16 VBA_ID_MODULEEND
css::uno::Sequence< sal_Int8 > StreamDataSequence
Stores, which key shortcut maps to which VBA macro method.
#define OOX_ENSURE_RECORDSIZE(cond)