LibreOffice Calc Goal Seek does not work from Basic Macro - libreoffice

I am trying to run a goal seek from a Calc Basic Macro.
Public Sub Goal_Seek()
oVariableCell = detailSheet.getCellRangeByName("VariableCell")
oFormulaCell = detailSheet.getCellRangeByName("FormulaCell")
oTargetCell = detailSheet.getCellRangeByName("TargetCell")
ThisComponent.seekGoal(oFormulaCell.CellAddress, oVariableCell.CellAddress, oTargetCell.getValue)
End Sub
When I run the Macro nothing is updated. When I run Goal Seek from the spreadsheet menu Tools->Goal Seek and enter the same cells in the form, the goal seek functions normally.
My Macro is in My Macros-Standard-Module1. The Named ranges return the right cell addresses. What could be causing the goal seek to not update when called from the Macro?

The reason it didn't work is I have to set the result myself when I call goal set from a Macro. I should have guessed that. The new code is
detailSheet = ThisComponent.Sheets(7)
oVariableCell = detailSheet.getCellRangeByName("VariableCell")
oFormulaCell = detailSheet.getCellRangeByName("FormulaCell")
oTargetCell = detailSheet.getCellRangeByName("TargetCell")
oGoal = ThisComponent.seekGoal(oFormulaCell.CellAddress, oVariableCell.CellAddress, oTargetCell.getValue)
oVariableCell.setValue(oGoal.Result)
End Sub

Related

Julia + GTK - global variable change in callback

I am trying to learn Julia Language, and my current project is a "5 in a row" program. I started making an interface with Julia wrapper on Gtk for this game, but stumbled upon an interesting problem. Code is below.
The problem is: after callback function work cur_step variable is not changing, and labels of buttons are not changing too. However, if I delete the if-condition in the callback function, buttons will all get labels "x" after pressing as it is supposed to be right now.
I'm writing my code with Julia 1.0 in Jupyter Notebook.
I've tried to set up cur_step variable as global, since thought that it was a scope problem, but it didn't work out.
using Gtk
cur_step = "x"
function click_once_callback(widget)
set_gtk_property!(widget, :sensitive, false)
set_gtk_property!(widget, :label, cur_step)
if cur_step == "x"
cur_step = "o"
else
cur_step = "x"
end
end
letters = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o']
win = GtkWindow("GoMoku")
g = GtkGrid()
buttons = []
for i=1:15
b = []
for j=1:15
letter = letters[i]
push!(b,GtkButton("$letter:$j"))
end
push!(buttons,b)
end
for i=1:15
for j=1:15
g[i,16-j] = buttons[i][j]
id = signal_connect(click_once_callback, buttons[i][j], "clicked")
end
end
set_gtk_property!(g, :column_homogeneous, true)
set_gtk_property!(g, :column_spacing, 15) # introduce a 15-pixel gap between columns
set_gtk_property!(g, :row_spacing, 15) # introduce a 15-pixel gap between rows
push!(win, g)
showall(win)
Why is it so that global variable not changing through the callback function? I expect to change cur_step iteratively after each button was clicked.
Thank you in advance!
You need to label cur_step as global inside your function (as well as outside, for good code signposting).
A function can use a variable from its parent scope without problems, as long as there's no assignment anywhere within the function's scope. If there is an assignment somewhere (even if it's in an if block), then the function is interpreted as local; this is true even prior to the point where its assignment occurs.
In order to treat a variable that gets assigned at some point inside the function properly as a global one, you need to explicitly point this out inside the function by using global cur_step.

LibreOffice Macro always show #NULL! after reopening the file

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

convert simple VB script to MATLAB

I have some problem converting simples VB scripts (formating) into MATLAB:
VB script:
Range("A1").Select
Selection.Font.Italic = True
With Selection.Borders(xlEdgeBottom)
.LineStyle = xlContinuous
End With
I tried:
xlswrite('test.xls',1,'A1');
Excel = actxserver('Excel.Application');
Excel.Workbooks.Open('test.xls');
Range = Excel.Range('A1');
Range.Font.Italic = True; % Doesnt work
Range.Border.Item('xlEdgeRight').LineStyle = 1; % Doesnt work
Excel.Visible = 1;
Any workaround? Thanks
The problem is probably this line:
Range = Excel.Range('A1');
Your Excel object is an Application object, which doesn't have a Range property. The VBA example you follow uses a (IMHO) poor practice of using the global default objects that are only available within the context of the application itself. You need to grab a reference to the Workbook returned by this call:
Excel.Workbooks.Open('test.xls');
After that, you need to get the worksheet from it's indexed Worksheets property, then get the Range from that. Also, "xlEdgeRight" is an enumeration member so external calls have to use the integer values for them instead of a string. You can replace xlEdgeRight with 10.
I know next to nothing about Matlab, but this is what the more explicit code would look like in VBA:
Dim book As Workbook, sheet As Worksheet, rng As Range
Set book = Application.Workbooks.Open("test.xls")
Set sheet = book.Worksheets("Sheet1")
Set rng = sheet.Range("A1")
rng.Font.Italic = True
rng.Borders.Item(10).LineStyle = 1
You should be able to get it from there.

1-line try/catch equivalent in MATLAB

I have a situation in MATLAB where I want to try to assign a struct field into a new variable, like this:
swimming = fish.carp;
BUT the field carp may or may not be defined. Is there a way to specify a default value in case carp is not a valid field? For example, in Perl I would write
my $swimming = $fish{carp} or my $swimming = 0;
where 0 is the default value and or specifies the action to be performed if the assignment fails. Seems like something similar should exist in MATLAB, but I can't seem to find any documentation of it. For the sake of code readability I'd rather not use an if statement or a try/catch block, if I can help it.
You can make your own function to handle this and keep the code rather clear. Something like:
swimming = get_struct(fish, 'carp', 0);
with
function v = get_struct(s, f, d)
if isfield(s, f)
v = s.(f); % Struct value
else
v = d; % Default value
end
Best,
From what I know, you can't do it in one line in MATLAB. MATLAB logical constructs require explicit if/else statements and can't do it in one line... like in Perl or Python.
What you can do is check to see if the fish structure contains the carp field. If it isn't, then you can set the default value to be 0.
Use isfield to help you do that. Therefore:
if isfield(fish, 'carp')
swimming = fish.carp;
else
swimming = 0;
end
Also, as what Ratbert said, you can put it into one line with commas... but again, you still need that if/else construct:
if isfield(fish,'carp'), swimming = fish.carp; else, swimming = 0;
Another possible workaround is to declare a custom function yourself that takes in a structure and a field, and allow it to return the value at the field, or 0.
function [out] = get_field(S, field)
if isfield(S, field)
out = S.(field);
else
out = 0;
end
Then, you can do this:
swimming = get_field(fish, 'carp');
swimming will either by 0, or fish.carp. This way, it doesn't sacrifice code readability, but you'll need to create a custom function to do what you want.
If you don't like to define a custom function in a separate function file - which is certainly a good option - you can define two anonymous functions at the beginning of your script instead.
helper = {#(s,f) 0, #(s,f) s.(f)}
getfieldOrDefault = #(s,f) helper{ isfield(s,f) + 1 }(s,f)
With the definition
fish.carp = 42
and the function calls
a = getfieldOrDefault(fish,'carp')
b = getfieldOrDefault(fish,'codfish')
you get for the first one
a = 42
and the previous defined default value for the second case
b = 0

Preventing Function Overriding in Lua Table

In my program when two functions with the same name are defined for the same table, I want my program to give an error. What's happening is that it's simply just calling the last function and executing it.
Here's a sample code
Class{'Cat'}
function Cat:meow( )
print("Meow!")
end
function Cat:meow()
print("Mmm")
end
kitty = Cat:create()
kitty:meow()
The result of the execution is only: "Mmm"
Instead I want something like an error message to be given.
Unfortunately, __newindex does not intercept assignments to fields which already exist. So the only way to do this is to keep Cat empty and store all its contents in a proxy table.
I don't know the nature of your OOP library, so you'll have to incorporate this example on your own:
local Cat_mt = {}
-- Hide the proxy table in closures.
do
local proxy = {}
function Cat_mt:__index(key)
return proxy[key]
end
function Cat_mt:__newindex(key, value)
if proxy[key] ~= nil then
error("Don't change that!")
end
proxy[key] = value
end
end
Cat = setmetatable({}, Cat_mt)