C#生成pdf -- iText7 设置自定义字体和表格
itextsharp已经不再更新,由iText 7来替代
安装
nuget 安装 itext7

注册自定义字体
下载字体文件 .ttc或.ttf到项目目录,设置更新则拷贝到输出目录,这样构建的时候会把字体文件拷贝过去

windows系统自带黑体, 可以直接复制到项目目录, 其路径是
C:\Windows\Fonts\simhei.ttf
因为字体注册只需要一次,所以建议放到StartUp中. 其中的simhei.ttf换为你的字体文件
iText.Kernel.Font.PdfFontFactory.Register("simhei.ttf");

新建pdf文档
using PdfWriter writer = new ("list.pdf");
PdfDocument pdf = new (writer);
Document doc = new (pdf);
PdfWriter可以传入pdf文件目标路径或者Stream,如果不想保存到本地,那用MemoryStream保存在内存中即可. 后边的例子我们就是直接用MemoryStream来保存数据
设置字体
PdfFont sysFont = PdfFontFactory.CreateRegisteredFont("simhei", PdfEncodings.IDENTITY_H, PdfFontFactory.EmbeddingStrategy.PREFER_EMBEDDED, true);
doc.SetFont(sysFont)
.SetFontSize(12);//设置字体大小
示例
public class OrderDto
{
public string Name { get; set; } public string Gender { get; set; } public string Address { get; set; } public string Phone { get; set; } public List<ProductDto> Products { get; set; } public string Remark { get; set; }
} public class ProductDto
{
public string Code { get; set; } public string Name { get; set; } public string Category { get; set; } public string Unit { get; set; } public string Sku { get; set; } public decimal Price { get; set; } public int Quantity { get; set; }
}
[HttpGet("pdf")]
public IActionResult ExportPdf()
{
MemoryStream stream = new ();
PdfWriter writer = new (stream);
PdfDocument pdf = new (writer);
Document doc = new (pdf);
//黑体
PdfFont sysFont = PdfFontFactory.CreateRegisteredFont("simhei", PdfEncodings.IDENTITY_H, PdfFontFactory.EmbeddingStrategy.PREFER_EMBEDDED, true);
doc.SetFont(sysFont)
.SetFontSize(12);//设置字体大小
doc.Add(new Paragraph("订单列表")
.SetBold()//粗体
.SetTextAlignment(iText.Layout.Properties.TextAlignment.CENTER)//居中
);
var headerTexts = new[] {
"序号", "姓名", "性别", "居住地址", "联系电话",
"货号", "产品名称", "分类", "单位", "规格", "售价", "数量",
"备注"
};
var table = new Table(headerTexts.Length) // 设置表格列数
.SetTextAlignment(iText.Layout.Properties.TextAlignment.CENTER)
;
//添加表头
foreach (var header in headerTexts)
{
table.AddHeaderCell(new Cell()
.Add(new Paragraph(header))
.SetBold()//设置粗体
);
}
var orders = new[]
{
new OrderDto
{
Name = "法外", Gender = "男", Address = "江苏省南京市江宁区梧桐路325号", Phone = "13545781245", Remark = "就这?",
Products = new List<ProductDto>{ new ProductDto { Code="XGRD102", Name = "格子衫", Category = "男装", Unit = "件", Sku = "紫色", Price = 39, Quantity = 1} }
},
new OrderDto
{
Name = "狂徒", Gender = "男", Address = "重庆市江北区朝鸽大道北777号", Phone = "15845568956", Remark = "代码敲得好,备胎当到老",
Products = new List<ProductDto>
{
new ProductDto { Code="FUS458", Name = "Amd R7 5800X", Category = "电子产品", Unit = "个", Sku = "盒装", Price = 2499, Quantity = 1},
new ProductDto { Code="TFES982", Name = "程序员帽子", Category = "配饰", Unit = "件", Sku = "绿色", Price = 666, Quantity = 1},
}
},
new OrderDto
{
Name = "张三", Gender = "女", Address = "辽宁省大连市甘井子区伞兵路2333号", Phone = "15952415263", Remark = "rnm, 退钱!!!",
Products = new List<ProductDto>{ new ProductDto { Code="TOP10", Name = "Rnm,退钱同款长袖", Category = "男装", Unit = "件", Sku = "红色", Price = 69, Quantity = 1} }
},
};
for (int i = 0; i < orders.Length; i++)
{
int rowSpan = orders[i].Products.Count;//商品行有多少个,基本信息列就要跨对应多少行
table.StartNewRow();//第一列开启新行
table
.AddCell(new Cell(rowSpan,1).Add(new Paragraph((i + 1).ToString()))//序号
.SetVerticalAlignment(iText.Layout.Properties.VerticalAlignment.MIDDLE))
.AddCell(new Cell(rowSpan, 1).Add(new Paragraph(orders[i].Name)).SetMinWidth(25)//姓名 设置最小列宽25,方便名字横向显示
.SetVerticalAlignment(iText.Layout.Properties.VerticalAlignment.MIDDLE))
.AddCell(new Cell(rowSpan, 1).Add(new Paragraph(orders[i].Gender))//性别
.SetVerticalAlignment(iText.Layout.Properties.VerticalAlignment.MIDDLE))
.AddCell(new Cell(rowSpan, 1).Add(new Paragraph(orders[i].Address))//居住地址
.SetVerticalAlignment(iText.Layout.Properties.VerticalAlignment.MIDDLE))
.AddCell(new Cell(rowSpan, 1).Add(new Paragraph(orders[i].Phone))//联系电话
.SetVerticalAlignment(iText.Layout.Properties.VerticalAlignment.MIDDLE));
//添加一行商品信息 (因为table只能按顺序从左到右一个cell一个cell地加)
table
.AddCell(new Cell(1,1).SetVerticalAlignment(iText.Layout.Properties.VerticalAlignment.MIDDLE)
.Add(new Paragraph(orders[i].Products[0].Code)//货号
))
.AddCell(new Cell().SetVerticalAlignment(iText.Layout.Properties.VerticalAlignment.MIDDLE)
.Add(new Paragraph(orders[i].Products[0].Name)//产品名称
))
.AddCell(new Cell().SetVerticalAlignment(iText.Layout.Properties.VerticalAlignment.MIDDLE)
.Add(new Paragraph(orders[i].Products[0].Category))
.SetMinWidth(25)
)//分类
.AddCell(new Cell().SetVerticalAlignment(iText.Layout.Properties.VerticalAlignment.MIDDLE)
.Add(new Paragraph(orders[i].Products[0].Unit)//单位
))
.AddCell(new Cell()
.SetVerticalAlignment(iText.Layout.Properties.VerticalAlignment.MIDDLE)
.Add(new Paragraph(orders[i].Products[0].Sku)//规格
.SetMinWidth(25)
))
.AddCell(new Cell().SetVerticalAlignment(iText.Layout.Properties.VerticalAlignment.MIDDLE)
.Add(new Paragraph(orders[i].Products[0].Price.ToString("0.00"))//售价
))
.AddCell(new Cell()
.SetVerticalAlignment(iText.Layout.Properties.VerticalAlignment.MIDDLE)
.Add(new Paragraph(orders[i].Products[0].Quantity.ToString())//数量
))
.AddCell(new Cell(rowSpan, 1).SetVerticalAlignment(iText.Layout.Properties.VerticalAlignment.MIDDLE)
.Add(new Paragraph(orders[i].Remark))
);//备注
//商品行大于1, 需要添加多行商品信息
if (orders[i].Products.Count > 1)
{
for (int j = 1; j < orders[i].Products.Count; j++)
{
table
.AddCell(new Cell(1, 1).SetVerticalAlignment(iText.Layout.Properties.VerticalAlignment.MIDDLE)
.Add(new Paragraph(orders[i].Products[j].Code)//货号
))
.AddCell(new Cell().SetVerticalAlignment(iText.Layout.Properties.VerticalAlignment.MIDDLE)
.Add(new Paragraph(orders[i].Products[j].Name)//产品名称
))
.AddCell(new Cell().SetVerticalAlignment(iText.Layout.Properties.VerticalAlignment.MIDDLE)
.Add(new Paragraph(orders[i].Products[j].Category))
.SetMinWidth(25)
)//分类
.AddCell(new Cell().SetVerticalAlignment(iText.Layout.Properties.VerticalAlignment.MIDDLE)
.Add(new Paragraph(orders[i].Products[j].Unit)//单位
))
.AddCell(new Cell()
.SetVerticalAlignment(iText.Layout.Properties.VerticalAlignment.MIDDLE)
.Add(new Paragraph(orders[i].Products[j].Sku)//规格
.SetMinWidth(25)
))
.AddCell(new Cell().SetVerticalAlignment(iText.Layout.Properties.VerticalAlignment.MIDDLE)
.Add(new Paragraph(orders[i].Products[j].Price.ToString("0.00"))//售价
))
.AddCell(new Cell()
.SetVerticalAlignment(iText.Layout.Properties.VerticalAlignment.MIDDLE)
.Add(new Paragraph(orders[i].Products[j].Quantity.ToString())//数量
));
}
}
}
doc.Add(table);
pdf.Close();//记得关闭PdfDocument和PdfWriter
writer.Close();
return File(stream.ToArray(), "application/pdf");
}
结果如下

有几个要点
- 单元格合并是通过跨行或跨列来实现的, new Cell(2, 2)表示此单元格跨2行 2列
- 单元格设置居中最好是放在Add(new Paragraph("xx"))之前
- 添加单元格只能从左到右一个一个地加,所以有合并行的时候要把第一行全部添加完再添加下边的几行,如图所示.

- 新的一行要先调用table.StartNewRow() 然后table.AddCell()才会添加到新行
- 表格的列数是在new Table(13) 时传入的, 传入13就表示有13列
C#生成pdf -- iText7 设置自定义字体和表格的更多相关文章
- Android Studio设置自定义字体
Android Studio设置自定义字体 (1)进入设置页面,File->Settings (2)自定义字体Editor->Colors&Fonts->Font (3)点击 ...
- poi生成excel整理(设置边框/字体/颜色/加粗/居中/)
转: poi生成excel整理(设置边框/字体/颜色/加粗/居中/) 2016年12月02日 11:05:23 吃奶的牛 阅读数:34324 HSSFWorkbook wb = new HSSFW ...
- freemark+ITextRenderer 生成PDF,设置pdf的页面大小
在html中添加样式,仅生成pdf是生效,浏览器展示时是不会生效的: <style> @page{ size : 200mm 300 mm; } </style>
- c# iText 生成PDF 有文字,图片,表格,文字样式,对齐方式,页眉页脚,等等等,
#region 下载说明书PDF protected void lbtnDownPDF_Click(object sender, EventArgs e) { int pid = ConvertHel ...
- PHP生成PDF并转换成图片爬过的坑
需求描述:根据订单通过模板合同生成新的PDF合同通过e签宝签约后转为图片给用户下载. 需求整理: 1.如何生成PDF文件:使用TCPDF扩展生成.思考: ⑴为了方便将模板中的固定占位符替换为订单中的内 ...
- CSS自定义字体的实现,前端实现字体压缩
CSS中使用自定义字体,首先需要下载你需要的字体ttf或者otf文件 这里推荐一个网站:http://www.zitixiazai.org/ /********css中********/ @font- ...
- iOS自定义字体
1.下载字体库,如:DINCond-Bold.otf 2.双击,在mac上安装 3.把下载的字体库拖入工程中: 4.配置info.plist文件 5.xib方式设置自定义字体:Font选Custom, ...
- CSS怎么在项目里引入自定义字体(@font-face)
前言: 以前我一直用内置的默认字体给文字设置字体,直到一天UI妹纸给了我下面的字体 当时我是蒙蔽的,这个字体的效果如下 默认字体并无该字体,直接设置是没有效果的,这时就需要用到自定义字体了 下面 ...
- Java使用iText7生成PDF
前言 我们之前使用js库html2canvas + jspdf实现html转PDF.图片,并下载(详情请戳:html页面转PDF.图片操作记录),大致原理是将页面塞到画布里,以图片的方式放到PDF中, ...
随机推荐
- 《手把手教你》系列技巧篇(四十二)-java+ selenium自动化测试 - 处理iframe -下篇(详解教程)
1.简介 经过宏哥长时间的查找,终于找到了一个含有iframe的网页.所以今天这一篇的主要内容就是用这个网页的iframe,宏哥给小伙伴或者童鞋们演示一下,在处理过程中遇到的问题以及宏哥是如何解决的. ...
- oracle基础:怎样把查询的null转换为0、打印、定义变量
https://blog.csdn.net/xuxile/article/details/49943665 oracle怎样把查询的null转换为0 1.查询的null转换为0 NVL(Expr1,E ...
- ErrorProvider与CheckedListBox
http://www.cnblogs.com/myshell/archive/2010/09/24/1834184.html 最近因为做WinForm的项目,遇到这个问题,当时以为CheckedLis ...
- WinRAR下载
https://www.win-rar.com 垃圾7Z有的解压不了.
- excel的表格数据插入到数据库
看到有excel保存insert的数据,自己照着教程弄了一下,可以的. 表格数据 接下来我们在d3的位置输入 =CONCATENATE("insert into user(code, nam ...
- ARC128D
考虑我们直接\(dp\). 那么需要快速的求出一段是否可以被消掉只剩两端. 我们可以考虑反过来做的. 我们知道如果全为\(abab\)型或者\(aa\)型则无法消掉 那么我们要前缀和,以及遇到\(aa ...
- THUSC2021 游记
Day -6 - 2459343 请了一天假在家卷 whk,u1s1 星期六为啥要去上学呢(bushi 中午 12:00 左右得知自己有去参加 THUSC 的资格 然后就是一堆待填写的资料和报名表 发 ...
- nmap相关
nmap -sT IP-sT(全链接扫描),获取目标IP+PORT的状态,其实是发了三个包:SYN,SYN/ACK,ACK,类似于TCP三次握手 状态: open 开放的 closed 关闭的 fil ...
- R数据科学-2
R数据科学(R for Data Science) Part 2:数据处理 导入-->整理-->转换 ------------------第7章 使用tibble实现简单数据框------ ...
- Pysam 处理bam文件
Pysam可用来处理bam文件 安装: 用 pip 或者 conda即可 使用: Pysam的函数有很多,主要的读取函数有: AlignmentFile:读取BAM/CRAM/SAM文件 Varian ...