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中, ...
随机推荐
- 大爽Python入门教程 2-4 练习
大爽Python入门公开课教案 点击查看教程总目录 方位输出 第一章有一个思考题,方位变换: 小明同学站在平原上,面朝北方,向左转51次之后(每次只转90度), 小明面朝哪里?小明转过了多少圈? (3 ...
- [luogu7476]苦涩
维护线段树,在其每一个节点上维护一个set(可重),以及子树内所有set的最大值 考虑下传标记,如果将所有元素全部下传复杂度显然不正确,但注意到我们仅关心于其中的最大值,即仅需要将最大值下传即可 其有 ...
- [noi707]LP
(以下用$Sa=\sum_{j=1}^{i}xi\cdot ai$,Sb和Sc同理)令f[i][x]表示前i个数,$Sa\le x\le Sb$时最小的Sc考虑第i个数是否选择,可以得到递推式$f[i ...
- [atAGC048F]01 Record
先将这个序列翻转,贪心找到最长的'101010--'的形式的子序列并删除,重复此过程并记这些字符串长度依次为$l_{1},l_{2},...,l_{n}$,若最终还有字符剩余则一定无解 假设$S$中元 ...
- 1、使用ValueOperations操作redis(String字符串)
文章来源:https://www.cnblogs.com/shiguotao-com/p/10559997.html 方法 c参数 s说明 void set(K key, V value); ke ...
- 【NetWork】-- 网络原理
2019-07-18 21:00:25 by冲冲 1. 网络拓扑 把网络中的计算机和通信设备抽象为一个点,把传输介质抽象为一条线,由点和线组成的几何图形就是计算机网络的拓扑结构(Network T ...
- Python技法1:变长和定长序列拆分
Python中的任何序列(可迭代的对象)都可以通过赋值操作进行拆分,包括但不限于元组.列表.字符串.文件.迭代器.生成器等. 元组拆分 元组拆分是最为常见的一种拆分,示例如下: p = (4, 5) ...
- vue-cli的安装步骤
1.安装Node.js 在Node.js官网 https://nodejs.org/zh-cn/下载安装包,修改安装路径到其它盘,如 G:\Program Files 2.设置 cnpm的下载路径和缓 ...
- Codeforces 375C - Circling Round Treasures(状压 dp+最短路转移)
题面传送门 注意到这题中宝藏 \(+\) 炸弹个数最多只有 \(8\) 个,故考虑状压,设 \(dp[x][y][S]\) 表示当前坐标为 \((x,y)\),有且仅有 \(S\) 当中的物品被包围在 ...
- NextDenovo 组装基因组
NextDenovo 是有武汉未来组团队开发出来用于组装ONT,Pacbio, HIFI (默认参数可对60-100X数据更有效),可通过correct--assemble对其进行组装.组装后,每个碱 ...