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中, ...
随机推荐
- Django 小实例S1 简易学生选课管理系统 12 CSS样式完善
Django 小实例S1 简易学生选课管理系统 第12节--CSS样式完善 点击查看教程总目录 作者自我介绍:b站小UP主,时常直播编程+红警三,python1对1辅导老师. 课程模块的逻辑代码到这里 ...
- request模块做post请求时,body为json格式,并且带有中文,如何请求
后台接口只能解析json,并且一定要是中文才能解析出来,如果是unicode编码的中文则会报错 看requests的源码.以下为解决方法: #将requests库中的models.py文件中的第461 ...
- uni-app 微信小程序全局分享
实际使用中,经常需要小程序分享到好友或者朋友圈,一般而言是一个个页面去设置. 官网分享介绍:https://uniapp.dcloud.io/api/plugins/share?id=onsharea ...
- 14-2-Unsupervised Learning ----Word Embedding
Introduction 词嵌入(word embedding)是降维算法(Dimension Reduction)的典型应用 那如何用vector来表示一个word呢? 1-of-N Encodin ...
- Ultraedit和写字板修改Tomcat 6.0的server.xml不生效
转:http://blog.csdn.net/greencacti/article/details/6615321 本人在修改Tomcat 6.0的server.xml的时候,发现写字板修改完保存的时 ...
- 简易发号SQL,可用于生成指定前缀自增序列--改进版
使用merge语法实现新增or更新 首先创建表 CREATE TABLE Test.dbo.Increments ( Prefix varchar(50) NOT NULL, [MaxNum ] bi ...
- [atARC098F]Donation
贪心,一定在最后一次经过某节点时付出$b_{u}$,条件是付出后$W\ge \max(a_{i}-b_{i},0)$(同时也可以仅考虑这个限制,因为$W$在过程中不会增大) 假设"最后一次经 ...
- spring security 认证源码跟踪
spring security 认证源码跟踪 在跟踪认证源码之前,我们先根据官网说明一下security的内部原理,主要是依据一系列的filter来实现,大家可以根据https://docs.sp ...
- JavaScript Sanitizer API:原生WEB安全API出现啦
10月18号, W3C中网络平台孵化器小组(Web Platform Incubator Community Group)公布了HTML Sanitizer API的规范草案.这份草案用来解决浏览器如 ...
- 洛谷 P3267 - [JLOI2016/SHOI2016]侦察守卫(树形 dp)
洛谷题面传送门 经典题一道,下次就称这种"覆盖距离不超过 xxx 的树形 dp"为<侦察守卫模型> 我们考虑树形 \(dp\),设 \(f_{x,j}\) 表示钦定了 ...