问题描述
我使用的是 Excel 2007 (12.0.4518.1014)
我一直在使用 WinHttpRequest 对象在为我托管数据的 Web 服务上执行 API GET 请求。
其他一切正常,它从网络服务中获取 JSON 格式的数据,并将其放入具有 .ResponseText
属性的字符串中。
我遇到的问题是在该字符串中,所有 Unicode 字符都变成了像 â??
这样的乱码,而不是 ✓
(U+2713)。这意味着当我执行 MyRange.Value = .ResponseText
时,单元格值变为 â??
。
如果我将 GET 请求设置为要求 Xml 格式,我会得到 �??
而不是 ✓
我已通过在 Chrome 中重复 GET 请求进行确认,网络服务正在输出正确的 Unicode 符号,并且 Chrome 能够向我显示 ✓
。所以这是 VBA 或 WinHttp 的问题。
Excel 本身能够生成 Unicode 符号,而 VBA 也能够生成ChrW(10003)
。
如何在 GET 请求期间保留 Unicode 符号?是否可以使用 WinHttp 或者我是否需要更改方法?
编辑:
以下是标准响应中的标头:
{
"access-control-allow-headers": "Content-Type","access-control-allow-methods": "GET,POST,PUT,DELETE,OPTIONS","access-control-allow-origin": "*","cache-control": "private","content-encoding": "gzip","content-security-policy": "frame-ancestors 'self',default-src * 'unsafe-inline' 'unsafe-eval' data: blob:;","content-type": "application/json","date": "Wed,23 Jun 2021 18:08:53 GMT","expect-ct": "max-age=0;","referrer-policy": "strict-origin-when-cross-origin","strict-transport-security": "max-age=31536000; includeSubDomains; preload","vary": "Accept-Encoding","x-content-type-options": "nosniff","x-frame-options": "SAMEORIGIN","x-stackifyid": "V2|80002f92-0000-3100-b63f-84710c7967bb|C61313|CD10436"
}
更新:已解决!
我已经通过@GSerg 的建议和@JoelCoeHoorn 的精彩见解解决了我的问题。自从我的问题结束后,我会在这里写下它是如何解决的。
WinHTTPRequest 被替换为 XMLHTTP 对象。该对象可以在 VBA 中使用与 WinHTTPRequest 类似的命令,如页面下方的链接所示。但是 XMLHTTP 对象能够毫无问题地返回 Unicode 字符。
要在 VBA 中使用它,您可以使用以下行创建它:
Dim http As Object
Set http = CreateObject("Microsoft.XMLHTTP")
然后您就可以使用类似于 WinHttpRequest 对象的 .open
和 .setRequestHeader
和 .Send
。
解决方法
我知道与 HTTP 事务相关的五种情况:
响应有一个标头,其中包含使用的特定编码。如果选择的编码不能显示文本中使用的所有字符点,这就是您得到的。
如果响应的文本是直接设置的,而不是映射到标头中指定的编码,那么这也是您得到的结果,因此编码表明文本应该与其实际不同。
由于历史原因,有一些编码是依赖于系统的,其中编码的上部区域取决于本地安装的语言包/设置。因此,如果标头选择特定于系统的编码并且文本设置在一个系统上,即使两端使用相同的编码,该上层区域的解释与客户端不同,您也可以看到这种效果。
出现这种情况的第四种方式是使用 UTF-8,当字节顺序标记被错误使用、忽略或解释为文本时。
最后,(这是这些选项中最有可能适合您的情况的)当在一个地方使用编码而另一个地方不支持时,可能会发生这种情况。 VBA 早于 unicode 的广泛采用,并且没有很好的 unicode 支持。特别是旧版本的 VBA,就像您在长期不受支持的 Excel 2007 中可能遇到的一样。
这些问题都倾向于仅在 unicode 字符上表现出来,而不会影响简单的拉丁字符,因为许多编码都以完全相同的方式处理简单的拉丁字符。