// first try to extract a sheet index
sal_Int32 nTab = -1; if( rArgs[ nIndex ] >>= nTab )
{ if( (nTab < 0) || (nTab > MAXTAB) ) throw lang::IllegalArgumentException(); returnstatic_cast< SCTAB >( nTab );
}
// try VBA Range object
uno::Reference< excel::XRange > xVbaRange = getXSomethingFromArgs< excel::XRange >( rArgs, nIndex ); if( xVbaRange.is() )
{
uno::Reference< XHelperInterface > xVbaHelper( xVbaRange, uno::UNO_QUERY_THROW ); // TODO: in the future, the parent may be an excel::XChart (chart sheet) -> will there be a common base interface?
uno::Reference< excel::XWorksheet > xVbaSheet( xVbaHelper->getParent(), uno::UNO_QUERY_THROW ); // VBA sheet index is 1-based returnstatic_cast< SCTAB >( xVbaSheet->getIndex() - 1 );
}
// try single UNO range object
uno::Reference< sheet::XCellRangeAddressable > xCellRangeAddressable = getXSomethingFromArgs< sheet::XCellRangeAddressable >( rArgs, nIndex ); if( xCellRangeAddressable.is() ) return xCellRangeAddressable->getRangeAddress().Sheet;
// at last, try UNO range list
uno::Reference< sheet::XSheetCellRangeContainer > xRanges = getXSomethingFromArgs< sheet::XSheetCellRangeContainer >( rArgs, nIndex ); if( xRanges.is() )
{
uno::Sequence< table::CellRangeAddress > aRangeAddresses = xRanges->getRangeAddresses(); if( aRangeAddresses.hasElements() ) return aRangeAddresses[ 0 ].Sheet;
}
// This class is to process Workbook window related event class ScVbaEventListener : public ::cppu::WeakImplHelper< awt::XTopWindowListener,
awt::XWindowListener,
frame::XBorderResizeListener,
util::XChangesListener >
{ public:
ScVbaEventListener( ScVbaEventsHelper& rVbaEvents, const uno::Reference< frame::XModel >& rxModel, ScDocShell* pDocShell );
/** Starts listening to the passed document controller. */ void startControllerListening( const uno::Reference< frame::XController >& rxController ); /** Stops listening to the passed document controller. */ void stopControllerListening( const uno::Reference< frame::XController >& rxController );
uno::Reference< awt::XWindow > xWindow( rEvent.Source, uno::UNO_QUERY );
VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow ); // do not fire activation event multiple time for the same window if( pWindow && (pWindow != mpActiveWindow) )
{ // if another window is active, fire deactivation event first if( mpActiveWindow )
processWindowActivateEvent( mpActiveWindow, false ); // fire activation event for the new window
processWindowActivateEvent( pWindow, true );
mpActiveWindow = std::move(pWindow);
}
}
if( !mbDisposed )
{
uno::Reference< awt::XWindow > xWindow( rEvent.Source, uno::UNO_QUERY );
VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow ); // do not fire the deactivation event, if the window is not active (prevent multiple deactivation) if( pWindow && (pWindow == mpActiveWindow) )
processWindowActivateEvent( pWindow, false ); // forget pointer to the active window
mpActiveWindow = nullptr;
}
}
/* Check that the passed window is still alive (it must be registered in maControllers).Whileclosingadocument,postWindowResizeEvent()may becalledonthelastwindowwhichpostsausereventvia Application::PostUserEventtocallthiseventhandler.VCLwilltrigger thehandlersometimelater.Sometimes,thewindowgetsdeletedbefore. Thisishandledviathedisposing()functionwhichremovesthewindow pointerfromthemembermaControllers.Thus,checkingwhether
maControllers contains pWindow ensures that the window is still alive. */ if( !mbDisposed && pWindow && !pWindow->isDisposed() && (maControllers.count(pWindow) > 0) )
{ // do not fire event unless all mouse buttons have been released
vcl::Window::PointerState aPointerState = pWindow->GetPointerState(); if( (aPointerState.mnState & (MOUSE_LEFT | MOUSE_MIDDLE | MOUSE_RIGHT)) == 0 )
{
uno::Reference< frame::XController > xController = getControllerForWindow( pWindow ); if( xController.is() )
{
uno::Sequence< uno::Any > aArgs{ uno::Any(xController) }; // #163419# do not throw exceptions into application core
mrVbaEvents.processVbaEventNoThrow( WORKBOOK_WINDOWRESIZE, aArgs );
}
}
}
{ // note: there may be multiple processWindowResizeEvent outstanding // for pWindow, so it may have been added to m_PostedWindows multiple // times - so this must delete exactly one of these elements! autoconst iter(m_PostedWindows.find(pWindow));
assert(iter != m_PostedWindows.end());
m_PostedWindows.erase(iter);
}
release();
}
/* For document events: check if events are enabled via the Application.EnableEventssymbol(thisisanExcel-onlyattribute). Checkthisagainforeveryevent,astheeventhandlermaychangethe stateoftheEnableEventssymbol.GlobaleventssuchasAUTO_OPENand
AUTO_CLOSE are always enabled. */ bool bExecuteEvent = (rInfo.mnModuleType != script::ModuleType::DOCUMENT) || ScVbaApplication::getDocumentEventsEnabled();
// framework and Calc fire a few events before 'OnLoad', ignore them if( bExecuteEvent )
bExecuteEvent = (rInfo.mnEventId == WORKBOOK_OPEN) ? !mbOpened : mbOpened;
// special handling for some events if( bExecuteEvent ) switch( rInfo.mnEventId )
{ case WORKBOOK_OPEN:
{ // execute delayed Activate event too (see above)
rEventQueue.emplace_back(WORKBOOK_ACTIVATE );
uno::Sequence< uno::Any > aArgs{ uno::Any(mxModel->getCurrentController()) };
rEventQueue.emplace_back( WORKBOOK_WINDOWACTIVATE, aArgs ); if (!hasModule(u"Auto_Open"_ustr))
rEventQueue.emplace_back(AUTO_OPEN ); // remember initial selection
maOldSelection <<= mxModel->getCurrentSelection();
} break; case WORKSHEET_SELECTIONCHANGE: // if selection is not changed, then do not fire the event
bExecuteEvent = isSelectionChanged( rArgs, 0 ); break;
}
// 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:
checkArgumentType< bool >( rArgs, 0 );
aVbaArgs = { rArgs[ 0 ], {} }; // current cancel state will be inserted by caller break; // 1 arg: success case WORKBOOK_AFTERSAVE:
checkArgumentType< bool >( rArgs, 0 );
aVbaArgs = { rArgs[ 0 ] }; break; // 1 arg: window case WORKBOOK_WINDOWACTIVATE: case WORKBOOK_WINDOWDEACTIVATE: case WORKBOOK_WINDOWRESIZE:
aVbaArgs = { createWindow( rArgs, 0 ) }; break; // 1 arg: worksheet case WORKBOOK_NEWSHEET:
aVbaArgs = { 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 = { createRange( rArgs, 0 ) }; break; // 2 args: range, cancel case WORKSHEET_BEFOREDOUBLECLICK: case WORKSHEET_BEFORERIGHTCLICK:
aVbaArgs = { createRange( rArgs, 0 ), {} }; // current cancel state will be inserted by caller break; // 1 arg: hyperlink case WORKSHEET_FOLLOWHYPERLINK:
aVbaArgs = { 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 ); auto pVbaArgs2 = aVbaArgs2.getArray();
*pVbaArgs2 = createWorksheet( rArgs, 0 );
std::copy_n(std::cbegin(aVbaArgs), nLength, std::next(pVbaArgs2));
aVbaArgs = std::move(aVbaArgs2);
}
return aVbaArgs;
}
void ScVbaEventsHelper::implPostProcessEvent( EventQueue& rEventQueue, const EventHandlerInfo& rInfo, bool bCancel )
{ switch( rInfo.mnEventId )
{ case WORKBOOK_OPEN:
mbOpened = true; // register the listeners if( !mxListener.is() )
mxListener = new ScVbaEventListener( *this, mxModel, mpDocShell ); 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 && !hasModule(u"Auto_Close"_ustr))
rEventQueue.emplace_back(AUTO_CLOSE ); break;
}
}
/** Compares the passed range lists representing sheet selections. Ignores
selections that refer to different sheets (returns false in this case). */ bool lclSelectionChanged( const ScRangeList& rLeft, const ScRangeList& rRight )
{ // one of the range lists empty? -> return false, if both lists empty bool bLeftEmpty = rLeft.empty(); bool bRightEmpty = rRight.empty(); if( bLeftEmpty || bRightEmpty ) return !(bLeftEmpty && bRightEmpty);
// check sheet indexes of the range lists (assuming that all ranges in a list are on the same sheet) if (rLeft[0].aStart.Tab() != rRight[0].aStart.Tab()) returnfalse;
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.