如何解决 VBA 和 Powershell 之间的这个特殊字符编码问题?
How can I solve this special character encoding problem between VBA and Powershell?
对于更大的 vba 应用程序,我需要使用 powershell 脚本为我提供共享上的文件名。因为我住在德国,所以这些文件名包含很多德语特殊字符,例如 ü、ä 等。
powershell 脚本的输出,应该(并且在 PS 控制台上)正确显示这些字符 而不是 在 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。
幸运的是,我找到了解决方案。
JosefZ's comment put me on the right track and led me to this underrated answer from Garric另一个问题。
将他的解决方案改编为我最初的最小示例代码给出了这个:
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á - 我们的德语元音变音正确:)
对于更大的 vba 应用程序,我需要使用 powershell 脚本为我提供共享上的文件名。因为我住在德国,所以这些文件名包含很多德语特殊字符,例如 ü、ä 等。
powershell 脚本的输出,应该(并且在 PS 控制台上)正确显示这些字符 而不是 在 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。
幸运的是,我找到了解决方案。
JosefZ's comment put me on the right track and led me to this underrated answer from Garric另一个问题。
将他的解决方案改编为我最初的最小示例代码给出了这个:
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á - 我们的德语元音变音正确:)