最近需要用到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; } //司机idpublic 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类是多余的,下载下来可以不用管

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

  1. C#和WPF自适应横板打印A5,打印预览和直接打印.

    看本文之前,可以先看我之前写的详细版 VS2017.WPF使用报表工具RDLC完成报表,打印预览和直接打印 1.首先调整rdlc文件的样式 A5横板打印的话,横是21cm,竖是14.8cm 然后再减去 ...

  2. 关闭rdlc报表打印预览后,关闭客户端,抛出异常“发生了应用程序级的异常 将退出”...

    问题:关闭rdlc报表打印预览后,关闭客户端,抛出异常"发生了应用程序级的异常 将退出" 办法:在容纳ReportViewer的窗体后台代码中,添加如下代码即可 protected ...

  3. 靠着零代码报表工具,转行报表开发后月薪超过3万

    作为一个在IT行业摸爬滚打多年的老油条,我刚进某东公司做程序开发时工资只有不到一万,当时公司的数据仓库非常原始,基本上都靠我一个人写SQL花了三年才完成. 虽然不同于其他程序员拧螺丝的工作,但我们部门 ...

  4. WEB 报表如何做到不需要预览就直接打印

    在浏览器中打印一般总要弹出个对话框预览再确认,但有时我们希望静默打印(点击打印后不再预览,直接打印),或者点击打印时能够连续打印多张表格. 这需要要写些 JS 或者页面代码来实现,比如要通过代码画表格 ...

  5. WPF的打印原理 实现打印页眉页脚和打印预览

    做应用特别是企业应用和网站一般都少不了打印功能,打印也是项特别麻烦的事情,要实现打印功能根据不能的技术也有不同的实现方案. 在MFC中手动实现打印功能很麻烦,如果不需要打印预览功能,可以直接用offi ...

  6. VS2017 MFC对话框程序打印及打印预览的实现

    VS2017 MFC对话框程序打印及打印预览的实现 花了一个星期,研究了网上大量的MFC对话框打印及打印预览功能的demo之后,网上现有的版本都比较旧,所以选中了几个版本,合并修改,得到这个比较完美的 ...

  7. java 视频转码工具类_JavaCV入门指南:FrameConverter转换工具类及CanvasFrame图像预览工具类(javaCV教程完结篇)...

    JavaCV入门指南:FrameConverter转换工具类及CanvasFrame图像预览工具类(javaCV教程完结篇) 前言 再此章之前,我们已经详细介绍和剖析了javacv的结构和ffmpeg ...

  8. hua图软件 mac_mac系统有画图工具吗|mac电脑把预览变成画图工具方法

    苹果电脑有画图工具吗?windows系统下会自带一些实用的工具,比如画图,从windows转战到苹果系统之后,这些用户也想要使用画图工具,但是在mac系统中找不到画图工具.苹果系统没有画图工具,但是我 ...

  9. C#实时打印预览工具

    C#实时打印预览工具 本人是C#业余爱好者,非专业在职编程攻城狮,只是工作时用C#做一些工具,提高工作效率. 首先,C#真的好用,现代化的语言特性. 平时会用C#做资料打印,划表格和打印字符串对坐标是 ...

最新文章

  1. Python selenium根据class定位页面元素,xpath定位
  2. Vue监听器与监听滥用
  3. Java中MessageFormat的使用
  4. getDimension等区别
  5. 数据湖,大数据的下一个变革!
  6. 记一次面试腾讯的奇葩经历
  7. html把多个div做成块,HTML块
  8. Chromium Embedded Framework中文文档 (SVN属性)
  9. TCP和UDP的区别与联系
  10. 在计算机里面建一个新的文档,电脑上的word怎么新建文档
  11. 演讲者模式投影到幕布也看到备注_PPT的备注功能怎么使用?如何让备注仅被演示者看到?...
  12. 2020COSMO时尚盛典即将闪耀启幕
  13. 哈希表、哈希桶的实现
  14. arcgis直方图工具在哪_这些分析工具都分不清?别说你懂数据分析!
  15. 卷入亿万骗局,他遭遇“死亡威胁”:如果没有光明,我愿成为火炬
  16. 在vue中禁止input框和textarea编辑的操作
  17. 项目代码中魔法值的优雅处理
  18. linux网卡是百兆还千兆,查看网卡是百兆还是千兆
  19. 书单标签:IT技术 - 酷瓜书单
  20. 你不知道的CS模式的进程管理工具,状态监测、项目启停一目了然!

热门文章

  1. 【工具使用】Word 排版
  2. 到底什么是5G LAN?
  3. 2018年自学编程的学习计划表
  4. 这些年,亲眼所见的软件公司中混迹的老油条汇总
  5. HTML5期末大作业:漫画网站设计——布卡漫画官网(4页) HTML+CSS+JavaScript 学生DW网页设计作业成品 w学生原创课程设计漫画设计制作大作业成品免费下载
  6. matlab基本操作与矩阵输入简单表示
  7. 雷锋工厂模式(笔记)
  8. 学雷锋是不需要动员的
  9. 博物馆3d数字化全景展示设计方案
  10. 【清北学堂济南刷题班】集合