【原创,提供下载】winfrom 打印表格,字符串的封装
以前写打印都是根据打印机的型号,找开发类库。然后在此基础上开发。写的多了自然就想到了封装。这是还是想到了微软,微软封装了PrintDocument的打印类。但这只是在低层对串口的封装。
所以对于应用层用着还不是很方便。最近做一个项目顺便就封装了一个调用默认打印机的类。虽说有几个小bug,但对于目前来说,已经满足需求了。以后不够了在来升级吧。
1,关于打印上下左右边距和纸张的高宽。以往都把这些写死到代码里面。既然是调用默认打印机,打印机的型号自然有差异。所以我就把这些配置放到app.config里面。但又怕每次打印都加载config影响效率。故此设计了个PrintPaper类。里面所有属性都是静态的。还有一个静态的构造方法。这样只有在程序开始运行加载一次config。之后就直接从内存读取了。
PrintPaper类
1 /*CreateBy:Bonker,Date:20121115*/ 2 /// <summary> 3 /// 从配置文件读取纸张的大小,与边框的距离 4 /// </summary> 5 public class PrintPaper 6 { 7 /// <summary> 8 /// 距离上边界的距离 9 /// </summary> 10 public static int MarginTop { set; get; } 11 /// <summary> 12 /// 距离左边界的距离 13 /// </summary> 14 public static int MarginLeft { set; get; } 15 /// <summary> 16 /// 距离右边界的距离 17 /// </summary> 18 public static int MarginRight { set; get; } 19 /// <summary> 20 /// 距离下边界的距离 21 /// </summary> 22 public static int MarginBottom { set; get; } 23 /// <summary> 24 /// 纸张的宽度 25 /// </summary> 26 public static int Width { set; get; } 27 /// <summary> 28 /// 纸张的高度 29 /// </summary> 30 public static int Height { set; get; } 31 /// <summary> 32 /// 异常情况 33 /// </summary> 34 public static string Error { set; get; } 35 36 //对于静态属性和构造方法。当第一次使用该类的时候,先初始化静态属性,然后调用静态类。 37 //故此配置文件只加载一次,以后调用都会从内存中读取。 38 //此中写法的好处,一次加载,以后不再加载,速度快。弊端:程序运行过程中,改变了config配置。则需重新运行程序。配置才加载生效。 39 static PrintPaper() 40 { 41 //先给异常赋空值,当异常不为空时。说明配置数据有问题,或者程序有异常 42 Error = null; 43 string marginTop = BonkerConfig.GetConfig("marginTop"); 44 string marginBottom = BonkerConfig.GetConfig("marginBottom"); 45 string marginLeft = BonkerConfig.GetConfig("marginLeft"); 46 string marginRight = BonkerConfig.GetConfig("marginRight"); 47 //margin的值可以为负值,但是width只能为正, 48 //marginTop,等值默认已经为0,如果margin不为空,取值复制给margin 49 try 50 { 51 if (!string.IsNullOrWhiteSpace(marginTop)) 52 { 53 MarginTop = int.Parse(marginTop); 54 } 55 if (!string.IsNullOrWhiteSpace(marginTop)) 56 { 57 MarginBottom = int.Parse(marginBottom); 58 } 59 if (!string.IsNullOrWhiteSpace(marginTop)) 60 { 61 MarginLeft = int.Parse(marginLeft); 62 } 63 if (!string.IsNullOrWhiteSpace(marginTop)) 64 { 65 MarginRight = int.Parse(marginRight); 66 } 67 } 68 catch (Exception ex) 69 { 70 //如果有异常继续 71 Error = ex.Message; 72 return; 73 } 74 //判断纸张宽度 75 try 76 { 77 //如果paperWidth配置不为正,则为PrintCore类打印的时候,则去默认值 78 string width = BonkerConfig.GetConfig("paperWidth"); 79 string height = BonkerConfig.GetConfig("paperWidth"); 80 if (!string.IsNullOrWhiteSpace(width)) 81 { 82 Width = int.Parse(width); 83 } 84 if (!string.IsNullOrWhiteSpace(height)) 85 { 86 Height = int.Parse(width); 87 } 88 } 89 catch (Exception ex) 90 { 91 //如果有异常继续 92 Error = ex.Message; 93 return; 94 } 95 } 96 }
app.config的内容
<?xml version="1.0" encoding="utf-8" ?> <configuration><appSettings><!--******************************连接字符串设置************************************--><add key="DBConnectionStr" value=" "/><!--********************************打印边界设置**********************************--><!--打印纸的距四个边界的距离,为空这表示默认为0,可以为负值--><!--与上边界距离--><add key="marginTop" value=""/><!--与上边界距离--><add key="marginBottom" value=""/><!--与上边界距离--><add key="marginLeft" value=""/><!--与上边界距离--><add key="marginRight" value=""/><!--********************************打印纸大小设置**********************************--><!--打印纸张的大小,为空表示取默认值,不可以为负值 --><!--纸张的宽度--><add key="paperWidth" value=""/><!--纸张的高度--><add key="paperHeight" value=""/><!--*******************************************************************************--></appSettings> </configuration>
2,打印表格,翻阅了很多msdn大神的代码。大致有点眉目。打印表格是在一点打印完字体后,然后不改变X,Y坐标继续打印个矩形。所以就有表格了。这样的表格理论上表格的四个边框有点细。里面的小格子有点粗。但打印出来后基本就没差别了。
打印表格是自适应表格里面的文字最大的宽度。但如果表格里面确实列很少,没列的最大宽度又很小。打印完真整个表格没有页面的纸张宽。那会自动拉宽每一列的宽度。
打印的核心类PrintCore
/*CreateBy:Bonker,Date:20121115*//// <summary>/// 打印类,负责打印表格,普通行等。/// </summary>public class PrintCore{/// <summary>/// 打印基础封装类PrintDocument/// </summary>public PrintDocument printDoc { set; get; }/// <summary>/// 当前打印的x坐标/// </summary>public float currentX { set; get; }/// <summary>/// 当前打印的Y坐标/// </summary>public float currentY { set; get; }/// <summary>/// 默认打印字体/// </summary>public Font defaultFont { set; get; }/// <summary>/// 打印的画刷,默认黑色加粗/// </summary>public Brush defaultBrush { set; get; }/// <summary>/// 是否居中打印,默认为false /// </summary>public bool isCenter { set; get; }/// <summary>/// 异常错误/// </summary>public string Error { set; get; }private Graphics graphic { set; get; }/// 构造函数/// </summary>/// <param name="_printDoc">打印基础类</param>/// <param name="_currentX">打印开始的x坐标,默认为0</param>/// <param name="_currentY">打印开始的y坐标,默认为0</param>public PrintCore(PrintDocument _printDoc, Graphics _graphics, Font _defaultFont, float _currentX = 0, float _currentY = 0){this.printDoc = _printDoc;this.currentX = _currentX;this.currentY = _currentY;this.defaultFont = _defaultFont;this.graphic = _graphics;this.defaultBrush = new SolidBrush(Color.Black); //默认加粗黑色this.isCenter = false;//读取配置文件 printDocConfig(_printDoc);Error = PrintPaper.Error;}private void printDocConfig(PrintDocument _printDoc){_printDoc.DefaultPageSettings.Margins = new Margins(PrintPaper.MarginLeft, PrintPaper.MarginRight, PrintPaper.MarginTop, PrintPaper.MarginBottom);//当paper配置的宽度和高度都大于0时,才配置。否则忽略if (PrintPaper.Width > 0 && PrintPaper.Height > 0){_printDoc.DefaultPageSettings.PaperSize = new PaperSize("", PrintPaper.Width, PrintPaper.Height);}}/// <summary>/// 打印字符串,系统可以总动判断换行打印。/// </summary>/// <param name="prnStr">打印的字符串</param>/// <param name="isPrintLine">打印完成后,是否换行,默认为true</param>public void printString(string prnStr, bool isPrintLine = true){//打印字符串,根据字符串长度,和纸张宽度,高度等自动换行SizeF measure = graphic.MeasureString(prnStr, defaultFont);//如果x坐标不为0,或者打印的一行宽度大于纸张的宽度,则居中打印是没用的。不考虑打印if (!isCenter || currentX != 0 || printDoc.DefaultPageSettings.PaperSize.Width < measure.Width){//计算打印这么多字要多少行int rows = (int)Math.Ceiling(measure.Width / (printDoc.DefaultPageSettings.PaperSize.Width - currentX));//根据行,算出要打印的边界矩形框graphic.DrawString(prnStr, defaultFont, defaultBrush, new Rectangle((int)currentX, (int)currentY, (int)Math.Ceiling((printDoc.DefaultPageSettings.PaperSize.Width - currentX)), (int)Math.Ceiling((measure.Height * rows))));if (isPrintLine)//如果换行 {currentY = currentY + measure.Height * rows;currentX = 0;}else{currentY = currentY + measure.Height * (rows - 1);currentX = (measure.Width % (printDoc.DefaultPageSettings.PaperSize.Width - currentX)) + currentX;}}else{//居中打印一行//计算打印前的留白宽度float blank = (printDoc.DefaultPageSettings.PaperSize.Width - measure.Width) / 2.0f;currentX = currentX + blank;graphic.DrawString(prnStr, defaultFont, defaultBrush, currentX, currentY);if (isPrintLine)//如果换行 {currentX = 0;currentY = currentY + measure.Height;}else{currentX = currentX + measure.Width;}}}/// <summary>/// 打印表格,自适应没列的宽度/// </summary>/// <param name="prnDgv"></param>/// <param name="isPrintLine"></param>public void printDataGridView(DataGridView prnDgv, Font titleFont, Brush titleBrush, Color titleBackGroup, bool isPrintLine = true){if (prnDgv == null){return;}prnDgv.AllowUserToAddRows = false;//记录每一列的宽度int[] columnWidths = new int[prnDgv.ColumnCount];//******************取每列的最大宽度***********************//先计算表头的宽度for (int i = 0; i < prnDgv.ColumnCount; i++){string celValue = prnDgv.Columns[i].HeaderText;SizeF measure = graphic.MeasureString(celValue, titleFont);columnWidths[i] = (int)Math.Ceiling(measure.Width);//把打印表头所占的宽度 先放到columnWidths里面 }//计算表中数据打印的最大宽度for (int i = 0; i < prnDgv.Rows.Count; i++){for (int j = 0; j < prnDgv.ColumnCount; j++){string celValue = prnDgv[j, i].Value.ToString();SizeF measure = graphic.MeasureString(celValue, defaultFont);if (columnWidths[j] < measure.Width)//如果宽度小于打印宽度,则把长的打印宽度赋值给列宽 {columnWidths[j] = (int)Math.Ceiling(measure.Width);}}}//如果表格的宽度小于纸张的宽度,表格没列的宽度加大int allColumsWidth = 0;for (int i = 0; i < prnDgv.ColumnCount; i++){allColumsWidth += columnWidths[i];//把打印表头所占的宽度 先放到columnWidths里面 }if (allColumsWidth + prnDgv.ColumnCount < PrintPaper.Width){int columnAddWidth = (PrintPaper.Width - allColumsWidth - prnDgv.ColumnCount) / prnDgv.ColumnCount;for (int i = 0; i < prnDgv.ColumnCount; i++){columnWidths[i] += columnAddWidth;}}//************************************************************* currentX = 0;int titleHeight = (int)Math.Ceiling(graphic.MeasureString("1e{(汗", titleFont).Height);//打印表头for (int i = 0; i < prnDgv.ColumnCount; i++){string celValue = prnDgv.Columns[i].HeaderText;//打印背景graphic.FillRectangle(new SolidBrush(titleBackGroup), new Rectangle((int)currentX, (int)currentY, columnWidths[i], titleHeight));//打印内容 graphic.DrawString(celValue, titleFont, titleBrush, currentX, currentY);//打印表格边框graphic.DrawRectangle(new Pen(titleBrush), new Rectangle((int)currentX, (int)currentY, columnWidths[i], titleHeight));currentX = currentX + columnWidths[i];}currentX = 0;currentY = currentY + titleHeight;int contentHeight = (int)Math.Ceiling(graphic.MeasureString("1e{(汗", defaultFont).Height);//打印内容for (int i = 0; i < prnDgv.Rows.Count; i++){for (int j = 0; j < prnDgv.ColumnCount; j++){string celValue = prnDgv[j, i].Value.ToString();//打印内容graphic.DrawString(celValue, defaultFont, defaultBrush, currentX, currentY);//打印表格边框graphic.DrawRectangle(new Pen(defaultBrush), new Rectangle((int)currentX, (int)currentY, columnWidths[j], contentHeight));currentX = currentX + columnWidths[j];}currentX = 0;currentY = currentY + contentHeight;}}}
调用示例代码
private void printDocument1_PrintPage(object sender, PrintPageEventArgs e){PrintCore print = new PrintCore(printDocument1, e.Graphics, new Font("宋体", 14));if (print.Error != null){e.Cancel = true;MessageBox.Show(print.Error);return;}print.isCenter = true;print.defaultFont = new Font("宋体", 16);print.printString("定积分落实到减肥了减肥了圣诞节死减", true);print.isCenter = false;print.defaultFont = new Font("宋体", 14);print.printString("111定积分落实到减定积分落实到减肥了圣诞节死定了减肥了束带结发连锁店减肥了哦定积分落实到减肥了圣诞节死定了减肥了束带结发连锁店减肥了哦肥了圣诞节死定了减肥了束带结发连锁店减肥了哦");print.printDataGridView(dataGridView1,new Font("宋体", 18),Brushes.Black,DefaultBackColor); }
总结:以上打印有两个小问题没有处理。一个是关于分页,一个是当表格的宽度过长,超过了页面的宽度,没有进行换行处理。
另附上源码
转载于:https://www.cnblogs.com/Bonker/archive/2012/11/21/2780411.html
【原创,提供下载】winfrom 打印表格,字符串的封装相关推荐
- php中文网11期录播资源下载,PHP中文网原创视频提供下载啦!
感谢广大的学员对PHP中文网的长期支持,为方便广大同学们的学习,网站现将会在晚些时刻提供原创视频的下载,大家后期可以登录PHP中文网下载站查看原创视频栏目进行下载,也可以从下方由小编对本站优秀原创视频 ...
- Java打印表格 Console/控制台
功能: 控制台打印表格,支持字段动态长度,左对齐,设置最多打印多少行. 类下载地址:https://download.csdn.net/download/qq_26599807/12840079 简单 ...
- 【java实现控制台打印表格】
背景 判断给定数据库是否可以连接,习惯做法是安装一个客户端,输入连接信息后连接测试.但是客户现场通常只提供一个linux系统,没有相关客户端.因此,需要一个能在linux上运行的数据库连接测试工具.我 ...
- Word文档下载(图片,数据表格)
Java 下载Word文档xwpfTemplate Java 下载Word文档xwpfTemplate 文档下载(图片,数据表格),pom依赖 <dependency><groupI ...
- Jeecg Boot 2.3 里程碑版本发布,支持微服务和单体自由切换、提供新行编辑表格JVXETable
项目介绍 JeecgBoot是一款基于代码生成器的低代码平台,开源界"小普元"超越传统商业级平台!采用前后端分离架构:SpringBoot 2.x,Ant Design&V ...
- 在CLI中打印表格----gotable使用介绍
目录 介绍 获取gotable 在github中获取 下载源码 git clone go mod API 创建table 从结构体中创建空table 获取版本信息 获取版本列表 打印表格 给表格添加行 ...
- [推荐推荐][提供下载]ORACLE SQL:经典查询练手系列文章收尾(目录篇)
[推荐推荐][提供下载]ORACLE SQL: 经典查询练手系列文章收尾(目录篇) --通过知识共享树立个人品牌. 通过近一个月的努力,<经典查询练手系列>也快告一段落,但并不代表结束,以 ...
- ruby 将字符串转为数组_Ruby程序将数组打印为字符串
ruby 将字符串转为数组 将数组打印为字符串 (Printing an array as string) Given an array and we have to print it as a st ...
- html表格分页打印样式,vue部分打印(多页自动分页、打印样式自定义、多页打印表格页面顶部带表头)...
写在前面:注意打印表格时,若需要多页打印,则尽量使用原生table元素实现,这样在分页时每页顶部会带有表头,用户体验比较好 一.引用插件(在 main.js 中全局引入!!注意,需要修改源码,所以尽量 ...
最新文章
- Python内部机制。
- 高通首次推出AI引擎 打包所有软硬件算力
- Storm之Bolt-接口
- rtmp 推送h264 + aac 的数据
- 【专场】揭秘端到端视频技术
- java清屏_【图片】请问java编写中如何做到清屏啊。。。_java吧_百度贴吧
- java 内置函数_java8 四大内置核心函数式接口
- 论文浅尝 |「知识表示学习」专题论文推荐
- vba 指定列后插入列_Excle中的VBA介绍分享
- Spring Boot 热启动
- 2017.4.20 火星人 思考记录
- linux_从windows到ubuntu再到manjaro
- 寄存器间接寻址缺点_详解西门子间接寻址之地址寄存器间接寻址
- windows 常用快捷键与重要文件的路径
- 为什么这么多人会选择单页设计?
- HIT-ICS大作业-程序人生Hello‘s P2P
- 对“佩戴低度数近视镜可延缓近视发展?”的一些疑问
- 用java实现判断回文
- 【办公类-22-02】周计划系列(2)-生成“主题知识”(提取旧docx指定段落的内容,写入EXCLE模板,再次生成新docx)
- 分贝表示的放大倍数--增益