客户提供导出的excel数据,批量生成pdf发票
例如:项目场景:只要涉及导出及填充pdf模板数据
怎么制作pdf模板
使用adobe acrbat DC 制作pdf所需模板,注意准备表单时选择好文本域等填写字段数据名称,只要是pdf填充同理!!!!不要使用2018版本,有bug,无法打印!
准备好模板,c#接收excel数据处理完后导出excel:使用nuget包 ----- EPPlus读取excel,iTextSharp导出pdf
下述功能逻辑:1:读取excel 2:导出子pdf 3:删除临时文件 4:合并所有pdf
//在使用EPPlus读取Excel前设置LicenseContext ----------粗略写功能,如需完整实现d
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
//使用EPPlus读取Excel文件
FileInfo fileInfo = new FileInfo(savePath);
List<Dictionary<string, string>> list_d = new List<Dictionary<string, string>>();
using (ExcelPackage package = new ExcelPackage(fileInfo))
{
// 获取第一个工作表
ExcelWorksheet worksheet = package.Workbook.Worksheets[0];
// 读取数据
int totalRows = worksheet.Dimension.End.Row; // 获取总行数
int totalCols = worksheet.Dimension.End.Column; // 获取总列数
for (int row = 1; row <= totalRows; row++) // 从第1行开始,假设第1行是表头
{
Dictionary<string, string> formData = new Dictionary<string, string>();
//是否是数电票
string is_szinvoice = "";
for (int col = 1; col <= totalCols; col++)
{
// 获取单元格的值
object cellValue = worksheet.Cells[row, col].Value;
if (row == 1)
{
break;
}
switch (col)
{
case 4:
formData.Add("fphm", cellValue.ToString());
break;
case 7:
formData.Add("nsrsbh", cellValue.ToString());
break;
case 8:
formData.Add("gfmc", cellValue.ToString());
break;
case 9:
formData.Add("kprq", cellValue.ToString());
break;
case 12:
formData.Add("xq", cellValue.ToString());
break;
case 20:
formData.Add("jshjxx", cellValue.ToString());
formData.Add("jshjdx", ConvertAmountToCapital(cellValue.ToString()));
break;
case 22:
is_szinvoice = cellValue.ToString();
break;
case 27:
formData.Add("fhr", (cellValue == null ? "无" : cellValue).ToString());
break;
case 26:
formData.Add("kpr", cellValue.ToString());
break;
default:
break;
}
}
if (is_szinvoice.Contains("电"))
{
list_d.Add(formData);
}
}
}
string pdfpath = AppDomain.CurrentDomain.BaseDirectory + "file/template/wby.pdf";
string pdfname = DateTime.Now.ToString("yyyyMMddhhmmss") + ".pdf";
string pdfoutpath = AppDomain.CurrentDomain.BaseDirectory + "file/invoice/" + pdfname;
//处理完数据取得所需进行pdf导出
PdfToPath(pdfpath, pdfoutpath, list_d[0], tableData);
///
/// 保存到指定路径pdf
///
/// 模板路径
/// 保存路径
/// 字典
public static void PdfToPath(string templatePath, string outputPath, Dictionary<string, string> fieldData, Dictionary<string, List<string[]>> tableData)
{
// 读取PDF模板文件
PdfReader reader = new PdfReader(templatePath);
using (FileStream fs = new FileStream(outputPath, FileMode.Create, FileAccess.Write, FileShare.None))
{
// 创建一个新的PDFStamper对象,用于填写表单
PdfStamper stamper = new PdfStamper(reader, fs);
// 获取表单域集合
AcroFields formFields = stamper.AcroFields;
// 设置中文字体
BaseFont baseFont = BaseFont.CreateFont("c:/windows/fonts/simsun.ttc,0", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
formFields.AddSubstitutionFont(baseFont);
// 填充数据到表单域
foreach (var entry in fieldData)
{
string fieldName = entry.Key;
string fieldValue = entry.Value;
if (formFields.Fields.ContainsKey(fieldName))
{
if (fieldName == "xq")
{
continue;
}
formFields.SetField(fieldName, fieldValue);
}
else
{
log.info("无此数据源");
}
}
// 设置表单为只读(可选)
stamper.FormFlattening = true; // 这会将表单扁平化,不可再编辑
// 关闭并释放资源
stamper.Close();
}
reader.Close();
}
//临时文件删除
///
/// 合并后清除所有pdf子文件 ----将上述添加的pdf路径泛型加入
///
/// 总路径
public void DeletePdfPath(List<string> allPdfPaths)
{
try
{
//删除每个路径指向的文件
foreach (string path in allPdfPaths)
{
//去除空白字符
string trimmedPath = path.Trim();
//检查文件是否存在
if (File.Exists(trimmedPath))
{
File.Delete(trimmedPath);
//已被删除
}
else
{
//文件不存在,无法删除
}
}
}
catch (Exception ex)
{
}
}
//将所有pdf子文件合并成一个完整pdf
///
/// 合并pdf
///
/// 需要合并的pdf文件路径集合
/// 返回合并后的pdf
public static void MergePdfTemplates(List<string> templatePaths, string outputFilePath)
{
Document document = new Document();
//PdfCopy对象合并PDF文件
PdfCopy copy = new PdfCopy(document, new FileStream(outputFilePath, FileMode.Create));
try
{
//打开文档
document.Open();
//遍历所有模板文件路径
foreach (string templatePath in templatePaths)
{
PdfReader reader = new PdfReader(templatePath);
//复制到输出文档
for (int i = 0; i < reader.NumberOfPages; i++)
{
copy.AddPage(copy.GetImportedPage(reader, i + 1));
}
reader.Close();
}
}
catch (Exception ex)
{
//log
}
finally
{
// 关闭文档
document.Close();
}
}
///
/// 小写金额数字转大写
///
/// 金额
///
public static string ConvertAmountToCapital(string number)
{
decimal dNum;
if (!decimal.TryParse(number.ToString(), out dNum))
return "数字格式不正确";
dNum = Math.Round(dNum, 2); //保留两位小数
if (dNum == 0)
return "零元整";
string strText = "零壹贰叁肆伍陆柒捌玖";
string strUnit = "万仟佰拾亿仟佰拾万仟佰拾元角分"; //单位
string strNum = (Math.Abs(dNum) * 100).ToString("f0"); //将要转换的值变成字符串
string tmpText, tmpUnit; //用于记录某一位上的数据与单位
int zeroCount = 0; //连续出现0的个数
int j; //第i位的数字
string strResult = "";
if (dNum < 0) strResult += "负";
int count = strNum.Length; //数字总长度
if (count > strUnit.Length) return "数据超出范围";
strUnit = strUnit.Substring(strUnit.Length - count); //截取可能用到的数据单位
for (int i = 0; i < count; i++)
{
j = int.Parse(strNum[i].ToString());
tmpText = "";
tmpUnit = "";
if (j != 0) //当前数据不为0时
{
if (zeroCount > 0) //之前的数字为0时
{
tmpText = strText[0].ToString();
zeroCount = 0;
}
tmpText += strText[j].ToString();
tmpUnit = strUnit[i].ToString();
}
else
{
zeroCount++;
if (count - i == 11 || count - i == 3 || (zeroCount <= 3 && (count + 1 - i) % 4 == 0)) //亿位或元位或0的连续数量不超过3 并且当前所取位数为元、万、亿、万亿上的数字时必须加上单位
tmpUnit = strUnit[i].ToString();
}
strResult += tmpText + tmpUnit;
if (i == count - 1 && j == 0) //最后一位为0时加上整
strResult += "整";
}
return strResult;
}
可能出现的问题:导出无法打印 ---------- 检查文本域等属性
适用于数据导出成pdf的需求