前言

c#做winform程序要求生成并打印Excel报告,为了不安装Office相应组件,我选择了NPOI来生成Excel报告,用winform的PrintDocument控件来触发打印操作,而难点在于如何将excel转换成Graphics对象,在NPOI中我只找到了excel打印的设置(如横向/纵向),还需要打开excel去触发打印操作,但项目要求是一次性直接实现打印,要用PrintDocument控件而不是再去操作excel。不得已重新搜索,发现了类库Spire.xls,最终实现了要求。有什么错误或更简洁的方法还请广大博友不吝赐教。

思路

       用npoi生成Excel  =》 用spire.xls转换成图片.png =》 获取生成的图片,利用Graphic的drawimage方法对图片进行操作,当然了,如果不介意的话,可以不对图片进行操作:) =》使用printDocument控件的print方法实现打印( 当然这里可以直接用spire.xls直接生成Excel,但是Spire.xls的免费版本有每个sheet最多有150行的限制 )

知识点

【0】NPOI使用方法

下载:http://npoi.codeplex.com/releases/

【1】winform的printDocument控件

参考:https://docs.microsoft.com/en-us/dotnet/framework/winforms/advanced/how-to-print-a-multi-page-text-file-in-windows-forms

理解:

PrintDocument控件的作用是定义一个向打印机发送输出的对象,有BeginPrint,PrintPage,EndPrint方法,当执行printdocument.Print()语句时,会检查是否存在BeginPrint方法,存在则先调用。然后调用PrintPage方法,该方法会向PrintPageEcentArgs类中获得一个空白的Graphics对象,我们可以对Graphics对象进行操作(可以理解对画布进行绘制,Graphics对象有内置的类似DrawString,DrawPie的方法),在PrintPage方法的最后,会向打印设备发送这个Graphics对象。打印设备完成打印后,会检查是否存在EndPrint方法,存在则调用。

【2】spire.xls使用方法

参考:http://www.cnblogs.com/asxinyu/p/4346907.html

具体代码  

  【1】winform使用的打印控件介绍

       printDocument1作用:定义一个向打印机发送输出的对象

printPreviewDialog1作用:显示一个对话框,向用户显示关联文档打印的样子

printDialog1作用:显示一个对话框,允许用户选择打印机并选择其他打印选项(如分数,纸张方向)

【2】代码展示

“直接打印” 按钮的后台设置

        private void DirectPrint_Click(object sender, EventArgs e)
{
isprint = false;
GenerateExcel_Click(sender, e); //使用NPOI生成excel
if (newsavefilepath != "" && isprint==true)
{
isprint = false;
ChangeExcel2Image(newsavefilepath); //利用Spire将excel转换成图片
if (printDialog1.ShowDialog() == DialogResult.OK)
{
printDocument1.Print(); //打印
}
} }

"生成excel" 按钮后台设置

       private void Generate_Click(object sender, EventArgs e)
{
CreateExcel(); //使用NPOI生成excel内容
SaveFileDialog savedialog = new SaveFileDialog(); //弹出让用户选择excel保存路径的窗口
savedialog.Filter = " excel files(*.xlsx)|*.xlsx|All files(*.*)|*.*";
savedialog.RestoreDirectory = true;
savedialog.FileName = string.Format("销售订单审批单{0}", DateTime.Now.ToString("yyyyMMddHHmm"));
if (savedialog.ShowDialog() == DialogResult.OK)
{
//newsavefilepath是excel的保存路径
newsavefilepath = savedialog.FileName.ToString().Trim();
using (FileStream newfs = new FileStream(newsavefilepath, FileMode.Create, FileAccess.ReadWrite))
{
singlexssfwk.Write(newfs); //将生成的excel写入用户选择保存的文件路径中
newfs.Close();
}
}
}

CreateExcel()方法举例

using NPOI.XSSF.UserModel;  

XSSFWorkbook singlexssfwk;  

//注意,不同的NPOI版本调用的方法不一致,这里使用的版本是2.1.3.1
private void CreatExcel()
{
//获取模板excel的路径
string str = System.Environment.CurrentDirectory + "\\XXXX.xlsx";
if (File.Exists(str))
{
using (FileStream fs = new FileStream(str, FileMode.Open, FileAccess.Read))
{
singlexssfwk = new XSSFWorkbook(fs);
fs.Close();
}
//获取表
XSSFSheet xssfsheet = (XSSFSheet)singlexssfwk.GetSheetAt();
//创建行
XSSFRow xssfrow1 = (XSSFRow)xssfsheet.GetRow();
//设置单元格内容
xssfrow1.GetCell().SetCellValue("...");
... ...
    }
else{
... ...
}
}

ChangeExcel2Image()方法举例

using Spire.Xls;
public void ChangeExcel2Image(string filename)
{
Workbook workbook = new Workbook();
workbook.LoadFromFile(filename);
Worksheet sheet = workbook.Worksheets[];
sheet.SaveToImage(imagepath); //图片后缀.bmp ,imagepath自己设置
}

执行printDocument1.Print()的方法会调用printDocument1_PrintPage方法

//在PrintPage方法中写截取图片 的代码
private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
#region 如果不需要截取图片,可以不用写以下代码
GC.Collect();
Graphics g = e.Graphics;
//imagepath是指 excel转成的图片的路径
using (Bitmap bitmap = new dBitmap(imagepath))
{
//如何截取自己摸索
Rectangle newarea = new Rectangle();
newarea.X = ;
newarea.Y = ;
newarea.Width = bitmap.Width;
newarea.Height = bitmap.Height - ;
using (Bitmap newbitmap = bitmap.Clone(newarea, bitmap.PixelFormat))
{
g.DrawImage(newbitmap, , , newbitmap.Width - , newbitmap.Height - );
}
}
#endregion
}

备注:关于预览的设置,关键在于printDocument1是个全局对象,直接设置printPreviewDialog1.Document = printDocument1; printPreviewDialog1.ShowDialog();即可,这个的原理没有研究,反正这样设置后,只要你处理好内容,就能在预览中看到。

 总结

以上就是我实现c# winform打印excel的经过,或许这只是一种比较冗杂的方法,如果有大佬有更精简的方法,请不吝赐教。如有错误,也请不吝赐教。

c# winform打印excel(使用NPOI+Spire.xls+PrintDocument直接打印excel)的更多相关文章

  1. C#组件系列——又一款Excel处理神器Spire.XLS,你值得拥有

    前言:最近项目里面有一些对Excel操作的需求,博主想都没想,NPOI呗,简单.开源.免费,大家都喜欢!确实,对于一些简单的Excel导入.导出.合并单元格等,它都没啥太大的问题,但是这次的需求有两点 ...

  2. Spire.XLS,生成Excel文件、加载Excel文件

    一.组件介绍 Spire.XLS是E-iceblue开发的一套基于企业级的专业Office文档处理的组件之一,全称Spire.Office for .NET.旗下有Spire.Doc,Spire XL ...

  3. C#组件系列——又一款Excel处理神器Spire.XLS,你值得拥有(二)

    前言:上篇 C#组件系列——又一款Excel处理神器Spire.XLS,你值得拥有 介绍了下组件的两个功能,说不上特色,但确实能解决我们项目中的一些实际问题,这两天继续研究了下这个组件,觉得有些功能用 ...

  4. 使用SPIRE.XLS来创建Excel 工作簿

               使用SPIRE.XLS来创建Excel 工作簿     概要 最近在研究 .NET 控件,使用这些控件在程序中可以快速低成本实现功能. 在这一篇中我们使用的控件是Spire.XL ...

  5. 【原创】.NET读写Excel工具Spire.Xls使用(2)Excel文件的控制

                  本博客所有文章分类的总目录:http://www.cnblogs.com/asxinyu/p/4288836.html .NET读写Excel工具Spire.Xls使用文章 ...

  6. csharp: Export or Import excel using MyXls,Spire.Xls

    excel 2003 (效果不太理想) using System; using System.Collections.Generic; using System.ComponentModel; usi ...

  7. c#(winform,webform通用)利用npoi将xls文件复制为xlsx文件(excel的修改,保存,包括excel2003-office2007+的处理)

    1.程序界面 每次需要处理excel文件的时候,都是去百度找方案,真是气一头火,今天好好总结一下,下次就不用度娘了. 我是用winform来试验的,因为winform比较方便测试,实际上只要是在.ne ...

  8. 【原创】.NET读写Excel工具Spire.Xls使用(1)入门介绍

    在.NET平台,操作Excel文件是一个非常常用的需求,目前比较常规的方法有以下几种: 1.Office Com组件的方式:这个方式非常累人,微软的东西总是这么的复杂,使用起来可能非常不便,需要安装E ...

  9. 【原创】.NET读写Excel工具Spire.Xls使用(3)单元格控制

                  本博客所有文章分类的总目录:http://www.cnblogs.com/asxinyu/p/4288836.html .NET读写Excel工具Spire.Xls使用文章 ...

随机推荐

  1. shell 批量修改较长字符串 字符串内容之间更换位置

    cat 1.txt src='http://img2.tgbusdata.cn/v2/thumb/jpg/MkY5Myw2NTUsMzAzLDksMywxLC0xLDAscms1MCwxOTIuMTY ...

  2. [经验交流] kubeadm 安装 kubernetes 一年过期的解决办法

    kubeadm 是 kubernetes 提供的一个初始化集群的工具,使用起来非常方便.但是它创建的apiserver.controller-manager等证书默认只有一年的有效期,同时kubele ...

  3. VS Code保存使用项目Eslint规则格式化代码

    One.文件-首选项-设置-选择项目                  Two.打开右上角JSON设置            Three. 插入以下代码 { "eslint.options& ...

  4. Mathematica/偏导数/最小二乘法(线性回归)

    a = / a //输出的还是2/123 N[a] //输出的就是小数点 N[a,] //保留三位小数点 Clear[a] Solve[== x^- , x] //结果-3 和 3 Plot[Sin[ ...

  5. 什么时候Python的List,Tuple最后一个Item后面要加上一个逗号

    为什么看Python的代码,有时候会在数据结构的最后一项末尾加上逗号.直接来看,这个逗号很多余. 根据PEP81的解释: Trailing commas are usually optional, e ...

  6. 题解-Codeforces671D Roads in Yusland

    Problem Codeforces-671D 题意概要:给定一棵 \(n\) 点有根树与 \(m\) 条链,链有费用,保证链端点之间为祖先关系,问至少花费多少费用才能覆盖整棵树(\(n-1\) 条边 ...

  7. mingw-gcc-9.0.1-i686-posix-sjlj-201903

    -------------------------------------------------------------------------------gcc version 9.0.1 201 ...

  8. form 组件

    https://www.cnblogs.com/wupeiqi/articles/6144178.html class F2Form(forms.Form): title1=fields.CharFi ...

  9. JAVA 类的定义(定义一个类,来模拟“学生”)

    package Code413;/*定义一个类,来模拟“学生”属性 (是什么) 姓名 年龄行为(能做什么) 吃饭 睡觉 学习对应到Java的类当中 成员变量(属性) String nanme; //姓 ...

  10. 04-HTTP协议和静态Web服务器

    一.HTTP协议(HyperText Transfer Protocol)     超文本传输协议,超文本是超级文本的缩写,是指超越文本限制或者超链接,比如:图片.音乐.视频.超链接等等都属于超文本. ...