【问题标题】:Get absolute width from PdfPTable column (iText)从 PdfPTable 列(iText)获取绝对宽度
【发布时间】:2019-07-25 10:38:42
【问题描述】:

当用相对大小指定表格列时,如何从iText获取列的绝对宽度

我尝试了什么

我将 3 列的 相对宽度 指定为浮动,如下所示:

PdfPCell cell2;
PdfPTable table2 =  new PdfPTable(new float[]{(float) 4.5, (float) 0.5, 9});
table2.setWidthPercentage(100);

我得到了什么

我尝试使用table2.getAbsoluteWidths()[2],但结果是浮动0.0

我的预期

在 PDF 上动态计算表格宽度后,我想获得每一列的绝对宽度(已最大化)。

----------------------- 编辑 ----------

实际上我需要在添加文档之前有一列的宽度,然后替换我的硬编码浮点变量restriction

我有很多数据字符串,想在获得最大宽度页面时设置在另一列中,并在函数 restrictWidthOfFont

中进行拆分
String fullAlamatPP = "test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test ";

float restrictions = (float) 330.12103; // this is width of a column from table

String alamatSesuaiKtpPP[] = restrictWidthOfFont(fullAlamatPP, font_body, restrictions);

Phrase p_alamat1_ct = new Phrase(alamatSesuaiKtpPP[0], font_body);
p_alamat1_ct.add(dottedline);
cell2 = new PdfPCell(p_alamat1_ct);
cell2.setBorder(PdfPCell.NO_BORDER);
table2.addCell(cell2);

Phrase p_alamat2_ct = new Phrase(alamatSesuaiKtpPP[1], font_body);
p_alamat2_ct.add(dottedline);
cell2 = new PdfPCell(p_alamat2_ct);
cell2.setBorder(PdfPCell.NO_BORDER);
table2.addCell(cell2);    

private static String[] restrictWidthOfFont(String character, Font font, float restrictions) {
        String results[];
        results = new String[] {"",""};
        String concatChar = " ";
        float widthOfString = 0;
        for (int i = 0; i < character.length();i++) {
            concatChar += character.charAt(i); 
            widthOfString = font.getCalculatedBaseFont(true).getWidthPoint(concatChar, font.getCalculatedSize());
//                System.out.println("widthOfString " + widthOfString);
            if (widthOfString > restrictions) {
                results[0] = concatChar.substring(0, concatChar.length() - 1);
                results[1] = character.substring(i, character.length());
                break;
            }
        }

        if (results[0] == "") {
            results[0] = character;
        }
        return results;
}    

可能在添加表格文档之前获得一列的宽度?

【问题讨论】:

    标签: java itext column-width pdftables


    【解决方案1】:

    问题及说明

    函数table.getAbsoluteWidths()依赖于必须设置表的totalWidth的要求,因此table.getTotalWidth() &gt; 0

    这是因为在 com.itextpdf.text.pdf.PdfPTable 类内部调用了一个方法 calculateWidths(),然后计算所有列的绝对宽度:

    this.absoluteWidths[k] = this.totalWidth * this.relativeWidths[k] / total;
    

    解决方案

    为了确保 totalWidth 在您检索 relativeWidths 数组之前设置,您需要:

    • 任一(A) 设置totalWidth,如this answer 中所述
    • (B) 将单元格添加到表格并将表格添加到文档

    解决方案代码

    以下代码将您的算法结合到拆分文本(即长地址或alamat跨单元格基于的限制>一列的最大宽度

    import com.itextpdf.text.*;
    import com.itextpdf.text.pdf.*;
    
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.util.Arrays;
    
    public class TableWidthSample {
    
        public static void main(String[] args) {
            Document document = new Document();
            try {
                PdfWriter.getInstance(document, new FileOutputStream("TableColumnWidth.pdf"));
                document.open();
    
                PdfPTable table = createTableWithRelativeColumnWidths();
    
                // needed for calculation of getAbsoluteWidths: (A) totalWidth is set for table
                table.setTotalWidth(calculateTableWidthBasedOnPageA4(document, table));
                // now it prints width, because (A)
                printTableWidth(table, "after totalWidth set manually"); // absoluteWidths: [134.4857, 14.942857, 268.9714]
    
                // long text, that needs to be split among cells (fullAlamatPP)
                String text = "this is a very long text. The text contains a full address. Because the text is too long to be shown in the last cell, it is split.";
                // your CODE to fill text into cells based on restrictions
                addTextAcrossTableCells(table, text);
    
                document.add(table);
    
    /*
                // need to add filled table to doc (B)
                addToDocumentCellsAndTable(document, table);
                // now it prints width, because (B)
                printTableWidth(table, "after added to doc"); // absoluteWidths: [134.4857, 14.942857, 268.9714]
    */
                document.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (DocumentException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        private static PdfPTable createTableWithRelativeColumnWidths() {
            float[] relativeWidths = {4.5F, 0.5F, 9F};
            PdfPTable table = new PdfPTable(relativeWidths);
            table.setWidthPercentage(100F);
            printTableWidth(table, "after table created"); // absoluteWidths: [0.0, 0.0, 0.0]
            return table;
        }
    
        private static float calculateTableWidthBasedOnPageA4(Document document, PdfPTable table) {
            return (PageSize.A4.getWidth() - document.leftMargin() - document.rightMargin())
                    * table.getWidthPercentage() / 100;
        }
    
        private static void addToDocumentCellsAndTable(Document document, PdfPTable table) throws DocumentException {
            // needed for calculation of getAbsoluteWidths: (B.1) add cells to table
            table.addCell("Hello");
            table.addCell("World");
            table.addCell("!");
            printTableWidth(table, "after cells added to table"); // absoluteWidths: [0.0, 0.0, 0.0]
    
            // needed for calculation of getAbsoluteWidths: (B.2) add table to doc
            document.add(table);
        }
    
        private static void addTextAcrossTableCells(PdfPTable table, String text) throws IOException, DocumentException {
            // restrictions; this is width of a column from table
            float maxColumnWidth = table.getAbsoluteWidths()[2]; // 330.12103F;
            System.out.println("use width of third column as max: " + maxColumnWidth);
            // sample font used for calculation of text-width
            Font font = new Font(BaseFont.createFont("Courier", BaseFont.CP1250, true), 12);
    
            // alamatSesuaiKtpPP
            String splitText[] = getTextPartsUsingFontWithMaxWidth(text, font, maxColumnWidth);
            String dottedLine = "..";
            table.addCell("Alamat / Address:");
    
            // p_alamat1_ct
            Phrase phrase1 = new Phrase(splitText[0], font);
            phrase1.add(dottedLine);
            PdfPCell cell1 = new PdfPCell(phrase1);
            cell1.setBackgroundColor(BaseColor.LIGHT_GRAY);
            cell1.setBorder(PdfPCell.NO_BORDER);
            table.addCell(cell1);
    
            // p_alamat2_ct
            Phrase phrase2 = new Phrase(splitText[1], font);
            phrase2.add(dottedLine);
            PdfPCell cell2 = new PdfPCell(phrase2);
            cell2.setBorder(PdfPCell.NO_BORDER);
            table.addCell(cell2);
        }
    
        private static String[] getTextPartsUsingFontWithMaxWidth(String text, Font font, float maxWidth) {
            String results[] = new String[] {"",""};
            String firstPartOfText = " ";
            float widthOfText = 0;
            for (int i = 0; i < text.length();i++) {
                firstPartOfText += text.charAt(i);
                widthOfText = font.getCalculatedBaseFont(true).getWidthPoint(firstPartOfText, font.getCalculatedSize());
                System.out.printf("%d: widthOfText: %f\n", i, widthOfText);
                if (widthOfText > maxWidth) {
                    results[0] = firstPartOfText.substring(0, firstPartOfText.length() - 1);
                    results[1] = text.substring(i); // second argument "text.length()" is not needed
                    break;
                }
            }
    
            if (results[0] == "") {
                results[0] = text;
            }
            return results;
        }
    
        private static void printTableWidth(PdfPTable table, String labelText) {
            float[] absoluteWidths = table.getAbsoluteWidths();
            System.out.println(labelText + "> getAbsoluteWidths: " + Arrays.toString(absoluteWidths));
        }
    }
    

    另见

    How to make PdfPTable calculate column-width dynamically

    【讨论】:

    • 谢谢回答,但我可以在添加文档之前获得一列的宽度吗?
    • @FakhryanAlbar 是的,你可以。根据您的额外要求调整了我的解决方案。请让我知道它是否适合您。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 2014-08-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多