// if the GraphicHelper tries to use noStorage it will of course crash // but... this shouldn't happen as there is no reason for GraphicHelper // to do that when importing VBA projects
GraphicHelper grfHlp(mxContext, xFrame, StorageRef());
importVbaProject( rVbaPrjStrg, grfHlp ); // return true if something has been imported return (mxBasicLib.is() && mxBasicLib->hasElements()) ||
(mxDialogLib.is() && mxDialogLib->hasElements());
}
void VbaProject::importVbaProject( StorageBase& rVbaPrjStrg, const GraphicHelper& rGraphicHelper )
{ if( rVbaPrjStrg.isStorage() )
{ // load the code modules and forms if( isImportVba() )
importVba( rVbaPrjStrg, rGraphicHelper ); // copy entire storage into model if( isExportVba() )
copyStorage( rVbaPrjStrg );
}
}
/* Read the 'VBA/dir' stream which contains general settings of the VBA projectsuchasthetextencodingusedthroughoutseveralstreams,and alistofallcodemodules.
*/
BinaryXInputStream aInStrm( xVbaStrg->openInputStream( u"dir"_ustr ), true ); // VbaInputStream implements decompression
VbaInputStream aDirStrm( aInStrm );
OSL_ENSURE( !aDirStrm.isEof(), "VbaProject::importVba - cannot open 'dir' stream" ); if( aDirStrm.isEof() ) return;
// virtual call, derived classes may do some preparations
prepareImport();
// read all records of the directory
rtl_TextEncoding eTextEnc = RTL_TEXTENCODING_MS_1252;
sal_uInt16 nModuleCount = 0; bool bExecutable = isImportVbaExecutable();
/* The directory does not contain the real type of the modules, it distinguishesonlybetween'procedural'and'document'(thelatter includesclassandformmodules).Now,theexacttypeofallmodules willbereadfromthe'PROJECT'stream.Itconsistsoftextlinesin 'key=value'formatwhichlistthecodemodulesbytype.
-Theline'document=<modulename>/&HXXXXXXXX'declaresdocument modules.TheseareattachedtotheWorddocument(usuallycalled 'ThisDocument'),theExcelworkbook(usuallycalled 'ThisWorkbook'),orsingleExcelworksheetsorchartsheets(usually called'SheetX'or'ChartX',Xbeingadecimalnumber).Ofcourse, usersmayrenameallthesemodules.Theslashcharacterseparates anautomationserverversionnumber(hexadecimal'XXXXXXXX')from themodulename. -Theline'Module=<modulename>'declarescommonproceduralcode modules. -Theline'Class=<modulename>'declaresaclassmodule. -Theline'BaseClass=<modulename>'declaresacodemoduleattached toauserformwiththesamename.
*/
BinaryXInputStream aPrjStrm( rVbaPrjStrg.openInputStream( u"PROJECT"_ustr ), true );
OSL_ENSURE( !aPrjStrm.isEof(), "VbaProject::importVba - cannot open 'PROJECT' stream" ); // do not exit if this stream does not exist, but proceed to load the modules below if( !aPrjStrm.isEof() )
{
TextInputStream aPrjTextStrm( mxContext, aPrjStrm, eTextEnc );
OUString aKey, aValue; bool bExitLoop = false; while( !bExitLoop && !aPrjTextStrm.isEof() )
{ // read a text line from the stream
OUString aLine = aPrjTextStrm.readLine().trim();
sal_Int32 nLineLen = aLine.getLength(); // exit if a subsection starts (section name is given in brackets)
bExitLoop = (nLineLen >= 2) && (aLine[ 0 ] == '[') && (aLine[ nLineLen - 1 ] == ']'); if( !bExitLoop && VbaHelper::extractKeyValue( aKey, aValue, aLine ) )
{
sal_Int32 nType = ModuleType::UNKNOWN; if( aKey.equalsIgnoreAsciiCase( "Document" ) )
{
nType = ModuleType::DOCUMENT; // strip automation server version from module names
sal_Int32 nSlashPos = aValue.indexOf( '/' ); if( nSlashPos >= 0 )
aValue = aValue.copy( 0, nSlashPos );
} elseif( aKey.equalsIgnoreAsciiCase( "Module" ) )
nType = ModuleType::NORMAL; elseif( aKey.equalsIgnoreAsciiCase( "Class" ) )
nType = ModuleType::CLASS; elseif( aKey.equalsIgnoreAsciiCase( "BaseClass" ) )
nType = ModuleType::FORM;
/* Now it is time to load the source code. All modules will be inserted intotheBasiclibraryofthedocumentspecifiedbythe'maPrjName' member.DonotcreatetheBasiclibrary,iftherearenomodules
specified. */ 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 );
// try to get access to document objects related to code modules
Reference< XNameAccess > xDocObjectNA; try
{
xDocObjectNA.set( xModelFactory->createInstance( u"ooo.vba.VBAObjectModuleObjectProvider"_ustr ), UNO_QUERY );
} catch(const Exception& )
{ // not all documents support this
}
if( xBasicLib.is() )
{ // #TODO cater for mxOleOverridesSink, like I used to before // call Basic source code import for each module, std::[c]ref enforces pass-by-ref
maModules.forEachMem( &VbaModule::createAndImportModule,
::std::ref( *xVbaStrg ), ::std::cref( xBasicLib ),
::std::cref( xDocObjectNA ) );
/* Load the forms. The file format specification requires that a module mustexistforeveryform.Weareabitmoretolerantandscanthe projectstorageforallformsubstorages.Thismay'repair'brokenVBA
storages that misses to mention a module for an existing form. */
::std::vector< OUString > aElements;
rVbaPrjStrg.getElementNames( aElements ); for (autoconst& elem : aElements)
{ // try to open the element as storage if( elem != "VBA" )
{
StorageRef xSubStrg = rVbaPrjStrg.openSubStorage( elem, false ); if( xSubStrg ) try
{ // resolve module name from storage name (which equals the module stream name)
VbaModule* pModule = maModulesByStrm.get( elem ).get();
OSL_ENSURE( pModule && (pModule->getType() == ModuleType::FORM), "VbaProject::importVba - form substorage without form module" );
OUString aModuleName; if( pModule )
aModuleName = pModule->getName();
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.