-->

pdfbox wrap text

2019-04-04 07:26发布

问题:

I am using PDFBox wit hthe following code:

doc = new PDDocument();
page = new PDPage();

doc.addPage(page);
PDFont font = PDType1Font.COURIER;

pdftitle = new PDPageContentStream(doc, page);
pdftitle.beginText();
pdftitle.setFont( font, 12 );
pdftitle.moveTextPositionByAmount( 40, 740 );
pdftitle.drawString("Here I insert a lot of text");
pdftitle.endText();
pdftitle.close();

Does anyone know how I can wrap the text so that it automatically goes to another line? Thanks a lot!

回答1:

I don´t think it is possible to wrap text automatically. But you can wrap your text yourself. See How to Insert a Linefeed with PDFBox drawString and How can I create fix-width paragraph with PDFbox



回答2:

This worked for me. A combination of WordUtils and split

String[] wrT = null;
String s = null;
text = "Job Description: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque hendrerit lectus nec ipsum gravida placerat. Fusce eu erat orci. Nunc eget augue neque. Fusce arcu risus, pulvinar eu blandit ac, congue non tellus. Sed eu neque vitae dui placerat ultricies vel vitae mi. Vivamus vulputate nullam.";
wrT = WordUtils.wrap(text, 100).split("\\r?\\n");

for (int i=0; i< wrT.length; i++) {
    contents.beginText();
    contents.setFont(PDType1Font.HELVETICA, 10);
    contents.newLineAtOffset(50,600-i*15);
    s = wrT[i];
    contents.showText(s);
    contents.endText(); 
}


回答3:

I found a solution for the linebreak problem in pdfBOX

In general, you need three steps to wrap your text:

1) split each word in string that has to be wrapped and put them into an array of string, e.g. String [] parts

2) create an array of stringbuffer with (textlength/(number of characters in a line)), e.g. 280/70=5 >> we need 5 linebreaks!

3) put the parts into the stringbuffer[i], until the limit of maximum number of characters in a line is allowed,

4) loop until stringbuffer.length < linebreaks

the method splitString is the method which does it. The method writeText just draws the wrapped text to the pdf

Here is an example

import java.io.IOException;
import java.util.ArrayList;

import org.apache.pdfbox.exceptions.COSVisitorException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.edit.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType1Font;

public class pdfTest{
 private ArrayList<String> arrayList;
 private PDDocument document;
 private PDFont font = PDType1Font.HELVETICA;

 pdfTest(PDDocument document, ArrayList arrayList, PDFont font) throws COSVisitorException, IOException {
    this.document = document;
    this.arrayList = arrayList;
    this.font = font;   
    writeText(document, arrayList, 30, 750, font); //method for easily drawing a text into a pdf
 } //constructor


 public void writeText(PDDocument document, ArrayList arrayList, int positionX, int positionY, PDFont font) throws IOException, COSVisitorException {
     PDPage page = new PDPage();
     document.addPage( page );

     // Start a new content stream
     PDPageContentStream contentStream = new PDPageContentStream(document, page);

     // Define a text content stream using the selected font, moving the cursor and drawing the text in arrayList
     for(int i=0;i<arrayList.size();i++) {  
         String text=(String) arrayList.get(i);
         String [] tmpText = splitString(text);
         for( int k=0;k<tmpText.length;k++) {
             contentStream.beginText();
             contentStream.setFont(font, 12);
             contentStream.moveTextPositionByAmount(positionX, positionY);
             contentStream.drawString(tmpText[k]);           
             contentStream.endText();
             positionY=positionY-20;
         }           
         contentStream.setLineWidth((float) 0.25);
     }

     // Make sure that the content stream is closed:
     contentStream.close();      
     document.save( "Test.pdf");
     document.close();
 } //main

 public static void main(String[] args) throws COSVisitorException, IOException {
     ArrayList arrayList = new ArrayList<String>();

     PDDocument document = new PDDocument();
     PDFont font = PDType1Font.HELVETICA;
     PDPage page = new PDPage();

     arrayList.add(       "12345 56789 0 aaa bbbew wel kwäer kweork merkweporkm roer wer wer e  er"
                        + "df sdmfkl  slkdfm sdkfdof sopdkfp osdkfo sädölf söldm,f sdkfpoekr re, ä"
                        + " sdfk msdlkfmsdlk fsdlkfnsdlk fnlkdn flksdnfkl sdnlkfn kln df sdmfn sn END");
     arrayList.add("this is an example");
     arrayList.add("java pdfbox stackoverflow");         

     new pdfTest(document,arrayList,font);
     System.out.println("pdf created!");
 }

 public String [] splitString(String text) {
     /* pdfBox doesnt support linebreaks. Therefore, following steps are requierd to automatically put linebreaks in the pdf
      * 1) split each word in string that has to be linefeded and put them into an array of string, e.g. String [] parts
      * 2) create an array of stringbuffer with (textlength/(number of characters in a line)), e.g. 280/70=5 >> we need 5 linebreaks!
      * 3) put the parts into the stringbuffer[i], until the limit of maximum number of characters in a line is allowed,
      * 4) loop until stringbuffer.length < linebreaks
      * 
      */
     int linebreaks=text.length()/80; //how many linebreaks do I need?  
     String [] newText = new String[linebreaks+1];       
     String tmpText = text;
     String [] parts = tmpText.split(" "); //save each word into an array-element

     //split each word in String into a an array of String text. 
     StringBuffer [] stringBuffer = new StringBuffer[linebreaks+1]; //StringBuffer is necessary because of manipulating text
     int i=0; //initialize counter 
     int totalTextLength=0;
     for(int k=0; k<linebreaks+1;k++) {
         stringBuffer[k] = new StringBuffer();
         while(true) {               
             if (i>=parts.length) break; //avoid NullPointerException
             totalTextLength=totalTextLength+parts[i].length(); //count each word in String              
             if (totalTextLength>80) break; //put each word in a stringbuffer until string length is >80
             stringBuffer[k].append(parts[i]);
             stringBuffer[k].append(" ");
             i++;
         }
         //reset counter, save linebreaked text into the array, finally convert it to a string 
         totalTextLength=0; 
         newText[k] = stringBuffer[k].toString();
     }
     return newText;
 } 

} 


回答4:

PdfBox and Boxable both auto wraps the the part of text longer than the cell width, so that means if cell width = 80 sentence width = 100 the remaining portion of the text of width 20 will start from next line (NOTE : I have mentioned width(actual space consumed by the sentence) and not length(no. of characters))

If sentence width = 60, text of width 20 will be required to fill the cell's width, and any text after that will go to the next line Solution : fill this width 20 with spaces

cell's Unfilled Space = cellWidth - sentenceWidth, numberOfSpaces = cell's Unfilled Space / width of a single Space

    private String autoWrappedHeaderText(String text, float cellWidth) {
    List<String> splitStrings = Arrays.asList(text.split("\n"));
    String wholeString = "";
    for (String sentence : splitStrings) {
        float sentenceWidth = FontUtils.getStringWidth(headerCellTemplate.getFont(), " " + sentence + " ",
                headerCellTemplate.getFontSize());
        if (sentenceWidth < cellWidth) {
            float spaceWidth = FontUtils.getStringWidth(headerCellTemplate.getFont(), " ",
                    headerCellTemplate.getFontSize());
            int numberOfSpacesReq = (int) ((cellWidth - sentenceWidth) / spaceWidth);
            wholeString += sentence;
            for (int counter = 0; counter < numberOfSpacesReq; counter++) {
                wholeString += " ";
            }
        }
    }

    return wholeString;
}
cell = headerRow.createCell(cellWidth * 100 / table.getWidth(), headerText, HorizontalAlignment.LEFT, VerticalAlignment.TOP);