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

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

替代方案对比

方案兼容性许可证功能完整性引用来源
iTextSharp.LGPLv2.Core支持.NET CoreLGPL(开源免费)部分功能异常‌1212
iText 7支持.NET 6.0/8.0商业许可完整功能12
QuestPDF支持.NET 6.0/8.0MIT(开源免费)基础表格/排版-

因为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,能不使用尽量不要使用。