VBA DIR函数返回非指定目录文件的异常问题排查
问题分析与解决方案
看起来你遇到了64位Windows系统下32位Office VBA的文件系统重定向坑——这是Windows更新后很常见的兼容性问题,咱们一步步拆解原因和解决办法:
为啥会出现这种矛盾的现象?
你的Office 16如果是32位版本,运行在64位Win10上时,VBA进程会被系统自动做文件重定向处理,这就导致了各个环节的行为不一致:
- Dir函数 & FileCopy:32位VBA访问
%CommonProgramFiles%时,系统会偷偷把路径重定向到C:\Program Files (x86)\Common Files,但实际上EXP_PDF.dll可能存在于64位专属的C:\Program Files\Common Files目录里。重定向对32位进程是透明的,所以Dir会返回“文件存在”,FileCopy也能成功复制(系统悄悄帮你从64位目录取了文件)。 - Shell.Application.Open:Shell.Application是系统级的64位组件,它不受32位进程重定向的影响,会直接访问你拼接的32位路径,而这个目录里确实没有目标文件,所以弹出“未找到”的错误。
验证重定向的存在
你可以运行这段代码,确认32位VBA看到的路径和系统真实路径的差异:
Sub CheckRedirectedPath() Dim actualPath As String Dim objWMIService As Object, colItems As Object, objItem As Object ' 通过WMI获取系统真实的64位CommonProgramFiles路径 Set objWMIService = GetObject("winmgmts:\\.\root\cimv2") Set colItems = objWMIService.ExecQuery("Select * From Win32_Environment Where Name='CommonProgramFiles'") For Each objItem In colItems actualPath = objItem.VariableValue Next Debug.Print "32位VBA看到的路径: " & Environ("commonprogramfiles") Debug.Print "系统真实的64位路径: " & actualPath End Sub
运行后你会发现,32位VBA拿到的是C:\Program Files (x86)\Common Files,而真实的64位路径是C:\Program Files\Common Files,EXP_PDF.dll大概率就在后者的对应Office子目录里。
解决办法
方法1:临时关闭文件系统重定向(推荐)
通过Windows API关闭重定向,让32位VBA能直接访问64位目录,操作完成后再恢复重定向:
Declare PtrSafe Function Wow64DisableWow64FsRedirection Lib "kernel32.dll" (ByRef OldValue As LongPtr) As Boolean Declare PtrSafe Function Wow64RevertWow64FsRedirection Lib "kernel32.dll" (ByVal OldValue As LongPtr) As Boolean Sub RetrieveFileFixed() Dim Shex As Object Dim oldRedirect As LongPtr Dim commonPath As String, officeVer As String, targetFile As String ' 临时关闭重定向,让32位VBA能访问64位目录 Wow64DisableWow64FsRedirection oldRedirect Set Shex = CreateObject("Shell.Application") officeVer = Format(Val(Application.Version), "00") ' 获取真实的64位CommonProgramFiles路径 commonPath = Environ("ProgramFiles") & "\Common Files" targetFile = commonPath & "\Microsoft Shared\OFFICE" & officeVer & "\EXp_PDF.DLL" If Dir(targetFile) > "" Then MsgBox targetFile & " Exists" Debug.Print targetFile FileCopy targetFile, "C:\Temp\exp_pdf.dll" Shex.Open targetFile ' 现在路径正确,能正常打开文件 Else MsgBox "File Doesn't Exist" End If ' 必须恢复重定向,避免影响后续其他操作 Wow64RevertWow64FsRedirection oldRedirect Set Shex = Nothing End Sub
方法2:替换为Office原生PDF导出(更彻底)
既然你的核心需求是导出PDF并发送邮件,Office 2016及以后版本已经支持原生PDF导出,完全不需要依赖EXP_PDF.dll,建议直接替换旧代码:
' 示例:导出当前工作表为PDF ActiveSheet.ExportAsFixedFormat _ Type:=xlTypePDF, _ Filename:="C:\Temp\MyEngineeringLog.pdf", _ Quality:=xlQualityStandard
这种方式从根源上避免了依赖第三方DLL的兼容性问题,更稳定可靠。
内容的提问来源于stack exchange,提问作者dlls4e
相关产品推荐
相关产品推荐

