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

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

软件是VS2017 .netframework是4.5
1.配置环境
工具,获取扩展和更新
然后安装RDLC,然后重启
在这里插入图片描述
新建项目
项目的引用里面添加
System.Printing
System.Management
System.Drawing

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

在这里插入图片描述

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; }//仓库
    }
}

然后创建两个数据集
在这里插入图片描述
数据集里 右键 添加 DataTable把实体类的属性都加进去
或者
工具箱 双击DataTable
加完之后是这样的
在这里插入图片描述

在这里插入图片描述

然后创建一个rdlc
在这里插入图片描述
左边 新建 数据集 在这里插入图片描述
自己找到实体类,或者直接选择刚才创建好的DataSet.xsd

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

然后在rdlc文件 右键 插入 表
在这里插入图片描述
表里绑定一下属性
在这里插入图片描述
表头的汉字是自己加的

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

<Window x:Class="RDLCPrinter.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:rv="clr-namespace:Microsoft.Reporting.WinForms;assembly=Microsoft.ReportViewer.WinForms" 
        xmlns:local="clr-namespace:RDLCPrinter"
        mc:Ignorable="d"
        Title="MainWindow" Height="324" Width="576">
    <Grid>
        <DockPanel>
            <Button Width="100" Height="30" Content="打印预览" Click="btnClickMe_Click" Margin="90,0,0,0"/>
            <Button x:Name="Button_Printer"  Width="100" Height="30"  Content="直接打印"  Click="Button_Print_Click"/>
        </DockPanel>
    </Grid>
</Window>

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

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

然后是整体的代码

<UserControl x:Class="RDLCPrinter.ReportViewer"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:rv="clr-namespace:Microsoft.Reporting.WinForms;assembly=Microsoft.ReportViewer.WinForms"
        xmlns:local="clr-namespace:RDLCPrinter"
        mc:Ignorable="d"
          d:DesignHeight="600" d:DesignWidth="800" Loaded="UserControl_Loaded">
    <Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
        <WindowsFormsHost Name="printArea">
            <rv:ReportViewer x:Name="reportViewer1" RenderingComplete="reportViewer_RenderingComplete" />
        </WindowsFormsHost>
    </Grid>
</UserControl>

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

<Window x:Class="RDLCPrinter.CustomerReport"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:RDLCPrinter"
        
        mc:Ignorable="d"
        Title="CustomerReport" Height="600" Width="800">

    <Grid>
        <local:ReportViewer ></local:ReportViewer>
    </Grid>
</Window>

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

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

namespace RDLCPrinter

{

    /// <summary>

    /// Interaction logic for ReportViewer.xaml

    /// </summary>

    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
{
    /// <summary>
    /// 通过RDLC向默认打印机输出打印报表
    /// </summary>
    public class BillPrint : IDisposable
    {
        /// <summary>
        /// 当前打印页号
        /// </summary>
        static int m_currentPageIndex;

        /// <summary>
        /// RDCL转换stream一页对应一个stream
        /// </summary>
        static List<Stream> m_streams;

        /// <summary>
        /// 把report输出成stream
        /// </summary>
        /// <param name="report">传入需要Export的report</param>
        private void Export(LocalReport report)
        {
            string deviceInfo =
              "<DeviceInfo>" +
              "  <OutputFormat>EMF</OutputFormat>" +
                //"  <PageWidth>2in</PageWidth>" +
                //"  <PageHeight>20in</PageHeight>" +
                "  <MarginTop>1in</MarginTop>" +
                "  <MarginLeft>0in</MarginLeft>" +
                "  <MarginRight>0in</MarginRight>" +
                "  <MarginBottom>1in</MarginBottom>" +
              "</DeviceInfo>";
            Warning[] warnings;
            m_streams = new List<Stream>();
            report.Render("Image", deviceInfo, CreateStream, out warnings);
            foreach (Stream stream in m_streams)
                stream.Position = 0;
        }

        /// <summary>
        /// 创建具有指定的名称和格式的流。
        /// </summary>
        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;
        }

        /// <summary>
        /// 打印输出
        /// </summary>
        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);
        }

        /// <summary>
        /// 打印预处理
        /// </summary>
        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;
            }
        }

        /// <summary>
        /// 对外接口,启动打印
        /// </summary>
        /// <param name="dtSource">打印报表对应的数据源</param>
        /// <param name="sReport">打印报表名称</param>
        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();
        }

        /// <summary>
        /// 获取打印机状态
        /// </summary>
        /// <param name="printerName">打印机名称</param>
        /// <param name="status">输出打印机状态</param>
        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;
            }
        }

        /// <summary>
        /// 对外接口,调去打印机信息
        /// </summary>
        /// <param name="printerName">打印机名称</param>
        /// <returns>返回打印机当前状态</returns>
        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.运行预览
准备工作结束之后
开始运行
点击打印预览
在这里插入图片描述
点击直接打印就直接打印了
上图
在这里插入图片描述
手机像素比较差
然后是项目下载地址
链接:https://pan.baidu.com/s/15p_qbIlgP5FQslTSYtqoSA
提取码:9xfp
6.注意点
1.打印预览如果正常,但是打印出来多余空白页的话
如下设置
点击到rdlc文件,然后右边的属性,选择报表
然后把下面的ConsumeContainerWhite设置为true

在这里插入图片描述
2.这个clsReportPrint类是多余的,下载下来可以不用管
在这里插入图片描述

  • 3
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
VS2017中的WPF报表是一种数据可视化工具,可以帮助开发人员在WPF应用程序中创建丰富的报表WPF报表具有许多强大功能,可用于展示和分析数据。 首先,WPF报表提供了丰富的图表和图形选项,开发人员可以根据需要选择合适的图表类型,如柱状图、折线图、饼图等。这些图表可以直观地展示数据的趋势和关系,帮助用户更好地理解数据。 其次,WPF报表支持数据绑定,可以从各种数据源中获取数据并将其展示在报表中。开发人员可以使用LINQ查询语言或直接连接数据库等方式获取数据,然后将其绑定到报表控件上,轻松实现数据的展示和分析。 此外,WPF报表还提供了一系列强大的计算和筛选功能。开发人员可以对数据进行各种计算,例如求和、平均值等,以及对数据进行筛选、排序等操作。这些功能使得数据的分析更加灵活和高效。 最后,WPF报表还支持自定义样式和模板,开发人员可以根据自己的需求进行报表的定制。可以通过改变报表的外观、颜色、字体等来实现自定义样式,并且可以根据具体需要定制数据的呈现方式。 总而言之,VS2017中的WPF报表是一个功能强大且易于使用工具,可以帮助开发人员在WPF应用程序中创建高度可视化的报表。它提供了丰富的图表和图形选项、数据绑定、计算和筛选功能,以及自定义样式和模板等特性,使得数据的展示和分析更加直观和灵活。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值