从Excel/VBA调用Scala函数

7
我知道使用C++可以创建包含特定函数的DLL文件,然后可以将其导入到Excel中(例如通过VBA)。我们来看一下以下的C++函数。
double __stdcall square_it(double &x)
{
    return x*x;
}

我们假设 square.dll 中包含了所需的代码,这样我们就可以使用以下的VBA导入。
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中调用它?


这里有一个关于在.Net上运行Scala的解决方案。可以推测,这个方案也可以用于VBA。 - David
Scala可以生成jar文件,因为它生成JVM字节码。因此寻找运行Java jar文件的方法即可。快速浏览发现了这篇文章:https://dev59.com/7mgu5IYBdhLWcg3wZmW8 - Gene
3个回答

4

Scala在这里与Java没有什么不同,看看Java的问题,比如Can you use Java libraries in a VB.net program?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

谢谢您的回答,但是我还是有点不清楚。在VBA示例中,到底在哪里(或如何)引用example.scala文件? - Phil-ZXX
Exec的参数是要在shell中运行的命令,因此它基本上取决于您通常如何从终端运行scala。 sbt run将在当前目录中运行一个具有主方法的.scala文件。我更新了答案,提供了一种替代的、更明确的运行example.scala的方式 :) - OlivierBlanvillain
当我在命令行(即cmd)中键入“scala C:\example.scala 123”时,我得到了正确的输出15129.0,正如人们所期望的那样。但是当我运行VBA脚本并使用“command =“scala C:\example.scala 123””时,我会收到错误消息“系统找不到指定的文件,运行时错误-2147024894(80070002)”。有任何想法吗? :/ - Phil-ZXX
嗯,当我写command = "C:\program files\...\bin\scala.bat C:\example.scala 123"时,一切都正常。 - Phil-ZXX

3

Scala 运行在 JVM 上,而 VBA 则不运行在上述平台,因此它们之间没有本地方式传递对象。

ScalaVBA 之间进行通讯有两个选择:

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

我认为首选方法是使用网络套接字进行通信,特别是使用Web服务器上的http

Web服务器

使用 Scala Web 服务器(有很多),例如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服务器,它将输出使用参数x调用函数f


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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接