/************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ #include "vbaeventshelper.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "cellsuno.hxx" #include "convuno.hxx" using namespace ::com::sun::star; using namespace ::com::sun::star::script::vba::VBAEventId; using namespace ::ooo::vba; // ============================================================================ typedef ::cppu::WeakImplHelper4< awt::XWindowListener, util::XCloseListener, frame::XBorderResizeListener, util::XChangesListener > ScVbaEventsListener_BASE; // This class is to process Workbook window related event class ScVbaEventsListener : public ScVbaEventsListener_BASE { public : ScVbaEventsListener( ScVbaEventsHelper& rVbaEvents, const uno::Reference< frame::XModel >& rxModel, ScDocShell* pDocShell ); virtual ~ScVbaEventsListener(); void startListening(); void stopListening(); // XWindowListener virtual void SAL_CALL windowResized( const awt::WindowEvent& aEvent ) throw (uno::RuntimeException); virtual void SAL_CALL windowMoved( const awt::WindowEvent& aEvent ) throw (uno::RuntimeException); virtual void SAL_CALL windowShown( const lang::EventObject& aEvent ) throw (uno::RuntimeException); virtual void SAL_CALL windowHidden( const lang::EventObject& aEvent ) throw (uno::RuntimeException); virtual void SAL_CALL disposing( const lang::EventObject& aEvent ) throw (uno::RuntimeException); // XCloseListener virtual void SAL_CALL queryClosing( const lang::EventObject& Source, ::sal_Bool GetsOwnership ) throw (util::CloseVetoException, uno::RuntimeException); virtual void SAL_CALL notifyClosing( const lang::EventObject& Source ) throw (uno::RuntimeException); // XBorderResizeListener virtual void SAL_CALL borderWidthsChanged( const uno::Reference< uno::XInterface >& aObject, const frame::BorderWidths& aNewSize ) throw (uno::RuntimeException); // XChangesListener virtual void SAL_CALL changesOccurred( const util::ChangesEvent& aEvent ) throw (uno::RuntimeException); private: uno::Reference< frame::XFrame > getFrame(); uno::Reference< awt::XWindow > getContainerWindow(); bool isMouseReleased(); DECL_LINK( fireResizeMacro, void* ); void processWindowResizeMacro(); private: ::osl::Mutex maMutex; ScVbaEventsHelper& mrVbaEvents; uno::Reference< frame::XModel > mxModel; ScDocShell* mpDocShell; bool mbWindowResized; bool mbBorderChanged; bool mbDisposed; }; // ---------------------------------------------------------------------------- ScVbaEventsListener::ScVbaEventsListener( ScVbaEventsHelper& rVbaEvents, const uno::Reference< frame::XModel >& rxModel, ScDocShell* pDocShell ) : mrVbaEvents( rVbaEvents ), mxModel( rxModel ), mpDocShell( pDocShell ), mbWindowResized( false ), mbBorderChanged( false ), mbDisposed( !rxModel.is() ) { OSL_TRACE( "ScVbaEventsListener::ScVbaEventsListener( 0x%x ) - ctor ", this ); } ScVbaEventsListener::~ScVbaEventsListener() { OSL_TRACE( "ScVbaEventsListener::~ScVbaEventsListener( 0x%x ) - dtor ", this ); stopListening(); } void ScVbaEventsListener::startListening() { if( !mbDisposed ) { // add window listener try { uno::Reference< awt::XWindow > xWindow( getContainerWindow(), uno::UNO_QUERY_THROW ); xWindow->addWindowListener( this ); } catch( uno::Exception& ) { } // add close listener try { uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( mxModel, uno::UNO_QUERY_THROW ); xCloseBroadcaster->addCloseListener( this ); } catch( uno::Exception& ) { } // add Border resize listener try { uno::Reference< frame::XControllerBorder > xControllerBorder( mxModel->getCurrentController(), uno::UNO_QUERY_THROW ); xControllerBorder->addBorderResizeListener( this ); } catch( uno::Exception& ) { } // add content change listener try { uno::Reference< util::XChangesNotifier > xChangesNotifier( mxModel, uno::UNO_QUERY_THROW ); xChangesNotifier->addChangesListener( this ); } catch( uno::Exception& ) { } } } void ScVbaEventsListener::stopListening() { if( !mbDisposed ) { try { uno::Reference< awt::XWindow > xWindow( getContainerWindow(), uno::UNO_QUERY_THROW ); xWindow->removeWindowListener( this ); } catch( uno::Exception& ) { } try { uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( mxModel, uno::UNO_QUERY_THROW ); xCloseBroadcaster->removeCloseListener( this ); } catch( uno::Exception& ) { } try { uno::Reference< frame::XControllerBorder > xControllerBorder( mxModel->getCurrentController(), uno::UNO_QUERY_THROW ); xControllerBorder->removeBorderResizeListener( this ); } catch( uno::Exception& ) { } try { uno::Reference< util::XChangesNotifier > xChangesNotifier( mxModel, uno::UNO_QUERY_THROW ); xChangesNotifier->removeChangesListener( this ); } catch( uno::Exception& ) { } } mbDisposed = true; } void SAL_CALL ScVbaEventsListener::windowResized( const awt::WindowEvent& /*aEvent*/ ) throw ( uno::RuntimeException ) { ::osl::MutexGuard aGuard( maMutex ); // Workbook_window_resize event mbWindowResized = true; if( !mbDisposed && mbBorderChanged ) { if( /*Window* pWindow =*/ VCLUnoHelper::GetWindow( getContainerWindow() ) ) { mbBorderChanged = mbWindowResized = false; acquire(); // ensure we don't get deleted before the event is handled Application::PostUserEvent( LINK( this, ScVbaEventsListener, fireResizeMacro ), 0 ); } } } void SAL_CALL ScVbaEventsListener::windowMoved( const awt::WindowEvent& /*aEvent*/ ) throw ( uno::RuntimeException ) { // not interest this time } void SAL_CALL ScVbaEventsListener::windowShown( const lang::EventObject& /*aEvent*/ ) throw ( uno::RuntimeException ) { // not interest this time } void SAL_CALL ScVbaEventsListener::windowHidden( const lang::EventObject& /*aEvent*/ ) throw ( uno::RuntimeException ) { // not interest this time } void SAL_CALL ScVbaEventsListener::disposing( const lang::EventObject& /*aEvent*/ ) throw ( uno::RuntimeException ) { ::osl::MutexGuard aGuard( maMutex ); OSL_TRACE( "ScVbaEventsListener::disposing( 0x%x )", this ); mbDisposed = true; } void SAL_CALL ScVbaEventsListener::queryClosing( const lang::EventObject& /*Source*/, sal_Bool /*GetsOwnership*/ ) throw (util::CloseVetoException, uno::RuntimeException) { // it can cancel the close, but need to throw a CloseVetoException, and it will be transmit to caller. } void SAL_CALL ScVbaEventsListener::notifyClosing( const lang::EventObject& /*Source*/ ) throw (uno::RuntimeException) { ::osl::MutexGuard aGuard( maMutex ); stopListening(); } void SAL_CALL ScVbaEventsListener::borderWidthsChanged( const uno::Reference< uno::XInterface >& /*aObject*/, const frame::BorderWidths& /*aNewSize*/ ) throw (uno::RuntimeException) { ::osl::MutexGuard aGuard( maMutex ); // work with WindowResized event to guard Window Resize event. mbBorderChanged = true; if( !mbDisposed && mbWindowResized ) { if( /*Window* pWindow =*/ VCLUnoHelper::GetWindow( getContainerWindow() ) ) { mbWindowResized = mbBorderChanged = false; acquire(); // ensure we don't get deleted before the timer fires. Application::PostUserEvent( LINK( this, ScVbaEventsListener, fireResizeMacro ), 0 ); } } } void SAL_CALL ScVbaEventsListener::changesOccurred( const util::ChangesEvent& aEvent ) throw (uno::RuntimeException) { sal_Int32 nCount = aEvent.Changes.getLength(); if( nCount == 0 ) return; util::ElementChange aChange = aEvent.Changes[ 0 ]; rtl::OUString sOperation; aChange.Accessor >>= sOperation; if( !sOperation.equalsIgnoreAsciiCaseAscii("cell-change") ) return; if( nCount == 1 ) { uno::Reference< table::XCellRange > xRangeObj; aChange.ReplacedElement >>= xRangeObj; if( xRangeObj.is() ) { uno::Sequence< uno::Any > aArgs(1); aArgs[0] <<= xRangeObj; mrVbaEvents.processVbaEvent( WORKSHEET_CHANGE, aArgs ); } return; } ScRangeList aRangeList; for( sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex ) { aChange = aEvent.Changes[ nIndex ]; aChange.Accessor >>= sOperation; uno::Reference< table::XCellRange > xRangeObj; aChange.ReplacedElement >>= xRangeObj; if( xRangeObj.is() && sOperation.equalsIgnoreAsciiCaseAscii("cell-change") ) { uno::Reference< sheet::XCellRangeAddressable > xCellRangeAddressable( xRangeObj, uno::UNO_QUERY ); if( xCellRangeAddressable.is() ) { ScRange aRange; ScUnoConversion::FillScRange( aRange, xCellRangeAddressable->getRangeAddress() ); aRangeList.Append( aRange ); } } } if( (aRangeList.Count() > 0) && mpDocShell ) { uno::Reference< sheet::XSheetCellRangeContainer > xRanges( new ScCellRangesObj( mpDocShell, aRangeList ) ); uno::Sequence< uno::Any > aArgs(1); aArgs[0] <<= xRanges; mrVbaEvents.processVbaEvent( WORKSHEET_CHANGE, aArgs ); } } // ---------------------------------------------------------------------------- uno::Reference< frame::XFrame > ScVbaEventsListener::getFrame() { if( !mbDisposed && mxModel.is() ) try { uno::Reference< frame::XController > xController( mxModel->getCurrentController(), uno::UNO_QUERY_THROW ); return xController->getFrame(); } catch( uno::Exception& ) { } return uno::Reference< frame::XFrame >(); } uno::Reference< awt::XWindow > ScVbaEventsListener::getContainerWindow() { try { uno::Reference< frame::XFrame > xFrame( getFrame(), uno::UNO_SET_THROW ); return xFrame->getContainerWindow(); } catch( uno::Exception& ) { } return uno::Reference< awt::XWindow >(); } bool ScVbaEventsListener::isMouseReleased() { if( Window* pWindow = VCLUnoHelper::GetWindow( getContainerWindow() ) ) { Window::PointerState aPointerState = pWindow->GetPointerState(); return (aPointerState.mnState & ( MOUSE_LEFT | MOUSE_MIDDLE | MOUSE_RIGHT )) == 0; } return false; } IMPL_LINK( ScVbaEventsListener, fireResizeMacro, void*, EMPTYARG ) { if( !mbDisposed && isMouseReleased() ) processWindowResizeMacro(); release(); return 0; } void ScVbaEventsListener::processWindowResizeMacro() { OSL_TRACE( "**** Attempt to FIRE MACRO **** " ); if( !mbDisposed ) mrVbaEvents.processVbaEvent( WORKBOOK_WINDOWRESIZE, uno::Sequence< uno::Any >() ); } // ============================================================================ ScVbaEventsHelper::ScVbaEventsHelper( const uno::Sequence< uno::Any >& rArgs, const uno::Reference< uno::XComponentContext >& xContext ) : VbaEventsHelperBase( rArgs, xContext ), mbOpened( false ) { mpDocShell = dynamic_cast< ScDocShell* >( mpShell ); // mpShell from base class mpDoc = mpDocShell ? mpDocShell->GetDocument() : 0; if( !mxModel.is() || !mpDocShell || !mpDoc ) return; #define REGISTER_EVENT( eventid, eventname, type, cancelindex, worksheet ) \ registerEventHandler( eventid, eventname, type, cancelindex, uno::Any( worksheet ) ) #define REGISTER_WORKBOOK_EVENT( eventid, eventname, cancelindex ) \ REGISTER_EVENT( WORKBOOK_##eventid, "Workbook_" eventname, EVENTHANDLER_DOCUMENT, cancelindex, false ) #define REGISTER_WORKSHEET_EVENT( eventid, eventname, cancelindex ) \ REGISTER_EVENT( WORKSHEET_##eventid, "Worksheet_" eventname, EVENTHANDLER_DOCUMENT, cancelindex, true ); \ REGISTER_EVENT( (USERDEFINED_START + WORKSHEET_##eventid), "Workbook_Sheet" eventname, EVENTHANDLER_DOCUMENT, (((cancelindex) >= 0) ? ((cancelindex) + 1) : -1), false ) // global REGISTER_EVENT( AUTO_OPEN, "Auto_Open", EVENTHANDLER_GLOBAL, -1, false ); REGISTER_EVENT( AUTO_CLOSE, "Auto_Close", EVENTHANDLER_GLOBAL, -1, false ); // Workbook REGISTER_WORKBOOK_EVENT( ACTIVATE, "Activate", -1 ); REGISTER_WORKBOOK_EVENT( DEACTIVATE, "Deactivate", -1 ); REGISTER_WORKBOOK_EVENT( OPEN, "Open", -1 ); REGISTER_WORKBOOK_EVENT( BEFORECLOSE, "BeforeClose", 0 ); REGISTER_WORKBOOK_EVENT( BEFOREPRINT, "BeforePrint", 0 ); REGISTER_WORKBOOK_EVENT( BEFORESAVE, "BeforeSave", 1 ); REGISTER_WORKBOOK_EVENT( AFTERSAVE, "AfterSave", -1 ); REGISTER_WORKBOOK_EVENT( NEWSHEET, "NewSheet", -1 ); REGISTER_WORKBOOK_EVENT( WINDOWACTIVATE, "WindowActivate", -1 ); REGISTER_WORKBOOK_EVENT( WINDOWDEACTIVATE, "WindowDeactivate", -1 ); REGISTER_WORKBOOK_EVENT( WINDOWRESIZE, "WindowResize", -1 ); // Worksheet events. All events have a corresponding workbook event. REGISTER_WORKSHEET_EVENT( ACTIVATE, "Activate", -1 ); REGISTER_WORKSHEET_EVENT( DEACTIVATE, "Deactivate", -1 ); REGISTER_WORKSHEET_EVENT( BEFOREDOUBLECLICK, "BeforeDoubleClick", 1 ); REGISTER_WORKSHEET_EVENT( BEFORERIGHTCLICK, "BeforeRightClick", 1 ); REGISTER_WORKSHEET_EVENT( CALCULATE, "Calculate", -1 ); REGISTER_WORKSHEET_EVENT( CHANGE, "Change", -1 ); REGISTER_WORKSHEET_EVENT( SELECTIONCHANGE, "SelectionChange", -1 ); REGISTER_WORKSHEET_EVENT( FOLLOWHYPERLINK, "FollowHyperlink", -1 ); #undef REGISTER_EVENT #undef REGISTER_WORKBOOK_EVENT #undef REGISTER_WORKSHEET_EVENT } ScVbaEventsHelper::~ScVbaEventsHelper() { } void SAL_CALL ScVbaEventsHelper::disposing( const lang::EventObject& rSource ) throw (uno::RuntimeException) { mxListener.clear(); VbaEventsHelperBase::disposing( rSource ); } // protected ------------------------------------------------------------------ bool ScVbaEventsHelper::implEventsEnabled() throw (uno::RuntimeException) { // document and document shell are needed during event processing if( !mpDocShell || !mpDoc ) throw uno::RuntimeException(); // get Application object and check if events are enabled (this is an Excel-only attribute) uno::Reference< excel::XApplication > xApplication( mxApplication.get(), uno::UNO_QUERY ); if( !xApplication.is() && mpShell ) { uno::Any aVBAGlobals; mpShell->GetBasicManager()->GetGlobalUNOConstant( "VBAGlobals", aVBAGlobals ); uno::Reference< XHelperInterface > xHelperInterface( aVBAGlobals, uno::UNO_QUERY ); if( xHelperInterface.is() ) { xApplication.set( xHelperInterface->Application(), uno::UNO_QUERY ); mxApplication = xApplication; } } if( !xApplication.is() ) throw uno::RuntimeException(); // return whether event processing is enabled return xApplication->getEnableEvents(); } bool ScVbaEventsHelper::implPrepareEvent( EventQueue& rEventQueue, const EventHandlerInfo& rInfo, const uno::Sequence< uno::Any >& rArgs ) throw (uno::RuntimeException) { // check preconditions for some events, add more events if needed bool bExecuteEvent = true; switch( rInfo.mnEventId ) { case WORKBOOK_ACTIVATE: // while loading, framework fires this before 'opened' event, delay it bExecuteEvent = mbOpened; break; case WORKBOOK_OPEN: bExecuteEvent = !mbOpened; if( bExecuteEvent ) { // execute delayed Activate event too (see above) rEventQueue.push_back( WORKBOOK_ACTIVATE ); rEventQueue.push_back( WORKBOOK_WINDOWACTIVATE ); rEventQueue.push_back( AUTO_OPEN ); } break; case WORKSHEET_SELECTIONCHANGE: // if selection is not changed, then do not fire the event bExecuteEvent = mbOpened && isSelectionChanged( rArgs, 0 ); break; } // add workbook event associated to a sheet event bool bSheetEvent = false; rInfo.maUserData >>= bSheetEvent; if( bSheetEvent && bExecuteEvent ) rEventQueue.push_back( EventQueueEntry( rInfo.mnEventId + USERDEFINED_START, rArgs ) ); return bExecuteEvent; } uno::Sequence< uno::Any > ScVbaEventsHelper::implBuildArgumentList( const EventHandlerInfo& rInfo, const uno::Sequence< uno::Any >& rArgs ) throw (lang::IllegalArgumentException) { // fill arguments for workbook events associated to sheet events according to sheet events, sheet will be added below bool bSheetEventAsBookEvent = rInfo.mnEventId > USERDEFINED_START; sal_Int32 nEventId = bSheetEventAsBookEvent ? (rInfo.mnEventId - USERDEFINED_START) : rInfo.mnEventId; uno::Sequence< uno::Any > aVbaArgs; switch( nEventId ) { // *** Workbook *** // no arguments case WORKBOOK_ACTIVATE: case WORKBOOK_DEACTIVATE: case WORKBOOK_OPEN: break; // 1 arg: cancel case WORKBOOK_BEFORECLOSE: case WORKBOOK_BEFOREPRINT: aVbaArgs.realloc( 1 ); // current cancel state will be inserted by caller break; // 2 args: saveAs, cancel case WORKBOOK_BEFORESAVE: aVbaArgs.realloc( 2 ); checkArgumentType< bool >( rArgs, 0 ); aVbaArgs[ 0 ] = rArgs[ 0 ]; // current cancel state will be inserted by caller break; // 1 arg: success case WORKBOOK_AFTERSAVE: aVbaArgs.realloc( 1 ); checkArgumentType< bool >( rArgs, 0 ); aVbaArgs[ 0 ] = rArgs[ 0 ]; break; // 1 arg: window case WORKBOOK_WINDOWACTIVATE: case WORKBOOK_WINDOWDEACTIVATE: case WORKBOOK_WINDOWRESIZE: aVbaArgs.realloc( 1 ); aVbaArgs[ 0 ] = createWindow(); break; // 1 arg: worksheet case WORKBOOK_NEWSHEET: aVbaArgs.realloc( 1 ); aVbaArgs[ 0 ] = createWorksheet( rArgs, 0 ); break; // *** Worksheet *** // no arguments case WORKSHEET_ACTIVATE: case WORKSHEET_CALCULATE: case WORKSHEET_DEACTIVATE: break; // 1 arg: range case WORKSHEET_CHANGE: case WORKSHEET_SELECTIONCHANGE: aVbaArgs.realloc( 1 ); aVbaArgs[ 0 ] = createRange( rArgs, 0 ); break; // 2 args: range, cancel case WORKSHEET_BEFOREDOUBLECLICK: case WORKSHEET_BEFORERIGHTCLICK: aVbaArgs.realloc( 2 ); aVbaArgs[ 0 ] = createRange( rArgs, 0 ); // current cancel state will be inserted by caller break; // 1 arg: hyperlink case WORKSHEET_FOLLOWHYPERLINK: aVbaArgs.realloc( 1 ); aVbaArgs[ 0 ] = createHyperlink( rArgs, 0 ); break; } /* For workbook events associated to sheet events, the workbook event gets the same arguments but with a Worksheet object in front of them. */ if( bSheetEventAsBookEvent ) { sal_Int32 nLength = aVbaArgs.getLength(); uno::Sequence< uno::Any > aVbaArgs2( nLength + 1 ); aVbaArgs2[ 0 ] = createWorksheet( rArgs, 0 ); for( sal_Int32 nIndex = 0; nIndex < nLength; ++nIndex ) aVbaArgs2[ nIndex + 1 ] = aVbaArgs[ nIndex ]; aVbaArgs = aVbaArgs2; } return aVbaArgs; } void ScVbaEventsHelper::implPostProcessEvent( EventQueue& rEventQueue, const EventHandlerInfo& rInfo, bool /*bSuccess*/, bool bCancel ) throw (uno::RuntimeException) { switch( rInfo.mnEventId ) { case WORKBOOK_OPEN: mbOpened = true; // register the listeners if( !mxListener.is() ) { mxListener = new ScVbaEventsListener( *this, mxModel, mpDocShell ); mxListener->startListening(); } break; case WORKBOOK_BEFORECLOSE: /* Execute Auto_Close only if not cancelled by event handler, but before UI asks user whether to cancel closing the document. */ if( !bCancel ) rEventQueue.push_back( AUTO_CLOSE ); break; } } ::rtl::OUString ScVbaEventsHelper::implGetDocumentModuleName( const EventHandlerInfo& rInfo, const uno::Sequence< uno::Any >& rArgs ) const throw (lang::IllegalArgumentException) { bool bSheetEvent = false; rInfo.maUserData >>= bSheetEvent; SCTAB nTab = bSheetEvent ? getTabFromArgs( rArgs, 0 ) : -1; if( bSheetEvent && (nTab < 0) ) throw lang::IllegalArgumentException(); String aCodeName; if( bSheetEvent ) mpDoc->GetCodeName( nTab, aCodeName ); else aCodeName = mpDoc->GetCodeName(); return aCodeName; } // private -------------------------------------------------------------------- SCTAB ScVbaEventsHelper::getTabFromArgs( const uno::Sequence< uno::Any >& rArgs, sal_Int32 nIndex ) throw (lang::IllegalArgumentException) { checkArgument( rArgs, nIndex ); // first try to extract a sheet index SCTAB nTab = -1; if( rArgs[ nIndex ] >>= nTab ) return nTab; // next, try single range object uno::Reference< sheet::XCellRangeAddressable > xCellRangeAddressable = getXSomethingFromArgs< sheet::XCellRangeAddressable >( rArgs, nIndex ); if( xCellRangeAddressable.is() ) return xCellRangeAddressable->getRangeAddress().Sheet; // at last, try range list uno::Reference< sheet::XSheetCellRangeContainer > xRanges = getXSomethingFromArgs< sheet::XSheetCellRangeContainer >( rArgs, nIndex ); if( xRanges.is() ) { uno::Sequence< table::CellRangeAddress > aRangeAddresses = xRanges->getRangeAddresses(); if( aRangeAddresses.getLength() > 0 ) return aRangeAddresses[ 0 ].Sheet; } throw lang::IllegalArgumentException(); } bool ScVbaEventsHelper::isSelectionChanged( const uno::Sequence< uno::Any >& rArgs, sal_Int32 nIndex ) throw (lang::IllegalArgumentException, uno::RuntimeException) { uno::Reference< uno::XInterface > xNewSelection = getXSomethingFromArgs< uno::XInterface >( rArgs, nIndex, false ); if( ScCellRangesBase* pNewCellRanges = ScCellRangesBase::getImplementation( xNewSelection ) ) { bool bChanged = maOldSelection != pNewCellRanges->GetRangeList(); maOldSelection = pNewCellRanges->GetRangeList(); return bChanged; } maOldSelection.Clear(); return true; } uno::Any ScVbaEventsHelper::createWorksheet( const uno::Sequence< uno::Any >& rArgs, sal_Int32 nIndex ) const throw (lang::IllegalArgumentException, uno::RuntimeException) { // Eventually we will be able to pull the Workbook/Worksheet objects // directly from basic and register them as listeners // extract sheet index, will throw, if parameter is invalid SCTAB nTab = getTabFromArgs( rArgs, nIndex ); // create Workbook uno::Sequence< uno::Any > aArgs( 2 ); aArgs[ 0 ] <<= uno::Reference< uno::XInterface >(); aArgs[ 1 ] <<= mxModel; uno::Reference< uno::XInterface > xWorkbook( createVBAUnoAPIServiceWithArgs( mpShell, "ooo.vba.excel.Workbook", aArgs ), uno::UNO_SET_THROW ); // create WorkSheet String aSheetName; mpDoc->GetName( nTab, aSheetName ); aArgs = uno::Sequence< uno::Any >( 3 ); aArgs[ 0 ] <<= xWorkbook; aArgs[ 1 ] <<= mxModel; aArgs[ 2 ] <<= ::rtl::OUString( aSheetName ); uno::Reference< uno::XInterface > xWorksheet( createVBAUnoAPIServiceWithArgs( mpShell, "ooo.vba.excel.Worksheet", aArgs ), uno::UNO_SET_THROW ); return uno::Any( xWorksheet ); } uno::Any ScVbaEventsHelper::createRange( const uno::Sequence< uno::Any >& rArgs, sal_Int32 nIndex ) const throw (lang::IllegalArgumentException, uno::RuntimeException) { uno::Reference< sheet::XSheetCellRangeContainer > xRanges = getXSomethingFromArgs< sheet::XSheetCellRangeContainer >( rArgs, nIndex ); uno::Reference< table::XCellRange > xRange = getXSomethingFromArgs< table::XCellRange >( rArgs, nIndex ); if ( !xRanges.is() && !xRange.is() ) throw lang::IllegalArgumentException(); uno::Sequence< uno::Any > aArgs( 2 ); aArgs[ 0 ] <<= uno::Reference< uno::XInterface >(); // dummy parent if ( xRanges.is() ) aArgs[ 1 ] <<= xRanges; else aArgs[ 1 ] <<= xRange; uno::Reference< uno::XInterface > xVbaRange( createVBAUnoAPIServiceWithArgs( mpShell, "ooo.vba.excel.Range", aArgs ), uno::UNO_SET_THROW ); return uno::Any( xVbaRange ); } uno::Any ScVbaEventsHelper::createHyperlink( const uno::Sequence< uno::Any >& rArgs, sal_Int32 nIndex ) const throw (lang::IllegalArgumentException, uno::RuntimeException) { uno::Sequence< uno::Any > aArgs( 2 ); aArgs[ 0 ] <<= uno::Reference< uno::XInterface >(); // dummy parent aArgs[ 1 ] <<= getXSomethingFromArgs< table::XCell >( rArgs, nIndex, false ); uno::Reference< uno::XInterface > xHyperlink( createVBAUnoAPIServiceWithArgs( mpShell, "ooo.vba.excel.Hyperlink", aArgs ), uno::UNO_SET_THROW ); return uno::Any( xHyperlink ); } uno::Any ScVbaEventsHelper::createWindow() const throw (uno::RuntimeException) { uno::Sequence< uno::Any > aArgs( 2 ); aArgs[ 0 ] <<= createVBAUnoAPIService( mpShell, "ooo.vba.Application" ); aArgs[ 1 ] <<= mxModel; uno::Reference< uno::XInterface > xWindow( createVBAUnoAPIServiceWithArgs( mpShell, "ooo.vba.excel.Window", aArgs ), uno::UNO_SET_THROW ); return uno::Any( xWindow ); } // ============================================================================ namespace vbaeventshelper { namespace sdecl = comphelper::service_decl; sdecl::class_ > serviceImpl; extern sdecl::ServiceDecl const serviceDecl( serviceImpl, "ScVbaEventsHelper", "com.sun.star.script.vba.VBASpreadsheetEventProcessor" ); } // ============================================================================