|
在一般的企業(yè)應(yīng)用開發(fā)中都會涉及到報(bào)表的生成,且一般報(bào)表的格式都是生成Excel格式的。對于各種報(bào)表的生成一直是程序員心中永遠(yuǎn)的痛,因?yàn)閷τ诤芏喑绦騿T來說每寫一個(gè)報(bào)表都意味著要寫一大斷代碼來實(shí)現(xiàn),而且有的報(bào)表可能極其復(fù)雜以及不規(guī)范,這時(shí)就會浪費(fèi)程序員大量的時(shí)間來編寫和調(diào)試這些代碼,那到底有沒有一種方法能使代碼盡量少寫,且又能實(shí)現(xiàn)各種Excel報(bào)表的生成呢,下面我們就轉(zhuǎn)入正題。
我們要生成Excel報(bào)表,其實(shí)我們只需要兩樣?xùn)|西: 1.報(bào)表的樣式,也就是哪個(gè)字段應(yīng)該填在哪里,哪一列應(yīng)該填什么,字體大小,顏色,單元格高度,寬度,單元格是否合并,是否跨行,是否跨列,是橫向報(bào)表(所謂橫向報(bào)表,我自定義為:一張Excel報(bào)表就是有一條記錄或者有一條記錄以及其關(guān)聯(lián)記錄而生成的報(bào)表,如一張訂單報(bào)表通常就是有一個(gè)訂單頭和其相關(guān)的訂單明細(xì)所生成,這個(gè)就是我自定義的橫向報(bào)表)還是縱向報(bào)表(所謂縱向報(bào)表,我自定義為:一張報(bào)表就是有一個(gè)記錄集所生成的,如要生成一張記錄某個(gè)班級學(xué)生情況的報(bào)表,則要把這個(gè)班級的學(xué)生記錄都要導(dǎo)出到這張報(bào)表中,這種報(bào)表基本上就是統(tǒng)計(jì)報(bào)表,一張報(bào)表可能會有幾萬條記錄或者更多,這個(gè)就是我自定義的縱向報(bào)表)等等報(bào)表樣式。 2.報(bào)表的數(shù)據(jù),對于我們而言有了報(bào)表樣式,我們就知道在哪個(gè)或者哪幾個(gè)單元格應(yīng)該填哪些數(shù)據(jù),具體的數(shù)據(jù),我們則可以以DataTable的形式來表現(xiàn),也可以以DataSet的形式來表現(xiàn),至于用怎么樣的數(shù)據(jù)格式可以隨自己喜歡,自己來定義。 現(xiàn)在我們知道了生成Excel報(bào)表只要有了樣式和數(shù)據(jù),就可以生成一張自己想要的報(bào)表了,數(shù)據(jù)的生成并不困難,但是我們的困難就是這個(gè)報(bào)表的樣式用什么來描述,怎么來描述。 對于樣式的描述我們可以用兩種方法來實(shí)現(xiàn): 1.直接用XML來描述,這個(gè)xml描述文件的主要描述的內(nèi)容可以如下(舉個(gè)列子說明一下,現(xiàn)在描述的還不是很規(guī)范): <?xml version="1.0" encoding="UTF-8"?> <Style> <ExcelStyle Sort="縱向" Space="1"> <Ranges> <RangeStyle> <Range CellWidth="2.0" CellHeight="20" CellBord="1" CellBackColor=""></Range> <TitleCell TitleName="部件編號" TitleStartxPos="1" TitleEndxPos="1" TitleStartyPos="1" TitleEndyPos="1"></TitleCell> <DataCell DataName="PartNo" DataStartxPos="2" DataEndxPos="14" DataStartyPos="34" DataEndyPos="34"IsMerger="False" Align="XlHAlign.xlHAlignLeft" IsToArray="True" IsDateTime="False" Interval="1"> </DataCell> <TitleFont TitleFontName="宋體" TitleFontSize="9" TitleFontColor="Black" TitleFontBold="False" TitleFontItatic="False" TitleFontPosition="Center"> </TitleFont> <DataFont DataFontName="宋體" DataFontSize="11" DataFontColor="Black" DataFontBold="True" DataFontItatic="False" DataFontHyperLink="False" DataFontPosition="Center"> </DataFont> </RangeStyle> </Ranges> </ExcelStyle> </Style> 這個(gè)XML中結(jié)點(diǎn)Excelstyle的屬性Sort描述了整個(gè)Excel的格式是縱向的還是橫向的(所謂縱向還是橫向,我上面已有所說明),而屬性Space則描述了報(bào)表每個(gè)記錄的行與行之間空多少行。Ranges則是下面的所有子節(jié)點(diǎn)RangeStyle的父節(jié)點(diǎn),對于一張報(bào)表通常會有很多的RangeStyle結(jié)點(diǎn)。RangeStyle其實(shí)就開始真正來描述哪個(gè)或哪些單元格來填寫哪些字段,如結(jié)點(diǎn)Range 就定義了單元格高度,寬度,邊框?qū)挾?,顏色這些屬性。TitleCell就是定義了報(bào)表(因?yàn)槲疫@張是縱向報(bào)表,所以有Title)Title的屬性,如Title的名稱,哪個(gè)單元格來填寫這個(gè)名稱。節(jié)點(diǎn)DataCell則定義了要幫定數(shù)據(jù)中的哪個(gè)字段,從哪個(gè)單元開始填寫,單元格是否要合并,對齊方式,還有這個(gè)字段行與行之間的間隔。結(jié)點(diǎn)Title Font定義了Title字體屬性,如大小,顏色,是否斜體,是否粗體,對齊方式。結(jié)點(diǎn)DataFont則定義了數(shù)據(jù)字體的屬性,如大小,顏色,是否斜體,是否粗體,對齊方式。一個(gè)RangeStyle結(jié)點(diǎn)其實(shí)也就定義了一個(gè)字段的填寫,如果你的報(bào)表要填寫很多字段的話,就會有很多個(gè)RangeStyle結(jié)點(diǎn)來描述。這個(gè)xml樣式定義文件可以自己寫個(gè)工具來生成,我有現(xiàn)成的自己寫的生成工具叫ExcelStyle,不過還很簡陋,用起來還不方便,不過能生成我需要的樣式,哪位需要我可以發(fā)給你們(我不知道怎么提供下載)。 2. XML描述文件和Excel模板相結(jié)合的方法,對于有些報(bào)表會很復(fù)雜,特別是那些橫向的報(bào)表,有時(shí)候會極其復(fù)雜,這時(shí)就需要現(xiàn)成的Excel模板,有了Excel模板我們就可以參照著模板來生成xml樣式定義文件,在具體生成報(bào)表的時(shí)候,我們只要知道用到的Excel模版是哪個(gè),XML樣式文件是哪個(gè),再綁上我們的數(shù)據(jù),那么即使再復(fù)雜的報(bào)表也同樣能簡單生成了。 具體使用,可參照如下測試用列代碼(聲明ExcelOperate,XmlOperate是我自己寫的幾個(gè)通用的組件,如有需要我可發(fā)郵件給你們,其中數(shù)據(jù)我是以DataTable的形式來描述的): sing System; using NUnit.Framework; using ExcelOperate; using XmlOperate; using System.Data; using System.Data.SqlClient; namespace TestExcel { /// <summary> /// </summary> /// [TestFixture] public class ExcelExport { [Test] public void Export()//不用Excel模板的數(shù)據(jù)導(dǎo)出 { string Sql ="Select top 100* from customers "; //取出100條數(shù)據(jù) ExcelFactory _factory = new ExcelFactory(); //定義一個(gè)沒有參數(shù)的ExcelFactory _factory.CreateExcelwithoutTemplate("c:\\bbbbbbb.xml",GetDataTable(Sql )); //載入定義的樣式文件bbbbbbb.xml和剛?cè)〕鰜淼臄?shù)據(jù)GetDataTable(Sql ) _factory.SaveExcel("c:\\bbbbbbbbbbbbbbbb.xls"); //保存導(dǎo)出的文件即可 } [Test] public void ExportWithTemplate()//用到了Excel模版的數(shù)據(jù)導(dǎo)出 { string Sql ="Select top 1* from customers "; //取出一條數(shù)據(jù) ExcelFactory _factory = new ExcelFactory("c:\\QStandardCustomer.xls"); //導(dǎo)入模版QStandardCustomer.xls _factory.CreateExcel("c:\\QStandardCustomer.xml",GetDataTable(Sql )); //載入定義的樣式文件QStandadrCustomer.xml和剛?cè)〕鰜淼臄?shù)據(jù)GetDataTable(Sql ) _factory.SaveExcel("c:\\Qreportstr.xls"); //最后保存導(dǎo)出的Excel文件即可 } private DataTable GetDataTable(string Sql) { string myConnectionString = "packet size=4096;user id=sa;data source=172.28.200.98;initial catalog=Northwind"; SqlConnection myConnection = new SqlConnection(myConnectionString); myConnection.Open(); SqlDataAdapter myAdapter = new SqlDataAdapter(); SqlCommand myCommand = new SqlCommand(Sql,myConnection); myCommand.CommandType = CommandType.Text; myAdapter.SelectCommand = myCommand; DataSet ds = new DataSet(); myAdapter.Fill(ds); myConnection.Close(); return ds.Tables[0]; } } } 由上面代碼可見,一般的報(bào)表生成都是三句代碼,即使對于報(bào)表的某些行,某些格式要調(diào)整我們也不需要在去修改程序,只要改xml描述文件即可,這樣就可以使我們大大的在報(bào)表的生成上來節(jié)省時(shí)間,而可以把更多的時(shí)間放在業(yè)務(wù)邏輯的處理上了。 |
|
|