如何在循环中的单个或多个页面中添加多个文本字段

时间:2019-01-30 14:31:43

标签: spring-boot itext

我正在使用Itext 5 Maven,我想在多个pdf页面中添加多个文本字段。例如第1页需要3个字段,第2页需要4个字段,等等。

我写了以下代码

public byte[] setupDocument(EditPdfDTO editPdfDTOList, MultipartFile attachment)
{

    WritePDF obj = new WritePDF();

    Document document = null;
    PdfWriter writer = null;
    PdfImportedPage page = null;
    PdfReader reader = null;
    try
    {
        // Create output PDF
        document = new Document(PageSize.A4);
        document.setMargins(0, 0, 0, 0);

        writer = PdfWriter.getInstance(document,
                new FileOutputStream("D:/test.pdf"));

        document.open();
        PdfContentByte cb = writer.getDirectContent();

        // Load existing PDF
        reader = new PdfReader(attachment.getBytes());

        int totalPages = reader.getNumberOfPages();
        for (int i = 0; i < totalPages; i++)
        {
            page = writer.getImportedPage(reader, i + 1);
            document.newPage();
            cb.addTemplate(page, 0, 0);

            for (int j = 0; j < editPdfDTOList.getPdf().size(); j++)
            {
                if (i + 1 == editPdfDTOList.getPdf().get(j).getPageNo())
                {
                    BaseFont baseFont = null;
                    try
                    {
                        baseFont = BaseFont.createFont();
                    }
                    catch (DocumentException | IOException e1)
                    {
                        e1.printStackTrace();
                    }

                    int a, b;
                    a = editPdfDTOList.getPdf().get(j).getxCoordinate();
                    b = editPdfDTOList.getPdf().get(j).getyCoordinate();

                    String str = editPdfDTOList.getPdf().get(j).getTextContent();

                    Rectangle linkLocation =
                            new Rectangle(a, b + baseFont.getDescentPoint(str, 10),
                                    a + 10 + baseFont.getWidthPoint(str, 10),
                                    b + baseFont.getAscentPoint(str, 10) + 10);
                    TextField field =
                            new TextField(writer, linkLocation, "user1" + j+UUID.randomUUID());

                    field.setFontSize(10);
                    field.setOptions(TextField.MULTILINE | TextField.READ_ONLY);
                    field.setTextColor(BaseColor.RED);
                    field.setText(str);
                    field.setBorderWidth(1);

                    cb = writer.getDirectContent();

                    try
                    {
                        cb.addAnnotation(field.getTextField(),false);
                    }
                    catch (IOException | DocumentException e)
                    {
                         e.printStackTrace();           
                    }

                }
            }
        }
    }
    catch (DocumentException | IOException e)
    {
        e.printStackTrace();
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }
    finally
    {
        document.close();

    }
    return null;
}

此代码只能在每个预期的对象上添加一个Textfield,但不能在单个页面中添加2个或多个Textfield。

没有多个try-catch块的问题。

1 个答案:

答案 0 :(得分:3)

要使用的适当类

首先,您说“要在多个pdf页面中添加多个文本字段” 。当执行这样的任务时,即仅使用一个文档并想要以某种方式操纵它,同时又在结构上保持或多或少保持不变的任务时,通常应该一对PdfReader / PdfStamper一起工作。这使您可以专注于操作,并提供原始PDF及其所有属性的副本。

在现有PDF页面上添加多个字段

在单个现有页面上添加多个字段很简单,例如:

PdfReader pdfReader = new PdfReader(resource);
PdfStamper pdfStamper = new PdfStamper(pdfReader, output);

TextField field1 = new TextField(pdfStamper.getWriter(),
                                 new Rectangle(100, 800, 200, 820), "Field1");
field1.setBorderColor(BaseColor.CYAN);
field1.setBorderStyle(PdfBorderDictionary.STYLE_DASHED);
field1.setBorderWidth(BaseField.BORDER_WIDTH_MEDIUM);
field1.setText("Field 1");
pdfStamper.addAnnotation(field1.getTextField(), 1);

TextField field2 = new TextField(pdfStamper.getWriter(),
                                 new Rectangle(300, 800, 400, 820), "Field2");
field2.setBorderColor(BaseColor.RED);
field2.setBorderStyle(PdfBorderDictionary.STYLE_INSET);
field2.setBorderWidth(BaseField.BORDER_WIDTH_THIN);
field2.setText("Field 2");
pdfStamper.addAnnotation(field2.getTextField(), 1);

pdfStamper.close();

AddField测试testAddMultipleFields

应用于我的示例文档

screen shot original

代码生成

screen shot result

因此,将多个文本字段添加到同一文档页面没有任何概念上的问题,它的工作方式非常自然。

在您的情况下,我将改用PdfReader / PdfStamper对。如果仍然存在问题,我将检查您的数据。大概它们每页仅包含一个字段数据集。或两个文本字段具有相同的坐标,因此看起来像一个。或某些文本字段具有屏幕外坐标。或者...或者...或者...

原始答案

最初,问题中的代码看起来有所不同。最初的答案集中在该代码的问题上。

您声明了密码

  

只能在每个预期的字段上添加一个文本框,但不能在单个页面中添加2个或多个文本框。

我怀疑是因为

  1. 您有两个不同的对象同时"D:/TemplateFilePDf/" + attachment.getOriginalFilename()PdfWriter writer同时写入同一文件PdfStamper stamper。如果您因代码而得到了一些明智的选择,那么只能靠运气了。和

  2. 另外,为stamper的{​​{1}}实例实例化了{li>

    null。实际上,这将在构造函数中导致PdfReader,这将使您添加文本的文本域根本无法执行。

因此,您共享的代码与您运行的代码有很大的不同,或者您的测试运行实际上都抛出了NullPointerException,您可能会发现以前的,破坏程度较小的代码的输出仅添加了一个文本字段。

在解决了这两个问题之后,仍然存在一些问题(例如,NullPointerException的意图是什么?仅在路径定义之后才允许使用该指令,该路径的内部区域要填充,但是我不愿意)看不到您定义任何路径。

此外,您访问cb.fill()可获得许多相关值,但我们不知道这些值。因此,我们无法运行您的代码来尝试重现该问题。可能您仅创建了一个文本字段,因为该对象仅包含单个文本字段的值...