Can I call a spreadsheet function from a custom function in SpreadsheetGear - spreadsheetgear

I am using SpreadsheetGear and have been given a spreadsheet with a VBA macro that I need to convert to a custom function (as SSG can't handle VBA code). The macro calls Excel functions (Match, Index) and I can't see how to call these functions from within my custom function. Any ideas if this is possible and how to do it?
Thanks

You can evaluate Excel formula strings by using the ISheet.EvaluateValue(...) method. Example:
// A1:A3 on "Sheet1" will be summed up.
object val = workbook.Worksheets["Sheet1"].EvaluateValue("SUM(A1:A3)");
// Ensure we actually get a numeric value back
if(val != null && val is double)
{
double sum = (double)val;
Console.WriteLine(sum);
}
However, it sounds like you will be using this method inside your custom function, so I should point out that you cannot use this method for any sheet that belongs to any workbook in the IWorkbookSet that is currently being calculated. Please review the rules that are laid out in the Remarks section for the Function.Evaluate(...) method, pasted below, particularly the ones I bolded:
The implementation of this method must follow a number of rules:
The method must be thread safe. Some versions of SpreadsheetGear call this method from multiple threads at the same time.
The method must not use any API in the workbook set which is being calculated except for IArguments.CurrentWorksheet.Name, IArguments.CurrentWorksheet.Index or IArguments.CurrentWorksheet.Workbook.Name.
All access to cells must be through arguments.
Accessing the IArguments indexer has the side effect of converting references to ranges or arrays to a single simple value. Use GetArrayDimensions and GetArrayValue to access the individual values of a range or array. For example, if the first custom function argument is the range A1:C3, setting a watch on arguments[0] in a debugger will convert this range to a single simple value.
No references to interfaces or objects passed to, or acquired during the execution of this method should be used after this method completes execution.
So if you call ISheet.EvaluateValue(...) within your custom function, it would have to be done on some sheet that belongs to an IWorkbookSet other than the one currently being calculated. It would also need to be done in a thread-safe manner, as per the first rule mentioned above.

Related

How can I combine these 2 functions without going over the 50,000 character limit?

I tried to simply replace anytime I referenced the cell into the actual function inside of the referred cell. This normally works in every single other function
I've done this with, but in this case, it's a big function and it gets referred to many times. This causes it to go over the 50,000 character limit for functions and this method no longer applies.
check out this spreadsheet to see the functions I'm talking about:
https://docs.google.com/spreadsheets/d/1RFA8s68TSQI2jQSOQm2_Ma776vC1LUQn7JP9tg-gZ1g/edit?usp=sharing
here's the formula:
=index(fixed(regexextract(A3,"[\d.]+")*product(10^vlookup(regexextract(A3,regexreplace(A3,"([A-Za-z])","($1)")),split(flatten(regexextract(flatten(split("Kk,Mm,Bb,Tt,q,Q,s,S,Oo,Nn,d,Uu,D",",")),regexreplace(flatten(split("Kk,Mm,Bb,Tt,q,Q,s,S,Oo,Nn,d,Uu,D",",")),"(.)","($1)"))&"❄️"&sequence(13,1,3,3)),"❄️"),2,0))/(2.5*B3+1)/10^sumproduct((exact(index(split(flatten(regexextract(flatten(split("Kk,Mm,Bb,Tt,q,Q,s,S,Oo,Nn,d,Uu,D",",")),regexreplace(flatten(split("Kk,Mm,Bb,Tt,q,Q,s,S,Oo,Nn,d,Uu,D",",")),"(.)","($1)"))&"❄️"&sequence(13,1,3,3)),"❄️"),,1),C3))*(index(split(flatten(regexextract(flatten(split("Kk,Mm,Bb,Tt,q,Q,s,S,Oo,Nn,d,Uu,D",",")),regexreplace(flatten(split("Kk,Mm,Bb,Tt,q,Q,s,S,Oo,Nn,d,Uu,D",",")),"(.)","($1)"))&"❄️"&sequence(13,1,3,3)),"❄️"),,2))),D3)&C3)
I couldn't find an efficient way to automatically convert back to the best unit because we are dealing with huge numbers that get turned to scientific notation preventing us from easily getting the actual length of the number. For this reason, I added a cell (C3) where you can specify the unit you want. I also added another cell (D3) where you can specify the amount of decimal places you want to display.

Is there a way to introspect a function in Lua?

I am creating a game in love2d (LuaJIT) and I am creating a debug window for changing values at runtime. I was able to do that, however, I also now want to be able to call functions. For example, I traverse a table and there is a function in this table called "hello" which is written like this:
self.hello = function(str, num)
print(string.format("%s: %d", str, num))
end
From the expression of type(object.hello) I only see function. If it had been a table, I could have traversed it and see the keys and values, but it is just a "function" and I have no idea how to properly call it, as I don't know what arguments does it take and how many. Is there a way to find this out at runtime in lua? Maybe this information is also stored in some table elsewhere?
it is just a "function" and I have no idea how to properly call it
Neither does Lua. As far as Lua is concerned, any Lua function can take any number of parameters and return any number of parameters. These parameters could be of any type, as could its return values.
Lua itself does not store this information. Or at least, not in any way you could retrieve without doing some decompiling of its byte-code. And since you're using LuaJIT, that "decompiling" might require decompiling assembly.

lldb python basic - print value of a global array while inside a breakpoint in a function

(Some background: I am not experienced with lldb or python and don't work on them frequently, but currently need to make some basic scripts for debugging an iphone program)
I am currently stopped at a breakpoint in side a function, and want to check the value of an array that has been accessed inside this function
This array is declared as
Float32 my_array[128];
and has global scope. I can view the array using print command, but I would like to make a python script so that I have more control over the output formatting and possibly plot the array elements as a graph using matplolib later on.
I am looking at the sample python code given in this question, and using the python given there I have verified that I can view local variables in this function (where currently I am stopped at a break point). For example, if I change 'base' in base=frame.FindVariable('base') to my local variable 'k' (the local variable is not an array) ,
base=frame.FindVariable('k')
then print base I can see the value of k. However, if I try this,
base=frame.FindVariable('my_array')
and do print base it gives me No value. How can I write a python command to get the values of any kind of variable currently in scope? Preferably it works for normal variables (int, float), arrays, and pointers, but if not, finding values of arrays are more important at the moment.
SBFrame.FindVariable searches among the variables local to that frame. It doesn't search among the global variables.
For that you need to use a search with a wider scope. If you know that the global variable is in the binary image containing the your frame's code - lldb calls that binary image a Module - then you can find the module containing that frame and use SBModule.FindGlobalVariables. If that's not true, you can search the whole target using SBTarget.FindGlobalVariables. If you know that only one global variable of that name exists, you can use FindFirstGlobalVariable variant.
All these commands will find variables of any type, and they all consistently return SBValues so you can format them in a consistent manner regardless of how you find them. For statically allocated arrays, the array elements are its children, so you can fetch individual elements with SBValue.GetChildAtIndex.
You can get to a SBFrame's module like:
module = frame.module
and its target:
target = frame.thread.process.target
lldb separates the contexts in which to search for variables primarily for efficiency. If SBFrame.FindVariable searched for globals as well as locals, a mistyped variable name would be a much more expensive mistake. But it also makes the call more predictable since you will never get some random global from some shared library that the system loaded on your behalf.

Closure inside Function

I'm trying to create a calculator using closures and functions. I got until the actual calculation function which takes in two values, then the user can select which operator to use (addition, multiplication, etc). I don't know how to actually return the value of that calculation.
A closure is, effectively, a function and you simply invoke it as such.
return operator(numberOne:valueOne, numberTwo:valueTwo)

Inheritance of TCollectionItem

I'm planning to have collection of items stored in a TCollection.
Each item will derive from TBaseItem which in turn derives from TCollectionItem,
With this in mind the Collection will return TBaseItem when an item is requested.
Now each TBaseItem will have a Calculate function, in the the TBaseItem this will just return an internal variable, but in each of the derivations of TBaseItem the Calculate function requires a different set of parameters.
The Collection will have a Calculate All function which iterates through the collection items and calls each Calculate function, obviously it would need to pass the correct parameters to each function
I can think of three ways of doing this:
Create a virtual/abstract method for each calculate function in the base class and override it in the derrived class, This would mean no type casting was required when using the object but it would also mean I have to create lots of virtual methods and have a large if...else statement detecting the type and calling the correct "calculate" method, it also means that calling the calculate method is prone to error as you would have to know when writing the code which one to call for which type with the correct parameters to avoid an Error/EAbstractError.
Create a record structure with all the possible parameters in and use this as the parameter for the "calculate" function. This has the added benefit of passing this to the "calculate all" function as it can contain all the parameters required and avoid a potentially very long parameter list.
Just type casting the TBaseItem to access the correct calculate method. This would tidy up the TBaseItem quite alot compared to the first method.
What would be the best way to handle this collection?
If they all have different method signatures, then you're not really gaining anything by having virtual methods - they might as well be static. I would be in favor of a "generic"/"canonical" set of parameters as in your case 2, and virtual/overridden Calculate methods, at least based on the description you've given so far.

Resources