C# 打印文件

这几天做的功能用到了打印这个功能,直接在网上找了点demo,在这里做个备份。

1、直接打印DataTable

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Printing;
using System.Data;

namespace CheckCargoNumber.Common
{    public class PrintInfo
    {
        public PrintInfo()
        {
            this.dataHead = "打印标题";
            this.headFont = new Font("黑体", 18, FontStyle.Bold);
            this.dataTip = "打印日期:" + DateTime.Now.ToShortDateString();
            this.tipFont = new Font("宋体", 10);
            this.dataFont = new Font("宋体", 10);
            this.landscape = false;
            this.autoWidth = true;
        }
        ///
        /// 获取设置标题头
        ///
        public String dataHead { set; get; }
        ///
        /// 获取或设置标题格式
        ///
        public Font headFont { set; get; }
        ///
        /// 获取或设置附加信息(打印时间等)
        ///
        public String dataTip { set; get; }
        ///
        /// 获取或设置附加信息字体格式(打印时间等)
        ///
        public Font tipFont { set; get; }
        ///
        /// 获取或设置数据字体格式
        ///
        public Font dataFont { set; get; }
        ///
        /// 获取或设置每列的宽度,当无设置或设置列数不正确时,列宽平均分配
        ///
        public int[] widths { set; get; }
        ///
        /// 设定是否是横向打印
        ///
        public Boolean landscape { set; get; }
        ///
        /// 是否根据比例自动调整至可打印宽度。默认自动调整。
        ///
        public Boolean autoWidth { set; get; }
    }

    public class HCPrintcs
    {
        int countNum = 0;//整体打印的条数
        DataTable printDt;
        PrintInfo pInfo;
        public void printDataTable(DataTable dt, PrintInfo p)
        {
            this.printDt = dt;
            this.pInfo = p;
            PrintDocument pd = new System.Drawing.Printing.PrintDocument();
            PrinterSettings pss = new System.Drawing.Printing.PrinterSettings();
            pss.DefaultPageSettings.Landscape = pInfo.landscape;
            pd.PrinterSettings = pss;

            pd.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(pd_PrintPage);

            PrintPreviewDialog ppd = new PrintPreviewDialog();
            ppd.Document = pd;
            if (printDt == null)
            {
                MessageBox.Show("出错", "没有可以打印的数据", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            else if (ppd.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    pd.Print();
                }
                catch (Exception ex)
                {
                    MessageBox.Show("出错", ex.Message, MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }
        private void pd_PrintPage(object sender, PrintPageEventArgs e)
        {
            Graphics graphic = e.Graphics;//获取绘图对象
            int linesPerPage = 0;//页面行号
            int yPosition = 0;//绘制字符串的纵向位置
            int xPosition = 0;//绘制字符串的横向位置
            int leftMargin = e.MarginBounds.Left;//左边距
            int topMargin = e.MarginBounds.Top;//上边距
            string line = string.Empty;//读取的行字符串
            int currentPageLine = 0;//当前页读取的行数
            SolidBrush brush = new SolidBrush(Color.Black);//刷子
            //首先打印标题
            StringFormat sf = new StringFormat();
            sf.Alignment = StringAlignment.Center;
            Rectangle rect = new Rectangle(leftMargin, topMargin, e.MarginBounds.Width, e.MarginBounds.Height);
            graphic.DrawString(pInfo.dataHead, pInfo.headFont, brush, rect, sf);
            topMargin += 35;

            //首先打印说明
            sf = new StringFormat();
            sf.Alignment = StringAlignment.Far;
            Rectangle rect2 = new Rectangle(leftMargin, topMargin, e.MarginBounds.Width, e.MarginBounds.Height);
            graphic.DrawString(pInfo.dataTip, pInfo.tipFont, brush, rect2, sf);
            topMargin += 25;

            linesPerPage = (int)((e.MarginBounds.Height - 60) / (pInfo.dataFont.GetHeight(graphic) + 2));//每页可打印的行数

            //判断宽度是否有效,无效的话,重新平均定义
            if (pInfo.widths == null || pInfo.widths.Length != printDt.Columns.Count)
            {
                int[] newit = new int[printDt.Columns.Count];
                for (int i = 0; i < printDt.Columns.Count; i++)
                {
                    newit[i] = e.MarginBounds.Width / printDt.Columns.Count;
                }
                pInfo.widths = newit;
            }
            //判断是否要自动增加宽度
            if (pInfo.autoWidth)
            {
                int[] newit = new int[printDt.Columns.Count];
                int s = pInfo.widths.Sum();
                for (int i = 0; i < printDt.Columns.Count; i++)
                {
                    newit[i] = pInfo.widths[i] * e.MarginBounds.Width / s;
                }
                pInfo.widths = newit;
            }
            //下面开始画表格
            Point ptS;
            Point ptE;
            int ti = leftMargin;//先画竖道
            //先判断要打印的数据(包括字段名称)是否多于每页可打印的行数,如果多则按每页可打印的行数算,否则按数据量算
            float ft = (printDt.Rows.Count - countNum + 1 > linesPerPage ? linesPerPage : (printDt.Rows.Count - countNum + 1)) * (pInfo.dataFont.GetHeight(graphic) + 2);//内容占的高度
            for (int j = 0; j <= printDt.Columns.Count; j++)
            {
                if (j > 0)
                {//如果是第一条竖线,开始点不变
                    ti += pInfo.widths[j - 1];
                }
                ptS = new Point(ti, topMargin);
                ptE = new Point(ti, topMargin + ((int)Math.Round(ft, 0)));
                graphic.DrawLine(Pens.Black, ptS, ptE);
            }
            //然后画上面封顶的横道。
            ptS = new Point(leftMargin, topMargin);
            ptE = new Point(ti, topMargin);
            graphic.DrawLine(Pens.Black, ptS, ptE);
            //然后,填入绘字段名称行
            xPosition = leftMargin;
            yPosition = topMargin;
            for (int j = 0; j < printDt.Columns.Count; j++)
            {
                line = printDt.Columns[j].ColumnName;
                graphic.DrawString(line, pInfo.dataFont, brush, xPosition, yPosition + 1, new StringFormat());
                xPosition += pInfo.widths[j];
            }
            topMargin = topMargin + ((int)Math.Round(pInfo.dataFont.GetHeight(graphic) + 2, 0));
            ptS = new Point(leftMargin, topMargin);
            ptE = new Point(xPosition, topMargin);
            graphic.DrawLine(Pens.Black, ptS, ptE);
            linesPerPage--;//因为已经画了标题栏,所以每页可画的条数少1
            //countNum记录全局行数,currentPageLine记录当前打印页行数。
            while (countNum < printDt.Rows.Count)
            {
                if (currentPageLine < linesPerPage)
                {
                    xPosition = leftMargin;
                    ft = currentPageLine * (pInfo.dataFont.GetHeight(graphic) + 2);//前面行数占的高度
                    yPosition = topMargin + ((int)Math.Round(ft, 0));
                    //绘制当前行
                    for (int j = 0; j < printDt.Columns.Count; j++)
                    {
                        line = printDt.Rows[countNum][j].ToString();
                        graphic.DrawString(line, pInfo.dataFont, brush, xPosition, yPosition + 1, new StringFormat());
                        xPosition += pInfo.widths[j];
                    }

                    countNum++;
                    currentPageLine++;
                    //然后画下面的横道
                    ft = currentPageLine * (pInfo.dataFont.GetHeight(graphic) + 2);//前面行数占的高度
                    yPosition = topMargin + ((int)Math.Round(ft, 0));
                    ptS = new Point(leftMargin, yPosition);
                    ptE = new Point(xPosition, yPosition);
                    graphic.DrawLine(Pens.Black, ptS, ptE);
                }
                else
                {
                    line = null;
                    break;
                }
            }
            //一页显示不完时自动重新调用此方法
            if (line == null)
            {
                e.HasMorePages = true;
            }
            else
            {
                e.HasMorePages = false;
            }
            //每次打印完后countNum清0;
            if (countNum >= printDt.Rows.Count)
            {
                countNum = 0;
            }
        }

    }

}

2、打印DataGridView

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing.Printing;
using System.Drawing;
using System.Windows.Forms;

namespace WinSys.Common
{
    public class Printer
    {
        private DataGridView dataview;
        private PrintDocument printDoc;
        //打印有效区域的宽度
        int width;
        int height;
        int columns;
        double Rate;
        bool hasMorePage = false;
        int currRow = 0;
        int rowHeight = 20;
        //打印页数
        int PageNumber;
        //当前打印页的行数
        int pageSize = 20;
        //当前打印的页码
        int PageIndex;

        private int PageWidth; //打印纸的宽度
        private int PageHeight; //打印纸的高度
        private int LeftMargin; //有效打印区距离打印纸的左边大小
        private int TopMargin;//有效打印区距离打印纸的上面大小
        private int RightMargin;//有效打印区距离打印纸的右边大小
        private int BottomMargin;//有效打印区距离打印纸的下边大小

        int rows;

        /**/
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="dataview">要打印的DateGridView</param>
        /// <param name="printDoc">PrintDocument用于获取打印机的设置</param>
        public Printer(DataGridView dataview, PrintDocument printDoc)
        {
            this.dataview = dataview;
            this.printDoc = printDoc;
            PageIndex = 0;
            //获取打印数据的具体行数
            this.rows = dataview.RowCount;

            this.columns = dataview.ColumnCount;
            //判断打印设置是否是横向打印
            if (!printDoc.DefaultPageSettings.Landscape)
            {

                PageWidth = printDoc.DefaultPageSettings.PaperSize.Width;
                PageHeight = printDoc.DefaultPageSettings.PaperSize.Height;
            }
            else
            {
                PageHeight = printDoc.DefaultPageSettings.PaperSize.Width;
                PageWidth = printDoc.DefaultPageSettings.PaperSize.Height;

            }
            LeftMargin = printDoc.DefaultPageSettings.Margins.Left;
            TopMargin = printDoc.DefaultPageSettings.Margins.Top;
            RightMargin = printDoc.DefaultPageSettings.Margins.Right;
            BottomMargin = printDoc.DefaultPageSettings.Margins.Bottom;

            height = PageHeight - TopMargin - BottomMargin - 2;
            width = PageWidth - LeftMargin - RightMargin - 2;

            double tempheight = height;
            double temprowHeight = rowHeight;
            while (true)
            {
                string temp = Convert.ToString(tempheight / Math.Round(temprowHeight, 3));
                int i = temp.IndexOf('.');
                double tt = 100;
                if (i != -1)
                {
                    tt = Math.Round(Convert.ToDouble(temp.Substring(temp.IndexOf('.'))), 3);
                }
                if (tt <= 0.01)
                {
                    rowHeight = Convert.ToInt32(temprowHeight);
                    break;
                }
                else
                {
                    temprowHeight = temprowHeight + 0.01;

                }
            }
            pageSize = height / rowHeight;
            if ((rows + 1) <= pageSize)
            {
                pageSize = rows + 1;
                PageNumber = 1;
            }
            else
            {
                PageNumber = rows / (pageSize - 1);
                if (rows % (pageSize - 1) != 0)
                {
                    PageNumber = PageNumber + 1;
                }
            }
        }



        /**/
        /// <summary>
        /// 初始化打印
        /// </summary>
        private void InitPrint()
        {
            PageIndex = PageIndex + 1;
            if (PageIndex == PageNumber)
            {
                hasMorePage = false;
                if (PageIndex != 1)
                {
                    pageSize = rows % (pageSize - 1) + 1;
                }
            }
            else
            {
                hasMorePage = true;
            }
        }
        //打印头
        private void DrawHeader(Graphics g)
        {
            Font font = new Font("宋体", 12, FontStyle.Bold);
            int temptop = (rowHeight / 2) + TopMargin + 1;
            int templeft = LeftMargin + 1;

            for (int i = 0; i < this.columns; i++)
            {
                string headString = this.dataview.Columns[i].HeaderText;
                float fontHeight = g.MeasureString(headString, font).Height;
                float fontwidth = g.MeasureString(headString, font).Width;
                float temp = temptop - (fontHeight) / 3;
                g.DrawString(headString, font, Brushes.Black, new PointF(templeft, temp));
                templeft = templeft + (int)(this.dataview.Columns[i].Width / Rate) + 1;
            }
        }
        //画表格
        private void DrawTable(Graphics g)
        {
            Rectangle border = new Rectangle(LeftMargin, TopMargin, width, (pageSize) * rowHeight);
            g.DrawRectangle(new Pen(Brushes.Black, 2), border);
            for (int i = 1; i < pageSize; i++)
            {
                if (i != 1)
                {
                    g.DrawLine(new Pen(Brushes.Black, 1), new Point(LeftMargin + 1, (rowHeight * i) + TopMargin + 1), new Point(width + LeftMargin, (rowHeight * i) + TopMargin + 1));
                }
                else
                {
                    g.DrawLine(new Pen(Brushes.Black, 2), new Point(LeftMargin + 1, (rowHeight * i) + TopMargin + 1), new Point(width + LeftMargin, (rowHeight * i) + TopMargin + 1));
                }
            }

            //计算出列的总宽度和打印纸比率
            Rate = Convert.ToDouble(GetDateViewWidth()) / Convert.ToDouble(width);
            int tempLeft = LeftMargin + 1;
            int endY = (pageSize) * rowHeight + TopMargin;
            for (int i = 1; i < columns; i++)
            {
                tempLeft = tempLeft + 1 + (int)(this.dataview.Columns[i - 1].Width / Rate);
                g.DrawLine(new Pen(Brushes.Black, 1), new Point(tempLeft, TopMargin), new Point(tempLeft, endY));
            }
        }
        /**/
        /// <summary>
        /// 获取打印的列的总宽度
        /// </summary>
        /// <returns></returns>
        private int GetDateViewWidth()
        {
            int total = 0;
            for (int i = 0; i < this.columns; i++)
            {
                total = total + this.dataview.Columns[i].Width;
            }
            return total;
        }

        //打印行数据
        private void DrawRows(Graphics g)
        {

            Font font = new Font("宋体", 12, FontStyle.Regular);
            int temptop = (rowHeight / 2) + TopMargin + 1 + rowHeight;

            for (int i = currRow; i < pageSize + currRow - 1; i++)
            {
                int templeft = LeftMargin + 1;
                for (int j = 0; j < columns; j++)
                {
                    string headString = this.dataview.Rows[i].Cells[j].Value.ToString();
                    float fontHeight = g.MeasureString(headString, font).Height;
                    float fontwidth = g.MeasureString(headString, font).Width;
                    float temp = temptop - (fontHeight) / 3;
                    while (true)
                    {
                        if (fontwidth <= (int)(this.dataview.Columns[j].Width / Rate))
                        {
                            break;
                        }
                        else
                        {
                            headString = headString.Substring(0, headString.Length - 1);
                            fontwidth = g.MeasureString(headString, font).Width;
                        }
                    }
                    g.DrawString(headString, font, Brushes.Black, new PointF(templeft, temp));

                    templeft = templeft + (int)(this.dataview.Columns[j].Width / Rate) + 1;
                }

                temptop = temptop + rowHeight;
            }
            currRow = pageSize + currRow - 1;
        }

        /**/
        /// <summary>
        /// 在PrintDocument中的PrintPage方法中调用
        /// </summary>
        /// <param name="g">传入PrintPage中PrintPageEventArgs中的Graphics</param>
        /// <returns>是否还有打印页 有返回true,无则返回false</returns>
        public bool Print(Graphics g)
        {
            InitPrint();
            DrawTable(g);
            DrawHeader(g);
            DrawRows(g);

            //打印页码
            string pagestr = PageIndex + " / " + PageNumber;
            Font font = new Font("宋体", 12, FontStyle.Regular);
            g.DrawString(pagestr, font, Brushes.Black, new PointF((PageWidth / 2) - g.MeasureString(pagestr, font).Width, PageHeight - (BottomMargin / 2) - g.MeasureString(pagestr, font).Height));
            //打印查询的功能项名称
            string temp = dataview.Tag.ToString() + " " + DateTime.Now.ToString("yyyy-MM-dd HH:mm");
            g.DrawString(temp, font, Brushes.Black, new PointF(PageWidth - 5 - g.MeasureString(temp, font).Width, PageHeight - 5 - g.MeasureString(temp, font).Height));
            return hasMorePage;
        }
    }
}
原文地址:https://www.cnblogs.com/bobo-pcb/p/5098824.html