【问题标题】:How can I solve this special character encoding problem between VBA and Powershell?如何解决 VBA 和 Powershell 之间的特殊字符编码问题?
【发布时间】:2021-10-11 04:10:36
【问题描述】:

对于较大的 vba 应用程序,我需要使用 powershell 脚本来为我提供共享上的文件名。由于我住在德国,这些文件名包含许多德国特殊字符,如 üä 等。

应该(并且在 PS 控制台上)正确显示这些字符的 powershell 脚本的输出在 VBA 中正确显示。我已经制作了这个最小的示例来演示这一点。

感谢任何回馈 für 而不是 fr 的解决方案。

Option Explicit
Const HK = """"

Sub ScanDrive()
    Dim s As String, command As String
   
    command = "echo 'für'"
    Debug.Print (command)
    'Method1: start PS in CMD with /u parameter
    s = CreateObject("Wscript.Shell").exec("cmd /u /c powershell.exe -command " & HK & command & HK).StdOut.ReadAll
    Debug.Print (s)
    'Method2: start PS directly (preferred)
    s = CreateObject("Wscript.Shell").exec("powershell.exe -command " & HK & command & HK).StdOut.ReadAll
    Debug.Print (s)
End Sub

我的输出看起来像这样(尽管 vba 根本不显示 `````` 字符):

echo 'für'
fr

fr

我已经了解到,当我写入文件输出时,我可以更改 PS 输出编码。不幸的是,这不是一个选择。

据我了解,我必须让 Excel 读取 UTF-8(我猜,就是这样)或让 PS 控制台写出 Win-1252(也只是猜测,这就是 Excel 使用的) .

由于我必须在公司中部署此脚本,因此我不能依赖 PS 控制台的任何全局开关。

更新

根据 JosefZ 的评论,我将命令设置为 [System.Console]::OutputEncoding 并在 VBA 中得到以下内容:

IsSingleByte      : True
BodyName          : ibm850
EncodingName      : Westeurop„isch (DOS)
HeaderName        : ibm850
WebName           : ibm850
WindowsCodePage   : 1252
IsBrowserDisplay  : False
IsBrowserSave     : False
IsMailNewsDisplay : False
IsMailNewsSave    : False
EncoderFallback   : System.Text.InternalEncoderBestFitFallback
DecoderFallback   : System.Text.InternalDecoderBestFitFallback
IsReadOnly        : True
CodePage          : 850

而不是直接在它声明的 powershell 中运行它:

IsSingleByte      : True
BodyName          : iso-8859-1
EncodingName      : Westeuropäisch (Windows)
HeaderName        : Windows-1252
WebName           : Windows-1252
WindowsCodePage   : 1252
IsBrowserDisplay  : True
IsBrowserSave     : True
IsMailNewsDisplay : True
IsMailNewsSave    : True
EncoderFallback   : System.Text.InternalEncoderBestFitFallback
DecoderFallback   : System.Text.InternalDecoderBestFitFallback
IsReadOnly        : True
CodePage          : 1252

CreateObject("Wscript.Shell") 似乎适用于 Dos 编码和 CP850。

【问题讨论】:

  • 我猜$OutputEncoding[System.Console]::OutputEncoding[System.Console]::InputEncoding 必须符合VBA 脚本编码(或内部Excel 编码?)...
  • @JosefZ,感谢您对这些命令的洞察力。我更新了添加这些命令的输出的问题。
  • 不是答案,但我发现这很有趣,可能对您有用:francescofoti.com/2020/01/…
  • 很好的问题/答案; +1。但是,您愿意编辑问题标题以使问题更准确吗? (提到编码特殊字符的东西),因为我相信它可能会在未来以这种方式帮助更多的人。
  • @Tragamor:感谢您的提示。我已经做到了。

标签: excel vba powershell encoding


【解决方案1】:

幸运的是,我找到了解决方案。

JosefZ 的评论让我走上了正轨,并把我从Garric 带到了this 被低估的答案,以回答另一个问题。

将他的解决方案改编为我最初的最小示例代码给出了这个:

Option Explicit
Const HK = """"

Sub ScanDrive()
    Dim s As String, command As String
    Dim codepage As String
    codepage = "windows-1252"
    command = "$OutputEncoding = [Console]::outputEncoding = [System.Text.Encoding]::GetEncoding('" + codepage + "'); echo 'für'"
    Debug.Print (command)
    s = CreateObject("Wscript.Shell").Exec("powershell.exe -command " & HK & command & HK).StdOut.ReadAll
    Debug.Print (s)
End Sub

Et Voilá - 我们的德语变音符号是正确的 :)

【讨论】:

  • 其他可能令人困惑的事情:如果您在 powershell 中运行此命令,则会出现无法分配给这些变量之一的错误。留下任何一个受让人可以修复错误,但它不适用于 vba。由于我们不消耗 Stderr,我认为这仍然可以。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-24
  • 2016-05-05
  • 1970-01-01
  • 1970-01-01
  • 2010-09-29
  • 1970-01-01
  • 2017-06-03
相关资源
最近更新 更多