Excellent. I knew I could count on you; that appears to be the trick.
It makes sense; the macro isn't associated with any particular
workbook, and needs to distinguish between possibly-conflicting macros
in multiple open workbooks.
I came up with this little helper to allow idiomatic F# curried
arguments:
open ExcelDna.Integration
open System
type FsXlCall = // Need to be class members to use ParamArray
static member TryExcel (xlFunction, [<ParamArray>] args:
Object[] )=
let oref = ref(new obj())
let result = XlCall.TryExcel(xlFunction,oref, args)
(result, !oref)
static member CallUDF ([<ParamArray>] args: Object[]) =
FsXlCall.TryExcel (XlCall.xlUDF, args)
let callUdfFromWorksheetFunction name args =
FsXlCall.CallUDF (name, args)
let callUdfFromMacro (refInWorkbook : ExcelReference) functionName arg
=
let sheetName = XlCall.Excel (XlCall.xlSheetNm, refInWorkbook) :?>
string
let workbookName = XlCall.Excel(XlCall.xlfGetDocument, 88,
sheetName) :?> string
let udfName = workbookName + "!" + functionName
FsXlCall.CallUDF (udfName, arg)
Now I can write
["Alice"; "Bob"; "Charlie"]
|> List.map (callUdfFromMacro worksheetName "FindLastName")
to get ["Cooper"; "Marley"; "Chaplain"]. And that makes me happy.
Of course, this only handles "uncurrying" one parameter. I think
you'd need individual functions (callUdf1, callUdf2, callUdf3...) for
each number of curried arguments. Otherwise you can go back to using
the (Fs)XlCall functions directly.
Thanks again, Govert!