如何使用 pdfHtml 和 iText 7 划掉 table 单元格
How to cross out a table cell using pdfHtml and iText 7
我正在尝试显示一个划掉的 table 单元格。
我已经尝试了几十种不同的方法。
我最好的解决方案是使用四个线性渐变,每个角一个(因为不支持透明背景)。
这里的问题是,我必须指定 table 单元格的高度,因此当同一行中任何其他单元格中的文本行数多于预期时,十字不再来自一个角落到一个角落。
我也尝试过使用 background-image
并将 background-size
设置为 100% 100%
。
但是,pdfHtml 不支持 background-size
.
我尝试了多种在 Chrome 中有效的解决方法,但 none 在 pdfHtml 中有效。
有人知道(可能的)解决方案吗?
谢谢,
--Zuzu_Typ--
你试过用 svg 做吗?应该在没有 background-size 属性 的情况下工作。
.diag {
background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' version='1.1' preserveAspectRatio='none' viewBox='0 0 100 100'><path d='M1 0 L0 1 L99 100 L100 99' fill='black' /><path d='M0 99 L99 0 L100 1 L1 100' fill='black' /></svg>");
background-repeat: no-repeat;
background-position: center center;
border: 1px solid red;
}
<div style="background-color: blue;">
<div class="diag" style="width: 300px; height: 100px;"></div>
</div>
pdfHTML最终利用了iText的非常灵活的布局机制。您可以通过自定义单元格的呈现逻辑并将该实现插入 pdfHTML.
来实现您的最终目标
首先,自定义单元格渲染器:
private static class CustomCellRenderer extends CellRenderer {
public CustomCellRenderer(Cell modelElement) {
super(modelElement);
}
@Override
public IRenderer getNextRenderer() {
return new CustomCellRenderer((Cell) modelElement);
}
@Override
public void drawBackground(DrawContext drawContext) {
super.drawBackground(drawContext);
PdfCanvas canvas = drawContext.getCanvas();
Rectangle area = getOccupiedAreaBBox();
canvas.moveTo(area.getLeft(), area.getTop()).lineTo(area.getRight(), area.getBottom());
canvas.moveTo(area.getLeft(), area.getBottom()).lineTo(area.getRight(), area.getTop());
canvas.stroke();
}
}
本质上,我们重用了默认实现,并通过从左下角到右上角和从左上角到右下角画一条线来扩展它。
现在,我们需要为在 pdf 中创建的布局对象使用自定义渲染器HTML。它们是在标签工作者中创建的,因此为 table 单元格定制标签工作者:
private static class CustomTdTagWorker extends TdTagWorker {
public CustomTdTagWorker(IElementNode element,
ProcessorContext context) {
super(element, context);
}
@Override
public IPropertyContainer getElementResult() {
IPropertyContainer cell = super.getElementResult();
if (cell instanceof Cell) {
((Cell) cell).setNextRenderer(new CustomCellRenderer((Cell) cell));
}
return cell;
}
}
缺少的部分是我们需要配置 pdfHTML 以将我们的自定义标签工作者用于 <td>
单元格以及创建自定义标签工作者工厂的方法:
private static class CustomTagWorkerFactory extends DefaultTagWorkerFactory {
@Override
public ITagWorker getCustomTagWorker(IElementNode tag, ProcessorContext context) {
if (TagConstants.TD.equals(tag.name())) {
return new CustomTdTagWorker(tag, context);
}
return super.getCustomTagWorker(tag, context);
}
}
唯一缺少的部分是将自定义标签工人工厂传递给 pdfHTML 本身,这是通过转换器属性完成的:
HtmlConverter.convertToPdf(inFile, outFile, new ConverterProperties().setTagWorkerFactory(new CustomTagWorkerFactory()));
用上面的代码进行以下HTML:
<html>
<head>
<style>
td, th {
border: solid 1px;
}
table {
border-collapse: collapse;
}
</style>
</head>
<body>
<table>
<tbody>
<tr>
<td>Cell 1</td>
<td>Cell 2</td>
</tr>
<tr>
<td>Another cell 1</td>
<td>Another cell 2</td>
</tr>
</tbody>
<tfoot>
<td>
Footer 1
</td>
<td>
Footer 2
</td>
</tfoot>
</table>
</body>
</html>
我在转换为 PDF 后得到了以下视觉效果:
我正在尝试显示一个划掉的 table 单元格。
我已经尝试了几十种不同的方法。
我最好的解决方案是使用四个线性渐变,每个角一个(因为不支持透明背景)。
这里的问题是,我必须指定 table 单元格的高度,因此当同一行中任何其他单元格中的文本行数多于预期时,十字不再来自一个角落到一个角落。
我也尝试过使用 background-image
并将 background-size
设置为 100% 100%
。
但是,pdfHtml 不支持 background-size
.
我尝试了多种在 Chrome 中有效的解决方法,但 none 在 pdfHtml 中有效。
有人知道(可能的)解决方案吗?
谢谢,
--Zuzu_Typ--
你试过用 svg 做吗?应该在没有 background-size 属性 的情况下工作。
.diag {
background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' version='1.1' preserveAspectRatio='none' viewBox='0 0 100 100'><path d='M1 0 L0 1 L99 100 L100 99' fill='black' /><path d='M0 99 L99 0 L100 1 L1 100' fill='black' /></svg>");
background-repeat: no-repeat;
background-position: center center;
border: 1px solid red;
}
<div style="background-color: blue;">
<div class="diag" style="width: 300px; height: 100px;"></div>
</div>
pdfHTML最终利用了iText的非常灵活的布局机制。您可以通过自定义单元格的呈现逻辑并将该实现插入 pdfHTML.
来实现您的最终目标首先,自定义单元格渲染器:
private static class CustomCellRenderer extends CellRenderer {
public CustomCellRenderer(Cell modelElement) {
super(modelElement);
}
@Override
public IRenderer getNextRenderer() {
return new CustomCellRenderer((Cell) modelElement);
}
@Override
public void drawBackground(DrawContext drawContext) {
super.drawBackground(drawContext);
PdfCanvas canvas = drawContext.getCanvas();
Rectangle area = getOccupiedAreaBBox();
canvas.moveTo(area.getLeft(), area.getTop()).lineTo(area.getRight(), area.getBottom());
canvas.moveTo(area.getLeft(), area.getBottom()).lineTo(area.getRight(), area.getTop());
canvas.stroke();
}
}
本质上,我们重用了默认实现,并通过从左下角到右上角和从左上角到右下角画一条线来扩展它。
现在,我们需要为在 pdf 中创建的布局对象使用自定义渲染器HTML。它们是在标签工作者中创建的,因此为 table 单元格定制标签工作者:
private static class CustomTdTagWorker extends TdTagWorker {
public CustomTdTagWorker(IElementNode element,
ProcessorContext context) {
super(element, context);
}
@Override
public IPropertyContainer getElementResult() {
IPropertyContainer cell = super.getElementResult();
if (cell instanceof Cell) {
((Cell) cell).setNextRenderer(new CustomCellRenderer((Cell) cell));
}
return cell;
}
}
缺少的部分是我们需要配置 pdfHTML 以将我们的自定义标签工作者用于 <td>
单元格以及创建自定义标签工作者工厂的方法:
private static class CustomTagWorkerFactory extends DefaultTagWorkerFactory {
@Override
public ITagWorker getCustomTagWorker(IElementNode tag, ProcessorContext context) {
if (TagConstants.TD.equals(tag.name())) {
return new CustomTdTagWorker(tag, context);
}
return super.getCustomTagWorker(tag, context);
}
}
唯一缺少的部分是将自定义标签工人工厂传递给 pdfHTML 本身,这是通过转换器属性完成的:
HtmlConverter.convertToPdf(inFile, outFile, new ConverterProperties().setTagWorkerFactory(new CustomTagWorkerFactory()));
用上面的代码进行以下HTML:
<html>
<head>
<style>
td, th {
border: solid 1px;
}
table {
border-collapse: collapse;
}
</style>
</head>
<body>
<table>
<tbody>
<tr>
<td>Cell 1</td>
<td>Cell 2</td>
</tr>
<tr>
<td>Another cell 1</td>
<td>Another cell 2</td>
</tr>
</tbody>
<tfoot>
<td>
Footer 1
</td>
<td>
Footer 2
</td>
</tfoot>
</table>
</body>
</html>
我在转换为 PDF 后得到了以下视觉效果: