如上所述,使用弱智的水晶报表,就会遇到如何构造数据源的问题,由于不同患者的药费记录和遗嘱记录都不同,而且整体上需要一个患者一个清单,所以其数据源只能为一个数组,而不是简单的
DataTable
。小弟一向对大且笨拙的
CrystalReport
不感冒,再加上对
GDI+
比较痴迷,索性费点功夫,使用
GDI+
来打印上述报表。
首先需要构造数据源,创建一个
ArrayList
对象
a
,然后再把每个患者需要打印的东东保存为一个
ArrayList
放入
ATotal
中。
if
( a !=
null
)
{
a.Clear();
}
for
(
int
m =
0
; m <
3
; m ++ )
{
ArrayList a1 =
new
ArrayList();
string
x0 =
"
住院患者一日清单
"
;
string
x1 =
"
入院日期:
2007-11-11
结算日期:
2007-11-11
至
2007-11-15 "
;
string
x2 =
"
姓名:欧阳峰
住院号:
20090909090
床:
512
妇科
"
;
string
x3 =
"
项目编号
*
项目名称
*
单价
*
数量
*
单位
"
; //
注意其中的
*
标志
string
[] x4 =
new
string
[
90
]; //
假设有
90
条数据,不固定
for
(
int
i =
0
; i <
90
; i ++ )
{
x4[ i ] =
"juejue1984*www.loyosoft.com*11.00*11*
鸟
"
; //
注意其中的
*
标志
}
string
x5 =
"
费用累计:
2500*
小计:
400 "
;
string
x6 =
"
累计按金:
3600*
余额:
1600 "
;
string
x7 =
"”;
string
x8 =
"”;
a1.Add( x0 );
a1.Add( x1 );
a1.Add( x2 );
a1.Add( x3 );
a1.Add( x4 );
a1.Add( x5 );
a1.Add( x6 );
a1.Add( x7 );
a1.Add( x8 );
a.
Add( a1 );
然后在
PrintDocument
对象的
PrinPage
事件作如下处理:
Size sTotal = new Size( 420, e.PageBounds.Height );
Graphics g = e.Graphics;
Font fTitle = new Font( "
宋体
", 16 ); //
标题字体
int titleHeight = 20; //
标题的高度
int textHeight = 13; //
普通文本的高度
Font fText = new Font( "
宋体
", 9 ); //
文本字体
int top = 30; //
顶部间距
int left = 10; //
左边距
int right = 10; //
右边距
int titleMargin = 15; //
标题和正文行间距
int textMargin = 5; //
行间距
int rectangleMargin = 3; //
边框和文本间距
int oneHeight = 19; //
一行文本
+ 2 *
行间距的高度
int oneWidth = sTotal.Width - left - right; //
打印内容的宽度
int y = 0;
while ( j < a.Count ) // Count
为要打印的患者个数
{
ArrayList a3 = a[ j ] as ArrayList; // a3
位要打印的患者的清单内容。
if( y >= e.PageBounds.Height - titleHeight ) //
如果已经到了底部则开始下一页
{
e.HasMorePages = true;
return;
}
//
string x = a3[ 0 ] as string;
if( !this.JudgeString( x ) ) //
如果此行记录还未打印过
{
//string x = "
住院患者一日清单
"; // a1
SizeF sTitle = g.MeasureString( x, fTitle ); //
计算标题的长度和高度
Point pTitle = new Point( ( sTotal.Width - (int)sTitle.Width ) / 2, y + top ); //
使标题绝对居中
y += top; // 1
//
g.DrawString( x, fTitle, Brushes.Black, pTitle.X, y ); //
标题
this.AddPrintedSign( ref x );
a3[ 0 ] = x; //
标记该患者的此行内容为已经打印过
y += titleHeight + titleMargin; // Y
坐标下移
}
//
if( y >= e.PageBounds.Height - oneHeight )
{
e.HasMorePages = true;
return;
}
////
正文第一行
string r1 = a3[ 1 ] as String;
if( !this.JudgeString( r1 ) )
{
g.DrawString( r1, fText, Brushes.Black, left, y );
this.AddPrintedSign( ref r1 );
a3[ 1 ] = r1;
y += textHeight + textMargin; // 3
}
//
if( y >= e.PageBounds.Height - oneHeight )
{
e.HasMorePages = true;
return;
}
//
////
正文第二行
string r2 = a3[ 2 ] as String;
if( !this.JudgeString( r2 ) )
{
g.DrawString( r2, fText, Brushes.Black, left, y );
this.AddPrintedSign( ref r2 );
a3[ 2 ] = r2;
y += textHeight + textMargin; // 4
}
//
if( y >= e.PageBounds.Height - oneHeight )
{
e.HasMorePages = true;
return;
}
//
////
内容
string column = a3[ 3 ] as string;
if( !this.JudgeString( column ) )
{
string[] c = column.Split( new char[] { '*' } );
Rectangle R1 = new Rectangle( left, y, oneWidth, oneHeight );
g.DrawRectangle( Pens.Black, R1 );
g.DrawLine( Pens.Black, new Point( R1.X + R1.Width * 4 / 16, R1.Y ), new Point( R1.X + R1.Width * 4 / 16, R1.Y + R1.Height ) );
g.DrawLine( Pens.Black, new Point( R1.X + R1.Width * 10 / 16, R1.Y ), new Point( R1.X + R1.Width * 10 / 16, R1.Y + R1.Height ) );
g.DrawLine( Pens.Black, new Point( R1.X + R1.Width * 12 / 16, R1.Y ), new Point( R1.X + R1.Width * 12 / 16, R1.Y + R1.Height ) );
g.DrawLine( Pens.Black, new Point( R1.X + R1.Width * 14 / 16, R1.Y ), new Point( R1.X + R1.Width * 14 / 16, R1.Y + R1.Height ) );
g.DrawString( c[ 0 ], fText, Brushes.Black, R1.X + rectangleMargin, R1.Y + rectangleMargin ); //
项目编号
//a4.1
g.DrawString( c[ 1 ], fText, Brushes.Black, R1.X + rectangleMargin + R1.Width * 4 / 16, R1.Y + rectangleMargin );//
项目名称
// a4.2
g.DrawString( c[ 2 ], fText, Brushes.Black, R1.X + rectangleMargin + R1.Width * 10 / 16, R1.Y + rectangleMargin );//
单价
//a4.3
g.DrawString( c[ 3 ], fText, Brushes.Black, R1.X + rectangleMargin + R1.Width * 12 / 16, R1.Y + rectangleMargin ); //
数量
//a4.4
g.DrawString( c[ 4 ], fText, Brushes.Black, R1.X + rectangleMargin + R1.Width * 14 / 16, R1.Y + rectangleMargin );//
单位
//a4.5
this.AddPrintedSign( ref column );
a3[ 3 ] = column;
y += oneHeight;
}
//
if( y >= e.PageBounds.Height - oneHeight )
{
e.HasMorePages = true;
return;
}
//
string[] row = a3[ 4 ] as string[];
int Row = row.Length;
for( int i = 0; i < Row; i ++ )
{
if( !this.JudgeString( row[ i ] ) )
{
string[] r = row[ i ].Split( new Char[] { '*' } );
g.DrawLine( Pens.Black, new Point( left + oneWidth * 0 / 16, y ), new Point( left + oneWidth * 0 / 16, y + oneHeight ) );
g.DrawLine( Pens.Black, new Point( left + oneWidth * 4 / 16, y ), new Point( left + oneWidth * 4 / 16, y + oneHeight ) );
g.DrawLine( Pens.Black, new Point( left + oneWidth * 10 / 16, y ), new Point( left + oneWidth * 10 / 16, y + oneHeight ) );
g.DrawLine( Pens.Black, new Point( left + oneWidth * 12 / 16, y ), new Point( left + oneWidth * 12 / 16, y + oneHeight ) );
g.DrawLine( Pens.Black, new Point( left + oneWidth * 14 / 16, y ), new Point( left + oneWidth * 14 / 16, y + oneHeight ) );
g.DrawLine( Pens.Black, new Point( left + oneWidth * 16 / 16, y ), new Point( left + oneWidth * 16 / 16, y + oneHeight ) );
g.DrawString( r[ 0 ], fText, Brushes.Red, left + rectangleMargin, y + rectangleMargin ); //a5.1
g.DrawString( r[ 1 ], fText, Brushes.Red, left + rectangleMargin + oneWidth * 4 / 16, y + rectangleMargin ); //a5.2
g.DrawString( r[ 2 ], fText, Brushes.Red, left + rectangleMargin + oneWidth * 10 / 16, y + rectangleMargin );//a5.3
g.DrawString( r[ 3 ], fText, Brushes.Red, left + rectangleMargin + oneWidth * 12 / 16, y + rectangleMargin );//a5.4
g.DrawString( r[ 4 ], fText, Brushes.Red, left + rectangleMargin + oneWidth * 14 / 16, y + rectangleMargin );//a5.5
this.AddPrintedSign( ref row[ i ] );
y += oneHeight;
}
//
if( y >= e.PageBounds.Height - oneHeight )
{
e.HasMorePages = true;
return;
}
//
if( i == Row - 1 )
{
g.DrawLine( Pens.Black, new Point( left, y ), new Point( sTotal.Width - left - right, y ) );
}
}
//
费用累计
//
if( y >= e.PageBounds.Height - oneHeight )
{
e.HasMorePages = true;
return;
}
//
////
费用累计
string feeTotal = a3[ 5 ] as String;
if( !this.JudgeString( feeTotal ) )
{
string[] feeT = feeTotal.Split( new char[] { '*' } );
Rectangle R3 = new Rectangle( left, y, oneWidth, oneHeight );
g.DrawRectangle( Pens.Black, R3 );
g.DrawLine( Pens.Black, new Point( left + oneWidth * 10 / 16, y ), new Point( left + oneWidth * 10 / 16, y + R3.Height ) );
g.DrawString( feeT[ 0 ], fText, Brushes.Black, R3.X + rectangleMargin, y + rectangleMargin );
g.DrawString( feeT[ 1 ], fText, Brushes.Black, left + 2 * rectangleMargin + R3.Width * 10 / 16, y + rectangleMargin );
this.AddPrintedSign( ref feeTotal );
a3[ 5 ] = feeTotal;
y += oneHeight;
}
//
if( y >= e.PageBounds.Height - oneHeight )
{
e.HasMorePages = true;
return;
}
//
////
费用按金
string feeBalance = a3[ 6 ] as String;
if( !this.JudgeString( feeBalance ) )
{
string[] feeB = feeBalance.Split( new char[] { '*' } );
Rectangle R4 = new Rectangle( left, y, oneWidth, oneHeight );
g.DrawRectangle( Pens.Black, R4 );
g.DrawLine( Pens.Black, new Point( left + oneWidth * 10 / 16, y ), new Point( left + oneWidth * 10 / 16, y + R4.Height ) );
g.DrawString( feeB[ 0 ], fText, Brushes.Black, left + rectangleMargin, y + rectangleMargin );
g.DrawString( feeB[ 1 ], fText, Brushes.Black, left + 2 * rectangleMargin + oneWidth * 10 / 16, y + rectangleMargin );
this.AddPrintedSign( ref feeBalance );
a3[ 6 ] = feeBalance;
y += oneHeight;
}
////
备注
//string remark = "
备注:此清单一式两份,正联由患者或者家属签字,科室留存,付联由患者保存,可随时查询。如
24
小时不签字,不质疑视为认可费用。如病情需要变更医嘱另行通知。
/r/n" +
// "
注:省保或者市保的比例为自费比例。
";
string remark1 = a3[ 7 ] as String;
SizeF remarkSize = g.MeasureString( remark1, fText );
int Row2 = ( int )remarkSize.Width / ( oneWidth - 2 * rectangleMargin );
if( Row2 * ( oneWidth - 2 * rectangleMargin ) < (int)remarkSize.Width )
{
Row2 += 1;
}
//
if( y >= e.PageBounds.Height - ( Row2 + 1 ) * textHeight + 2 * rectangleMargin + Row2 * textMargin )
{
e.HasMorePages = true;
return;
}
//
if( !this.JudgeString( remark1 ) )
{
Rectangle R5 = new Rectangle( left, y, oneWidth, ( Row2 + 1 ) * textHeight + 2 * rectangleMargin + Row2 * textMargin );
g.DrawRectangle( Pens.Black, R5 );
R5.Offset( 2, 5 );
g.DrawString( remark1, fText, Brushes.Black, R5 );
this.AddPrintedSign( ref remark1 );
a3[ 7 ] = remark1;
y += R5.Height;
}
//
if( y >= e.PageBounds.Height - 3 * oneHeight )
{
e.HasMorePages = true;
return;
}
////
签字
string signature = a3[ 8 ] as String;
Rectangle R6 = new Rectangle( left, y, oneWidth, 2 * rectangleMargin + 3 * textHeight + 2 * textMargin );
if( !this.JudgeString( signature ) )
{
g.DrawRectangle( Pens.Black, R6 );
g.DrawString( signature, fText, Brushes.Black, left, y + rectangleMargin + textMargin + textHeight );
this.AddPrintedSign( ref signature );
a3[ 8 ] = signature;
y += R6.Height;
}
j ++;
}
j = 0; //
打印完毕
e.HasMorePages = false;
}
判断一行内容是否已经打印过:
/// <summary>
///
判断该字符串最后一个字符是否是
*
号,如果是,则表示已经打印过
/// </summary>
/// <param name="s">
需要判断的字符串
</param>
/// <returns>
如果有则返回
true
,否则返回
false</returns>
private bool JudgeString( string s )
{
int l = s.Length;
if( s[ l - 1 ] != '*' )
{
return false;
}
return true;
}
将已经打印过的内容标记为已打印
/// <summary>
///
将已经打印过的行最后一个字符标记为
*
,表示该行已经打印
/// </summary>
/// <param name="s">
字符串对象
</param>
private void AddPrintedSign( ref string s )
{
int l = s.Length;
s = s.Replace( s.Substring( l - 1, 1 ), "*" );
}