iTextSharp 7 对象引用未设置为对象的实例
iTextSharp 7 object reference not set to an instance of an object
是否建议使用包含段落的单元格来构建 tables,以避免在将某些单元格添加到 table 或 table 以记录时出现异常?我明白了,但我不知道会发生什么:
[NullReferenceException: Object reference not set to an instance of an object.]
iText.Layout.Renderer.TableRenderer.DrawBorders(DrawContext drawContext) +2493
iText.Layout.Renderer.TableRenderer.DrawChildren(DrawContext drawContext) +1497
iText.Layout.Renderer.AbstractRenderer.Draw(DrawContext drawContext) +153
iText.Layout.Renderer.TableRenderer.Draw(DrawContext drawContext) +637
iText.Layout.Renderer.AbstractRenderer.DrawChildren(DrawContext drawContext) +104
iText.Layout.Renderer.BlockRenderer.Draw(DrawContext drawContext) +525
iText.Layout.Renderer.TableRenderer.DrawChildren(DrawContext drawContext) +1382
iText.Layout.Renderer.AbstractRenderer.Draw(DrawContext drawContext) +153
iText.Layout.Renderer.TableRenderer.Draw(DrawContext drawContext) +637
iText.Layout.Renderer.DocumentRenderer.FlushSingleRenderer(IRenderer resultRenderer) +473
iText.Layout.Renderer.RootRenderer.AddChild(IRenderer renderer) +1999
iText.Layout.RootElement`1.Add(BlockElement`1 element) +92
iText.Layout.Document.Add(BlockElement`1 element) +81
这是使用 Windows 控制台项目的简单快照(与真实项目相比):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using iText.Layout;
using iText.Layout.Borders;
using iText.Layout.Element;
namespace iTextTest
{
public static class iTextSharpHelper
{
public static T SetBorderEx<T>(this ElementPropertyContainer<T> element, Border border)
where T : ElementPropertyContainer<T>
{
element.SetBorder(border);
return (T)element;
}
public static Paragraph Style(this BlockElement<Paragraph> element)
{
element
.SetBorderEx(iText.Layout.Borders.Border.NO_BORDER)
.SetFont(iText.Kernel.Font.PdfFontFactory.CreateFont(iText.IO.Font.FontConstants.HELVETICA))
.SetFontSize(10.0f)
.SetFixedLeading(12.0f)
.SetVerticalAlignment(iText.Layout.Properties.VerticalAlignment.BOTTOM)
.SetMargin(0f);
return (Paragraph)element;
}
}
class Program
{
private static float[] tableColumns = { 0.35f, 0.25f, 0.15f, 0.25f };
static void Main(string[] args)
{
iText.Kernel.Pdf.PdfDocument pdf = new iText.Kernel.Pdf.PdfDocument(new iText.Kernel.Pdf.PdfWriter("test.pdf"));
iText.Layout.Document document = new iText.Layout.Document(pdf, iText.Kernel.Geom.PageSize.A4);
document.SetMargins(50f, 50f, 25f, 50f);
iText.Layout.Element.Table mainTable = new iText.Layout.Element.Table(tableColumns)
.SetBorderEx(iText.Layout.Borders.Border.NO_BORDER)
.SetWidthPercent(100)
.SetHorizontalAlignment(iText.Layout.Properties.HorizontalAlignment.LEFT)
.SetPadding(0f);
for (int i = 0; i < 10; i++)
{
AddRow(mainTable, "ABCDEFGHIJ", "ABCDEFGHIJ", "ABCDEFGHIJ");
}
document.Add(mainTable);
document.Close();
}
private static void AddRow(iText.Layout.Element.Table table, string col1, string col2, string col3)
{
// Label
AddCell(table, col1, true)
.SetBorderTop(new iText.Layout.Borders.SolidBorder(iText.Kernel.Colors.Color.BLACK, 0.5f));
// Product - Voucher and price/pcs
AddCell(table, col2, true)
.SetBorderTop(new iText.Layout.Borders.SolidBorder(iText.Kernel.Colors.Color.BLACK, 0.5f));
// Message
AddCell(table, col3, true, 2)
.SetBorderTop(new iText.Layout.Borders.SolidBorder(iText.Kernel.Colors.Color.BLACK, 0.5f))
//.SetBorderRight(new iText.Layout.Borders.SolidBorder(iText.Kernel.Colors.Color.BLACK, 0.5f))
.SetHorizontalAlignment(iText.Layout.Properties.HorizontalAlignment.RIGHT)
.SetTextAlignment(iText.Layout.Properties.TextAlignment.RIGHT);
}
private static iText.Layout.Element.Cell AddCell(iText.Layout.Element.Table table, string text, bool setBold = false, int colSpan = 1)
{
iText.Layout.Element.Cell cell = new iText.Layout.Element.Cell(1, colSpan)
.SetBorderEx(iText.Layout.Borders.Border.NO_BORDER)
.SetVerticalAlignment(iText.Layout.Properties.VerticalAlignment.BOTTOM);
if (!string.IsNullOrEmpty(text))
{
iText.Layout.Element.Paragraph paragraph = new iText.Layout.Element.Paragraph(text)
.Style();
if (setBold)
paragraph.SetBold();
cell.Add(paragraph);
}
table.AddCell(cell);
return cell;
}
}
}
注意,注释掉的代码行:
//.SetBorderRight(new iText.Layout.Borders.SolidBorder(iText.Kernel.Colors.Color.BLACK, 0.5f))
添加它作为一种解决方法,使文档呈现无异常。
鉴于 OP 添加的示例代码,问题很容易重现。
此外,在将代码移植到 iText/Java 之后,该问题也可以在那里重现,请参见。 MikesTableIssue.java test method testMikesCode。因此,从 Java(原始 iText 代码)到 C# 没有移植错误。
示例甚至可以大大简化并仍然重现问题:
try ( FileOutputStream target = new FileOutputStream("mikesTableIssueSimple.pdf");
PdfWriter pdfWriter = new PdfWriter(target);
PdfDocument pdfDocument = new PdfDocument(pdfWriter) )
{
Document document = new Document(pdfDocument);
Table mainTable = new Table(1);
Cell cell = new Cell()
.setBorder(Border.NO_BORDER)
//.setBorderRight(new SolidBorder(Color.BLACK, 0.5f))
.setBorderTop(new SolidBorder(Color.BLACK, 0.5f));
cell.add("TESCHTINK");
mainTable.addCell(cell);
document.add(mainTable);
}
(MikesTableIssue.java test method testSimplified
)
如果一个
就不会出现这个问题
- 删除
setBorder(Border.NO_BORDER)
或
- 删除
setBorderTop(new SolidBorder(Color.BLACK, 0.5f))
或
- 添加
setBorderRight(new SolidBorder(Color.BLACK, 0.5f))
.
在这种情况下com.itextpdf.layout.renderer.TableRenderer.drawBorders(DrawContext)
执行这段代码:
if (lastBorder != null) {
if (verticalBorders.get(j).size() > 0) {
if (i == 0) {
x2 += verticalBorders.get(j).get(i).getWidth() / 2;
} else if(i == horizontalBorders.size() - 1 && verticalBorders.get(j).size() >= i - 1 && verticalBorders.get(j).get(i - 1) != null) {
x2 += verticalBorders.get(j).get(i - 1).getWidth() / 2;
}
}
lastBorder.drawCellBorder(drawContext.getCanvas(), x1, y1, x2, y1);
}
而 lastBorder
是 SolidBorder
实例,verticalBorders
是 [[null], [null]]
、j == 1
和 i == 0
。
因此,这里应该引入一些额外的 null
检查。
是否建议使用包含段落的单元格来构建 tables,以避免在将某些单元格添加到 table 或 table 以记录时出现异常?我明白了,但我不知道会发生什么:
[NullReferenceException: Object reference not set to an instance of an object.]
iText.Layout.Renderer.TableRenderer.DrawBorders(DrawContext drawContext) +2493
iText.Layout.Renderer.TableRenderer.DrawChildren(DrawContext drawContext) +1497
iText.Layout.Renderer.AbstractRenderer.Draw(DrawContext drawContext) +153
iText.Layout.Renderer.TableRenderer.Draw(DrawContext drawContext) +637
iText.Layout.Renderer.AbstractRenderer.DrawChildren(DrawContext drawContext) +104
iText.Layout.Renderer.BlockRenderer.Draw(DrawContext drawContext) +525
iText.Layout.Renderer.TableRenderer.DrawChildren(DrawContext drawContext) +1382
iText.Layout.Renderer.AbstractRenderer.Draw(DrawContext drawContext) +153
iText.Layout.Renderer.TableRenderer.Draw(DrawContext drawContext) +637
iText.Layout.Renderer.DocumentRenderer.FlushSingleRenderer(IRenderer resultRenderer) +473
iText.Layout.Renderer.RootRenderer.AddChild(IRenderer renderer) +1999
iText.Layout.RootElement`1.Add(BlockElement`1 element) +92
iText.Layout.Document.Add(BlockElement`1 element) +81
这是使用 Windows 控制台项目的简单快照(与真实项目相比):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using iText.Layout;
using iText.Layout.Borders;
using iText.Layout.Element;
namespace iTextTest
{
public static class iTextSharpHelper
{
public static T SetBorderEx<T>(this ElementPropertyContainer<T> element, Border border)
where T : ElementPropertyContainer<T>
{
element.SetBorder(border);
return (T)element;
}
public static Paragraph Style(this BlockElement<Paragraph> element)
{
element
.SetBorderEx(iText.Layout.Borders.Border.NO_BORDER)
.SetFont(iText.Kernel.Font.PdfFontFactory.CreateFont(iText.IO.Font.FontConstants.HELVETICA))
.SetFontSize(10.0f)
.SetFixedLeading(12.0f)
.SetVerticalAlignment(iText.Layout.Properties.VerticalAlignment.BOTTOM)
.SetMargin(0f);
return (Paragraph)element;
}
}
class Program
{
private static float[] tableColumns = { 0.35f, 0.25f, 0.15f, 0.25f };
static void Main(string[] args)
{
iText.Kernel.Pdf.PdfDocument pdf = new iText.Kernel.Pdf.PdfDocument(new iText.Kernel.Pdf.PdfWriter("test.pdf"));
iText.Layout.Document document = new iText.Layout.Document(pdf, iText.Kernel.Geom.PageSize.A4);
document.SetMargins(50f, 50f, 25f, 50f);
iText.Layout.Element.Table mainTable = new iText.Layout.Element.Table(tableColumns)
.SetBorderEx(iText.Layout.Borders.Border.NO_BORDER)
.SetWidthPercent(100)
.SetHorizontalAlignment(iText.Layout.Properties.HorizontalAlignment.LEFT)
.SetPadding(0f);
for (int i = 0; i < 10; i++)
{
AddRow(mainTable, "ABCDEFGHIJ", "ABCDEFGHIJ", "ABCDEFGHIJ");
}
document.Add(mainTable);
document.Close();
}
private static void AddRow(iText.Layout.Element.Table table, string col1, string col2, string col3)
{
// Label
AddCell(table, col1, true)
.SetBorderTop(new iText.Layout.Borders.SolidBorder(iText.Kernel.Colors.Color.BLACK, 0.5f));
// Product - Voucher and price/pcs
AddCell(table, col2, true)
.SetBorderTop(new iText.Layout.Borders.SolidBorder(iText.Kernel.Colors.Color.BLACK, 0.5f));
// Message
AddCell(table, col3, true, 2)
.SetBorderTop(new iText.Layout.Borders.SolidBorder(iText.Kernel.Colors.Color.BLACK, 0.5f))
//.SetBorderRight(new iText.Layout.Borders.SolidBorder(iText.Kernel.Colors.Color.BLACK, 0.5f))
.SetHorizontalAlignment(iText.Layout.Properties.HorizontalAlignment.RIGHT)
.SetTextAlignment(iText.Layout.Properties.TextAlignment.RIGHT);
}
private static iText.Layout.Element.Cell AddCell(iText.Layout.Element.Table table, string text, bool setBold = false, int colSpan = 1)
{
iText.Layout.Element.Cell cell = new iText.Layout.Element.Cell(1, colSpan)
.SetBorderEx(iText.Layout.Borders.Border.NO_BORDER)
.SetVerticalAlignment(iText.Layout.Properties.VerticalAlignment.BOTTOM);
if (!string.IsNullOrEmpty(text))
{
iText.Layout.Element.Paragraph paragraph = new iText.Layout.Element.Paragraph(text)
.Style();
if (setBold)
paragraph.SetBold();
cell.Add(paragraph);
}
table.AddCell(cell);
return cell;
}
}
}
注意,注释掉的代码行:
//.SetBorderRight(new iText.Layout.Borders.SolidBorder(iText.Kernel.Colors.Color.BLACK, 0.5f))
添加它作为一种解决方法,使文档呈现无异常。
鉴于 OP 添加的示例代码,问题很容易重现。
此外,在将代码移植到 iText/Java 之后,该问题也可以在那里重现,请参见。 MikesTableIssue.java test method testMikesCode。因此,从 Java(原始 iText 代码)到 C# 没有移植错误。
示例甚至可以大大简化并仍然重现问题:
try ( FileOutputStream target = new FileOutputStream("mikesTableIssueSimple.pdf");
PdfWriter pdfWriter = new PdfWriter(target);
PdfDocument pdfDocument = new PdfDocument(pdfWriter) )
{
Document document = new Document(pdfDocument);
Table mainTable = new Table(1);
Cell cell = new Cell()
.setBorder(Border.NO_BORDER)
//.setBorderRight(new SolidBorder(Color.BLACK, 0.5f))
.setBorderTop(new SolidBorder(Color.BLACK, 0.5f));
cell.add("TESCHTINK");
mainTable.addCell(cell);
document.add(mainTable);
}
(MikesTableIssue.java test method testSimplified
)
如果一个
就不会出现这个问题- 删除
setBorder(Border.NO_BORDER)
或 - 删除
setBorderTop(new SolidBorder(Color.BLACK, 0.5f))
或 - 添加
setBorderRight(new SolidBorder(Color.BLACK, 0.5f))
.
在这种情况下com.itextpdf.layout.renderer.TableRenderer.drawBorders(DrawContext)
执行这段代码:
if (lastBorder != null) {
if (verticalBorders.get(j).size() > 0) {
if (i == 0) {
x2 += verticalBorders.get(j).get(i).getWidth() / 2;
} else if(i == horizontalBorders.size() - 1 && verticalBorders.get(j).size() >= i - 1 && verticalBorders.get(j).get(i - 1) != null) {
x2 += verticalBorders.get(j).get(i - 1).getWidth() / 2;
}
}
lastBorder.drawCellBorder(drawContext.getCanvas(), x1, y1, x2, y1);
}
而 lastBorder
是 SolidBorder
实例,verticalBorders
是 [[null], [null]]
、j == 1
和 i == 0
。
因此,这里应该引入一些额外的 null
检查。