2011-04-28 69 views
7

我正在寫一個Java程序,打印賓果卡的PDF文件。每頁是一張卡。爲了讓我更容易,我創建了一個帶有acrofields的模板PDF文件,這樣程序只需要創建一個該模板的副本,用數字填充ac場,然後將其平坦化。截至目前,我可以創建1賓果卡。我想在一個PDF文件中有多個頁面(因此,多張卡片)。但我不知道如何做到這一點。我讀到的是一個PDFStamper關聯到一個且只有一個PDFReader對象。有沒有一種方法,我可以做到這一點,而不訴諸創建多個PDF文件並將它們合併爲一個(我最後一次這樣做,我發現真的很慢)先謝謝了!Itext - 如何使用acrofields克隆頁面?

回答

13

花了我一會兒才弄明白這一點。這不是最有效的方法的代碼,但這裏的本質是什麼呢:

  • 創建文檔
  • 爲每個頁面(S)與acrofield:
  • 複製模板
  • 填寫表格
  • 扁平化的形式
  • 添加頁面

這裏是我的實現你可以嘗試和修改,以適應您的需求:

private void createPdf() throws Exception { 
    Document doc = new Document(); 
    PdfSmartCopy copy = new PdfSmartCopy(doc, new FileOutputStream("result.pdf")); 
    doc.open(); 

    PdfReader reader; 
    PdfStamper stamper; 
    AcroFields form; 
    ByteArrayOutputStream baos; 

    for(int i = 0; i < getTotalPages(); i++) { 
     copyPdf(i); 

     reader = new PdfReader(String.format("%d%s", i, "template.pdf")); 
     baos = new ByteArrayOutputStream(); 
     stamper = new PdfStamper(reader, baos); 
     form = stamper.getAcroFields(); 
     //methods to fill forms 

     stamper.setFormFlattening(true); 
     stamper.close(); 

     reader = new PdfReader(baos.toByteArray()); 
     copy.addPage(copy.getImportedPage(reader, 1)); 
    } 

    doc.close(); 
} 

private void copyPdf(int currentPage) throws Exception { 
    PdfReader reader = new PdfReader("timesheet.pdf"); 
    Document doc = new Document(); 
    File file = new File(String.format("%d%s", currentPage, "template.pdf")); 
    file.deleteOnExit(); 
    PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(file)); 
    stamper.close(); 
} 

的copyPdf()方法創建用來允許填寫表格,而不會影響整個文檔的臨時文件。如果你找到一個更有效的方法來做到這一點,讓我知道。

此外,我發現在基於Intel的Mac和Windows計算機上,Mac可以更快地完成此操作。

如果您不反對獲取iText參考書,我會推薦Bruno Lowagie的「iText in Action,第二版」。這是一本很棒的書,非常有幫助。

+0

+1書建議 – oers 2011-04-28 12:08:49

+0

+1正是我所需要的!謝謝!只需注意,copyPdf中的'doc'不會被使用:) – Jairo 2011-04-28 16:51:18

+3

您根本不需要'copyPdf()'。即使你這樣做了,從A到B複製一個文件(這恰好是PDF)的方式是非常低效的方式。你甚至可以爲'PdfStamper'的所有不同實例使用相同的'PdfReader',但這很可能會揭示Bug。你會*在相同的文件上使用多個閱讀器當然會很好。 – 2011-04-28 19:17:40

1

所以,這裏的代碼,而無需使用扎克的「copyPdf」的方法,如馬克斯托勒和MaxArt建議:

private void createPdf() throws Exception { 
    Document doc = new Document(); 
    PdfSmartCopy copy = new PdfSmartCopy(doc, new FileOutputStream("result.pdf")); 
    doc.open(); 

    PdfReader mainReader = new PdfReader("timesheet.pdf"); 

    PdfReader reader; 
    PdfStamper stamper; 
    AcroFields form; 
    ByteArrayOutputStream baos; 

    for(int i = 0; i < getTotalPages(); i++) { 

     reader = new PdfReader(mainReader); 
     baos = new ByteArrayOutputStream(); 
     stamper = new PdfStamper(reader, baos); 
     AcroFields form = stamper.getAcroFields(); 

     //methods to fill forms 

     stamper.setFormFlattening(true); 
     stamper.close(); 

     reader = new PdfReader(baos.toByteArray()); 
     copy.addPage(copy.getImportedPage(reader, 1)); 
    } 

    doc.close(); 
}