从 Excel/VBA 调用 Scala 函数

Call Scala Functions from Excel/VBA

我知道使用 C++ 可以创建包含某些函数的 DLL 文件,然后可以将其导入 Excel(例如通过 VBA)。让我们采用以下 C++ 函数

double __stdcall square_it(double &x)
{
    return x*x;
}

我们假设它包含在 square.dll 中,因此我们可以使用以下 VBA import

Declare PtrSafe Function square_it Lib "square.dll" (ByRef x As Double) As Double
Private Sub TestSub()
    MsgBox square_it(4.5)
End Sub

所以我的问题是:是否可以在 Scala 中编写一个函数,然后从 VBA 中调用它类似的时尚?

Scala 在这里与 Java 没有任何不同,并且查看 Java 问题,例如 Can you use Java libraries in a VB.net program? and Calling Java library (JAR) from VBA/VBScript/Visual Basic Classic,没有很好的解决方案来获得相同级别的集成你有 VBA/C++ 在 VBA/Java 或 VBA/Scala.

您始终可以使用任何外部渠道在您的 VBA 和您的 Scala 之间进行通信,例如 shell、文件系统,甚至是 http,但这不会那么简单和你的 VBA/C++ 示例一样高效。

这是通过 shell 进行通信的样子:

在example.scala中:

object Example {
  def main(args: Array[String]): Unit = {
    val d = args.head.toDouble
    println(d * d)
  }
}

在example.vba中:

Module Example
  Sub Main()
    Dim command As String 
    command = "scala /path/to/example.scala 123"
    Range("A1").Value = CreateObject("WScript.Shell").Exec(command).StdOut.ReadAll
  End Sub 
End Module

ScalaJVM 上运行,而 VBA 不运行,因此没有本地方式在它们之间传递对象。

ScalaVBA之间有两种通信方式:

一个选项是为每个过程调用启动一个新进程并解析输出,正如@OlivierBlanvillain 在他的回答中所建议的那样。

我认为首选方法是在网络套接字中进行通信,尤其是 http 使用网络服务器。

网络服务器

使用 scala 网络服务器(有很多),例如 scalatra,每个过程调用都应映射到对本地主机的 http 请求:

Scala 服务器代码(scalatra

class ScalaCall extends ScalatraServlet {

  get("/:func/:params") {
       Calling function {params("func")} with parameters {params("params")}
  }

}

VBA 客户端代码

Public Function ScalaCall(ByVal func As String, ByVal params As String) As String
  Dim WinHttpReq As Object
  Set WinHttpReq = CreateObject("Microsoft.XMLHTTP")
  WinHttpReq.Open "GET",   "http://127.0.0.1/" & func & "/" & params, False
  WinHttpReq.Send
  If WinHttpReq.Status = 200 Then
      ScalaCall = WinHttpReq.ResponseBody
  End If
End Function

VBA 上调用 ScalaCall("f","x") 应该调用对 scala 服务器的请求,这将输出 Calling function f with parameters x

您可以使用 Obba - 用于 Excel、LibreOffice 和 OpenOffice 的 Java 对象处理程序。