以编程方式打印到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文件???

