从VBA调用Python - 返回Python函数值

时间:2018-06-18 18:02:14

标签: python vba

我从VBA调用Python脚本。这个Python脚本的结构是一个没有其他功能的单一函数:

def myFunction():
    # do stuff
    return stuff_output

我知道这个函数正常工作,因为如果添加,print(myFunction())会在命令行中生成正确的输出(JSON响应)。

在我的VBA代码中,'RetVal`始终是一个4位整数值。也许Python函数甚至没有被执行?

我应该修复哪些代码以使其正常工作?我很感激一个接近我当前代码的解决方案,如果可能的话没有外部库。

Option Explicit

Sub RunPython()

    Dim RetVal
    Dim scriptPath As String

    scriptPath = "C:\Users\Rychu\Desktop\python\myPythonScript.py"
    RetVal = Shell("C:\Python36-32\python.exe" & " " & scriptPath, vbHide)

    If RetVal = 0 Then
        MsgBox "Couldn't run python script!", vbOKOnly
    Else
        Debug.Print RetVal
    End If

End Sub

1 个答案:

答案 0 :(得分:1)

我无法找到传递Python函数返回值的直接方法,因此我通过将Python结果保存到桌面上的文本文件并使用VBA读取+删除相同文件来处理它。

重要的是:

    shellObj.Run不同的
  1. Shell允许设置一个布尔参数以等待返回True,以便其余的VBA代码不会尝试获取数据来自文本文件,但还没有创建。

  2. 如果文本文件没有指定完整的文件路径,只有文件名,Python不会在Python脚本所在的目录中创建文本文件,就像我运行时一样脚本通过命令行或Visual Studio。显然,当从VBA调用时,Python对默认目录有不同的看法,它也不是VBA文件的目录。

  3. 这是我的Python代码:

    def myFunction():
        # do stuff
        return stuff_output
    
    import os
    
    f = open(os.path.expanduser("~\Desktop") + "\myTemp.txt","w")   #create a new text file on Desktop in write mode
    f.write(str(myFunction()))  #write output to created text file 
    f.close()   #close file object
    

    这是我的VBA代码:

    Option Explicit
    
    Sub RunPython()
    
        Dim shellObj As Object: Set shellObj = CreateObject("WScript.Shell")
        Dim tempTxtPath As String
    
        Const scriptPath As String = "C:\Users\Rychu\Desktop\python\myPythonScript.py"
        Const pythonPath As String = "C:\Python36-32\python.exe"
        tempTxtPath = CreateObject("WScript.Shell").specialfolders("Desktop") & "\myTemp.txt"
    
        shellObj.Run pythonPath & " " & scriptPath, vbHide, True
    
        Debug.Print (getTextAndDelete(tempTxtPath))
    
    End Sub
    
    Function getTextAndDelete(filePath) As String
    
        Dim fileNum As Long
        Dim myData As String
    
        fileNum = FreeFile
        Open filePath For Binary As #fileNum
    
        myData = Space$(LOF(1))
        Get #fileNum, , myData
        Close #fileNum
    
        Kill filePath
    
        getTextAndDelete = myData
    
    End Function