使用方法
- 填「收据编号」,默认 SR-20261004-001。编号规则是「前缀-开票日期-当日序号」,方便按日期追溯。
- 选「开票日期」,默认 2026-10-04。日期会原样印进收据,并参与编号的默认拼装。
- 填「付款方」(收到款项一方,默认 北京样例科技有限公司)和「收款方」(开具收据一方,默认 柳泉工具工作室)。两栏都不允许留空。
- 在明细框里按「项目|数量|单价」逐行录入,默认三行是 设计服务|2|1500、域名续费|1|89.5、服务器托管|3|200。竖线用半角,单价单位是元、可带两位小数。
- 选「收款方式」,默认银行转账,可写备注。
- 点「生成收据」,或在任一单行框里按 Enter、在明细框里按 Ctrl + Enter(macOS 用 Cmd + Enter)。
这个收据生成能解决什么问题
一是把「小写金额」自动转成不出错的大写。手写大写最容易错在三处:「壹拾」写成「拾」、「元」后该补「零」的地方漏掉、连续的零写了两个。默认示例合计 3,689.50 元,规范大写是「叁仟陆佰捌拾玖元伍角」,少一个「零」、多一个「整」都不合规。
二是避免浮点误差造成的对不上账。0.1 + 0.2 在 JavaScript 里等于 0.30000000000000004,单价带小数的明细直接相加很容易出现「合计比手算少一分」。本页先把每条小计换算成整数分再累加,避免这类误差。
三是统一收据的要素与排版。一份可用的收据至少要有编号、日期、付款方、收款方、项目、数量、单价、小计、合计小写、合计大写、收款方式和签章栏。这个收据生成工具按固定骨架输出,漏项一眼就能看出来。
四是补上「没有发票只有收据」的凭证空白。定金、押金、个人之间的款项往来往往不开票,但又需要一张写清数额与事由的凭据。生成纯文本后打印或存 PDF 都方便。
本页不做这些事:不生成增值税发票(发票有税号、税率、价税分离等专用字段,请用「发票生成器」);不做销售单、送货单(请用「账单销售单生成器」);不做带条款的合同(请用「简易合同生成器」)。
原理:金额按「分」运算与大写规则
所有金额先换算成整数分。输入 1500 元的单价,先做 Math.round(1500 * 100) = 150000,再乘数量得到小计的分值,最后累加成合计。这样做是因为 IEEE 754 双精度浮点无法精确表示大多数小数:0.1 + 0.2 得到 0.30000000000000004,19.99 × 3 虽然刚好是 59.97,但只要中间多做一次加减就可能跑出 59.96999999999999。换成整数分之后,加法是精确的,只在最后显示时除以 100。
大写算法分两层:元部分四位一组,角分单独处理。元部分用 fourGroups() 按四位切组,对应「万」和「亿」两个量级:1234 万 5678 元 就读作「壹仟贰佰叁拾肆万伍仟陆佰柒拾捌」。每组内部逐位取数字,映射到「零壹贰叁肆伍陆柒捌玖」与「拾佰仟」,遇到组内连续的零只保留一个「零」。组与组之间是否插「零」,看低位组是不是小于 1000 且不为零——这正是「壹万零壹」与「壹万元整」的区别所在。
角分有两条容易忽略的规则。第一,角位是 0 而分位不是 0 时,元和大写分之间必须补一个「零」,所以 1000.05 是「壹仟元零伍分」而不是「壹仟元伍分」。第二,角分都为零时末尾加「整」,所以 1 元是「壹元整」;一旦有角或分,就绝不能再写「整」——「叁仟陆佰捌拾玖元伍角整」是常见错误写法。
元位为零时以「零元」打头。0.5 元读作「零元伍角」,0.01 元读作「零元零壹分」,这样元、角、分三个位置都不会缺失。大写数字依据的是人民币票据金额的规范写法(中国人民银行《正确填写票据和结算凭证的基本规定》,银发〔1997〕485 号),它给出了「壹贰叁肆伍陆柒捌玖拾佰仟万亿元角分整」这套用字,与日常行文里的「一二三」是两套体系,不能混用。
编号采用「前缀-日期-流水」。默认 SR-20261004-001:SR 表示收据,20261004 是开票日期去掉连字符,001 是当日第几号。这样排序时是按日期加序号排的,不用额外维护一张编号表;跨日之后序号自然从 001 重新开始。
完整示例(数值仅作演示)
页面打开时的默认值就是一份完整收据:编号 SR-20261004-001、日期 2026-10-04、付款方 北京样例科技有限公司、收款方 柳泉工具工作室、收款方式 银行转账,明细三行。逐条复算如下:
- 设计服务:2 × 1500.00 = 3,000.00 元,大写「叁仟元整」;
- 域名续费:1 × 89.50 = 89.50 元,大写「捌拾玖元伍角」;
- 服务器托管:3 × 200.00 = 600.00 元,大写「陆佰元整」;
- 合计 3,689.50 元,逐条小写相加 3000 + 89.50 + 600 = 3689.50,与大写「叁仟陆佰捌拾玖元伍角」互为印证;
- 换算成整数分是 368950 分,远低于 JavaScript 的安全整数上限 9007199254740991,因此本页全程用普通整数即可;
- 明细条数 3,条数与合计分别显示在结果卡上,方便核对有没有漏行。
再看两个边界:单价填 19.99、数量填 3,小计精确算出 59.97 元(按分是 5997 分),若用浮点乘法再四舍五入到分,某些组合会差 1 分;合计填到本页上限 999999999.99 元时,分值也只有 99999999999,仍在安全整数范围内,所以金额上限不是随便定的。
金额与大写对照表
下表是常见金额的规范大写写法。写票据时照着核对,尤其是「零」和「整」两个字的取舍。
| 阿拉伯金额(元) | 规范中文大写 | 规则要点 |
|---|---|---|
| 0 | 零元整 | 金额为零,直接写「零元整」 |
| 0.01 | 零元零壹分 | 角位为 0、分位不为 0,元后必须补「零」 |
| 0.5 | 零元伍角 | 只有角没有分,元为 0 时以「零元」打头 |
| 1 | 壹元整 | 整元且无角分,末尾加「整」 |
| 10 | 壹拾元整 | 「拾」前必须有「壹」,不能只写「拾元」 |
| 1000.05 | 壹仟元零伍分 | 分位不为 0 而角位为 0,需补「零」 |
| 205.06 | 贰佰零伍元零陆分 | 中间连续零只写一个「零」 |
| 10000 | 壹万元整 | 万位非零,万后不补「零」 |
| 10001 | 壹万零壹元整 | 万位与个位之间用「零」连接 |
| 100000000 | 壹亿元整 | 亿位非零,亿后不补「零」 |
| 12345678.9 | 壹仟贰佰叁拾肆万伍仟陆佰柒拾捌元玖角 | 四位一组,完整读出万与亿 |
| 3689.5 | 叁仟陆佰捌拾玖元伍角 | 默认示例合计金额 |
再看收据本身必须有哪些要素,缺了就难以作为凭证使用:
| 要素 | 本页对应栏位 | 作用 |
|---|---|---|
| 编号 | 收据编号(SR-日期-序号) | 唯一标识,便于按编号追溯与对账 |
| 日期 | 开票日期 | 确定收款时点,也参与编号拼装 |
| 收付款双方 | 付款方 / 收款方 | 明确款项关系,两栏都不允许为空 |
| 项目明细 | 项目 / 数量 / 单价 / 小计 | 说明款项事由,数量与单价相乘得小计 |
| 合计金额 | 合计小写 + 合计大写 | 小写便于计算,大写防篡改 |
| 收款方式 | 银行转账 / 现金 / 微信 等 | 与银行流水或支付记录对得上 |
| 签章 | 收款人(签字/盖章)/ 开票人 | 纸质凭证的确认位,打印后手签或盖章 |
输入范围、边界与精度说明
- 编号、付款方、收款方都不允许为空。缺了编号无法追溯,缺了双方名称这张收据就没有款项关系的依据,所以本页直接拦下,而不是生成一个空白栏位的模板。
- 明细格式固定为「项目|数量|单价」三段。分隔符必须是半角竖线。少了段数、多了段数都会报出是第几行、错在哪里。空行会被自动忽略,所以从别处粘进来的行尾空行不影响。
- 数量必须是大于 0 的整数。半件、1.5 个这类需求请改成换算后的整数单位(例如 1.5 箱写成 15 盒,单价同步换算),否则小计会出现除不尽的角分。
- 单价必须是不小于 0 的数字,可带两位小数。单价 0 是允许的(赠品行),负单价会破坏合计口径,一律拒绝。
- 金额上限 999,999,999.99 元。再大就会超过整数分的合理表示范围,也会让大写读法变得难以核对,超过时建议拆成多张收据。
- 金额一律按整数分运算。换算方式是
Math.round(数量 × 单价 × 100)得到该行分值,各行分值相加得合计,最后除以 100 显示。这样每一条小计都是精确到分的,不会出现 0.30000000000000004 这类尾巴。 - 大写金额按人民币票据规范生成。用字限于「零壹贰叁肆伍陆柒捌玖拾佰仟万亿元角分整」,不含「两」「廿」等口语写法。
- 生成结果不落服务器。全部计算都在当前页面完成,没有网络请求、不写浏览器存储;刷新后回到默认示例。要留档请用「复制收据」把文本带走自行保存。
常见问题
为什么「壹拾元整」不能写成「拾元整」?
因为票据金额的大写规范要求「拾」这类量级字前面必须有数字。只写「拾元整」,单独看没有数字约束,容易被加字或改字。同一支规范里还规定不能写「两」「廿」这类口语数字,要用「贰」和「贰拾」。本页的对照表里 10 元一行就是「壹拾元整」,可以照着核。
什么时候写「整」,什么时候不写?
角位和分位都为零时才写「整」,例如 1 元是「壹元整」、3689 元是「叁仟陆佰捌拾玖元整」。只要有角或有分,就绝不能写「整」——3,689.50 元的正确写法是「叁仟陆佰捌拾玖元伍角」,多加一个「整」就是错的。示例里默认合计带五角,所以没有「整」字。
为什么合计和手算差了一分钱?
大概率是浮点误差。0.1 加 0.2 在双精度浮点里等于 0.30000000000000004,多条带小数的明细连续相加就会在末位跑偏。本页先把手算里的每个数字换算成整数分再相加,分值是精确整数,只在显示时除以 100,所以「合计」这一栏和你用计算器逐条加的结果一致。这也是收据金额不该直接用浮点相加的原因。
明细里能不能写中文全角的竖线?
不建议。分隔符统一按半角竖线 | 解析,全角竖线 | 会被当成项目名的一部分,导致「数量」这一段解析不出数字并报错。若从网页或文档复制进来时被自动转成了全角,改回半角即可,报错信息会指出是第几行。
数量可以是小数吗?
不可以,必须是大于 0 的整数。因为收据的小计要精确到分,数量带小数时「单价 × 数量」很容易出现除不尽的角分,反而制造新的误差。正确做法是先统一最小计量单位:按箱卖的改成按盒,按小时算的改成按分钟,数量取整、单价同步换算,结果不变。
生成的收据有法律效力吗?
收据只是款项往来的书面凭据,能不能作为证据取决于内容是否真实、有无双方签章。本页帮你把要素写全、金额大写算准,但签章栏留空由你打印后手签或盖章。涉及大额交易、税务处理时,应以正式发票和合同为准,本页的输出仅作辅助。
为什么明细最多 200 行?
收据是「一张一事」的凭证,200 行已经远超正常使用场景;限制行数主要是防止误粘贴一整张表格导致页面卡顿。如果你的场景确实需要几十上百行明细,那更接近销售清单或对账单,用「账单销售单生成器」更合适,本页的明细行更适合收据这种短凭证。
数据会上传或被保存吗?
不会。这个收据生成工具的全部运算——分值换算、小计累加、大写转换、文本拼装——都在浏览器里完成,没有任何网络请求,也不写入本地存储。刷新页面后输入框回到默认示例。想自己确认,可以打开开发者工具的 Network 面板观察。