VS2017、WPF使用报表工具RDLC完成报表,打印预览和直接打印

最近需要用到WPF做一个报表
然后经过各种查阅资料
终于整出来了一个Demo

软件是VS2017 .netframework是4.5
1.配置环境
工具,获取扩展和更新
然后安装RDLC,然后重启
VS2017、WPF使用报表工具RDLC完成报表,打印预览和直接打印_第1张图片
新建项目
项目的引用里面添加
System.Printing
System.Management
System.Drawing

NuGet包里面添加
Microsoft.ReportViewer V11.0.3366.16

VS2017、WPF使用报表工具RDLC完成报表,打印预览和直接打印_第2张图片

2.创建实体类和数据集

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace RDLCPrinter
{
    public class Customer
    { 

        public string carrierCompanyName { get; set; }
        public string checkInTime { get; set; }
        public string startPoint { get; set; }
        public string outStock { get; set; }

    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace RDLCPrinter
{
    class Plan
    {
        public string carrierCompanyName { get; set; }  //承运单位
        public string driver { get; set; } //司机
        public string driverId { get; set; } //司机id
        public string vehicleNo { get; set; } //车牌号
        public string mobile { get; set; } //电话
        public string planNo { get; set; } //调度单号
        public string startPoint { get; set; } //装点
        public string endPoint { get; set; } //卸点
        public string flowName { get; set; } //流向
        public string prodName { get; set; } //品名
        public string planWeight { get; set; } //重量
        public string planQuantity { get; set; } //件数
        public string remark { get; set; } //备注
        public string cardNo { get; set; }
        public string planStatusName { get; set; }//签到状态
        public string checkInTime { get; set; }//签到时间
        public string scanDateTime { get; set; }//扫码日期和时间
        public string scanTime { get; set; }//扫码时间
        public string outStock { get; set; }//仓库
    }
}

然后创建两个数据集
VS2017、WPF使用报表工具RDLC完成报表,打印预览和直接打印_第3张图片
数据集里 右键 添加 DataTable把实体类的属性都加进去
或者
工具箱 双击DataTable
加完之后是这样的
VS2017、WPF使用报表工具RDLC完成报表,打印预览和直接打印_第4张图片

VS2017、WPF使用报表工具RDLC完成报表,打印预览和直接打印_第5张图片

然后创建一个rdlc
VS2017、WPF使用报表工具RDLC完成报表,打印预览和直接打印_第6张图片
左边 新建 数据集 VS2017、WPF使用报表工具RDLC完成报表,打印预览和直接打印_第7张图片
自己找到实体类,或者直接选择刚才创建好的DataSet.xsd

两个实体类都添加一下数据源

然后在rdlc文件 右键 插入 表
VS2017、WPF使用报表工具RDLC完成报表,打印预览和直接打印_第8张图片
表里绑定一下属性
VS2017、WPF使用报表工具RDLC完成报表,打印预览和直接打印_第9张图片
表头的汉字是自己加的

新建几个文本框 还有创建一个页眉
一个文本框绑定页数
另外的绑定另外一个实体类
具体的操作流程
在一个文本框上面右键
数据集->DataSet->然后选择属性双击
VS2017、WPF使用报表工具RDLC完成报表,打印预览和直接打印_第10张图片
绑定页数同理,用的是内置字段->pageNumber双击,然后用一下字符串拼接
(这个感觉和Excel非常神似啊)
VS2017、WPF使用报表工具RDLC完成报表,打印预览和直接打印_第11张图片
3.页面设计
MainWindow添加两个按钮,一个是打印预览的,一个是直接打印的


    
        
            

然后是RepoerViewer.xaml
这个需要注意的是
需要在头上加上这个

xmlns:rv="clr-namespace:Microsoft.Reporting.WinForms;assembly=Microsoft.ReportViewer.WinForms"

然后是整体的代码


    
        
            
        
    

然后新建一个CustomerReport.xaml
这个是打印预览界面
调一下刚才的ReportViewer



    
        
    


4.数据注入
这一步是最主要的
ReportViewer.cs注入打印预览界面的数据
然后mainWindow注入直接打印的数据

using System.Data;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Reporting.WinForms;

namespace RDLCPrinter

{

    /// 

    /// Interaction logic for ReportViewer.xaml

    /// 

    public partial class ReportViewer : UserControl
    {
        public ReportViewer()
        {
            InitializeComponent();
        }
        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {          
            DataTable dt2 = new DataTable();
            dt2.Columns.Add(new DataColumn("carrierCompanyName", typeof(string)));
            dt2.Columns.Add(new DataColumn("checkInTime", typeof(string)));
            dt2.Columns.Add(new DataColumn("startPoint", typeof(string)));
            dt2.Columns.Add(new DataColumn("outStock", typeof(string)));
            DataRow dr2 = dt2.NewRow();
            dr2["carrierCompanyName"] = "日照钢铁";
            dr2["checkInTime"] = "2019-8-13 16:03";
            dr2["startPoint"] = "山东青岛";
            dr2["outStock"] = "Z1-热轧#1580成品库";
            dt2.Rows.Add(dr2);
            ReportDataSource reportDataSource2 = new ReportDataSource();
            reportDataSource2.Name = "DataSet1";
            reportDataSource2.Value = dt2;
            reportViewer1.LocalReport.DataSources.Add(reportDataSource2);
            DataTable dt = new DataTable();
            dt.Columns.Add(new DataColumn("carrierCompanyName", typeof(string)));
            dt.Columns.Add(new DataColumn("driverId", typeof(string)));
            dt.Columns.Add(new DataColumn("startPoint", typeof(string)));
            dt.Columns.Add(new DataColumn("endPoint", typeof(string)));
            dt.Columns.Add(new DataColumn("prodName", typeof(string)));
            dt.Columns.Add(new DataColumn("planQuantity", typeof(string)));
            dt.Columns.Add(new DataColumn("checkInTime", typeof(string)));
            dt.Columns.Add(new DataColumn("outStock", typeof(string)));

            DataRow dr = dt.NewRow();
            for (int i = 0; i < 20; i++)
            {
                dt.Rows.Add(new string[] { ("京创" + i).ToString(), (i + 10).ToString(), ("日照"+i).ToString(),
                    ("山东" +i).ToString(),"卷钢" + i.ToString(),(10+i).ToString(),("2019-8-1"+i).ToString(), (i+"号").ToString()});
            } 

            ReportDataSource reportDataSource = new ReportDataSource();
            reportDataSource.Name = "DataSet2";
            reportDataSource.Value = dt;
            reportViewer1.LocalReport.DataSources.Add(reportDataSource);
            reportViewer1.LocalReport.ReportPath = "D:\\Documents\\GitHub\\DEMO\\RDLC\\RDLC\\CustomerReport.rdlc"; 
            //刷新
            reportViewer1.RefreshReport();
        }
        private void reportViewer_RenderingComplete(object sender, Microsoft.Reporting.WinForms.RenderingCompleteEventArgs e)

        {
        }

    }

}

直接打印用到了一个工具类

using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing.Imaging;
using System.Drawing.Printing;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.Reporting.WinForms;

namespace RDLCPrinter
{
    /// 
    /// 通过RDLC向默认打印机输出打印报表
    /// 
    public class BillPrint : IDisposable
    {
        /// 
        /// 当前打印页号
        /// 
        static int m_currentPageIndex;

        /// 
        /// RDCL转换stream一页对应一个stream
        /// 
        static List m_streams;

        /// 
        /// 把report输出成stream
        /// 
        /// 传入需要Export的report
        private void Export(LocalReport report)
        {
            string deviceInfo =
              "" +
              "  EMF" +
                //"  2in" +
                //"  20in" +
                "  1in" +
                "  0in" +
                "  0in" +
                "  1in" +
              "";
            Warning[] warnings;
            m_streams = new List();
            report.Render("Image", deviceInfo, CreateStream, out warnings);
            foreach (Stream stream in m_streams)
                stream.Position = 0;
        }

        /// 
        /// 创建具有指定的名称和格式的流。
        /// 
        private Stream CreateStream(string name, string fileNameExtension,
      Encoding encoding, string mimeType, bool willSeek)
        {
            Stream stream = new FileStream(name + "." + fileNameExtension,
              FileMode.Create);
            m_streams.Add(stream);
            return stream;
        }

        /// 
        /// 打印输出
        /// 
        private void PrintPage(object sender, PrintPageEventArgs ev)
        {
            Metafile pageImage =
              new Metafile(m_streams[m_currentPageIndex]);
            ev.Graphics.DrawImage(pageImage, ev.PageBounds);
            m_currentPageIndex++;
            ev.HasMorePages = (m_currentPageIndex < m_streams.Count);
        }

        /// 
        /// 打印预处理
        /// 
        private void Print()
        {
            PrintDocument printDoc = new PrintDocument();
            string printerName = printDoc.PrinterSettings.PrinterName;
            if (m_streams == null || m_streams.Count == 0)
                return;
            printDoc.PrinterSettings.PrinterName = printerName;
            if (!printDoc.PrinterSettings.IsValid)
            {
                string msg = String.Format("Can't find printer \"{0}\".", printerName);
                throw new Exception(msg);
            }
            printDoc.PrintPage += new PrintPageEventHandler(PrintPage);
            StandardPrintController spc = new StandardPrintController();
            printDoc.PrintController = spc;
            printDoc.Print();
        }

        public void Dispose()
        {
            if (m_streams != null)
            {
                foreach (Stream stream in m_streams)
                    stream.Close();
                m_streams = null;
            }
        }

        /// 
        /// 对外接口,启动打印
        /// 
        /// 打印报表对应的数据源
        /// 打印报表名称
        public static void Run(LocalReport report)
        {
            //LocalReport report = new LocalReport();
            //report.ReportPath = @"..\..\" + sReport;
            //ReportDataSource dataset = new ReportDataSource("DataSet1", dtSource);
            //report.DataSources.Add(dataset);
            m_currentPageIndex = 0;
            BillPrint billPrint = new BillPrint();
            billPrint.Export(report);
            billPrint.Print();
            billPrint.Dispose();
        }

        /// 
        /// 获取打印机状态
        /// 
        /// 打印机名称
        /// 输出打印机状态
        private static void GetPrinterStatus2(string printerName, ref uint status)
        {
            try
            {

                string lcPrinterName = printerName;
                IntPtr liHandle = IntPtr.Zero;
                if (!Win32.OpenPrinter(lcPrinterName, out liHandle, IntPtr.Zero))
                {
                    Console.WriteLine("print  is close");
                    return;
                }
                UInt32 level = 2;
                UInt32 sizeNeeded = 0;
                IntPtr buffer = IntPtr.Zero;
                Win32.GetPrinter(liHandle, level, buffer, 0, out sizeNeeded);
                buffer = Marshal.AllocHGlobal((int)sizeNeeded);
                if (!Win32.GetPrinter(liHandle, level, buffer, sizeNeeded, out sizeNeeded))
                {
                    Console.WriteLine(Environment.NewLine + "Fail GetPrinter:" + Marshal.GetLastWin32Error());
                    return;
                }

                Win32.PRINTER_INFO_2 info = (Win32.PRINTER_INFO_2)Marshal.PtrToStructure(buffer, typeof(Win32.PRINTER_INFO_2));
                status = info.Status;
                Marshal.FreeHGlobal(buffer);
                Win32.ClosePrinter(liHandle);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// 
        /// 对外接口,调去打印机信息
        /// 
        /// 打印机名称
        /// 返回打印机当前状态
        public static string GetPrinterStatus(string printerName)
        {
            uint intValue = 0;
            PrintDocument pd = new PrintDocument();
            printerName = printerName == "" ? pd.PrinterSettings.PrinterName : printerName;
            GetPrinterStatus2(printerName, ref intValue);
            string strRet = string.Empty;
            switch (intValue)
            {
                case 0:
                    strRet = "准备就绪(Ready)";
                    break;
                case 4194432:
                    strRet = "被打开(Lid Open)";
                    break;
                case 144:
                    strRet = "打印纸用完(Out of Paper)";
                    break;
                case 4194448:
                    strRet = "被打开并且打印纸用完(Out of Paper && Lid Open)";
                    break;
                case 1024:
                    strRet = "打印中(Printing)";
                    break;
                case 32768:
                    strRet = "初始化(Initializing)";
                    break;
                case 160:
                    strRet = "手工送纸(Manual Feed in Progress)";
                    break;
                case 4096:
                    strRet = "脱机(Offline)";
                    break;
                default:
                    strRet = "未知状态(unknown state)";
                    break;
            }
            return strRet;
        }
    }
    public class Win32
    {
        [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool OpenPrinter(string printer, out IntPtr handle, IntPtr printerDefaults);
        [DllImport("winspool.drv")]
        public static extern bool ClosePrinter(IntPtr handle);
        [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool GetPrinter(IntPtr handle, UInt32 level, IntPtr buffer, UInt32 size, out UInt32 sizeNeeded);
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        public struct PRINTER_INFO_2
        {
            public string pServerName;
            public string pPrinterName;
            public string pShareName;
            public string pPortName;
            public string pDriverName;
            public string pComment;
            public string pLocation;
            public IntPtr pDevMode;
            public string pSepFile;
            public string pPrintProcessor;
            public string pDatatype;
            public string pParameters;
            public IntPtr pSecurityDescriptor;
            public UInt32 Attributes;
            public UInt32 Priority;
            public UInt32 DefaultPriority;
            public UInt32 StartTime;
            public UInt32 UntilTime;
            public UInt32 Status;
            public UInt32 cJobs;
            public UInt32 AveragePPM;
        }
    }
}

判断打印机状态好像没啥用

最后是MainWindow的数据

using Microsoft.Reporting.WinForms;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace RDLCPrinter
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
        private void btnClickMe_Click(object sender, RoutedEventArgs e)
        {
            CustomerReport rpt = new CustomerReport();
            rpt.ShowDialog();
        }
        //打印
        private void Button_Print_Click(object sender, RoutedEventArgs e)
        {
            ReportViewer rvDoc = new ReportViewer();
            DataTable dt2 = new DataTable();
            dt2.Columns.Add(new DataColumn("carrierCompanyName", typeof(string)));
            dt2.Columns.Add(new DataColumn("checkInTime", typeof(string)));
            dt2.Columns.Add(new DataColumn("startPoint", typeof(string)));
            dt2.Columns.Add(new DataColumn("outStock", typeof(string)));

            DataRow dr2 = dt2.NewRow();
            dr2["carrierCompanyName"] = "日照钢铁";
            dr2["checkInTime"] = "2019-8-13 16:03";
            dr2["startPoint"] = "山东青岛";
            dr2["outStock"] = "Z1-热轧#1580成品库";
            dt2.Rows.Add(dr2);

            ReportDataSource reportDataSource2 = new ReportDataSource();

            reportDataSource2.Name = "DataSet1";
            reportDataSource2.Value = dt2;
            rvDoc.reportViewer1.LocalReport.DataSources.Add(reportDataSource2);
           
            //rvDoc.reportViewer1
            //rvDoc.reportViewer1.LocalReport.DataSources.Add(reportDataSource2);
            rvDoc.reportViewer1.LocalReport.ReportPath = @"D:\\Documents\\GitHub\\DEMO\\RDLC\\RDLC\\CustomerReport.rdlc";
            //rvDoc.reportViewer1.RefreshReport();

            /*自动打印*/
            DataTable dt = new DataTable();
            dt.Columns.Add(new DataColumn("carrierCompanyName", typeof(string)));
            dt.Columns.Add(new DataColumn("driverId", typeof(string)));
            dt.Columns.Add(new DataColumn("startPoint", typeof(string)));
            dt.Columns.Add(new DataColumn("endPoint", typeof(string)));
            dt.Columns.Add(new DataColumn("prodName", typeof(string)));
            dt.Columns.Add(new DataColumn("planQuantity", typeof(string)));
            dt.Columns.Add(new DataColumn("checkInTime", typeof(string)));
            dt.Columns.Add(new DataColumn("outStock", typeof(string)));

            DataRow dr = dt.NewRow();
            for (int i = 0; i < 20; i++)
            {
                dt.Rows.Add(new string[] { ("京创" + i).ToString(), (i + 10).ToString(), ("日照"+i).ToString(),
                    ("山东" +i).ToString(),"卷钢" + i.ToString(),(10+i).ToString(),("2019-8-1"+i).ToString(), (i+"号").ToString()});
            }

            ReportDataSource reportDataSource = new ReportDataSource();
            reportDataSource.Name = "DataSet2";
            reportDataSource.Value = dt;
            rvDoc.reportViewer1.LocalReport.DataSources.Add(reportDataSource);
            RDLCPrinter.BillPrint.Run(rvDoc.reportViewer1.LocalReport);
        }
    }

}

5.运行预览
准备工作结束之后
开始运行
点击打印预览
VS2017、WPF使用报表工具RDLC完成报表,打印预览和直接打印_第12张图片
点击直接打印就直接打印了
上图
VS2017、WPF使用报表工具RDLC完成报表,打印预览和直接打印_第13张图片
手机像素比较差
然后是项目下载地址
链接:https://pan.baidu.com/s/15p_qbIlgP5FQslTSYtqoSA
提取码:9xfp
6.注意点
1.打印预览如果正常,但是打印出来多余空白页的话
如下设置
点击到rdlc文件,然后右边的属性,选择报表
然后把下面的ConsumeContainerWhite设置为true

VS2017、WPF使用报表工具RDLC完成报表,打印预览和直接打印_第14张图片
2.这个clsReportPrint类是多余的,下载下来可以不用管
VS2017、WPF使用报表工具RDLC完成报表,打印预览和直接打印_第15张图片

你可能感兴趣的:(C#与WPF,WPF,VS2017,RDLC,直接打印,不用预览)