Did you find something
helpful on my site? Consider a donation!
Heeft u iets gevonden waar u wat aan had? Overweeg dan een donatie!
Registering a User Defined Function with Excel
Class module
The main code has been written in a class module called CUdfHelper.
This class contains almost all code you need to set things up. Internally,
there is a number of tricks involved in getting things working reliably:
Write all argument data for the REGISTER function into Excel's hidden name
space
Execute the REGISTER function using ExecuteExcel4Macro
This creates a new hidden name, with the name of the function and a
pointer to the dll that has been used. To ensure nothing goes wrong, this
pointer is set to zero
By declaring the UDF functions as type private, you avoid them from
showing up twice in the function wizard.
Relevant code:
Function RegisterFunction() AsBoolean ' Purpose : This procedure registers the user defined function ' Arguments : none ' Results : True is the function was registered successfully ' ' Notes : You must FIRST assign the properties ' --------------------------------------------------------------------- ' Date Developer Action ' 2006-02-23 Jurgen Volkerink Created
Dim i%, sCmd$, vRes
If VERBOSE Then 'Check we've got enough data SelectCaseTrue Case Len(m_uArgs.sDllName) = 0 MsgBox "DLLname not specified", vbExclamation ExitFunction Case Len(m_uArgs.sDllProc) = 0 MsgBox "DLLproc not specified", vbExclamation Case ProcInUse SelectCase MsgBox(DllName & " " & DllProc & " already registered." & _ vbLf & "Delete existing registration?", vbOKCancel) Case vbOK UnregisterFunction Case vbCancel ExitFunction EndSelect Case Len(m_uArgs.sFunText) = 0 MsgBox "FunText not specified", vbExclamation ExitFunction Case Len(m_uArgs.vCatName) = 0 MsgBox "CatName not specified", vbExclamation ExitFunction EndSelect Else 'errors will be raised by the property procedures EndIf
'Clear existing names DelArgumentNames 'Define names for each argument needed by the Register function SetArgumentNames
'Create the command string For i = 1 To 10 + NumArgs: sCmd = sCmd & "," & NAMEID & i: Next sCmd = "REGISTER(" & Mid(sCmd, 2) & ")"
'Execute the command vRes = Application.ExecuteExcel4Macro(sCmd)
'Block access to the DLL memory address 'Assign 0 to the Function namespace!!!! SetGlobalName Me.FunText, 0
'Unload arguments from namespace DelArgumentNames
If IsError(vRes) Then vRes = "Failed to Register:" & DllName & " " & DllProc & " " & FunText If VERBOSE Then MsgBox vRes Else Err.Raise 5, , vRes EndIf EndIf
EndFunction
And the routines that handle creating and deleting of the hidden names:
PrivateFunction SetGlobalName(sName AsString, OptionalByVal vValue AsVariant) AsVariant 'defines a global name to refer to a value. 'if vValue is omitted the name 'sName' is deleted.
Dim sCmd$ SelectCaseTrue Case IsArray(vValue) Err.Raise 16, , "SetGlobalName: Arrays s/b assigned as string like '{1,2,3}'" Case IsMissing(vValue) sCmd = "SET.NAME(" & Q & sName & Q & ")" Case IsEmpty(vValue) sCmd = "SET.NAME(" & Q & sName & QCQ & Q & ")" Case TypeName(vValue) = "String" sCmd = "SET.NAME(" & Q & sName & QCQ & vValue & Q & ")" CaseElse 'Int'l: The value must use a . as decimal separator vValue = Application.Substitute(CStr(vValue), Application.International(xlDecimalSeparator), ".") sCmd = "SET.NAME(" & Q & sName & QC & vValue & ")" EndSelect SetGlobalName = Application.ExecuteExcel4Macro(sCmd) EndFunction
PrivateSub DelArgumentNames() 'Deletes the argument "names" from Excel's (hidden) global namespace Dim i% For i = 1 To 30 SetGlobalName NAMEID & i Next EndSub