C#.NET4.8-iTextSharp5.5如何转移到.NET8.0中

替代方案对比
iTextSharp.LGPLv2.Core | 支持.NET Core | LGPL(开源免费) | 部分功能异常12 | 12 |
iText 7 | 支持.NET 6.0/8.0 | 商业许可 | 完整功能 | 12 |
QuestPDF | 支持.NET 6.0/8.0 | MIT(开源免费) | 基础表格/排版 | - |
因为iTextSharp免费版最高到5.X版本且最高支持.NET Framework4.8版本,而iTextSharp的iText7版本最高支持.NET8.0版本,但它是商业收费版本,因此需要寻找其他可代替的方案。
一、代替方案
1. 使用QuestPDF(免费替代)
PM> Install-Package QuestPDF
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
Document.Create(container =>
{
container.Page(page =>
{
page.Content().Column(col =>
{
col.Item().Text("报表标题").FontSize(16);
col.Item().Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.RelativeColumn();
columns.RelativeColumn();
});
table.Cell().Text("列1");
table.Cell().Text("列2");
});
});
});
}).GeneratePdf("output.pdf");
优势:MIT协议、无依赖冲突、语法简洁
2、iTextSharp.LGPLv2.Core
iTextSharp.LGPLv2.Core 3.7.1
iTextSharp.LGPLv2.Core is an unofficial port of the last LGPL version of the iTextSharp (V4.1.6) to .NET Core.

iTextSharp.LGPLv2.Core是基于旧版iTextSharp 4.1.6的非官方端口,且不支持高版本ITextSharp的许多功能,并且有严重兼容性问题(表格索引列),下面会提到。
二、使用iTextSharp.LGPLv2.Core表格索引越界问题解决方案
1. 问题根源分析
- 版本差异:
iTextSharp.LGPLv2.Core
基于 iTextSharp 4.1.6 实现,与原版 iTextSharp 5.x 的表格动态列处理逻辑存在差异,导致索引越界。 - 动态列限制:移植版对动态表格的列数变更支持较弱,若未显式定义列数或动态调整时未更新索引,会触发
IndexOutOfRangeException
。
2. 具体解决方法
(1)预定义表格列数
在创建 PdfPTable
时显式指定列数,避免后续操作中动态调整列数导致索引越界
PdfPTable table = new PdfPTable(3); // 明确指定3列
table.AddCell("列1");
table.AddCell("列2");
table.AddCell("列3");
(2)检查索引有效性
访问表格列或行时,先验证索引是否在有效范围内(0 <= index < table.Rows.Count
)
if (rowIndex >= 0 && rowIndex < table.Rows.Count)
{
PdfPRow row = table.Rows[rowIndex];
// 操作行数据
}
else
{
// 处理索引越界逻辑
}
(3)动态数据填充优化
若需动态添加数据,使用 AddCell()
自动换行逻辑,而非手动控制行列索引
foreach (var item in dataList)
{
table.AddCell(item.Value1);
table.AddCell(item.Value2);
table.AddCell(item.Value3);
// 自动换行,无需手动计算行索引
}
(4)异常捕获与回退
使用 try-catch
捕获索引越界异常,并记录日志或提供默认值
try
{
PdfPCell cell = row.GetCell(columnIndex);
}
catch (IndexOutOfRangeException ex)
{
// 记录错误或返回空单元格
PdfPCell defaultCell = new PdfPCell(new Phrase("N/A"));
}
三、使用iTextSharp.LGPLv2.Core实战演示
#region 磅条生成单个分单的PDF
if (cargoId > 0 )
{
var item = aircargoresult[0];//有空运订舱货物明细主键时,一定是一条货物信息明细
#region 赋值
productHAWB = item.ProductHAWB;//分单号
piece = item.Piece.ToString();//件数
productWeight = Math.Round(Convert.ToDouble(item.GrossWeight)).ToString();//重量/毛重
productVolume = Math.Round(Convert.ToDecimal(item.Volume), 3, MidpointRounding.AwayFromZero).ToString();//实际体积
productSize = item.Size;//尺寸
productCName = item.CNProductName;//申报货物品名清单(中文)
productEName = item.ENProductName;//申报货物品名清单(英文)
#endregion
#region 生成磅条
var doc = new iTextSharp.text.Document();
//服务器本地存储路径
string pdfPath = Path.Combine(App.WebHostEnvironment.WebRootPath, uploadpath);
if (!Directory.Exists(pdfPath))
{
Directory.CreateDirectory(pdfPath);
}
filename = mawb + "_" + productHAWB + "磅条";
filenamesuffix = filename + ".pdf";
PdfWriter writer = PdfWriter.GetInstance(doc, new FileStream(pdfPath + filename + ".pdf", FileMode.Create));
//外链地址
filedownPath = $"{GetHost()}/{filePath}/{filenamesuffix}";
#region 写入PDF文件
doc.Open();
iTextSharp.text.Font smallfont = new iTextSharp.text.Font(BaseFontAndSize("宋体", 10, iTextSharp.text.Font.NORMAL, BaseColor.Red));
iTextSharp.text.Font font = new iTextSharp.text.Font(BaseFontAndSize("宋体", 13, iTextSharp.text.Font.NORMAL, BaseColor.Black));
iTextSharp.text.Font fonter = new iTextSharp.text.Font(BaseFontAndSize("宋体", 18, iTextSharp.text.Font.NORMAL, BaseColor.Black));
iTextSharp.text.Font largefont = new iTextSharp.text.Font(BaseFontAndSize("宋体", 38, iTextSharp.text.Font.NORMAL, BaseColor.Black));
//添加保单表头图片信息
PdfPTable tableweight = new PdfPTable(4);
tableweight.WidthPercentage = 96;
tableweight.HorizontalAlignment = iTextSharp.text.Element.ALIGN_LEFT;
//设置每个单元格的宽度比例
tableweight.SetWidths(new int[] { 25, 25, 25, 25 });
// 添加标题行(占满4列)
PdfPCell celltitle = new PdfPCell(new Phrase("胶东机场国际货场部货物分单收运磅条", fonter));
celltitle.HorizontalAlignment = iTextSharp.text.Element.ALIGN_CENTER;
celltitle.VerticalAlignment = iTextSharp.text.Element.ALIGN_MIDDLE;
celltitle.BorderWidth = 0;
celltitle.Padding = 4;
celltitle.Colspan = 4;
tableweight.AddCell(celltitle);
// 添加第二行:左侧3列合并 + 右侧1列
PdfPCell celltiao = new PdfPCell(new Phrase("", font));
celltiao.HorizontalAlignment = Element.ALIGN_CENTER;
celltiao.VerticalAlignment = Element.ALIGN_MIDDLE;
celltiao.BorderWidth = 0;
celltiao.PaddingLeft = 125;
celltiao.Colspan = 3;
tableweight.AddCell(celltiao);
PdfPCell cellnum = new PdfPCell(new Phrase("", smallfont));
cellnum.HorizontalAlignment = Element.ALIGN_RIGHT;
cellnum.VerticalAlignment = Element.ALIGN_MIDDLE;
cellnum.BorderWidth = 0;
cellnum.Padding = 4;
cellnum.Colspan = 1;// 显式指定占1列
tableweight.AddCell(cellnum);
// 添加第三行:代理公司信息(占1列)
PdfPCell cellhuodai = new PdfPCell(new Phrase("代理公司:" + huoDai, font));
cellhuodai.HorizontalAlignment = Element.ALIGN_LEFT;
cellhuodai.VerticalAlignment = Element.ALIGN_MIDDLE;
cellhuodai.BorderWidth = 0;
cellhuodai.Padding = 10;
cellhuodai.Colspan = 1;
tableweight.AddCell(cellhuodai);
// 添加空单元格(占2列)
PdfPCell cellcode = new PdfPCell(new Phrase("", font));
cellcode.HorizontalAlignment = Element.ALIGN_CENTER;
cellcode.BorderWidth = 0;
cellcode.VerticalAlignment = Element.ALIGN_MIDDLE;
cellcode.Padding = 4;
cellcode.Colspan = 2;
tableweight.AddCell(cellcode);
// 添加日期单元格(占1列)
PdfPCell celldate = new PdfPCell(new Phrase(khdate.ToString("yyyy年MM月dd日"), font));//dtnow.ToString("yyyy年MM月dd日")
celldate.HorizontalAlignment = Element.ALIGN_RIGHT;
celldate.BorderWidth = 0;
celldate.VerticalAlignment = Element.ALIGN_MIDDLE;
celldate.Padding = 10;
celldate.Colspan = 1;
tableweight.AddCell(celldate);
// 添加第四行
PdfPCell cellmawb = new PdfPCell(new Phrase("主单号", font));
cellmawb.HorizontalAlignment = Element.ALIGN_CENTER;
cellmawb.VerticalAlignment = Element.ALIGN_MIDDLE;
cellmawb.Padding = 4;
cellmawb.Colspan = 1;
tableweight.AddCell(cellmawb);
PdfPCell txtmawb = new PdfPCell(new Phrase(mawb, font));
txtmawb.HorizontalAlignment = Element.ALIGN_LEFT;
txtmawb.VerticalAlignment = Element.ALIGN_MIDDLE;
txtmawb.Padding = 4;
txtmawb.Colspan = 1;
tableweight.AddCell(txtmawb);
PdfPCell cellflight = new PdfPCell(new Phrase("航班号", font));
cellflight.HorizontalAlignment = Element.ALIGN_CENTER;
cellflight.VerticalAlignment = Element.ALIGN_MIDDLE;
cellflight.Padding = 4;
cellflight.Colspan = 1;
tableweight.AddCell(cellflight);
PdfPCell txtflight = new PdfPCell(new Phrase(voyageNo, font));
txtflight.HorizontalAlignment = Element.ALIGN_LEFT;
txtflight.VerticalAlignment = Element.ALIGN_MIDDLE;
txtflight.Padding = 4;
txtflight.Colspan = 1;
tableweight.AddCell(txtflight);
// 添加第五行
PdfPCell cellhawb = new PdfPCell(new Phrase("分单号", font));
cellhawb.HorizontalAlignment = Element.ALIGN_CENTER;
cellhawb.VerticalAlignment = Element.ALIGN_MIDDLE;
cellhawb.Padding = 4;
cellhawb.Colspan = 1;
tableweight.AddCell(cellhawb);
PdfPCell txthawb = new PdfPCell(new Phrase(productHAWB, font));
txthawb.HorizontalAlignment = Element.ALIGN_LEFT;
txthawb.VerticalAlignment = Element.ALIGN_MIDDLE;
txthawb.Padding = 4;
txthawb.Colspan = 3;
tableweight.AddCell(txthawb);
// 添加第六行
PdfPCell cellpiece = new PdfPCell(new Phrase("件数", font));
cellpiece.HorizontalAlignment = Element.ALIGN_CENTER;
cellpiece.VerticalAlignment = Element.ALIGN_MIDDLE;
cellpiece.Padding = 4;
cellpiece.Colspan = 1;
tableweight.AddCell(cellpiece);
PdfPCell txtpiece = new PdfPCell(new Phrase(piece, font));
txtpiece.HorizontalAlignment = Element.ALIGN_LEFT;
txtpiece.VerticalAlignment = Element.ALIGN_MIDDLE;
txtpiece.Padding = 4;
txtpiece.Colspan = 1;
tableweight.AddCell(txtpiece);
PdfPCell cellweight = new PdfPCell(new Phrase("重量(公斤)", font));
cellweight.HorizontalAlignment = Element.ALIGN_CENTER;
cellweight.VerticalAlignment = Element.ALIGN_MIDDLE;
cellweight.Padding = 4;
cellweight.Colspan = 1;
tableweight.AddCell(cellweight);
PdfPCell txtweight = new PdfPCell(new Phrase(productWeight, font));
txtweight.HorizontalAlignment = Element.ALIGN_LEFT;
txtweight.VerticalAlignment = Element.ALIGN_MIDDLE;
txtweight.Padding = 4;
txtweight.Colspan = 1;
tableweight.AddCell(txtweight);
// 添加第七行
PdfPCell cellsize = new PdfPCell(new Phrase("尺寸", font));
cellsize.HorizontalAlignment = Element.ALIGN_CENTER;
cellsize.VerticalAlignment = Element.ALIGN_MIDDLE;
cellsize.Padding = 4;
//cellsize.Rowspan = 4;
cellsize.Colspan = 1;
tableweight.AddCell(cellsize);
PdfPCell txtsize = new PdfPCell(new Phrase(productSize, font));
txtsize.HorizontalAlignment = Element.ALIGN_LEFT;
txtsize.VerticalAlignment = Element.ALIGN_MIDDLE;
txtsize.Padding = 4;
//txtsize.Rowspan = 4;
txtsize.Colspan = 2;
tableweight.AddCell(txtsize);
PdfPCell txtvol = new PdfPCell(new Phrase("体积:" + productVolume, font));
txtvol.HorizontalAlignment = Element.ALIGN_LEFT;
txtvol.VerticalAlignment = Element.ALIGN_MIDDLE;
txtvol.Padding = 4;
//txtvol.Rowspan = 4;
txtvol.Colspan = 1;
tableweight.AddCell(txtvol);
#region 申报货物清单
// 添加第八行
PdfPCell cellen = new PdfPCell(new Phrase("申报货物品名清单(英文)", font));
cellen.HorizontalAlignment = Element.ALIGN_LEFT;
cellen.VerticalAlignment = Element.ALIGN_MIDDLE;
cellen.Padding = 4;
//cellen.Rowspan = 4;
cellen.Colspan = 1;
tableweight.AddCell(cellen);
PdfPCell txten = new PdfPCell(new Phrase(productEName, font));
txten.HorizontalAlignment = Element.ALIGN_LEFT;
txten.VerticalAlignment = Element.ALIGN_MIDDLE;
txten.Padding = 4;
//txten.Rowspan = 4;
txten.Colspan = 3;
tableweight.AddCell(txten);
// 添加第九行
PdfPCell cellcn = new PdfPCell(new Phrase("申报货物品名清单(中文)", font));
cellcn.HorizontalAlignment = Element.ALIGN_LEFT;
cellcn.VerticalAlignment = Element.ALIGN_MIDDLE;
cellcn.Padding = 4;
//cellcn.Rowspan = 4;
cellcn.Colspan = 1;
tableweight.AddCell(cellcn);
PdfPCell txtcn = new PdfPCell(new Phrase(productCName, font));
txtcn.HorizontalAlignment = Element.ALIGN_LEFT;
txtcn.VerticalAlignment = Element.ALIGN_MIDDLE;
txtcn.Padding = 4;
//txtcn.Rowspan = 4;
txtcn.Colspan = 3;
tableweight.AddCell(txtcn);
#endregion
//cell.DisableBorderSide(1);//隐藏上边框
//cell.DisableBorderSide(2);//隐藏下边框
//cell.DisableBorderSide(4);//隐藏左边框
//cell.DisableBorderSide(8);//隐藏右边框
//cell.DisableBorderSide(15);//隐藏全部边框
// 添加第十行
PdfPCell cellms = new PdfPCell(new Phrase("上述货物均如实申报货物品名,无瞒报、夹带、伪报违禁品及危险品", font));
cellms.HorizontalAlignment = Element.ALIGN_LEFT;
cellms.VerticalAlignment = Element.ALIGN_MIDDLE;
cellms.Padding = 5;
cellms.Colspan = 4;//列
cellms.DisableBorderSide(2);//隐藏下边框
tableweight.AddCell(cellms);
// 添加第十一行
PdfPCell cellyqqz = new PdfPCell(new Phrase("交货员:", font));
cellyqqz.HorizontalAlignment = Element.ALIGN_LEFT;
cellyqqz.VerticalAlignment = Element.ALIGN_MIDDLE;
cellyqqz.Padding = 10;
cellyqqz.Colspan = 2;
cellyqqz.DisableBorderSide(9);
tableweight.AddCell(cellyqqz);
PdfPCell celldlqz = new PdfPCell(new Phrase("", font));
celldlqz.HorizontalAlignment = Element.ALIGN_LEFT;
celldlqz.VerticalAlignment = Element.ALIGN_MIDDLE;
celldlqz.Padding = 10;
celldlqz.Colspan = 2;
celldlqz.DisableBorderSide(5);
tableweight.AddCell(celldlqz);
doc.Add(tableweight);
doc.Close();
#endregion
#endregion
}
#endregion
以上为ITextSharp5.X版本转移到iTextSharp.LGPLv2.Core的代码,具体改动和遇到的问题如下:
(1)与转移前一样,先预定义我创建表格的列数,以及列的宽度。
(2)添加行时与转移之前不一样,如果使用到了colspan参数,则每个表格行添加时必须书写该参数赋值,最小值为1列colspan=1,不能省略!因为该社区维护版本对行列排列不够智能,必须手动控制其列数,否则会出现之前说的索引越界问题。
(3)在转移过来后,我移除了所有使用跨行rowspan参数的地方,因为使用该版本rowspan有许多限制,一个是跟colspan一样,若使用则每个添加行的地方都需要赋值,还有关于该属性有许多BUG,能不使用尽量不要使用。