Running a Macro from a form

In a database of mine a very convenient way to execute some operations is by
running a small series of SQL statements.

As Base has no direct way to run a text file of SQL statements I asked on
Ask Libre Office and was given code in Basic that would read and execute a
file of SQL.

The first few lines of code are shown below

REM ***** BASIC *****

rem Option Explicit

Sub DoSQL

rem how to read text file

rem https://forum.openoffice.org/en/forum/viewtopic.php?f=20&t=33009

rem how to execute sql

rem
http://ask.libreoffice.org/en/question/21205/libreofficebase-how-to-execute-
sql-from-basic-script/

rem check database connection

DIM txtfile AS STRING

DIM f1 AS INTEGER

DIM s AS STRING

DIM oStatement AS OBJECT

MsgBox("Code started")

if IsNull(ThisComponent.CurrentController.ActiveConnection) then

     ThisComponent.CurrentController.connect

endif

If I run this from the macro menu it runs perfectly.

However if I create blank form with just one button and set the properties
of that button to

run the macro it fails at the line

if IsNull(ThisComponent.CurrentController.ActiveConnection) then

with the error message

"BASIC runtime error.

Property or method not found: ActiveConnection."

Can anyone help me please?

My final objective would be a form with 3 or 4 buttons each of which would
execute a different file of SQL

Regards

Allan

I assume that you have read this:

https://forum.openoffice.org/en/forum/viewtopic.php?f=45&t=67139

I have not looked at this stuff in a long time, but, here are a few thoughts off hand.

1. The error is stating that the "ActiveConnection" property is not available from the current controller for the current document. So, what is different with respect to the current document when you run this from a "form" compared to running this from an event handler? Again, I am just guessing, but... is the form part of a Base document? If it is, then you may need to grab the parent containing Base document, but that is a straight up guess. Do you know that you have an active connection? I think that this leads directly back into the link above related to ThisDatabaseDocument compared to ThisComponent.

Another possibility is that you test the current controller to see if it supports the ActiveConnection property. The fact that you test to see if the ActiveConnection is null, tells me that if you suspect that it may not contain one. I assume that you do something like this if needed:

oBaseContext = CreateUnoService("com.sun.star.sdb.DatabaseContext")
oDataBase = oBaseContext.getByName(sDBURL)
oCon = oDataBase.getConnection("", "")

At one point, I even did something silly like this inside of an event handler (not that I know if that would work for your or if it would still work):

oCon = oEvent.Source.Model.Parent.ActiveConnection
container = oCon.Parent.DatabaseDocument.FormDocuments

I hope this helps a little.

Hi Allan,

However if I create blank form with just one button and set the properties
of that button to

run the macro it fails at the line

if IsNull(ThisComponent.CurrentController.ActiveConnection) then

with the error message

"BASIC runtime error.

Property or method not found: ActiveConnection."

Can anyone help me please?

That error message is telling you (or should be telling you) that you
have no Database Context. ActiveConnection is instantiated via a
database connection context :

http://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1_1sdbc_1_1XConnection.html

so the macro in your form has to create such a context before
ActiveConnection can return any value.

As you don't say whether your form has been made within your ODB file,
or whether it is independent, it is hard to help out much further.
Generally, if the form is created within the ODB file, the connection
context is initiated upon opening the main ODB interface, whereas an
independent form needs to establish the connection context first. If
your form is within the ODB file, then one of the reasons why the
connection context might not be found is because it needs to walk up the
window hierarchy to find the main or parent. As far as I know, this has
always been a weakness of the CurrentComponent method within Base
containers where child form windows do not automatically inherit the
connection context. Andrew has indicated a way of obtaining the
connection context from by walking up the Model hierarchy of the
Database container.

From a quick read, the answer to your problem seems to have been

published here :

https://forum.openoffice.org/en/forum/viewtopic.php?f=45&t=42882#p198477

Alex

Hi Allan,

With the help of Andrew and Alex, you may have solved your problem by now.
But if not, I run lots of SQL commands in my Base applications and I could
post the Basic code I use, if that was likely to be of any use to you.

Noel

I always assume that it might be useful, which is why any of my documents exist :slight_smile:

So, by all means, post the code.

Noel,

Thanks to the replies from Andrew and Alex I have my code working.

I do however dislike "cut and paste without understanding" coding which is almost what I am doing
so any additional code would certainly be interesting to me.

Many thanks

Allan

Hi Andrew and Allan,

Below is the latest code I use in my databases for calling an SOL
Statement from a form. I have a Windows 7 64 bit PC and the database I use
is H2. The code should also work with Base's native database HSQL. I don't
know how it would work with other databases.

These macros normally have other lines in them, mainly creating variables
for use in reading from and writing to form controls, but for clarity, I
have stripped them out in this example. I've added a few comments which
hopefully will explain what is happening.

The example is taken from my TimeLog database which I use for recording
start and end times for each of my daily tasks. The form also has fields
for Job No, Job Class, Time taken and brief details of what was done.

For this example there are two forms –

1. the main form (which includes the 'Display Today's Tasks' button) and

2. a form which displays the results of the SQL commands in a table frame
linked to the table, TodaysTasks

REM ***** BASIC *****

' TimeLog.odb version: Example – Calling an SQL Statement from a form

OPTION EXPLICIT

'Global Variables

' Database Object

Global goConn AS Object 'database connection object

' ExecuteQuery variable

Global goStmt7 AS Object 'statement service object for any Table

' Misc variables

Global gsSQL AS String 'SQL Query string

Global gbInitDBDone AS Boolean 'Flag indicating connection state of Database

' fTimeLog 'Name of TimeLog Form

Global goFormTimeLog AS Object 'Form object

Global gbInitfTimeLog AS Boolean 'Flag indicating initialization state of
Timelog Form

'–------------- Initialization Macros
–-------------------------------------------------------------------------------------------------------------

Sub OpenfTimeLog() ' Called from TimeLog LO Main Menu.
Tools>Customise>Event: Open Document

Dim oCurrentForm AS Object

  gbInitDBDone = False

OpenForm("fTimeLog")

oCurrentForm = ThisDatabaseDocument.FormDocuments.getByName("fTimeLog")

goFormTimeLog = oCurrentForm.Component.Drawpage.Forms.getByName("fTimeLog")

End Sub

Sub OpenForm(FormName AS String) 'Called from OpenfTimeLog()

If gbInitDBDone = False Then

ConnectToTimeLogDatabase()

End if

With ThisDatabaseDocument.currentcontroller

If Not .isConnected Then

.Connect

End if

End With

ThisDatabaseDocument.FormDocuments.getByName(FormName).open()

End Sub

Sub ConnectToTimeLogDatabase() 'Called from openForm()

Dim oContext AS Object 'database context object

Dim oDB AS Object

oContext = CreateUnoService("com.sun.star.sdb.DatabaseContext")

oDB = oContext.getByName("TimeLog") 'get Database

goConn = oDB.getConnection("","") 'establish connection to database.

goStmt7 = goConn.createStatement() 'create a statement service object

gbInitDBDone = True

End Sub

' ------------------------------ End of Initialization Macros