Coder Social home page Coder Social logo

easytable's Introduction

easytable

This is a small project that builds upon Apache's PDFBox (>= 3.0.0) and should allow you to create tables in a fairly simple way. It emerged from the need in another project. Therefore, it also may miss some crucial features. Nevertheless, there is:

  • setting font and font size, table, row, column and cell level
  • line breaking and line spacing
  • background color and style on table, row, column and cell level
  • padding (top, bottom, left, right) on table, row and cell level
  • border color, width and style (on table, row or cell level)
  • support for text alignment (right, left, center, justified)
  • vertical text alignment (top, middle, bottom)
  • column spanning and row spanning
  • images in cells
  • allowing for a lot of customizations
  • experimental: vertical text, drawing a large table's overflow on the same page

One can also override classes that are responsible for table/cell drawing, i.e. their drawing behaviour can be customized to a pretty high extent.

It is also possible to draw a table over multiple pages (even with the header row being repeated on every new page) or to draw a large table's overflow next to the already existing table on the same page (see below for examples).

Installation

Add this to your pom.xml:

<dependency>
    <groupId>com.github.vandeseer</groupId>
    <artifactId>easytable</artifactId>
    <version>1.0.2</version>
</dependency>

Or checkout the repository and install it locally with maven (e.g. for thedevelop branch):

mvn clean install -DskipTests -Dgpg.skip -Ddependency-check.skip=true

Examples

There is a minimal full working example which should help you to get started.

For a bit more involved tables have a look at this code which is needed for creating a PDF document with the following two tables:

easytable table

easytable table

For the next example have a look at the SettingsTest.java:

easytable table

The last one illustrates the use of vertical text in text cells. The code for it can be found here:

easytable table

Drawing the overflow of a large table on the same page is also possible:

easytable table

If you run the tests with mvn clean test there also some PDF documents created which you can find in the target folder. The corresponding sources (in order to understand how to use the code) can be found in the test package.

Kudos

  • to Binghammer for implementing cell coloring and text center alignment
  • to Sebastian Göhring for finding and fixing a bug (column spanning)
  • to AndreKoepke for the line breaking feature, some bigger nice refactorings and improvements
  • to Wolfgang Apolinarski for the printing over pages and bugfixes
  • to AdrianMiska for finding and fixing an issue with cell height
  • to TheRealSourceSeeker for finding a bug caused by using floats
  • to Drummond Dawson for code changes that allowed removing a dependency
  • to styssi for allowing several multipage tables being drawn on the same page
  • to Richard Mealing for adding the license section to the pom.xml
  • to msww for finding a small issue
  • to VakhoQ for implementing border styles
  • to Miloš Čadek for implementing alignment of vertical text cells
  • to Chemmic for adding repeating headers to tables that overflow on the same page

Q&A

Can I use the library with version PDFBox 2.x.x?

Every version of easytable < 1.0.0 is built on PDFBox 2.x.x.

Note that easytable 1.0.0 and below do basically only differ in the support PDFBox version, but not in their feature set. Only exception being the experimental support for paragraph cells which had to be dropped with the upgrade to PDFBox 3.

Also note that easytable >= 1.0.0 is built for Java 11 and higher, whereas lower versions are using Java 8.

Can I customize the drawers for my own specific needs?

Yep, you can customize the cell drawers itself or (depending on your use case) you can just create a custom cell.

For using a customized cell drawer, have a look at CustomCellDrawerTest.

In case you want to create your own type of cell (which shouldn't really be necessary since the drawing can be completely adapted) you will need to use Lombok's @SuperBuilder annotation. Again, just have a look at the code: CustomCellWithCustomDrawerUsingLombokTest

Can I draw a table over multiple pages?

Yes, have a look at TableOverSeveralPagesTest.java. Just use startY(...) and endY(..) in order to restrict the vertical part of the page where the table should be drawn:

RepeatedHeaderTableDrawer.builder()
    .table(createTable())
    .startX(50)
    .startY(100F)
    .endY(50F) // <-- If the table is bigger, a new page is started
    .build()

Is there a way to repeat the header on every page?

Depending on whether you want to repeat the header row or not you should use RepeatedHeaderTableDrawer or TableDrawer respectively.

Can I get the y coordinate of the end of a drawn table?

Yes. Just use the .getFinalY() method. Also see FinalYTest.java.

Cool, I like it, can I buy you a beer?

Yes. Or you can upvote this answer on stackoverflow. Or:

Donate with PayPal

easytable's People

Contributors

andrekoepke avatar dependabot[bot] avatar drumonii avatar grass-hopper-moc avatar mealingr avatar styssi avatar vakhoq avatar vandeseer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

easytable's Issues

There Seems To Be No Way of Creating a Multipage Table Starting On Existing Page

According to your integration test, the way to draw a multipage table is:

/* builder details here */
.draw(() -> document, () -> new PDPage(PDRectangle.A4), 50f);

But this seems to call a new page for every section of the table. On the other hand, if I list an existing page, the table will just overwrite the same page. Would it be too hard to provide a function or class that takes two PDPage objects? The first would be the initial page the table starts in. The second would be a constructor for any table overflow (preferably, the new pages would be inserted in between existing pages if, for example, you wanted a table to be inserted in a document on page 2, with the document already containing 3 pages). For example:

/* builder details here */
.draw(() -> document, () -> existingPage, () -> new PDPage(PDRectangle.A4), 50f);

Allow images to be added in cells

One of doing this could be to register a callback with the content stream so that the users of the library could place the image themselves.

How to draw text or small rectangle within ImageCell

I have a requirement where I need to draw text or small rectangle/circle/square within imageCell.
PS - the data will be dynamic... please see below sample images which i am trying to build. As of now I am able to add background images as ImageCell is easytable.

Please let me know your inputs.
e.g
image

image

Vertical Alignment within a row (Feature)

Hey vandeseer,
many thanks for your little project. At the moment I´m trying to use the easytable for the first time. I need to create a table over several pages and with pdfarcform in it.

I played around with your .setWordBreaking() function. It would be great if it would be possible to use a vertical alignment within a row, if the wordbreaking feature is used.

I attached an image regarding this topic.

Best regards

Kevin

vertical_align

Problem with cell - one of them is empty

My code:

        final TableBuilder tableBuilder = Table.builder()
                .addColumnsOfWidth(35, 92, 50, 50, 72, 240)
                .fontSize(8)
                .font(HELVETICA)
                .borderColor(Color.BLACK);

        tableBuilder.addRow(Row.builder()
                .add(TextCell.builder().text("XXXXXXXXX")
                        .colSpan(4)
                        .lineSpacing(1f)
                        .borderWidthTop(1)
                        .textColor(Color.BLACK)
                        .backgroundColor(Color.RED)
                        .fontSize(14)
                        .font(PDType1Font.HELVETICA_BOLD)
                        .verticalAlignment(VerticalAlignment.MIDDLE)
                        .horizontalAlignment(CENTER)
                        .borderWidth(1)
                        .build())
                .add(TextCell.builder().text("YYY YYY")
                        .colSpan(2)
                        .textColor(Color.BLACK)
                        .backgroundColor(Color.RED)
                        .fontSize(11)
                        .font(PDType1Font.HELVETICA_BOLD)
                        .verticalAlignment(VerticalAlignment.MIDDLE)
                        .horizontalAlignment(CENTER)
                        .borderWidth(1)
                        .build())
                .horizontalAlignment(LEFT)
                .build());

        tableBuilder.addRow(Row.builder()
                .add(TextCell.builder().text("#")
                        .rowSpan(3)
                        .lineSpacing(1f)
                        .borderWidthTop(1)
                        .textColor(Color.BLACK)
                        .backgroundColor(GRAY_LIGHT_3)
                        .fontSize(8)
                        .font(PDType1Font.HELVETICA_BOLD)
                        .verticalAlignment(VerticalAlignment.MIDDLE)
                        .horizontalAlignment(CENTER)
                        .borderWidth(1)
                        .build())
                .add(TextCell.builder().text("CCC")
                        .rowSpan(3)
                        .textColor(Color.BLACK)
                        .backgroundColor(GRAY_LIGHT_3)
                        .fontSize(8)
                        .font(PDType1Font.HELVETICA_BOLD)
                        .verticalAlignment(VerticalAlignment.MIDDLE)
                        .horizontalAlignment(CENTER)
                        .borderWidth(1)
                        .build())
                .add(TextCell.builder().text("QWERTY")
                        .colSpan(3)
                        .textColor(Color.BLACK)
                        .backgroundColor(Color.YELLOW)
                        .fontSize(10)
                        .font(PDType1Font.HELVETICA_BOLD)
                        .verticalAlignment(VerticalAlignment.MIDDLE)
                        .horizontalAlignment(CENTER)
                        .borderWidth(1)
                        .build())
                .add(TextCell.builder().text("John Black")
                        .textColor(Color.BLACK)
                        .backgroundColor(Color.YELLOW)
                        .fontSize(8)
                        .verticalAlignment(VerticalAlignment.MIDDLE)
                        .horizontalAlignment(CENTER)
                        .borderWidth(1)
                        .build())
                .horizontalAlignment(LEFT)
                .build());

        tableBuilder.addRow(Row.builder()
                .add(TextCell.builder().text("QQQQ")
                        .colSpan(3)
                        .lineSpacing(1f)
                        .borderWidthTop(1)
                        .textColor(Color.BLACK)
                        .backgroundColor(GRAY_LIGHT_3)
                        .fontSize(8)
                        .font(PDType1Font.HELVETICA_BOLD)
                        .verticalAlignment(VerticalAlignment.MIDDLE)
                        .horizontalAlignment(CENTER)
                        .borderWidth(1)
                        .build())
                .add(TextCell.builder().text("ZZZZZ")
                        .rowSpan(2)
                        .lineSpacing(1f)
                        .borderWidthTop(1)
                        .textColor(Color.BLACK)
                        .backgroundColor(GRAY_LIGHT_3)
                        .fontSize(8)
                        .font(PDType1Font.HELVETICA_BOLD)
                        .verticalAlignment(VerticalAlignment.MIDDLE)
                        .horizontalAlignment(CENTER)
                        .borderWidth(1)
                        .build())
                .horizontalAlignment(LEFT)
                .build());

        tableBuilder.addRow(Row.builder()
                .add(TextCell.builder().text("X")
                        .lineSpacing(1f)
                        .borderWidthTop(1)
                        .textColor(Color.BLACK)
                        .backgroundColor(GRAY_LIGHT_3)
                        .fontSize(8)
                        .font(HELVETICA)
                        .verticalAlignment(VerticalAlignment.MIDDLE)
                        .horizontalAlignment(CENTER)
                        .borderWidth(1)
                        .build())
                .add(TextCell.builder().text("Y")
                        .lineSpacing(1f)
                        .borderWidthTop(1)
                        .textColor(Color.BLACK)
                        .backgroundColor(GRAY_LIGHT_3)
                        .fontSize(8)
                        .font(HELVETICA)
                        .verticalAlignment(VerticalAlignment.MIDDLE)
                        .horizontalAlignment(CENTER)
                        .borderWidth(1)
                        .build())
                .add(TextCell.builder().text("LLLLLLLLLL")
                        .lineSpacing(1f)
                        .borderWidthTop(1)
                        .textColor(Color.BLACK)
                        .backgroundColor(GRAY_LIGHT_3)
                        .fontSize(8)
                        .font(HELVETICA)
                        .verticalAlignment(VerticalAlignment.MIDDLE)
                        .horizontalAlignment(CENTER)
                        .borderWidth(1)
                        .build())
                .horizontalAlignment(LEFT)
                .build());

        return tableBuilder.build();

A1A and accessibility

Hi, I am planning on adding A1A and accessibility to the easytable framework, because I need this. Can you please add a branch for me, I can work on. I would like to push some code in between, instead of pushing everything in the end.

Hyperlink text

Hello, first of all thank you very much for releasing this great library. I wanted to ask if there has been any update on Hyperlink support. I can see in issue #39 that this was mentioned.

Moreover, I am in need also of underlining text so that it looks like a link. Is this currently possible?

Thank you very much.

Publish to jcenter and maven repo

Hello, first of all thanks for this amazing little lib. Do you think it would be possible for you to push this in jcenter and maven ? It would be easier for new versions and maintenance.
Thanks again !

Table always gets added to the last page

The table gets always added to the last page in my implementation.
Is there a way to add the copy of a table to each page? Would be handy to create footers or headers of a document.

val contentStream = PDPageContentStream(
            pdfDocument, pdfDocument.getPage(0),
            PDPageContentStream.AppendMode.APPEND, false, false
        )

        TableDrawer.builder()
            .table(table)
            .startY(yPos)
            .startX(tableRect.lowerLeftX)
            .contentStream(contentStream)
            .build()
            .draw(Supplier<PDDocument> { pdfDocument }, Supplier<PDPage> { PDPage(PDRectangle.A4) }, headerOffset)

Infinite draw loop bug

When a cell in the table of the drawer has text that exceeds the length of the page, then the draw() method never finishes. Edit the TwoPagesTableTest integration test

public class TwoPagesTableTest {

@Test
public void createTwoPageTable() throws IOException {
    final Table.TableBuilder tableBuilder = Table.builder()
            .addColumnOfWidth(200)
            .addColumnOfWidth(200);

    CellText dummyHeaderCell = CellText.builder()
            .text("Header dummy")
            .backgroundColor(Color.BLUE)
            .textColor(Color.WHITE)
            .borderWidth(1F)
            .build();

    String longText = "Sed turpis nisl, ullamcorper vitae ornare eget, porta ac odio. Nunc lacinia convallis urna sit amet scelerisque. Morbi neque est, tempor sit amet sagittis in, luctus et nisl. Phasellus ut mollis felis. Sed viverra tortor in ligula ultricies, quis faucibus turpis varius. Duis ante leo, ornare sed lectus in, finibus placerat est. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Phasellus rhoncus felis sit amet ex consequat aliquam. Ut euismod odio iaculis vulputate malesuada. Donec euismod ipsum id erat ullamcorper elementum. Aenean malesuada mattis libero ac pretium. Nam non tempor risus, in congue turpis. Nam mi dolor, gravida ac imperdiet quis, pulvinar sed metus. Sed tempor orci magna, non aliquet nisl posuere vitae. Cras erat felis, euismod et sodales cursus, fermentum at arcu. Aenean maximus magna vel dignissim ullamcorper.Sed turpis nisl, ullamcorper vitae ornare eget, porta ac odio. Nunc lacinia convallis urna sit amet scelerisque. Morbi neque est, tempor sit amet sagittis in, luctus et nisl. Phasellus ut mollis felis. Sed viverra tortor in ligula ultricies, quis faucibus turpis varius. Duis ante leo, ornare sed lectus in, finibus placerat est. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Phasellus rhoncus felis sit amet ex consequat aliquam. Ut euismod odio iaculis vulputate malesuada. Donec euismod ipsum id erat ullamcorper elementum.";

    CellText dummyCell = CellText.builder()
            .text("dummy")
            .borderWidth(1F)
            .build();


    CellText bigCell = CellText.builder()
            .text(longText)
            .borderWidth(1F)
            .build();

    tableBuilder.addRow(
            Row.builder()
                    .add(dummyHeaderCell)
                    .add(dummyHeaderCell)
                    .build());


        tableBuilder.addRow(
                Row.builder()
                        .add(dummyCell)
                        .add(bigCell)
                        .build());


    final PDDocument document = new PDDocument();

    PDPage page = new PDPage(PDRectangle.A4);
    TableDrawer drawer = TableDrawer.builder()
            .table(tableBuilder.build())
            .startX(50)
            .startY(page.getMediaBox().getHeight() - 50)
            .endY(50F) // note: if not set, table is drawn over the end of the page
            .build();

    do {

        document.addPage(page);
        try (PDPageContentStream contentStream = new PDPageContentStream(document, page)) {
            drawer.contentStream(contentStream).draw();
        }
    } while (!drawer.isFinished());

    document.save("target/twoPageTable.pdf");
    document.close();
}

How to make the font bold in case i use a font other than specified in PDFBOX

Hi,

I am trying to use a different font which is not part of default pdfbox. so loading the ttf file for that font and adding modifying the contentstream to use that font.
but i am not able to make the font bold where needed in tables. like some columns require bold for the same font and some does not. can you tell me if its possible to bold the font (without using existing fonts like times bold) etc

Support of Rectangle in Table Column

I have a requirement where I want to draw rectangle in each column of rows.

e.g. I want to show the estimates and actual hours worked using filled rectangle color (RGB) for each row. In iText this can be achieved using PdfTemplate (rectangle, setRGBColorFill, setRGBColorStroke methods).

How to get the end position of last table in the page?

Hi,
I am trying to add multiple tables appended in the same page.
Because i have a requirement to display the data from multiple table and the fomat for each data is Different, some needs to be written in 2 columns (cannot do the col span because the size of column should be less in this case )and some 4 -5 columns
Is therea way I can get the StartY location from the previous table which is written in page? so that i can append the table at correct location based on that?

How to increase image size when we do col span

Hi,

I have written a table with 4 columns but i have a requirement of that table to sometime display either two or one image in one of the rows.
I do that by doing the col Span if one row then span col to 4 cells. else if two images then span two columns into two cells.
The only problem i am facing here is the size of the image which is coming its very small.

When i create the Table of two columns and use the same image , the image is better but is there a way to increase the width of image in case of Col span as well?

below is part of my code for table and some of the if else conditions for image display:

Table.TableBuilder tableBuilder = Table.builder()
.addColumnOfWidth(145)
.addColumnOfWidth(145)
.addColumnOfWidth(145)
.addColumnOfWidth(145);

if (pdfImage5_4 && pdfImage5_6)
{

        		 tableBuilder.addRow(
 		                Row.builder()
 		                        .add(ImageCell.builder().image(image5_4).maxHeight(2000l).borderWidth(1).horizontalAlignment(HorizontalAlignment.CENTER).colSpan(2).build())
 		                        .add(ImageCell.builder().image(image5_6).maxHeight(2000l).borderWidth(1).horizontalAlignment(HorizontalAlignment.CENTER).colSpan(2).build())
 		                        .build());
        	}

if (pdfImage5_4)
{
tableBuilder.addRow(
Row.builder()
.add(ImageCell.builder().image(image5_4).borderWidth(1).maxHeight(2000l).colSpan(4).horizontalAlignment(HorizontalAlignment.CENTER).build())
.build());
}

if (!(pdfImage5_4) && pdfImage5_6)
{
tableBuilder.addRow(
Row.builder()
.add(TextCell.builder().text(Constants.NOPREVIEWPREUPGRADE).font(TIMES_ROMAN).fontSize(6).borderWidth(1).colSpan(2).horizontalAlignment(HorizontalAlignment.LEFT).build())
.add(ImageCell.builder().image(image5_6).borderWidth(1).maxHeight(2000l).horizontalAlignment(HorizontalAlignment.CENTER).colSpan(2).build())
.build());
}

Bug with span width

Since i cant make a pull request for whatever reason:

Theres a bug in the TableDrawer which causes glitches like this (replace this test with the actual one) :

    @Test
    public void createSampleDocumentWithCellSpanning() throws Exception {
        // Define the table structure first
        TableBuilder tableBuilder = TableBuilder.newBuilder()
                .addColumnOfWidth(300)
                .addColumnOfWidth(120)
                .addColumnOfWidth(70)
                .setFontSize(8)
                .setFont(HELVETICA);

        // Header ...
        tableBuilder.addRow(RowBuilder.newBuilder()
                .add(Cell.withText("This is right aligned without a border").setHorizontalAlignment(RIGHT))
                .add(Cell.withText("Sum")..setBackgroundColor(Color.ORANGE))
                .setBackgroundColor(Color.BLUE)
                .build());

        // Header ...
        tableBuilder.addRow(RowBuilder.newBuilder()
                .add(Cell.withText("This is right aligned without a border").span(2).setHorizontalAlignment(RIGHT))
                .setBackgroundColor(Color.BLUE)
                .build());

        createDocumentWithTable(tableBuilder.build(), "target/sampleWithCellSpanning.pdf");
    }

You see, adding span on the second cell in a row works. But on the first one it turns to a unwanted result.

Simply replace:

columnCounter++;

with

columnCounter += cell.getSpan()

in your drawBackgroundAndText and drawBorders.

Regards

Feature Request - Row spanning

Love the tool, but it would be helpful if it had row spanning. The idea is that a cell could span two or more rows, with alignment of top/middle/bottom for the text that in it. Would also be helpful if text within could be broken across multiple lines.

Allow for easier reuse of classes from outside

Currently easytable is suffering from "excessive data hiding", e.g. you cannot easily subclass the TableDrawer class because its constructor is private. That makes it unnecessary hard or prohibits simple customisations for the library user.

Overlapping borders

I'm facing an issue with borders of different color and width.
The output of the following snippet of code is attached
test.pdf

public static void main(String[] args) {

		try (PDDocument doc = new PDDocument()) {

			String header = "HEADER HEADER HEADER HEADER HEADER HEADER HEADER HEADER HEADER HEADER HEADER HEADER HEADER HEADER HEADER HEADER "
					+ "HEADER HEADER HEADER HEADER HEADER HEADER HEADER HEADER HEADER HEADER HEADER HEADER HEADER HEADER HEADER HEADER "
					+ "HEADER HEADER HEADER HEADER HEADER HEADER HEADER HEADER HEADER HEADER HEADER HEADER HEADER HEADER HEADER HEADER "
					+ "HEADER HEADER HEADER HEADER HEADER HEADER HEADER HEADER HEADER HEADER HEADER HEADER HEADER HEADER HEADER HEADER ";

					PDPage page = new PDPage();
				    doc.addPage( page );
				    
			        final TableBuilder tableBuilder = Table.builder()
			                .addColumnsOfWidth(250, 250);
			        final org.vandeseer.easytable.structure.Row headerRow = org.vandeseer.easytable.structure.Row.builder()
			                .add(CellText.builder().text(header).horizontalAlignment(CENTER).colSpan(2).borderColor(Color.BLACK).borderWidth(1).build())
			                .backgroundColor(Color.WHITE)
			                .textColor(Color.BLACK)
			                .font(PDType1Font.HELVETICA_BOLD)
			                .fontSize(11)
			                .build();
			        tableBuilder.addRow(headerRow);


					
					for (int row = 0; row < 10 ; row++) {

				        final org.vandeseer.easytable.structure.Row dataRow = org.vandeseer.easytable.structure.Row.builder()
				                .add(CellText.builder()
				                		.text("Name"+row)
				                		.horizontalAlignment(LEFT)
				                		.backgroundColor(Color.WHITE)
				                		.textColor(Color.BLACK)
				                		.borderColor(Color.WHITE)
				                		.borderWidth(0.5f).build())
				                .add(CellText.builder()
				                		.text("Value"+row)
				                		.horizontalAlignment(RIGHT)
				                		.backgroundColor(Color.CYAN)
				                		.textColor(Color.BLUE)
				                		.borderColor(Color.BLACK)
				                		.borderWidth(0.5f).build())
				                
				                .font(PDType1Font.HELVETICA_BOLD)
				                .fontSize(9)
				                .build();
				        tableBuilder.addRow(dataRow);
				        final org.vandeseer.easytable.structure.Row spareRow = org.vandeseer.easytable.structure.Row.builder()
				                .add(CellText.builder()
				                		.text("Spare"+row)
				                		.horizontalAlignment(LEFT)
				                		.backgroundColor(Color.WHITE)
				                		.textColor(Color.BLACK)
				                		.font(PDType1Font.HELVETICA_OBLIQUE)
				                		.borderColor(Color.WHITE)
				                		.borderWidth(1).build())
				                .add(CellText.builder()
				                		.text("")
				                		.horizontalAlignment(RIGHT)
				                		.backgroundColor(Color.WHITE)
				                		.textColor(Color.BLUE)
				                		.borderColor(Color.WHITE)
				                		.borderWidth(1).build())
				                
				                .font(PDType1Font.HELVETICA_BOLD).fontSize(9)
				                .build();
				        tableBuilder.addRow(spareRow);
					}
					String footer = "FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER "
							+ "FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER "
							+ "FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER "
							+ "FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER FOOTER ";
			        final org.vandeseer.easytable.structure.Row footerRow = org.vandeseer.easytable.structure.Row.builder()
			                .add(CellText.builder().text(footer).horizontalAlignment(CENTER).colSpan(2).borderWidth(1).build())
			                .backgroundColor(TURQUOISE)
			                .textColor(Color.BLACK)
			                .font(PDType1Font.HELVETICA_BOLD).fontSize(9)
			                .build();
			        tableBuilder.addRow(footerRow);
			        try (final PDPageContentStream contentStream = new PDPageContentStream(doc, page)) {

						float startY = page.getMediaBox().getHeight() - PADDING;
						Table pdfTable = tableBuilder.build();
		                TableDrawer.builder()
		                        .contentStream(contentStream)
		                        .table(pdfTable)
		                        .startX(PADDING)
		                        .startY(startY)
		                        .build()
		                        .draw();

			        }
			        String fileName="test.pdf";
			doc.save(fileName);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

the upper white border of the first name cell, falls in the middle of the thicker black header border, while the upper white border of spare rows hides the lower black border of value cells.
Is this a real issue or am I doing something wrong?

Enabling WordBreak on Tables causes a Stackoverflow on cells with only a single character

When you have single character CellTexts WordBreak breaks (haha.) .

How to reproduce:

Create a cell with only one single CellText. Causes this StackoverflowError:

Exception in thread "JavaFX Application Thread" java.lang.StackOverflowError
	at java.util.concurrent.ConcurrentHashMap.get(ConcurrentHashMap.java:936)
	at org.apache.pdfbox.pdmodel.font.PDType1Font.encode(PDType1Font.java:412)
	at org.apache.pdfbox.pdmodel.font.PDFont.encode(PDFont.java:324)
	at org.apache.pdfbox.pdmodel.font.PDFont.getStringWidth(PDFont.java:353)
	at org.vandeseer.pdfbox.easytable.util.PdfUtil.getStringWidth(PdfUtil.java:27)
	at org.vandeseer.pdfbox.easytable.util.PdfUtil.isLineFine(PdfUtil.java:120)
	at org.vandeseer.pdfbox.easytable.util.PdfUtil.wrapLine(PdfUtil.java:65)
	at org.vandeseer.pdfbox.easytable.util.PdfUtil.splitBySize(PdfUtil.java:87)
	at org.vandeseer.pdfbox.easytable.util.PdfUtil.wrapLine(PdfUtil.java:72)
	at org.vandeseer.pdfbox.easytable.util.PdfUtil.splitBySize(PdfUtil.java:87)
	at org.vandeseer.pdfbox.easytable.util.PdfUtil.wrapLine(PdfUtil.java:72)
	at org.vandeseer.pdfbox.easytable.util.PdfUtil.splitBySize(PdfUtil.java:87)
	at org.vandeseer.pdfbox.easytable.util.PdfUtil.wrapLine(PdfUtil.java:72)
	at org.vandeseer.pdfbox.easytable.util.PdfUtil.splitBySize(PdfUtil.java:87)
	at org.vandeseer.pdfbox.easytable.util.PdfUtil.wrapLine(PdfUtil.java:72)
	at org.vandeseer.pdfbox.easytable.util.PdfUtil.splitBySize(PdfUtil.java:87)
	at org.vandeseer.pdfbox.easytable.util.PdfUtil.wrapLine(PdfUtil.java:72)
	at org.vandeseer.pdfbox.easytable.util.PdfUtil.splitBySize(PdfUtil.java:87)
	at org.vandeseer.pdfbox.easytable.util.PdfUtil.wrapLine(PdfUtil.java:72)
	at org.vandeseer.pdfbox.easytable.util.PdfUtil.splitBySize(PdfUtil.java:87)
	at org.vandeseer.pdfbox.easytable.util.PdfUtil.wrapLine(PdfUtil.java:72)
	at org.vandeseer.pdfbox.easytable.util.PdfUtil.splitBySize(PdfUtil.java:87)
	at org.vandeseer.pdfbox.easytable.util.PdfUtil.wrapLine(PdfUtil.java:72)
	at org.vandeseer.pdfbox.easytable.util.PdfUtil.splitBySize(PdfUtil.java:87)
	at org.vandeseer.pdfbox.easytable.util.PdfUtil.wrapLine(PdfUtil.java:72)
	at org.vandeseer.pdfbox.easytable.util.PdfUtil.splitBySize(PdfUtil.java:87)
	at org.vandeseer.pdfbox.easytable.util.PdfUtil.wrapLine(PdfUtil.java:72)
	at org.vandeseer.pdfbox.easytable.util.PdfUtil.splitBySize(PdfUtil.java:87)
	at org.vandeseer.pdfbox.easytable.util.PdfUtil.wrapLine(PdfUtil.java:72)
	at org.vandeseer.pdfbox.easytable.util.PdfUtil.splitBySize(PdfUtil.java:87)
	at org.vandeseer.pdfbox.easytable.util.PdfUtil.wrapLine(PdfUtil.java:72)
	at org.vandeseer.pdfbox.easytable.util.PdfUtil.splitBySize(PdfUtil.java:87)

Quick fix is to add an empty character to the given CellText. Looks a bit off when entered or right aligned but is still better then nothing. Will next week look into this issue myself if it isnt fixed until then, but due to the lack of time im just writing an issue for now.

Takes too long to draw and create pdf.

The pdf drawing takes too long. Like to get a 300 pages pdf from dynamic data creating 300 tables i.e. a table on each page, it took me 3 minutes. Any way for faster performance.

Get Height of Row

Hey, sorry for no response on the other thread, will get to that later. So, question:

row.getHeight() only works apparently when i fake a table like here:

   private float getRowHeight(Row row) {
        Table dummy = baseTable().addRow(row).build();
        return row.getHeight();
    }

Is there a way to return the expected row Height (need it for formatting multipage bills)

Offset Bug in 0.6.0

When i draw a repeated header table the endY gets shifted lower with every page the table gets drawn on. The vice versa effect happens with the header offset inside the .draw() function of the RepeatedHeaderTableDrawer (the table gets shifted higher every time the table reaches a new page).

private fun drawTable(
        table: Table,
        tableRect: PDRectangle,
        pdfDocument: PDDocument,
        contentStream: PDPageContentStream
    ) {

        RepeatedHeaderTableDrawer.builder()
            .table(table)
            .startY(tableRect.upperRightY)
            .startX(tableRect.lowerLeftX)
            .contentStream(contentStream)
            .endY(footerOffset)
            .build()
            .draw(Supplier<PDDocument> { pdfDocument }, Supplier<PDPage> { PDPage(PDRectangle.A4) }, headerOffset)
    }

On version 0.5.2 the offsets are working correctly.

Feature Request - Font per Row/Cell

Love the tool but it would be helpful to set a different font style/size on a row or cell. For example, having the header row be bold. Currently, font style is set for entire table. Only color can be changed per cell.

Questions regarding 0.6.0

Hi,

imagine I want to add a table in a header section of a pdf. So I render the content area for all pages in the pdf and afterwards i want to render a table containing "Page x of 10" in the top area on every page.

This was not easy in 0.5.2 but I managed to subclass "TableDrawer" to not use the last page of the document every time draw() is called. In 0.6.0 this is not so easy anymore because of the refactorings. There should be a page supplier which is not only for new appended pages but for every existing page I want Easytable to render onto.

Are there plans supporting that kind of feature?

2nd question: is there an easy way to determine where the table ends? I mean, getting the y coordinate after adding the table.

Thank you

Building a Row does not set the Settings for the Cells leading to a NullPointerException

Hello :)

I think I found a bug with the new Settings object. I have taken this example from your tests and slightly modified it:

Row row = Row.builder()
                .add(CellText.builder().text(RandomStringUtils.randomAlphabetic(23)).span(2).borderWidth(1).build())
                .add(CellText.builder().text("Booz").build())
                .font(COURIER_BOLD).fontSize(8)
                .build();

tableBuilder.addRow(row);

If I call row.getHeight() now, I get a NullPointerException. This used to work in version 0.1.0.
If I first call tableBuilder.build() and row.getHeight() afterwards, it works just fine.

I've identified that this is caused by the Cell Settings being filled with fillingMergeBy when the Table is built. But when the Row is built the Cells Settings remain empty.

Edit: I just noticed that it's not as easy as filling the Cells when the Rows are built. We still can't get the correct height because at that time we don't know yet if the Table will have line breaking :/

Row spanning affects image resizing in the next cel

I have two rows where the first cell of each row is spanning the two rows. The remainder of the cells in each row contains images. The first row of images is sized correctly, but the first cell of the second row will resize image in the first cell with the remaining cells in the row sized correctly.

If I disable the row spanning of the first cell all the images are sized correctly.

I have not found a possible work around.

no row spanning
row spanning

Multiple Fonts

For a project we have different fonts. The regular fonts, for "normal" characters. And "fallback"-fonts, for ❤ (emojis).

Our example for this fallback-method looks like this:

    private void printWithFallback(final String line, final int fontSize, final float startX, final float startY) throws IOException {
        this.contentStream.beginText();
        this.contentStream.newLineAtOffset(startX, startY);


        for (int offset = 0; offset < line.length(); ) {

            PDFont fontToPrint = this.document.getFonts().get(0);
            final int codePoint = line.codePointAt(offset);
            offset += Character.charCount(codePoint);
            String codePointAsString = new String(new int[]{codePoint}, 0, 1);

            //try all available fonts
            for (final PDFont fontToTry : this.document.getFonts()) {
                try {
                    fontToTry.encode(codePointAsString);
                    fontToPrint = fontToTry;
                    break;
                } catch (final IllegalArgumentException e) {
                    //try next font
                }
            }

            try {
                fontToPrint.encode(codePointAsString);
            } catch (final IllegalArgumentException e) {
                log.error("Codepoint {} could not be printed to PDF and has been replaced by the fallback character {}. " +
                                "This probably means that a font which can encode this codepoint should be included in the next release.",
                        codePoint, FALLBACK_CHARACTER);
                codePointAsString = FALLBACK_CHARACTER;
            }

            this.contentStream.setFont(fontToPrint, fontSize);
            this.contentStream.showText(codePointAsString);
        }

        this.contentStream.endText();
    }

Paragraph in a cell

I am using your EasyTable library and it is fantastic, for my use it is better than itext7. I have only one problem. I'm trying to insert a paragraph with multiple lines inside a cell but it gives me an error. Here is my class.

The error is:

Exception in thread "main" java.lang.NullPointerException at org.vandeseer.easytable.drawing.cell.ParagraphCellDrawer.drawContent(ParagraphCellDrawer.java:52) at org.vandeseer.easytable.TableDrawer.lambda$new$0(TableDrawer.java:53) at org.vandeseer.easytable.TableDrawer.drawRow(TableDrawer.java:161) at org.vandeseer.easytable.TableDrawer.drawWithFunction(TableDrawer.java:145) at org.vandeseer.easytable.TableDrawer.lambda$drawPage$1(TableDrawer.java:75) at java.lang.Iterable.forEach(Iterable.java:75) at org.vandeseer.easytable.TableDrawer.drawPage(TableDrawer.java:74) at org.vandeseer.easytable.TableDrawer.draw(TableDrawer.java:70) at it.baz.ProvaPDF.crea(ProvaPDF.java:66) at it.baz.ProvaPDF.main(ProvaPDF.java:21)

'
ProvaPDF.txt

pom.xml.txt

Thank you

first 2 or 3 rows for table header

Do we have a way to add first 2/3 rows for header. I have requirement where I would like to repeat first 3 rows on each page while drawing table data. please let me know your comments.

Exception when adding cyrillic text

I tried creating a table with cyrillic text in it, but I get an exception in TableDrawer->draw(); The same snippet works fine with text in English.

    final Row headerRow = Row.builder().add(CellText.builder().text("Проба").build()).build();
    tableBuilder.addRow(headerRow);
    float startY = page.getMediaBox().getHeight() - 10;
    TableDrawer.builder().contentStream(contentStream).table(tableBuilder.build())
            .startY(startY).build()
            .draw();

Exception when CellText Font is Symbol Font

I tried to set the text of CellText as uppercase sigma character. In order to do this I used the code below

CellText sigmaCell = CellText.builder()
                .text("S")
                .borderWidth(1F)
                .font(PDType1Font.SYMBOL)
                .build();

It gives the following error
java.lang.IllegalArgumentException: U+2013 ('endash') is not available in this font Symbol encoding: SymbolEncoding

Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.