因公司需要 , 需要打印如下表单:
第一:首先考虑自己画表格 ,然后打印.因为这样可以很方便的控制纸张,大小等...
通过使用网上打印gridview代码,进行打印,发现能实现基本要求..但是 ,当商品名称多字换行时,不能自动换行,数据分页也不能很好的支持,并且
表格并不会随着换行而增高..这是打印类的问题..下面讲打印类贴出,希望有朋友看见的话 帮忙改下.,所以这种方法由于是自己的技术不过关。然后
确实没太多的时间来弄,而打算采用报表来做.
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Printing;
using System.Drawing;
namespace Etaocn.Util
{
/**/ /// <summary>
/// 创建人 贺挺
/// </summary>
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 = 40 ; // 行高是固定死的..应该根据 字体是否换行而增加高度..
// 打印页数
int PageNumber;
// 当前打印页的行数
int pageSize = 20 ;
// 当前打印的页码
int PageIndex;
int AreaHeight;
private int PageWidth; // 打印纸的宽度
private int PageHeight; // 打印纸的高度
private int LeftMargin; // 有效打印区距离打印纸的左边大小
private int TopMargin; // 有效打印区距离打印纸的上面大小
private int RightMargin; // 有效打印区距离打印纸的右边大小
private int BottomMargin; // 有效打印区距离打印纸的下边大小
int rows;
private string [] footer;
/**/ /// <summary>
/// 构造函数
/// </summary>
/// <param name="dataview"> 要打印的DateGridView </param>
/// <param name="printDoc"> PrintDocument用于获取打印机的设置 </param>
public Printer(DataGridView dataview, PrintDocument printDoc, string [] footer)
{
this .footer = footer;
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 - 50 ;
TopMargin = printDoc.DefaultPageSettings.Margins.Top + 60 ;
RightMargin = printDoc.DefaultPageSettings.Margins.Right;
BottomMargin = printDoc.DefaultPageSettings.Margins.Bottom - 100 ;
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( " 宋体 " , 11 , FontStyle.Regular);
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, 1 ), 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, 1 ), 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( " 宋体 " , 10 , 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 ;
AreaHeight = temptop;
}
/**/ /// <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 s1 = " 如果配送员已经提醒您验货,并且已经完成验货过程请您签字:收货时间: 年 月 日 时 " ;
string s2 = " 订单审核: 送货: 客户签字: " ;
string s3 = " 您所有订购的商品有任何质量问题请在一周内与时代网客服中心联系,我们将为您安排退货事宜!\n详细售后服务细则请登录时代网www.vsvt.com查看帮助! " ;
string s4 = " 订全年时尚杂志、瑞丽杂志、企业家、经理人、商界杂志送精美礼品,订购电话:028-8688 8688 " ;
// 打印页码
string pagestr = PageIndex + " / " + PageNumber;
Font font = new Font( " 宋体 " , 11 , 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 = DateTime.Now.ToString("yyyy-MM-dd HH:mm") + AreaHeight.ToString();
g.DrawRectangle( new Pen(Brushes.Black), LeftMargin, AreaHeight - 11 , 675 , 20 );
g.DrawString( " 收款账户: " + footer[ 0 ] + " 商品总数量: " + footer[ 1 ] + " 商品费用: " + footer[ 2 ] + " 总金额: " + footer[ 3 ] + " " , font, Brushes.Black, new PointF(LeftMargin, AreaHeight - 9 ));
g.DrawString(s1, font, Brushes.Black, LeftMargin, AreaHeight + 30 );
g.DrawString(s2, font, Brushes.Black, LeftMargin, AreaHeight + rowHeight + 40 );
g.DrawString(s3, font, Brushes.Black, LeftMargin, AreaHeight + rowHeight + 65 );
g.DrawString(s4, new Font( " 宋体 " , 11 ,FontStyle.Bold), Brushes.Black, LeftMargin, AreaHeight + rowHeight + 105 );
return hasMorePage;
}
}
}
第二:采用微软的报表..微软报表对表格的支持非常的友好,内容自动换行,都是默认就支持的,
但是呢.微软报表的页眉和页脚不能直接使用数据源的数据,只有把数据放在主体中(如果不放在表格的循环体中,而是放在循环的下面或者上面的话,
当数据分页的时候,其他页面就不能显示数据),然后页眉页脚再来引用主题中的数据,
如图:
这样的话 只需要把上面textboxobj里面的属性 Hidedaplicates 设置成下面单元格的名称就可以在打印的时候 隐藏下面对应的字段了。
接下来的工作基本完成,可是到了最后一步居然发现 ,当打印纸的宽度大于高度的时候,系统会默认横向打印..(微软报表的bug.)后面在网上
找了几种方法,比如把高和宽颠倒写的。发现不能满足自己的要求..于是乎最后决定再试试水晶报表- -!
第三:水晶报表
我用的是vs2008自带的版本..
开始水晶报表会根据你自定义的纸张,来显示工作区的大小(这点儿我觉得比那个微软报表好),然后建立数据源等等..
最后 开始画表格..还有调整textobj的位置.. 位置调好以后,最先以为只要把textobj的边框显示出来,就是最后的表格呈现方式,结果鼓捣半天鼓捣不出来.
继续找相关资料,,原来表格是通过boxobj 和 lineobj画上去的, 再然后开始画表格..最后也是字段内容自动换行的问题..
根据网上通用的方法,一:设置字段可以自动扩大,二:详细资料 节专家,延伸到后续节,三.lineobj,boxobj,打印时扩展到节的底部.,实现成功!
但是发现当字段内容包含数字的时候 ,数字会自动格式化成默认的格式,并且自动换行会变的不正常。我设置了报表的数字默认格式以后还是不行,
最后采用公式字段,把里面的.00和, 去掉-- !
去掉以后 , 报表自动换行也正常了。
总结: 如果要自己来做打印的话。确实需要一些功底,而且需要耐心去调整。。
微软报表:MicroSoftReportViewer,太鸡肋了,看看以后会不会以后什么改变..
水晶报表:字段格式出现了点儿问题以外,其他都很满意。。。 以后就用这个了。。