LibreOffice Macro always show #NULL! after reopening the file - macros

I wrote a macro in LibreOffice Calc and it is able to run correctly. But if I close the file and reopen, it always show #NULL! instead of the correct value. What am I missing here?
My macro code
Rem Attribute VBA_ModuleType=VBAModule
Option VBASupport 1
Function Calculate(CalType As String) As Double
'
' Calculate Macro
'
Dim i As Integer
Calc = 0
i = 1
Do While Not IsEmpty(Cells(i, 2))
If (Cells(i, 3).Value = CalType And (Cells(i,2) = "A" Or Cells(i,2) = "B")) Then
Calculate = Calculate + Cells(i, 4).Value
ElseIf (Cells(i, 3).Value = CalType And Cells(i,2) = "C") Then
Calculate = Calculate - Cells(i, 4).Value
End If
i = i + 1
Loop
'
End Function
The calling function will be something like =Calculate(J6)
The file is saved as .ods format.

The Cells call did not work at all for me. It is from VBA, not LO Basic. However I do not think that is the main problem.
LibreOffice expects that user-defined functions will be simple, only accessing the cell that contains the formula. Since the spreadsheet has not been fully loaded yet when the function is called, it is not possible to read other cells.
The workaround is to ignore errors and wait until the document is fully loaded before running the function. Take the following code as an example:
Function ReadOtherCell(row, col)
On Error GoTo ErrorHandler
oSheet = ThisComponent.CurrentController.ActiveSheet()
oCell = oSheet.getCellByPosition(row, col)
ReadOtherCell = "value is '" & oCell.getString() & "'"
Exit Function
ErrorHandler:
Reset
End Function
Sub RecalculateAll
' This is for user-defined functions that need to read the spreadsheet.
' Assign it to the "View created" event,
' because before that, the spreadsheet is not fully loaded.
ThisComponent.calculateAll
End Sub
Enter foo in A1, and =ReadOtherCell(0,0) in A2. So far, this has the same problem -- It will fail when the document is first opened.
Now, go to Tools -> Customize. In the Events tab, highlight View created. Press Macro... and find the RecalculateAll function. Then press OK.
Now when the document is closed and reopened, cell A2 should show the result value is 'foo'.
This is derived from B. Marcelly's answer at http://ooo-forums.apache.org/en/forum/viewtopic.php?f=20&t=73090&sid=f92a89d676058ab597b4b4494833b2a0.

I had the same problem.
I noticed that in the module, i had an empty Sub Main
After i 've erased it, the functions started working again

Related

Sub- or Function Procedure not defined

I am writing my first macro for Libre Office right now and I have come into a bit of a problem: My code throws the error: BASIC Runtime error; Sub- or Function procedure not defined.
The line with the "If Cells (RowCnt,ChkCol......) throws the error.
I've looked through other entries on here, but I could not find the error... can anyone help me?
REM ***** BASIC *****
Sub Zeilennausblenden_Nullsummen
BeginRow=4
EndRow = 46
ChkCol= D
For RowCnt = BeginRow To EndRow step 1
If Cells(RowCnt,ChkCol).Value > 1 Then
Cells(RowCnt,ChkCol).EntireRow.Hidden = True
End if
Next
End Sub
PS: The function should hide all rows in which an integer higher than "1" appears in column "D"
Thanks in advance
Here is what the code looks like in LibreOffice Basic (aka StarBasic):
Sub Zeilennausblenden_Nullsummen
BeginRow=4
EndRow = 46
ChkCol= 3
oSheet = ThisComponent.Sheets(0)
For RowCnt = BeginRow To EndRow step 1
oCell = oSheet.getCellByPosition(ChkCol,RowCnt)
If oCell.Value > 1 Then
oRow = oSheet.getRows().getByIndex(RowCnt)
oRow.IsVisible = False
End if
Next
End Sub
I wasn't sure if BeginRow should be 3 or 4, because it's zero-based. You can test it and decide.
Note that a macro is not necessary in order to accomplish this task. The easiest way is to go to Data -> More Filters -> Standard Filter.
That's because CELLS isn't a StarBasic function.
It's VBA (different programming language). Some versions of OpenOffice support the use of it if a statement (Option VBASupport 1) is put in first line of source code.
Check the net for Andrew Pitonyak's "OpenOffice Macros Explained" document - very good for learning and available in German translation, too.

How to end a Basic function properly

I'm trying to write a function in Basic for LibreOffice Calc to get the first letter of each word of the selected cell using the following code:
Function GetFirstLetters(rng) As String
Dim arr
Dim I As Long
arr = Split(rng, " ")
If IsArray(arr) Then
For I = LBound(arr) To UBound(arr)
GetFirstLetters = GetFirstLetters & Left(arr(I), 1)
Next I
Else
GetFirstLetters = Left(arr, 1)
End If
End Function
And it works correctly, unless I try to execute it again, then it seems that the new result gets appended to that of any previous execution and it will return both strings together, example:
It also doesn't matter if I delete some or even all cells, or if I call it using an empty cell or even in another page, it will always append the result to the previous one:
Why does this happen? How can I fix this behaviour?
I don't know anything about Basic, so please don't bash on me if this is something very simple.
The original function is this:
Function GetFirstLetters(rng As Range) As String
'Update 20140325
Dim arr
Dim I As Long
arr = VBA.Split(rng, " ")
If IsArray(arr) Then
For I = LBound(arr) To UBound(arr)
GetFirstLetters = GetFirstLetters & Left(arr(I), 1)
Next I
Else
GetFirstLetters = Left(arr, 1)
End If
End Function
And I got it from here: http://www.extendoffice.com/documents/excel/1580-excel-extract-first-letter-of-each-word.html.
The code you have found is VBA for Excel. Openoffice or Libreoffice uses StarBasic, not VBA. This is similar but not equal. So you can't simply use the same code as in Excel.
First difference is, there is no Range object. This you have noticed and have used rng as an Variant.
But another difference is, function names are like variable names in the global scope. And they will not be reseted if the function is called again. So in StarBasic we better do:
Function GetFirstLetters(sCellValue as String) As String
Dim arr As Variant
Dim I As Long
Dim sResult As String
arr = Split(sCellValue, " ")
If IsArray(arr) Then
For I = LBound(arr) To UBound(arr)
sResult = sResult & Left(arr(I), 1)
Next I
Else
sResult = Left(arr, 1)
End If
GetFirstLetters = sResult
End Function
sResult is reseted (new Dimed) every time the function is called. So even the function's return value.

Keeping information on Form B from Form A when Form A is closed

I was wondering if there is any code that lets some information you enter on Form A remain in the textboxes in Form B when Form A is closed. Im hoping to keep some user information entered into the first form on the second form and still have the first form close.
Thank you!
You can't maintain value from field when you close a form. So you can create some Global vars to copy his value and maintain on memory.
Sometimes i use another option: hide the form A meanwhile you use form B, then when you need to close Form B, simply check if A is open and then close it.
Function FIsLoaded(stFrmName$) As Integer
Dim I As Integer
For I% = 0 To Forms.Count - 1
If (Forms(I%).FormName = stFrmName$) Then
FIsLoaded = True
Exit Function
End If
Next I%
For I% = 0 To Reports.Count - 1
If (Reports(I%).FormName = stFrmName$) Then
FIsLoaded = True
Exit Function
End If
Next I%
FIsLoaded = False
End Function
With this function you can do before close form:
if fisloaded("formA") then
DoCmd.Close acForm ,"formA"
end if

Wanting to allow only 2 of the same form to be opened VB6

So far i have some code that allows a user to Hit F1 which loads a new form of the same properties and then hides the one the first one they had up, Hitting F2, allows the user to close the newly opened form and show the one they opened first. I would like a restriction that allows the user to open only 1 extra form if they hit F1 with 2 of the same forms open then a messagebox appears telling them to close the second form first otherwise allow it to be opened.
Here is what i have so far.
Private Sub Form_Load()
End Sub
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
Select Case KeyCode
Case vbKeyF1
'hides the current form
Me.Hide
'loads a new form with the same properties
Dim f As New Form1
Load f
'shows this new form
f.Show
'says that the second form is open
fOpen = True
Case vbKeyF2
'closes the second form
Unload Me
'says that the second form is closed
fOpen = False
'shows the first form you were on
Form1.Show
End Select
End Sub
Private Sub Form_QueryUnload(cancel As Integer, unloadmode As Integer)
'if your hitting "X" on second form then just close form2
If fOpen = False Then
Form1.Show
Else
'if your hitting "X" on main form close everything
Unload Me
End If
End Sub
Maybe something like if fOpen = true then disallow the user to hit F1? Not quite sure, but im close.
Forgive me if my VB6 is a little off, but you need to enumerate though the Forms collection to check to see if your form is already open...
Dim frm As Form
For Each frm In Forms
If frm.Name = "myForm" Then frm.Show()
Next frm
See this.
-- EDIT --
Just while I think on, to tune your code you could use a numeric iteration...
Dim f As Integer
Dim t As Integer
t = Forms.Count - 1
For f = 0 To t
If Forms(f).Name = "myForm" Then Forms(f).Show()
Next frm
-- EDIT 2 --
Just a further note on this. You may also want to introduce a counter so that you can check to see if there are two fields as in your original post...
Dim frm As Form
Dim c As Integer
For Each frm In Forms
If frm.Name = "myForm" Then
c = c + 1
If c = 2 Then
frm.Show()
Exit For 'Speed up the search if there are lots of forms
End If
End if
Next frm

add a matlab gui to a powerpoint presentation

I am curious if I can add a matlab gui to a powerpoint presentation. Either within the presentation or a link to open up matlab.
I call this function and it will open the figure then immediately close it.
Private Sub click_Click()
Call RunFile("new_control_pan", "C:\Users\mhaartman\Documents\PANE_golden2\PANE_golden\code")
End Sub
Sub RunFile(FILENAME As String, Optional FilePath As String)
Dim MATLAB As Object
Dim Result As String
Dim Command As String
Dim MATLABWasNotRunning As Boolean
'''''''''''''''''''''''''''''''''''''''''''''''''''
' Set Up
'''''''''''''''''''''''''''''''''''''''''''''''''''
' Connect to the automation server.
' MATLAB becomes a MATLAB handle to the running instance
' of MATLAB.
On Error Resume Next ' Defer error trapping
MATLAB = GetObject(, "matlab.application")
If Err.Number <> 0 Then
MATLABWasNotRunning = True
Set MATLAB = CreateObject("matlab.application")
Err.Clear ' Clear Err object in case error occurred.
End If
'''''''''''''''''''''''''''''''''''''''''''''''''''
' Do the Work
'''''''''''''''''''''''''''''''''''''''''''''''''''
If Not IsMissing(FilePath) And Not FilePath = "" Then
Command = "cd('" + FilePath + "')"
Result = MATLAB.Execute(Command)
End If
Command = FILENAME
Result = MATLAB.Execute(Command)
'Result = MsgBox("Done", vbOkayOnly, "Click when done")
End Sub
Thanks!
Maybe you could take a look at Calling MATLAB from PowerPoint.This submission on the File Exchange may be out of date, as it was created a few years ago. But the latest versions of MATLAB continue in general to offer a COM interface, which can be called from PowerPoint. It may need some updating, but I'm sure any issues are correctable.