【问题标题】:pdfbox wrap textpdfbox 自动换行
【发布时间】:2013-01-19 02:37:54
【问题描述】:

我正在使用带有以下代码的 PDFBox:

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();

有谁知道如何将文本换行以使其自动转到另一行?

【问题讨论】:

    标签: java text pdfbox


    【解决方案1】:

    我认为自动换行是不可能的。但是您可以自己包装文本。请参阅How to Insert a Linefeed with PDFBox drawStringHow can I create fixed-width paragraphs with PDFbox?

    【讨论】:

      【解决方案2】:

      这对我有用。 WordUtils和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(); 
      }
      

      【讨论】:

      • WordUtils 是从哪里来的?
      • @jrahhali 看起来像 org.apache.commons.text.WordUtils
      【解决方案3】:

      PdfBox 和 Boxable 都会自动换行比单元格宽度更长的文本部分,这意味着如果 单元格宽度 = 80 句子宽度 = 100 宽度为 20 的文本的剩余部分将从下一行开始 (注意:我提到了宽度(句子占用的实际空间)而不是长度(字符数))

      如果句子宽度 = 60, 将需要宽度为 20 的文本来填充单元格的宽度,之后的任何文本都将转到下一行 解决方案:用空格填充这个宽度 20

      单元格的未填充空间 = cellWidth - sentenceWidth, numberOfSpaces = 单元格的未填充空间/单个空间的宽度

          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);
      

      【讨论】:

        【解决方案4】:

        我在pdfBOX中找到了换行问题的解决方案

        一般来说,你需要三个步骤来换行你的文本:

        1) 将每个单词拆分成必须被包装的字符串,并将它们放入一个字符串数组中,例如字符串 [] 部分

        2) 使用 (textlength/(一行中的字符数)) 创建一个字符串缓冲区数组,例如280/70=5 >> 我们需要 5 个换行符!

        3) 将部分放入stringbuffer[i],直到达到一行最大字符数的限制,

        4) 循环直到 stringbuffer.length

        方法 splitString 是执行此操作的方法。 writeText 方法只是将包装后的文本绘制到 pdf 中

        这是一个例子

        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;
         } 
        
        } 
        

        【讨论】:

        • 对大多数字体使用每行字符数的限制似乎是不够的。相反,您可能希望限制 pdf 中绘制的线的实际长度。 This answer 可能会在这方面为您提供帮助
        猜你喜欢
        • 2017-11-23
        • 2019-01-17
        • 2011-11-27
        • 2015-08-22
        • 2015-09-13
        • 2015-11-30
        • 2014-06-01
        • 2012-02-26
        • 2012-04-30
        相关资源
        最近更新 更多