1 /*************************************************************************
3 * OpenOffice.org - a multi-platform office productivity suite
5 * $RCSfile: vbaeventshelper.cxx,v $
9 * last change: $Author: vg $ $Date: 2007/12/07 10:42:26 $
11 * The Contents of this file are made available subject to
12 * the terms of GNU Lesser General Public License Version 2.1.
15 * GNU Lesser General Public License Version 2.1
16 * =============================================
17 * Copyright 2005 by Sun Microsystems, Inc.
18 * 901 San Antonio Road, Palo Alto, CA 94303, USA
20 * This library is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU Lesser General Public
22 * License version 2.1, as published by the Free Software Foundation.
24 * This library is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 * Lesser General Public License for more details.
29 * You should have received a copy of the GNU Lesser General Public
30 * License along with this library; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
34 ************************************************************************/
35 #include "vbaeventshelper.hxx"
36 #include <vbahelper/helperdecl.hxx>
37 #include <sfx2/objsh.hxx>
38 #include "scextopt.hxx"
39 #include <sfx2/evntconf.hxx>
40 #include <sfx2/event.hxx>
41 #include <sfx2/sfx.hrc>
42 #include <toolkit/unohlp.hxx>
43 #include <comphelper/processfactory.hxx>
44 #include <cppuhelper/implbase1.hxx>
45 #include <com/sun/star/sheet/XSheetCellRangeContainer.hpp>
46 #include <com/sun/star/document/XEventsSupplier.hpp>
47 #include <com/sun/star/sheet/XCellRangeReferrer.hpp>
48 #include <com/sun/star/table/XCell.hpp>
49 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
50 #include <com/sun/star/sheet/XSpreadsheet.hpp>
51 #include <com/sun/star/container/XNamed.hpp>
52 #include <com/sun/star/awt/WindowEvent.hpp>
53 #include <com/sun/star/lang/EventObject.hpp>
54 #include <com/sun/star/util/XCloseListener.hpp>
55 #include <com/sun/star/util/XCloseBroadcaster.hpp>
56 #include <com/sun/star/frame/XControllerBorder.hpp>
57 #include <com/sun/star/frame/XBorderResizeListener.hpp>
58 #include <com/sun/star/util/XChangesListener.hpp>
59 #include <com/sun/star/util/ElementChange.hpp>
60 #include <com/sun/star/util/XChangesNotifier.hpp>
61 #include <com/sun/star/sheet/XCellRangeAddressable.hpp>
62 #include <cellsuno.hxx>
63 #include <convuno.hxx>
65 #include <svx/msvbahelper.hxx>
66 #include <vcl/svapp.hxx>
69 using namespace com::sun::star
;
70 using namespace ooo::vba
;
71 using namespace com::sun::star::document::VbaEventId
;
73 typedef ::cppu::WeakImplHelper1
< util::XChangesListener
> WorksheetChangeListener_BASE
;
75 class WorksheetChangeListener
: public WorksheetChangeListener_BASE
78 ScVbaEventsHelper
* pVbaEventsHelper
;
80 WorksheetChangeListener(ScVbaEventsHelper
* pHelper
) : pVbaEventsHelper( pHelper
){}
81 virtual void SAL_CALL
changesOccurred(const util::ChangesEvent
& aEvent
) throw (uno::RuntimeException
);
82 virtual void SAL_CALL
disposing(const lang::EventObject
& aSource
) throw(uno::RuntimeException
){}
85 void WorksheetChangeListener::changesOccurred(const util::ChangesEvent
& aEvent
) throw (uno::RuntimeException
)
87 sal_Int32 nCount
= aEvent
.Changes
.getLength();
91 util::ElementChange aChange
= aEvent
.Changes
[ 0 ];
92 rtl::OUString sOperation
;
93 aChange
.Accessor
>>= sOperation
;
94 if( !sOperation
.equalsIgnoreAsciiCaseAscii("cell-change") )
99 uno::Reference
< table::XCellRange
> xRangeObj
;
100 aChange
.ReplacedElement
>>= xRangeObj
;
103 uno::Sequence
< uno::Any
> aArgs(1);
104 aArgs
[0] <<= xRangeObj
;
105 pVbaEventsHelper
->ProcessCompatibleVbaEvent( VBAEVENT_WORKSHEET_CHANGE
, aArgs
);
110 ScRangeList aRangeList
;
111 for( sal_Int32 nIndex
= 0; nIndex
< nCount
; ++nIndex
)
113 aChange
= aEvent
.Changes
[ nIndex
];
114 aChange
.Accessor
>>= sOperation
;
115 uno::Reference
< table::XCellRange
> xRangeObj
;
116 aChange
.ReplacedElement
>>= xRangeObj
;
117 if( xRangeObj
.is() && sOperation
.equalsIgnoreAsciiCaseAscii("cell-change") )
119 uno::Reference
< sheet::XCellRangeAddressable
> xCellRangeAddressable( xRangeObj
, uno::UNO_QUERY
);
120 if( xCellRangeAddressable
.is() )
123 ScUnoConversion::FillScRange( aRange
, xCellRangeAddressable
->getRangeAddress() );
124 aRangeList
.Append( aRange
);
129 if( aRangeList
.Count() > 0 )
131 uno::Reference
< sheet::XSheetCellRangeContainer
> xRanges( new ScCellRangesObj( pVbaEventsHelper
->getDocumentShell(), aRangeList
) );
132 uno::Sequence
< uno::Any
> aArgs(1);
133 aArgs
[0] <<= xRanges
;
134 pVbaEventsHelper
->ProcessCompatibleVbaEvent( VBAEVENT_WORKSHEET_CHANGE
, aArgs
);
138 typedef ::cppu::WeakImplHelper3
< awt::XWindowListener
, util::XCloseListener
, frame::XBorderResizeListener
> WindowListener_BASE
;
140 // This class is to process Workbook window related event
141 class VbaEventsListener
: public WindowListener_BASE
143 ::osl::Mutex m_aMutex
;
144 ScVbaEventsHelper
* pVbaEventsHelper
;
145 uno::Reference
< frame::XModel
> m_xModel
;
146 sal_Bool m_bWindowResized
;
147 sal_Bool m_bBorderChanged
;
149 uno::Reference
< awt::XWindow
> GetContainerWindow();
150 uno::Reference
< frame::XFrame
> GetFrame();
151 sal_Bool
IsMouseReleased();
152 DECL_LINK( fireResizeMacro
, void* );
153 void processWindowResizeMacro();
155 VbaEventsListener( ScVbaEventsHelper
* pHelper
);
156 ~VbaEventsListener();
157 void startEventsLinstener();
158 void stopEventsLinstener();
160 virtual void SAL_CALL
windowResized( const awt::WindowEvent
& aEvent
) throw ( uno::RuntimeException
);
161 virtual void SAL_CALL
windowMoved( const awt::WindowEvent
& aEvent
) throw ( uno::RuntimeException
);
162 virtual void SAL_CALL
windowShown( const lang::EventObject
& aEvent
) throw ( uno::RuntimeException
);
163 virtual void SAL_CALL
windowHidden( const lang::EventObject
& aEvent
) throw ( uno::RuntimeException
);
164 virtual void SAL_CALL
disposing( const lang::EventObject
& aEvent
) throw ( uno::RuntimeException
);
166 virtual void SAL_CALL
queryClosing( const lang::EventObject
& Source
, ::sal_Bool GetsOwnership
) throw (util::CloseVetoException
, uno::RuntimeException
);
167 virtual void SAL_CALL
notifyClosing( const lang::EventObject
& Source
) throw (uno::RuntimeException
);
168 // XBorderResizeListener
169 virtual void SAL_CALL
borderWidthsChanged( const uno::Reference
< uno::XInterface
>& aObject
, const frame::BorderWidths
& aNewSize
) throw (uno::RuntimeException
);
171 VbaEventsListener::VbaEventsListener( ScVbaEventsHelper
* pHelper
) : pVbaEventsHelper( pHelper
)
173 OSL_TRACE("VbaEventsListener::VbaEventsListener( 0x%x ) - ctor ", this );
174 m_xModel
.set( pVbaEventsHelper
->getDocument()->GetDocumentShell()->GetModel(), uno::UNO_QUERY
);
175 m_bWindowResized
= sal_False
;
176 m_bBorderChanged
= sal_False
;
179 VbaEventsListener::~VbaEventsListener()
181 OSL_TRACE("VbaEventsListener::~VbaEventsListener( 0x%x ) - dtor ", this );
183 uno::Reference
< frame::XFrame
>
184 VbaEventsListener::GetFrame()
188 if( pVbaEventsHelper
)
192 uno::Reference
< frame::XController
> xController( m_xModel
->getCurrentController(), uno::UNO_QUERY
);
193 if( xController
.is() )
195 uno::Reference
< frame::XFrame
> xFrame( xController
->getFrame(), uno::UNO_QUERY
);
204 catch( uno::Exception
& /*e*/ )
207 return uno::Reference
< frame::XFrame
>();
209 uno::Reference
< awt::XWindow
>
210 VbaEventsListener::GetContainerWindow()
214 uno::Reference
< frame::XFrame
> xFrame( GetFrame(), uno::UNO_QUERY
);
217 uno::Reference
< awt::XWindow
> xWindow( xFrame
->getContainerWindow(), uno::UNO_QUERY
);
222 catch( uno::Exception
& /*e*/ )
225 return uno::Reference
< awt::XWindow
>();
228 VbaEventsListener::IsMouseReleased()
230 Window
* pWindow
= (VCLUnoHelper::GetWindow( GetContainerWindow() ) );
233 Window::PointerState aPointerState
= pWindow
->GetPointerState();
234 if( !aPointerState
.mnState
& ( MOUSE_LEFT
| MOUSE_MIDDLE
| MOUSE_RIGHT
) )
240 VbaEventsListener::startEventsLinstener()
244 // add window listener
245 uno::Reference
< awt::XWindow
> xWindow( GetContainerWindow(), uno::UNO_QUERY
);
247 xWindow
->addWindowListener( this );
248 // add close listener
249 //uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( GetFrame(), uno::UNO_QUERY );
250 uno::Reference
< util::XCloseBroadcaster
> xCloseBroadcaster( m_xModel
, uno::UNO_QUERY
);
251 if( xCloseBroadcaster
.is() )
253 xCloseBroadcaster
->addCloseListener( this );
255 // add Border resize listener
256 uno::Reference
< frame::XController
> xController( m_xModel
->getCurrentController(), uno::UNO_QUERY
);
257 if( xController
.is() )
259 uno::Reference
< frame::XControllerBorder
> xControllerBorder( xController
, uno::UNO_QUERY
);
260 if( xControllerBorder
.is() )
262 xControllerBorder
->addBorderResizeListener( this );
268 VbaEventsListener::stopEventsLinstener()
272 uno::Reference
< awt::XWindow
> xWindow( GetContainerWindow(), uno::UNO_QUERY
);
275 xWindow
->removeWindowListener( this );
277 //uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( GetFrame(), uno::UNO_QUERY );
278 uno::Reference
< util::XCloseBroadcaster
> xCloseBroadcaster( m_xModel
, uno::UNO_QUERY
);
279 if( xCloseBroadcaster
.is() )
281 xCloseBroadcaster
->removeCloseListener( this );
283 uno::Reference
< frame::XController
> xController( m_xModel
->getCurrentController(), uno::UNO_QUERY
);
284 if( xController
.is() )
286 uno::Reference
< frame::XControllerBorder
> xControllerBorder( xController
, uno::UNO_QUERY
);
287 if( xControllerBorder
.is() )
289 xControllerBorder
->removeBorderResizeListener( this );
292 pVbaEventsHelper
= NULL
;
297 VbaEventsListener::processWindowResizeMacro()
299 OSL_TRACE("**** Attempt to FIRE MACRO **** ");
300 if( pVbaEventsHelper
)
301 pVbaEventsHelper
->ProcessCompatibleVbaEvent( VBAEVENT_WORKBOOK_WINDOWRESIZE
, uno::Sequence
< uno::Any
>() );
304 IMPL_LINK( VbaEventsListener
, fireResizeMacro
, void*, pParam
)
306 if ( pVbaEventsHelper
)
308 if( IsMouseReleased() )
309 processWindowResizeMacro();
316 VbaEventsListener::windowResized( const awt::WindowEvent
& /*aEvent*/ ) throw ( uno::RuntimeException
)
318 ::osl::MutexGuard
aGuard( m_aMutex
);
319 // Workbook_window_resize event
320 m_bWindowResized
= sal_True
;
321 Window
* pWindow
= (VCLUnoHelper::GetWindow( GetContainerWindow() ) );
323 if( pWindow
&& m_bBorderChanged
)
325 m_bBorderChanged
= m_bWindowResized
= sal_False
;
326 acquire(); // ensure we don't get deleted before the event is handled
327 Application::PostUserEvent( LINK( this, VbaEventsListener
, fireResizeMacro
), NULL
);
331 VbaEventsListener::windowMoved( const awt::WindowEvent
& /*aEvent*/ ) throw ( uno::RuntimeException
)
333 // not interest this time
336 VbaEventsListener::windowShown( const lang::EventObject
& /*aEvent*/ ) throw ( uno::RuntimeException
)
338 // not interest this time
341 VbaEventsListener::windowHidden( const lang::EventObject
& /*aEvent*/ ) throw ( uno::RuntimeException
)
343 // not interest this time
346 VbaEventsListener::disposing( const lang::EventObject
& /*aEvent*/ ) throw ( uno::RuntimeException
)
348 ::osl::MutexGuard
aGuard( m_aMutex
);
349 OSL_TRACE("VbaEventsListener::disposing(0x%x)", this);
350 pVbaEventsHelper
= NULL
;
353 VbaEventsListener::queryClosing( const lang::EventObject
& Source
, ::sal_Bool GetsOwnership
) throw (util::CloseVetoException
, uno::RuntimeException
)
355 // it can cancel the close, but need to throw a CloseVetoException, and it will be transmit to caller.
358 VbaEventsListener::notifyClosing( const lang::EventObject
& Source
) throw (uno::RuntimeException
)
360 ::osl::MutexGuard
aGuard( m_aMutex
);
361 stopEventsLinstener();
364 VbaEventsListener::borderWidthsChanged( const uno::Reference
< uno::XInterface
>& aObject
, const frame::BorderWidths
& aNewSize
) throw (uno::RuntimeException
)
366 ::osl::MutexGuard
aGuard( m_aMutex
);
367 // work with WindowResized event to guard Window Resize event.
368 m_bBorderChanged
= sal_True
;
369 Window
* pWindow
= (VCLUnoHelper::GetWindow( GetContainerWindow() ) );
370 if( pWindow
&& m_bWindowResized
)
372 m_bWindowResized
= m_bBorderChanged
= sal_False
;
373 acquire(); // ensure we don't get deleted before the timer fires.
374 Application::PostUserEvent( LINK( this, VbaEventsListener
, fireResizeMacro
), NULL
);
378 class ImplVbaEventNameInfo
381 map
< sal_Int32
, rtl::OUString
> m_aEventNameMap
;
384 static ImplVbaEventNameInfo
* pImplVbaEventNameInfo
;
385 ImplVbaEventNameInfo() { InitImplVbaEventNameInfo(); }
387 void insert( const sal_Int32 nId
, const rtl::OUString
& sEventName
)
389 m_aEventNameMap
.insert( make_pair( nId
, sEventName
) );
391 void InitImplVbaEventNameInfo();
393 virtual ~ImplVbaEventNameInfo();
394 rtl::OUString
getEventName( const sal_Int32 nId
)
396 map
< sal_Int32
, rtl::OUString
>::iterator iter
= m_aEventNameMap
.find( nId
);
397 if( iter
!= m_aEventNameMap
.end() )
399 return rtl::OUString();
401 static ImplVbaEventNameInfo
* GetImplVbaEventNameInfo();
403 ImplVbaEventNameInfo
* ImplVbaEventNameInfo::pImplVbaEventNameInfo
= NULL
;
405 ImplVbaEventNameInfo::~ImplVbaEventNameInfo()
407 if( pImplVbaEventNameInfo
)
409 delete pImplVbaEventNameInfo
;
410 pImplVbaEventNameInfo
= NULL
;
414 ImplVbaEventNameInfo
*
415 ImplVbaEventNameInfo::GetImplVbaEventNameInfo()
417 if( !pImplVbaEventNameInfo
)
419 pImplVbaEventNameInfo
= new ImplVbaEventNameInfo
;
421 return pImplVbaEventNameInfo
;
424 #define CREATEOUSTRING(asciistr) rtl::OUString::createFromAscii(asciistr)
426 #define INSERT_EVENT_INFO( Object, Event, ObjectName, EventName ) \
427 insert( VBAEVENT_##Object##_##Event, ObjectName + CREATEOUSTRING( EventName ) )
429 #define INSERT_WORKSHEET_EVENT_INFO( Event, EventName ) \
430 INSERT_EVENT_INFO( WORKSHEET, Event,CREATEOUSTRING("Worksheet_"), EventName ); \
431 INSERT_EVENT_INFO( WORKBOOK_SHEET, Event, CREATEOUSTRING("Workbook_Sheet"), EventName )
433 #define INSERT_WORKBOOK_EVENT_INFO( Event, EventName ) \
434 INSERT_EVENT_INFO( WORKBOOK, Event, CREATEOUSTRING("Workbook_"), EventName )
436 void ImplVbaEventNameInfo::InitImplVbaEventNameInfo()
438 INSERT_WORKSHEET_EVENT_INFO( ACTIVATE
, "Activate");
439 INSERT_WORKSHEET_EVENT_INFO( BEFOREDOUBLECLICK
, "BeforeDoubleClick" );
440 INSERT_WORKSHEET_EVENT_INFO( BEFORERIGHTCLICK
, "BeforeRightClick" );
441 INSERT_WORKSHEET_EVENT_INFO( CALCULATE
, "Calculate" );
442 INSERT_WORKSHEET_EVENT_INFO( CHANGE
, "Change" );
443 INSERT_WORKSHEET_EVENT_INFO( DEACTIVATE
, "Deactivate" );
444 INSERT_WORKSHEET_EVENT_INFO( FOLLOWHYPERLINK
, "FollowHyperlink" );
445 INSERT_WORKSHEET_EVENT_INFO( PIVOTTABLEUPDATE
, "PivotTableUpdate" );
446 INSERT_WORKSHEET_EVENT_INFO( SELECTIONCHANGE
, "SelectionChange" );
449 INSERT_WORKBOOK_EVENT_INFO( ACTIVATE
, "Activate" );
450 INSERT_WORKBOOK_EVENT_INFO( DEACTIVATE
, "Deactivate" );
451 INSERT_WORKBOOK_EVENT_INFO( OPEN
, "Open" );
452 // AUTOOPEN doesn't be used. TODO, this should be "auto_open"
453 insert( VBAEVENT_WORKBOOK_AUTOOPEN
, CREATEOUSTRING("Auto_Open") );
454 INSERT_WORKBOOK_EVENT_INFO( BEFORECLOSE
, "BeforeClose" );
455 INSERT_WORKBOOK_EVENT_INFO( BEFOREPRINT
, "BeforePrint" );
456 INSERT_WORKBOOK_EVENT_INFO( BEFORESAVE
, "BeforeSave" );
457 INSERT_WORKBOOK_EVENT_INFO( NEWSHEET
, "NewSheet" );
458 INSERT_WORKBOOK_EVENT_INFO( WINDOWACTIVATE
, "WindowActivate" );
459 INSERT_WORKBOOK_EVENT_INFO( WINDOWDEACTIVATE
, "WindowDeactivate" );
460 INSERT_WORKBOOK_EVENT_INFO( WINDOWRESIZE
, "WindowResize" );
463 ScVbaEventsHelper::ScVbaEventsHelper( uno::Sequence
< css::uno::Any
> const& aArgs
, uno::Reference
< uno::XComponentContext
> const& xContext
)
464 : m_xContext( xContext
), mbOpened( sal_False
), mbIgnoreEvents( sal_False
)
466 uno::Reference
< frame::XModel
> xModel ( getXSomethingFromArgs
< frame::XModel
>( aArgs
, 0 ), uno::UNO_QUERY
);
467 pDocShell
= excel::getDocShell( xModel
);
468 pDoc
= pDocShell
->GetDocument();
469 // Add worksheet change listener
470 uno::Reference
< util::XChangesNotifier
> xChangesNotifier( xModel
, uno::UNO_QUERY
);
471 if( xChangesNotifier
.is() )
472 xChangesNotifier
->addChangesListener( uno::Reference
< util::XChangesListener
>( new WorksheetChangeListener( this ) ) );
475 ScVbaEventsHelper::~ScVbaEventsHelper()
480 ScVbaEventsHelper::getEventName( const sal_Int32 nId
)
482 rtl::OUString sEventName
;
483 ImplVbaEventNameInfo
* pEventInfo
= ImplVbaEventNameInfo::GetImplVbaEventNameInfo();
485 sEventName
= pEventInfo
->getEventName( nId
);
489 uno::Any
ScVbaEventsHelper::createWorkSheet( SfxObjectShell
* pShell
, SCTAB nTab
)
494 uno::Reference
< lang::XMultiComponentFactory
> xSMgr( ::comphelper::getProcessServiceFactory(), uno::UNO_QUERY_THROW
);
495 uno::Reference
< beans::XPropertySet
> xProps( xSMgr
, uno::UNO_QUERY_THROW
);
496 uno::Reference
<uno::XComponentContext
> xCtx( xProps
->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))), uno::UNO_QUERY_THROW
);
497 // Eventually we will be able to pull the Workbook/Worksheet objects
498 // directly from basic and register them as listeners
501 uno::Sequence
< uno::Any
> aArgs(2);
502 aArgs
[0] = uno::Any( uno::Reference
< uno::XInterface
>() );
503 aArgs
[1] = uno::Any( pShell
->GetModel() );
504 uno::Reference
< uno::XInterface
> xWorkbook( ov::createVBAUnoAPIServiceWithArgs( pShell
, "ooo.vba.excel.Workbook", aArgs
), uno::UNO_QUERY
);
508 pDoc
->GetName( nTab
, sSheetName
);
509 aArgs
= uno::Sequence
< uno::Any
>(3);
510 aArgs
[ 0 ] <<= xWorkbook
;
511 aArgs
[ 1 ] <<= pShell
->GetModel();
512 aArgs
[ 2 ] = uno::makeAny( rtl::OUString( sSheetName
) );
513 aRet
<<= ov::createVBAUnoAPIServiceWithArgs( pShell
, "ooo.vba.excel.Worksheet", aArgs
);
515 catch( uno::Exception
& e
)
521 uno::Any
ScVbaEventsHelper::createRange( const uno::Any
& aRange
)
526 uno::Reference
< sheet::XSheetCellRangeContainer
> xRanges( aRange
, uno::UNO_QUERY
);
527 uno::Reference
< table::XCellRange
> xRange( aRange
, uno::UNO_QUERY
);
528 uno::Reference
< lang::XMultiComponentFactory
> xSMgr( ::comphelper::getProcessServiceFactory(), uno::UNO_QUERY_THROW
);
529 uno::Reference
< beans::XPropertySet
> xProps( xSMgr
, uno::UNO_QUERY_THROW
);
530 if ( xRanges
.is() || xRange
.is() )
532 uno::Reference
<uno::XComponentContext
> xCtx( xProps
->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))), uno::UNO_QUERY_THROW
);
533 uno::Sequence
< uno::Any
> aArgs(2);
534 aArgs
[0] = uno::Any( uno::Reference
< uno::XInterface
>() ); // dummy parent
537 aArgs
[1] <<= xRanges
;
539 else if ( xRange
.is() )
545 throw uno::RuntimeException(); //
547 aRet
<<= ov::createVBAUnoAPIServiceWithArgs( pDoc
->GetDocumentShell(), "ooo.vba.excel.Range", aArgs
);
550 catch( uno::Exception
& e
)
556 uno::Any
ScVbaEventsHelper::createHyperlink( const uno::Any
& rCell
)
561 uno::Reference
< lang::XMultiComponentFactory
> xSMgr( ::comphelper::getProcessServiceFactory(), uno::UNO_QUERY_THROW
);
562 uno::Reference
< beans::XPropertySet
> xProps( xSMgr
, uno::UNO_QUERY_THROW
);
563 uno::Reference
< table::XCell
> xCell( rCell
, uno::UNO_QUERY
);
566 uno::Reference
<uno::XComponentContext
> xCtx( xProps
->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))), uno::UNO_QUERY_THROW
);
567 uno::Sequence
< uno::Any
> aArgs(2);
568 aArgs
[0] = uno::Any( uno::Reference
< uno::XInterface
>() ); // dummy parent
571 aRet
<<= ov::createVBAUnoAPIServiceWithArgs( pDoc
->GetDocumentShell(), "ooo.vba.excel.Hyperlink", aArgs
);
575 throw uno::RuntimeException(); //
578 catch( uno::Exception
& e
)
584 uno::Any
ScVbaEventsHelper::createWindow( SfxObjectShell
* pShell
)
588 uno::Reference
< lang::XMultiServiceFactory
> xSF( comphelper::getProcessServiceFactory(), uno::UNO_QUERY
);
589 uno::Reference
< frame::XModel
> xModel( pShell
->GetModel(), uno::UNO_QUERY
);
590 uno::Sequence
< uno::Any
> aWindowArgs(2);
591 aWindowArgs
[0] = uno::Any( uno::Reference
< uno::XInterface
> () );
592 aWindowArgs
[1] = uno::Any( xModel
);
593 uno::Reference
< uno::XInterface
> xWindow( xSF
->createInstanceWithArguments( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ooo.vba.excel.Window" ) ), aWindowArgs
), uno::UNO_QUERY
);
595 return uno::makeAny( xWindow
);
597 catch( uno::Exception
& e
)
603 String
ScVbaEventsHelper::getSheetModuleName( SCTAB nTab
)
605 ScExtDocOptions
* pExtOptions
= pDoc
->GetExtDocOptions();
607 pDoc
->GetName( nTab
, aCodeName
);
608 // Use code name if that exists
610 aCodeName
= pExtOptions
->GetCodeName( nTab
);
615 ScVbaEventsHelper::getMacroPath( const sal_Int32 nEventId
, const SCTAB nTab
)
617 SfxObjectShell
* pShell
= pDoc
->GetDocumentShell();
618 String sMacroName
= getEventName( nEventId
);
619 VBAMacroResolvedInfo sMacroResolvedInfo
;
623 case VBAEVENT_WORKSHEET_ACTIVATE
:
624 case VBAEVENT_WORKSHEET_BEFOREDOUBLECLICK
:
625 case VBAEVENT_WORKSHEET_BEFORERIGHTCLICK
:
626 case VBAEVENT_WORKSHEET_CALCULATE
:
627 case VBAEVENT_WORKSHEET_CHANGE
:
628 case VBAEVENT_WORKSHEET_DEACTIVATE
:
629 case VBAEVENT_WORKSHEET_FOLLOWHYPERLINK
:
630 case VBAEVENT_WORKSHEET_PIVOTTABLEUPDATE
:
631 case VBAEVENT_WORKSHEET_SELECTIONCHANGE
:
633 String aSheetModuleName
= getSheetModuleName( nTab
);
634 sMacroName
.Insert( '.', 0 ).Insert( aSheetModuleName
, 0);
635 sMacroResolvedInfo
= resolveVBAMacro( pShell
, sMacroName
);
639 case VBAEVENT_WORKBOOK_ACTIVATE
:
640 case VBAEVENT_WORKBOOK_DEACTIVATE
:
641 case VBAEVENT_WORKBOOK_OPEN
:
642 case VBAEVENT_WORKBOOK_BEFORECLOSE
:
643 case VBAEVENT_WORKBOOK_BEFOREPRINT
:
644 case VBAEVENT_WORKBOOK_BEFORESAVE
:
645 case VBAEVENT_WORKBOOK_NEWSHEET
:
646 case VBAEVENT_WORKBOOK_WINDOWACTIVATE
:
647 case VBAEVENT_WORKBOOK_WINDOWDEACTIVATE
:
648 case VBAEVENT_WORKBOOK_WINDOWRESIZE
:
650 case VBAEVENT_WORKBOOK_SHEET_ACTIVATE
:
651 case VBAEVENT_WORKBOOK_SHEET_BEFOREDOUBLECLICK
:
652 case VBAEVENT_WORKBOOK_SHEET_BEFORERIGHTCLICK
:
653 case VBAEVENT_WORKBOOK_SHEET_CALCULATE
:
654 case VBAEVENT_WORKBOOK_SHEET_CHANGE
:
655 case VBAEVENT_WORKBOOK_SHEET_DEACTIVATE
:
656 case VBAEVENT_WORKBOOK_SHEET_FOLLOWHYPERLINK
:
657 case VBAEVENT_WORKBOOK_SHEET_PIVOTTABLEUPDATE
:
658 case VBAEVENT_WORKBOOK_SHEET_SELECTIONCHANGE
:
660 ScExtDocOptions
* pExtOptions
= pDoc
->GetExtDocOptions();
661 String sWorkbookModuleName
= pDoc
->GetCodeName();
664 ScExtDocSettings aExtDocSettings
= pExtOptions
->GetDocSettings();
665 sWorkbookModuleName
= aExtDocSettings
.maGlobCodeName
;
668 sMacroName
.Insert( '.', 0 ).Insert( sWorkbookModuleName
, 0);
669 sMacroResolvedInfo
= resolveVBAMacro( pShell
, sMacroName
);
672 case VBAEVENT_WORKBOOK_AUTOOPEN
:
674 sMacroResolvedInfo
= resolveVBAMacro( pShell
, sMacroName
);
680 return sMacroResolvedInfo
.ResolvedMacro();
683 sal_Bool
ScVbaEventsHelper::processVbaEvent( const sal_Int32 nEventId
, const uno::Sequence
< uno::Any
>& rArgs
, const SCTAB nTab
)
685 SfxObjectShell
* pShell
= pDoc
->GetDocumentShell();
687 sal_Bool result
= sal_False
;
688 sal_Bool bCancel
= sal_False
;
689 uno::Sequence
< uno::Any
> aArgs
;
691 uno::Any aDummyCaller
;
693 // For most cases, there is no corresponsible event macro in the document.
694 // It is better fo check if the event macro exists before process the arguments to improve performance.
695 rtl::OUString sMacroPath
= getMacroPath( nEventId
, nTab
);
696 if( sMacroPath
.getLength() )
700 case VBAEVENT_WORKSHEET_ACTIVATE
:
701 case VBAEVENT_WORKSHEET_CALCULATE
:
702 case VBAEVENT_WORKSHEET_DEACTIVATE
:
703 case VBAEVENT_WORKBOOK_ACTIVATE
:
704 case VBAEVENT_WORKBOOK_DEACTIVATE
:
705 case VBAEVENT_WORKBOOK_OPEN
:
706 case VBAEVENT_WORKBOOK_AUTOOPEN
:
711 case VBAEVENT_WORKBOOK_SHEET_DEACTIVATE
:
712 case VBAEVENT_WORKBOOK_SHEET_CALCULATE
:
713 case VBAEVENT_WORKBOOK_SHEET_ACTIVATE
:
714 case VBAEVENT_WORKBOOK_NEWSHEET
:
716 aArgs
= uno::Sequence
< uno::Any
>(1);
717 aArgs
[0] = createWorkSheet( pShell
, nTab
);
720 case VBAEVENT_WORKSHEET_CHANGE
:
721 case VBAEVENT_WORKSHEET_SELECTIONCHANGE
:
723 // one argument: range
724 uno::Any aRange
= createRange( rArgs
[0] );
725 aArgs
= uno::Sequence
< uno::Any
>(1);
729 case VBAEVENT_WORKBOOK_SHEET_CHANGE
:
730 case VBAEVENT_WORKBOOK_SHEET_SELECTIONCHANGE
:
732 uno::Any aRange
= createRange( rArgs
[0] );
733 aArgs
= uno::Sequence
< uno::Any
>(2);
734 aArgs
[0] = createWorkSheet( pShell
, nTab
);
738 case VBAEVENT_WORKSHEET_BEFOREDOUBLECLICK
:
739 case VBAEVENT_WORKSHEET_BEFORERIGHTCLICK
:
741 // two aruments: range and cancel
742 uno::Any aRange
= createRange( rArgs
[0] );
743 aArgs
= uno::Sequence
< uno::Any
>(2);
745 aArgs
[1] <<= bCancel
;
746 // TODO: process "cancel" action
749 case VBAEVENT_WORKBOOK_SHEET_BEFOREDOUBLECLICK
:
750 case VBAEVENT_WORKBOOK_SHEET_BEFORERIGHTCLICK
:
752 uno::Any aRange
= createRange( rArgs
[0] );
753 aArgs
= uno::Sequence
< uno::Any
>(3);
754 aArgs
[0] = createWorkSheet( pShell
, nTab
);
756 aArgs
[2] <<= bCancel
;
757 // TODO: process "cancel" action
760 case VBAEVENT_WORKSHEET_FOLLOWHYPERLINK
:
762 // one argument: hyperlink
763 uno::Any aHyperlink
= createHyperlink( rArgs
[0] );
764 aArgs
= uno::Sequence
< uno::Any
>(1);
765 aArgs
[0] = aHyperlink
;
768 case VBAEVENT_WORKBOOK_SHEET_FOLLOWHYPERLINK
:
770 uno::Any aHyperlink
= createHyperlink( rArgs
[0] );
771 aArgs
= uno::Sequence
< uno::Any
>(2);
772 aArgs
[0] = createWorkSheet( pShell
, nTab
);
773 aArgs
[1] = aHyperlink
;
776 case VBAEVENT_WORKSHEET_PIVOTTABLEUPDATE
:
777 case VBAEVENT_WORKBOOK_SHEET_PIVOTTABLEUPDATE
:
779 // one argument: pivottable
780 // TODO: not support yet
783 case VBAEVENT_WORKBOOK_BEFORECLOSE
:
784 case VBAEVENT_WORKBOOK_BEFOREPRINT
:
786 // process Cancel argument
787 aArgs
= uno::Sequence
< uno::Any
>(1);
788 aArgs
[0] <<= bCancel
;
789 executeMacro( pShell
, sMacroPath
, aArgs
, aRet
, aDummyCaller
);
790 aArgs
[0] >>= bCancel
;
793 case VBAEVENT_WORKBOOK_BEFORESAVE
:
795 // two arguments: SaveAs and Cancel
796 aArgs
= uno::Sequence
< uno::Any
>(2);
798 aArgs
[1] <<= bCancel
;
799 executeMacro( pShell
, sMacroPath
, aArgs
, aRet
, aDummyCaller
);
800 aArgs
[1] >>= bCancel
;
803 case VBAEVENT_WORKBOOK_WINDOWACTIVATE
:
804 case VBAEVENT_WORKBOOK_WINDOWDEACTIVATE
:
805 case VBAEVENT_WORKBOOK_WINDOWRESIZE
:
807 // one argument: windows
808 aArgs
= uno::Sequence
< uno::Any
>(1);
809 aArgs
[0] = createWindow( pShell
);
817 result
= executeMacro( pShell
, sMacroPath
, aArgs
, aRet
, aDummyCaller
);
823 SCTAB
ScVbaEventsHelper::getTabFromArgs( const uno::Sequence
< uno::Any
> aArgs
, const sal_Int32 nPos
)
826 uno::Reference
< sheet::XCellRangeAddressable
> xCellRangeAddressable( getXSomethingFromArgs
< sheet::XCellRangeAddressable
>( aArgs
, nPos
), uno::UNO_QUERY
);
827 if( xCellRangeAddressable
.is() )
829 table::CellRangeAddress aAddress
= xCellRangeAddressable
->getRangeAddress();
830 nTab
= aAddress
.Sheet
;
834 uno::Reference
< sheet::XSheetCellRangeContainer
> xRanges( getXSomethingFromArgs
< sheet::XSheetCellRangeContainer
>( aArgs
, nPos
), uno::UNO_QUERY
);
837 uno::Sequence
< table::CellRangeAddress
> aRangeAddresses
= xRanges
->getRangeAddresses();
838 if( aRangeAddresses
.getLength() > 0 )
840 nTab
= aRangeAddresses
[ 0 ].Sheet
;
848 ScVbaEventsHelper::ProcessCompatibleVbaEvent( sal_Int32 nEventId
, const uno::Sequence
< uno::Any
>& aArgs
) throw (uno::RuntimeException
)
850 SfxObjectShell
* pShell
= pDoc
->GetDocumentShell();
851 if( !pShell
|| mbIgnoreEvents
)
854 // In order to better support "withevents" in the future,
855 // it is better to process a event at a time
856 SCTAB nTab
= INVALID_TAB
;
860 case VBAEVENT_WORKSHEET_ACTIVATE
:
863 if( nTab
!= INVALID_TAB
)
866 processVbaEvent( nEventId
, aArgs
, nTab
);
867 // recursive process related workbook sheet event.
868 ProcessCompatibleVbaEvent( VBAEVENT_WORKBOOK_SHEET_ACTIVATE
, aArgs
);
872 case VBAEVENT_WORKSHEET_BEFOREDOUBLECLICK
:
874 nTab
= getTabFromArgs( aArgs
);
875 if( nTab
!= INVALID_TAB
)
877 processVbaEvent( nEventId
, aArgs
, nTab
);
878 ProcessCompatibleVbaEvent( VBAEVENT_WORKBOOK_SHEET_BEFOREDOUBLECLICK
, aArgs
);
882 case VBAEVENT_WORKSHEET_BEFORERIGHTCLICK
:
884 nTab
= getTabFromArgs( aArgs
);
885 if( nTab
!= INVALID_TAB
)
887 processVbaEvent( nEventId
, aArgs
, nTab
);
888 ProcessCompatibleVbaEvent( VBAEVENT_WORKBOOK_SHEET_BEFORERIGHTCLICK
, aArgs
);
892 case VBAEVENT_WORKSHEET_CALCULATE
:
895 if( nTab
!= INVALID_TAB
)
897 processVbaEvent( nEventId
, aArgs
, nTab
);
898 ProcessCompatibleVbaEvent( VBAEVENT_WORKBOOK_SHEET_CALCULATE
, aArgs
);
902 case VBAEVENT_WORKSHEET_CHANGE
:
904 nTab
= getTabFromArgs( aArgs
);
905 if( nTab
!= INVALID_TAB
)
907 processVbaEvent( nEventId
, aArgs
, nTab
);
908 ProcessCompatibleVbaEvent( VBAEVENT_WORKBOOK_SHEET_CHANGE
, aArgs
);
912 case VBAEVENT_WORKSHEET_DEACTIVATE
:
915 if( nTab
!= INVALID_TAB
)
917 processVbaEvent( nEventId
, aArgs
, nTab
);
918 ProcessCompatibleVbaEvent( VBAEVENT_WORKBOOK_SHEET_DEACTIVATE
, aArgs
);
922 case VBAEVENT_WORKSHEET_FOLLOWHYPERLINK
:
924 nTab
= getTabFromArgs( aArgs
);
925 if( nTab
!= INVALID_TAB
)
927 processVbaEvent( nEventId
, aArgs
, nTab
);
928 ProcessCompatibleVbaEvent( VBAEVENT_WORKBOOK_SHEET_FOLLOWHYPERLINK
, aArgs
);
932 case VBAEVENT_WORKSHEET_PIVOTTABLEUPDATE
:
935 case VBAEVENT_WORKSHEET_SELECTIONCHANGE
:
937 nTab
= getTabFromArgs( aArgs
);
938 if( nTab
!= INVALID_TAB
)
940 processVbaEvent( nEventId
, aArgs
, nTab
);
941 ProcessCompatibleVbaEvent( VBAEVENT_WORKBOOK_SHEET_SELECTIONCHANGE
, aArgs
);
946 case VBAEVENT_WORKBOOK_SHEET_ACTIVATE
:
947 case VBAEVENT_WORKBOOK_SHEET_CALCULATE
:
948 case VBAEVENT_WORKBOOK_SHEET_DEACTIVATE
:
951 if( nTab
!= INVALID_TAB
)
953 processVbaEvent( nEventId
, aArgs
, nTab
);
957 case VBAEVENT_WORKBOOK_SHEET_BEFOREDOUBLECLICK
:
958 case VBAEVENT_WORKBOOK_SHEET_BEFORERIGHTCLICK
:
959 case VBAEVENT_WORKBOOK_SHEET_CHANGE
:
960 case VBAEVENT_WORKBOOK_SHEET_FOLLOWHYPERLINK
:
961 case VBAEVENT_WORKBOOK_SHEET_SELECTIONCHANGE
:
963 nTab
= getTabFromArgs( aArgs
);
964 if( nTab
!= INVALID_TAB
)
966 processVbaEvent( nEventId
, aArgs
, nTab
);
970 case VBAEVENT_WORKBOOK_SHEET_PIVOTTABLEUPDATE
:
974 case VBAEVENT_WORKBOOK_ACTIVATE
:
976 // if workbook open event do not be fired. fired it before
977 // workbook activate event to compatible with MSO.
980 // process workbook activate event
981 processVbaEvent( nEventId
, aArgs
);
982 // process workbook window activate event at the same time
983 ProcessCompatibleVbaEvent( VBAEVENT_WORKBOOK_WINDOWACTIVATE
, aArgs
);
987 case VBAEVENT_WORKBOOK_DEACTIVATE
:
989 processVbaEvent( nEventId
, aArgs
);
990 // same as workbook window deactivate
991 ProcessCompatibleVbaEvent( VBAEVENT_WORKBOOK_WINDOWDEACTIVATE
, aArgs
);
994 case VBAEVENT_WORKBOOK_OPEN
:
996 // process workbook open macro
997 // does auto open work here?
1000 processVbaEvent( nEventId
, aArgs
);
1001 processVbaEvent( VBAEVENT_WORKBOOK_AUTOOPEN
, aArgs
);
1002 mbOpened
= sal_True
;
1003 ProcessCompatibleVbaEvent( VBAEVENT_WORKBOOK_ACTIVATE
, aArgs
);
1005 // register the window listener.
1006 if( !m_xVbaEventsListener
.is() )
1008 m_xVbaEventsListener
= new VbaEventsListener( this );
1009 VbaEventsListener
* pEventsListener
= dynamic_cast< VbaEventsListener
* >( m_xVbaEventsListener
.get() );
1010 pEventsListener
->startEventsLinstener();
1014 case VBAEVENT_WORKBOOK_BEFORECLOSE
:
1016 sal_Bool bCancel
= processVbaEvent( nEventId
, aArgs
);
1017 if( m_xVbaEventsListener
.is() && !bCancel
)
1019 VbaEventsListener
* pEventsListener
= dynamic_cast< VbaEventsListener
* >( m_xVbaEventsListener
.get() );
1020 pEventsListener
->stopEventsLinstener();
1021 m_xVbaEventsListener
= NULL
;
1025 case VBAEVENT_WORKBOOK_BEFOREPRINT
:
1026 case VBAEVENT_WORKBOOK_BEFORESAVE
:
1027 case VBAEVENT_WORKBOOK_WINDOWACTIVATE
:
1028 case VBAEVENT_WORKBOOK_WINDOWDEACTIVATE
:
1029 case VBAEVENT_WORKBOOK_WINDOWRESIZE
:
1031 return processVbaEvent( nEventId
, aArgs
);
1033 case VBAEVENT_WORKBOOK_NEWSHEET
:
1036 if( nTab
!= INVALID_TAB
)
1038 processVbaEvent( nEventId
, aArgs
, nTab
);
1043 OSL_TRACE( "Invalid Event" );
1050 ScVbaEventsHelper::getIgnoreEvents() throw (uno::RuntimeException
)
1052 return mbIgnoreEvents
;
1056 ScVbaEventsHelper::setIgnoreEvents( ::sal_Bool _ignoreevents
) throw (uno::RuntimeException
)
1058 mbIgnoreEvents
= _ignoreevents
;
1062 namespace vbaeventshelper
1064 namespace sdecl
= comphelper::service_decl
;
1065 sdecl::class_
<ScVbaEventsHelper
, sdecl::with_args
<true> > serviceImpl
;
1066 extern sdecl::ServiceDecl
const serviceDecl(
1068 "ScVbaEventsHelper",
1069 "com.sun.star.document.VbaEventsHelper" );