VBA的调试输出只有简单的Debug.Print,在接触过C语言之后,很喜欢printf那种形式的打印输出,无奈一直觉得C语言太难了,没能深入去学习。
后来接触了go语言后,觉得这种语言学起来还算简单,也很像C语言。所以在学习一段时间后,就想着能不能用go语言封装dll给VBA使用,前面讲到的那些关于指针、数据类型的东西,主要就是为了做dll:
在了解了VBA的数据类型后,我们才能把VBA的数据传递到dll中,并正确的解析数据,这里简单介绍一下封装go语言的Sprintf函数。
效果:
1、函数声明
func Sprintf(format string, a ...interface{}) string
这个是go语言的Sprintf函数,可以按c语言的Sprintf函数来理解,第1个参数好处理,关键是后面的可变参数,因为它是允许任意类型和任意数量的:
所以,VBA里的函数声明为:
Public Sub Printf(format As Variant, ParamArray args() As Variant)
End Sub
format是string,为了方便统一处理,都按Variant类型来传递。
封装Sprintf的目的就是为了能得到一个格式化的字符串,VBA的String和go语言里的string是不一样的,所以dll传出来的string需要转换,API声明:
Public Declare Function gosprintf Lib "godllForVBA32.dll" (ByVal pFormat As Long, ByVal pVBAVariant As Long, ByVal nCount As Long) As MyString
Type MyString
pUCS2 As Long
Len As Long
End Type
为了方便处理,我是在go语言里把String转换为了VBA里的编码,这样在VBA里不需要再次转码了。
2、go实现:
go语言里的函数:
func Sprintf(pformat, pParamArray, nCount int32) (ptr unsafe.Pointer, lenth int)
参数pformat, pParamArray接收VBA传入的指针,nCount直接接收数值,函数返回VBA的String及长度。
实现过程:
3、编译
go.exe build -v -x -buildmode=c-archive -o c\go.a
生成.a和.h 2个文件
struct Sprintf_return __stdcall gosprintf(GoInt p0, GoInt p1, GoInt p2) {
return Sprintf(p0, p1, p2);
}
EXPORTS
gosprintf
cfree
gcc.exe c\stdcall.c c\go.def c\go.a -shared -lwinmm -lWs2_32 -o go.dll -Wl,--enable-stdcall-fixup,--out-implib,go.lib
go语言的具体实现因为和VBA代码相关性不大,就不展开讲。