iText7画发票PDF——小tips

itext7教程:

1、https://blog.csdn.net/allway2/article/details/124295097
2、https://max.book118.com/html/2017/0720/123235195.shtm
3、https://www.cnblogs.com/fonks/p/15090635.html
4、https://www.cnblogs.com/sky-chen/p/13026203.html
5、官方:https://api.itextpdf.com/iText/dotnet/8.0.2/classi_text_1_1_layout_1_1_splitting_1_1_keep_all_split_characters.html
6、git:https://github.com/itext/itext7-dotnet

1.毫米转换磅
itext中是用磅值作为像素位置点的。为方便画PDF,则需要把常规毫米转换成磅值;
转换规则:毫米/10/2.54f*72

2.添加每页的固定表头
(给pdf添加AddEventHandler)

  • 创建类PdfEventHandler
    (在PdfEventHandler中将每页要重复的部分画进去。)
PdfEventHandler handler = new PdfEventHandler(model, KT, ST, CN);//
  • pdf增加Event,将创建的类新增到pdf中:
pdf.AddEventHandler(PdfDocumentEvent.START_PAGE, handler);

3.金额转换成中文大写金额

 /// <summary>
 /// 金额转换成中文大写金额
 /// </summary>
 /// <param name="LowerMoney">传入的数字金额,eg:10.74</param>
 /// <returns></returns>
 private static string MoneyToUpper(string LowerMoney)
 {
     string functionReturnValue = null;
     bool IsNegative = false; // 是否是负数
     if (LowerMoney.Trim().Substring(0, 1) == "-")
     {
         // 是负数则先转为正数
         LowerMoney = LowerMoney.Trim().Remove(0, 1);
         IsNegative = true;
     }
     string strLower = null;
     string strUpart = null;
     string strUpper = null;
     int iTemp = 0;
     // 保留两位小数 123.489→123.49  123.4→123.4
     LowerMoney = Math.Round(double.Parse(LowerMoney), 2).ToString();
     if (LowerMoney.IndexOf(".") > 0)
     {
         if (LowerMoney.IndexOf(".") == LowerMoney.Length - 2)
         {
             LowerMoney = LowerMoney + "0";
         }
     }
     else
     {
         LowerMoney = LowerMoney + ".00";
     }
     strLower = LowerMoney;
     iTemp = 1;
     strUpper = "";
     while (iTemp <= strLower.Length)
     {
         switch (strLower.Substring(strLower.Length - iTemp, 1))
         {
             case ".":
                 strUpart = "圆";
                 break;
             case "0":
                 strUpart = "零";
                 break;
             case "1":
                 strUpart = "壹";
                 break;
             case "2":
                 strUpart = "贰";
                 break;
             case "3":
                 strUpart = "叁";
                 break;
             case "4":
                 strUpart = "肆";
                 break;
             case "5":
                 strUpart = "伍";
                 break;
             case "6":
                 strUpart = "陆";
                 break;
             case "7":
                 strUpart = "柒";
                 break;
             case "8":
                 strUpart = "捌";
                 break;
             case "9":
                 strUpart = "玖";
                 break;
         }

         switch (iTemp)
         {
             case 1:
                 strUpart = strUpart + "分";
                 break;
             case 2:
                 strUpart = strUpart + "角";
                 break;
             case 3:
                 strUpart = strUpart + "";
                 break;
             case 4:
                 strUpart = strUpart + "";
                 break;
             case 5:
                 strUpart = strUpart + "拾";
                 break;
             case 6:
                 strUpart = strUpart + "佰";
                 break;
             case 7:
                 strUpart = strUpart + "仟";
                 break;
             case 8:
                 strUpart = strUpart + "万";
                 break;
             case 9:
                 strUpart = strUpart + "拾";
                 break;
             case 10:
                 strUpart = strUpart + "佰";
                 break;
             case 11:
                 strUpart = strUpart + "仟";
                 break;
             case 12:
                 strUpart = strUpart + "亿";
                 break;
             case 13:
                 strUpart = strUpart + "拾";
                 break;
             case 14:
                 strUpart = strUpart + "佰";
                 break;
             case 15:
                 strUpart = strUpart + "仟";
                 break;
             case 16:
                 strUpart = strUpart + "万";
                 break;
             default:
                 strUpart = strUpart + "";
                 break;
         }

         strUpper = strUpart + strUpper;
         iTemp = iTemp + 1;
     }

     strUpper = strUpper.Replace("零拾", "零");
     strUpper = strUpper.Replace("零佰", "零");
     strUpper = strUpper.Replace("零仟", "零");
     strUpper = strUpper.Replace("零零零", "零");
     strUpper = strUpper.Replace("零零", "零");
     strUpper = strUpper.Replace("零角零分", "整");
     strUpper = strUpper.Replace("零分", "整");
     strUpper = strUpper.Replace("零角", "零");
     strUpper = strUpper.Replace("零亿零万零圆", "亿圆");
     strUpper = strUpper.Replace("亿零万零圆", "亿圆");
     strUpper = strUpper.Replace("零亿零万", "亿");
     strUpper = strUpper.Replace("零万零圆", "万圆");
     strUpper = strUpper.Replace("零亿", "亿");
     strUpper = strUpper.Replace("零万", "万");
     strUpper = strUpper.Replace("零圆", "圆");
     strUpper = strUpper.Replace("零零", "零");
     Console.WriteLine("零角零分");
     // 对壹圆以下的金额的处理
     if (strUpper.Substring(0, 1) == "圆")
     {
         strUpper = strUpper.Substring(1, strUpper.Length - 1);
     }
     if (strUpper.Substring(0, 1) == "零")
     {
         strUpper = strUpper.Substring(1, strUpper.Length - 1);
     }
     if (strUpper.Substring(0, 1) == "角")
     {
         strUpper = strUpper.Substring(1, strUpper.Length - 1);
     }
     if (strUpper.Substring(0, 1) == "分")
     {
         strUpper = strUpper.Substring(1, strUpper.Length - 1);
     }
     if (strUpper.Substring(0, 1) == "整")
     {
         strUpper = "零圆整";
     }
     functionReturnValue = strUpper;

     if (IsNegative == true)
     {
         return "负" + functionReturnValue;
     }
     else
     {
         return string.Format(functionReturnValue, Encoding.GetEncoding("GB2312"));
     }
 }

4、画双横线
在这里插入图片描述

pdfCanvas.MoveTo(computeValue.computeUnit(141), computeValue.computeUnit(278.5f));
pdfCanvas.LineTo(computeValue.computeUnit(69), computeValue.computeUnit(278.5f));
pdfCanvas.SetStrokeColor(new DeviceRgb(128, 0, 0));
pdfCanvas.MoveTo(computeValue.computeUnit(141), computeValue.computeUnit(277.5f));
pdfCanvas.LineTo(computeValue.computeUnit(69), computeValue.computeUnit(277.5f));
pdfCanvas.SetStrokeColor(new DeviceRgb(128, 0, 0));
pdfCanvas.ClosePathStroke();

5、创作二维码

//设置扫描二维码后显示的文字或内容
string code = $"01,{发票票种model},," + 发票号码model + "," + 价税合计model + "," + DateTime.Parse(开票日期model).ToString("yyyyMMdd") + ",,";
//将code与转换为CRC16编码后的字节链接
code = code + CRC16(System.Text.Encoding.UTF8.GetBytes(code));
//将链接好的字符串转换为二维码字节
model.qrCode = GetQrCode(code);//model.qrCode为byte[]类型
//在Canvas中添加动态二维码(具体实现可参考下一篇笔记(iText7——画发票PDF(完整)))
 Image EWM = new Image(ImageDataFactory.Create(_model.qrCode))
     .SetWidth(computeValue.computeUnit(20))
     .SetHeight(computeValue.computeUnit(20));
 canvas.Add(EWM.SetFixedPosition(1, computeValue.computeUnit(7), computeValue.computeUnit(271)));
//若要在二维码中间放图片,则加上图片:
Image S = new Image(ImageDataFactory.Create("E://图片//发票图片//Shui.png"))
    .SetWidth(computeValue.computeUnit(4))
    .SetHeight(computeValue.computeUnit(4));
canvas.Add(S.SetFixedPosition(1, computeValue.computeUnit(15), computeValue.computeUnit((float)279)));


/// <summary>
/// CRC16编码
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
private static string CRC16(byte[] data)
{
    ushort crc = 0xFFFF;
    int len = data.Length;
    for (int i = 0; i < len; i++)
    {
        crc = (ushort)((crc >> 8) ^ data[i]);
        for (int j = 0; j < 8; j++)
            crc = (crc & 1) == 1 ? (ushort)((crc >> 1) ^ 0xA001) : (ushort)(crc >> 1);
    }
    return string.Format("{0:X}", crc).PadLeft(4, '0');
}

/// <summary>
/// 生成发票二维码
/// </summary>
/// <returns></returns>
private static byte[] GetQrCode(string codeValue)
{
    // 设定二维码大小
    QrCodeEncodingOptions qrCode = new QrCodeEncodingOptions();
    qrCode.ErrorCorrection = ErrorCorrectionLevel.M;
    qrCode.CharacterSet = "UTF-8";
    qrCode.Height = 180;
    qrCode.Width = 180;
    qrCode.Margin = 1;
    // 生成二维码
    BarcodeWriter writer = new BarcodeWriter();
    writer.Format = BarcodeFormat.QR_CODE;
    writer.Options = qrCode;
    writer.Options.PureBarcode = true; // 不显示条码下面的数据
    Bitmap bitmap = writer.Write(codeValue);
    MemoryStream ms = new MemoryStream();
    bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
    byte[] arr = new byte[ms.Length];
    ms.Position = 0;
    ms.Read(arr, 0, (int)ms.Length);
    ms.Close();
    return arr;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/708230.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

短视频矩阵工具有哪些?如何辨别是否正规?

随着短视频平台的持续火爆&#xff0c;搭建短视频矩阵成为各大品牌商家提高营销效果和完成流量变现的主要方式之一&#xff0c;类似于短视频矩阵工具有哪些等问题也在多个社群有着不小的讨论度。 而就短视频矩阵工具的市场现状而言&#xff0c;其整体呈现出数量不断增长&#x…

Mybatis中#和$的区别

在MyBatis中&#xff0c;#{} 和 ${} 是两种用于参数替换的占位符&#xff0c;但它们在处理方式和安全性上有所不同 #{} 预编译处理&#xff1a;MyBatis在处理#{}时&#xff0c;会将其中的内容作为参数进行预编译处理。这意味着MyBatis会生成一个PreparedStatement对象&#x…

Prometheus+Grafana监控MySQL

一、准备 grafana服务器&#xff1a;192.168.48.136Prometheus服务器&#xff1a;192.168.48.136被监控服务器&#xff1a;192.168.48.134、192.168.48.135查看时间是否同步 二、安装prometheus server 【2.1】安装 # 解压安装包 tar -zxvf prometheus-2.52.0.linux-amd64.t…

location.href = ‘welcome.html‘;报错 - Completed 406 NOT_ACCEPTABLE

巧妙解决方案&#xff0c;使用服务端进行redirect即可 。 package com.aliyun.controller;import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping;Controller public class RedirectController {GetMapping("/r…

华为云CodeArts API:API管理一体化平台 5月新特性上线啦!

CodeArts API是华为云API全生命周期管理一体化解决方案平台&#xff0c;支持开发者高效实现API设计、API开发、API测试、API托管、API运维、API变现的一站式体验。 通过以API契约为锚点&#xff0c;CodeArts API保证API各阶段数据高度一致&#xff0c;为开发者提供友好易用的A…

【kubernetes】k8s中包管理工具-----Helm 超详细解读

目录 一、Helm 1.1什么是 Helm 1.2Helm 有三个重要的概念 1.2.1Chart 1.2.2Repository&#xff08;仓库&#xff09; 1.2.3Release 1.3Helm3 与 Helm2 的区别 二、Helm 部署 2.1安装 helm 2.2命令补全 2.3使用 helm 安装 Chart 2.3.1添加常用的 chart 仓库 2.3.2…

数据结构 实验 2

题目一&#xff1a;遍历二叉树 一、实验目的 熟练掌握指针变量、链表的含义掌握二叉树的结构特性&#xff0c;以及二叉链表的存储方式的特点掌握用递归的方法处理二叉树的基本算法掌握二叉树的四种遍历方式&#xff08;先序、中序、后序、按层次&#xff09; 二、实验步骤 …

Linux C语言:字符串处理函数

一、字符串函数 1、C库中实现了很多字符串处理函数 #include <string.h> ① 求字符串长度的函数strlen② 字符串拷贝函数strcpy③ 字符串连接函数strcat④ 字符串比较函数strcmp 2、字符串长度函数strlen 格式&#xff1a;strlen(字符数组)功能&#xff1a;计算字符串…

Spring AI 接入OpenAI实现文字生成图片功能

Spring AI 框架集成的图片大模型 2022年出现的三款文生图的现象级产品&#xff0c;DALL-E、Stable Diffusion、Midjourney。 OpenAI dall-e-3dall-e-2 Auzre OpenAI dall-e-3dall-e-2 Stability stable-diffusion-v1-6 ZhiPuAI cogview-3 OpenAI 与 Auzer OpenAI 使用的图片…

接口自动化测试工程化——了解接口测试

什么是接口测试 接口测试也是一种功能测试 我理解的接口测试&#xff0c;其实也是一种功能测试&#xff0c;只是平时大家说的功能测试更多代指 UI 层面的功能测试&#xff0c;而接口测试更偏向于服务端层面的功能测试。 接口测试的目的 测试左移&#xff0c;尽早介入测试&a…

6.归并+快排

5. 归并排序 核心思想 将无序数组从中间分为左右两个部分&#xff0c;分别给左右两个部分排序&#xff0c;排序以后把两个有序区间进行合并 把数组从中间分为左右两部分分别对前后两部分进行排序将排好序的两部分合并 包含两个部分&#xff1a;拆解阶段和合并阶段 归并排序…

跨平台看抖音、哔哩哔哩、虎牙、斗鱼啦,一个app即可完成

一、简介 1、一款免费、开源、无广告、跨平台的,可以观看抖音、哔哩哔哩、虎牙、斗鱼等平台的直播内容的软件。它简单好用,支持 Windows、MacOS、Linux、Android、iOS 等平台。 二、下载 1、文末有下载链接,apk手机可直接安装,不明白可以私聊我哈(麻烦咚咚咚,动动小手给个…

详解QFileSystemModel的使用

在Qt应用程序开发中&#xff0c;QFileSystemModel是一个强大的类&#xff0c;用于展示和操作文件系统的信息。它基于标准的QAbstractItemModel&#xff0c;提供了浏览本地文件系统目录树的能力&#xff0c;并且能够自动更新以反映文件系统的变化。本文将详细讲解QFileSystemMod…

MongoDB——写入耗时

mongodb写入10万条数据的耗时差不多是1s import time import pymongo from pymongo import MongoClient# 连接到MongoDB client MongoClient(mongodb://localhost:27017/) db client[test_db] collection db[test_collection]# 生成10万条数据 documents [{"name&quo…

ThinkPHP内核在线客服系统源码多商户版 对接适用场景(PC+WAP+公众号)

源码介绍 大部分站长都了解美洽系统&#xff0c;就跟这种类似的&#xff0c;可以实现一行代码接入客服&#xff0c;非常舒服&#xff0c;支持无限客服&#xff0c;无限坐席! 私有化源码部署&#xff0c;数据可控&#xff0c;稳定可靠。可自定义版权、logo。支持网页、微信公众…

CPN tools学习——可执行的 PN

目录 1添加令牌 2.转换防护Guard 1添加令牌 左侧新建颜色集和变量的声明定义&#xff1a; 为库所分配颜色集&#xff1a;左键tab键 P1处&#xff1a;添加多重集合&#xff0c;表示添加了两个令牌&#xff0c;第一个令牌值为A&#xff0c;第二个为B。 P2处&#xff1a;表示…

docker的教程长亭

把我的常用docker写在这里 之前用 vul - hub 靶场经常用 现在docker不知道为什么挂了 开启 docker-compose up -d 关闭 docker-compose down docker ps 只是运行 docker ps -a 所有 包括停止 docker ps -q 只看id docker stop <container_name_or_id> docker 的容器…

辣椒属2个T2T基因组-文献精读23

Two telomere-to-telomere gapless genomes reveal insights into Capsicum evolution and capsaicinoid biosynthesis 两个端粒到端粒无缝基因组揭示了辣椒进化和辣椒素生物合成的相关见解 摘要 辣椒&#xff08;Capsicum&#xff09;因其果实中含有辣椒素而闻名&#xff0c…

zabbix自定义监控mysql状态和延迟

zabbix自定义监控mysql状态和延迟 文章目录 zabbix自定义监控mysql状态和延迟zabbix自定义监控mysql状态配置主从配置自定义监控添加监控项添加触发器模拟测试异常 zabbix自定义监控mysql延迟配置自定义监控添加监控项添加触发器测试 zabbix自定义监控mysql状态 配置主从 1.安…