动态创建新页面时出现PDFBox问题

时间:2017-03-13 15:33:14

标签: java pdfbox

考虑一个SQL查询,其结果将写入pdf。

我可以在pdf中成功编写内容(从查询中检索)但如果内容超过一页的最大限制,它会截断内容。这意味着,只创建了一个页面。

在写入pdf(通过PDFBox)时,如何知道我们已经到达页面的末尾,这样一旦我们动态地知道我们到达了结束点,我们就可以触发doc.addPage(page);页。

以下是代码:

public PDDocument processPdf(Class1 objectClass1) {
    String text;
    int count;
    //New Document is created
    PDDocument doc = new PDDocument();
    List<Class1Questions> objectClass1Questions;
    Class2 objectClass2;
    try {
        float fontSize = 12;
        float margin = 72;
        float leading = 1.5f * fontSize;
        PDFont font = PDType1Font.HELVETICA;
        PDPage page = new PDPage();
        page.setMediaBox(PDRectangle.A4);
        PDRectangle pageSize = page.getMediaBox();
        float startX = pageSize.getLowerLeftX() + margin;
        float startY = pageSize.getUpperRightY() - margin;
        //First page is added
        doc.addPage(page);
        List<String> lines;
        PDPageContentStream contentStream = new PDPageContentStream(doc, page);
        contentStream.setFont(font, fontSize);
        contentStream.beginText();
        //The resultset gets collected and written in PDF.
        text = objectClass1.getClass1Name();
        lines = spacing(text, margin, font, pageSize);
        contentStream.newLineAtOffset(startX, startY);
        contentStream.showText("Class1: ");
        for (String line : lines) {
            contentStream.showText(line);
            contentStream.newLineAtOffset(0, -leading);
        }
        List<Class1Version> versionList = objectClass1.getClass1Versions();
        for (Class1Version version : versionList) {

            String versionNum = Long.toString(version.getClass1VersionNumber());
            contentStream.showText("Version: " + versionNum);

            contentStream.newLineAtOffset(0, -leading);
            objectClass1Questions = version.getClass1Questions();
            count = 0;
            for (Class1Questions objectClass1Question : objectClass1Questions) {
                count++;
                objectClass2 = objectClass1Question.getQuestion();
                String question = objectClass2.getQuestionDesc();
                lines = spacing(question, margin, font, pageSize);
                contentStream.showText("Q" + count + ": ");
                for (String line : lines) {
                    contentStream.showText(line);
                    contentStream.newLineAtOffset(0, -leading);
                }
                contentStream.newLineAtOffset(0, -leading);
            }
        }
        contentStream.endText();
        contentStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return doc;
    }

    public List<String> spacing (String text, float margin, PDFont font, PDRectangle pageSize) throws IOException {
    int lastSpace = -1;
    List<String> lines = new ArrayList<String>();
    float fontSize = 25;
    float width = pageSize.getWidth() - 2*margin;

    while (text.length() > 0)
    {
        int spaceIndex = text.indexOf(' ', lastSpace + 1);
        if (spaceIndex < 0)
            spaceIndex = text.length();
        String subString = text.substring(0, spaceIndex);
        float size = fontSize * font.getStringWidth(subString) / 1000;
        System.out.printf("'%s' - %f of %f\n", subString, size, width);
        if (size > width)
        {
            if (lastSpace < 0)
                lastSpace = spaceIndex;
            subString = text.substring(0, lastSpace);
            lines.add(subString);
            text = text.substring(lastSpace).trim();
            System.out.printf("'%s' is line\n", subString);
            lastSpace = -1;
        }
        else if (spaceIndex == text.length())
        {
            lines.add(text);
            System.out.printf("'%s' is line\n", text);
            text = "";
        }
        else
        {
            lastSpace = spaceIndex;
        }
    }
    return lines;
}

2 个答案:

答案 0 :(得分:1)

声明totalHeight变量,将其设置为边距高度;

float totalHeight = margin;

获取如下字体高度:

float fontHeight = font.getFontDescriptor().getFontBoundingBox()
            .getHeight()
            / 1000 * fontSize;

但它不会返回确切的高度,你可以用它来获得更好的结果。 然后获得a4页面大小:

float a4Height= PDRectangle.A4.getHeight();

每当你输入一个新行增加总高度并检查它是否超过a4Height考虑边际高度

totalHeight += fontHeight;
if(totalHeight+margin>=a4Height){
    page = new PDPage();
    doc.addPage(page);
    totalHeight = margin;
}

答案 1 :(得分:1)

我试图采用@AhmetRasitBekar给出的解决方案和@mkl评论中提到的解决方案。

  1. 引入一个变量,在其中记下当前的y坐标, 将它设置为startY。将变量视为yCordinate
  2. 计算字体高度

    float fontHeight = font.getFontDescriptor().getFontBoundingBox().getHeight() / 1000 * fontSize;

  3. 每次将文本内容写入pdf文件时,变量 yCordinate将减少fontHeight

    contentStream.showText(line); yCordinate -= fontHeight;

  4. 每次添加新行时,yCordinate都会减少 leading

  5. contentStream.newLineAtOffset(0, -leading); yCordinate -= leading;

    1. 每次访问和更改yCordinate时,都会有条件 编写语句以检查是否yCordinate <= 10。如果 是的,然后是下面的代码。
    2. if(yCordinate <= 10){
           page = new PDPage();  //new page created
           page.setMediaBox(PDRectangle.A4);
           pageSize = page.getMediaBox();
           startX = pageSize.getLowerLeftX() + margin;  //Calculate the X and Y cordinate
           startY = pageSize.getUpperRightY() - margin;
           doc.addPage(page);  //Add the page to the PDDocument
           yCordinate = startY;   //Reset the yCordinate with the new Y cordinate
           contentStream.endText();  //End and Close the previous contentStream
           contentStream.close();
           contentStream = new PDPageContentStream(doc, page);  //Create a new contentStream and use it further
           contentStream.setFont(font, fontSize);
           contentStream.beginText();
           contentStream.newLineAtOffset(startX, startY);
       }
      

      如果内容超出PDF页面限制,这将动态创建pdf中的页面。