Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>pdftablesample</groupId>
<artifactId>paginated-pdfbox-table</artifactId>

<version>1.0.0-SNAPSHOT</version>
<name>Paginated PDFBox Table Sample</name>
<packaging>jar</packaging>

<properties>
<!--<pdfbox.version>2.0.0-20150403</pdfbox.version>-->
<pdfbox.version>1.8.9</pdfbox.version>
</properties>

<dependencies>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>${pdfbox.version}</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
<configuration>
<executable>java</executable>
<workingDirectory>${project.build.directory}/exec-working-directory</workingDirectory>
<arguments>
<!-- automatically creates the classpath using all project dependencies,
also adding the project build directory -->
<argument>-classpath</argument>
<classpath>
</classpath>
<argument>pdftablesample.PDFSample</argument>
</arguments>
</configuration>
</plugin>
</plugins>
</build>
</project>

Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
package pdftablesample;
public class Column {
private String name;
private float width;
public Column(String name, float width) {
this.name = name;
this.width = width;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getWidth() {
return width;
}
public void setWidth(float width) {
this.width = width;
}
}
package pdftablesample;

public class Column {

private String name;
private float width;

public Column(String name, float width) {
this.name = name;
this.width = width;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public float getWidth() {
return width;
}

public void setWidth(float width) {
this.width = width;
}
}
Original file line number Diff line number Diff line change
@@ -1,131 +1,131 @@
package pdftablesample;
import java.io.IOException;
import java.util.Arrays;
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;
public class PDFTableGenerator {
// Generates document from Table object
public void generatePDF(Table table) throws IOException, COSVisitorException {
PDDocument doc = null;
try {
doc = new PDDocument();
drawTable(doc, table);
doc.save("sample.pdf");
} finally {
if (doc != null) {
doc.close();
}
}
}
// Configures basic setup for the table and draws it page by page
public void drawTable(PDDocument doc, Table table) throws IOException {
// Calculate pagination
Integer rowsPerPage = new Double(Math.floor(table.getHeight() / table.getRowHeight())).intValue() - 1; // subtract
Integer numberOfPages = new Double(Math.ceil(table.getNumberOfRows().floatValue() / rowsPerPage)).intValue();
// Generate each page, get the content and draw it
for (int pageCount = 0; pageCount < numberOfPages; pageCount++) {
PDPage page = generatePage(doc, table);
PDPageContentStream contentStream = generateContentStream(doc, page, table);
String[][] currentPageContent = getContentForCurrentPage(table, rowsPerPage, pageCount);
drawCurrentPage(table, currentPageContent, contentStream);
}
}
// Draws current page table grid and border lines and content
private void drawCurrentPage(Table table, String[][] currentPageContent, PDPageContentStream contentStream)
throws IOException {
float tableTopY = table.isLandscape() ? table.getPageSize().getWidth() - table.getMargin() : table.getPageSize().getHeight() - table.getMargin();
// Draws grid and borders
drawTableGrid(table, currentPageContent, contentStream, tableTopY);
// Position cursor to start drawing content
float nextTextX = table.getMargin() + table.getCellMargin();
// Calculate center alignment for text in cell considering font height
float nextTextY = tableTopY - (table.getRowHeight() / 2)
- ((table.getTextFont().getFontDescriptor().getFontBoundingBox().getHeight() / 1000 * table.getFontSize()) / 4);
// Write column headers
writeContentLine(table.getColumnsNamesAsArray(), contentStream, nextTextX, nextTextY, table);
nextTextY -= table.getRowHeight();
nextTextX = table.getMargin() + table.getCellMargin();
// Write content
for (int i = 0; i < currentPageContent.length; i++) {
writeContentLine(currentPageContent[i], contentStream, nextTextX, nextTextY, table);
nextTextY -= table.getRowHeight();
nextTextX = table.getMargin() + table.getCellMargin();
}
contentStream.close();
}
// Writes the content for one line
private void writeContentLine(String[] lineContent, PDPageContentStream contentStream, float nextTextX, float nextTextY,
Table table) throws IOException {
for (int i = 0; i < table.getNumberOfColumns(); i++) {
String text = lineContent[i];
contentStream.beginText();
contentStream.moveTextPositionByAmount(nextTextX, nextTextY);
contentStream.drawString(text != null ? text : "");
contentStream.endText();
nextTextX += table.getColumns().get(i).getWidth();
}
}
private void drawTableGrid(Table table, String[][] currentPageContent, PDPageContentStream contentStream, float tableTopY)
throws IOException {
// Draw row lines
float nextY = tableTopY;
for (int i = 0; i <= currentPageContent.length + 1; i++) {
contentStream.drawLine(table.getMargin(), nextY, table.getMargin() + table.getWidth(), nextY);
nextY -= table.getRowHeight();
}
// Draw column lines
final float tableYLength = table.getRowHeight() + (table.getRowHeight() * currentPageContent.length);
final float tableBottomY = tableTopY - tableYLength;
float nextX = table.getMargin();
for (int i = 0; i < table.getNumberOfColumns(); i++) {
contentStream.drawLine(nextX, tableTopY, nextX, tableBottomY);
nextX += table.getColumns().get(i).getWidth();
}
contentStream.drawLine(nextX, tableTopY, nextX, tableBottomY);
}
private String[][] getContentForCurrentPage(Table table, Integer rowsPerPage, int pageCount) {
int startRange = pageCount * rowsPerPage;
int endRange = (pageCount * rowsPerPage) + rowsPerPage;
if (endRange > table.getNumberOfRows()) {
endRange = table.getNumberOfRows();
}
return Arrays.copyOfRange(table.getContent(), startRange, endRange);
}
private PDPage generatePage(PDDocument doc, Table table) {
PDPage page = new PDPage();
page.setMediaBox(table.getPageSize());
page.setRotation(table.isLandscape() ? 90 : 0);
doc.addPage(page);
return page;
}
private PDPageContentStream generateContentStream(PDDocument doc, PDPage page, Table table) throws IOException {
PDPageContentStream contentStream = new PDPageContentStream(doc, page, false, false);
// User transformation matrix to change the reference when drawing.
// This is necessary for the landscape position to draw correctly
if (table.isLandscape()) {
contentStream.concatenate2CTM(0, 1, -1, 0, table.getPageSize().getWidth(), 0);
}
contentStream.setFont(table.getTextFont(), table.getFontSize());
return contentStream;
}
}
package pdftablesample;

import java.io.IOException;
import java.util.Arrays;

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;

public class PDFTableGenerator {

// Generates document from Table object
public void generatePDF(Table table) throws IOException, COSVisitorException {
PDDocument doc = null;
try {
doc = new PDDocument();
drawTable(doc, table);
doc.save("sample.pdf");
} finally {
if (doc != null) {
doc.close();
}
}
}

// Configures basic setup for the table and draws it page by page
public void drawTable(PDDocument doc, Table table) throws IOException {
// Calculate pagination
Integer rowsPerPage = new Double(Math.floor(table.getHeight() / table.getRowHeight())).intValue() - 1; // subtract
Integer numberOfPages = new Double(Math.ceil(table.getNumberOfRows().floatValue() / rowsPerPage)).intValue();

// Generate each page, get the content and draw it
for (int pageCount = 0; pageCount < numberOfPages; pageCount++) {
PDPage page = generatePage(doc, table);
PDPageContentStream contentStream = generateContentStream(doc, page, table);
String[][] currentPageContent = getContentForCurrentPage(table, rowsPerPage, pageCount);
drawCurrentPage(table, currentPageContent, contentStream);
}
}

// Draws current page table grid and border lines and content
private void drawCurrentPage(Table table, String[][] currentPageContent, PDPageContentStream contentStream)
throws IOException {
float tableTopY = table.isLandscape() ? table.getPageSize().getWidth() - table.getMargin() : table.getPageSize().getHeight() - table.getMargin();

// Draws grid and borders
drawTableGrid(table, currentPageContent, contentStream, tableTopY);

// Position cursor to start drawing content
float nextTextX = table.getMargin() + table.getCellMargin();
// Calculate center alignment for text in cell considering font height
float nextTextY = tableTopY - (table.getRowHeight() / 2)
- ((table.getTextFont().getFontDescriptor().getFontBoundingBox().getHeight() / 1000 * table.getFontSize()) / 4);

// Write column headers
writeContentLine(table.getColumnsNamesAsArray(), contentStream, nextTextX, nextTextY, table);
nextTextY -= table.getRowHeight();
nextTextX = table.getMargin() + table.getCellMargin();

// Write content
for (int i = 0; i < currentPageContent.length; i++) {
writeContentLine(currentPageContent[i], contentStream, nextTextX, nextTextY, table);
nextTextY -= table.getRowHeight();
nextTextX = table.getMargin() + table.getCellMargin();
}

contentStream.close();
}

// Writes the content for one line
private void writeContentLine(String[] lineContent, PDPageContentStream contentStream, float nextTextX, float nextTextY,
Table table) throws IOException {
for (int i = 0; i < table.getNumberOfColumns(); i++) {
String text = lineContent[i];
contentStream.beginText();
contentStream.moveTextPositionByAmount(nextTextX, nextTextY);
contentStream.drawString(text != null ? text : "");
contentStream.endText();
nextTextX += table.getColumns().get(i).getWidth();
}
}

private void drawTableGrid(Table table, String[][] currentPageContent, PDPageContentStream contentStream, float tableTopY)
throws IOException {
// Draw row lines
float nextY = tableTopY;
for (int i = 0; i <= currentPageContent.length + 1; i++) {
contentStream.drawLine(table.getMargin(), nextY, table.getMargin() + table.getWidth(), nextY);
nextY -= table.getRowHeight();
}

// Draw column lines
final float tableYLength = table.getRowHeight() + (table.getRowHeight() * currentPageContent.length);
final float tableBottomY = tableTopY - tableYLength;
float nextX = table.getMargin();
for (int i = 0; i < table.getNumberOfColumns(); i++) {
contentStream.drawLine(nextX, tableTopY, nextX, tableBottomY);
nextX += table.getColumns().get(i).getWidth();
}
contentStream.drawLine(nextX, tableTopY, nextX, tableBottomY);
}

private String[][] getContentForCurrentPage(Table table, Integer rowsPerPage, int pageCount) {
int startRange = pageCount * rowsPerPage;
int endRange = (pageCount * rowsPerPage) + rowsPerPage;
if (endRange > table.getNumberOfRows()) {
endRange = table.getNumberOfRows();
}
return Arrays.copyOfRange(table.getContent(), startRange, endRange);
}

private PDPage generatePage(PDDocument doc, Table table) {
PDPage page = new PDPage();
page.setMediaBox(table.getPageSize());
page.setRotation(table.isLandscape() ? 90 : 0);
doc.addPage(page);
return page;
}

private PDPageContentStream generateContentStream(PDDocument doc, PDPage page, Table table) throws IOException {
PDPageContentStream contentStream = new PDPageContentStream(doc, page, false, false);
// User transformation matrix to change the reference when drawing.
// This is necessary for the landscape position to draw correctly
if (table.isLandscape()) {
contentStream.concatenate2CTM(0, 1, -1, 0, table.getPageSize().getWidth(), 0);
}
contentStream.setFont(table.getTextFont(), table.getFontSize());
return contentStream;
}
}
Loading