From 3eb95ab426482ba90171b8fff6d81e01cb0a6647 Mon Sep 17 00:00:00 2001 From: Dries Horions Date: Sat, 2 Apr 2016 14:01:01 +0200 Subject: [PATCH 01/19] csv handling --- src/main/java/be/quodlibet/boxable/Cell.java | 25 +++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/main/java/be/quodlibet/boxable/Cell.java b/src/main/java/be/quodlibet/boxable/Cell.java index 52be66da..6f1c2707 100644 --- a/src/main/java/be/quodlibet/boxable/Cell.java +++ b/src/main/java/be/quodlibet/boxable/Cell.java @@ -654,5 +654,28 @@ public boolean isColspanCell() { public void setColspanCell(boolean isColspanCell) { this.isColspanCell = isColspanCell; - } + } + + /** + *

+ * Copies the style of an existing cell to this cell + *

+ * + * @param sourceCell + */ + public void copyCellStyle(Cell sourceCell) + { + setBorderStyle(sourceCell.getTopBorder()); + setFont(sourceCell.getFont()); + setFontBold(sourceCell.getFontBold()); + setFillColor(sourceCell.getFillColor()); + setTextColor(sourceCell.getTextColor()); + setHeight(sourceCell.getHeight()); + } + + public void setWidth(float width) + { + this.width = width; + } + } From 266b40460d34fd4fd104dad389344fc42350e3c3 Mon Sep 17 00:00:00 2001 From: Dries Horions Date: Sat, 2 Apr 2016 14:24:27 +0200 Subject: [PATCH 02/19] left border --- src/main/java/be/quodlibet/boxable/Cell.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/be/quodlibet/boxable/Cell.java b/src/main/java/be/quodlibet/boxable/Cell.java index 6f1c2707..b61ed484 100644 --- a/src/main/java/be/quodlibet/boxable/Cell.java +++ b/src/main/java/be/quodlibet/boxable/Cell.java @@ -665,7 +665,11 @@ public void setColspanCell(boolean isColspanCell) { */ public void copyCellStyle(Cell sourceCell) { + Boolean leftBorder = this.leftBorderStyle == null; setBorderStyle(sourceCell.getTopBorder()); + if (leftBorder) { + this.leftBorderStyle = null;//if left border wasn't set, don't set it now + } setFont(sourceCell.getFont()); setFontBold(sourceCell.getFontBold()); setFillColor(sourceCell.getFillColor()); From 1b413c83e4c03bc67f028684df8c2839c18b6adb Mon Sep 17 00:00:00 2001 From: Dries Horions Date: Sat, 2 Apr 2016 14:56:29 +0200 Subject: [PATCH 03/19] copyCellStyle setting font invalidated paragraph --- src/main/java/be/quodlibet/boxable/Cell.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/be/quodlibet/boxable/Cell.java b/src/main/java/be/quodlibet/boxable/Cell.java index b61ed484..031c681e 100644 --- a/src/main/java/be/quodlibet/boxable/Cell.java +++ b/src/main/java/be/quodlibet/boxable/Cell.java @@ -670,7 +670,7 @@ public void copyCellStyle(Cell sourceCell) if (leftBorder) { this.leftBorderStyle = null;//if left border wasn't set, don't set it now } - setFont(sourceCell.getFont()); + this.font = sourceCell.getFont();//otherwise paragraph gets invalidated setFontBold(sourceCell.getFontBold()); setFillColor(sourceCell.getFillColor()); setTextColor(sourceCell.getTextColor()); From 6c65c796becdc3edc1c434b9ded7df52e9cc8517 Mon Sep 17 00:00:00 2001 From: Dries Horions Date: Sat, 2 Apr 2016 15:00:55 +0200 Subject: [PATCH 04/19] fontbold --- src/main/java/be/quodlibet/boxable/Cell.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/be/quodlibet/boxable/Cell.java b/src/main/java/be/quodlibet/boxable/Cell.java index 031c681e..8a346fc3 100644 --- a/src/main/java/be/quodlibet/boxable/Cell.java +++ b/src/main/java/be/quodlibet/boxable/Cell.java @@ -671,7 +671,7 @@ public void copyCellStyle(Cell sourceCell) this.leftBorderStyle = null;//if left border wasn't set, don't set it now } this.font = sourceCell.getFont();//otherwise paragraph gets invalidated - setFontBold(sourceCell.getFontBold()); + this.fontBold = sourceCell.getFontBold(); setFillColor(sourceCell.getFillColor()); setTextColor(sourceCell.getTextColor()); setHeight(sourceCell.getHeight()); From 352d07a0177edbc19bf2fc1d76079b3a0c783603 Mon Sep 17 00:00:00 2001 From: Dries Horions Date: Sat, 2 Apr 2016 22:00:31 +0200 Subject: [PATCH 05/19] Write csv's to tables in pdf documents --- pom.xml | 16 +- src/main/java/be/quodlibet/boxable/Cell.java | 2 +- .../be/quodlibet/boxable/csv/CSVTable.java | 211 +++++++++++++++ .../java/be/quodlibet/boxable/CSVTest.java | 254 ++++++++++++++++++ 4 files changed, 479 insertions(+), 4 deletions(-) create mode 100644 src/main/java/be/quodlibet/boxable/csv/CSVTable.java create mode 100644 src/test/java/be/quodlibet/boxable/CSVTest.java diff --git a/pom.xml b/pom.xml index cbbef789..a5c243c6 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ 4.0.0 com.github.dhorions boxable - 1.3 + 1.4-SNAPSHOT jar Boxable, a high-level API to creates table on top of Apache Pdfbox @@ -22,7 +22,7 @@ org.apache.pdfbox pdfbox - 2.0.0-RC3 + 2.0.0 compile @@ -39,7 +39,11 @@ 18.0 compile - + + org.apache.commons + commons-csv + 1.1 + junit @@ -47,6 +51,12 @@ 4.12 test + + commons-io + commons-io + 2.4 + test + diff --git a/src/main/java/be/quodlibet/boxable/Cell.java b/src/main/java/be/quodlibet/boxable/Cell.java index 8a346fc3..0527c148 100644 --- a/src/main/java/be/quodlibet/boxable/Cell.java +++ b/src/main/java/be/quodlibet/boxable/Cell.java @@ -674,7 +674,7 @@ public void copyCellStyle(Cell sourceCell) this.fontBold = sourceCell.getFontBold(); setFillColor(sourceCell.getFillColor()); setTextColor(sourceCell.getTextColor()); - setHeight(sourceCell.getHeight()); + //setHeight(sourceCell.getHeight()); } public void setWidth(float width) diff --git a/src/main/java/be/quodlibet/boxable/csv/CSVTable.java b/src/main/java/be/quodlibet/boxable/csv/CSVTable.java new file mode 100644 index 00000000..65fae7a6 --- /dev/null +++ b/src/main/java/be/quodlibet/boxable/csv/CSVTable.java @@ -0,0 +1,211 @@ +package be.quodlibet.boxable.csv; + +import be.quodlibet.boxable.BaseTable; +import be.quodlibet.boxable.Cell; +import be.quodlibet.boxable.HorizontalAlignment; +import be.quodlibet.boxable.Row; +import be.quodlibet.boxable.Table; +import be.quodlibet.boxable.VerticalAlignment; +import be.quodlibet.boxable.line.LineStyle; +import be.quodlibet.boxable.utils.FontUtils; +import java.awt.Color; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVParser; +import org.apache.commons.csv.CSVRecord; +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.pdmodel.PDPage; +import org.apache.pdfbox.pdmodel.font.PDType1Font; + +/** + * + * @author Dries Horions + */ +public class CSVTable +{ + public static final Boolean HASHEADER = true; + public static final Boolean NOHEADER = false; + private Table table; + private Cell headerCellTemplate; + private Cell dataCellTemplateEven; + private Cell dataCellTemplateOdd; + private Cell firstColumnCellTemplate; + private Cell lastColumnCellTemplate; + public CSVTable(Table table, PDPage page) throws IOException + { + this.table = table; + //Create a dummy pdf document, page and table to create template cells + PDDocument ddoc = new PDDocument(); + PDPage dpage = new PDPage(); + dpage.setMediaBox(page.getMediaBox()); + dpage.setRotation(page.getRotation()); + ddoc.addPage(dpage); + BaseTable dummyTable = new BaseTable(10f, 10f, 10f, table.getWidth(), 10f, ddoc, dpage, false, + false); + Row dr = dummyTable.createRow(0f); + headerCellTemplate = dr.createCell(10f, "A", HorizontalAlignment.CENTER, VerticalAlignment.MIDDLE); + dataCellTemplateEven = dr.createCell(10f, "A", HorizontalAlignment.LEFT, VerticalAlignment.MIDDLE); + dataCellTemplateOdd = dr.createCell(10f, "A", HorizontalAlignment.LEFT, VerticalAlignment.MIDDLE); + firstColumnCellTemplate = dr.createCell(10f, "A", HorizontalAlignment.LEFT, VerticalAlignment.MIDDLE); + lastColumnCellTemplate = dr.createCell(10f, "A", HorizontalAlignment.LEFT, VerticalAlignment.MIDDLE); + setDefaultStyles(); + ddoc.close(); + } + + private void setDefaultStyles() + { + LineStyle thinline = new LineStyle(Color.DARK_GRAY, 0.5f); + //Header style + headerCellTemplate.setFillColor(new Color(137, 218, 245)); + headerCellTemplate.setTextColor(Color.BLACK); + headerCellTemplate.setFont(PDType1Font.HELVETICA_BOLD); + headerCellTemplate.setLeftBorderStyle(thinline); + + //Normal cell style, all rows and columns are the same by default + dataCellTemplateEven.setFillColor(new Color(242, 242, 242)); + dataCellTemplateEven.setTextColor(Color.BLACK); + dataCellTemplateEven.setFont(PDType1Font.HELVETICA); + dataCellTemplateEven.setLeftBorderStyle(thinline); + + dataCellTemplateOdd.setFillColor(new Color(242, 242, 242)); + dataCellTemplateOdd.setTextColor(Color.BLACK); + dataCellTemplateOdd.setFont(PDType1Font.HELVETICA); + dataCellTemplateOdd.setLeftBorderStyle(thinline); + + firstColumnCellTemplate.setFillColor(new Color(242, 242, 242)); + firstColumnCellTemplate.setTextColor(Color.BLACK); + firstColumnCellTemplate.setFont(PDType1Font.HELVETICA); + firstColumnCellTemplate.setLeftBorderStyle(thinline); + + lastColumnCellTemplate.setFillColor(new Color(242, 242, 242)); + lastColumnCellTemplate.setTextColor(Color.BLACK); + lastColumnCellTemplate.setFont(PDType1Font.HELVETICA); + lastColumnCellTemplate.setLeftBorderStyle(thinline); + } + + + /** + * Set the table to add the csv content to + * + * @return + */ + public Table getTable() + { + return table; + } + + public void setTable(Table table) + { + this.table = table; + } + + public Cell getHeaderCellTemplate() + { + return headerCellTemplate; + } + + public Cell getDataCellTemplateEven() + { + return dataCellTemplateEven; + } + + public Cell getDataCellTemplateOdd() + { + return dataCellTemplateOdd; + } + + public Cell getFirstColumnCellTemplate() + { + return firstColumnCellTemplate; + } + + public Cell getLastColumnCellTemplate() + { + return lastColumnCellTemplate; + } + + + public void addCsvToTable(String data, Boolean hasHeader, char separator) throws IOException + { + Iterable records = CSVParser.parse(data, CSVFormat.EXCEL.withDelimiter(separator)); + Boolean isHeader = hasHeader; + Boolean isFirst = true; + Boolean odd = true; + Map colWidths = new HashMap(); + int numcols = 0; + for (CSVRecord line : records) { + + if (isFirst) { + + + //calculate the width of the columns + float totalPct = 0.0f; + float totalWidth = 0.0f; + for (int i = 0; i < line.size(); i++) { + String cellValue = line.get(i); + float textWidth = FontUtils.getStringWidth(headerCellTemplate.getFont(), " " + cellValue + " ", headerCellTemplate.getFontSize()); + float widthPct = textWidth * 100 / table.getWidth(); + totalPct += widthPct; + totalWidth += textWidth; + numcols = i; + } + //now totalPct has the total % of width we need to have all columns full sized. + //now calculate a factor to reduce size by to make it fit + float sizefactor = 100.0f / totalPct; + sizefactor = table.getWidth() / totalWidth; + for (int i = 0; i <= numcols; i++) { + String cellValue = ""; + if (line.size() >= i) { + cellValue = line.get(i); + } + float textWidth = FontUtils.getStringWidth(headerCellTemplate.getFont(), " " + cellValue + " ", headerCellTemplate.getFontSize()); + float widthPct = textWidth * 100 / table.getWidth(); + //apply width factor + widthPct = widthPct * sizefactor; + colWidths.put(i, widthPct); + } + isFirst = false; + } + if (isHeader) { + //Add Header Row + Row h = table.createRow(headerCellTemplate.getCellHeight()); + for (int i = 0; i <= numcols; i++) { + String cellValue = line.get(i); + Cell c = h.createCell(colWidths.get(i), cellValue, headerCellTemplate.getAlign(), headerCellTemplate.getValign()); + //Apply style of header cell to this cell + c.copyCellStyle(headerCellTemplate); + c.setText(cellValue); + } + table.addHeaderRow(h); + isHeader = false; + } + else { + Row r = table.createRow(dataCellTemplateEven.getCellHeight()); + for (int i = 0; i <= numcols; i++) { + String cellValue = ""; + if (line.size() >= i) { + cellValue = line.get(i); + } + //Choose the correct template for the cell + Cell template = dataCellTemplateEven; + if (odd) { + template = dataCellTemplateOdd; + } + if (i == 0) { + template = firstColumnCellTemplate; + } + if (i == numcols) { + template = lastColumnCellTemplate; + } + Cell c = r.createCell(colWidths.get(i), cellValue, template.getAlign(), template.getValign()); + //Apply style of header cell to this cell + c.copyCellStyle(template); + c.setText(cellValue); + } + } + odd = !odd; + } + } +} diff --git a/src/test/java/be/quodlibet/boxable/CSVTest.java b/src/test/java/be/quodlibet/boxable/CSVTest.java new file mode 100644 index 00000000..8d6f55d4 --- /dev/null +++ b/src/test/java/be/quodlibet/boxable/CSVTest.java @@ -0,0 +1,254 @@ +package be.quodlibet.boxable; + +import be.quodlibet.boxable.csv.CSVTable; +import com.google.common.io.Files; +import java.awt.Color; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import org.apache.commons.io.IOUtils; +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.pdmodel.PDPage; +import org.apache.pdfbox.pdmodel.common.PDRectangle; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +/** + * + * @author Dries Horions + */ +public class CSVTest +{ + + public CSVTest() + { + } + + @BeforeClass + public static void setUpClass() + { + } + + @AfterClass + public static void tearDownClass() + { + } + + @Before + public void setUp() + { + } + + @After + public void tearDown() + { + } + + // TODO add test methods here. + // The methods must be annotated with annotation @Test. For example: + // + @Test + public void csvTestColWidths() throws IOException + { + String data = readData("https://s3.amazonaws.com/misc.quodlibet.be/Boxable/teknologic.csv"); + //Initialize Document + PDDocument doc = new PDDocument(); + PDPage page = new PDPage(); + //Create a landscape page + page.setMediaBox(new PDRectangle(PDRectangle.A4.getHeight(), PDRectangle.A4.getWidth())); + doc.addPage(page); + //Initialize table + float margin = 10; + float tableWidth = page.getMediaBox().getWidth() - (2 * margin); + float yStartNewPage = page.getMediaBox().getHeight() - (2 * margin); + float yStart = yStartNewPage; + float bottomMargin = 70; + + BaseTable dataTable = new BaseTable(yStart, yStartNewPage, bottomMargin, tableWidth, margin, doc, page, true, + true); + CSVTable t = new CSVTable(dataTable, page); + t.addCsvToTable(data, CSVTable.HASHEADER, ";".toCharArray()[0]); + dataTable.draw(); + File file = new File("target/CSVexampleColWidths.pdf"); + System.out.println("Sample file saved at : " + file.getAbsolutePath()); + Files.createParentDirs(file); + doc.save(file); + doc.close(); + } + + @Test + public void csvTestPortrait() throws IOException + { + String data = readData("https://s3.amazonaws.com/misc.quodlibet.be/Boxable/Eurostat_Immigration_Applications.csv"); + //Initialize Document + PDDocument doc = new PDDocument(); + PDPage page = new PDPage(); + //Create a landscape page + //page.setMediaBox(new PDRectangle(PDRectangle.A4.getHeight(), PDRectangle.A4.getWidth())); + doc.addPage(page); + //Initialize table + float margin = 10; + float tableWidth = page.getMediaBox().getWidth() - (2 * margin); + float yStartNewPage = page.getMediaBox().getHeight() - (2 * margin); + float yStart = yStartNewPage; + float bottomMargin = 70; + + BaseTable dataTable = new BaseTable(yStart, yStartNewPage, bottomMargin, tableWidth, margin, doc, page, true, + true); + CSVTable t = new CSVTable(dataTable, page); + t.addCsvToTable(data, CSVTable.HASHEADER, ";".toCharArray()[0]); + dataTable.draw(); + File file = new File("target/CSVexamplePortrait.pdf"); + System.out.println("Sample file saved at : " + file.getAbsolutePath()); + Files.createParentDirs(file); + doc.save(file); + doc.close(); + } + + @Test + public void csvTestLandscape() throws IOException + { + String data = readData("https://s3.amazonaws.com/misc.quodlibet.be/Boxable/Eurostat_Immigration_Applications.csv"); + //Initialize Document + PDDocument doc = new PDDocument(); + PDPage page = new PDPage(); + //Create a landscape page + //page.setMediaBox(new PDRectangle(PDRectangle.A4.getHeight(), PDRectangle.A4.getWidth())); + doc.addPage(page); + //Initialize table + float margin = 10; + float tableWidth = page.getMediaBox().getWidth() - (2 * margin); + float yStartNewPage = page.getMediaBox().getHeight() - (2 * margin); + float yStart = yStartNewPage; + float bottomMargin = 70; + + BaseTable dataTable = new BaseTable(yStart, yStartNewPage, bottomMargin, tableWidth, margin, doc, page, true, + true); + CSVTable t = new CSVTable(dataTable, page); + t.addCsvToTable(data, CSVTable.HASHEADER, ";".toCharArray()[0]); + dataTable.draw(); + File file = new File("target/CSVexampleLandscape.pdf"); + System.out.println("Sample file saved at : " + file.getAbsolutePath()); + Files.createParentDirs(file); + doc.save(file); + doc.close(); + } + + @Test + public void csvTestSimple() throws IOException + { + + String data = readData("https://s3.amazonaws.com/misc.quodlibet.be/Boxable/Eurostat_Energcy_Prices_Medium_Household.csv"); + //Initialize Document + PDDocument doc = new PDDocument(); + PDPage page = new PDPage(); + //Create a landscape page + page.setMediaBox(new PDRectangle(PDRectangle.A4.getHeight(), PDRectangle.A4.getWidth())); + doc.addPage(page); + //Initialize table + float margin = 10; + float tableWidth = page.getMediaBox().getWidth() - (2 * margin); + float yStartNewPage = page.getMediaBox().getHeight() - (2 * margin); + float yStart = yStartNewPage; + float bottomMargin = 70; + + BaseTable dataTable = new BaseTable(yStart, yStartNewPage, bottomMargin, tableWidth, margin, doc, page, true, + true); + //Add a few things to the table that's not coming from the csv file + Row h1 = dataTable.createRow(0f); + Cell c1 = h1.createCell(100, "Electricity Prices by type of user"); + c1.setFillColor(new Color(144, 195, 212)); + dataTable.addHeaderRow(h1); + Row h2 = dataTable.createRow(0f); + Cell c2 = h2.createCell(100, "Eur per kWh for Medium Size Households.
Source http://ec.europa.eu/eurostat/tgm/table.do?tab=table&init=1&plugin=1&language=en&pcode=ten00117"); + c2.setFillColor(new Color(175, 212, 224)); + dataTable.addHeaderRow(h2); + CSVTable t = new CSVTable(dataTable, page); + t.addCsvToTable(data, CSVTable.HASHEADER, ";".toCharArray()[0]); + dataTable.draw(); + File file = new File("target/CSVexampleSimple.pdf"); + System.out.println("Sample file saved at : " + file.getAbsolutePath()); + Files.createParentDirs(file); + doc.save(file); + doc.close(); + + } + + @Test + public void csvTestAdvanced() throws IOException + { + + String data = readData("https://s3.amazonaws.com/misc.quodlibet.be/Boxable/Eurostat_Energcy_Prices_Medium_Household.csv"); + //String data = readData("https://s3.amazonaws.com/misc.quodlibet.be/Boxable/simplecsv.csv"); + //Initialize Document + PDDocument doc = new PDDocument(); + PDPage page = new PDPage(); + //Create a landscape page + page.setMediaBox(new PDRectangle(PDRectangle.A4.getHeight(), PDRectangle.A4.getWidth())); + doc.addPage(page); + //Initialize table + float margin = 10; + float tableWidth = page.getMediaBox().getWidth() - (2 * margin); + float yStartNewPage = page.getMediaBox().getHeight() - (2 * margin); + float yStart = yStartNewPage; + float bottomMargin = 70; + + BaseTable dataTable = new BaseTable(yStart, yStartNewPage, bottomMargin, tableWidth, margin, doc, page, true, + true); + //Add a few things to the table that's not coming from the csv file + Row h1 = dataTable.createRow(0f); + Cell c1 = h1.createCell(100, "Electricity Prices by type of user"); + c1.setFillColor(new Color(144, 195, 212)); + dataTable.addHeaderRow(h1); + Row h2 = dataTable.createRow(0f); + Cell c2 = h2.createCell(100, "Eur per kWh for Medium Size Households.
Source http://ec.europa.eu/eurostat/tgm/table.do?tab=table&init=1&plugin=1&language=en&pcode=ten00117"); + c2.setFillColor(new Color(175, 212, 224)); + dataTable.addHeaderRow(h2); + CSVTable t = new CSVTable(dataTable, page); + //set the style template for header cells + t.getHeaderCellTemplate().setFillColor(new Color(13, 164, 214)); + //set the style template for first column + t.getFirstColumnCellTemplate().setFillColor(new Color(13, 164, 214)); + //set the style template for last column + t.getLastColumnCellTemplate().setFillColor(new Color(144, 195, 212)); + //set the style template for normal, data columns + t.getDataCellTemplateEven().setFillColor(Color.WHITE); + t.getDataCellTemplateOdd().setFillColor(new Color(250, 242, 242)); + + t.addCsvToTable(data, CSVTable.HASHEADER, ";".toCharArray()[0]); + + dataTable.draw(); + File file = new File("target/CSVexampleAdvanced.pdf"); + System.out.println("Sample file saved at : " + file.getAbsolutePath()); + Files.createParentDirs(file); + doc.save(file); + doc.close(); + } + + private static String readData(String url) + { + InputStream in = null; + try { + in = new URL(url).openStream(); + return IOUtils.toString(in); + } + catch (IOException ex) { + System.out.println(ex.getMessage()); + } + finally { + IOUtils.closeQuietly(in); + } + return ""; + } + + private static PDPage addNewPage(PDDocument doc) + { + PDPage page = new PDPage(); + doc.addPage(page); + return page; + } +} From 7759175d5f9420d925bf329a6fc3dd8ab4982c49 Mon Sep 17 00:00:00 2001 From: Dries Horions Date: Sun, 3 Apr 2016 08:42:53 +0200 Subject: [PATCH 06/19] Cleanup and javadoc --- .../be/quodlibet/boxable/csv/CSVTable.java | 92 +++++++++++++++---- 1 file changed, 74 insertions(+), 18 deletions(-) diff --git a/src/main/java/be/quodlibet/boxable/csv/CSVTable.java b/src/main/java/be/quodlibet/boxable/csv/CSVTable.java index 65fae7a6..eb79a3e1 100644 --- a/src/main/java/be/quodlibet/boxable/csv/CSVTable.java +++ b/src/main/java/be/quodlibet/boxable/csv/CSVTable.java @@ -20,6 +20,7 @@ import org.apache.pdfbox.pdmodel.font.PDType1Font; /** + * Write CSV documents directly to PDF Tables * * @author Dries Horions */ @@ -33,6 +34,17 @@ public class CSVTable private Cell dataCellTemplateOdd; private Cell firstColumnCellTemplate; private Cell lastColumnCellTemplate; + + /** + *

+ * Create a CSVTable object to be able to add CSV document to a Table. + * A page needs to be passed to the constructor so the Template Cells can be created. + *

+ * + * @param table + * @param page + * @throws IOException + */ public CSVTable(Table table, PDPage page) throws IOException { this.table = table; @@ -53,7 +65,11 @@ public CSVTable(Table table, PDPage page) throws IOException setDefaultStyles(); ddoc.close(); } - + /** + *

+ * Default cell styles for all cells. By default, only the header cell has a different style than the rest of the table. + *

+ */ private void setDefaultStyles() { LineStyle thinline = new LineStyle(Color.DARK_GRAY, 0.5f); @@ -95,38 +111,81 @@ public Table getTable() { return table; } - + /** + *

+ * Set the Table that the CSV document will be added to + *

+ * + * @param table + */ public void setTable(Table table) { this.table = table; } - + /** + *

+ * Get the Cell Template that will be applied to header cells. + *

+ * @return + */ public Cell getHeaderCellTemplate() { return headerCellTemplate; } - + /** + *

+ * Get the Cell Template that will be assigned to Data cells that are in even rows, and are not the first or last column + *

+ * + * @return + */ public Cell getDataCellTemplateEven() { return dataCellTemplateEven; } - + /** + *

+ * Get the Cell Template that will be assigned to Data cells that are in odd rows, and are not the first or last column + *

+ * + * @return + */ public Cell getDataCellTemplateOdd() { return dataCellTemplateOdd; } - + /** + *

+ * Get the Cell Template that will be assigned to cells in the first column + *

+ * + * @return + */ public Cell getFirstColumnCellTemplate() { return firstColumnCellTemplate; } - + /** + *

+ * Get the Cell Template that will be assigned to cells in the last columns + * + * @return + */ public Cell getLastColumnCellTemplate() { return lastColumnCellTemplate; } - + /** + *

+ * Add a String representing a CSV document to the Table + *

+ * + * @param data + * @param hasHeader + * @param separator + * @throws IOException + */ public void addCsvToTable(String data, Boolean hasHeader, char separator) throws IOException { Iterable records = CSVParser.parse(data, CSVFormat.EXCEL.withDelimiter(separator)); @@ -141,20 +200,17 @@ public void addCsvToTable(String data, Boolean hasHeader, char separator) throws //calculate the width of the columns - float totalPct = 0.0f; float totalWidth = 0.0f; for (int i = 0; i < line.size(); i++) { String cellValue = line.get(i); float textWidth = FontUtils.getStringWidth(headerCellTemplate.getFont(), " " + cellValue + " ", headerCellTemplate.getFontSize()); float widthPct = textWidth * 100 / table.getWidth(); - totalPct += widthPct; totalWidth += textWidth; numcols = i; } - //now totalPct has the total % of width we need to have all columns full sized. - //now calculate a factor to reduce size by to make it fit - float sizefactor = 100.0f / totalPct; - sizefactor = table.getWidth() / totalWidth; + //totalWidth has the total width we need to have all columns full sized. + //calculate a factor to reduce/increase size by to make it fit in our table + float sizefactor = table.getWidth() / totalWidth; for (int i = 0; i <= numcols; i++) { String cellValue = ""; if (line.size() >= i) { @@ -184,10 +240,6 @@ public void addCsvToTable(String data, Boolean hasHeader, char separator) throws else { Row r = table.createRow(dataCellTemplateEven.getCellHeight()); for (int i = 0; i <= numcols; i++) { - String cellValue = ""; - if (line.size() >= i) { - cellValue = line.get(i); - } //Choose the correct template for the cell Cell template = dataCellTemplateEven; if (odd) { @@ -199,6 +251,10 @@ public void addCsvToTable(String data, Boolean hasHeader, char separator) throws if (i == numcols) { template = lastColumnCellTemplate; } + String cellValue = ""; + if (line.size() >= i) { + cellValue = line.get(i); + } Cell c = r.createCell(colWidths.get(i), cellValue, template.getAlign(), template.getValign()); //Apply style of header cell to this cell c.copyCellStyle(template); From 7587171190050035bfbd5374daf2f0dd12635ba2 Mon Sep 17 00:00:00 2001 From: Dries Horions Date: Sun, 3 Apr 2016 08:56:17 +0200 Subject: [PATCH 07/19] test cleanup --- .../java/be/quodlibet/boxable/CSVTest.java | 28 ++++++++----------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/src/test/java/be/quodlibet/boxable/CSVTest.java b/src/test/java/be/quodlibet/boxable/CSVTest.java index 8d6f55d4..da5a4a7b 100644 --- a/src/test/java/be/quodlibet/boxable/CSVTest.java +++ b/src/test/java/be/quodlibet/boxable/CSVTest.java @@ -48,9 +48,6 @@ public void tearDown() { } - // TODO add test methods here. - // The methods must be annotated with annotation @Test. For example: - // @Test public void csvTestColWidths() throws IOException { @@ -66,12 +63,12 @@ public void csvTestColWidths() throws IOException float tableWidth = page.getMediaBox().getWidth() - (2 * margin); float yStartNewPage = page.getMediaBox().getHeight() - (2 * margin); float yStart = yStartNewPage; - float bottomMargin = 70; + float bottomMargin = 20; BaseTable dataTable = new BaseTable(yStart, yStartNewPage, bottomMargin, tableWidth, margin, doc, page, true, true); CSVTable t = new CSVTable(dataTable, page); - t.addCsvToTable(data, CSVTable.HASHEADER, ";".toCharArray()[0]); + t.addCsvToTable(data, CSVTable.HASHEADER, ';'); dataTable.draw(); File file = new File("target/CSVexampleColWidths.pdf"); System.out.println("Sample file saved at : " + file.getAbsolutePath()); @@ -87,20 +84,18 @@ public void csvTestPortrait() throws IOException //Initialize Document PDDocument doc = new PDDocument(); PDPage page = new PDPage(); - //Create a landscape page - //page.setMediaBox(new PDRectangle(PDRectangle.A4.getHeight(), PDRectangle.A4.getWidth())); doc.addPage(page); //Initialize table float margin = 10; float tableWidth = page.getMediaBox().getWidth() - (2 * margin); float yStartNewPage = page.getMediaBox().getHeight() - (2 * margin); float yStart = yStartNewPage; - float bottomMargin = 70; + float bottomMargin = 20; BaseTable dataTable = new BaseTable(yStart, yStartNewPage, bottomMargin, tableWidth, margin, doc, page, true, true); CSVTable t = new CSVTable(dataTable, page); - t.addCsvToTable(data, CSVTable.HASHEADER, ";".toCharArray()[0]); + t.addCsvToTable(data, CSVTable.HASHEADER, ';'); dataTable.draw(); File file = new File("target/CSVexamplePortrait.pdf"); System.out.println("Sample file saved at : " + file.getAbsolutePath()); @@ -117,19 +112,19 @@ public void csvTestLandscape() throws IOException PDDocument doc = new PDDocument(); PDPage page = new PDPage(); //Create a landscape page - //page.setMediaBox(new PDRectangle(PDRectangle.A4.getHeight(), PDRectangle.A4.getWidth())); + page.setMediaBox(new PDRectangle(PDRectangle.A4.getHeight(), PDRectangle.A4.getWidth())); doc.addPage(page); //Initialize table float margin = 10; float tableWidth = page.getMediaBox().getWidth() - (2 * margin); float yStartNewPage = page.getMediaBox().getHeight() - (2 * margin); float yStart = yStartNewPage; - float bottomMargin = 70; + float bottomMargin = 20; BaseTable dataTable = new BaseTable(yStart, yStartNewPage, bottomMargin, tableWidth, margin, doc, page, true, true); CSVTable t = new CSVTable(dataTable, page); - t.addCsvToTable(data, CSVTable.HASHEADER, ";".toCharArray()[0]); + t.addCsvToTable(data, CSVTable.HASHEADER, ';'); dataTable.draw(); File file = new File("target/CSVexampleLandscape.pdf"); System.out.println("Sample file saved at : " + file.getAbsolutePath()); @@ -154,7 +149,7 @@ public void csvTestSimple() throws IOException float tableWidth = page.getMediaBox().getWidth() - (2 * margin); float yStartNewPage = page.getMediaBox().getHeight() - (2 * margin); float yStart = yStartNewPage; - float bottomMargin = 70; + float bottomMargin = 20; BaseTable dataTable = new BaseTable(yStart, yStartNewPage, bottomMargin, tableWidth, margin, doc, page, true, true); @@ -168,7 +163,7 @@ public void csvTestSimple() throws IOException c2.setFillColor(new Color(175, 212, 224)); dataTable.addHeaderRow(h2); CSVTable t = new CSVTable(dataTable, page); - t.addCsvToTable(data, CSVTable.HASHEADER, ";".toCharArray()[0]); + t.addCsvToTable(data, CSVTable.HASHEADER, ';'); dataTable.draw(); File file = new File("target/CSVexampleSimple.pdf"); System.out.println("Sample file saved at : " + file.getAbsolutePath()); @@ -183,7 +178,6 @@ public void csvTestAdvanced() throws IOException { String data = readData("https://s3.amazonaws.com/misc.quodlibet.be/Boxable/Eurostat_Energcy_Prices_Medium_Household.csv"); - //String data = readData("https://s3.amazonaws.com/misc.quodlibet.be/Boxable/simplecsv.csv"); //Initialize Document PDDocument doc = new PDDocument(); PDPage page = new PDPage(); @@ -195,7 +189,7 @@ public void csvTestAdvanced() throws IOException float tableWidth = page.getMediaBox().getWidth() - (2 * margin); float yStartNewPage = page.getMediaBox().getHeight() - (2 * margin); float yStart = yStartNewPage; - float bottomMargin = 70; + float bottomMargin = 20; BaseTable dataTable = new BaseTable(yStart, yStartNewPage, bottomMargin, tableWidth, margin, doc, page, true, true); @@ -219,7 +213,7 @@ public void csvTestAdvanced() throws IOException t.getDataCellTemplateEven().setFillColor(Color.WHITE); t.getDataCellTemplateOdd().setFillColor(new Color(250, 242, 242)); - t.addCsvToTable(data, CSVTable.HASHEADER, ";".toCharArray()[0]); + t.addCsvToTable(data, CSVTable.HASHEADER, ';'); dataTable.draw(); File file = new File("target/CSVexampleAdvanced.pdf"); From 250f07b50a1b1ca86a53753e873cd6375e7a4f40 Mon Sep 17 00:00:00 2001 From: Dries Horions Date: Sun, 3 Apr 2016 10:51:17 +0200 Subject: [PATCH 08/19] remove unnecessary bottom margin from CSV tests --- src/test/java/be/quodlibet/boxable/CSVTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/java/be/quodlibet/boxable/CSVTest.java b/src/test/java/be/quodlibet/boxable/CSVTest.java index da5a4a7b..3e54eb88 100644 --- a/src/test/java/be/quodlibet/boxable/CSVTest.java +++ b/src/test/java/be/quodlibet/boxable/CSVTest.java @@ -90,7 +90,7 @@ public void csvTestPortrait() throws IOException float tableWidth = page.getMediaBox().getWidth() - (2 * margin); float yStartNewPage = page.getMediaBox().getHeight() - (2 * margin); float yStart = yStartNewPage; - float bottomMargin = 20; + float bottomMargin = 0; BaseTable dataTable = new BaseTable(yStart, yStartNewPage, bottomMargin, tableWidth, margin, doc, page, true, true); @@ -119,7 +119,7 @@ public void csvTestLandscape() throws IOException float tableWidth = page.getMediaBox().getWidth() - (2 * margin); float yStartNewPage = page.getMediaBox().getHeight() - (2 * margin); float yStart = yStartNewPage; - float bottomMargin = 20; + float bottomMargin = 0; BaseTable dataTable = new BaseTable(yStart, yStartNewPage, bottomMargin, tableWidth, margin, doc, page, true, true); @@ -149,7 +149,7 @@ public void csvTestSimple() throws IOException float tableWidth = page.getMediaBox().getWidth() - (2 * margin); float yStartNewPage = page.getMediaBox().getHeight() - (2 * margin); float yStart = yStartNewPage; - float bottomMargin = 20; + float bottomMargin = 0; BaseTable dataTable = new BaseTable(yStart, yStartNewPage, bottomMargin, tableWidth, margin, doc, page, true, true); @@ -189,7 +189,7 @@ public void csvTestAdvanced() throws IOException float tableWidth = page.getMediaBox().getWidth() - (2 * margin); float yStartNewPage = page.getMediaBox().getHeight() - (2 * margin); float yStart = yStartNewPage; - float bottomMargin = 20; + float bottomMargin = 0; BaseTable dataTable = new BaseTable(yStart, yStartNewPage, bottomMargin, tableWidth, margin, doc, page, true, true); From 38ccca5cfd899ee6052f5ef1f7ec0f074036019a Mon Sep 17 00:00:00 2001 From: Dries Horions Date: Sun, 3 Apr 2016 11:32:58 +0200 Subject: [PATCH 09/19] fix default border issue --- src/main/java/be/quodlibet/boxable/csv/CSVTable.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/be/quodlibet/boxable/csv/CSVTable.java b/src/main/java/be/quodlibet/boxable/csv/CSVTable.java index eb79a3e1..64e842e8 100644 --- a/src/main/java/be/quodlibet/boxable/csv/CSVTable.java +++ b/src/main/java/be/quodlibet/boxable/csv/CSVTable.java @@ -72,33 +72,33 @@ public CSVTable(Table table, PDPage page) throws IOException */ private void setDefaultStyles() { - LineStyle thinline = new LineStyle(Color.DARK_GRAY, 0.5f); + LineStyle thinline = new LineStyle(Color.BLACK, 0.75f); //Header style headerCellTemplate.setFillColor(new Color(137, 218, 245)); headerCellTemplate.setTextColor(Color.BLACK); headerCellTemplate.setFont(PDType1Font.HELVETICA_BOLD); - headerCellTemplate.setLeftBorderStyle(thinline); + headerCellTemplate.setBorderStyle(thinline); //Normal cell style, all rows and columns are the same by default dataCellTemplateEven.setFillColor(new Color(242, 242, 242)); dataCellTemplateEven.setTextColor(Color.BLACK); dataCellTemplateEven.setFont(PDType1Font.HELVETICA); - dataCellTemplateEven.setLeftBorderStyle(thinline); + dataCellTemplateEven.setBorderStyle(thinline); dataCellTemplateOdd.setFillColor(new Color(242, 242, 242)); dataCellTemplateOdd.setTextColor(Color.BLACK); dataCellTemplateOdd.setFont(PDType1Font.HELVETICA); - dataCellTemplateOdd.setLeftBorderStyle(thinline); + dataCellTemplateOdd.setBorderStyle(thinline); firstColumnCellTemplate.setFillColor(new Color(242, 242, 242)); firstColumnCellTemplate.setTextColor(Color.BLACK); firstColumnCellTemplate.setFont(PDType1Font.HELVETICA); - firstColumnCellTemplate.setLeftBorderStyle(thinline); + firstColumnCellTemplate.setBorderStyle(thinline); lastColumnCellTemplate.setFillColor(new Color(242, 242, 242)); lastColumnCellTemplate.setTextColor(Color.BLACK); lastColumnCellTemplate.setFont(PDType1Font.HELVETICA); - lastColumnCellTemplate.setLeftBorderStyle(thinline); + lastColumnCellTemplate.setBorderStyle(thinline); } From fe132f643585bac2ed2744a82970acb7f56c28d8 Mon Sep 17 00:00:00 2001 From: Dries Horions Date: Sun, 3 Apr 2016 12:48:51 +0200 Subject: [PATCH 10/19] Implement List to pdf table --- .../be/quodlibet/boxable/csv/CSVTable.java | 40 +++++++++++++++++ .../java/be/quodlibet/boxable/CSVTest.java | 43 +++++++++++++++++++ 2 files changed, 83 insertions(+) diff --git a/src/main/java/be/quodlibet/boxable/csv/CSVTable.java b/src/main/java/be/quodlibet/boxable/csv/CSVTable.java index 64e842e8..d1ad7f42 100644 --- a/src/main/java/be/quodlibet/boxable/csv/CSVTable.java +++ b/src/main/java/be/quodlibet/boxable/csv/CSVTable.java @@ -11,6 +11,7 @@ import java.awt.Color; import java.io.IOException; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVParser; @@ -176,6 +177,45 @@ public Cell getLastColumnCellTemplate() return lastColumnCellTemplate; } + /** + *

+ * Add a List of Lists to the Table + *

+ * + * @param data + * @param hasHeader + * @param separator + * @throws IOException + */ + public void addListToTable(List data, Boolean hasHeader) throws IOException + { + char separator = ';'; + if (data == null || data.isEmpty()) { + return; + } + String output = ""; + //Convert Map of arbitrary objects to a csv String + for (List inputList : data) { + for (Object v : inputList) { + String value = v.toString(); + if (value.contains("" + separator)) { + //surround value with quotes if it contains the escape character + value = "\"" + value + "\""; + } + output += value + separator; + } + //remove the last separator + output = removeLastChar(output); + output += "\n"; + } + addCsvToTable(output, hasHeader, separator); + + } + + private static String removeLastChar(String str) + { + return str.substring(0, str.length() - 1); + } /** *

* Add a String representing a CSV document to the Table diff --git a/src/test/java/be/quodlibet/boxable/CSVTest.java b/src/test/java/be/quodlibet/boxable/CSVTest.java index 3e54eb88..b5a5cad5 100644 --- a/src/test/java/be/quodlibet/boxable/CSVTest.java +++ b/src/test/java/be/quodlibet/boxable/CSVTest.java @@ -7,6 +7,9 @@ import java.io.IOException; import java.io.InputStream; import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import org.apache.commons.io.IOUtils; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; @@ -48,6 +51,46 @@ public void tearDown() { } + @Test + public void listTestLandscape() throws IOException + { + + + + //Initialize Document + PDDocument doc = new PDDocument(); + PDPage page = new PDPage(); + //Create a landscape page + page.setMediaBox(new PDRectangle(PDRectangle.A4.getHeight(), PDRectangle.A4.getWidth())); + doc.addPage(page); + //Initialize table + float margin = 10; + float tableWidth = page.getMediaBox().getWidth() - (2 * margin); + float yStartNewPage = page.getMediaBox().getHeight() - (2 * margin); + float yStart = yStartNewPage; + float bottomMargin = 0; + + //Create the data + List data = new ArrayList(); + data.add(new ArrayList<>( + Arrays.asList("Column One", "Column Two", "Column Three", "Column Four", "Column Five"))); + for (int i = 1; i <= 100; i++) { + data.add(new ArrayList<>( + Arrays.asList("Row " + i + " Col One", "Row " + i + " Col Two", "Row " + i + " Col Three", "Row " + i + " Col Four", "Row " + i + " Col Five"))); + } + + BaseTable dataTable = new BaseTable(yStart, yStartNewPage, bottomMargin, tableWidth, margin, doc, page, true, + true); + CSVTable t = new CSVTable(dataTable, page); + t.addListToTable(data, CSVTable.HASHEADER); + dataTable.draw(); + File file = new File("target/ListExampleLandscape.pdf"); + System.out.println("Sample file saved at : " + file.getAbsolutePath()); + Files.createParentDirs(file); + doc.save(file); + doc.close(); + } + @Test public void csvTestColWidths() throws IOException { From 63620ff58d4d28a2bd348d1d941c13c6aad51b8d Mon Sep 17 00:00:00 2001 From: Dries Horions Date: Mon, 4 Apr 2016 06:36:48 +0200 Subject: [PATCH 11/19] scope for commons-csv in pom --- pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pom.xml b/pom.xml index a5c243c6..b999b987 100644 --- a/pom.xml +++ b/pom.xml @@ -43,6 +43,7 @@ org.apache.commons commons-csv 1.1 + compile From 6d431d4ec586763f9cc05a0047a4c27c54943caa Mon Sep 17 00:00:00 2001 From: Dries Horions Date: Mon, 4 Apr 2016 06:40:19 +0200 Subject: [PATCH 12/19] commons-csv 1.2 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b999b987..d58b3a18 100644 --- a/pom.xml +++ b/pom.xml @@ -42,7 +42,7 @@ org.apache.commons commons-csv - 1.1 + 1.2 compile From 5ce13fcb73eb9c4b8e44ee80549ba904ae358017 Mon Sep 17 00:00:00 2001 From: Dries Horions Date: Mon, 4 Apr 2016 15:12:48 +0200 Subject: [PATCH 13/19] rename csvTable to dataTable & fix issues with first and last column --- src/main/java/be/quodlibet/boxable/Cell.java | 51 +++++++++++++++++-- .../DataTable.java} | 38 ++++++-------- .../be/quodlibet/boxable/line/LineStyle.java | 42 ++++++++++++--- .../{CSVTest.java => DataTableTest.java} | 30 +++++------ 4 files changed, 114 insertions(+), 47 deletions(-) rename src/main/java/be/quodlibet/boxable/{csv/CSVTable.java => datatable/DataTable.java} (89%) rename src/test/java/be/quodlibet/boxable/{CSVTest.java => DataTableTest.java} (93%) diff --git a/src/main/java/be/quodlibet/boxable/Cell.java b/src/main/java/be/quodlibet/boxable/Cell.java index 0527c148..54a4ff78 100644 --- a/src/main/java/be/quodlibet/boxable/Cell.java +++ b/src/main/java/be/quodlibet/boxable/Cell.java @@ -45,8 +45,8 @@ public class Cell { private boolean textRotated = false; - private final HorizontalAlignment align; - private final VerticalAlignment valign; + private HorizontalAlignment align; + private VerticalAlignment valign; float horizontalFreeSpace = 0; float verticalFreeSpace = 0; @@ -656,6 +656,16 @@ public void setColspanCell(boolean isColspanCell) { this.isColspanCell = isColspanCell; } + public void setAlign(HorizontalAlignment align) + { + this.align = align; + } + + public void setValign(VerticalAlignment valign) + { + this.valign = valign; + } + /** *

* Copies the style of an existing cell to this cell @@ -674,9 +684,44 @@ public void copyCellStyle(Cell sourceCell) this.fontBold = sourceCell.getFontBold(); setFillColor(sourceCell.getFillColor()); setTextColor(sourceCell.getTextColor()); - //setHeight(sourceCell.getHeight()); + setAlign(sourceCell.getAlign()); + setValign(sourceCell.getValign()); + } + /** + *

+ * Compares the style of a cell with another cell + *

+ * + * @param sourceCell + * @return + */ + public Boolean hasSameStyle(Cell sourceCell) + { + if (!sourceCell.getTopBorder().equals(getTopBorder())) { + return false; + } + if (!sourceCell.getFont().equals(getFont())) { + return false; + } + if (!sourceCell.getFontBold().equals(getFontBold())) { + return false; + } + if (!sourceCell.getFillColor().equals(getFillColor())) { + return false; + } + if (!sourceCell.getTextColor().equals(getTextColor())) { + return false; + } + if (!sourceCell.getAlign().equals(getAlign())) { + return false; + } + if (!sourceCell.getValign().equals(getValign())) { + return false; + } + return true; } + public void setWidth(float width) { this.width = width; diff --git a/src/main/java/be/quodlibet/boxable/csv/CSVTable.java b/src/main/java/be/quodlibet/boxable/datatable/DataTable.java similarity index 89% rename from src/main/java/be/quodlibet/boxable/csv/CSVTable.java rename to src/main/java/be/quodlibet/boxable/datatable/DataTable.java index d1ad7f42..c286b3b6 100644 --- a/src/main/java/be/quodlibet/boxable/csv/CSVTable.java +++ b/src/main/java/be/quodlibet/boxable/datatable/DataTable.java @@ -1,4 +1,4 @@ -package be.quodlibet.boxable.csv; +package be.quodlibet.boxable.datatable; import be.quodlibet.boxable.BaseTable; import be.quodlibet.boxable.Cell; @@ -25,7 +25,7 @@ * * @author Dries Horions */ -public class CSVTable +public class DataTable { public static final Boolean HASHEADER = true; public static final Boolean NOHEADER = false; @@ -35,6 +35,7 @@ public class CSVTable private Cell dataCellTemplateOdd; private Cell firstColumnCellTemplate; private Cell lastColumnCellTemplate; + private Cell defaultCellTemplate; /** *

@@ -46,7 +47,7 @@ public class CSVTable * @param page * @throws IOException */ - public CSVTable(Table table, PDPage page) throws IOException + public DataTable(Table table, PDPage page) throws IOException { this.table = table; //Create a dummy pdf document, page and table to create template cells @@ -63,6 +64,7 @@ public CSVTable(Table table, PDPage page) throws IOException dataCellTemplateOdd = dr.createCell(10f, "A", HorizontalAlignment.LEFT, VerticalAlignment.MIDDLE); firstColumnCellTemplate = dr.createCell(10f, "A", HorizontalAlignment.LEFT, VerticalAlignment.MIDDLE); lastColumnCellTemplate = dr.createCell(10f, "A", HorizontalAlignment.LEFT, VerticalAlignment.MIDDLE); + defaultCellTemplate = dr.createCell(10f, "A", HorizontalAlignment.LEFT, VerticalAlignment.MIDDLE); setDefaultStyles(); ddoc.close(); } @@ -81,25 +83,15 @@ private void setDefaultStyles() headerCellTemplate.setBorderStyle(thinline); //Normal cell style, all rows and columns are the same by default - dataCellTemplateEven.setFillColor(new Color(242, 242, 242)); - dataCellTemplateEven.setTextColor(Color.BLACK); - dataCellTemplateEven.setFont(PDType1Font.HELVETICA); - dataCellTemplateEven.setBorderStyle(thinline); + defaultCellTemplate.setFillColor(new Color(242, 242, 242)); + defaultCellTemplate.setTextColor(Color.BLACK); + defaultCellTemplate.setFont(PDType1Font.HELVETICA); + defaultCellTemplate.setBorderStyle(thinline); - dataCellTemplateOdd.setFillColor(new Color(242, 242, 242)); - dataCellTemplateOdd.setTextColor(Color.BLACK); - dataCellTemplateOdd.setFont(PDType1Font.HELVETICA); - dataCellTemplateOdd.setBorderStyle(thinline); - - firstColumnCellTemplate.setFillColor(new Color(242, 242, 242)); - firstColumnCellTemplate.setTextColor(Color.BLACK); - firstColumnCellTemplate.setFont(PDType1Font.HELVETICA); - firstColumnCellTemplate.setBorderStyle(thinline); - - lastColumnCellTemplate.setFillColor(new Color(242, 242, 242)); - lastColumnCellTemplate.setTextColor(Color.BLACK); - lastColumnCellTemplate.setFont(PDType1Font.HELVETICA); - lastColumnCellTemplate.setBorderStyle(thinline); + dataCellTemplateEven.copyCellStyle(defaultCellTemplate); + dataCellTemplateOdd.copyCellStyle(defaultCellTemplate); + firstColumnCellTemplate.copyCellStyle(defaultCellTemplate); + lastColumnCellTemplate.copyCellStyle(defaultCellTemplate); } @@ -285,10 +277,10 @@ public void addCsvToTable(String data, Boolean hasHeader, char separator) throws if (odd) { template = dataCellTemplateOdd; } - if (i == 0) { + if (i == 0 & !firstColumnCellTemplate.hasSameStyle(defaultCellTemplate)) { template = firstColumnCellTemplate; } - if (i == numcols) { + if (i == numcols & !lastColumnCellTemplate.hasSameStyle(defaultCellTemplate)) { template = lastColumnCellTemplate; } String cellValue = ""; diff --git a/src/main/java/be/quodlibet/boxable/line/LineStyle.java b/src/main/java/be/quodlibet/boxable/line/LineStyle.java index 6e5b5bb1..361e58d1 100644 --- a/src/main/java/be/quodlibet/boxable/line/LineStyle.java +++ b/src/main/java/be/quodlibet/boxable/line/LineStyle.java @@ -2,13 +2,14 @@ import java.awt.BasicStroke; import java.awt.Color; +import java.util.Objects; /** *

* The LineStyle class defines a basic set of rendering attributes * for lines. *

- * + * * @author hstimac * @author mkuehne * @@ -27,7 +28,7 @@ public class LineStyle { *

* Simple constructor for setting line {@link Color} and line width *

- * + * * @param color * The line {@link Color * @param width @@ -42,7 +43,7 @@ public LineStyle(final Color color, final float width) { *

* Provides ability to produce dotted line. *

- * + * * @param color * The {@link Color} of the line * @param width @@ -61,7 +62,7 @@ public static LineStyle produceDotted(final Color color, final int width) { *

* Provides ability to produce dashed line. *

- * + * * @param color * The {@link Color} of the line * @param width @@ -73,7 +74,7 @@ public static LineStyle produceDashed(final Color color, final int width) { } /** - * + * * @param color * The {@link Color} of the line * @param width @@ -107,6 +108,35 @@ public float[] getDashArray() { public float getDashPhase() { return dashPhase; - } + } + + @Override + public int hashCode() + { + int hash = 7; + hash = 89 * hash + Objects.hashCode(this.color); + hash = 89 * hash + Float.floatToIntBits(this.width); + return hash; + } + + @Override + public boolean equals(Object obj) + { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final LineStyle other = (LineStyle) obj; + if (!Objects.equals(this.color, other.color)) { + return false; + } + if (Float.floatToIntBits(this.width) != Float.floatToIntBits(other.width)) { + return false; + } + return true; + } + } diff --git a/src/test/java/be/quodlibet/boxable/CSVTest.java b/src/test/java/be/quodlibet/boxable/DataTableTest.java similarity index 93% rename from src/test/java/be/quodlibet/boxable/CSVTest.java rename to src/test/java/be/quodlibet/boxable/DataTableTest.java index b5a5cad5..9ba9256e 100644 --- a/src/test/java/be/quodlibet/boxable/CSVTest.java +++ b/src/test/java/be/quodlibet/boxable/DataTableTest.java @@ -1,6 +1,6 @@ package be.quodlibet.boxable; -import be.quodlibet.boxable.csv.CSVTable; +import be.quodlibet.boxable.datatable.DataTable; import com.google.common.io.Files; import java.awt.Color; import java.io.File; @@ -24,10 +24,10 @@ * * @author Dries Horions */ -public class CSVTest +public class DataTableTest { - public CSVTest() + public DataTableTest() { } @@ -81,8 +81,8 @@ public void listTestLandscape() throws IOException BaseTable dataTable = new BaseTable(yStart, yStartNewPage, bottomMargin, tableWidth, margin, doc, page, true, true); - CSVTable t = new CSVTable(dataTable, page); - t.addListToTable(data, CSVTable.HASHEADER); + DataTable t = new DataTable(dataTable, page); + t.addListToTable(data, DataTable.HASHEADER); dataTable.draw(); File file = new File("target/ListExampleLandscape.pdf"); System.out.println("Sample file saved at : " + file.getAbsolutePath()); @@ -110,8 +110,8 @@ public void csvTestColWidths() throws IOException BaseTable dataTable = new BaseTable(yStart, yStartNewPage, bottomMargin, tableWidth, margin, doc, page, true, true); - CSVTable t = new CSVTable(dataTable, page); - t.addCsvToTable(data, CSVTable.HASHEADER, ';'); + DataTable t = new DataTable(dataTable, page); + t.addCsvToTable(data, DataTable.HASHEADER, ';'); dataTable.draw(); File file = new File("target/CSVexampleColWidths.pdf"); System.out.println("Sample file saved at : " + file.getAbsolutePath()); @@ -137,8 +137,8 @@ public void csvTestPortrait() throws IOException BaseTable dataTable = new BaseTable(yStart, yStartNewPage, bottomMargin, tableWidth, margin, doc, page, true, true); - CSVTable t = new CSVTable(dataTable, page); - t.addCsvToTable(data, CSVTable.HASHEADER, ';'); + DataTable t = new DataTable(dataTable, page); + t.addCsvToTable(data, DataTable.HASHEADER, ';'); dataTable.draw(); File file = new File("target/CSVexamplePortrait.pdf"); System.out.println("Sample file saved at : " + file.getAbsolutePath()); @@ -166,8 +166,8 @@ public void csvTestLandscape() throws IOException BaseTable dataTable = new BaseTable(yStart, yStartNewPage, bottomMargin, tableWidth, margin, doc, page, true, true); - CSVTable t = new CSVTable(dataTable, page); - t.addCsvToTable(data, CSVTable.HASHEADER, ';'); + DataTable t = new DataTable(dataTable, page); + t.addCsvToTable(data, DataTable.HASHEADER, ';'); dataTable.draw(); File file = new File("target/CSVexampleLandscape.pdf"); System.out.println("Sample file saved at : " + file.getAbsolutePath()); @@ -205,8 +205,8 @@ public void csvTestSimple() throws IOException Cell c2 = h2.createCell(100, "Eur per kWh for Medium Size Households.
Source http://ec.europa.eu/eurostat/tgm/table.do?tab=table&init=1&plugin=1&language=en&pcode=ten00117"); c2.setFillColor(new Color(175, 212, 224)); dataTable.addHeaderRow(h2); - CSVTable t = new CSVTable(dataTable, page); - t.addCsvToTable(data, CSVTable.HASHEADER, ';'); + DataTable t = new DataTable(dataTable, page); + t.addCsvToTable(data, DataTable.HASHEADER, ';'); dataTable.draw(); File file = new File("target/CSVexampleSimple.pdf"); System.out.println("Sample file saved at : " + file.getAbsolutePath()); @@ -245,7 +245,7 @@ public void csvTestAdvanced() throws IOException Cell c2 = h2.createCell(100, "Eur per kWh for Medium Size Households.
Source http://ec.europa.eu/eurostat/tgm/table.do?tab=table&init=1&plugin=1&language=en&pcode=ten00117"); c2.setFillColor(new Color(175, 212, 224)); dataTable.addHeaderRow(h2); - CSVTable t = new CSVTable(dataTable, page); + DataTable t = new DataTable(dataTable, page); //set the style template for header cells t.getHeaderCellTemplate().setFillColor(new Color(13, 164, 214)); //set the style template for first column @@ -256,7 +256,7 @@ public void csvTestAdvanced() throws IOException t.getDataCellTemplateEven().setFillColor(Color.WHITE); t.getDataCellTemplateOdd().setFillColor(new Color(250, 242, 242)); - t.addCsvToTable(data, CSVTable.HASHEADER, ';'); + t.addCsvToTable(data, DataTable.HASHEADER, ';'); dataTable.draw(); File file = new File("target/CSVexampleAdvanced.pdf"); From 62922dcdca22d67c87dd6d4d1aac3b0a800d0379 Mon Sep 17 00:00:00 2001 From: Dries Horions Date: Tue, 5 Apr 2016 08:11:41 +0200 Subject: [PATCH 14/19] make a few attributes final --- pom.xml | 2 -- .../be/quodlibet/boxable/datatable/DataTable.java | 13 ++++++------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index d58b3a18..17f5da05 100644 --- a/pom.xml +++ b/pom.xml @@ -25,8 +25,6 @@ 2.0.0 compile - - org.slf4j slf4j-api diff --git a/src/main/java/be/quodlibet/boxable/datatable/DataTable.java b/src/main/java/be/quodlibet/boxable/datatable/DataTable.java index c286b3b6..775074f6 100644 --- a/src/main/java/be/quodlibet/boxable/datatable/DataTable.java +++ b/src/main/java/be/quodlibet/boxable/datatable/DataTable.java @@ -30,12 +30,12 @@ public class DataTable public static final Boolean HASHEADER = true; public static final Boolean NOHEADER = false; private Table table; - private Cell headerCellTemplate; - private Cell dataCellTemplateEven; - private Cell dataCellTemplateOdd; - private Cell firstColumnCellTemplate; - private Cell lastColumnCellTemplate; - private Cell defaultCellTemplate; + private final Cell headerCellTemplate; + private final Cell dataCellTemplateEven; + private final Cell dataCellTemplateOdd; + private final Cell firstColumnCellTemplate; + private final Cell lastColumnCellTemplate; + private final Cell defaultCellTemplate; /** *

@@ -201,7 +201,6 @@ public void addListToTable(List data, Boolean hasHeader) throws IOExceptio output += "\n"; } addCsvToTable(output, hasHeader, separator); - } private static String removeLastChar(String str) From 994d714917751338421ae7c8071d7ea068f71bae Mon Sep 17 00:00:00 2001 From: Dries Horions Date: Tue, 5 Apr 2016 08:39:51 +0200 Subject: [PATCH 15/19] prepare for version 1.4 --- README.md | 102 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 68 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index bd646925..47db6965 100644 --- a/README.md +++ b/README.md @@ -1,52 +1,86 @@ -boxable +[Boxable](http://dhorions.github.io/boxable/) - A java library to build tables in PDF documents. ======= -http://dhorions.github.io/boxable/ -Create tables in pdf documents using [PDFBox](http://pdfbox.apache.org) -Here are a few examples of the type of tables boxable can created : +Boxable is a library that can be used to easily create tables in pdf documents. It uses the [PDFBox](https://pdfbox.apache.org/) PDF library under the hood. -* [Table with text and images](https://s3.amazonaws.com/misc.quodlibet.be/Boxable/BoxableSample1.pdf) -![alt text](https://s3.amazonaws.com/misc.quodlibet.be/Boxable/sample1_preview.png) -* [Vertical and Horizontal text](https://s3.amazonaws.com/misc.quodlibet.be/Boxable/BoxableSample3.pdf) -![alt text](https://s3.amazonaws.com/misc.quodlibet.be/Boxable/sample3_preview.png) - - -Example code can be found [here](https://github.com/dhorions/boxable/blob/master/src/test/java/be/quodlibet/boxable/TableTest.java) - -The project is Java 7 compliant. - -Maven : -The project can be used as a Maven dependency : +# Maven ```xml com.github.dhorions boxable - 1.3 + 1.4 ``` +For other build systems, check the [Maven Central Repository](http://search.maven.org/#search%7Cga%7C1%7Ca%3A%22boxable%22). +# Features -The project can also be used as a Maven dependency by using jitpack.io. -* add the repository : -```xml - - jitpack.io - https://jitpack.io - +- Build tables in pdf documents +- Convert csv data into tables in pdf documents +- Convert Lists into tables in pdf documents +- +# Tutorial + +A tutorial is being created and will be accessible at http://dhorions.github.io/boxable/ + +# Usage examples + +## Create a pdf from a csv file + +```java +String data = readData("https://s3.amazonaws.com/misc.quodlibet.be/Boxable/Eurostat_Immigration_Applications.csv"); +BaseTable pdfTable = new BaseTable(yStart, yStartNewPage, bottomMargin, tableWidth, margin, doc, page, true,true); +DataTable t = new DataTable(pdfTable, page); +t.addCsvToTable(data, DataTable.HASHEADER, ';'); +pdfTable.draw(); ``` -* add the dependency -```xml - - - com.github.dhorions - boxable - 1.3 - - +Output : [CSVExamplePortrait.pdf](https://s3.amazonaws.com/misc.quodlibet.be/Boxable/CSVexamplePortrait.pdf) + +## Create a pdf from a List + +```java +List data = new ArrayList(); +data.add(new ArrayList<>( + Arrays.asList("Column One", "Column Two", "Column Three", "Column Four", "Column Five"))); +for (int i = 1; i <= 100; i++) { + data.add(new ArrayList<>( + Arrays.asList("Row " + i + " Col One", "Row " + i + " Col Two", "Row " + i + " Col Three", "Row " + i + " Col Four", "Row " + i + " Col Five"))); +} +``` +Output : [ListExampleLandscape.pdf](https://s3.amazonaws.com/misc.quodlibet.be/Boxable/ListExampleLandscape.pdf) + +##Build tables in pdf documents + +```java +BaseTable table = new BaseTable(yStart, yStartNewPage, bottomMargin, tableWidth, margin, doc, page, true, + drawContent); +//Create Header row +Row headerRow = table.createRow(15f); +Cell cell = headerRow.createCell(100, "Awesome Facts About Belgium"); +cell.setFont(PDType1Font.HELVETICA_BOLD); +cell.setFillColor(Color.BLACK); +table.addHeaderRow(headerRow); +List facts = getFacts(); +for (String[] fact : facts) { + Row row = table.createRow(10f); + cell = row.createCell((100 / 3.0f) * 2, fact[0] ); + for (int i = 1; i < fact.length; i++) { + cell = row.createCell((100 / 9f), fact[i]); + } +} +table.draw(); ``` -Special Thanks to [dgautier](https://github.com/dgautier),[ZeerDonker](https://github.com/ZeerDonker),[Frulenzo](https://github.com/Frulenzo),[dobluth](https://github.com/dobluth) and [schmitzhermes](https://github.com/schmitzhermes) for their valuable contributions. + + + +Special Thanks to these awesome contributers : +- [dgautier](https://github.com/dgautier) +- [ZeerDonker](https://github.com/ZeerDonker) +- [Frulenzo](https://github.com/Frulenzo) +- [dobluth](https://github.com/dobluth) +- [schmitzhermes](https://github.com/schmitzhermes) ======= From ae2fe1fbbd6870a97b11e862bec1cb5ee148277b Mon Sep 17 00:00:00 2001 From: Dries Horions Date: Tue, 5 Apr 2016 08:41:06 +0200 Subject: [PATCH 16/19] Update README.md --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 47db6965..9657e7e1 100644 --- a/README.md +++ b/README.md @@ -19,10 +19,11 @@ For other build systems, check the [Maven Central Repository](http://search.mave - Build tables in pdf documents - Convert csv data into tables in pdf documents - Convert Lists into tables in pdf documents -- + # Tutorial -A tutorial is being created and will be accessible at http://dhorions.github.io/boxable/ +A tutorial is being created and will be accessible at http://dhorions.github.io/boxable/. +If you want to help, please let us know [here](https://github.com/dhorions/boxable/issues/41). # Usage examples From 82b26f522aa96f2c087bc580ed2f981cdf8d2017 Mon Sep 17 00:00:00 2001 From: Dries Horions Date: Tue, 5 Apr 2016 08:43:19 +0200 Subject: [PATCH 17/19] 1.4 prep --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9657e7e1..9eed73e9 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,10 @@ data.add(new ArrayList<>( for (int i = 1; i <= 100; i++) { data.add(new ArrayList<>( Arrays.asList("Row " + i + " Col One", "Row " + i + " Col Two", "Row " + i + " Col Three", "Row " + i + " Col Four", "Row " + i + " Col Five"))); +BaseTable dataTable = new BaseTable(yStart, yStartNewPage, bottomMargin, tableWidth, margin, doc, page, true, true); +DataTable t = new DataTable(dataTable, page); +t.addListToTable(data, DataTable.HASHEADER); +dataTable.draw(); } ``` Output : [ListExampleLandscape.pdf](https://s3.amazonaws.com/misc.quodlibet.be/Boxable/ListExampleLandscape.pdf) @@ -85,7 +89,7 @@ Special Thanks to these awesome contributers : ======= -Copyright [2016] [Quodlibet.be] +Copyright [2016](Quodlibet.be) Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From 19868c96c4c3be119828ba013dc0ba91603efc9d Mon Sep 17 00:00:00 2001 From: Dries Horions Date: Tue, 5 Apr 2016 08:43:44 +0200 Subject: [PATCH 18/19] 1.4 prep --- README.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 9eed73e9..5ec609d1 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,13 @@ Boxable is a library that can be used to easily create tables in pdf documents. It uses the [PDFBox](https://pdfbox.apache.org/) PDF library under the hood. +# Features + +- Build tables in pdf documents +- Convert csv data into tables in pdf documents +- Convert Lists into tables in pdf documents + + # Maven ```xml @@ -14,11 +21,6 @@ Boxable is a library that can be used to easily create tables in pdf documents. ``` For other build systems, check the [Maven Central Repository](http://search.maven.org/#search%7Cga%7C1%7Ca%3A%22boxable%22). -# Features - -- Build tables in pdf documents -- Convert csv data into tables in pdf documents -- Convert Lists into tables in pdf documents # Tutorial From d7d96031f764f7323392e1279853bc9928cbc3e2 Mon Sep 17 00:00:00 2001 From: Dries Horions Date: Tue, 5 Apr 2016 08:54:59 +0200 Subject: [PATCH 19/19] update version to 1.4 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 17f5da05..69694ba6 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ 4.0.0 com.github.dhorions boxable - 1.4-SNAPSHOT + 1.4 jar Boxable, a high-level API to creates table on top of Apache Pdfbox