如何在Crystal Report中生成Code 128与QR code?
Crystal Report 集成ZXing生成QR Code/Code128条码实现方案
你已经搭好了DataSet推数的模式,还装了ZXing,直接走后端生成条码字节流推到报表的方案就行,不用折腾Crystal的第三方公式、条码字体那些坑,兼容所有运行时版本,部署也不用额外装东西。
1. 改造现有DataSet
打开你项目里给Crystal Report供数的强类型DataSet,给对应业务DataTable新增2个字段:
- 字段名:
QRCodeImg,类型选System.Byte[](字节数组) - 字段名:
Code128Img,类型选System.Byte[](字节数组)
不用设成Image类型,字节数组是Crystal识别图片兼容性最好的格式。
2. 后端用ZXing生成条码字节
先引入必要的命名空间,缺哪个引用直接补就行:
using ZXing; using ZXing.QrCode; using ZXing.Code128; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Runtime.InteropServices;
直接复用两个生成方法,输出的PNG格式字节流直接能被Crystal识别:
/// <summary> /// 生成QR Code字节流 /// </summary> /// <param name="content">编码内容</param> /// <param name="width">图片宽度</param> /// <param name="height">图片高度</param> private byte[] GenerateQRCode(string content, int width = 150, int height = 150) { var barcodeWriter = new BarcodeWriterPixelData { Format = BarcodeFormat.QR_CODE, Options = new QrCodeEncodingOptions { CharacterSet = "UTF-8", Width = width, Height = height, Margin = 1 // 保留最小白边,保证扫码识别率 } }; var pixelData = barcodeWriter.Write(content); using (var bmp = new Bitmap(pixelData.Width, pixelData.Height, PixelFormat.Format32bppRgb)) using (var ms = new MemoryStream()) { var bmpLock = bmp.LockBits(new Rectangle(0, 0, pixelData.Width, pixelData.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppRgb); try { Marshal.Copy(pixelData.Pixels, 0, bmpLock.Scan0, pixelData.Pixels.Length); } finally { bmp.UnlockBits(bmpLock); } bmp.Save(ms, ImageFormat.Png); return ms.ToArray(); } } /// <summary> /// 生成Code128条码字节流 /// </summary> /// <param name="content">编码内容</param> /// <param name="width">图片宽度</param> /// <param name="height">图片高度</param> private byte[] GenerateCode128(string content, int width = 220, int height = 60) { var barcodeWriter = new BarcodeWriterPixelData { Format = BarcodeFormat.CODE_128, Options = new Code128EncodingOptions { Width = width, Height = height, Margin = 1, PureBarcode = false // 设为true则不显示条码下方的明文内容 } }; var pixelData = barcodeWriter.Write(content); using (var bmp = new Bitmap(pixelData.Width, pixelData.Height, PixelFormat.Format32bppRgb)) using (var ms = new MemoryStream()) { var bmpLock = bmp.LockBits(new Rectangle(0, 0, pixelData.Width, pixelData.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppRgb); try { Marshal.Copy(pixelData.Pixels, 0, bmpLock.Scan0, pixelData.Pixels.Length); } finally { bmp.UnlockBits(bmpLock); } bmp.Save(ms, ImageFormat.Png); return ms.ToArray(); } }
在你原来给DataSet填充业务数据的逻辑里,加一步给条码字段赋值就行,举个例子:
// 假设reportTable是你已经填充完业务数据的DataTable foreach (DataRow row in reportTable.Rows) { // 替换成你实际要编码的字段,比如订单号、追溯码之类的 string qrEncodeStr = row["订单ID"].ToString(); string code128EncodeStr = row["SKU编码"].ToString(); row["QRCodeImg"] = GenerateQRCode(qrEncodeStr); row["Code128Img"] = GenerateCode128(code128EncodeStr); } // 后面按你原有逻辑把DataSet绑定到Crystal Report报表即可,不用改其他传参代码
3. 报表模板绑定条码字段
- 打开你的rpt报表文件,刷新字段资源管理器里的DataSet字段,能看到刚才加的两个字节数组字段
- 直接把这两个字段拖到报表上要放置条码的位置,Crystal会自动识别为图片控件
- 右键点图片控件选「设置对象格式」,在图片标签页调整等比缩放比例到合适尺寸就行
踩过的坑提醒
- 别尝试在Crystal的公式字段里直接调用ZXing生成条码,Crystal运行时对第三方DLL的加载权限、版本匹配限制极多,部署到服务器十有八九报加载依赖失败,后端生成传字节流是最稳的方案
- 条码Margin别设成0,四周留最少1个单位的白边,不然扫码枪/手机扫码识别率极低
- 调整条码大小优先改生成方法里的width、height参数,别在模板里硬拉图片导致变形,变形后大概率扫不出来
- Code128不用你手动加起始/停止校验位,ZXing会自动处理,直接传原始编码字符串就行
- 不用在服务器或者客户端装任何条码字体,生成的是图片,所有环境打开都能正常显示
内容的提问来源于stack exchange,提问作者pankaj babbar
相关产品推荐
相关产品推荐

