[Calc] Event-Listeners & Handlers

Creating Extension - Shared Libraries
Forum rules
For sharing working examples of macros / scripts. These can be in any script language supported by OpenOffice.org [Basic, Python, Netbean] or as source code files in Java or C# even - but requires the actual source code listing. This forum is not for asking questions about writing your own macros.
Post Reply
User avatar
onidarbe
Posts: 84
Joined: Thu Nov 29, 2007 8:03 pm
Location: Belgium, Mechelen

[Calc] Event-Listeners & Handlers

Post by onidarbe »

Errors and behaviors described here, are when using OpenOffice 2.4.1 !!! No garantee given that there are no faults in this text :oops:
Please report faults or missing information ... Thank you, Onidar - Belgium
You can download the calc-file which shows every event on the statusBar....


Handler & Listeners
Events are tricky in OO !!! >>>>>>>>>>>> "OO-DEVELOPMENT, PLEASE DO SOMETHING !!!" ;)
They should beter insert a DataChangedInDocument" in oo-Calc/Tools/Customize/Events/...
providing the changed range and if possible the previous-cell, -selection and data
triggering the sub-event after the full copied data has entered with already moving the selection and activecell.


!!! Events will temporary interrupt each other until there own prg-code in the corresponding sub has finished !!!
Have a look at the statusbar and youll see while entering data, which event will fire and interrupt the other.
Using "WAIT 25" at the start of a event-sub will let the second event-sub start before running a bit of his own code.

ooBUGG: Stopping event-listeners and handlers only works when there is no programming done!
This is because objects get lost on programming while listeners keep on running.
So it is best to stop/start all events before programming using the sEvent_DeactivateDocument/sEvent_ActivateDocument
>>>>>> MORE FOR OO-DEVELOPMENT ;) Keep variables while programming and have a real step-by-step debugging system.

------------------------------------------------- XKeyHandler ----------------------------------------------------------
ooBUGG: Stops after a print-preview and maybe after something else? !!!
Starts every time an other listener up! So never start it twice.

---------------------------------------------- XMouseClickHandler ------------------------------------------------------
ooBUGG: Stops after a print-preview and maybe after something else? !!!
Starts every time an other listener up! So never start it twice.

------------------------------------------- XSelectionChangeListener ---------------------------------------------------
ooBUGG: Stops after a print-preview and maybe after something else? !!!
ooBUGG: ..._disposing doesnt get called. So one cant know when listener is suddenly gone !!!
ooBUGG: Triggers even when mousebutton is still down, so it keeps on selecting while still running sub.
Like when Msgbox is/has popped-up from the XSelectionChangeListener-sub selecting a range is still busy!!!
So dont use Msgbox in this sub !!!

If used with XChartDataChangeEventListener, XSelectionChangeListener will fire first, but XChart will interrupt it.
It is unpredictable where the XSelection...-sub-prg-code will be temporally stopt running XChart...-sub first !!!
Deleting cell-contense doesnt trigger this, but copy data in a selection does though the selection didnt change !?
Starts every time an other listener up! So never start it twice.

------------------------------------------ XPropertyChangeListener -----------------------------------------------------
ooBUGG: ..._disposing doesnt get called. So one cant know when listener is suddenly gone !!!
ooBUGG: Stops after a print-preview and maybe after something else? !!!

Triggers whenever the view changes: scroll, changing from sheet, ...
Doesnt normally start twice, unless you have altered the program-code. So never start it twice!

---------------------------------------------- XModifyListener ---------------------------------------------------------
ooBUGG: ..._disposing doesnt get called. So one cant know when listener is suddenly gone !!!
ooBUGG: No way to now what range has changed when using drag-fill, nothing in oEvent nor is it selected jet !!!

Triggers before changing the selection of a drag-fill and before moving the active-cell.
Doesnt stop with a print-preview. It keeps running as far as I know...
To be able to stop it, you need to put the range in an object, because ThisComponent.Sheets(0) doesnt seem to stay the same when using it to remove the listener !!!???
Starts every time an other listener up! So never start it twice.

---------------------------------------- XChartDataChangeEventListener -------------------------------------------------
ooBUGG: ..._disposing doesnt get called. So one cant know when listener is suddenly gone !!!
ooBUGG: To be able to stop it, you need to put the range in an object, because ThisComponent.Sheets(0) doesnt seem to stay the same when using it to remove the listener !!!???
ooBUGG: Listener stops on inserting a line. I did find a sulution to overcome this bugg, read next line...

:idea: TIP: Inserting/Deleting one line before starting the listener will allow you to inserting lines later on ;)
Runs after changing the selecting and activeCell & starting oXSelectionChangeListener-sub, but will interrupt it !
Doesnt stop with a print-preview. It keeps running as far as I know...
Doesnt normally start twice, unless you have altered the program-code. So never start it twice!

------------------------------------------------- XEventListener -------------------------------------------------------
= main listener, doesnt tell you when any data has changed, but it keeps running as far as I know...
EventName: OnFocus OnUnfocus OnNew OnPrint OnSave OnSaveAs OnSaveAsDone OnSaveDone OnLoad OnUnload OnPrepareUnload OnModifyChange OnCopyTo
ooBUGG: ..._disposing doesnt get called. So one cant know when listener is suddenly gone !!!
Doesnt stop with a print-preview. It keeps running as far as I know...
Cant be used to start lost listeners after print-preview. There is no trigger when chart is ready to be pointed to after print-preview.
If ooCalc-auto-saving is on, the listener will trigger this sub while programming!
Starts every time an other listener up! So never start it twice.

Code: Select all

'=================================== OOoBasic program-code to test the Events-Listeners =================================

'Errors and behaviors described here, are when using OpenOffice 2.4.1 !!!

sub sEvent_OpenDocument 'set to be called in oo-Calc/Tools/Customize/Events/"Open Document"
	'ooBAD: This event starts after ActivateDocument and will therefor interupting it while running this sub.
	sStatusBar ," OpenDoc{"
	wait 25
	sStartXModifyListener
	sStartXChartDataChangeEventListener
	sStartXEventListener
	sStatusBar ,"}"
end sub
sub sEvent_CloseDocument 'set to be called in oo-Calc/Tools/Customize/Events/"Close Document"
	sStatusBar ," CloseDoc{"
	wait 25
	sStopXModifyListener
	sStopXChartDataChangeEventListener
	sStopXEventListener
	sStatusBar ,"}"
	wait 2000
end sub

sub sEvent_ActivateDocument 'set to be called in oo-Calc/Tools/Customize/Events/"Activate Document"
	'ooBAD: Seems this event starts before OpenDocument, but get interupted at some time until OpenDocument-event has run his sub!!!
	sStatusBar ," ActDoc{"
	wait 25 'just to be shure sEvent_OpenDocument runs first
	sStartXKeyHandler
	sStartXMouseClickHandler
	sStartXSelectionChangeListener
	sStartXPropertyChangeListener
'	sStartXModifyListener
'	sStartXChartDataChangeEventListener
'	sStartXEventListener
	sStatusBar ,"}"
end sub
sub sEvent_DeactivateDocument 'set to be called in oo-Calc/Tools/Customize/Events/"Deactivate Document"
	sStatusBar ," DeactDoc{"
	wait 25
	sStopXKeyHandler
	sStopXMouseClickHandler
	sStopXSelectionChangeListener
	sStopXPropertyChangeListener
'	sStopXModifyListener
'	sStopXChartDataChangeEventListener
'	sStopXEventListener
	sStatusBar ,"}"
end sub

'========================================================================================================================
'============================================== Handler & Listeners =====================================================
'    Events are tricky in OO !!!   >>>>>>>>>>>> "OO-DEVELOPMENT, PLEASE DO SOMETHING !!!"
'    They should beter insert a 'DataChangedInDocument" in oo-Calc/Tools/Customize/Events/... 
'    providing the changed range and if possible the previous-cell, -selection and data ;-)
'    triggering the sub-event after the full copied data has entered with already moving the selection and activecell. 
'
' !!! Events will temporary interrupt each other until there own prg-code in the corresponding sub has finished !!!
' Have a look at the statusbar and you'll see while entering data, which event will fire and interrupt the other.
' Using "WAIT  25" at the start of a event-sub will let the second event-sub start before running a bit of his own code.
'
' ooBUGG: Stopping event-listeners and handlers only works when there is no programming done!
'    This is because objects get lost on programming while listeners keep on running.
'    >>>>>> MORE FOR OO-DEVELOPMENT ;-) Keep variables while programming and have a real step-by-step debugging system.
'    So it is best to stop/start all events before programming using the sEvent_DeactivateDocument/sEvent_ActivateDocument
'========================================================================================================================

'--------------------------------------------------- XKeyHandler --------------------------------------------------------
global oXKeyHandler as object
sub sStartXKeyHandler
	'ooBUGG: Stops after a print-preview and maybe after something else? !!!
	'Starts every time an other listener up! So never start it twice.
 	if isNull(oXKeyHandler) then 'only if not jet running
		sStatusBar ,"+K" 
		oXKeyHandler = CreateUnoListener("XKeyHandler_", "com.sun.star.awt.XKeyHandler") 
		ThisComponent.GetCurrentController.AddKeyHandler(oXKeyHandler) 
	else
		sStatusBar ,"!K"
	endif
end sub
sub sStopXKeyHandler
	if not IsNull(oXKeyHandler) then 'only if still running
		sStatusBar ,"-K"
		ThisComponent.GetCurrentController.removeKeyHandler(oXKeyHandler)
		oXKeyHandler=Nothing 'To know later this handler has stopt.
	else
		sStatusBar ,"!K"
	end if
end sub
sub XKeyHandler_Disposing(oEvent)
	sStopXKeyHandler
end sub 
function XKeyHandler_KeyPressed(oEvent) as boolean '''Shift, Ctrl and Alt alone doesn't trigger this !!!
	sScreenUpdatingOff
	sStatusBar ," Key" & chr(34)
	XKeyHandler_KeyPressed = False '=Don't cancel this KeyPressed 
	'if oEvent.KeyCode = com.sun.star.awt.Key.RIGHT then
	vCode=oEvent.keyCode
	select case vCode
	case 256 to 265 : vName="Num" & vCode-256
	case 512 to 537 : vName=chr(vCode-447)
	case 768 to 793 : vName="F" & vCode-767
	case 1024 to 1031 :	vName=choose(vCode-1023,"DOWN","UP","LEFT","RIGHT","HOME","END","PAGEUP","PAGEDOWN")
	case 1280 to 1290 : vName=choose(vCode-1279,"RETURN","ESCAPE","TAB","BACKSPACE","SPACE","INSERT","DELETE","ADD","SUBTRACT","MULTIPLY","DIVIDE")
	case 1291 to 1301 : vName=choose(vCode-1290,"POINT","COMMA","LESS","GREATER","EQUAL","OPEN","CUT","COPY","PASTE","UNDO","REPEAT")
	case 1302 to 1311 : vName=choose(vCode-1301,"FIND","PROPERTIES","FRONT","CONTEXTMENU","HELP","MENU","HANGUL_HANJA","DECIMAL","TILDE","QUOTELEFT")
	case 1536 to 1557 : vName=choose(vCode-1535,"DELETE_TO_BEGIN_OF_LINE","DELETE_TO_END_OF_LINE","DELETE_TO_BEGIN_OF_PARAGRAPH","DELETE_TO_END_OF_PARAGRAPH","DELETE_WORD_BACKWARD","DELETE_WORD_FORWARD","INSERT_LINEBREAK","INSERT_PARAGRAPH","MOVE_WORD_BACKWARD","MOVE_WORD_FORWARD","MOVE_TO_BEGIN_OF_LINE","MOVE_TO_END_OF_LINE","MOVE_TO_BEGIN_OF_PARAGRAPH","MOVE_TO_END_OF_PARAGRAPH","SELECT_BACKWARD","SELECT_FORWARD","SELECT_WORD_BACKWARD","SELECT_WORD_FORWARD","SELECT_WORD","SELECT_LINE","SELECT_PARAGRAPH","SELECT_ALL")
	case else : vName="???"
	end select
	vFunc=choose(oEvent.keyFunc+1,"","NEW","OPEN","SAVE","SAVEAS","PRINT","CLOSE","QUIT","CUT","COPY","PASTE","UNDO","REDO","DELETE","REPEAT","FIND","FINDBACKWARD","PROPERTIES","FRONT") 
	oMod=oEvent.Modifiers '1=Shift, 2=Ctrl, 4=Alt
	if oMod and 1 then vMod=vMod & "+SHIFT"
	if oMod and 2 then vMod=vMod & "+CTRL"
	if oMod and 4 then vMod=vMod & "+ALT"
	vChar=oEvent.keyChar
	IF vChar="" then
		vOut=vName
	elseif asc(vChar)>32 and asc(vChar)<176 then
		vOut=vChar
	else
		vOut=vName 
	end if
	wait 25
	sStatusBar ,vOut & vMod & chr(34)
	sScreenUpdatingOn
end function 
function XKeyHandler_KeyReleased(oEvent) as boolean 
	XKeyHandler_KeyReleased = False 'Don't cancel this
end function 

' ------------------------------------------ XMouseClickHandler -------------------------------------------------
global oXMouseClickHandler as object
global bMouseButton as boolean
global bMouseDoubleClick as boolean
sub sStartXMouseClickHandler
	'ooBUGG: Stops after a print-preview and maybe after something else? !!!
	'Starts every time an other listener up! So never start it twice.
	if isNull(oXMouseClickHandler) then 'only if not jet running
		sStatusBar ,"+M"
		oXMouseClickHandler = CreateUnoListener("XMouseClickHandler_", "com.sun.star.awt.XMouseClickHandler")
		ThisComponent.CurrentController.AddMouseClickHandler(oXMouseClickHandler)
	else
		sStatusBar ,"!M"
	endif
end sub
sub sStopXMouseClickHandler
	if not IsNull(oXMouseClickHandler) then 'only if still running
		sStatusBar ,"-M"
		ThisComponent.CurrentController.removeMouseClickHandler(oXMouseClickHandler)
		oXMouseClickHandler=Nothing 'To know later this handler has stopt.
	else
		sStatusBar ,"!M"
	end if
end sub
sub XMouseClickHandler_Disposing(oEvent)
	sStopXMouseClickHandler	
end sub
function XMouseClickHandler_mousePressed(oEvent) as boolean
	'Program code here could be temporary interrupted if mouse button is released earlier then executing this function-code!
	sStatusBar , " M("
	XMouseClickHandler_mousePressed = False 'Don't cancel mousePressed
	bMouseDoubleClick=(oEvent.ClickCount=2)
	if oEvent.Buttons=1 then bMouseButton=true
	wait 25
	sStatusBar , abs(bMouseDoubleClick)+1 & ")"
end function
function XMouseClickHandler_mouseReleased(oEvent) as boolean
	sStatusBar , " M("
	XMouseClickHandler_mouseReleased = False 'Don't cancel mouseReleased
	if oEvent.Buttons=1 then bMouseButton=false
	wait 25
	sStatusBar , abs(bMouseButton) & ")"
end function

' ----------------------------------------- XSelectionChangeListener ------------------------------------------------
global oXSelectionChangeListener as object
sub sStartXSelectionChangeListener
	'ooBAD: Stops after a print-preview and maybe after something else? !!!
	'ooBUGG: ..._disposing doesn't get called. So one can't know when listener is suddenly gone !!!
	'ooBUGG: Triggers even when mousebutton is still down, so it keeps on selecting while still running sub.
	'        Like when Msgbox is/has popped-up from the XSelectionChangeListener-sub selecting a range is still busy!!!
	'        So don't use Msgbox in this sub !!!
	'If used with XChartDataChangeEventListener, XSelectionChangeListener will fire first, but XChart will interrupt it.
	'  It is unpredictable where the XSelection...-sub-prg-code will be temporally stopt running XChart...-sub first !!!
	'Deleting cell-contense doesn't trigger this, but copy data in a selection does though the selection didn't change !?
	'Starts every time an other listener up! So never start it twice.
	if isNull(oXSelectionChangeListener)then 'just to be shure it doesn't start twice
		sStatusBar ,"+s"
		oXSelectionChangeListener=CreateUnoListener("XSelectionChangeListener_", "com.sun.star.view.XSelectionChangeListener")
		ThisComponent.CurrentController.AddSelectionChangeListener(oXSelectionChangeListener)
	else
		sStatusBar ,"!s"
	end if
end sub
sub sStopXSelectionChangeListener
	if not isNull(oXSelectionChangeListener) then 'only if still running
		sStatusBar ,"-s"
		ThisComponent.CurrentController.removeSelectionChangeListener(oXSelectionChangeListener)
		oXSelectionChangeListener=nothing 'To know later this listener has stopt.
	else
		sStatusBar ,"!s"
	end if
end sub
sub XSelectionChangeListener_Disposing(oEvent)
	Msgbox "XSelectionChangeListener_disposing does work now !?"
	sStopXSelectionChangeListener
end sub
sub XSelectionChangeListener_selectionChanged(oEvent)
	sScreenUpdatingOff
	sStatusBar ," s[" & a(ThisComponent.CurrentSelection) & "#" & a(o()) 
	wait 25
	sStatusBar ,"]"
	sScreenUpdatingOn
end sub

' ------------------------------------------ XPropertyChangeListener -------------------------------------------------
global oXPropertyChangeListener as object
sub sStartXPropertyChangeListener
	'ooBUGG: ..._disposing doesn't get called. So one can't know when listener is suddenly gone !!!
	'ooBUGG: Stops after a print-preview and maybe after something else? !!!
	'Triggers whenever the view changes: scroll, changing from sheet, ...
	'Doesn't normally start twice, unless you have altered the program-code. So never start it twice!
	if isNull(oXPropertyChangeListener)then 'just to be shure it doesn't start twice
		sStatusBar ,"+p"
		oXPropertyChangeListener=CreateUnoListener("XPropertyChangeListener_", "com.sun.star.beans.XPropertyChangeListener")
		ThisComponent.CurrentController.AddPropertyChangeListener("ActiveSheet", oXPropertyChangeListener)
	else
		sStatusBar ,"!p"
	end if
end sub
sub sStopXPropertyChangeListener
	if not isNull(oXPropertyChangeListener) then 'only if still running
		sStatusBar ,"-p"
		ThisComponent.CurrentController.removePropertyChangeListener("ActiveSheet", oXPropertyChangeListener)
		oXPropertyChangeListener=nothing 'To know later the listener has stopt.
	else
		sStatusBar ,"!p"
	end if
end sub
sub XPropertyChangeListener_Disposing(oEvent)
	Msgbox "XPropertyChangeListener_disposing does work now !?"
	sStoptXPropertyChangeListener
end sub
sub XPropertyChangeListener_propertyChange(oEvent)
	sStatusBar ," p("
	wait 25
	sStatusBar ,")"
end sub

' ------------------------------------------- XModifyListener --------------------------------------------------
global oXModifyListener as object
global oXModifyRange as object
sub sStartXModifyListener
	'ooBUGG: ..._disposing doesn't get called. So one can't know when listener is suddenly gone !!!
	'ooBUGG: No way to now what range has changed when using drag-fill, nothing in oEvent nor is it selected jet !!!
	'Triggers before changing the selection of a drag-fill and before moving the active-cell.
	'Doesn't stop with a print-preview. It keeps running as far as I know...
	'To be able to stop it, you need to put the range in an object, because ThisComponent.Sheets(0) doesn't seem to stay the same when using it to remove the listener !!!???
	'Starts every time an other listener up! So never start it twice.
	if isNull(oXModifyListener)then 'just to be shure it doesn't start twice
		sStatusBar ,"+m"
		oXModifyListener=CreateUnoListener("XModifyListener_", "com.sun.star.util.XModifyListener")
		'can't stop it using ThisComponent.Sheets(0).AddModifyListener(oXModifyListener)
		oXModifyRange=ThisComponent.Sheets(0)
		oXModifyRange.AddModifyListener(oXModifyListener)
	else
		sStatusBar ,"!m"
	end if
end sub
sub sStopXModifyListener
	if not isNull(oXModifyListener) then 'only if still running
		sStatusBar ,"-m"
		oXModifyRange.removeModifyListener(oXModifyListener)
		oXModifyListener=nothing 'To know later this listener has stopt.
	else
		sStatusBar ,"!m"
	end if
end sub
sub XModifyListener_Disposing(oEvent)
	Msgbox "XModifyListener_disposing does work now !?"
	sStopXModifyListener
end sub
sub XModifyListener_modified(oEvent)
	sScreenUpdatingOff
	sStatusBar ," m[" & a(ThisComponent.CurrentSelection) & "#" & a(o()) 
	wait 25
	sStatusBar ,"]"
	sScreenUpdatingOn
end sub

' --------------------------------------- XChartDataChangeEventListener ----------------------------------------------
global oXChartDataChangeEventListener as object
global oXChartDataChangeRange as object
sub sStartXChartDataChangeEventListener
	'ooBUGG: ..._disposing doesn't get called. So one can't know when listener is suddenly gone !!!
	'ooBUGG: To be able to stop it, you need to put the range in an object, because ThisComponent.Sheets(0) doesn't seem to stay the same when using it to remove the listener !!!???
	'ooBUGG: Listener stops on inserting a line. I did find a sulution to overcome this bugg, read next line...
	'   TIP: Inserting/Deleting one line before starting the listener will allow you to inserting lines later on ;-)
	'Runs after changing the selecting and activeCell & starting oXSelectionChangeListener-sub, but will interrupt it !
	'Doesn't stop with a print-preview. It keeps running as far as I know...
	'Doesn't normally start twice, unless you have altered the program-code. So never start it twice!
	if isNull(oXChartDataChangeEventListener)then 'just to be shure it doesn't start twice
		sStatusBar ,"+c"
		'!!! Following line can't be deleted, because otherwise the XChartDataChangeEventListener will stop if inserting a row or column just after the listener starts up.
		CreateUnoService("com.sun.star.frame.DispatchHelper").ExecuteDispatch(ThisComponent.CurrentController.Frame, ".uno:InsertRows", "", 0, Array())
		oXChartDataChangeEventListener=CreateUnoListener("XChartDataChangeEventListener_", "com.sun.star.chart.XChartDataChangeEventListener")	
		'Can't be stopt using:	ThisComponent.Sheets(0).AddChartDataChangeEventListener(oXChartDataChangeEventListener) 
		oXChartDataChangeRange=ThisComponent.Sheets(0)
		oXChartDataChangeRange.AddChartDataChangeEventListener(oXChartDataChangeEventListener) 
		'!!! Following line is to delete the needed inserted empty line. This will also trigger the listener!
		CreateUnoService("com.sun.star.frame.DispatchHelper").ExecuteDispatch(ThisComponent.CurrentController.Frame, ".uno:DeleteRows", "", 0, Array())
	else
		sStatusBar ,"!c"
	end if
end sub 
sub sStopXChartDataChangeEventListener
	if not isNull(oXChartDataChangeEventListener) then 'only if still running
		sStatusBar ,"-c"
		oXChartDataChangeRange.removeChartDataChangeEventListener(oXChartDataChangeEventListener)
		oXChartDataChangeEventListener=nothing 'To know later this listener has stopt.
	else
		sStatusBar ,"!c"
	end if
end sub
sub XChartDataChangeEventListener_Disposing(oEvent)
	'ooBUGG: this is never called, but should be!!!
	Msgbox "XChartDataChangeEventListener_disposing does work now !?"
	sStopXChartDataChangeEventListener
end sub
sub XChartDataChangeEventListener_chartDataChanged(oEvent)
	sScreenUpdatingOff
	sStatusBar ," c[" & a(ThisComponent.CurrentSelection) & "#" & a(o()) 
	'wait 25
	sStatusBar ,"]"
	sScreenUpdatingOn
end sub

' ----------------------------------------------- XEventListener ------------------------------------------------------
global oXEventListener as object
sub sStartXEventListener
	'= main listener, doesn't tell you when any data has changed, but it keeps running as far as I know...
	'EventName: OnFocus OnUnfocus OnNew OnPrint OnSave OnSaveAs OnSaveAsDone OnSaveDone OnLoad OnUnload OnPrepareUnload OnModifyChange OnCopyTo
	'ooBUGG: ..._disposing doesn't get called. So one can't know when listener is suddenly gone !!!
	'Doesn't stop with a print-preview. It keeps running as far as I know...
	'Can't be used to start lost listeners after print-preview. There is no trigger when chart is ready to be pointed to after print-preview.
	'If ooCalc-auto-saving is on, the listener will trigger this sub while programming!
	'Starts every time an other listener up! So never start it twice.
	if isNull(oXEventListener)then 'just to be shure it doesn't start twice
		sStatusBar ,"+e"
		oXEventListener=CreateUnoListener("XEventListener_", "com.sun.star.document.XEventListener")	
		ThisComponent.com_sun_star_document_XEventBroadcaster_addEventListener(oXEventListener)
	else
		sStatusBar ,"!e"
	end if
end sub
sub sStopXEventListener
	if not isNull(oXEventListener) then 'only if still running
		sStatusBar ,"-e"
		ThisComponent.com_sun_star_document_XEventBroadcaster_removeEventListener(oXEventListener)
		oXEventListener=nothing 'To know later the listener has stopt.
	else
		sStatusBar ,"!e"
	end if
end sub
sub XEventListener_Disposing(oEvent)
	Msgbox "XEventListener_disposing does work now !?"
	sStopXEventListener
end sub
sub XEventListener_notifyEvent(oEvent as object) 
	sStatusBar ," e(" & oEvent.EventName
	wait 25
	sStatusBar ,")"
	if OEvent.EventName="OnFocus" or OEvent.EventName="OnUnfocus" then exit sub
end sub
'====================================================================================================================
'======================================================= UTILITIES ==================================================
'========================================================================================================================
sub sOpenMacroEditor 'Assigned to a button to speed up opening the macro editor in this code.
'to assign it to a button: ooCalc/Tools/Customize/ToolBars/Add.../OpenOffice.org Macros/ThisFilename/Standard/Module1/sOpenMacroEditor/Add
	dim aOptions(5) as New com.sun.star.beans.PropertyValue
	aOptions(0).Name="LibName" : aOptions(0).Value="Standard" 'Name of library
	aOptions(1).Name="Name" : aOptions(1).Value="Module1" 'Name from Module or Dialog
	aOptions(2).Name="Line" : aOptions(2).Value=65 'Linenumber to set the cursor. NOTE: I which I could go to the last cursor or a marker...
	aOptions(3).Name="Type" : aOptions(3).Value="Module" 'Module or Dialog
	aTemp=split(ConvertFromURL(ThisComponent.GetURL),"\") :	aTemp=split(aTemp(uBound(aTemp)),".") 'Get filename
	aOptions(4).Name="Document" : aOptions(4).Value=aTemp(0) 'Name of the document = filename without extention
	oFrame = CreateUnoService("com.sun.star.frame.Frame")
	oDispatchHelper = createUnoService("com.sun.star.frame.DispatchHelper")
	oTemp = oDispatchHelper.ExecuteDispatch(oFrame, ".uno:BasicIDEAppear" ,"" ,0 ,aOptions())
end sub

sub sScreenUpdatingOff 
	EXIT SUB
	ThisComponent.CurrentController.Frame.ContainerWindow.Enable=False 
	if ThisComponent.isActionLocked=false then ThisComponent.AddActionLock
	if ThisComponent.hasControllersLocked=false then ThisComponent.LockControllers 
end sub 
sub sScreenUpdatingOn 
	EXIT SUB
	if ThisComponent.hasControllersLocked=true then ThisComponent.unLockControllers 
	if ThisComponent.isActionLocked=true then ThisComponent.removeActionLock
	ThisComponent.CurrentController.Frame.ContainerWindow.Enable=True 
end sub

sub sUndo()
	sScreenUpdatingOff
	oCell=o() 'get activecell
	CreateUnoService("com.sun.star.frame.DispatchHelper").ExecuteDispatch(ThisComponent.CurrentController.Frame, ".uno:Undo", "", 0, Array()) '= undo
	if not isError(oCell) then ThisComponent.CurrentController.Select(oCell) 'reselect previous activecell
	ThisComponent.CurrentController.Select(ThisComponent.CreateInstance("com.sun.star.sheet.SheetCellRanges")) 'unselect any range
	sScreenUpdatingOn
end sub
sub sRedo()
	sScreenUpdatingOff
	oCell=o() 'get activecell
	'activate undo
	CreateUnoService("com.sun.star.frame.DispatchHelper").ExecuteDispatch(ThisComponent.CurrentController.Frame, ".uno:Redo", "", 0, Array())
	if not isError(oCell) then ThisComponent.CurrentController.Select(oCell) 'reselect previous activecell
	ThisComponent.CurrentController.Select(ThisComponent.CreateInstance("com.sun.star.sheet.SheetCellRanges")) 'unselect any range
	sScreenUpdatingOn
end sub

function a(oIn) 'Gives the address with column-letters and without sheetname or $ from a cell, range or multiple ranges
	if isNull(oIn) then a="" : exit function
	vOut=oIn.Absolutename
	vOut=join(split(vOut,"$"),"") 'replaces all $ with ""
	vSheetName=left(vOut,instr(2,vOut,".")) 'get sheetname
	a=join(split(vOut,vSheetName),"") 'replaces all sheetnames with ""
end function

function fLastRow() as integer
	oSheet = ThisComponent.CurrentController.ActiveSheet
	oCursor = oSheet.createCursor()
	oCursor.GotoEndOfUsedArea(False)
	fLastRow = oCursor.RangeAddress().EndRow
end function
function fLastCol() as integer
	oSheet = ThisComponent.CurrentController.ActiveSheet
	oCursor = oSheet.createCursor()
	oCursor.GotoEndOfUsedArea(False)
	fLastCol = oCursor.RangeAddress().EndColumn
end function

function o(optional vChangeColOrRow) as object 'get the activecell with or whitout changing to an other row or column, column=columnname, row+1=number
	oActiveSheet=ThisComponent.CurrentController.ActiveSheet
	vViewData=ThisComponent.CurrentController.viewData
	vViewData=join(split(vViewData,";"),"/") 'replace ; with /
	vViewData=join(split(vViewData,":"),"/") 'replace : with /
	vViewData=join(split(vViewData,"+"),"/") 'replace + with /
	vViewData=split(vViewData,"/") 'split the string
	iCol=val(vViewData(6))
	iRow=val(vViewData(7))
	if not isError(vChangeColOrRow) then 'change row or column
		if isNumeric(vChangeColOrRow) then 'change row
			iRow=int(val(vChangeColOrRow))
		else 'change column
			for iCol=0 to 999
				if oActiveSheet.GetCellByPosition(iCol,0).String=vChangeColOrRow then exit for
				if oActiveSheet.GetCellByPosition(iCol,0).String="" then  'Column-label not found
					msgbox "Column-name " & chr(34) & vChangeColOrRow & chr(34) & " is not found !!!"
					exit function
				endif
			next
		endif
	endif
	o=oActiveSheet.GetCellByPosition(iCol,iRow)
end function

global vStatusBarText as string '=text that is been displayed on the statusbar
sub sStatusBar(optional vNewText, optional vAddText) 'set or add text to the statusbar, nothing = clear&reset it.
	if isNull(ThisComponent.CurrentController) then exit sub 'Exit if there is no statusbar, as on closing document.
	if isError(vNewText) then
		if isError(vAddText) then 'clear statusbar
			vStatusBarText=""
		else 'add text to the previous statusbar
			vStatusBarText=vStatusBarText & vAddText 
		endif
	else
		if isError(vAddText) then 'use new text
			vStatusBarText=vNewText
		else 'use new text and add the other text as well
			vStatusBarText=vNewText & vAddText
		endif
	endif
	if vStatusBarText="" then 'reset statusbar
		ThisComponent.CurrentController.StatusIndicator.Reset
	else 'change the text in the statusbar
		on error resume next 'comming from print-preview, XEventListener could run this and ThisComponent.CurrentController.VisibleArea doesn't exist.
		vStatusBarText=right(vStatusBarText,int(ThisComponent.CurrentController.VisibleArea.Width/150)) 'Select last part that could be displayed.
		ThisComponent.CurrentController.StatusIndicator.Start(vStatusBarText,0)
		on error goto 0
	endif
end sub
'===========================================================================================================================
Attachments
Event Listeners & Handlers.ods
ooCalc-file with the OOoBasic program-code to test the Events-Listeners
(15.61 KiB) Downloaded 1276 times
OOo 3.1.X on Ms Windows XP
oobigner
Posts: 1
Joined: Tue Jun 09, 2009 4:40 am

Re: [Calc] Event-Listeners & Handlers

Post by oobigner »

Thank for your post, it is amazing script, thanks. :P
OOo 2.4.X on Ubuntu 7.x + Linux
User avatar
Villeroy
Volunteer
Posts: 30676
Joined: Mon Oct 08, 2007 1:35 am
Location: Germany

Re: [Calc] Event-Listeners & Handlers

Post by Villeroy »

ooBUGG: Stopping event-listeners and handlers only works when there is no programming done!
Not everything is a bug. As a matter of course your global variables get lost when you recompile the edited code.
Simply store all the declarations on a separate module you don't have to touch:

Code: Select all

REM Separate module for declaration of persistent global symbols
Global gFooListener, gBarListener, gCounter%, gSomething
Please, edit this topic's initial post and add "[Solved]" to the subject line if your problem has been solved.
Ubuntu 18.04 with LibreOffice 6.0, latest OpenOffice and LibreOffice
Post Reply