Table and cell events to draw borders
These examples were written in answer to questions such as:
celltitle
JAVA
JAVA
/*
This file is part of the iText (R) project.
Copyright (c) 1998-2023 Apryse Group NV
Authors: Apryse Software.
For more information, please contact iText Software at this address:
sales@itextpdf.com
*/
package com.itextpdf.samples.sandbox.tables;
import com.itextpdf.kernel.colors.ColorConstants;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.layout.Canvas;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Cell;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.properties.UnitValue;
import com.itextpdf.layout.renderer.CellRenderer;
import com.itextpdf.layout.renderer.DrawContext;
import com.itextpdf.layout.renderer.IRenderer;
import java.io.File;
public class CellTitle {
public static final String DEST = "./target/sandbox/tables/cell_title.pdf";
public static void main(String[] args) throws Exception {
File file = new File(DEST);
file.getParentFile().mkdirs();
new CellTitle().manipulatePdf(DEST);
}
protected void manipulatePdf(String dest) throws Exception {
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
Document doc = new Document(pdfDoc);
// By default column width is calculated automatically for the best fit.
// useAllAvailableWidth() method makes table use the whole page's width while placing the content.
Table table = new Table(UnitValue.createPercentArray(1)).useAllAvailableWidth();
Cell cell = getCell("The title of this cell is title 1", "title 1");
table.addCell(cell);
cell = getCell("The title of this cell is title 2", "title 2");
table.addCell(cell);
cell = getCell("The title of this cell is title 3", "title 3");
table.addCell(cell);
doc.add(table);
doc.close();
}
private static class CellTitleRenderer extends CellRenderer {
protected String title;
public CellTitleRenderer(Cell modelElement, String title) {
super(modelElement);
this.title = title;
}
// If a renderer overflows on the next area, iText uses #getNextRenderer() method to create a new renderer for the overflow part.
// If #getNextRenderer() isn't overridden, the default method will be used and thus the default rather than the custom
// renderer will be created
@Override
public IRenderer getNextRenderer() {
return new CellTitleRenderer((Cell) modelElement, title);
}
@Override
public void drawBorder(DrawContext drawContext) {
PdfPage currentPage = drawContext.getDocument().getPage(getOccupiedArea().getPageNumber());
// Create an above canvas in order to draw above borders.
// Notice: bear in mind that iText draws cell borders on its TableRenderer level.
PdfCanvas aboveCanvas = new PdfCanvas(currentPage.newContentStreamAfter(), currentPage.getResources(),
drawContext.getDocument());
new Canvas(aboveCanvas, getOccupiedAreaBBox())
.add(new Paragraph(title)
.setMultipliedLeading(1)
.setMargin(0)
.setBackgroundColor(ColorConstants.LIGHT_GRAY)
.setFixedPosition(getOccupiedAreaBBox().getLeft() + 5,
getOccupiedAreaBBox().getTop() - 8, 30));
}
}
private static Cell getCell(String content, String title) {
Cell cell = new Cell().add(new Paragraph(content));
cell.setNextRenderer(new CellTitleRenderer(cell, title));
cell.setPaddingTop(8).setPaddingBottom(8);
return cell;
}
}
C#
C#
using System;
using System.IO;
using iText.Kernel.Colors;
using iText.Kernel.Pdf;
using iText.Kernel.Pdf.Canvas;
using iText.Layout;
using iText.Layout.Element;
using iText.Layout.Properties;
using iText.Layout.Renderer;
namespace iText.Samples.Sandbox.Tables
{
public class CellTitle
{
public static readonly string DEST = "results/sandbox/tables/cell_title.pdf";
public static void Main(String[] args)
{
FileInfo file = new FileInfo(DEST);
file.Directory.Create();
new CellTitle().ManipulatePdf(DEST);
}
private void ManipulatePdf(String dest)
{
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
Document doc = new Document(pdfDoc);
// By default column width is calculated automatically for the best fit.
// useAllAvailableWidth() method set table to use the whole page's width while placing the content.
Table table = new Table(UnitValue.CreatePercentArray(1)).UseAllAvailableWidth();
Cell cell = GetCell("The title of this cell is title 1", "title 1");
table.AddCell(cell);
cell = GetCell("The title of this cell is title 2", "title 2");
table.AddCell(cell);
cell = GetCell("The title of this cell is title 3", "title 3");
table.AddCell(cell);
doc.Add(table);
doc.Close();
}
private class CellTitleRenderer : CellRenderer
{
protected string title;
public CellTitleRenderer(Cell modelElement, String title)
: base(modelElement)
{
this.title = title;
}
// If renderer overflows on the next area, iText uses getNextRender() method to create a renderer for the overflow part.
// If getNextRenderer isn't overriden, the default method will be used and thus a default rather than custom
// renderer will be created
public override IRenderer GetNextRenderer()
{
return new CellTitleRenderer((Cell) modelElement, title);
}
public override void DrawBorder(DrawContext drawContext)
{
PdfPage currentPage = drawContext.GetDocument().GetPage(GetOccupiedArea().GetPageNumber());
// Create an above canvas in order to draw above borders.
// Notice: bear in mind that iText draws cell borders on its TableRenderer level.
PdfCanvas aboveCanvas = new PdfCanvas(currentPage.NewContentStreamAfter(), currentPage.GetResources(),
drawContext.GetDocument());
new Canvas(aboveCanvas, GetOccupiedAreaBBox())
.Add(new Paragraph(title)
.SetMultipliedLeading(1)
.SetMargin(0)
.SetBackgroundColor(ColorConstants.LIGHT_GRAY)
.SetFixedPosition(GetOccupiedAreaBBox().GetLeft() + 5,
GetOccupiedAreaBBox().GetTop() - 8, 30));
}
}
private static Cell GetCell(string content, string title)
{
Cell cell = new Cell().Add(new Paragraph(content));
cell.SetNextRenderer(new CellTitleRenderer(cell, title));
cell.SetPaddingTop(8).SetPaddingBottom(8);
return cell;
}
}
}
customborder
JAVA
JAVA
/*
This file is part of the iText (R) project.
Copyright (c) 1998-2023 Apryse Group NV
Authors: Apryse Software.
For more information, please contact iText Software at this address:
sales@itextpdf.com
*/
package com.itextpdf.samples.sandbox.tables;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.borders.Border;
import com.itextpdf.layout.borders.SolidBorder;
import com.itextpdf.layout.element.Cell;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.properties.BorderCollapsePropertyValue;
import com.itextpdf.layout.properties.Property;
import com.itextpdf.layout.properties.UnitValue;
import com.itextpdf.layout.renderer.CellRenderer;
import com.itextpdf.layout.renderer.DrawContext;
import com.itextpdf.layout.renderer.IRenderer;
import com.itextpdf.layout.renderer.TableRenderer;
import java.io.File;
public class CustomBorder {
public static final String DEST = "./target/sandbox/tables/custom_border.pdf";
public static final String TEXT = "This is some long paragraph\n" +
"that will be added over and over\n" +
"again to prove a point.\n" +
"It should result in rows\n" +
"that are split\n" +
" and rows that aren't.";
public static void main(String[] args) throws Exception {
File file = new File(DEST);
file.getParentFile().mkdirs();
new CustomBorder().manipulatePdf(DEST);
}
protected void manipulatePdf(String dest) throws Exception {
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
Document doc = new Document(pdfDoc);
// By default column width is calculated automatically for the best fit.
// useAllAvailableWidth() method makes table use the whole page's width while placing the content.
Table table = new Table(UnitValue.createPercentArray(2)).useAllAvailableWidth();
// Fill a table with cells.
// Be aware that by default all the cells will not have ay bottom borders
for (int i = 1; i <= 60; i++) {
table.addCell(new Cell().add(new Paragraph("Cell " + i)).setBorderBottom(Border.NO_BORDER));
table.addCell(new Cell().add(new Paragraph(TEXT)).setBorderBottom(Border.NO_BORDER));
}
// We do not need a smart collapse logic: on the contrary, we want to override
// processing of some cells, that's why we set SEPARATE value here
table.setBorderCollapse(BorderCollapsePropertyValue.SEPARATE);
// Use a custom renderer in which borders drawing is overridden
table.setNextRenderer(new CustomBorderTableRenderer(table));
doc.add(table);
doc.close();
}
private static class CustomBorderTableRenderer extends TableRenderer {
private boolean bottom = true;
private boolean top = true;
public CustomBorderTableRenderer(Table modelElement) {
super(modelElement);
}
// If a renderer overflows on the next area, iText uses #getNextRenderer() method to create a new renderer for the overflow part.
// If #getNextRenderer() isn't overridden, the default method will be used and thus the default rather than the custom
// renderer will be created
@Override
public IRenderer getNextRenderer() {
return new CustomBorderTableRenderer((Table) modelElement);
}
@Override
protected TableRenderer[] split(int row, boolean hasContent, boolean cellWithBigRowspanAdded) {
TableRenderer[] renderers = super.split(row, hasContent, cellWithBigRowspanAdded);
// The first row of the split renderer represent the first rows of the current renderer
((CustomBorderTableRenderer) renderers[0]).top = top;
// If there are some split cells, we should draw top borders of the overflow renderer
// and bottom borders of the split renderer
if (hasContent) {
((CustomBorderTableRenderer) renderers[0]).bottom = false;
((CustomBorderTableRenderer) renderers[1]).top = false;
}
return renderers;
}
@Override
public void draw(DrawContext drawContext) {
// If not set, iText will omit drawing of top borders
if (!top) {
for (CellRenderer cellRenderer : rows.get(0)) {
cellRenderer.setProperty(Property.BORDER_TOP, Border.NO_BORDER);
}
}
// If set, iText will draw bottom borders
if (bottom) {
for (CellRenderer cellRenderer : rows.get(rows.size() - 1)) {
cellRenderer.setProperty(Property.BORDER_BOTTOM, new SolidBorder(0.5f));
}
}
super.draw(drawContext);
}
}
}
C#
C#
using System;
using System.IO;
using iText.Kernel.Pdf;
using iText.Layout;
using iText.Layout.Borders;
using iText.Layout.Element;
using iText.Layout.Properties;
using iText.Layout.Renderer;
namespace iText.Samples.Sandbox.Tables
{
public class CustomBorder
{
public static readonly string DEST = "results/sandbox/tables/custom_border.pdf";
public static readonly string TEXT = "This is some long paragraph\n" +
"that will be added over and over\n" +
"again to prove a point.\n" +
"It should result in rows\n" +
"that are split\n" +
" and rows that aren't.";
public static void Main(String[] args)
{
FileInfo file = new FileInfo(DEST);
file.Directory.Create();
new CustomBorder().ManipulatePdf(DEST);
}
private void ManipulatePdf(string dest)
{
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
Document doc = new Document(pdfDoc);
// By default column width is calculated automatically for the best fit.
// useAllAvailableWidth() method set table to use the whole page's width while placing the content.
Table table = new Table(UnitValue.CreatePercentArray(2)).UseAllAvailableWidth();
// Fill a table with cells.
// Be aware that by default all the cells will not have ay bottom borders
for (int i = 1; i <= 60; i++)
{
table.AddCell(new Cell().Add(new Paragraph("Cell " + i)).SetBorderBottom(Border.NO_BORDER));
table.AddCell(new Cell().Add(new Paragraph(TEXT)).SetBorderBottom(Border.NO_BORDER));
}
// We do not need a smart collapse logic: on the contrary, we want to override
// processing of some cells, that's why we set SEPARATE value here
table.SetBorderCollapse(BorderCollapsePropertyValue.SEPARATE);
// Use a custom renderer in which borders drawing is overridden
table.SetNextRenderer(new CustomBorderTableRenderer(table));
doc.Add(table);
doc.Close();
}
private class CustomBorderTableRenderer : TableRenderer
{
private bool bottom = true;
private bool top = true;
public CustomBorderTableRenderer(Table modelElement) : base(modelElement)
{
}
// If renderer overflows on the next area, iText uses getNextRender() method to create a renderer for the overflow part.
// If getNextRenderer isn't overriden, the default method will be used and thus a default rather than custom
// renderer will be created
public override IRenderer GetNextRenderer()
{
return new CustomBorderTableRenderer((Table)modelElement);
}
protected override TableRenderer[] Split(int row, bool hasContent, bool cellWithBigRowspanAdded)
{
TableRenderer[] renderers = base.Split(row, hasContent, cellWithBigRowspanAdded);
// The first row of the split renderer represent the first rows of the current renderer
((CustomBorderTableRenderer)renderers[0]).top = top;
// If there are some split cells, we should draw top borders of the overflow renderer
// and bottom borders of the split renderer
if (hasContent)
{
((CustomBorderTableRenderer)renderers[0]).bottom = false;
((CustomBorderTableRenderer)renderers[1]).top = false;
}
return renderers;
}
public override void Draw(DrawContext drawContext)
{
// If not set, iText will omit drawing of top borders
if (!top)
{
foreach (CellRenderer cellRenderer in rows[0])
{
cellRenderer.SetProperty(Property.BORDER_TOP, Border.NO_BORDER);
}
}
// If set, iText will draw bottom borders
if (bottom)
{
foreach (CellRenderer cellRenderer in rows[rows.Count - 1])
{
cellRenderer.SetProperty(Property.BORDER_BOTTOM, new SolidBorder(0.5f));
}
}
base.Draw(drawContext);
}
}
}
}
dottedlinecell
JAVA
JAVA
/*
This file is part of the iText (R) project.
Copyright (c) 1998-2023 Apryse Group NV
Authors: Apryse Software.
For more information, please contact iText Software at this address:
sales@itextpdf.com
*/
package com.itextpdf.samples.sandbox.tables;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.borders.Border;
import com.itextpdf.layout.borders.DottedBorder;
import com.itextpdf.layout.element.Cell;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.properties.UnitValue;
import com.itextpdf.layout.renderer.CellRenderer;
import com.itextpdf.layout.renderer.DrawContext;
import com.itextpdf.layout.renderer.IRenderer;
import com.itextpdf.layout.renderer.TableRenderer;
import java.io.File;
public class DottedLineCell {
public static final String DEST = "./target/sandbox/tables/dotted_line_cell.pdf";
public static void main(String[] args) throws Exception {
File file = new File(DEST);
file.getParentFile().mkdirs();
new DottedLineCell().manipulatePdf(DEST);
}
protected void manipulatePdf(String dest) throws Exception {
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
Document doc = new Document(pdfDoc);
doc.add(new Paragraph("Table event setter approach"));
Table table = new Table(UnitValue.createPercentArray(3)).useAllAvailableWidth();
table.addCell(createCellWithBorders("A1"));
table.addCell(createCellWithBorders("A2"));
table.addCell(createCellWithBorders("A3"));
table.addCell(createCellWithBorders("B1"));
table.addCell(createCellWithBorders("B2"));
table.addCell(createCellWithBorders("B3"));
table.addCell(createCellWithBorders("C1"));
table.addCell(createCellWithBorders("C2"));
table.addCell(createCellWithBorders("C3"));
doc.add(table);
doc.add(new Paragraph("Cell event setter approach"));
table = new Table(UnitValue.createPercentArray(1)).useAllAvailableWidth();
table.addCell(createCellWithBorders("Test"));
doc.add(table);
doc.add(new Paragraph("Table event custom render approach"));
table = new Table(UnitValue.createPercentArray(3)).useAllAvailableWidth();
table.addCell(new Cell().add(new Paragraph("A1")).setBorder(Border.NO_BORDER));
table.addCell(new Cell().add(new Paragraph("A2")).setBorder(Border.NO_BORDER));
table.addCell(new Cell().add(new Paragraph("A3")).setBorder(Border.NO_BORDER));
table.addCell(new Cell().add(new Paragraph("B1")).setBorder(Border.NO_BORDER));
table.addCell(new Cell().add(new Paragraph("B2")).setBorder(Border.NO_BORDER));
table.addCell(new Cell().add(new Paragraph("B3")).setBorder(Border.NO_BORDER));
table.addCell(new Cell().add(new Paragraph("C1")).setBorder(Border.NO_BORDER));
table.addCell(new Cell().add(new Paragraph("C2")).setBorder(Border.NO_BORDER));
table.addCell(new Cell().add(new Paragraph("C3")).setBorder(Border.NO_BORDER));
// Draws dotted line borders.
table.setNextRenderer(new DottedLineTableRenderer(table));
doc.add(table);
doc.add(new Paragraph("Cell event custom render approach"));
table = new Table(UnitValue.createPercentArray(1)).useAllAvailableWidth();
Cell cell = new Cell().add(new Paragraph("Test"));
cell.setNextRenderer(new DottedLineCellRenderer(cell));
// Since we override the border drawing, we do not need the default logic to be triggered, that's why we set
// the border value as null
cell.setBorder(Border.NO_BORDER);
table.addCell(cell);
doc.add(table);
doc.close();
}
private static class DottedLineTableRenderer extends TableRenderer {
public DottedLineTableRenderer(Table modelElement) {
super(modelElement);
}
// If a renderer overflows on the next area, iText uses #getNextRenderer() method to create a new renderer for the overflow part.
// If #getNextRenderer() isn't overridden, the default method will be used and thus the default rather than the custom
// renderer will be created
@Override
public IRenderer getNextRenderer() {
return new DottedLineTableRenderer((Table) modelElement);
}
@Override
public void drawChildren(DrawContext drawContext) {
super.drawChildren(drawContext);
PdfCanvas canvas = drawContext.getCanvas();
canvas.setLineDash(1f, 3f);
// first horizontal line
CellRenderer[] cellRenderers = rows.get(0);
canvas.moveTo(cellRenderers[0].getOccupiedArea().getBBox().getLeft(),
cellRenderers[0].getOccupiedArea().getBBox().getTop());
canvas.lineTo(cellRenderers[cellRenderers.length - 1].getOccupiedArea().getBBox().getRight(),
cellRenderers[cellRenderers.length - 1].getOccupiedArea().getBBox().getTop());
for (CellRenderer[] renderers : rows) {
// horizontal lines
canvas.moveTo(renderers[0].getOccupiedArea().getBBox().getX(),
renderers[0].getOccupiedArea().getBBox().getY());
canvas.lineTo(renderers[renderers.length - 1].getOccupiedArea().getBBox().getRight(),
renderers[renderers.length - 1].getOccupiedArea().getBBox().getBottom());
// first vertical line
Rectangle cellRect = renderers[0].getOccupiedArea().getBBox();
canvas.moveTo(cellRect.getLeft(), cellRect.getBottom());
canvas.lineTo(cellRect.getLeft(), cellRect.getTop());
// vertical lines
for (CellRenderer renderer : renderers) {
cellRect = renderer.getOccupiedArea().getBBox();
canvas.moveTo(cellRect.getRight(), cellRect.getBottom());
canvas.lineTo(cellRect.getRight(), cellRect.getTop());
}
}
canvas.stroke();
}
}
private static class DottedLineCellRenderer extends CellRenderer {
public DottedLineCellRenderer(Cell modelElement) {
super(modelElement);
}
// If a renderer overflows on the next area, iText uses #getNextRenderer() method to create a new renderer for the overflow part.
// If #getNextRenderer() isn't overridden, the default method will be used and thus the default rather than the custom
// renderer will be created
@Override
public IRenderer getNextRenderer() {
return new DottedLineCellRenderer((Cell) modelElement);
}
@Override
public void draw(DrawContext drawContext) {
super.draw(drawContext);
drawContext.getCanvas().setLineDash(1f, 3f);
drawContext.getCanvas().rectangle(this.getOccupiedArea().getBBox());
drawContext.getCanvas().stroke();
}
}
private Cell createCellWithBorders(String content) {
Cell cell = new Cell().add(new Paragraph(content));
cell.setBorder(new DottedBorder(1));
return cell;
}
}
C#
C#
using System;
using System.IO;
using iText.Kernel.Geom;
using iText.Kernel.Pdf;
using iText.Kernel.Pdf.Canvas;
using iText.Layout;
using iText.Layout.Element;
using iText.Layout.Properties;
using iText.Layout.Renderer;
namespace iText.Samples.Sandbox.Tables
{
public class CustomBorder2
{
public static readonly string DEST = "results/sandbox/tables/custom_border2.pdf";
public static readonly string TEXT = "This is some long paragraph that will be added over and over " +
"again to prove a point. It should result in rows that are split and rows that aren't.";
public static void Main(String[] args)
{
FileInfo file = new FileInfo(DEST);
file.Directory.Create();
new CustomBorder2().ManipulatePdf(DEST);
}
private void ManipulatePdf(string dest)
{
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
Document doc = new Document(pdfDoc);
// By default column width is calculated automatically for the best fit.
// useAllAvailableWidth() method makes table use the whole page's width while placing the content.
Table table = new Table(UnitValue.CreatePercentArray(2)).UseAllAvailableWidth();
for (int i = 1; i < 60; i++)
{
table.AddCell(new Cell().Add(new Paragraph("Cell " + i)));
table.AddCell(new Cell().Add(new Paragraph(TEXT)));
}
// Use a custom renderer in which borders drawing is overridden
table.SetNextRenderer(new CustomBorder2TableRenderer(table));
doc.Add(table);
doc.Close();
}
private class CustomBorder2TableRenderer : TableRenderer
{
private bool top = true;
private bool bottom = true;
public CustomBorder2TableRenderer(Table modelElement) : base(modelElement)
{
}
// If renderer overflows on the next area, iText uses getNextRender() method to create a renderer for the overflow part.
// If getNextRenderer isn't overriden, the default method will be used and thus a default rather than custom
// renderer will be created
public override IRenderer GetNextRenderer()
{
return new CustomBorder2TableRenderer((Table) modelElement);
}
protected override TableRenderer[] Split(int row, bool hasContent, bool cellWithBigRowspanAdded)
{
// Being inside this method implies that split has occurred
TableRenderer[] results = base.Split(row, hasContent, cellWithBigRowspanAdded);
CustomBorder2TableRenderer splitRenderer = (CustomBorder2TableRenderer)results[0];
// iText shouldn't draw the bottom split renderer's border,
// because there is an overflow renderer
splitRenderer.bottom = false;
// If top is true, the split renderer is the first renderer of the document.
// If false, iText has already processed the first renderer
splitRenderer.top = this.top;
CustomBorder2TableRenderer overflowRenderer = (CustomBorder2TableRenderer)results[1];
// iText shouldn't draw the top overflow renderer's border
overflowRenderer.top = false;
return results;
}
protected override void DrawBorders(DrawContext drawContext)
{
Rectangle area = occupiedArea.GetBBox();
PdfCanvas canvas = drawContext.GetCanvas();
canvas
.SaveState()
.MoveTo(area.GetLeft(), area.GetBottom())
.LineTo(area.GetLeft(), area.GetTop())
.MoveTo(area.GetRight(), area.GetTop())
.LineTo(area.GetRight(), area.GetBottom());
if (top)
{
canvas
.MoveTo(area.GetLeft(), area.GetTop())
.LineTo(area.GetRight(), area.GetTop());
}
if (bottom)
{
canvas
.MoveTo(area.GetLeft(), area.GetBottom())
.LineTo(area.GetRight(), area.GetBottom());
}
canvas
.Stroke()
.RestoreState();
}
}
}
}
dottedlinecell2
JAVA
JAVA
/*
This file is part of the iText (R) project.
Copyright (c) 1998-2023 Apryse Group NV
Authors: Apryse Software.
For more information, please contact iText Software at this address:
sales@itextpdf.com
*/
package com.itextpdf.samples.sandbox.tables;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.Style;
import com.itextpdf.layout.borders.Border;
import com.itextpdf.layout.borders.DottedBorder;
import com.itextpdf.layout.element.Cell;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.properties.UnitValue;
import com.itextpdf.layout.renderer.CellRenderer;
import com.itextpdf.layout.renderer.DrawContext;
import com.itextpdf.layout.renderer.IRenderer;
import java.io.File;
public class DottedLineCell2 {
public static final String DEST = "./target/sandbox/tables/dotted_line_cell2.pdf";
public static void main(String[] args) throws Exception {
File file = new File(DEST);
file.getParentFile().mkdirs();
new DottedLineCell2().manipulatePdf(DEST);
}
protected void manipulatePdf(String dest) throws Exception {
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
Document document = new Document(pdfDoc);
Paragraph paragraph = new Paragraph("Setter approach");
document.add(paragraph.setFontSize(25));
Table table = new Table(UnitValue.createPercentArray(4)).useAllAvailableWidth();
table.setMarginBottom(30);
table.addCell(createCell("left border", new Style().setBorderLeft(new DottedBorder(1))));
table.addCell(createCell("right border", new Style().setBorderRight(new DottedBorder(1))));
table.addCell(createCell("top border", new Style().setBorderTop(new DottedBorder(1))));
table.addCell(createCell("bottom border", new Style().setBorderBottom(new DottedBorder(1))));
document.add(table);
table = new Table(UnitValue.createPercentArray(4)).useAllAvailableWidth();
table.setMarginBottom(30);
table.addCell(createCell("left and top border", new Style()
.setBorderLeft(new DottedBorder(1))
.setBorderTop(new DottedBorder(1))));
table.addCell(createCell("right and bottom border", new Style()
.setBorderRight(new DottedBorder(1))
.setBorderBottom(new DottedBorder(1))));
table.addCell(createCell("no border", new Style()));
table.addCell(createCell("full border", new Style()
.setBorderBottom(new DottedBorder(1))
.setBorderTop(new DottedBorder(1))
.setBorderRight(new DottedBorder(1))
.setBorderLeft(new DottedBorder(1))));
document.add(table);
paragraph = new Paragraph("Custom render approach");
document.add(paragraph.setFontSize(25));
table = new Table(UnitValue.createPercentArray(4)).useAllAvailableWidth();
table.setMarginBottom(30);
Cell cell = new Cell().add(new Paragraph("left border"));
cell.setBorder(Border.NO_BORDER);
cell.setNextRenderer(new DottedLineCellRenderer(cell, new boolean[] {false, true, false, false}));
table.addCell(cell);
cell = new Cell().add(new Paragraph("right border"));
cell.setBorder(Border.NO_BORDER);
cell.setNextRenderer(new DottedLineCellRenderer(cell, new boolean[] {false, false, false, true}));
table.addCell(cell);
cell = new Cell().add(new Paragraph("top border"));
cell.setBorder(Border.NO_BORDER);
cell.setNextRenderer(new DottedLineCellRenderer(cell, new boolean[] {true, false, false, false}));
table.addCell(cell);
cell = new Cell().add(new Paragraph("bottom border"));
cell.setBorder(Border.NO_BORDER);
cell.setNextRenderer(new DottedLineCellRenderer(cell, new boolean[] {false, false, true, false}));
table.addCell(cell);
document.add(table);
table = new Table(UnitValue.createPercentArray(4)).useAllAvailableWidth();
table.setMarginBottom(30);
cell = new Cell().add(new Paragraph("left and top border"));
cell.setBorder(Border.NO_BORDER);
cell.setNextRenderer(new DottedLineCellRenderer(cell, new boolean[] {true, true, false, false}));
table.addCell(cell);
cell = new Cell().add(new Paragraph("right and bottom border"));
cell.setBorder(Border.NO_BORDER);
cell.setNextRenderer(new DottedLineCellRenderer(cell, new boolean[] {false, false, true, true}));
table.addCell(cell);
cell = new Cell().add(new Paragraph("no border"));
cell.setBorder(Border.NO_BORDER);
table.addCell(cell);
cell = new Cell().add(new Paragraph("full border"));
cell.setBorder(Border.NO_BORDER);
cell.setNextRenderer(new DottedLineCellRenderer(cell, new boolean[] {true, true, true, true}));
table.addCell(cell);
document.add(table);
document.close();
}
private static class DottedLineCellRenderer extends CellRenderer {
boolean[] borders;
public DottedLineCellRenderer(Cell modelElement, boolean[] borders) {
super(modelElement);
this.borders = new boolean[borders.length];
for (int i = 0; i < this.borders.length; i++) {
this.borders[i] = borders[i];
}
}
// If a renderer overflows on the next area, iText uses #getNextRenderer() method to create a new renderer for the overflow part.
// If #getNextRenderer() isn't overridden, the default method will be used and thus the default rather than the custom
// renderer will be created
@Override
public IRenderer getNextRenderer() {
return new DottedLineCellRenderer((Cell) modelElement, borders);
}
@Override
public void draw(DrawContext drawContext) {
super.draw(drawContext);
PdfCanvas canvas = drawContext.getCanvas();
Rectangle position = getOccupiedAreaBBox();
canvas.saveState();
canvas.setLineDash(1f,3f);
if (borders[0]) {
canvas.moveTo(position.getRight(), position.getTop());
canvas.lineTo(position.getLeft(), position.getTop());
}
if (borders[2]) {
canvas.moveTo(position.getRight(), position.getBottom());
canvas.lineTo(position.getLeft(), position.getBottom());
}
if (borders[3]) {
canvas.moveTo(position.getRight(), position.getTop());
canvas.lineTo(position.getRight(), position.getBottom());
}
if (borders[1]) {
canvas.moveTo(position.getLeft(), position.getTop());
canvas.lineTo(position.getLeft(), position.getBottom());
}
canvas.stroke();
canvas.restoreState();
}
}
private static Cell createCell(String content, Style style) {
Cell cell = new Cell()
.add(new Paragraph(content))
// By default there is a BORDER property set as SolidBorder. We want to override it
// and that's why this property is set to null.
// However, if there is a BORDER property in the passed Style instance,
// it will be used because it's added afterwards.
.addStyle(new Style().setBorder(Border.NO_BORDER));
cell.addStyle(style);
return cell;
}
}
C#
C#
using System;
using System.IO;
using iText.Kernel.Geom;
using iText.Kernel.Pdf;
using iText.Kernel.Pdf.Canvas;
using iText.Layout;
using iText.Layout.Borders;
using iText.Layout.Element;
using iText.Layout.Properties;
using iText.Layout.Renderer;
namespace iText.Samples.Sandbox.Tables
{
public class DottedLineCell2
{
public static readonly string DEST = "results/sandbox/tables/dotted_line_cell2.pdf";
public static void Main(String[] args)
{
FileInfo file = new FileInfo(DEST);
file.Directory.Create();
new DottedLineCell2().ManipulatePdf(DEST);
}
private void ManipulatePdf(String dest)
{
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
Document document = new Document(pdfDoc);
Paragraph paragraph = new Paragraph("Setter approach");
document.Add(paragraph.SetFontSize(25));
Table table = new Table(UnitValue.CreatePercentArray(4)).UseAllAvailableWidth();
table.SetMarginBottom(30);
table.AddCell(CreateCell("left border", new Style().SetBorderLeft(new DottedBorder(1))));
table.AddCell(CreateCell("right border", new Style().SetBorderRight(new DottedBorder(1))));
table.AddCell(CreateCell("top border", new Style().SetBorderTop(new DottedBorder(1))));
table.AddCell(CreateCell("bottom border", new Style().SetBorderBottom(new DottedBorder(1))));
document.Add(table);
table = new Table(UnitValue.CreatePercentArray(4)).UseAllAvailableWidth();
table.SetMarginBottom(30);
table.AddCell(CreateCell("left and top border", new Style()
.SetBorderLeft(new DottedBorder(1))
.SetBorderTop(new DottedBorder(1))));
table.AddCell(CreateCell("right and bottom border", new Style()
.SetBorderRight(new DottedBorder(1))
.SetBorderBottom(new DottedBorder(1))));
table.AddCell(CreateCell("no border", new Style()));
table.AddCell(CreateCell("full border", new Style()
.SetBorderBottom(new DottedBorder(1))
.SetBorderTop(new DottedBorder(1))
.SetBorderRight(new DottedBorder(1))
.SetBorderLeft(new DottedBorder(1))));
document.Add(table);
paragraph = new Paragraph("Custom render approach");
document.Add(paragraph.SetFontSize(25));
table = new Table(UnitValue.CreatePercentArray(4)).UseAllAvailableWidth();
table.SetMarginBottom(30);
Cell cell = new Cell().Add(new Paragraph("left border"));
cell.SetBorder(Border.NO_BORDER);
cell.SetNextRenderer(new DottedLineCellRenderer(cell, new bool[] { false, true, false, false}));
table.AddCell(cell);
cell = new Cell().Add(new Paragraph("right border"));
cell.SetBorder(Border.NO_BORDER);
cell.SetNextRenderer(new DottedLineCellRenderer(cell, new bool[] { false, false, false, true}));
table.AddCell(cell);
cell = new Cell().Add(new Paragraph("top border"));
cell.SetBorder(Border.NO_BORDER);
cell.SetNextRenderer(new DottedLineCellRenderer(cell, new bool[] { true, false, false, false}));
table.AddCell(cell);
cell = new Cell().Add(new Paragraph("bottom border"));
cell.SetBorder(Border.NO_BORDER);
cell.SetNextRenderer(new DottedLineCellRenderer(cell, new bool[] { false, false, true, false}));
table.AddCell(cell);
document.Add(table);
table = new Table(UnitValue.CreatePercentArray(4)).UseAllAvailableWidth();
table.SetMarginBottom(30);
cell = new Cell().Add(new Paragraph("left and top border"));
cell.SetBorder(Border.NO_BORDER);
cell.SetNextRenderer(new DottedLineCellRenderer(cell, new bool[] { true, true, false, false}));
table.AddCell(cell);
cell = new Cell().Add(new Paragraph("right and bottom border"));
cell.SetBorder(Border.NO_BORDER);
cell.SetNextRenderer(new DottedLineCellRenderer(cell, new bool[] { false, false, true, true}));
table.AddCell(cell);
cell = new Cell().Add(new Paragraph("no border"));
cell.SetBorder(Border.NO_BORDER);
table.AddCell(cell);
cell = new Cell().Add(new Paragraph("full border"));
cell.SetBorder(Border.NO_BORDER);
cell.SetNextRenderer(new DottedLineCellRenderer(cell, new bool[] { true, true, true, true }));
table.AddCell(cell);
document.Add(table);
document.Close();
}
private class DottedLineCellRenderer : CellRenderer
{
internal bool[] borders;
public DottedLineCellRenderer(Cell modelElement, bool[] borders)
: base(modelElement)
{
this.borders = new bool[borders.Length];
for (int i = 0; i < this.borders.Length; i++)
{
this.borders[i] = borders[i];
}
}
// If renderer overflows on the next area, iText uses getNextRender() method to create a renderer for the overflow part.
// If getNextRenderer isn't overriden, the default method will be used and thus a default rather than custom
// renderer will be created
public override IRenderer GetNextRenderer()
{
return new DottedLineCellRenderer((Cell)modelElement, borders);
}
public override void Draw(DrawContext drawContext)
{
base.Draw(drawContext);
PdfCanvas canvas = drawContext.GetCanvas();
Rectangle position = GetOccupiedAreaBBox();
canvas.SaveState();
canvas.SetLineDash(1f, 3f);
if (borders[0])
{
canvas.MoveTo(position.GetRight(), position.GetTop());
canvas.LineTo(position.GetLeft(), position.GetTop());
}
if (borders[2])
{
canvas.MoveTo(position.GetRight(), position.GetBottom());
canvas.LineTo(position.GetLeft(), position.GetBottom());
}
if (borders[3])
{
canvas.MoveTo(position.GetRight(), position.GetTop());
canvas.LineTo(position.GetRight(), position.GetBottom());
}
if (borders[1])
{
canvas.MoveTo(position.GetLeft(), position.GetTop());
canvas.LineTo(position.GetLeft(), position.GetBottom());
}
canvas.Stroke();
canvas.RestoreState();
}
}
private static Cell CreateCell(String content, Style style)
{
Cell cell = new Cell()
.Add(new Paragraph(content))
// By default there is a BORDER property set as SolidBorder. We want to override it
// and that's why this property is set to null.
// However, if there is a BORDER property in the passed Style instance,
// it will be used because it's added afterwards.
.AddStyle(new Style().SetBorder(Border.NO_BORDER));
cell.AddStyle(style);
return cell;
}
}
}
dottedlineheader
JAVA
JAVA
/*
This file is part of the iText (R) project.
Copyright (c) 1998-2023 Apryse Group NV
Authors: Apryse Software.
For more information, please contact iText Software at this address:
sales@itextpdf.com
*/
package com.itextpdf.samples.sandbox.tables;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.Style;
import com.itextpdf.layout.borders.Border;
import com.itextpdf.layout.element.Cell;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.properties.UnitValue;
import com.itextpdf.layout.renderer.CellRenderer;
import com.itextpdf.layout.renderer.DrawContext;
import com.itextpdf.layout.renderer.IRenderer;
import com.itextpdf.layout.renderer.TableRenderer;
import java.io.File;
public class DottedLineHeader {
public static final String DEST = "./target/sandbox/tables/dotted_line_header.pdf";
public static void main(String[] args) throws Exception {
File file = new File(DEST);
file.getParentFile().mkdirs();
new DottedLineHeader().manipulatePdf(DEST);
}
protected void manipulatePdf(String dest) throws Exception {
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
Document doc = new Document(pdfDoc);
Table table = new Table(UnitValue.createPercentArray(3)).useAllAvailableWidth();
// Draws dotted line border in table
table.setNextRenderer(new DottedHeaderTableRenderer(table, new Table.RowRange(0, 1)));
Style noBorder = new Style().setBorder(Border.NO_BORDER);
table.addHeaderCell(new Cell().add(new Paragraph("A1")).addStyle(noBorder));
table.addHeaderCell(new Cell().add(new Paragraph("A2")).addStyle(noBorder));
table.addHeaderCell(new Cell().add(new Paragraph("A3")).addStyle(noBorder));
table.addCell(new Cell().add(new Paragraph("B1")).addStyle(noBorder));
table.addCell(new Cell().add(new Paragraph("B2")).addStyle(noBorder));
table.addCell(new Cell().add(new Paragraph("B3")).addStyle(noBorder));
table.addCell(new Cell().add(new Paragraph("C1")).addStyle(noBorder));
table.addCell(new Cell().add(new Paragraph("C2")).addStyle(noBorder));
table.addCell(new Cell().add(new Paragraph("C3")).addStyle(noBorder));
doc.add(table);
doc.add(new Paragraph("Cell event"));
table = new Table(UnitValue.createPercentArray(3)).useAllAvailableWidth();
Cell cell = new Cell().add(new Paragraph("A1")).addStyle(noBorder);
// Draws dotted line border in cell
cell.setNextRenderer(new DottedHeaderCellRenderer(cell));
table.addCell(cell);
cell = new Cell().add(new Paragraph("A2")).addStyle(noBorder);
cell.setNextRenderer(new DottedHeaderCellRenderer(cell));
table.addCell(cell);
cell = new Cell().add(new Paragraph("A3")).addStyle(noBorder);
cell.setNextRenderer(new DottedHeaderCellRenderer(cell));
table.addCell(cell);
table.addCell(new Cell().add(new Paragraph("B1")).addStyle(noBorder));
table.addCell(new Cell().add(new Paragraph("B2")).addStyle(noBorder));
table.addCell(new Cell().add(new Paragraph("B3")).addStyle(noBorder));
table.addCell(new Cell().add(new Paragraph("C1")).addStyle(noBorder));
table.addCell(new Cell().add(new Paragraph("C2")).addStyle(noBorder));
table.addCell(new Cell().add(new Paragraph("C3")).addStyle(noBorder));
doc.add(table);
doc.close();
}
private static class DottedHeaderTableRenderer extends TableRenderer {
public DottedHeaderTableRenderer(Table modelElement, Table.RowRange rowRange) {
super(modelElement, rowRange);
}
// If a renderer overflows on the next area, iText uses #getNextRenderer() method to create a new renderer for the overflow part.
// If #getNextRenderer() isn't overridden, the default method will be used and thus the default rather than the custom
// renderer will be created
@Override
public IRenderer getNextRenderer() {
return new DottedHeaderTableRenderer((Table) modelElement, rowRange);
}
@Override
public void drawChildren(DrawContext drawContext) {
super.drawChildren(drawContext);
Rectangle headersArea = headerRenderer.getOccupiedArea().getBBox();
PdfCanvas canvas = drawContext.getCanvas();
canvas.setLineDash(3f, 3f);
canvas.moveTo(headersArea.getLeft(), headersArea.getTop());
canvas.lineTo(headersArea.getRight(), headersArea.getTop());
canvas.moveTo(headersArea.getLeft(), headersArea.getBottom());
canvas.lineTo(headersArea.getRight(), headersArea.getBottom());
canvas.stroke();
}
}
private static class DottedHeaderCellRenderer extends CellRenderer {
public DottedHeaderCellRenderer(Cell modelElement) {
super(modelElement);
}
// If a renderer overflows on the next area, iText uses #getNextRenderer() method to create a new renderer for the overflow part.
// If #getNextRenderer() isn't overridden, the default method will be used and thus the default rather than the custom
// renderer will be created
@Override
public IRenderer getNextRenderer() {
return new DottedHeaderCellRenderer((Cell) modelElement);
}
@Override
public void draw(DrawContext drawContext) {
super.draw(drawContext);
PdfCanvas canvas = drawContext.getCanvas();
Rectangle bbox = getOccupiedArea().getBBox();
canvas.setLineDash(3f, 3f);
canvas.moveTo(bbox.getLeft(), bbox.getBottom());
canvas.lineTo(bbox.getRight(), bbox.getBottom());
canvas.moveTo(bbox.getLeft(), bbox.getTop());
canvas.lineTo(bbox.getRight(), bbox.getTop());
canvas.stroke();
}
}
}
C#
C#
using System;
using System.IO;
using iText.Kernel.Geom;
using iText.Kernel.Pdf;
using iText.Kernel.Pdf.Canvas;
using iText.Layout;
using iText.Layout.Borders;
using iText.Layout.Element;
using iText.Layout.Properties;
using iText.Layout.Renderer;
namespace iText.Samples.Sandbox.Tables
{
public class DottedLineHeader
{
public static readonly string DEST = "results/sandbox/tables/dotted_line_header.pdf";
public static void Main(String[] args)
{
FileInfo file = new FileInfo(DEST);
file.Directory.Create();
new DottedLineHeader().ManipulatePdf(DEST);
}
private void ManipulatePdf(string dest)
{
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
Document doc = new Document(pdfDoc);
Table table = new Table(UnitValue.CreatePercentArray(3)).UseAllAvailableWidth();
// Draws dotted line border in table
table.SetNextRenderer(new DottedHeaderTableRenderer(table, new Table.RowRange(0, 1)));
Style noBorder = new Style().SetBorder(Border.NO_BORDER);
table.AddHeaderCell(new Cell().Add(new Paragraph("A1")).AddStyle(noBorder));
table.AddHeaderCell(new Cell().Add(new Paragraph("A2")).AddStyle(noBorder));
table.AddHeaderCell(new Cell().Add(new Paragraph("A3")).AddStyle(noBorder));
table.AddCell(new Cell().Add(new Paragraph("B1")).AddStyle(noBorder));
table.AddCell(new Cell().Add(new Paragraph("B2")).AddStyle(noBorder));
table.AddCell(new Cell().Add(new Paragraph("B3")).AddStyle(noBorder));
table.AddCell(new Cell().Add(new Paragraph("C1")).AddStyle(noBorder));
table.AddCell(new Cell().Add(new Paragraph("C2")).AddStyle(noBorder));
table.AddCell(new Cell().Add(new Paragraph("C3")).AddStyle(noBorder));
doc.Add(table);
doc.Add(new Paragraph("Cell event"));
table = new Table(UnitValue.CreatePercentArray(3)).UseAllAvailableWidth();
Cell cell = new Cell().Add(new Paragraph("A1")).AddStyle(noBorder);
// Draws dotted line border in cell
cell.SetNextRenderer(new DottedHeaderCellRenderer(cell));
table.AddCell(cell);
cell = new Cell().Add(new Paragraph("A2")).AddStyle(noBorder);
cell.SetNextRenderer(new DottedHeaderCellRenderer(cell));
table.AddCell(cell);
cell = new Cell().Add(new Paragraph("A3")).AddStyle(noBorder);
cell.SetNextRenderer(new DottedHeaderCellRenderer(cell));
table.AddCell(cell);
table.AddCell(new Cell().Add(new Paragraph("B1")).AddStyle(noBorder));
table.AddCell(new Cell().Add(new Paragraph("B2")).AddStyle(noBorder));
table.AddCell(new Cell().Add(new Paragraph("B3")).AddStyle(noBorder));
table.AddCell(new Cell().Add(new Paragraph("C1")).AddStyle(noBorder));
table.AddCell(new Cell().Add(new Paragraph("C2")).AddStyle(noBorder));
table.AddCell(new Cell().Add(new Paragraph("C3")).AddStyle(noBorder));
doc.Add(table);
doc.Close();
}
private class DottedHeaderTableRenderer : TableRenderer
{
public DottedHeaderTableRenderer(Table modelElement, Table.RowRange rowRange)
: base(modelElement, rowRange)
{
}
// If renderer overflows on the next area, iText uses getNextRender() method to create a renderer for the overflow part.
// If getNextRenderer isn't overriden, the default method will be used and thus a default rather than custom
// renderer will be created
public override IRenderer GetNextRenderer()
{
return new DottedHeaderTableRenderer((Table) modelElement, rowRange);
}
public override void DrawChildren(DrawContext drawContext)
{
base.DrawChildren(drawContext);
PdfCanvas canvas = drawContext.GetCanvas();
Rectangle headersArea = headerRenderer.GetOccupiedArea().GetBBox();
canvas.SetLineDash(3f, 3f);
canvas.MoveTo(headersArea.GetLeft(), headersArea.GetTop());
canvas.LineTo(headersArea.GetRight(), headersArea.GetTop());
canvas.MoveTo(headersArea.GetLeft(), headersArea.GetBottom());
canvas.LineTo(headersArea.GetRight(), headersArea.GetBottom());
canvas.Stroke();
}
}
private class DottedHeaderCellRenderer : CellRenderer
{
public DottedHeaderCellRenderer(Cell modelElement)
: base(modelElement)
{
}
// If renderer overflows on the next area, iText uses getNextRender() method to create a renderer for the overflow part.
// If getNextRenderer isn't overriden, the default method will be used and thus a default rather than custom
// renderer will be created
public override IRenderer GetNextRenderer()
{
return new DottedHeaderCellRenderer((Cell) modelElement);
}
public override void Draw(DrawContext drawContext)
{
base.Draw(drawContext);
PdfCanvas canvas = drawContext.GetCanvas();
Rectangle bbox = GetOccupiedArea().GetBBox();
canvas.SetLineDash(3f, 3f);
canvas.MoveTo(bbox.GetLeft(), bbox.GetBottom());
canvas.LineTo(bbox.GetRight(), bbox.GetBottom());
canvas.MoveTo(bbox.GetLeft(), bbox.GetTop());
canvas.LineTo(bbox.GetRight(), bbox.GetTop());
canvas.Stroke();
}
}
}
}
roundedcorners
JAVA
JAVA
/*
This file is part of the iText (R) project.
Copyright (c) 1998-2023 Apryse Group NV
Authors: Apryse Software.
For more information, please contact iText Software at this address:
sales@itextpdf.com
*/
package com.itextpdf.samples.sandbox.tables;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Cell;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.properties.BorderCollapsePropertyValue;
import com.itextpdf.layout.properties.BorderRadius;
import com.itextpdf.layout.properties.UnitValue;
import java.io.File;
public class RoundedCorners {
public static final String DEST = "./target/sandbox/tables/rounded_corners.pdf";
public static void main(String[] args) throws Exception {
File file = new File(DEST);
file.getParentFile().mkdirs();
new RoundedCorners().manipulatePdf(DEST);
}
protected void manipulatePdf(String dest) throws Exception {
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
Document doc = new Document(pdfDoc);
Table table = new Table(UnitValue.createPercentArray(3)).useAllAvailableWidth();
// By default iText collapses borders and draws them on table level.
// In this sample, however, we want each cell to draw its borders separately,
// that's why we need to override border collapse.
table.setBorderCollapse(BorderCollapsePropertyValue.SEPARATE);
// Sets horizontal spacing between all the table's cells. See css's border-spacing for more information.
table.setHorizontalBorderSpacing(5);
Cell cell = getCell("These cells have rounded borders at the top.");
table.addCell(cell);
cell = getCell("These cells aren't rounded at the bottom.");
table.addCell(cell);
cell = getCell("A custom cell event was used to achieve this.");
table.addCell(cell);
doc.add(table);
doc.close();
}
private static Cell getCell(String content) {
Cell cell = new Cell().add(new Paragraph(content));
cell.setBorderTopRightRadius(new BorderRadius(4));
cell.setBorderTopLeftRadius(new BorderRadius(4));
return cell;
}
}
C#
C#
using System;
using System.IO;
using iText.Kernel.Pdf;
using iText.Layout;
using iText.Layout.Element;
using iText.Layout.Properties;
namespace iText.Samples.Sandbox.Tables
{
public class RoundedCorners
{
public static readonly string DEST = "results/sandbox/tables/rounded_corners.pdf";
public static void Main(String[] args)
{
FileInfo file = new FileInfo(DEST);
file.Directory.Create();
new RoundedCorners().ManipulatePdf(DEST);
}
private void ManipulatePdf(String dest)
{
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
Document doc = new Document(pdfDoc);
Table table = new Table(UnitValue.CreatePercentArray(3)).UseAllAvailableWidth();
// By default iText collapses borders and draws them on table level.
// In this sample, however, we want each cell to draw its borders separately,
// that's why we need to override border collapse.
table.SetBorderCollapse(BorderCollapsePropertyValue.SEPARATE);
// Sets horizontal spacing between all the table's cells. See css's border-spacing for more information.
table.SetHorizontalBorderSpacing(5);
Cell cell = GetCell("These cells have rounded borders at the top.");
table.AddCell(cell);
cell = GetCell("These cells aren't rounded at the bottom.");
table.AddCell(cell);
cell = GetCell("A custom cell event was used to achieve this.");
table.AddCell(cell);
doc.Add(table);
doc.Close();
}
private static Cell GetCell(String content)
{
Cell cell = new Cell().Add(new Paragraph(content));
cell.SetBorderTopRightRadius(new BorderRadius(4));
cell.SetBorderTopLeftRadius(new BorderRadius(4));
return cell;
}
}
}
tableborder
JAVA
JAVA
/*
This file is part of the iText (R) project.
Copyright (c) 1998-2023 Apryse Group NV
Authors: Apryse Software.
For more information, please contact iText Software at this address:
sales@itextpdf.com
*/
package com.itextpdf.samples.sandbox.tables;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.borders.Border;
import com.itextpdf.layout.element.Cell;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.properties.UnitValue;
import com.itextpdf.layout.renderer.DrawContext;
import com.itextpdf.layout.renderer.IRenderer;
import com.itextpdf.layout.renderer.TableRenderer;
import java.io.File;
public class TableBorder {
public static final String DEST = "./target/sandbox/tables/tables_border.pdf";
public static void main(String[] args) throws Exception {
File file = new File(DEST);
file.getParentFile().mkdirs();
new TableBorder().manipulatePdf(DEST);
}
protected void manipulatePdf(String dest) throws Exception {
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
Document doc = new Document(pdfDoc);
Table table = new Table(UnitValue.createPercentArray(4)).useAllAvailableWidth();
for (int aw = 0; aw < 16; aw++) {
table.addCell(new Cell().add(new Paragraph("hi")).setBorder(Border.NO_BORDER));
}
// Notice that one should set renderer after cells are added to the table
table.setNextRenderer(new TableBorderRenderer(table));
doc.add(table);
doc.close();
}
private static class TableBorderRenderer extends TableRenderer {
public TableBorderRenderer(Table modelElement) {
super(modelElement);
}
// If a renderer overflows on the next area, iText uses #getNextRenderer() method to create a new renderer for the overflow part.
// If #getNextRenderer() isn't overridden, the default method will be used and thus the default rather than the custom
// renderer will be created
@Override
public IRenderer getNextRenderer() {
return new TableBorderRenderer((Table) modelElement);
}
@Override
protected void drawBorders(DrawContext drawContext) {
Rectangle rect = getOccupiedAreaBBox();
drawContext.getCanvas()
.saveState()
.rectangle(rect.getLeft(), rect.getBottom(), rect.getWidth(), rect.getHeight())
.stroke()
.restoreState();
}
}
}
C#
C#
using System;
using System.IO;
using iText.Kernel.Geom;
using iText.Kernel.Pdf;
using iText.Layout;
using iText.Layout.Borders;
using iText.Layout.Element;
using iText.Layout.Properties;
using iText.Layout.Renderer;
namespace iText.Samples.Sandbox.Tables
{
public class TableBorder
{
public static readonly string DEST = "results/sandbox/tables/tables_border.pdf";
public static void Main(String[] args)
{
FileInfo file = new FileInfo(DEST);
file.Directory.Create();
new TableBorder().ManipulatePdf(DEST);
}
private void ManipulatePdf(String dest)
{
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
Document doc = new Document(pdfDoc);
Table table = new Table(UnitValue.CreatePercentArray(4)).UseAllAvailableWidth();
for (int aw = 0; aw < 16; aw++)
{
table.AddCell(new Cell().Add(new Paragraph("hi")).SetBorder(Border.NO_BORDER));
}
// Notice that one should set renderer after cells are added to the table
table.SetNextRenderer(new TableBorderRenderer(table));
doc.Add(table);
doc.Close();
}
private class TableBorderRenderer : TableRenderer
{
public TableBorderRenderer(Table modelElement)
: base(modelElement)
{
}
// If renderer overflows on the next area, iText uses getNextRender() method to create a renderer for the overflow part.
// If getNextRenderer isn't overriden, the default method will be used and thus a default rather than custom
// renderer will be created
public override IRenderer GetNextRenderer()
{
return new TableBorderRenderer((Table) modelElement);
}
protected override void DrawBorders(DrawContext drawContext)
{
Rectangle rect = GetOccupiedAreaBBox();
drawContext.GetCanvas()
.SaveState()
.Rectangle(rect.GetLeft(), rect.GetBottom(), rect.GetWidth(), rect.GetHeight())
.Stroke()
.RestoreState();
}
}
}
}