報表列印|建立|報表列印 摘要:
看過盧彥先生的關於WEB報表列印實現文章的人,一定會為裡面所提供的解決方案擊節叫好,本文試圖給大家展現一個更靈活的列印工作流水,並具有一定的實用性。建議大家在閱讀本文之前先閱讀盧彥先生的兩篇文章,同時本文採用了微軟的WSE(1.0)作為協助工具輔助,對此感到陌生的朋友,建議先參考一些概念性的文章,我在文章的最後列了一些參考資料和所需工具,大家可自行體會。
--------------------------------------------------------------------------------
目錄
引言
軟體原理
程式實現
注意事項
總結
參考資料
--------------------------------------------------------------------------------
引言:
WSE提供了一個非常方便的功能,就是支援附件的傳輸,儘管我們可以採用別的方式來達到這個目的,比如直接的返回byte型的資料,但是對於大多數應用而言,直接返回一個附件,如一張圖片更為實在些,請大家不要誤會我文章的標題,以為建立一個WEBSERVICE就可以方便地實現了列印了,我們的軟體原理和最終列印的方式跟盧彥先生裡提到的並無多大區別,我們只是利用了WebService的強大的穿透性,來使這個方式更為靈活,更易於應用和拓展,本文所採用的代碼全部用C#編寫。
--------------------------------------------------------------------------------
軟體原理:
本文採用了XML形式的資料,用戶端將需要列印的資料和一些基本的參數,如圖象大小,圖象形式等傳送給伺服器端,而伺服器端則根據用戶端的要求產生特定的一張或多張圖片返回給用戶端,由用戶端的列印程式統一處理,看了這個邏輯我們就可以發現:所有的商務規則完全在伺服器端運做,而用戶端只需要少量的代碼就可以實現報表的列印。這樣就避免了各種升級所帶來的煩惱,當實際運用中要求增加一種或多種圖表的時候,我們所需要做的只是增加或者修改伺服器端的商務規則,而客戶所要做的只是告訴我們要列印這種圖表就可以了。
本文採用了一些簡單的XML資料,僅供示範用,用戶端的Demo資料如下:
<?xml version="1.0" encoding="utf-8"?>
<Root PrintType="line" Width="450" Height="500" Title="Print Demo">
<Child Text="1" Value="100" Color="Black">
</Child>
<Child Text="2" Value="60" Color="Orange">
</Child>
<Child Text="3" Value="30" Color="Red">
</Child>
<Child Text="4" Value="40" Color="Gray">
</Child>
<Child Text="5" Value="90" Color="Blue">
</Child>
<Child Text="6" Value="60" Color="Green">
</Child>
</Root>
其中PrintType就是用戶端要求的列印類型。
程式實現:
伺服器端代碼
本系統也同樣採用了Abstract Factory的設計模式,以利於伺服器端方便的擴充,此處就不再贅述。
建立一個Web服務項目,添加抽象基類,實作類別,解析類,建成後的介面如下所示:
需要加入對Microsoft.Web.Services命名空間的引用
其中
PrintBase.cs是基類
Parser.cs是解析類
LinePrint.cs是實現具體圖象的類
基類代碼:
public class PrintBase
{
public PrintBase()
{
//
// TODO: 在此處添加建構函式邏輯
//
}
public virtual Stream DrawImage()
{
return null;
}
}
解析類代碼:
public class Parser
{
public Parser()
{
//
// TODO: 在此處添加建構函式邏輯
//
}
public static PrintBase CreateElement(DataSet ds)
{
PrintBase pb = null;
string l_strPrintType = ds.Tables["Root"].Rows[0]["PrintType"].ToString();
switch(l_strPrintType)
{
case "line":
pb = new LinePrint(ds);
break;
default:
pb = new PrintBase();
break;
}
return pb;
}
}
實作類別的代碼:
由於此處代碼較長,我只貼出部分代碼供參考,大家可以根據自己的實際情況進行圖形的繪製。
/// <summary>
/// 重載畫的規則
/// </summary>
/// <returns>圖象Stream</returns>
public override Stream DrawImage()
{
_ChartSize = new SizeF(float.Parse(ds.Tables["Root"].Rows[0]["Width"].ToString()),
float.Parse(ds.Tables["Root"].Rows[0]["Height"].ToString()));
Bitmap b = new Bitmap((int)_ChartSize.Width,(int)_ChartSize.Height,
PixelFormat.Format32bppArgb);
//初始化
_Graphics = Graphics.FromImage(b);
//以下省略,請自行繪製
//儲存返回
MemoryStream s = new MemoryStream();
b.Save(s,ImageFormat.Png);
return s;
}
我個人一直比較喜歡用DataSet操作小型的XML資料,大家請按自己喜好調整,此處展示的方法將直接供Web服務類調用。
Web服務類的代碼:
[WebMethod]
public bool CreateImage(DataSet ds)
{
bool l_bStatus = true;
try
{
PrintBase pb = null;
pb = Parser.CreateElement(ds);
Stream s = pb.DrawImage();
SoapContext sc = HttpSoapContext.ResponseContext;
sc.Attachments.Add(new DimeAttachment("image/png",TypeFormatEnum.MediaType,s));
}
catch
{
l_bStatus = false;
}
return l_bStatus;
}
至此,我們伺服器端的代碼就基本完成了,下面我們來看用戶端所需要做的工作,我在此處建立了一個WinForm工程來做示範用,實際運用中,則採用盧彥文章裡提到的usercontrol就可以了。
用戶端代碼:
private void butto