内容将会持续更新,有错误的地方欢迎指正,谢谢!
拥有更好的学习体验 —— 不断努力,不断进步,不断探索 |
助力快速掌握 PDF 的创建与导出 为初学者节省宝贵的学习时间,避免困惑! |
TechX 教程效果:
文章目录
一、第三方库iTextSharp导入
在Unity中生成PDF文件并写入内容,需要使用第三方库,因为Unity本身不提供直接操作PDF的API。一个常用的库是iTextSharp,这是一个强大的PDF处理库。iTextSharp是iText的C#版本,可以用于创建、修改和读取PDF文档。
1、通过Visual Studio的NuGet包管理器下载iTextSharp库
打开NuGet包管理器:
在Visual Studio中,点击Tools菜单,选择NuGet Package Manager,然后选择Manage NuGet Packages for Solution…。
搜索iTextSharp:
在打开的NuGet包管理器窗口中,点击Browse选项卡,然后在搜索框中输入iTextSharp。
安装iTextSharp:
在搜索结果中找到iTextSharp包,点击Install按钮进行安装。根据提示完成安装过程。
2、导入DLL文件到Unity中
上一步下载的iTextSharp包在工程目录的Packages下,共包含两个文件夹:BouncyCastle.Cryptography.2.4.0和iTextSharp.5.5.13.4。
进入BouncyCastle.Cryptography.2.4.0\lib\net461和iTextSharp.5.5.13.4\lib\net461目录中找到BouncyCastle.Cryptography.dll和itextsharp.dll。
将两个DLL文件复制到你的Unity项目的Assets/Plugins文件夹中。如果没有Plugins文件夹,可以创建一个。
二、使用iTextSharp生成和写入PDF文件的示例
在Unity项目中创建一个C#脚本,例如PDFGenerator.cs。
在脚本中使用iTextSharp来生成和写入PDF。
以下是完整的示例代码:
using UnityEngine;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;
using Image = iTextSharp.text.Image;
public class PDFGenerator : MonoBehaviour
{
void Start()
{
// 设置PDF保存路径
string path = Application.dataPath + "/GeneratedPDF.pdf";
// 图片路径
string imgPath = Application.streamingAssetsPath+ "/path_to_image.jpg";
using (FileStream fileStream = new FileStream(path, FileMode.Create))
{
// 创建一个文档对象
Document document = new Document();
// 创建一个PDF写入流
PdfWriter pdfWriter = PdfWriter.GetInstance(document, fileStream );
// 打开文档
document.Open();
// 添加内容到文档
document.Add(new Paragraph("Hello, World!"));
document.Add(new Paragraph("This is a PDF generated in Unity."));
// 添加图片
Image image = Image.GetInstance(imgPath );
document.Add(image);
// 添加表格
PdfPTable table = new PdfPTable(3); // 3列的表格
table.AddCell("Cell 1");
table.AddCell("Cell 2");
document.Add(table);
//关闭写入流
pdfWriter.Close();
// 关闭文档
document.Close();
}
Debug.Log("PDF generated at: " + path);
}
}
三、写入和导出PDF实战
我们将创建一个名为PDFOperation的类,用于封装PDF文档的创建和操作功能。
分步讲解:
构造函数
我们的PDFOperation类有三个构造函数,用于初始化PDF文档对象,可以指定页面大小和边距文档操作
我们提供了一些方法来打开和关闭PDF文档,以及创建和关闭PDF写入流设置字体
我们可以设置基础字体并创建字体对象,以便在文档中使用添加页面和段落
我们可以添加新页面、空行和段落添加图片
我们可以通过路径添加图片,并指定对齐方式和大小添加表格
我们可以通过PdfPTable对象向PDF文档添加表格
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;
using UnityEngine;
using Font = iTextSharp.text.Font;
using Rectangle = iTextSharp.text.Rectangle;
namespace PDFExport
{
/// <summary>
/// PDF文档操作类
/// </summary>
public class PDFOperation
{
#region 私有字段
private Font font = default;
private PdfWriter pdfWriter;
private Rectangle documentSize; //文档大小
private Document document;//文档对象
private BaseFont basefont;//字体
#endregion
#region 构造函数
/// <summary>
/// 构造函数
/// </summary>
public PDFOperation()
{
documentSize = PageSize.A4;
document = new Document(documentSize);
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="type">页面大小(如"A4")</param>
public PDFOperation(Rectangle size)
{
documentSize = size;
document = new Document(size);
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="type">页面大小(如"A4")</param>
/// <param name="marginLeft">内容距左边框距离</param>
/// <param name="marginRight">内容距右边框距离</param>
/// <param name="marginTop">内容距上边框距离</param>
/// <param name="marginBottom">内容距下边框距离</param>
public PDFOperation(Rectangle size, float marginLeft, float marginRight, float marginTop, float marginBottom)
{
documentSize = size;
document = new Document(size, marginLeft, marginRight, marginTop, marginBottom);
}
#endregion
#region 文档操作
/// <summary>
/// 创建写入流
/// </summary>
/// <param name="os">文档相关信息(如路径,打开方式等)</param>
public PdfWriter OpenPdfWriter(FileStream os)
{
pdfWriter = PdfWriter.GetInstance(document, os);
return pdfWriter;
}
/// <summary>
/// 关闭写入流
/// </summary>
/// <param name="writer"></param>
public void ClosePdfWriter()
{
pdfWriter.Close();
}
/// <summary>
/// 打开文档
/// </summary>
public void Open()
{
document.Open();
}
/// <summary>
/// 关闭打开的文档
/// </summary>
public void Close()
{
document.Close();
}
#endregion
#region 设置字体
/// <summary>
/// 设置字体
/// </summary>
public void SetBaseFont(string path)
{
basefont = BaseFont.CreateFont(path, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
}
/// <summary>
/// 设置字体
/// </summary>
/// <param name="size">字体大小</param>
public Font SetFont(float size)
{
font = new Font(basefont, size);
return font;
}
/// <summary>
/// 设置字体
/// </summary>
/// <param name="size"></param>
/// <param name="style"></param>
public Font SetFont(float size, int style)
{
font = new Font(basefont, size, style);
return font;
}
/// <summary>
/// 设置字体
/// </summary>
/// <param name="size"></param>
/// <param name="style"></param>
/// <param name="fontColor"></param>
public Font SetFont(float size, int style, BaseColor fontColor)
{
font = new Font(basefont, size, style, fontColor);
return font;
}
/// <summary>
/// 获取字体
/// </summary>
/// <returns></returns>
public Font GetFont()
{
return font;
}
#endregion
public void AddPage()
{
document.NewPage();
}
#region 添加段落
/// <summary>
/// 空格
/// 加入空行,用以区分上下行
/// </summary>
public void AddNullLine(int nullLine=1,int lightHeight=12)
{
// Change this to the desired number of empty lines
int numberOfEmptyLines = nullLine;
for (int i = 0; i < numberOfEmptyLines; i++)
{
Paragraph emptyLine = new Paragraph(" ", new Font(Font.FontFamily.HELVETICA, lightHeight));
document.Add(emptyLine);
}
}
/// <summary>
/// 插入文字内容
/// </summary>
/// <param name="content">内容</param>
/// <param name="alignmentType">对齐格式,0为左对齐,1为居中</param>
/// <param name="indent">首行缩进</param>
public void AddParagraph(string content, int alignmentType = 0,float indent = 0)
{
Paragraph contentP = new Paragraph(new Chunk(content, font));
contentP.FirstLineIndent = indent;
contentP.Alignment = alignmentType;
document.Add(contentP);
}
/// <summary>
/// 添加段落
/// </summary>
/// <param name="content">内容</param>
/// <param name="Alignment">对齐方式(1为居中,0为居左,2为居右)</param>
/// <param name="SpacingAfter">段后空行数(0为默认值)</param>
/// <param name="SpacingBefore">段前空行数(0为默认值)</param>
/// <param name="MultipliedLeading">行间距(0为默认值)</param>
public void AddParagraph(string content, int Alignment, float SpacingAfter, float SpacingBefore, float MultipliedLeading)
{
Paragraph pra = new Paragraph(content, font);
pra.Alignment = Alignment;
if (SpacingAfter != 0)
{
pra.SpacingAfter = SpacingAfter;
}
if (SpacingBefore != 0)
{
pra.SpacingBefore = SpacingBefore;
}
if (MultipliedLeading != 0)
{
pra.MultipliedLeading = MultipliedLeading;
}
document.Add(pra);
}
#endregion
#region 添加图片
/// <summary>
/// 添加图片
/// </summary>
/// <param name="path">图片路径</param>
/// <param name="Alignment">对齐方式(1为居中,0为居左,2为居右)</param>
/// <param name="newWidth">图片宽(0为默认值,如果宽度大于页宽将按比率缩放)</param>
/// <param name="newHeight">图片高</param>
public Image AddImage(string imagePath, int Alignment, float newWidth, float newHeight)
{
if (!File.Exists(imagePath))
{
Debug.Log("该路径下不存在指定图片,请检测路径是否正确!");
return null;
}
Image img = Image.GetInstance(imagePath);
img.Alignment = Alignment;
if (newWidth != 0)
{
img.ScaleAbsolute(newWidth, newHeight);
}
else
{
if (img.Width > PageSize.A4.Width)
{
img.ScaleAbsolute(documentSize.Width, img.Width * img.Height / documentSize.Height);
}
}
document.Add(img);
return img;
}
/// <summary>
/// 添加图片
/// </summary>
/// <param name="path">图片路径</param>
/// <param name="Alignment">对齐方式(1为居中,0为居左,2为居右)</param>
/// <param name="newWidth">图片宽</param>
/// <param name="newHeight">图片高</param>
public Image AddImage(string imagePath, int Alignment, int fitWidth, int fitHeight)
{
if (!File.Exists(imagePath))
{
Debug.Log("该路径下不存在指定图片,请检测路径是否正确!");
return null;
}
Image image = Image.GetInstance(imagePath);
image.ScaleToFit(fitWidth, fitHeight);
image.Alignment = Alignment;
document.Add(image);
return image;
}
#endregion
#region Table表
public void AddTable(PdfPTable table)
{
document.Add(table);
}
#endregion
}
}
下面是一个使用PDFOperation类创建和导出PDF文档的完整示例。
通过上述类和方法,我们可以轻松创建带有页眉和页脚的实验报告PDF文件。
完整示例:
using iTextSharp.text;
using iTextSharp.text.pdf;
using System;
using System.IO;
using UnityEditor;
using UnityEngine;
using Font = iTextSharp.text.Font;
using Image = iTextSharp.text.Image;
namespace PDFExport
{
public class ReportExporterPDF: MonoBehaviour
{
private string fontPath = Application.streamingAssetsPath + "/Fonts/SIMFANG.TTF";
string imagePath1 = Application.streamingAssetsPath + "/Images/logo.png";
private void Start()
{
GenerateReportPDF();
}
public void GenerateReportPDF()
{
CreatePDF(Application.streamingAssetsPath + "/Report.pdf");
}
private void CreatePDF(string filePath)
{
using (FileStream fileStream = new FileStream(filePath, FileMode.Create))
{
PDFOperation pdf = new PDFOperation(PageSize.A4, 55f, 55f, 96f, 96f);
pdf.SetBaseFont(fontPath);
PdfWriter pdfWriter = pdf.OpenPdfWriter(fileStream);
pdf.Open();
HeaderFooterPageEvent headerFooterPageEvent = new HeaderFooterPageEvent(pdf,this);
pdfWriter.PageEvent = headerFooterPageEvent;
FirstPasge(pdf);
pdf.Close();
pdf.ClosePdfWriter();
#if UNITY_EDITOR
AssetDatabase.Refresh();
#endif
}
Application.OpenURL(filePath);
}
#region FirstPage
private void FirstPasge(PDFOperation pdf)
{
pdf.AddNullLine(1, 22);
Image image1 = Image.GetInstance(imagePath1);
PdfPTable table = new PdfPTable(1);
table.DefaultCell.Border = Rectangle.NO_BORDER;
table.DefaultCell.Padding = 0;
table.DefaultCell.FixedHeight = 100;
// 设置图片的缩放比例
float scale = 0.9f;
image1.ScaleAbsolute(image1.Width * scale, image1.Height * scale);
PdfPCell cell1 = new PdfPCell(image1);
cell1.HorizontalAlignment = 1;
cell1.PaddingRight = 0;
cell1.Border = Rectangle.NO_BORDER;
table.AddCell(cell1);
pdf.AddTable(table);
pdf.AddNullLine();
pdf.SetFont(24);
pdf.AddParagraph("汽车实验系统", 1);
pdf.AddNullLine();
pdf.SetFont(36, Font.BOLD);
pdf.AddParagraph("实验报告", 1);
pdf.AddNullLine(3);
AddMainInfo(pdf);
}
public void AddMainInfo(PDFOperation pdf)
{
// 创建一个有 2 列的表格
float[] columnWidths = { 124, 369 };
PdfPTable table = new PdfPTable(columnWidths);
table.DefaultCell.Border = Rectangle.NO_BORDER;
// 设置表格宽度和对齐方式
table.WidthPercentage = 80;
table.HorizontalAlignment = Element.ALIGN_CENTER;
string[] cellContents = {
"实验名称:", "汽车仿真实验",
"实验地点:", "",
"学生姓名:", "",
"指导教师:", "",
"所属单位:", "",
"支持单位:", "XXXX科技大学",
"支持单位:", "XXXXXX股份有限公司",
"实验时间:", DateTime.Now.ToString("yyyy年MM月dd日")
};
// 用提供的信息添加表格单元格
for (int i = 0; i < cellContents.Length; i++)
{
PdfPCell cell;
if (i % 2 == 0)
{
pdf.SetFont(14, Font.BOLD);
cell = new PdfPCell(new Phrase(cellContents[i], pdf.GetFont()));
}
else
{
pdf.SetFont(14, Font.NORMAL);
cell = new PdfPCell(new Phrase(cellContents[i], pdf.GetFont()));
}
cell.Padding = 10;
cell.Border = Rectangle.NO_BORDER;
table.AddCell(cell);
}
pdf.AddTable(table);
}
#endregion
#region 页眉页脚
public class HeaderFooterPageEvent : PdfPageEventHelper
{
PDFOperation pdf;
ReportExporterPDF reportExporter;
public HeaderFooterPageEvent(PDFOperation pdf, ReportExporterPDF reportExporter)
{
this.pdf = pdf;
this.reportExporter = reportExporter;
}
public override void OnEndPage(PdfWriter writer, Document doc)
{
base.OnEndPage(writer, doc);
Header(writer, doc);
Footer(writer, doc);
}
private void Header(PdfWriter writer, Document doc)
{
float[] columnWidths = { 25, 200 };
// 添加带图片和文字的页眉
PdfPTable headerTable = new PdfPTable(columnWidths);
headerTable.DefaultCell.Border = Rectangle.NO_BORDER;
headerTable.WidthPercentage = 100;
headerTable.HorizontalAlignment = Element.ALIGN_CENTER;
headerTable.TotalWidth = doc.PageSize.Width - doc.LeftMargin - doc.RightMargin; // Set table width
headerTable.LockedWidth = true; // Lock the table width
Image image1 = Image.GetInstance(reportExporter.imagePath1);
// Add images to the header
image1.ScaleAbsolute(image1.Width / 2, image1.Height / 2);
PdfPCell imageCell1 = new PdfPCell(image1);
imageCell1.Border = Rectangle.NO_BORDER;
// Add text to the header
pdf.SetFont(10, Font.NORMAL, BaseColor.GRAY);
Font headerFont = pdf.GetFont();
PdfPCell textCell = new PdfPCell(new Phrase("XXXXXX股份有限公司", headerFont));
textCell.HorizontalAlignment = Element.ALIGN_RIGHT;
textCell.VerticalAlignment = Element.ALIGN_BOTTOM;
textCell.Border = Rectangle.NO_BORDER;
headerTable.AddCell(imageCell1);
headerTable.AddCell(textCell);
headerTable.WriteSelectedRows(0, -1, doc.Left, doc.Top + 60, writer.DirectContent);
}
private void Footer(PdfWriter writer, Document doc)
{
// Add footer with page number
PdfPTable footerTable = new PdfPTable(1);
footerTable.DefaultCell.Border = Rectangle.NO_BORDER;
footerTable.WidthPercentage = 100;
footerTable.HorizontalAlignment = Element.ALIGN_CENTER;
footerTable.TotalWidth = doc.PageSize.Width - doc.LeftMargin - doc.RightMargin; // Set table width
footerTable.LockedWidth = true; // Lock the table width
int pageNumber = writer.PageNumber;
int totalPages = writer.CurrentPageNumber; // Exclude the cover page
pdf.SetFont(9, Font.NORMAL, BaseColor.GRAY);
Font footFont = pdf.GetFont();
PdfPCell footerCell = new PdfPCell(new Phrase($"{totalPages}", footFont));
footerCell.HorizontalAlignment = Element.ALIGN_CENTER;
footerCell.Border = Rectangle.NO_BORDER;
footerTable.AddCell(footerCell);
footerTable.WriteSelectedRows(0, -1, doc.Left, doc.Bottom - 50, writer.DirectContent);
}
}
#endregion
}
}
每一次跌倒都是一次成长 每一次努力都是一次进步 |
如果您喜欢本博客,请点赞和分享给更多的朋友,让更多人受益。同时,您也可以关注我的博客,以便及时获取最新的更新和文章。
在未来的写作中,我将继续努力,分享更多有趣、实用的内容。再次感谢大家的支持和鼓励,期待与您在下一篇博客再见!