1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 #include "oox/ole/vbaproject.hxx"
25
26 #include <com/sun/star/document/XStorageBasedDocument.hpp>
27 #include <com/sun/star/embed/ElementModes.hpp>
28 #include <com/sun/star/embed/XTransactedObject.hpp>
29 #include <com/sun/star/frame/XModel.hpp>
30 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
31 #include <com/sun/star/script/ModuleType.hpp>
32 #include <com/sun/star/script/XLibraryContainer.hpp>
33 #include <com/sun/star/script/vba/XVBACompatibility.hpp>
34 #include <com/sun/star/script/vba/XVBAMacroResolver.hpp>
35 #include <com/sun/star/uno/XComponentContext.hpp>
36 #include <comphelper/configurationhelper.hxx>
37 #include <comphelper/string.hxx>
38 #include <rtl/tencinfo.h>
39 #include <rtl/ustrbuf.h>
40 #include "oox/helper/binaryinputstream.hxx"
41 #include "oox/helper/containerhelper.hxx"
42 #include "oox/helper/propertyset.hxx"
43 #include "oox/helper/textinputstream.hxx"
44 #include "oox/ole/olestorage.hxx"
45 #include "oox/ole/vbacontrol.hxx"
46 #include "oox/ole/vbahelper.hxx"
47 #include "oox/ole/vbainputstream.hxx"
48 #include "oox/ole/vbamodule.hxx"
49
50 namespace oox {
51 namespace ole {
52
53 // ============================================================================
54
55 using namespace ::com::sun::star::container;
56 using namespace ::com::sun::star::document;
57 using namespace ::com::sun::star::embed;
58 using namespace ::com::sun::star::frame;
59 using namespace ::com::sun::star::io;
60 using namespace ::com::sun::star::lang;
61 using namespace ::com::sun::star::script;
62 using namespace ::com::sun::star::script::vba;
63 using namespace ::com::sun::star::uno;
64
65 using ::comphelper::ConfigurationHelper;
66 using ::rtl::OUString;
67 using ::rtl::OUStringBuffer;
68
69 // ============================================================================
70
71 namespace {
72
lclReadConfigItem(const Reference<XInterface> & rxConfigAccess,const OUString & rItemName)73 bool lclReadConfigItem( const Reference< XInterface >& rxConfigAccess, const OUString& rItemName )
74 {
75 // some applications do not support all configuration items, assume 'false' in this case
76 try
77 {
78 Any aItem = ConfigurationHelper::readRelativeKey( rxConfigAccess, CREATE_OUSTRING( "Filter/Import/VBA" ), rItemName );
79 return aItem.has< bool >() && aItem.get< bool >();
80 }
81 catch( Exception& )
82 {
83 }
84 return false;
85 }
86
87 } // namespace
88
89 // ----------------------------------------------------------------------------
90
VbaFilterConfig(const Reference<XComponentContext> & rxContext,const OUString & rConfigCompName)91 VbaFilterConfig::VbaFilterConfig( const Reference< XComponentContext >& rxContext, const OUString& rConfigCompName )
92 {
93 OSL_ENSURE( rxContext.is(), "VbaFilterConfig::VbaFilterConfig - missing component context" );
94 if( rxContext.is() ) try
95 {
96 OSL_ENSURE( rConfigCompName.getLength() > 0, "VbaFilterConfig::VbaFilterConfig - invalid configuration component name" );
97 OUString aConfigPackage = CREATE_OUSTRING( "org.openoffice.Office." ) + rConfigCompName;
98 Reference< XMultiServiceFactory > xFactory( rxContext->getServiceManager(), UNO_QUERY_THROW );
99 mxConfigAccess = ConfigurationHelper::openConfig( xFactory, aConfigPackage, ConfigurationHelper::E_READONLY );
100 }
101 catch( Exception& )
102 {
103 }
104 OSL_ENSURE( mxConfigAccess.is(), "VbaFilterConfig::VbaFilterConfig - cannot open configuration" );
105 }
106
~VbaFilterConfig()107 VbaFilterConfig::~VbaFilterConfig()
108 {
109 }
110
isImportVba() const111 bool VbaFilterConfig::isImportVba() const
112 {
113 return lclReadConfigItem( mxConfigAccess, CREATE_OUSTRING( "Load" ) );
114 }
115
isImportVbaExecutable() const116 bool VbaFilterConfig::isImportVbaExecutable() const
117 {
118 return lclReadConfigItem( mxConfigAccess, CREATE_OUSTRING( "Executable" ) );
119 }
120
isExportVba() const121 bool VbaFilterConfig::isExportVba() const
122 {
123 return lclReadConfigItem( mxConfigAccess, CREATE_OUSTRING( "Save" ) );
124 }
125
126 // ============================================================================
127
VbaMacroAttacherBase(const OUString & rMacroName)128 VbaMacroAttacherBase::VbaMacroAttacherBase( const OUString& rMacroName ) :
129 maMacroName( rMacroName )
130 {
131 OSL_ENSURE( maMacroName.getLength() > 0, "VbaMacroAttacherBase::VbaMacroAttacherBase - empty macro name" );
132 }
133
~VbaMacroAttacherBase()134 VbaMacroAttacherBase::~VbaMacroAttacherBase()
135 {
136 }
137
resolveAndAttachMacro(const Reference<XVBAMacroResolver> & rxResolver)138 void VbaMacroAttacherBase::resolveAndAttachMacro( const Reference< XVBAMacroResolver >& rxResolver )
139 {
140 try
141 {
142 attachMacro( rxResolver->resolveVBAMacroToScriptURL( maMacroName ) );
143 }
144 catch( Exception& )
145 {
146 }
147 }
148
149 // ============================================================================
150
VbaProject(const Reference<XComponentContext> & rxContext,const Reference<XModel> & rxDocModel,const OUString & rConfigCompName)151 VbaProject::VbaProject( const Reference< XComponentContext >& rxContext,
152 const Reference< XModel >& rxDocModel, const OUString& rConfigCompName ) :
153 VbaFilterConfig( rxContext, rConfigCompName ),
154 mxContext( rxContext ),
155 mxDocModel( rxDocModel ),
156 maPrjName( CREATE_OUSTRING( "Standard" ) )
157 {
158 OSL_ENSURE( mxContext.is(), "VbaProject::VbaProject - missing component context" );
159 OSL_ENSURE( mxDocModel.is(), "VbaProject::VbaProject - missing document model" );
160 mxBasicLib = openLibrary( PROP_BasicLibraries, false );
161 mxDialogLib = openLibrary( PROP_DialogLibraries, false );
162 }
163
~VbaProject()164 VbaProject::~VbaProject()
165 {
166 }
167
importVbaProject(StorageBase & rVbaPrjStrg,const GraphicHelper & rGraphicHelper,bool bDefaultColorBgr)168 void VbaProject::importVbaProject( StorageBase& rVbaPrjStrg, const GraphicHelper& rGraphicHelper, bool bDefaultColorBgr )
169 {
170 if( rVbaPrjStrg.isStorage() )
171 {
172 // load the code modules and forms
173 if( isImportVba() )
174 importVba( rVbaPrjStrg, rGraphicHelper, bDefaultColorBgr );
175 // copy entire storage into model
176 if( isExportVba() )
177 copyStorage( rVbaPrjStrg );
178 }
179 }
180
registerMacroAttacher(const VbaMacroAttacherRef & rxAttacher)181 void VbaProject::registerMacroAttacher( const VbaMacroAttacherRef& rxAttacher )
182 {
183 OSL_ENSURE( rxAttacher.get(), "VbaProject::registerMacroAttacher - unexpected empty reference" );
184 maMacroAttachers.push_back( rxAttacher );
185 }
186
hasModules() const187 bool VbaProject::hasModules() const
188 {
189 return mxBasicLib.is() && mxBasicLib->hasElements();
190 }
191
hasModule(const OUString & rModuleName) const192 bool VbaProject::hasModule( const OUString& rModuleName ) const
193 {
194 return mxBasicLib.is() && mxBasicLib->hasByName( rModuleName );
195 }
196
hasDialogs() const197 bool VbaProject::hasDialogs() const
198 {
199 return mxDialogLib.is() && mxDialogLib->hasElements();
200 }
201
hasDialog(const OUString & rDialogName) const202 bool VbaProject::hasDialog( const OUString& rDialogName ) const
203 {
204 return mxDialogLib.is() && mxDialogLib->hasByName( rDialogName );
205 }
206
207 // protected ------------------------------------------------------------------
208
addDummyModule(const OUString & rName,sal_Int32 nType)209 void VbaProject::addDummyModule( const OUString& rName, sal_Int32 nType )
210 {
211 OSL_ENSURE( rName.getLength() > 0, "VbaProject::addDummyModule - missing module name" );
212 maDummyModules[ rName ] = nType;
213 }
214
prepareImport()215 void VbaProject::prepareImport()
216 {
217 }
218
finalizeImport()219 void VbaProject::finalizeImport()
220 {
221 }
222
223 // private --------------------------------------------------------------------
224
getLibraryContainer(sal_Int32 nPropId)225 Reference< XLibraryContainer > VbaProject::getLibraryContainer( sal_Int32 nPropId )
226 {
227 PropertySet aDocProp( mxDocModel );
228 Reference< XLibraryContainer > xLibContainer( aDocProp.getAnyProperty( nPropId ), UNO_QUERY );
229 return xLibContainer;
230 }
231
openLibrary(sal_Int32 nPropId,bool bCreateMissing)232 Reference< XNameContainer > VbaProject::openLibrary( sal_Int32 nPropId, bool bCreateMissing )
233 {
234 Reference< XNameContainer > xLibrary;
235 try
236 {
237 Reference< XLibraryContainer > xLibContainer( getLibraryContainer( nPropId ), UNO_SET_THROW );
238 if( bCreateMissing && !xLibContainer->hasByName( CREATE_OUSTRING( "Standard" ) /*maPrjName*/ ) )
239 xLibContainer->createLibrary( CREATE_OUSTRING( "Standard" ) /*maPrjName*/ );
240 xLibrary.set( xLibContainer->getByName( CREATE_OUSTRING( "Standard" ) /*maPrjName*/ ), UNO_QUERY_THROW );
241 }
242 catch( Exception& )
243 {
244 }
245 OSL_ENSURE( !bCreateMissing || xLibrary.is(), "VbaProject::openLibrary - cannot create library" );
246 return xLibrary;
247 }
248
createBasicLibrary()249 Reference< XNameContainer > VbaProject::createBasicLibrary()
250 {
251 if( !mxBasicLib.is() )
252 mxBasicLib = openLibrary( PROP_BasicLibraries, true );
253 return mxBasicLib;
254 }
255
createDialogLibrary()256 Reference< XNameContainer > VbaProject::createDialogLibrary()
257 {
258 if( !mxDialogLib.is() )
259 mxDialogLib = openLibrary( PROP_DialogLibraries, true );
260 return mxDialogLib;
261 }
262
importVba(StorageBase & rVbaPrjStrg,const GraphicHelper & rGraphicHelper,bool bDefaultColorBgr)263 void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGraphicHelper, bool bDefaultColorBgr )
264 {
265 StorageRef xVbaStrg = rVbaPrjStrg.openSubStorage( CREATE_OUSTRING( "VBA" ), false );
266 OSL_ENSURE( xVbaStrg.get(), "VbaProject::importVba - cannot open 'VBA' substorage" );
267 if( !xVbaStrg )
268 return;
269
270 /* Read the 'VBA/dir' stream which contains general settings of the VBA
271 project such as the text encoding used throughout several streams, and
272 a list of all code modules.
273 */
274 BinaryXInputStream aInStrm( xVbaStrg->openInputStream( CREATE_OUSTRING( "dir" ) ), true );
275 // VbaInputStream implements decompression
276 VbaInputStream aDirStrm( aInStrm );
277 OSL_ENSURE( !aDirStrm.isEof(), "VbaProject::importVba - cannot open 'dir' stream" );
278 if( aDirStrm.isEof() )
279 return;
280
281 // virtual call, derived classes may do some preparations
282 prepareImport();
283
284 // read all records of the directory
285 rtl_TextEncoding eTextEnc = RTL_TEXTENCODING_MS_1252;
286 sal_uInt16 nModuleCount = 0;
287 bool bExecutable = isImportVbaExecutable();
288
289 typedef RefMap< OUString, VbaModule > VbaModuleMap;
290 VbaModuleMap aModules, aModulesByStrm;
291
292 sal_uInt16 nRecId = 0;
293 StreamDataSequence aRecData;
294 while( VbaHelper::readDirRecord( nRecId, aRecData, aDirStrm ) && (nRecId != VBA_ID_PROJECTEND) )
295 {
296 // create record stream object from imported record data
297 SequenceInputStream aRecStrm( aRecData );
298 sal_Int32 nRecSize = aRecData.getLength();
299 switch( nRecId )
300 {
301 #define OOX_ENSURE_RECORDSIZE( cond ) OSL_ENSURE( cond, "VbaProject::importVba - invalid record size" )
302 case VBA_ID_PROJECTCODEPAGE:
303 {
304 OOX_ENSURE_RECORDSIZE( nRecSize == 2 );
305 OSL_ENSURE( aModules.empty(), "VbaProject::importVba - unexpected PROJECTCODEPAGE record" );
306 rtl_TextEncoding eNewTextEnc = rtl_getTextEncodingFromWindowsCodePage( aRecStrm.readuInt16() );
307 OSL_ENSURE( eNewTextEnc != RTL_TEXTENCODING_DONTKNOW, "VbaProject::importVba - unknown text encoding" );
308 if( eNewTextEnc != RTL_TEXTENCODING_DONTKNOW )
309 eTextEnc = eNewTextEnc;
310 }
311 break;
312 case VBA_ID_PROJECTNAME:
313 {
314 OUString aPrjName = aRecStrm.readCharArrayUC( nRecSize, eTextEnc );
315 OSL_ENSURE( aPrjName.getLength() > 0, "VbaProject::importVba - invalid project name" );
316 if( aPrjName.getLength() > 0 )
317 maPrjName = aPrjName;
318 }
319 break;
320 case VBA_ID_PROJECTMODULES:
321 OOX_ENSURE_RECORDSIZE( nRecSize == 2 );
322 OSL_ENSURE( aModules.empty(), "VbaProject::importVba - unexpected PROJECTMODULES record" );
323 aRecStrm >> nModuleCount;
324 break;
325 case VBA_ID_MODULENAME:
326 {
327 OUString aName = aRecStrm.readCharArrayUC( nRecSize, eTextEnc );
328 OSL_ENSURE( aName.getLength() > 0, "VbaProject::importVba - invalid module name" );
329 OSL_ENSURE( !aModules.has( aName ), "VbaProject::importVba - multiple modules with the same name" );
330 VbaModuleMap::mapped_type& rxModule = aModules[ aName ];
331 rxModule.reset( new VbaModule( mxContext, mxDocModel, aName, eTextEnc, bExecutable ) );
332 // read all remaining records until the MODULEEND record
333 rxModule->importDirRecords( aDirStrm );
334 OSL_ENSURE( !aModulesByStrm.has( rxModule->getStreamName() ), "VbaProject::importVba - multiple modules with the same stream name" );
335 aModulesByStrm[ rxModule->getStreamName() ] = rxModule;
336 }
337 break;
338 #undef OOX_ENSURE_RECORDSIZE
339 }
340 }
341 OSL_ENSURE( nModuleCount == aModules.size(), "VbaProject::importVba - invalid module count" );
342
343 /* The directory does not contain the real type of the modules, it
344 distinguishes only between 'procedural' and 'document' (the latter
345 includes class and form modules). Now, the exact type of all modules
346 will be read from the 'PROJECT' stream. It consists of text lines in
347 'key=value' format which list the code modules by type.
348
349 - The line 'document=<modulename>/&HXXXXXXXX' declares document
350 modules. These are attached to the Word document (usually called
351 'ThisDocument'), the Excel workbook (usually called
352 'ThisWorkbook'), or single Excel worksheets or chartsheets (usually
353 called 'SheetX' or 'ChartX', X being a decimal number). Of course,
354 users may rename all these modules. The slash character separates
355 an automation server version number (hexadecimal 'XXXXXXXX') from
356 the module name.
357 - The line 'Module=<modulename>' declares common procedural code
358 modules.
359 - The line 'Class=<modulename>' declares a class module.
360 - The line 'BaseClass=<modulename>' declares a code module attached
361 to a user form with the same name.
362 */
363 BinaryXInputStream aPrjStrm( rVbaPrjStrg.openInputStream( CREATE_OUSTRING( "PROJECT" ) ), true );
364 OSL_ENSURE( !aPrjStrm.isEof(), "VbaProject::importVba - cannot open 'PROJECT' stream" );
365 // do not exit if this stream does not exist, but proceed to load the modules below
366 if( !aPrjStrm.isEof() )
367 {
368 TextInputStream aPrjTextStrm( mxContext, aPrjStrm, eTextEnc );
369 OUString aKey, aValue;
370 bool bExitLoop = false;
371 while( !bExitLoop && !aPrjTextStrm.isEof() )
372 {
373 // read a text line from the stream
374 OUString aLine = aPrjTextStrm.readLine().trim();
375 sal_Int32 nLineLen = aLine.getLength();
376 // exit if a subsection starts (section name is given in brackets)
377 bExitLoop = (nLineLen >= 2) && (aLine[ 0 ] == '[') && (aLine[ nLineLen - 1 ] == ']');
378 if( !bExitLoop && VbaHelper::extractKeyValue( aKey, aValue, aLine ) )
379 {
380 sal_Int32 nType = ModuleType::UNKNOWN;
381 if( aKey.equalsIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "Document" ) ) )
382 {
383 nType = ModuleType::DOCUMENT;
384 // strip automation server version from module names
385 sal_Int32 nSlashPos = aValue.indexOf( '/' );
386 if( nSlashPos >= 0 )
387 aValue = aValue.copy( 0, nSlashPos );
388 }
389 else if( aKey.equalsIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "Module" ) ) )
390 nType = ModuleType::NORMAL;
391 else if( aKey.equalsIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "Class" ) ) )
392 nType = ModuleType::CLASS;
393 else if( aKey.equalsIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "BaseClass" ) ) )
394 nType = ModuleType::FORM;
395
396 if( (nType != ModuleType::UNKNOWN) && (aValue.getLength() > 0) )
397 {
398 OSL_ENSURE( aModules.has( aValue ), "VbaProject::importVba - module not found" );
399 if( VbaModule* pModule = aModules.get( aValue ).get() )
400 pModule->setType( nType );
401 }
402 }
403 }
404 }
405
406 // create empty dummy modules
407 VbaModuleMap aDummyModules;
408 for( DummyModuleMap::iterator aIt = maDummyModules.begin(), aEnd = maDummyModules.end(); aIt != aEnd; ++aIt )
409 {
410 OSL_ENSURE( !aModules.has( aIt->first ) && !aDummyModules.has( aIt->first ), "VbaProject::importVba - multiple modules with the same name" );
411 VbaModuleMap::mapped_type& rxModule = aDummyModules[ aIt->first ];
412 rxModule.reset( new VbaModule( mxContext, mxDocModel, aIt->first, eTextEnc, bExecutable ) );
413 rxModule->setType( aIt->second );
414 }
415
416 /* Now it is time to load the source code. All modules will be inserted
417 into the Basic library of the document specified by the 'maPrjName'
418 member. Do not create the Basic library, if there are no modules
419 specified. */
420 if( !aModules.empty() || !aDummyModules.empty() ) try
421 {
422 // get the model factory and the basic library
423 Reference< XMultiServiceFactory > xModelFactory( mxDocModel, UNO_QUERY_THROW );
424 Reference< XNameContainer > xBasicLib( createBasicLibrary(), UNO_SET_THROW );
425
426 /* Set library container to VBA compatibility mode. This will create
427 the VBA Globals object and store it in the Basic manager of the
428 document. */
429 try
430 {
431 Reference< XVBACompatibility >( getLibraryContainer( PROP_BasicLibraries ), UNO_QUERY_THROW )->setVBACompatibilityMode( sal_True );
432 }
433 catch( Exception& )
434 {
435 }
436
437 // try to get access to document objects related to code modules
438 Reference< XNameAccess > xDocObjectNA;
439 try
440 {
441 xDocObjectNA.set( xModelFactory->createInstance( CREATE_OUSTRING( "ooo.vba.VBAObjectModuleObjectProvider" ) ), UNO_QUERY );
442 }
443 catch( Exception& )
444 {
445 // not all documents support this
446 }
447
448 if( xBasicLib.is() )
449 {
450 // call Basic source code import for each module, boost::[c]ref enforces pass-by-ref
451 aModules.forEachMem( &VbaModule::createAndImportModule,
452 ::boost::ref( *xVbaStrg ), ::boost::cref( xBasicLib ),
453 ::boost::cref( xDocObjectNA ) );
454
455 // create empty dummy modules
456 aDummyModules.forEachMem( &VbaModule::createEmptyModule,
457 ::boost::cref( xBasicLib ), ::boost::cref( xDocObjectNA ) );
458 }
459 }
460 catch( Exception& )
461 {
462 }
463
464 /* Load the forms. The file format specification requires that a module
465 must exist for every form. We are a bit more tolerant and scan the
466 project storage for all form substorages. This may 'repair' broken VBA
467 storages that misses to mention a module for an existing form. */
468 ::std::vector< OUString > aElements;
469 rVbaPrjStrg.getElementNames( aElements );
470 for( ::std::vector< OUString >::iterator aIt = aElements.begin(), aEnd = aElements.end(); aIt != aEnd; ++aIt )
471 {
472 // try to open the element as storage
473 if( !aIt->equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "VBA" ) ) )
474 {
475 StorageRef xSubStrg = rVbaPrjStrg.openSubStorage( *aIt, false );
476 if( xSubStrg.get() ) try
477 {
478 // resolve module name from storage name (which equals the module stream name)
479 VbaModule* pModule = aModulesByStrm.get( *aIt ).get();
480 OSL_ENSURE( pModule && (pModule->getType() == ModuleType::FORM),
481 "VbaProject::importVba - form substorage without form module" );
482 OUString aModuleName;
483 if( pModule )
484 aModuleName = pModule->getName();
485
486 // create and import the form
487 Reference< XNameContainer > xDialogLib( createDialogLibrary(), UNO_SET_THROW );
488 VbaUserForm aForm( mxContext, mxDocModel, rGraphicHelper, bDefaultColorBgr );
489 aForm.importForm( xDialogLib, *xSubStrg, aModuleName, eTextEnc );
490 }
491 catch( Exception& )
492 {
493 }
494 }
495 }
496
497 // attach macros to registered objects
498 attachMacros();
499 // virtual call, derived classes may do some more processing
500 finalizeImport();
501 }
502
attachMacros()503 void VbaProject::attachMacros()
504 {
505 if( !maMacroAttachers.empty() && mxContext.is() ) try
506 {
507 Reference< XMultiComponentFactory > xFactory( mxContext->getServiceManager(), UNO_SET_THROW );
508 Sequence< Any > aArgs( 2 );
509 aArgs[ 0 ] <<= mxDocModel;
510 aArgs[ 1 ] <<= maPrjName;
511 Reference< XVBAMacroResolver > xResolver( xFactory->createInstanceWithArgumentsAndContext(
512 CREATE_OUSTRING( "com.sun.star.script.vba.VBAMacroResolver" ), aArgs, mxContext ), UNO_QUERY_THROW );
513 maMacroAttachers.forEachMem( &VbaMacroAttacherBase::resolveAndAttachMacro, ::boost::cref( xResolver ) );
514 }
515 catch( Exception& )
516 {
517 }
518 }
519
copyStorage(StorageBase & rVbaPrjStrg)520 void VbaProject::copyStorage( StorageBase& rVbaPrjStrg )
521 {
522 if( mxContext.is() ) try
523 {
524 Reference< XStorageBasedDocument > xStorageBasedDoc( mxDocModel, UNO_QUERY_THROW );
525 Reference< XStorage > xDocStorage( xStorageBasedDoc->getDocumentStorage(), UNO_QUERY_THROW );
526 {
527 const sal_Int32 nOpenMode = ElementModes::SEEKABLE | ElementModes::WRITE | ElementModes::TRUNCATE;
528 Reference< XStream > xDocStream( xDocStorage->openStreamElement( CREATE_OUSTRING( "_MS_VBA_Macros" ), nOpenMode ), UNO_SET_THROW );
529 OleStorage aDestStorage( mxContext, xDocStream, false );
530 rVbaPrjStrg.copyStorageToStorage( aDestStorage );
531 aDestStorage.commit();
532 }
533 Reference< XTransactedObject >( xDocStorage, UNO_QUERY_THROW )->commit();
534 }
535 catch( Exception& )
536 {
537 }
538 }
539
540 // ============================================================================
541
542 } // namespace ole
543 } // namespace oox
544