我正在寻找一种方法来拆分宽表,以便它们跨越多个页面。目标是使具有大量列的表可读。我发现了一个discussion thread where this topic is covered;但是,那里引用的示例不可用。 Manning的“iText in Action”(2006)并未涵盖此主题。
这可以在版本1.4.8中完成,如果没有,我应该升级到哪个版本的iText?
答案 0 :(得分:2)
请查看chapter 4 of my book的示例,更具体地说,请参阅Zhang示例。在这个例子中,我有一个包含四列的表:(1)年份,(2)英文电影片名,(3)中文电影片名,以及(4)游程长度。如果查看生成的PDF,您将看到此表是垂直分割的。
实现这一点需要更多的工作,然后只需添加一个表并允许iText决定如何在行之间拆分它。如果要在列之间拆分,则需要在代码中组织布局。这是使用writeSelectedRows()
)方法完成的。
在我的简单书籍示例中,我使用以下几行:
// draw the first two columns on one page
table.writeSelectedRows(0, 2, 0, -1, 236, 806, canvas);
document.newPage();
// draw the remaining two columns on the next page
table.writeSelectedRows(2, -1, 0, -1, 36, 806, canvas);
首先,我将索引0的列绘制到索引2.索引为0的列是第一列,索引为2的列是未包含的第一列,即第三列。我从索引0(第一行)绘制行直到-1。减去一个意味着:绘制所有剩余的行。
你还会在下一页看到减号,在那里我用索引2(第三列)绘制列,直到索引为-1的列(意思是:其余列)。
值(236,806)和(36,806)是坐标:这是您希望表开始的位置。您无法定义“结束坐标”。如果表格不适合页面,iText将继续绘制表格,即使这意味着某些内容超出了页面的可见区域。这意味着在使用此方法时您必须非常小心:在添加表之前,您需要计算行和列的宽度和高度,否则您可能会得到表中不可见的部分。
答案 1 :(得分:1)
这是一个类的source code,当您的列不适合单个页面时,会将您的表格拆分为多个页面
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfPTable;
import com.lowagie.text.pdf.PdfWriter;
/**
* Class that writes a <code>PdfPTable</code>, and spans it across multiple
* pages if the columns won't fit on one page
*/
public class PdfPTableWriter {
// Instance variables
private PdfPTable table;
private PdfWriter writer;
private Document document;
// List of how many columns per horizontal page
private List numberOfColumnsPerPage;
// List of how many rows per vertical page
private List numberOfRowsPerPage;
// Offsets if given
private float widthOffset = 20;
private float heightOffset = 70;
/**
* Class Constructor
*/
public PdfPTableWriter(Document document, PdfWriter writer, PdfPTable table) {
this.document = document;
this.writer = writer;
this.table = table;
calculateColumns();
calculateRows();
}
/**
* Writes the table to the document
*/
public void writeTable() throws DocumentException {
// Begin at row 1 (row after the header)
int rowBegin = 1;
int rowEnd = 0;
// Note the size of numberOfRowsPerPage is how many vertical
// pages there are.
Iterator rowsIter = numberOfRowsPerPage.iterator();
while (rowsIter.hasNext()) {
rowEnd = ((Integer) rowsIter.next()).intValue();
writeSelectedRows(rowBegin, rowEnd);
rowBegin = rowEnd;
}
}
/**
* Prints the Report's columns (splitting horizontally if necessary) and
* subsequent rows
*
* @param rowBegin
* @param rowEnd
* @throws DocumentException
*/
private void writeSelectedRows(int rowBegin, int rowEnd) throws DocumentException {
int colBegin = 0;
int colEnd = 0;
float pageHeight = document.getPageSize().getHeight() - heightOffset;
PdfContentByte contentByte = writer.getDirectContent();
Iterator columnsIter = numberOfColumnsPerPage.iterator();
while (columnsIter.hasNext()) {
colEnd = colBegin + ((Integer) columnsIter.next()).intValue();
// Writer table header
writeSelectedRows(colBegin, colEnd, 0, 1, widthOffset, pageHeight);
// Writes selected rows to the document
writeSelectedRows(colBegin, colEnd, rowBegin, rowEnd, widthOffset, pageHeight - table.getRowHeight(0) /*table.getHeaderHeight()*/);
// Add a new page
document.newPage();
colBegin = colEnd;
}
}
public int getTotalPages() {
return numberOfColumnsPerPage.size() * numberOfRowsPerPage.size();
}
public void setHeightOffset(float heightOffset) {
this.heightOffset = heightOffset;
}
public void setWidthOffset(float widthOffset) {
this.widthOffset = widthOffset;
}
private void writeSelectedRows(int colBegin, int colEnd, int rowBegin, int rowEnd, float x, float y) {
PdfContentByte cb = writer.getDirectContent();
table.writeSelectedRows(colBegin, colEnd, rowBegin, rowEnd, x, y, cb);
}
private void calculateColumns() {
numberOfColumnsPerPage = new ArrayList();
float pageWidth = document.getPageSize().getWidth() - widthOffset;
float[] widths = table.getAbsoluteWidths();
if (table.getTotalWidth() > pageWidth) {
// tmp variable for amount of total width thus far
float tmp = 0f;
// How many columns for this page
int columnCount = 0;
// Current page we're on
int currentPage = 0;
// Iterate through the column widths
for (int i = 0; i < widths.length; i++) {
// Add to the temporary total
tmp += widths[i];
// If this column will not fit on the page
if (tmp > pageWidth) {
// Add the current column count to this page
numberOfColumnsPerPage.add(new Integer(columnCount));
// Since this column won't fit, the tmp variable should
// start off the next iteration
// as this column's width
tmp = widths[i];
// Set column count to 1, since we have moved this column to
// the next page
columnCount = 1;
}
// If this is will fit on the page
else {
// Increase the column count
columnCount++;
}
}
// Save the remaining columns
numberOfColumnsPerPage.add(new Integer(columnCount));
}
// All the columns will fit on one horizontal page
// Note: -1 means all the columns
else {
numberOfColumnsPerPage.add(new Integer(-1));
}
}
private void calculateRows() {
numberOfRowsPerPage = new ArrayList();
float pageHeight = document.getPageSize().getHeight() - heightOffset - table.getRowHeight(0) /*table.getHeaderHeight()*/;
// If the table won't fit on the first page
if (table.getTotalHeight() > pageHeight /*table.getHeaderHeight()*/) {
// Temp variables
float tmp = 0f;
// Determine the start and end rows for each page
for (int i = 1; i < table.size(); i++) {
// Add this row's height to the tmp total
tmp += table.getRowHeight(i);
if (tmp > pageHeight - (heightOffset/2)) {
// This row won't fit so end at previous row
numberOfRowsPerPage.add(new Integer(i - 1));
// Since this row won't fit, the tmp variable should start
// off the next iteration
// as this row's height
tmp = table.getRowHeight(i);
}
}
// Last page always ends on totalRows
numberOfRowsPerPage.add(new Integer(table.size()));
}
// All the rows will fit on one vertical page
// Note: -1 means all the rows
else {
numberOfRowsPerPage.add(new Integer(-1));
}
}
}
答案 2 :(得分:0)
好吧,我会尽力给你一些回应。首先,正如@mkl所说,1.4.8是古代版本。查看http://sourceforge.net/projects/itext/files/iText/以获得更好的结果,最后一个版本是5.4.5。而且据我所知,没有办法将宽表分成两页。如果文档比页面“有点”宽 - 旋转页面,但如果你有许多不适合的列 - 你必须按照自己的方式去做,这可能会很痛苦。没有自动功能可以检查您的列是否包含太多文本且不适合页面。
希望这会对你有所帮助。