java生成电子发票_C#/Java 动态生成电子发票

2023-11-15

电子发票是电商时代的产物,PDF发票是最常见的电子发票之一。在这篇文章中,我将给大家分享一个免费的动态生成PDF电子发票的C#方案,并在文章末尾附上Java解决方案。

典型的发票包含客户和供应商的名称和地址、发票编号、购买物品的描述、付款金额等信息。为了动态地生成发票,我使用MS Word创建了一个模板,在该模板中设计好想要呈现的大部分内容及文档样式,然后通过代码替换文本和插入新内容,最后保存为PDF文档。用代码操作Word文档的部分需要使用

创建模板

如图1所示,发票模板由两个表组成。表1用于显示买卖双方的信息和订单信息,表2用于陈列卖方向买方提供的产品或服务列表。我们需要做的是替换表1中以#开头的文本,并将客户的购物清单填充至第二个表格。

为了能自动计算总金额,需要在某些单元格添加公式域。例如,单元格E2包含公式“=C2*D2”,该公式将计算单元格B2中商品的总价。当买家购买超过一件商品时,我们需要在表格添加更多行并动态更新一些单元格的公式。

edfa172a54025e7d8c767824e5f99567.png

图1 发票模板

如何替换文本

Spire.Doc 有一个IBodyRegion.Replace(string given, string replace, bool caseSensitive, bool wholeWord)方法,可以用于替换文档中的指定字符串。例如,将“#orderNum”替换成“2516595027”,我们可以直接使用下面的代码,代码中doc是Document对象。

doc.Replace("#orderNum", "2516595027", true, true);

如何更新表格二

现在,让我们看看如何向现有表格添加行,如何将数据填充至表格,以及如何动态地更新公式。为了使逻辑更清晰,我创建了三个方法,并制作了图2,来展示它们的具体含义以及它们之间的调用关系。

93349a792afcca0256d87d0ec6841a13.png

图2 自定义方法的含义及调用关系

下面,看一下这三个方法的代码片段:

1. AddRows()

此方法实际上复制了现有表格的第二行,将复制行依次添加到第二行的下面。新行继承了第二行的单元格格式、字体样式和公式。因此,我们需要依次更新新行中的公式,以及下面随行数增加而变化的公式。

private static void AddRows(Table table, introwNum)

{for (int i = 0; i < rowNum; i++)

{//将指定个数的第二行的复制行依次添加到第二行下面

table.Rows.Insert(2 + i, table.Rows[1].Clone());//更新“金额”所对应单元格的公式

foreach (var item in table.Rows[2 + i].Cells[4].Paragraphs[0].ChildObjects)

{if (item isField)

{

Field field= item asField;

field.Code= string.Format("=C{0}*D{0}\\# \"0.00\"", 3 +i);

}break;

}

}//更新“折扣金额”对应的单元格的公式

foreach (var item in table.Rows[4 + rowNum].Cells[4].Paragraphs[0].ChildObjects)

{if (item isField)

{

Field field= item asField;

field.Code= string.Format("=E{0}*0.05\\# \"0.00\"", 3 +rowNum);

}break;

}//更新“总计”对应的单元格的公式

foreach (var item in table.Rows[5 + rowNum].Cells[4].Paragraphs[0].ChildObjects)

{if (item isField)

{

Field field= item asField;

field.Code= string.Format("=E{0}-E{1}\\# \"¥#,##0.00\"", 3 + rowNum, 5 +rowNum);

}break;

}

}

2. FillTableWithData()

此方法仅用于将sting[][]类型数据从表格的第二行开始写入表格。

private static void FillTableWithData(Table table, string[][] data)

{for (int r = 0; r < data.Length; r++)

{for (int c = 0; c < data[r].Length; c++)

{//将数据从表格的第二行开始写入表格

table.Rows[r + 1].Cells[c].Paragraphs[0].Text =data[r][c];

}

}

}

3. WriteDataToDocument()

由于发票模板已经有一行(第二行)用于显示一项商品,因此我们需要判断是否需要添加更多行。如果客户只购买一项商品,模板文档就可以容纳商品信息并输出结果;否则,我们需要添加行来容纳更多的项目,并动态更新公式以获得正确的总金额。

private static void WriteDataToDocument(Document doc, string[][] purhcaseData)

{//获取Word模板中的第二个表格

Table table = doc.Sections[0].Tables[1] asTable;//若购买商品多于一项,则添加purhcaseData.Length - 1个行

if (purhcaseData.Length > 1)

{

AddRows(table, purhcaseData.Length- 1);

}//将购买数据填充至表格

FillTableWithData(table, purhcaseData);

}

WriteDataToDocument()方法的参数之一是sting[][]对象,该对象存储了客户的购买信息,它的每个元素都是一个字符串数组,可以这样设置:

string[] product = new string[] { "1023", "华为 P30 Pro (8G+128G)全网通", "1", "4288" };

string[][]的长度则是商品的项数,如果长度大于1,则需要添加[长度 - 1]个新行。

生成发票

以下是Main函数中用于生成PDF发票的代码。

usingSpire.Doc;usingSpire.Doc.Fields;namespaceCreatePdfInvoice

{classProgram

{static void Main(string[] args)

{//加载Word模板文档

Document doc = newDocument();

doc.LoadFromFile("Invoice-Template.docx");//替换文档中以#开头的文本

doc.Replace("#customerName", "小伟", true, true);

doc.Replace("#contactNum", "13601234567", true, true);

doc.Replace("#shippingAdd", "北京市海淀区幸福小区1幢2单元3号", true, true);

doc.Replace("#orderDate", "2019-05-30", true, true);

doc.Replace("#orderNum", "2516595027", true, true);//定义客户购买数据

string[][] purchaseData ={new string[]{"1023","华为 P30 Pro (8G+128G)全网通","1","4288"},new string[]{"1429","华为Watch GT运动版","2","1288"},new string[]{"1268","华为无线耳机 FreeBuds 2Pro","2","799"},new string[]{"1281","华为 MateBook 14 (i5 8G 512G)","1","5999"},

};//将购买数据写入模板文档的第二个表格

WriteDataToDocument(doc, purchaseData);//更新域

doc.IsUpdateFields = true;//保存为PDF格式文档

doc.SaveToFile("Invoice.pdf", FileFormat.PDF);

System.Diagnostics.Process.Start("Invoice.pdf");

}

}

}

生成的结果文档如下:

e17e67acbb280b9088ed9508d0775001.png

图 3 多项目PDF发票

如果你输入购买数据只有一行,那么你将得到如图4所示的结果文档。

string[][] purchaseData = {new string[]{"1023","华为 P30 Pro (8G+128G)全网通","1","4288"},};

3d0d9ab7c294425bb6ed8ab561959908.png

图4 单项目PDF发票

工程下载

注:

免费版 Spire.Doc能加载和生成的Word文档不能超过500个段落或25个表格,将Word文档保存为PDF时仅支持前3页。绝大多数发票只有1页或2页,所以该方案适用于大多数情况。

————————————————

版权声明:本文为CSDN博主「ssw_jack」的原创文章。

原文链接:https://blog.csdn.net/ssw_jack/article/details/91379486

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java生成电子发票_C#/Java 动态生成电子发票 的相关文章

  • linux 挂载目录

    这本阿里P8撰写的算法笔记 再次推荐给大家 身边不少朋友学完这本书最后加入大厂 Github 疯传 史上最强悍 阿里大佬 LeetCode刷题手册 开放下载了 挂载的基本概念 前面讲过 Linux 系统中 一切皆文件 所有文件都放置在以根目
  • 网络故障排除之Traceroute命令详解

    概要 遇到网络故障的时候 你一般会最先使用哪条命令进行排障 除了Ping 还有Traceroute Show Telnet又或是Clear Debug等等 今天安排的 是Traceroute排障命令详解 给你分享3个经典排障案例哈 一 Tr
  • linux的应用线程同步与驱动同步机制

    同步机制 在 Linux 应用程序和内核中的驱动程序中 有一些常见的同步机制用于实现线程或进程之间的同步和数据访问保护 下面是它们的一些主要机制 Linux 应用程序中的同步机制 互斥锁 Mutex 用于保护共享资源 确保只有一个线程可以访
  • 华为机试题74-参数解析

    描述 在命令行输入如下命令 xcopy s c d e 各个参数如下 参数1 命令字xcopy 参数2 字符串 s 参数3 字符串c 参数4 字符串d e 请编写一个参数解析程序 实现将命令行各个参数解析出来 解析规则 1 参数分隔符为空格
  • 窥孔优化(Peephole Optimization)

    窥孔优化 Peephole Optimization 是编译器中的一个技术 用于优化生成的中间代码或目标代码 该优化方法通过查看代码的小部分 或称为 窥孔 来识别并提供更高效的代码替代方案 1 基本概念 定义 窥孔优化涉及观察编译器输出中的
  • 常用数字电路模块之三:计数器与分频器(二))

    三 分频电路 1 简单的计数器 计数器实质是对输入的驱动时钟进行计数 所以计数器在某种意义上讲 等同于对时钟进行分频 例如一个最大计数长度为N 2 n 从0计数到N 1 的计数器 也就是寄存器位数位n 那么寄存器最高位的输出为N 2 n分频
  • 告诉上述代码报错的原因onnxruntime.capi.onnxruntime_pybind11_state.InvalidArgument: [ONNXRuntimeError] : 2 : INV...

    这个错误的原因是输入的数据类型和预期的数据类型不匹配 根据错误信息 实际输入的数据类型是 unsigned 8 bit integer tensor uint8 而预期的数据类型是浮点数 tensor float 这意味着模型期望输入浮点数
  • 第5章 用户身份与文件权限

    目录 序言 5 1 用户身份与能力 5 1 1 useradd命令 5 1 2 groupadd命令 5 1 3 usermod命令 5 1 4 passwd命令 5 1 5 userdel命令 5 2 文件权限与归属 5 3 文件的特殊权
  • 都在说视频号,真有机会?

    大家好 我是北妈 0 公众号日渐式微 已经远不复当年 这两年也没有很厉害的博主突然起来或者大幅增粉 前两年基本每年都会有 现在基本都是头 腰部效应 有些粉丝基础的还能赚些小钱 但也都断崖式下跌 现在流量和甲方广告投入基本都去了视频领域 所以
  • SpringApplication详解

    22 SpringApplication SpringApplication类提供了一种从main 方法启动Spring应用的便捷方式 在很多情况下 你只需委托给SpringApplication run这个静态方法 public stat
  • 初识Pytest自动化测试框架,我彻底懂了

    初识Pytest Pytest是Python实现的一个测试工具 可以用于所有类型和级别的软件测试 Pytest是一个可以自动查找到你编写的用例并运行后输出结果的测试框架 Pytest的特点 是一个命令行工具 编写用例简单 可读性强 非常容易
  • Java21天打卡day18--继承

    public class Person18 继承 1 描述什么是继承 在已存在的类的基础上进行扩展 从而产生新的类 2 创建一个person类 赋予name age sex属性 并创建一个有参数的构造方法并赋值 3 创建一个方法work p
  • HC32F448-小华MCU

    由于要开发和学习使用低成本MCU 这里记录下小华半导体HC32F448的手册参数 芯片官网 HC32F448MCTI LQFP80 小华半导体有限公司 xhsc com cn HC32F448 系列MCU是32位的ARM Cortex M4
  • 使用Git往github上提交代码时出现[packet_write_wait connection to xx.xx.xx.xx Broken pipe]错误的解决办法:

    使用Git往github上提交代码时出现 packet write wait connection to xx xx xx xx Broken pipe 错误的解决办法 找到git安装的目录 etc ssh 打开ssh config文件 在
  • AOP源码笔记

    在创建对象doCreateBean方法里面 执行完依赖注入populateBean方法以后 在initializeBean方法中进行AOP增强 try populateBean beanName mbd instanceWrapper ex
  • Centos7下载安装mysql

    参考文档 https xie infoq cn article 5da9bfdfbdaabf7b0b982ab6e https blog csdn net Lance welcome article details 107314575 一
  • 非对称加密-RSA

    一 非对称加密 1 对称加密 对称密码的核心是一把密钥 使用相同的密钥进行加密和解密 如移位密码 S DES 但密匙本身也是信息 对称密码中它的安全得不到保障 2 非对称加密 非对称密码的核心是公钥和私钥 公钥是用于加密数据的密钥 而私钥则
  • Python报错集合篇5-FileNotFoundError: [Errno 2] No such file or directory: '不存在的文档.txt'

    本文介绍如何处理报错 FileNotFoundError Errno 2 No such file or directory 不存在的文档 txt 源代码 f open 不存在的文档 txt print f read f close 运行报

随机推荐

  • Unity_UGUI_Image的图层遮挡问题_渲染层级

    有时候 创建图片 图片会被遮挡 如何改变 图片不被遮挡呢 只需要改变图片的层级就可以了 把要显示在 上面的Image 变为遮挡它的 image的子物体就可以了 或者 把要显示在上面的Image 放在下面 渲染层级 1 Camera 相机 D
  • MySQL单行函数

    目录 1 数值函数 2 字符串函数 3 日期和时间函数 3 1 获取日期 时间 3 2 日期与时间戳的转换 3 3 获取月份 星期 星期数 天数等函数 3 4 日期的操作函数 3 5 时间和秒钟转换的函数 3 6 计算日期和时间的函数 3
  • 持续集成工具Jenkins安装及Jenkins离线状态解决

    使用的虚拟机是centos6 1 前置条件 虚拟机已安装jdk和Tomcat 这里只介绍安装Tomcat 安装jdk网上版本很多 大家可以自行查阅 2 安装Tomcat 1 下载地址 https tomcat apache org down
  • Stream流的常用方法(自用)

    自用的笔记 有 需要多看 基本数据 自定义实体 Data class Student private String name private Integer age private Double height public Student
  • 机器学习处理问题的基本路线

    基本路线 1 搭建环境 数据读入 2 数据分析 3 特征工程 4 建模调参 5 模型融合 异常处理 通过箱线图 或 3 Sigma 分析删除异常值 BOX COX 转换 处理有偏分布 长尾截断 特征筛选常用方法 过滤式 filter 先对数
  • Acwing-包含min函数的栈

    stk表示存入这些数据的栈 stk min表示栈里面前i数中的最小值是多少 class MinStack public stack
  • 第二十五篇:UE4如何通过http方式请求接口Json数据

    本篇介绍UE4如何向接口请求数据并解析数据 首先我们需要用到两个插件VaRest和Json Blueprint 这两个插件都是免费的 在虚幻商城可以免费获取到 两个插件安装到UE4引擎之后 新建一个工程 开启这两个插件 记下来介绍两种接口请
  • 教学:四步利用PHP study小皮面板在vscode上编辑php并运行

    第一步 安装完PHP study 需要自行安装phpstudy和vscode 不会的问度娘 第二步 下载xdebug xdebug下载地址 http xdebug org download 这里我是把PHP study安装到我的Window
  • 人大金仓数据库-kingbaseES

    KingbaseES数据库是一个大型通用的跨平台系统 可以安装和运行于Windows Linux UNIX等多种操作系统平台下 KingbaseES数据库在各种操作系统平台上都很容易安装和配置 用户可以参考相应平台下的安装指南 安装King
  • 如何使用CSS实现一个带有动画效果的折叠面板(Accordion)?

    聚沙成塔 每天进步一点点 专栏简介 折叠面板 Accordion 带动画效果 写在最后 专栏简介 前端入门之旅 探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅 这个专栏是为那些对W
  • 【leetcode算法】02-两数之和

    目录 1 题目描述 2 解题思路 第一种解法 暴力枚举 第二种解法 哈希映射 3 代码展示 4 小结 前言 声明 本文仅为学习记录 图片以及题目资源来自牛客和力扣网 如有侵权请联系删除 大家好 我是尼根 一个又菜又想学算法的准程序猿 今天为
  • 数据分析 -- Pandas①

    目录 Pandas简介 Pandas中的两个主要数据结构 Series 创建 访问 DataFrame 创建 列的查改增删 查看列 修改列 新增列 删除列 导入 导出 表格文件以及常规操作 head 方法 tail 方法 info 方法 d
  • path png转svg_svg之path详解

    一 svg 介绍 path元素是SVG基本形状中最强大的一个 它不仅能创建其他基本形状 还能创建更多其他形状 你可以用path元素绘制矩形 直角矩形或者圆角矩形 圆形 椭圆 折线形 多边形 以及一些其他的形状 例如贝塞尔曲线 2次曲线等曲线
  • 解决java.net.SocketException: No buffer space available (maximum connections reach

    严重 Catalina stop java net SocketException No buffer space available maximum connections reached JVM Bindat java net Plai
  • 断网重启路由器就好_路由器间断性的无网络,重启就恢复正常,可能是这些原因导致的!...

    说到 互联网 这一个词 相信大家对它再熟悉不过了 早在互联网刚出来的时候 人们就被它那强大的 引力 给吸引过去 直到现在 互联网已成为人们可以加以利用的一种 道具 了 现如今的我们可以通过网络来了解到一些国内外最新的热点资讯 可以通过网络来
  • 局域网抓包分析工具_巧用Wireshark抓包工具,分析底层网络协议,帮助排除网络故障...

    地址解析协议 ARP Address Resolution Protocol 1 ARP头 2 数据包分析 长度 8 位 字节 MAC 地址 48 位 即 6 字节 IP 地址 32 位 即 4 字节 3 无偿的 ARP 当 IP 地址改变
  • 如何使用PT对电路进行功耗分析

    首先声明本文所讲的范围 在这篇文章中 是采用synopsys的设计流程 对数字电路进行功耗分析 生成功耗分析报告的流程 分析的对象是逻辑综合之后布局布线之前的功耗分析 以及布局布线之后的功耗分析 Synopsys做功耗分析使用到的工具是 P
  • cobra golang好用的CLI工具

    Cobra 每个好的开源项目都会有很多好用的开源库的诞生 之前学openstack的时候就对openstack的oslo系列工具组用的非常多 现在学习k8s后发现同样在go下也有很多类似的开源库 比如Cobra 就是一个用来创建命令行的 g
  • 【Qt】信号和槽对值传递参数和引用传递参数的总结

    在同一个线程中 当信号和槽都在同一个线程中时 值传递参数和引用传递参数有区别 值传递会复制对象 测试时 打印传递前后的地址不同 引用传递不会复制对象 测试时 打印传递前后的地址相同 不在同一个线程中 当信号和槽不在同一个线程中时 分两种情况
  • java生成电子发票_C#/Java 动态生成电子发票

    电子发票是电商时代的产物 PDF发票是最常见的电子发票之一 在这篇文章中 我将给大家分享一个免费的动态生成PDF电子发票的C 方案 并在文章末尾附上Java解决方案 典型的发票包含客户和供应商的名称和地址 发票编号 购买物品的描述 付款金额