3

我正在尝试移植我们在 Windows 上为 MS Word 工作的宏,该宏使用网站生成方程式图像并返回该图像以插入文档。当前(在 Windows 上工作)调用如下。当我在 OSX 中使用相同的调用时,我收到一条错误 429,指出“ActiveX 组件无法创建对象”。

' Create an xmlhttp object.
Set w_page = CreateObject("Microsoft.XMLHTTP")

' Open the connection to the remote server.
w_page.Open "POST", WebAdd, False

' Indicate that the body of the request contains form data
w_page.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"

' Actually send the request and return the data:
Font_Size = ComboFontSize.Value
w_page.Send "formula=" & Font_Size & "." & Latex_Str

错误是在Set w_page = CreateObject("Microsoft.XMLHTTP")语句上生成的。我尝试了几种替代方法,例如:

Set w_page = CreateObject("MSXML2.ServerXMLHTTP")

Set w_page = CreateObject("WinHttp.WinHttpRequest.5.1")

但是会产生同样的错误。请帮助我找到在 OSX Word 2011 中发送 POST 的正确方法。

对于任何感兴趣的人,该项目都可以在GitHub上找到。

非常感谢!

编辑:我发现这篇文章详细介绍了与 OSX Excel 一起使用的选项,但我找不到 OSX Word 的类似物。有人知道ActiveSheet.QueryTables可以在 OSX 中发送 POST 的与 Excel 等效的 Word 吗?

编辑:我取得了一些进展。看起来你可以通过 VBA 调用外部程序,并且所有 Mac 都安装了 Python,所以我编写了一个 Python 脚本,使用urlliburllib2发送请求到服务器。Python 文件还用于argparse从命令行解析公式字符串、字体大小和网址。

现在我的宏可以调用我的 python 脚本,例如:

sCmd = "python " & pyPath & "getURL.py --formula " & Latex_Str & " --fontsize "_
    & Font_Size & " " & WebAdd
sResult = Shell(sCmd, vbNormalFocus)

Latex_Str用户通过应用程序输入的Font_Size位置同样由用户定义,并且WebAdd是两个地址之一,具体取决于我们是生成方程式还是清理临时文件。

我无法弄清楚的是如何让 VBA 从我的 Python 脚本中读取返回值(一个字符串,其中包含来自我的服务器的返回值,我需要它以便以后检索图像文件)。该Shell命令似乎只返回一个 PID 号。有人可以帮忙吗?

解决方案:我想通了!我能够编写一个 Python 脚本来处理对服务器的 POST 请求并将其响应打印到标准输出。在社区和大量在线文档的帮助下,我能够使用 VBA 中的 AppleScript 和该result = vba.MacScript(command)方法调用这个 Python 脚本。这使我能够将 Python 脚本中的标准输出读入 VBA 中的字符串变量。我的 Python 脚本如下:

# Import the required libraries
from urllib import urlencode
from urllib2 import Request, urlopen, URLError, ProxyHandler, build_opener, install_opener
import argparse

# Set up our argument parser
parser = argparse.ArgumentParser(description='Sends LaTeX string to web server and returns meta data used by LaTeX in Word project')
parser.add_argument('webAddr', type=str, help='Web address of LaTeX in Word server')
parser.add_argument('--formula', metavar='FRML', type=str, help='A LaTeX formula string')
parser.add_argument('--fontsize', metavar='SIZE', type=int, default=10, help='Integer representing font size (can be 10, 11, or 12. Default 10)')
parser.add_argument('--proxServ', metavar='SERV', type=str, help='Web address of proxy server, i.e. http://proxy.server.com:80')
parser.add_argument('--proxType', metavar='TYPE', type=str, default='http', help='Type of proxy server, i.e. http')

# Get the arguments from the parser
args = parser.parse_args()

# Define formula string if input
if args.formula:
    values = {'formula': str(args.fontsize) + '.' + args.formula}   # generate formula from args
else:
    values = {}

# Define proxy settings if proxy server is input.
if args.proxServ:       # set up the proxy server support
    proxySupport = ProxyHandler({args.proxType: args.proxServ})
    opener = build_opener(proxySupport)
    install_opener(opener)

# Set up the data object
data = urlencode(values)
data = data.encode('utf-8')

# Send request to the server and receive response, with error handling!
try:
    req = Request(args.webAddr, data)

    # Read the response and print to a file
    response = urlopen(req)
    print response.read()

except URLError, e:
    if hasattr(e, 'reason'):    # URL error case
        # a tuple containing error code and text error message
        print 'Error: Failed to reach a server.'
        print 'Reason: ', e.reason
    elif hasattr(e, 'code'):    # HTTP error case
        # HTTP error code, see section 10 of RFC 2616 for details
        print 'Error: The server could not fulfill the request.'
        print 'Error code: ', e.code
        # print e.read()

我最近开始的这个相关线程MacScript将我指向调用我的函数并获取字符串返回的命令的方向,@CuberChase 让我开始编写外部函数来处理对服务器的调用。非常感谢!

4

1 回答 1

6

不幸的是,无法通过 Mac Office直接从 VBA执行 HTTP Post 请求。

您当前收到错误 429 说明“ActiveX 组件无法创建对象”,因为 OS X 中没有 XMLHTTP 对象模型(或 MSXML2 或 WinHttp),这些对象模型仅适用于 Windows。这意味着它们不适用于任何 Office 程序,而不仅仅是 Word。

您必须找到一种解决方法,例如可能使用 AppleScript(不确定是否可行)或在 curl 等外部程序上发出 shell 命令。这个 SO 答案将 Curl 用于 HTTP Get 请求,可能是最好的起点

于 2013-06-11T03:25:54.333 回答