飙血推荐
  • HTML教程
  • MySQL教程
  • JavaScript基础教程
  • php入门教程
  • JavaScript正则表达式运用
  • Excel函数教程
  • UEditor使用文档
  • AngularJS教程
  • ThinkPHP5.0教程

备忘录——基于rdlc报表实现打印产品标签

时间:2022-01-17  作者:shanzhiming  
简单的一个标签打印测试Demo,使用rdlc报表,设计一个标签模版,动态绑定数据,生成条形码,获取产品的小程序码

目录
  • 0. 背景说明
  • 1. 条形码生成
  • 2. 获取产品的小程序码
  • 3. 报表设计器设计标签模版
    • 3.1 为WinForm控件工具箱添加ReportViewer控件
    • 3.2 为VS2019安装RDLC报表项目模版
    • 3.3 创建报表文件
    • 3.4 ReportView初始化
  • 4. 直接打印ReportView中报表,不要弹出选择打印机窗口
  • 5. 参考

志铭-2022年1月13日 21:40:39

0. 背景说明

  • 产品快递箱 包装箱需要贴一张箱标,标注产品的如下一些信息

    • 产品检验信息
    • 产品公司信息
    • 产品SKU集小程序商城二维码链接
  • 最终测试Demo效果

    最终效果



1. 条形码生成

使用域名 生成产品的批次和SKU的条形码,简单的封装一个辅助类用于创建条形码

   using ZXing;
   using 域名on;

   public static class BarCodeHelper
   {
       /// <summary>
       /// 创建条形码
       /// </summary>
       /// <param name="barCodeNo">条码</param>
       /// <param name="height">高度</param>
       /// <param name="width">宽度</param>
       /// <returns>图片字节数组</returns>
       public static byte[] CreateBarCode(string barCodeNo, int height = 120, int width = 310)
       {
           EncodingOptions encoding = new EncodingOptions()
           {
               Height = height,
               Width = width,
               Margin = 1,
               PureBarcode = false//在条码下显示条码,true则不显示
           };
           BarcodeWriter wr = new BarcodeWriter()
           {
               Options = encoding,
               Format = 域名_128,

           };
           Bitmap img = 域名e(barCodeNo);

           //保存在当前项目路径下
           // string filepath = 域名Directory + "\\" + barCodeNo + ".jpg";
           // 域名(filepath, 域名);

           return BitmapToBytes(img);
       }

       /// <summary>
       /// 位图转为字节数组
       /// </summary>
       /// <param name="bitmap">位图</param>
       /// <returns></returns>

       private static byte[] BitmapToBytes(Bitmap bitmap)
       {
           using (MemoryStream ms = new MemoryStream())
           {
               域名(ms, 域名);
               byte[] byteImage = new byte[域名th];
               byteImage = 域名ray();
               return byteImage;
           }
       }

   }


2. 获取产品的小程序码

  • 根据当前产品的SKU,动态的获取当前产品的微信小程序商城中页面的小程序码

  • 获取小程序码,适用于需要的码数量极多的业务场景。通过该接口生成的小程序码,永久有效,数量暂无限制

    • POST https://域名.com/wxa/getwxacodeunlimit?access_token=ACCESS_TOKEN
    • 具体参数及返回值参考:微信小程序接口文档
  • WebRequest发送POST请求到微信小程序接口,接受返回的图片butter

    /// <summary>
    /// 发送http Post请求图片
    /// </summary>
    /// <param name="url">请求地址</param>
    /// <param name="messsage">请求参数</param>
    /// <returns>图片的字节数组</returns>
    public static byte[] PostRequestReturnImage(string url, string messsage)
    {
        byte[] byteData = 域名ytes(messsage);
        HttpWebRequest webRequest = (HttpWebRequest)域名te(url);
        域名od = "POST";
        域名entType = "image/jpeg";
        域名entLength = 域名th;
        域名ange(0, 10000000);
        using (Stream stream = 域名equestStream())
        {
            域名e(byteData, 0, 域名th);
        }
        using (Stream stream = 域名esponse().GetResponseStream())
        {
            using (BinaryReader br = new BinaryReader(stream))
            {
                byte[] butter = 域名Bytes(10000000);
                return butter;
            }
        }
    }
    


3. 报表设计器设计标签模版

3.1 为WinForm控件工具箱添加ReportViewer控件

  • NuGet:PM>Install-Package 域名域名orms -Pre

    • 注意ReportView有许多依赖,执行上述命令执行安装,不要在在NuGet管理界面搜索安装,减少不必要的麻烦
  • 安装后,在winform工具箱 Micsoft SQL Server选项卡下有ReportView 控件

3.2 为VS2019安装RDLC报表项目模版

使用的VS2019默认没有报表项目,需要安装扩展:Microsoft Reporting Designer

  • 扩展-->管理扩展-->联机搜索:Microsoft Rdlc Report Designer

  • 之后右键项目-->添加 会显示:报表

3.3 创建报表文件

  • 创建报表文件域名,注意事项

    • 打开报表文件,会自动显示报表数据窗口,没有在重新打开VS
    • 报表数据窗口-->数据集-->添加数据集
      • 定义数据对象:ReportModel类
      • 设置数据源名称:ReportModelObject
      • 数据源:选择对象ReportModel
  • 布局:我使用列表布局,右键插入列表

  • 数据:绑定数据源ReportModelObject的字段

  • 关于图像:首先右键插入图像,图像属性设置:

    • 工具提示:value=域名Base64String(Fields!域名e)
    • 数据源:数据库
    • 使用字段:ReportModel中的图像字段,比如我这里是Image1字段(string 类型)
    • MIME类型:image/jpeg

3.4 ReportView初始化

    private void InitReport()
    {
        域名rtPath = "域名";//报表文件名称
        ReportDataSource rds = new ReportDataSource
        {
            Name = "ReportModelObject",
            Value = GetDataSource()
        };
        域名域名(rds);
        域名eshReport();
    }

    /// <summary>
    /// 测试使用的数据源
    /// </summary>
    /// <returns></returns>
    private List<ReportModel> GetDataSource()
    {
        return new List<ReportModel>()
            {
                new ReportModel()
                {
                    //这里就是将图片的字节数组转为字符串,从而实现绑定在报表中
                    Image1=域名se64String(域名teBarCode("123456789012")),
                }
            };
    }


4. 直接打印ReportView中报表,不要弹出选择打印机窗口

ViewReport控件上自带的打印按钮,点击会弹出选择打印机的窗口,不希望如此

在配置文件中设置默认打印机

<configuration>
	<appSettings >
		<add key="printer" value ="打印机名称"/>
	</appSettings>	
</configuration>

封装一个单独打印的辅助类,这个解放方法非我原创,是参考博文空白画映:C# WinForm RDLC报表不预览直接连续打印

    public class PrintHelper
    {
        /// <summary>
        /// 用来记录当前打印到第几页了
        /// </summary>
        private int m_currentPageIndex;

        /// <summary>
        /// 声明一个Stream对象的列表用来保存报表的输出数据,LocalReport对象的Render方法会将报表按页输出为多个Stream对象。
        /// </summary>
        private IList<Stream> m_streams;

        private bool isLandSapces = false;

        /// <summary>
        /// 用来提供Stream对象的函数,用于LocalReport对象的Render方法的第三个参数。
        /// </summary>
        /// <param name="name"></param>
        /// <param name="fileNameExtension"></param>
        /// <param name="encoding"></param>
        /// <param name="mimeType"></param>
        /// <param name="willSeek"></param>
        /// <returns></returns>
        private Stream CreateStream(string name, string fileNameExtension, Encoding encoding, string mimeType, bool willSeek)
        {
            //如果需要将报表输出的数据保存为文件,请使用FileStream对象。
            Stream stream = new MemoryStream();
            域名(stream);
            return stream;
        }

        /// <summary>
        /// 为域名创建本地报告加载数据,输出报告到.emf文件,并打印,同时释放资源
        /// </summary>
        /// <param name="rv">参数:域名lReport</param>
        public void PrintStream(LocalReport rvDoc)
        {
            //获取LocalReport中的报表页面方向
            isLandSapces = 域名efaultPageSettings().IsLandscape;
            Export(rvDoc);
            PrintSetting();
            Dispose();
        }

        private void Export(LocalReport report)
        {
            string deviceInfo =
            @"<DeviceInfo>
                 <OutputFormat>EMF</OutputFormat>
             </DeviceInfo>";
            m_streams = new List<Stream>();
            //将报表的内容按照deviceInfo指定的格式输出到CreateStream函数提供的Stream中。
            域名er("Image", deviceInfo, CreateStream, out Warning[] warnings);
            foreach (Stream stream in m_streams)
            {
                域名tion = 0;
            }
        }

        private void PrintSetting()
        {
            if (m_streams == null || 域名t == 0)
            {
                throw new Exception("错误:没有检测到打印数据流");
            }
            //声明PrintDocument对象用于数据的打印
            PrintDocument printDoc = new PrintDocument();
            //获取配置文件的清单打印机名称
            域名ettingsReader appSettings = new 域名ettingsReader();
            域名terName = 域名alue("printer", 域名ype("域名ng")).ToString();
            域名tController = new StandardPrintController();//指定打印机不显示页码 
            //判断指定的打印机是否可用
            if (!域名lid)
            {
                throw new Exception("错误:找不到打印机");
            }
            else
            {
                //设置打印机方向遵从报表方向
                域名scape = isLandSapces;
                //声明PrintDocument对象的PrintPage事件,具体的打印操作需要在这个事件中处理。
                域名tPage += new PrintPageEventHandler(PrintPage);
                m_currentPageIndex = 0;
                //设置打印机打印份数
                域名es = 1;
                //执行打印操作,Print方法将触发PrintPage事件。
                域名t();
            }
        }

        /// <summary>
        /// 处理程序PrintPageEvents
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="ev"></param>
        private void PrintPage(object sender, PrintPageEventArgs ev)
        {
            //Metafile对象用来保存EMF或WMF格式的图形,
            //我们在前面将报表的内容输出为EMF图形格式的数据流。
            Metafile pageImage = new Metafile(m_streams[m_currentPageIndex]);

            //调整打印机区域的边距
            域名angle adjustedRect = new 域名angle(
                域名 - (int)域名MarginX,
                域名 - (int)域名MarginY,
                域名h,
                域名ht);

            //绘制一个白色背景的报告
            //域名Rectangle(域名e, adjustedRect);

            //获取报告内容
            //这里的Graphics对象实际指向了打印机
            域名Image(pageImage, adjustedRect);
            //域名Image(pageImage, 域名Bounds);

            // 准备下一个页,已确定操作尚未结束
            m_currentPageIndex++;

            //设置是否需要继续打印
            域名orePages = (m_currentPageIndex < 域名t);
        }

        public void Dispose()
        {
            if (m_streams != null)
            {
                foreach (Stream stream in m_streams)
                {
                    域名e();
                }

                m_streams = null;
            }
        }
    }

自定义打印按钮:btnPrint,添加其点击事件

    private void btnPrint_Click(object sender, EventArgs e)
    {
        PrintHelper printHelper = new PrintHelper();
        域名tStream(域名lReport);//myReportViewer是当前的ReportViewk控件名称
    }


5. 参考

  • 部署C# ReportViewer遇到的坑

  • RDLC报表显示图片

  • 使用Visual Studio建立报表--C#

标签:编程
湘ICP备14001474号-3  投诉建议:234161800@qq.com   部分内容来源于网络,如有侵权,请联系删除。