VBA宏打印PDF需求:自定义选择打印机并调出打印对话框
实现PDF打印时选择打印机并调出打印对话框
下面提供两种可行方案,根据你的环境选择:
方案1:依赖Adobe Acrobat(推荐)
如果系统安装了Adobe Acrobat完整版(非Reader),可以利用其VBA对象模型直接调出打印对话框,支持选择打印机和设置参数:
Sub GetBOM() Dim strPth As String, strFile As String Dim acroPDDoc As Object strPth = "C:\" strFile = "X.pdf" Set acroPDDoc = CreateObject("AcroExch.PDDoc") If acroPDDoc.Open(strPth & strFile) Then ' 弹出打印对话框,用户可选择打印机、调整设置 If Not acroPDDoc.PrintPagesSilent(0, acroPDDoc.GetNumPages - 1, 0, False) Then MsgBox "打印失败" End If acroPDDoc.Close Else MsgBox "无法打开指定PDF文件" End If Set acroPDDoc = Nothing End Sub
PrintPagesSilent的第四个参数设为False时触发打印对话框;设为True则静默用默认打印机打印。- 未安装Acrobat完整版时此方法不可用,可改用方案2。
方案2:无第三方依赖(系统API实现)
通过Windows API调用打印对话框获取用户选择的打印机,再执行打印:
' 32位Excel声明,64位需添加PtrSafe关键字 Public Declare Function PrintDlg Lib "comdlg32.dll" Alias "PrintDlgA" (pPrintdlg As PRINTDLG_TYPE) As Long Public Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" ( _ ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, _ ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long Public Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" ( _ ByVal Destination As String, ByVal Source As Long, ByVal Length As Long) ' 打印对话框结构体定义 Type PRINTDLG_TYPE lStructSize As Long hwndOwner As Long hDevMode As Long hDevNames As Long hDC As Long Flags As Long nFromPage As Integer nToPage As Integer nMinPage As Integer nMaxPage As Integer nCopies As Integer hInstance As Long lCustData As Long lpfnPrintHook As Long lpfnSetupHook As Long lpPrintTemplateName As String lpSetupTemplateName As String hPrintTemplate As Long hSetupTemplate As Long End Type Sub GetBOM() Dim strPth As String, strFile As String Dim pd As PRINTDLG_TYPE Dim result As Long strPth = "C:\" strFile = "X.pdf" ' 初始化对话框参数 pd.lStructSize = Len(pd) pd.hwndOwner = 0 pd.Flags = &H4 ' PD_RETURNDC:获取选中打印机的设备上下文 ' 调出打印对话框 result = PrintDlg(pd) If result = 1 Then ' 用户确认打印 If Not PrintPDFWithPrinter(0, strPth & strFile, pd.hDevNames) Then MsgBox "打印失败" End If Else MsgBox "已取消打印" End If End Sub Public Function PrintPDFWithPrinter(xlHwnd As Long, FileName As String, hDevNames As Long) As Boolean Dim X As Long Dim printerName As String Dim devNamesData As String Dim offset As Integer ' 从hDevNames中提取打印机名称 devNamesData = Space$(256) CopyMemory ByVal devNamesData, ByVal hDevNames, 256 offset = Asc(Mid$(devNamesData, 5, 1)) + Asc(Mid$(devNamesData, 6, 1)) * 256 + 7 printerName = Mid$(devNamesData, offset) ' 指定打印机执行打印 X = ShellExecute(xlHwnd, "PrintTo", FileName, Chr$(34) & printerName & Chr$(34), 0&, 3) PrintPDFWithPrinter = (X > 32) End Function
64位Excel适配说明
将所有API声明前添加PtrSafe关键字,例如:
Public Declare PtrSafe Function PrintDlg Lib "comdlg32.dll" Alias "PrintDlgA" (pPrintdlg As PRINTDLG_TYPE) As Long
注意事项
- 确保PDF文件路径正确,避免因路径错误导致操作失败。
- 方案1功能更完善,支持更多打印设置;方案2无需额外软件依赖,兼容性更广。
内容的提问来源于stack exchange,提问作者Vigna 65ST
相关产品推荐
相关产品推荐

