【问题标题】:How can you eliminate white-space in multiple columns using iTextSharp?如何使用 iTextSharp 消除多列中的空白?
【发布时间】:2015-03-31 20:56:11
【问题描述】:

我想在 2 列的页面中添加一段文本。我了解MultiColumnText 已被淘汰。我知道我可以创建第 1 列并写入它,如果有更多文本创建第 2 列并写入它。如果还有更多文字,请转到下一页并重复。

但我总是以以下任一方式结束:

  1. 左列中孤立的一大段文本。
  2. 完整的左列和部分使用的右列。

如何在减少空白的同时将我的内容格式化为 2 列,例如压缩列以便以 2 个等长的完整列结束?

谢谢!

【问题讨论】:

    标签: itextsharp itext


    【解决方案1】:

    您应该添加您的列两次,一次是在模拟模式下,一次是在真实模式下。

    我已经修改了ColumnTextParagraphs 示例来说明模拟模式的含义。看看ColumnTextParagraphs2 的例子:

    我们在模拟模式下添加柱子以获得柱子所需的总高度。这是通过以下方法完成的:

    public float getNecessaryHeight(ColumnText ct) throws DocumentException {
        ct.setSimpleColumn(new Rectangle(0, 0, COLUMN_WIDTH, -500000));
        ct.go(true);
        return -ct.getYLine();
    }
    

    我们在添加左右列时使用这个高度:

    Rectangle left;
    float top = COLUMNS[0].getTop();
    float middle = (COLUMNS[0].getLeft() + COLUMNS[1].getRight()) / 2;
    float columnheight;
    int status = ColumnText.START_COLUMN;
    while (ColumnText.hasMoreText(status)) {
        if (checkHeight(height)) {
            columnheight = COLUMNS[0].getHeight();
            left = COLUMNS[0];
        }
        else {
            columnheight = (height / 2) + ERROR_MARGIN;
            left = new Rectangle(
                COLUMNS[0].getLeft(),
                COLUMNS[0].getTop() - columnheight,
                COLUMNS[0].getRight(),
                COLUMNS[0].getTop()
            );
        }
        // left half
        ct.setSimpleColumn(left);
        ct.go();
        height -= COLUMNS[0].getTop() - ct.getYLine();
        // separator
        canvas.moveTo(middle, top - columnheight);
        canvas.lineTo(middle, top);
        canvas.stroke();
        // right half
        ct.setSimpleColumn(COLUMNS[1]);
        status = ct.go();
        height -= COLUMNS[1].getTop() - ct.getYLine();
        // new page
        document.newPage();
    }
    

    这是我们检查高度的方式:

    public boolean checkHeight(float height) {
        height -= COLUMNS[0].getHeight() + COLUMNS[1].getHeight() + ERROR_MARGIN;
        return height > 0;
    }
    

    如您所见,只要两列的高度小于剩余高度,我们就会添加整列。添加列时,我们调整剩余高度。一旦高度低于 to 列的高度,我们就会调整第一列的高度。

    请注意,我们使用ERROR_MARGIN,因为除以二通常会导致第二列比第一列多一行的情况。反之则更好。

    这是应您要求的完整示例:

    /**
     * Example written by Bruno Lowagie in answer to:
     * http://stackoverflow.com/questions/29378407/how-can-you-eliminate-white-space-in-multiple-columns-using-itextsharp
     */
    package sandbox.objects;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    import com.itextpdf.text.Document;
    import com.itextpdf.text.DocumentException;
    import com.itextpdf.text.Paragraph;
    import com.itextpdf.text.Rectangle;
    import com.itextpdf.text.pdf.ColumnText;
    import com.itextpdf.text.pdf.PdfContentByte;
    import com.itextpdf.text.pdf.PdfWriter;
    
    public class ColumnTextParagraphs2 {
    
        public static final String DEST = "results/objects/column_paragraphs2.pdf";
    
        public static final String TEXT = "This is some long paragraph that will be added over and over again to prove a point.";
        public static final float COLUMN_WIDTH = 254;
        public static final float ERROR_MARGIN = 16;
        public static final Rectangle[] COLUMNS = {
            new Rectangle(36, 36, 36 + COLUMN_WIDTH, 806),
            new Rectangle(305, 36, 305 + COLUMN_WIDTH, 806)
        };
    
        public static void main(String[] args) throws IOException, DocumentException {
            File file = new File(DEST);
            file.getParentFile().mkdirs();
            new ColumnTextParagraphs2().createPdf(DEST);
        }
    
        public void createPdf(String dest) throws IOException, DocumentException {
            // step 1
            Document document = new Document();
            // step 2
            PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(dest));
            // step 3
            document.open();
            // step 4
            PdfContentByte canvas = writer.getDirectContent();
            ColumnText ct = new ColumnText(canvas);
            addContent(ct);
            float height = getNecessaryHeight(ct);
            addContent(ct);
            Rectangle left;
            float top = COLUMNS[0].getTop();
            float middle = (COLUMNS[0].getLeft() + COLUMNS[1].getRight()) / 2;
            float columnheight;
            int status = ColumnText.START_COLUMN;
            while (ColumnText.hasMoreText(status)) {
                if (checkHeight(height)) {
                    columnheight = COLUMNS[0].getHeight();
                    left = COLUMNS[0];
                }
                else {
                    columnheight = (height / 2) + ERROR_MARGIN;
                    left = new Rectangle(
                        COLUMNS[0].getLeft(),
                        COLUMNS[0].getTop() - columnheight,
                        COLUMNS[0].getRight(),
                        COLUMNS[0].getTop()
                    );
               }
                // left half
                ct.setSimpleColumn(left);
                ct.go();
                height -= COLUMNS[0].getTop() - ct.getYLine();
                // separator
                canvas.moveTo(middle, top - columnheight);
                canvas.lineTo(middle, top);
                canvas.stroke();
                // right half
                ct.setSimpleColumn(COLUMNS[1]);
                status = ct.go();
                height -= COLUMNS[1].getTop() - ct.getYLine();
                // new page
                document.newPage();
            }
            // step 5
            document.close();
        }
    
        public void addContent(ColumnText ct) {
            for (int i = 0; i < 35; i++) {
                ct.addElement(new Paragraph(String.format("Paragraph %s: %s", i, TEXT)));
            }
        }
    
        public float getNecessaryHeight(ColumnText ct) throws DocumentException {
            ct.setSimpleColumn(new Rectangle(0, 0, COLUMN_WIDTH, -500000));
            ct.go(true);
            return -ct.getYLine();
        }
    
        public boolean checkHeight(float height) {
            height -= COLUMNS[0].getHeight() + COLUMNS[1].getHeight() + ERROR_MARGIN;
            return height > 0;
        }
    }
    

    【讨论】:

    • 我无法打开您提供的链接,所以我不确定 getHeight() 方法会做什么。我的 cmets 将是: 1)这假设列的顶部总是在相同的位置。如果列需要从第一页的一半开始怎么办? 2)看起来你每次迭代都会开始一个新页面。这仍然会留下空白,假设最后一页上的列是否只有 1 英寸高。
    • 我刚刚检查了链接。他们为我工作。创建完整示例所需的所有 sn-ps 都在答案中,但无论如何我都会复制粘贴完整的代码。 getHeight() 方法获取Rectangle 的高度,例如COLUMN[0]
    • 问题 1 无关紧要。您可以任意定义COLUMN[0]COLUMN[1]。问题2很奇怪:当你有一系列A4页面时,你是否想要一个页面突然变小很多的情况?这很奇怪,但并非不可能:因为您知道height,您可以在触发新页面之前检查剩余高度并更改页面大小。
    • 问题 1 并非无关紧要。看起来定义 COLUMN 的坐标永远不会改变。因此,如果列碰巧从第 N 页的中间开始,它们将在随后的每一页上从相同的位置开始。在转到下一页之前,您应该将 URy 坐标更改为文档的顶部。问题2并不奇怪。看起来当您的方法结束时,它总是转到下一页。假设最后你得到 2 列只有 2 英寸高。你不希望页面的其余部分是空白的,然后内容在下一页继续。
    • 愚人节是昨天。我给你写了一个概念证明,因为我想帮助你。如果您想取笑它,请继续,但不要指望任何进一步的帮助。
    猜你喜欢
    • 2023-03-15
    • 2018-02-21
    • 1970-01-01
    • 2011-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多