如何使用iTextSharp消除多列中的空白?

时间:2015-03-31 20:56:11

标签: itextsharp itext

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

但是我总是最终得到:

  1. 左栏中孤立的一大段文字。
  2. 完整的左列和部分使用的右列。
  3. 如何在减少空格的同时将我的内容格式化为2列,例如压缩列,以便以2个相等长度的完整列结束?

    谢谢!

1 个答案:

答案 0 :(得分:1)

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

我已经调整了ColumnTextParagraphs示例以显示模拟模式的含义。看看ColumnTextParagraphs2示例:

enter image description here

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

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

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

请注意,我们使用ERROR_MARGIN,因为除以2通常会导致第二列比第一列多一行。反之亦然。

这是您要求的完整示例:

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