OpenOffice.org Forum at OOoForum.orgThe OpenOffice.org Forum
 
 [Home]   [FAQ]   [Search]   [Memberlist]   [Usergroups]   [Register
 [Profile]   [Log in to check your private messages]   [Log in

Timer in OOBasic

 
Post new topic   Reply to topic    OOoForum.org Forum Index -> OpenOffice.org Code Snippets
View previous topic :: View next topic  
Author Message
ms777
Super User
Super User


Joined: 07 Feb 2004
Posts: 1355

PostPosted: Mon Jul 16, 2007 10:35 am    Post subject: Timer in OOBasic Reply with quote

Hi,

OOBasic lacks a timer functionality. This post shows, how to implement a timer functionality in OOBasic using BeanShell.

It is rather straightforward and should be self explaining. To install
- put the BeanShell code into a calc document, into the library 'timer', under the name 'timer'(.bsh)
- put the Basic code into any module in the same document.
- run the Basic code

Have fun,

ms777

Edit May 2009: Please note that the below script stopped working since OO 2.3 or OO 2.4 due to a regression in the class loader handling ( http://qa.openoffice.org/issues/show_bug.cgi?id=89978 ). Please use the new script given in one of the next posts for OO 2.4, maybe also for OO 2.3

The Basic Code:
Code:
Sub Main
oP = GenerateTimerPropertySet()
oJob1 = createUnoListener("JOB1_", "com.sun.star.task.XJobExecutor")
oP.xJob = oJob1
oP.lMaxIterations    = 5
oP.lPeriodInMilliSec = 4000
oP.start()

oP2 = GenerateTimerPropertySet()
oJob2 = createUnoListener("JOB2_", "com.sun.star.task.XJobExecutor")
oP2.xJob = oJob2
oP2.lMaxIterations    = 10
oP2.lPeriodInMilliSec = 2000
oP2.start()
End Sub


function GenerateTimerPropertySet() as Any
oSP    = ThisComponent.getScriptProvider("")
oScript = oSP.getScript("vnd.sun.star.script:timer.timer.bsh?language=BeanShell&location=document")
GenerateTimerPropertySet = oScript.invoke(Array(), Array(), Array()
end function

sub JOB1_trigger(s as String)
oCell = ThisComponent.sheets.getByIndex(0).getCellByPosition(0,0)
oCell.Value = oCell.Value + 1
end sub

sub JOB2_trigger(s as String)
oCell = ThisComponent.sheets.getByIndex(0).getCellByPosition(1,0)
oCell.Value = oCell.Value + 1
end sub


The beanshell code:
Code:
import com.sun.star.uno.Type;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.lib.uno.helper.PropertySet;
import com.sun.star.lib.uno.helper.WeakBase;
import com.sun.star.task.XJobExecutor;
import com.sun.star.lang.XInitialization;
import com.sun.star.beans.PropertyValue;
import com.sun.star.beans.XPropertyChangeListener;
import com.sun.star.beans.PropertyChangeEvent;
import com.sun.star.lang.EventObject;
import com.sun.star.uno.AnyConverter;
import com.sun.star.xml.crypto.sax.XElementStackKeeper ; // defines a start and a stop routine

// This prevents an error message when executing the script a second time
xClassLoader = java.lang.ClassLoader.getSystemClassLoader();

try {
  xClassLoader.loadClass("ms777Timer_01");
  } catch (ClassNotFoundException e)
  {
  System.out.println( "class not found - compiling" );


public class ms777Timer_01 extends PropertySet  implements XElementStackKeeper
  {

// These are the properties of the PropertySet
  public boolean bFixedRate = true;
  public boolean bIsRunning = false;
  public int lPeriodInMilliSec = 2000;
  public int lDelayInMilliSec = 0;
  public int lMaxIterations = 5;
  public int lCurrentIteration = 0;
  public XJobExecutor xJob = null;

// These are some additional properties
  Task xTask =null;
  Timer xTimer = null;

  public ms777Timer_01()  {
    registerProperty("bFixedRate",  (short) 0);
    registerProperty("bIsRunning",  (short) com.sun.star.beans.PropertyAttribute.READONLY);
    registerProperty("lPeriodInMilliSec",  (short) 0);
    registerProperty("lDelayInMilliSec",  (short) 0);
    registerProperty("lMaxIterations",  (short) 0);
    registerProperty("lCurrentIteration",  (short) 0);
    registerProperty("xJob",  (short) com.sun.star.beans.PropertyAttribute.MAYBEVOID);
    xTimer = new Timer();
    }

//XElementStackKeeper
  public void start() {
    stop();
    if (xJob==null) {return;}
    xTask = new Task();
    lCurrentIteration = 1;
    bIsRunning = true;
    if (bFixedRate) {
      xTimer.scheduleAtFixedRate( xTask, (long) lDelayInMilliSec, (long) lPeriodInMilliSec );
      } else {
      xTimer.schedule( xTask, (long) lDelayInMilliSec, (long) lPeriodInMilliSec );
      }
    }

  public void stop() {
    lCurrentIteration = 0;
    bIsRunning = false;
    if (xTask!=null) { xTask.cancel();}
    }

  public void retrieve(com.sun.star.xml.sax.XDocumentHandler  h, boolean  b) { }

  class Task extends TimerTask  {
    public void run()  {
        xJob.trigger(lCurrentIteration.toString());
        lCurrentIteration +=1;
        if (lCurrentIteration > lMaxIterations) {
          stop();
          }
      }
    }
  }

System.out.println( "ms777PropertySet generated" );
} // of  if (xClass = null)

Object TA = new ms777Timer_01();
return TA;


Last edited by ms777 on Sun May 03, 2009 5:01 am; edited 1 time in total
Back to top
View user's profile Send private message
crun
General User
General User


Joined: 13 Jul 2007
Posts: 5

PostPosted: Sat Aug 25, 2007 3:10 pm    Post subject: Reply with quote

I have gotten time to try this now.
Thanks for the timer code, it runs as advertised.

From within JobXX_ callback function I can call an OOBasic routine in the same module eg "IncCell"

However I cannot call any method of RT, the Realterm active X server (this has been opened already, and can be used happily from button clicks)
It appears that RT.PutString never completes, ie if any instruction follows it in the JOB3 function, then OO locks up and must be terminated.


Code:

Global RT As Object  'public doesn't seem to be persistent in openoffice

Public Sub Realterm_Open
   Set RT = CreateObject("Realterm.RealtermIntf")
   RT.HalfDuplex = True  'so you can see what we send out through the port...
   RT.Caption = "Realterm Controlled from OpenOffice Calc"
   RT.portopen = True  'port is always closed when starting by automation
   RT.SelectTabSheet ("I2C")
 End Sub

Sub StartTempUpdateTimer
  oP3 = GenerateTimerPropertySet()
  oJob3 = createUnoListener("JOB3_", "com.sun.star.task.XJobExecutor")
  oP3.xJob = oJob3
  oP3.lMaxIterations    = 1
  oP3.lPeriodInMilliSec = 2000
  oP3.start()
End Sub

sub JOB3_trigger(s as String)
  IncCell    'works OK
  RT.PutString ("?")    'does not work
End Sub

sub IncCell
  oCell = ThisComponent.sheets.getByIndex(0).getCellByPosition(2,38)
  oCell.Value = oCell.Value + 1
End Sub

[/list]
Back to top
View user's profile Send private message
ms777
Super User
Super User


Joined: 07 Feb 2004
Posts: 1355

PostPosted: Tue Aug 28, 2007 1:13 pm    Post subject: Reply with quote

Hi,

I have done a little testing. As I do not have the Realterm ActiveX installed, I tried the MSScriptControl ActiveX:
Code:
Global VBScript as Object

Sub Main
oleService = createUnoService("com.sun.star.bridge.OleObjectFactory")
VBScript= oleService.createInstance("MSScriptControl.ScriptControl")
VBScript.Language = "VBScript"

oP = GenerateTimerPropertySet()
oJob1 = createUnoListener("JOB1_", "com.sun.star.task.XJobExecutor")
oP.xJob = oJob1
oP.lMaxIterations    = 10
oP.lPeriodInMilliSec = 1000
oP.start()
End Sub


function GenerateTimerPropertySet() as Any
oSP    = ThisComponent.getScriptProvider("")
oScript = oSP.getScript("vnd.sun.star.script:timer.timer.bsh?language=BeanShell&location=document")
GenerateTimerPropertySet = oScript.invoke(Array(), Array(), Array()
end function


sub JOB1_trigger(s as String)
x = GetShellWindows()
oSheet =  ThisComponent.sheets.getByIndex(0)
for k=0 to 20
  oSheet.getCellByPosition(0,k).String = ""
  next k
for k=LBound(x) to UBound(x)
  if x(k).Name = "Microsoft Internet Explorer" then
    oSheet.getCellByPosition(0,k).String = x(k).LocationUrl
    endif
  next k
end sub

function GetShellWindows() as Object
  Dim oleService
  Dim VBScript
  Dim s as string
  Dim ad

'comment these lines out, and the Basic IDE will pop up for each timer event
oleService = createUnoService("com.sun.star.bridge.OleObjectFactory")
VBScript= oleService.createInstance("MSScriptControl.ScriptControl")
VBScript.Language = "VBScript"

  s = ""   
  s = s + "Public oIE()" + Chr(10)
  s = s + "set oShell = CreateObject(""Shell.Application"")" + Chr(10)
  s = s + "set oShellWindows = oShell.Windows" + Chr(10)
  s = s + "if (not oShellWindows is nothing) then" + Chr(10)     
  s = s + " ReDim oIE(oShellWindows.count-1)" + Chr(10)     
  s = s + " k = 0" + Chr(10)     
  s = s + " for each o in oShellWindows" + Chr(10)
  s = s + "  set oIE(k) = o" + Chr(10)
  s = s + "  k = k + 1" + Chr(10)
  s = s + "  next" + Chr(10)
  s = s + " end if" + Chr(10)

  VBScript.ExecuteStatement(s)
  ad = VBScript.CodeObject.oIE
  GetShellWindows = ad
End function


This code runs as it should: It lists all open InternetExplorers with their LocationUrls in sheet 0.
The funny thing is: When you comment out the marked three lines in sub GetShellWindows, which are actually not necessary due to the global variable VBScript and the redundant initialization in the main sub, the Basic IDE pops up for each iteration. Seems a bit buggy ...

Maybe you want to try to shift your sub Realterm_open into the JOB3_trigger sub, if this is compatible with the 2000 msec repetition time ...

Good luck,

ms777
Back to top
View user's profile Send private message
ms777
Super User
Super User


Joined: 07 Feb 2004
Posts: 1355

PostPosted: Sun May 03, 2009 5:02 am    Post subject: Reply with quote

Here the BeanShell script which should be used from OO 2.4 onwards:

Code:
import com.sun.star.uno.Type;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.lib.uno.helper.PropertySet;
import com.sun.star.lib.uno.helper.WeakBase;
import com.sun.star.task.XJobExecutor;
import com.sun.star.lang.XInitialization;
import com.sun.star.beans.PropertyValue;
import com.sun.star.beans.XPropertyChangeListener;
import com.sun.star.beans.PropertyChangeEvent;
import com.sun.star.lang.EventObject;
import com.sun.star.uno.AnyConverter;
import com.sun.star.xml.crypto.sax.XElementStackKeeper ; // defines a start and a stop routine

// Workaround for  http://qa.openoffice.org/issues/show_bug.cgi?id=89978 needed from OO 2.4 onwards
Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());

// This prevents an error message when executing the script a second time

try { Class.forName("ms777Timer_06");}
  catch (ClassNotFoundException e) {
  System.out.println( "class not found - compiling start" );


public class ms777Timer_06 extends PropertySet  implements XElementStackKeeper
  {

// These are the properties of the PropertySet
  public boolean bFixedRate = true;
  public boolean bIsRunning = false;
  public int lPeriodInMilliSec = 2000;
  public int lDelayInMilliSec = 0;
  public int lMaxIterations = 5;
  public int lCurrentIteration = 0;
  public XJobExecutor xJob = null;

// These are some additional properties
  Task xTask =null;
  Timer xTimer = null;

  public ms777Timer_06()  {
    registerProperty("bFixedRate",  (short) 0);
    registerProperty("bIsRunning",  (short) com.sun.star.beans.PropertyAttribute.READONLY);
    registerProperty("lPeriodInMilliSec",  (short) 0);
    registerProperty("lDelayInMilliSec",  (short) 0);
    registerProperty("lMaxIterations",  (short) 0);
    registerProperty("lCurrentIteration",  (short) 0);
    registerProperty("xJob",  (short) com.sun.star.beans.PropertyAttribute.MAYBEVOID);
    xTimer = new Timer();
    }

//XElementStackKeeper
  public void start() {
    stop();
    if (xJob==null) {return;}
    xTask = new Task();
    lCurrentIteration = 1;
    bIsRunning = true;
    if (bFixedRate) {
      xTimer.scheduleAtFixedRate( xTask, (long) lDelayInMilliSec, (long) lPeriodInMilliSec );
      } else {
      xTimer.schedule( xTask, (long) lDelayInMilliSec, (long) lPeriodInMilliSec );
      }
    }

  public void stop() {
    lCurrentIteration = 0;
    bIsRunning = false;
    if (xTask!=null) { xTask.cancel();}
    }

  public void retrieve(com.sun.star.xml.sax.XDocumentHandler  h, boolean  b) { }

  class Task extends TimerTask  {
    public void run()  {
        xJob.trigger(lCurrentIteration.toString());
        lCurrentIteration +=1;
        if (lCurrentIteration > lMaxIterations) {
          stop();
          }
      }
    }
  }

System.out.println( "class not found - compiling end" );
} // of   catch (ClassNotFoundException e)

System.out.println( "generating timer property set ... " );
return new ms777Timer_06();
Back to top
View user's profile Send private message
ellebi
General User
General User


Joined: 11 Oct 2009
Posts: 13

PostPosted: Sun Oct 11, 2009 2:32 am    Post subject: Beanshell error for timer.bsh Reply with quote

Hi all
I try to make work this timer in my ooo calc sheet, with ooo basic macros, where i want to put the time (i.e. hours, minutes, seconds) in a TimeField of dialog, and I cannot fix the error that ooo gives me. The error exactly is
"Errore di runtime basic. Si รจ verificata un'eccezione
Type: com.sun.star.reflection.InvocationTargetException
Message: Beanshell error for timer.bsh
TargetException:
Type:
com.sun.star.script.provider.ScriptErrorRaisedException
Message: :Class cannot extends type: class.bsh.Primitive"

.
The ooo version is 3.1.1. I hope someone can help me.
Thanks.
Back to top
View user's profile Send private message
ms777
Super User
Super User


Joined: 07 Feb 2004
Posts: 1355

PostPosted: Sun Oct 11, 2009 7:17 am    Post subject: Reply with quote

Hi,

does my original code run on your machine as advertised ? Note that you have to take the OO2.4+ version ...

If yes, please post your complete code. If no, let me know what failure is generated

Good luck,

ms777
Back to top
View user's profile Send private message
ellebi
General User
General User


Joined: 11 Oct 2009
Posts: 13

PostPosted: Sun Oct 11, 2009 1:27 pm    Post subject: Reply with quote

Thanks for your reply!
As I told, my oo version is 3.1.1 (last), so your code does not work on my laptop (with fedora 11, kernel 2.6.30) because it is for 002.4+ version! I think not so...
Anyway I try to explain my code; it's a basic macro, in a calc document, for a dialogue with (between various controls) a TimeField where I want to see the current time (that of course change every minute). That's why I want to use the timer. I put your basic "main" code in the function where this dialog is opened (not complete) and the function "GenerateTimerPropertySet":

Function setDateTimeUnitsDialog() as boolean
...
Dim oThisDialog As Object
Dim oP As Object, oJob1 As Object
oP = GenerateTimerPropertySet()
oJob1 = createUnoListener("nowJob_", "com.sun.star.task.XJobExecutor")
oP.xJob = oJob1
oP.lMaxIterations = 5
oP.lPeriodInMilliSec = 1000
oP.start()
...
oThisDialog = CreateUnoDialog(DialogLibraries.Standard.dateTimeUnitsDialog)
setDateTimeUnitsDialog = oThisDialog.execute()
...
end function

'run script in Timer.bsh
Function GenerateTimerPropertySet() as Any
Dim oSP As Object, oScript As Object
oSP = ThisComponent.getScriptProvider("")
oScript = oSP.getScript("vnd.sun.star.script:Timer.Timer.bsh?language=BeanShell&location=document")
GenerateTimerPropertySet = oScript.invoke(Array(), Array(), Array())
End function

'here I would put later the instructions for update the TimeField
sub nowJob_trigger(s as String)
...
end sub

When I run the macro (a click on the sheet...) calc gives me the error; in the basic IDE, the code is highlighted at:

GenerateTimerPropertySet = oScript.invoke(Array(), Array(), Array())

in the beanshell editor there's a red arrow at:

public class ms777Timer_06 extends PropertySet implements XElementStackKeeper

The error is:
Basic runtime error. Exception occurred (...this translated in English, from Italian)
Type: com.sun.star.reflection.InvocationTargetException
Message: Beanshell error for timer.bsh
TargetException:
Type:
com.sun.star.script.provider.ScriptErrorRaisedException
Message: :Class cannot extends type: class bsh.Primitive

That's all. I hope you understand my problem.
Thanks.
Back to top
View user's profile Send private message
ellebi
General User
General User


Joined: 11 Oct 2009
Posts: 13

PostPosted: Sun Oct 11, 2009 3:15 pm    Post subject: Reply with quote

Hi,
I just tried the code (2nd version of beanshell script) on xp and it works. Perhaps it does not work in linux!
Back to top
View user's profile Send private message
ellebi
General User
General User


Joined: 11 Oct 2009
Posts: 13

PostPosted: Sun Oct 18, 2009 4:04 am    Post subject: Reply with quote

Hi
someone tell me if it is possible and how extend a java class in a BeanShell script in Linux environment! Thanks.
Back to top
View user's profile Send private message
blabj
Newbie
Newbie


Joined: 27 Oct 2009
Posts: 1

PostPosted: Tue Oct 27, 2009 11:05 am    Post subject: works on linux with oo3.0 Reply with quote

Great solution. Just advising that this is working on ubuntu hardy with OO 2.4 and ubuntu jaunty with OO 3.0. Only trick was that "bsh" (beanshell) needed to be installed separately.

-Bob
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    OOoForum.org Forum Index -> OpenOffice.org Code Snippets All times are GMT - 8 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group