VBA打开Unicode文件名二进制读取失败,报运行时错误52求助
解决VBA读取Unicode文件名文件时的错误52问题
这个问题我之前也碰到过,核心原因是VBA原生的Open语句仅支持ANSI编码的文件路径,完全不兼容Unicode字符(比如特殊中文、非拉丁语系字符),所以当你传入带Unicode的路径时就会触发"Bad file name or number"错误。下面给你两个可靠的解决办法:
方法一:使用Windows API的Unicode版本函数(推荐)
通过调用Windows API的宽字符版本函数(后缀带W的),可以完美支持Unicode路径。具体步骤如下:
- 在VBA模块的最顶部添加API声明(兼容32位和64位Office):
#If VBA7 Then Private Declare PtrSafe Function CreateFileW Lib "kernel32" (ByVal lpFileName As LongPtr, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As LongPtr, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As LongPtr) As LongPtr Private Declare PtrSafe Function ReadFile Lib "kernel32" (ByVal hFile As LongPtr, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, ByVal lpOverlapped As LongPtr) As Long Private Declare PtrSafe Function CloseHandle Lib "kernel32" (ByVal hObject As LongPtr) As Long Private Declare PtrSafe Function GetFileSize Lib "kernel32" (ByVal hFile As LongPtr, lpFileSizeHigh As Long) As Long #Else Private Declare Function CreateFileW Lib "kernel32" (ByVal lpFileName As Long, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long Private Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, ByVal lpOverlapped As Long) As Long Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long Private Declare Function GetFileSize Lib "kernel32" (ByVal hFile As Long, lpFileSizeHigh As Long) As Long #End If Private Const GENERIC_READ As Long = &H80000000 Private Const OPEN_EXISTING As Long = 3 Private Const FILE_SHARE_READ As Long = &H1
- 重写你的
GetFileBytes函数,用API替代原生Open:
Function GetFileBytes(ByVal sPath As String) As Byte() Dim hFile As LongPtr Dim fileSize As Long Dim bytesRead As Long Dim bytRtnVal() As Byte ' 打开Unicode路径的文件 hFile = CreateFileW(StrPtr(sPath), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0) If hFile = -1 Then Err.Raise 53 ' 文件未找到或无法打开 End If ' 获取文件大小 fileSize = GetFileSize(hFile, 0) If fileSize = 0 Then ' 处理空文件 ReDim bytRtnVal(0 To -1) Else ReDim bytRtnVal(0 To fileSize - 1) As Byte ' 读取文件内容到字节数组 ReadFile hFile, bytRtnVal(0), fileSize, bytesRead, 0 If bytesRead <> fileSize Then Err.Raise 70 ' 读取文件失败 End If End If ' 关闭文件句柄 CloseHandle hFile GetFileBytes = bytRtnVal Erase bytRtnVal End Function
方法二:使用FileSystemObject(简单场景备选)
如果你不想用API,也可以用FSO来读取二进制文件,FSO对Unicode路径的支持更好:
Function GetFileBytes_FSO(ByVal sPath As String) As Byte() Dim fso As Object Dim fileStream As Object Set fso = CreateObject("Scripting.FileSystemObject") If Not fso.FileExists(sPath) Then Err.Raise 53 ' 文件未找到 End If Set fileStream = fso.OpenTextFile(sPath, 1, False, -2) ' -2代表Unicode格式打开 GetFileBytes_FSO = fileStream.ReadAll fileStream.Close Set fileStream = Nothing Set fso = Nothing End Function
注意:FSO对于超大文件的读取效率不如API,所以大文件优先用方法一。
额外提醒
- 可以用
Debug.Print sPath把路径输出到立即窗口,确认路径没有隐藏的不可见字符 - 确保Excel单元格里的路径没有被自动截断或格式错乱
内容的提问来源于stack exchange,提问作者MarkS
相关产品推荐
相关产品推荐

