C#报表打印时,有多页内容,怎样去转到下一页断续显示打印呢?这个问题困扰了我很长时间,HasMorePages这个属性的用法刚开始也不知道怎么用,后才想明白,要先加一个 if 判断,然后再用HasMorePages = true ,else HasMorePages = false ,这样才能正常显示转到下一页。详细如下:
这是一个汽车零件仓库的货架标签打印软件,从EXCEL文件导入表格,再生成一格一格的标签,打印在A4纸上,剪出来,贴在货架上。先来个界面截图:
直接来导入数据后的界面,导入前就不截图了,
EXCEL文件格式
预览第一页
预览第二页
项目文件结构图
Form1.cs
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Data.OleDb; using System.Data.SqlClient; using System.Drawing; using System.Text; using System.Windows.Forms; namespace PrintLabel { public partial class Form1 : Form { public Form1() { InitializeComponent(); } DataTable dt = new DataTable(); //新建DataTable对象,用于接收表数据 private void button1_Click(object sender, EventArgs e) { string path = ""; //定义路径字符串变量 string fileType = ""; //定义文件类型字符串变量 if (openFileDialog1.ShowDialog()==DialogResult.OK) { path = openFileDialog1.FileName; //路径变量取值 string[] f = openFileDialog1.SafeFileName.Split('.'); //截取文件名后缀 fileType = '.'+f[1]; //文件类型变量取值 dt = new ImportExcel().importExcel(path, fileType).Tables[0]; //用匿名对象方法,新建ImportExcel的importExcel方法,取得数据集DataSet,再取第一个表Table[0],赋值入数据表dt dataGridView1.DataSource = dt; //把表中数据显示在数据表格上 label1.Text = "共" + (dataGridView1.RowCount-1) + "条记录"; } } string[] partParameters=new string[4]; //定义零件数据数组( 1 零件编码,2 零件名 3 车型 4 仓位) private string[] getPartParmeters(int r ) { for (int i = 0; i < 4; i++) //零件数据有4个,循环4次 { try { partParameters[i] = (dataGridView1.Rows[r].Cells[i].Value + ""); //先连接一个空字符串,把取出来的数据Object类型隐式转换为字符串类型 }catch(Exception ) { } } return partParameters; } private void btnSmallLabel_Click(object sender, EventArgs e) { recordRows = 0; //初始化记录条数 label = new SmallLabel(); //多态建立SmallLabel对象 rows = 7; //每页打印7行 printPreviewDlg.ShowDialog(); //显示打印预览对话框 } int recordRows; //声明记录条数变量 int[] rectPosition= new int[2]; //创建方框位置数据数组 Label label; //声明Label对象,以备多态调用 int rows; //声明变量,每页打印的行数 private void printDocSmall_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e) { for (int i = 0; i < rows; i++) //设置每页打印出的行数 { for (int j = 0; j < 2; j++) //设置每行打印的列数 { rectPosition[0] = label.rectPosition[0] + (label.rectWH[0] + label.rectWHSpace) * j ; //设置方框的左坐标 rectPosition[1] = label.rectPosition[1] + (label.rectWH[1] + label.rectWHSpace) * i ; //设置方框的上坐标 label.draw(getPartParmeters(recordRows), rectPosition, e) ; //调用对象的draw方法,画方框里面的数据 recordRows++; } } if (recordRows < dataGridView1.RowCount-1) //如果行数小于等于记录数-1 { e.HasMorePages = true; //则有下一页 } else { e.HasMorePages = false; //否则是最后一页 recordRows = 0; //把记录条数的变量重置为0,否则预览时为有数据,打印纸出来时数据为空。 } } private void btnLargeLabel_Click(object sender, EventArgs e) { recordRows = 0; //初始化记录条数 label = new LargeLabel(); //多态建立LargeLabel对象 rows = 5; //每页打印6行 printPreviewDlg.ShowDialog(); //显示打印预览对话框 } private void btnInOutLabel_Click(object sender, EventArgs e) { recordRows = 0; //初始化记录条数 label = new InOutLabel(); //多态建立InOutLabel对象 rows = 7; //每页打印7行 printPreviewDlg.ShowDialog(); //显示打印预览对话框 } /////////////////////////////////////////////////////////////////// } }
ImportExcel.cs
using System; using System.Collections.Generic; using System.Data; using System.Data.OleDb; using System.Text; using System.Windows.Forms; namespace PrintLabel { class ImportExcel { //定义文件类型字符串变量 private string connstr; //定义连接字符串变量 public DataSet importExcel(string path,string fileType) { //if (fileType == ".xls") //如果类型是.xls,excel2003,则用此连接字符串 // connstr = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + path + ";" + ";Extended Properties=\"Excel 8.0;HDR=YES;IMEX=1\""; //else //如果类型是其它的,即excel2007以上,则用此连接字符串 // connstr = "Provider=Microsoft.ACE.OLEDB.12.0;" + "Data Source=" + path + ";" + ";Extended Properties=\"Excel 12.0;HDR=YES;IMEX=1\""; // string connstr = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + path + ";" + "Extended Properties=Excel 8.0;"; connstr = "Provider=Microsoft.ACE.OLEDB.12.0;" + "Data Source=" + path + ";" + ";Extended Properties=\"Excel 12.0;HDR=YES;IMEX=1\""; OleDbConnection conn = new OleDbConnection(connstr); //新建连接 try { conn.Open(); //打开连接 DataTable schemaTable = conn.GetOleDbSchemaTable(System.Data.OleDb.OleDbSchemaGuid.Tables, null); //取出excel文件的表 string tableName = schemaTable.Rows[0][2].ToString().Trim(); //取出表名 string sqlcmd = "select * from [" + tableName + "]"; //定义查询字符串 OleDbDataAdapter da = new OleDbDataAdapter(sqlcmd, connstr); //新建 OleDbDataAdapter对象da DataSet ds = new DataSet(); //新建DateSet对象 ds da.Fill(ds, "table1"); //填充ds对象 return ds; //返回DataSet对象ds } catch (Exception ex) { throw ex; } finally { conn.Close(); //关闭连接 conn.Dispose(); } } } }
Label.cs //标签类的基类
using System; using System.Collections.Generic; using System.Text; using System.Drawing; namespace PrintLabel { public class Label { public Label() //无参的构造方法 { } /// <summary> /// 框的左上角坐标左、上 /// </summary> private int[] s_rectPosition = new int[2]; internal int[] rectPosition { get { return s_rectPosition; } set { s_rectPosition = value; } } /// <summary> /// 字符的位置左、上 /// </summary> private int[] s_stringPosition = new int[2]; internal int[] stringPosition { get { return s_stringPosition; } set { s_stringPosition = value; } } /// <summary> /// 字符的上下、左右的间隔 /// </summary> private int[] s_stringWHSpace = new int[2]; internal int[] stringWHSpace { get { return s_stringWHSpace; } set { s_stringWHSpace = value; } } /// <summary> /// 零件表的字体 /// </summary> private Font s_font; internal Font font { get { return s_font; } set { s_font = value; } } /// <summary> /// 零件属性的字体 /// </summary> private Font s_fontPartParameters; internal Font fontPartParameters { get { return s_fontPartParameters; } set { s_fontPartParameters =value; } } /// <summary> /// 框的长、宽 /// </summary> private int[] s_rectWH; internal int[] rectWH { get { return s_rectWH; } set { s_rectWH =value; } } public void draw() { } public virtual void draw(string[] parameters, int[] rectPosition, System.Drawing.Printing.PrintPageEventArgs e) //定义虚方法,由子类去重写 { } private Pen s_pen; internal Pen pen { get { return s_pen; } set { s_pen = value; } } private Rectangle s_rect; internal Rectangle rect { get { return s_rect; } set { s_rect = value; } } private int s_rectWHSpace; internal int rectWHSpace { get { return s_rectWHSpace; } set { s_rectWHSpace = value; } } private string[] s_names; public string[] names { get { return s_names; } set { s_names = value; } } } }
SmallLabel.cs //继承自Label类
using System; using System.Collections.Generic; using System.Drawing; using System.Text; namespace PrintLabel { internal class SmallLabel : Label { public SmallLabel() //无参构造方法 { this.rectPosition=new int[]{30,30}; //初始化框的左上角坐标 this.rectWH = new int[] { 256, 143 }; //框的长和宽 this.font = new Font("黑体",12,FontStyle.Bold); //前段字体 this.fontPartParameters = new Font("黑体", 15, FontStyle.Bold); //后段字体 this.stringWHSpace = new int[] {80,30 }; //字符串的左右和上下间距 this.pen = new Pen(Brushes.Black, 4); //画笔 this.rectWHSpace = 8; this.names = new string[] { "零件编码:", "零 件 名:", "车 型:", "仓 位:" }; } public override void draw(string[] partParameters, int[] rectPosition, System.Drawing.Printing.PrintPageEventArgs e) //重写基类的draw方法 { this.rect = new Rectangle(rectPosition[0], rectPosition[1], rectWH[0], rectWH[1]); this.stringPosition[0] = rectPosition[0] + 10; //字符串的左坐标 this.stringPosition[1] = rectPosition[1] + 20; //字符串的上从标 e.Graphics.DrawRectangle(pen, rect); e.Graphics.DrawString(names[0], font, Brushes.Black, stringPosition[0], stringPosition[1]); //画字符串 e.Graphics.DrawString(names[1], font, Brushes.Black, stringPosition[0], stringPosition[1] + stringWHSpace[1]); //画字符串 e.Graphics.DrawString(names[2], font, Brushes.Black, stringPosition[0], stringPosition[1] + stringWHSpace[1] * 2); //画字符串 e.Graphics.DrawString(names[3], font, Brushes.Black, stringPosition[0], stringPosition[1] + stringWHSpace[1] * 3); //画字符串 e.Graphics.DrawString(partParameters[0], fontPartParameters, Brushes.Black, stringPosition[0] + stringWHSpace[0], stringPosition[1]); //画零件编码 e.Graphics.DrawString(partParameters[1], fontPartParameters, Brushes.Black, stringPosition[0] + stringWHSpace[0], stringPosition[1] + stringWHSpace[1]); //画零件名 e.Graphics.DrawString(partParameters[2], fontPartParameters, Brushes.Black, stringPosition[0] + stringWHSpace[0], stringPosition[1] + stringWHSpace[1] * 2); //画车型 e.Graphics.DrawString(partParameters[3], fontPartParameters, Brushes.Black, stringPosition[0] + stringWHSpace[0], stringPosition[1] + stringWHSpace[1] * 3); //画仓位 } } }
LargeLabel.cs //继承自SmallLabel类
using System; using System.Collections.Generic; using System.Text; using System.Drawing; namespace PrintLabel { internal class LargeLabel :SmallLabel { public LargeLabel() { //大标签的尺寸跟小标签不一样,重新定义标签的尺寸。 this.rectWH = new int[] { 346, 203 }; //框的长和宽 this.font = new Font("黑体",15,FontStyle.Bold); //前段字体 this.fontPartParameters = new Font("黑体", 18, FontStyle.Bold); //后段字体 this.stringWHSpace = new int[] {100,47 }; //字符串的左右和上下间距 } } }
InOutLabel.cs 继承自SmallLabel
using System; using System.Collections.Generic; using System.Text; namespace PrintLabel { class InOutLabel :SmallLabel { public InOutLabel() { this.names = new string[] { "内侧编码:", "外侧编码:", "零件属性:", "仓 位:" }; } } }
HasMorePages用法的主要代码,在Form1.cs里面。
private void printDocSmall_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e) { for (int i = 0; i < rows; i++) //设置每页打印出的行数 { for (int j = 0; j < 2; j++) //设置每行打印的列数 { rectPosition[0] = label.rectPosition[0] + (label.rectWH[0] + label.rectWHSpace) * j ; //设置方框的左坐标 rectPosition[1] = label.rectPosition[1] + (label.rectWH[1] + label.rectWHSpace) * i ; //设置方框的上坐标 label.draw(getPartParmeters(recordRows), rectPosition, e) ; //调用对象的draw方法,画方框里面的数据 recordRows++; } } if (recordRows < dataGridView1.RowCount-1) //如果行数小于等于记录数-1 { e.HasMorePages = true; //则有下一页 } else { e.HasMorePages = false; //否则是最后一页 recordRows = 0; //把记录条数的变量重置为0,否则预览时为有数据,打印纸出来时数据为空。 } }
最后把完整代码奉上,开发环境vs2013