以编程方式打印到pdf打印机
我正在尝试在Visual Basic 2008中以编程方式将现有文件打印为PDF。
我们当前的相关资产是:
Visual Studio 2008专业版
Adobe Acrobat专业版8.0
我曾考虑过要使用像ITextSharp这样的sdk,但是对于我正在尝试做的事情似乎有些过头了,尤其是因为我们拥有完整版的Adobe。
是否有一些相对简单的代码可以打印到PDF打印机(当然还要将其分配给特定位置打印),还是需要使用另一个库才能打印到pdf?
我想将以前创建的文档打印为pdf文件。在这种情况下,它是一个我想制作为.pdf文件的.snp文件,但我认为任何文件类型的逻辑都相同。
我只是尝试了上面的shell执行,它不会按照我想要的方式执行。因为它会提示我要打印的位置,但仍然不打印我要打印的位置(多个位置),这一点至关重要,因为我们创建了很多相同名称的PDF文件(PDF中包含不同的数据,并放置在相应的客户端文件夹)
当前过程是:
- 转到\ report server \ client1
- 手动创建文件夹中所有snp文档的pdf文件
- 将pdf复制到\ website report \ client1
- 然后对所有100多个客户重复一次,大约需要两个小时才能完成并验证
我知道可以做得更好,但我来这里只有三个月,还有其他紧迫的问题要立即解决。我也没想到看起来如此琐碎的东西很难编写。
解决方案
我们要做的是找到一个不错的免费PDF打印机驱动程序。它们是作为打印机安装的,但不是将其打印到物理设备,而是将打印机命令呈现为PDF。然后,我们可以如上所述执行ShellExecute,也可以使用内置的.net PrintDocument,通过名称引用PDF"打印机"。我很快找到了几个免费的产品,包括Primo和BullZip的产品(自由限制为10个用户)。
看起来SNP文件是Microsoft Access快照。我们将必须寻找Access或者Snapshot Viewer的命令行界面,以便我们指定打印机目标。
我还看到SnapshotViewer下载中包含一个ActiveX控件。我们可以尝试在程序中使用它来加载snp文件,然后告诉它在哪里打印(如果它支持该功能)。
尝试将ShellExecute与Print Verb一起使用。
这是我在Google上找到的博客。
http://www.vbforums.com/showthread.php?t=508684
PDFforge提供PDFCreator。它将从任何能够打印的程序(甚至是现有程序)创建PDF。请注意,它基于GhostScript,因此可能不适合Acrobat许可证。
我们是否看过Adobe Distiller Server?我们可以使用任何打印机驱动程序生成PostScript文件,并将其转换为PDF。 (实际上,PDFCreator做类似的事情。)
如果我们尝试手动生成PDF(使用SDK和SDK或者PDF打印机驱动程序),则并非易事。可从Adobe获得PDF格式参考。
问题在于文件是ASCII码和表的混合,这些表在文件中具有到引用对象的二进制偏移量。这是一种有趣的格式,并且非常可扩展,但是很难编写一个简单的文件。
如果需要的话,这是可行的。我查看了Adobe PDF参考资料中的示例,然后手动键入它们并进行处理,直到我可以根据需要使它们工作为止。如果我们将大量执行此操作,那可能是值得的,否则请查看SDK。
这就是我在VBScript中所做的。可能对我们不是很有用,但可能会让我们入门。我们需要具有PDF制造商(adobe acrobat)作为名为" Adobe PDF"的打印机。
'PDF_WILDCARD = "*.pdf" 'PrnName = "Adobe PDF" Sub PrintToPDF(ReportName As String, TempPath As String, _ OutputName As String, OutputDir As String, _ Optional RPTOrientation As Integer = 1) Dim rpt As Report Dim NewFileName As String, TempFileName As String '--- Printer Set Up --- DoCmd.OpenReport ReportName, View:=acViewPreview, WindowMode:=acHidden Set rpt = Reports(ReportName) Set rpt.Printer = Application.Printers(PrnName) 'Set up orientation If RPTOrientation = 1 Then rpt.Printer.Orientation = acPRORPortrait Else rpt.Printer.Orientation = acPRORLandscape End If '--- Print --- 'Print (open) and close the actual report without saving changes DoCmd.OpenReport ReportName, View:=acViewNormal, WindowMode:=acHidden ' Wait until file is fully created Call waitForFile(TempPath, ReportName & PDF_EXT) 'DoCmd.Close acReport, ReportName, acSaveNo DoCmd.Close acReport, ReportName TempFileName = TempPath & ReportName & PDF_EXT 'default pdf file name NewFileName = OutputDir & OutputName & PDF_EXT 'new file name 'Trap errors caused by COM interface On Error GoTo Err_File FileCopy TempFileName, NewFileName 'Delete all PDFs in the TempPath '(which is why you should assign it to a pdf directory) On Error GoTo Err_File Kill TempPath & PDF_WILDCARD Exit_pdfTest: Set rpt = Nothing Exit Sub Err_File: ' Error-handling routine while copying file Select Case Err.Number ' Evaluate error number. Case 53, 70 ' "Permission denied" and "File Not Found" msgs ' Wait 3 seconds. Debug.Print "Error " & Err.Number & ": " & Err.Description & vbCr & "Please wait a few seconds and click OK", vbInformation, "Copy File Command" Call sleep(2, False) Resume Case Else MsgBox Err.Number & ": " & Err.Description Resume Exit_pdfTest End Select Resume End Sub Sub waitForFile(ByVal pathName As String, ByVal tempfile As String) With Application.FileSearch .NewSearch .LookIn = pathName .SearchSubFolders = True .filename = tempfile .MatchTextExactly = True '.FileType = msoFileTypeAllFiles End With Do While True With Application.FileSearch If .Execute() > 0 Then Exit Do End If End With Loop End Sub Public Sub sleep(seconds As Single, EventEnable As Boolean) On Error GoTo errSleep Dim oldTimer As Single oldTimer = Timer Do While (Timer - oldTimer) < seconds If EventEnable Then DoEvents Loop errSleep: Err.Clear End Sub
这里最大的要点是PDF很难。如果有什么可以避免直接创建或者编辑PDF文档的方法,强烈建议我们这样做。听起来我们真正想要的是批处理SNP至PDF转换器。我们可能可以使用现成的产品来执行此操作,甚至根本不需要打开Visual Studio。有人提到过Adobe Distiller Server-检查Acrobat文档,我知道它是基本的Distiller附带的,我们也许可以将Distiller设置为以类似的模式运行,在该模式下,它可以监视目录A并吐出所有文件的PDF版本显示在目录B中。
另一种选择:由于我们正在使用Access快照,因此最好编写一个VBA脚本,该脚本可遍历目录中的所有SNP并将它们打印到已安装的PDF打印机中。
预计到达时间:如果我们需要指定PDF打印机的输出,则可能会更难。我建议我们将PDF分配器配置为输出到临时目录,以便我们可以打印其中一个,移动结果,然后打印另一个,依此类推。
我在CASP.NET应用程序中遇到了类似的问题。我的解决方案是在命令行中使用一些生成的代码来启动LaTeX编译器。这不是一个简单的解决方案,但它会生成一些非常漂亮的.pdf。
最好的Java库是iText,但是从去年开始观看邮件列表并不是一件容易的事
我也遇到了同样的挑战。我提出的解决方案是购买一个名为PDFTron的组件。它具有一个API,可从无人值守服务将pdf文档发送到打印机。
我在博客中发布了一些有关此的信息。看一看!
如何以编程方式打印PDF文件???