轉(zhuǎn)帖|其它|編輯:郝浩|2011-02-24 11:14:30.000|閱讀 1824 次
概述:本文章主要介紹報(bào)表的生成,基于Aspose.Cell控件的報(bào)表生成。談到報(bào)表,估計(jì)大家都有所領(lǐng)悟以及個(gè)人的理解,總的來說,一般的報(bào)表生成,基本上是基于以下幾種方式:一種是基于微軟Excel內(nèi)置的引擎來實(shí)現(xiàn);一種是構(gòu)造HTML格式的Excle報(bào)表;一種是基于控件的方式來處理,基于控件有很多種方式,個(gè)人認(rèn)為比較有名的是Aspose.Cell(收費(fèi)破解)和NPOI(開源)。
# 界面/圖表報(bào)表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
時(shí)光飛逝,生活、工作、業(yè)余研究總是在不停忙碌著,轉(zhuǎn)眼快到月底,該月的博客文章任務(wù)未完,停頓回憶一下,總結(jié)一些經(jīng)驗(yàn)以及好的東西出來,大家一起分享一下。本文章主要介紹報(bào)表的生成,基于Aspose.Cell控件的報(bào)表生成。談到報(bào)表,估計(jì)大家都有所領(lǐng)悟以及個(gè)人的理解,總的來說,一般的報(bào)表生成,基本上是基于以下幾種方式:一種是基于微軟Excel內(nèi)置的引擎來實(shí)現(xiàn);一種是構(gòu)造HTML格式的Excle報(bào)表;一種是基于控件的方式來處理,基于控件有很多種方式,個(gè)人認(rèn)為比較有名的是Aspose.Cell(收費(fèi)破解)和NPOI(開源)。
而報(bào)表的表現(xiàn)方式大致可以分為兩種:
一種是通用的二維表導(dǎo)出的Excel格式,這種方式通過封裝一個(gè)操作類,傳遞一個(gè)DataTable參數(shù),把數(shù)據(jù)導(dǎo)出就可以了。這種報(bào)表特點(diǎn)是操作方便,通用,能應(yīng)付一般常用的數(shù)據(jù)報(bào)表,如下所示;
由于這種報(bào)表,一般是在一個(gè)數(shù)據(jù)表格中顯示,通常的做法是把這個(gè)東西做成控件,一個(gè)可以解決分頁問題,一個(gè)可以解決導(dǎo)出、打印問題等,如我的隨筆文章《WinForm界面開發(fā)之“分頁控件”》 介紹的解決辦法。
當(dāng)然,也可以把導(dǎo)入導(dǎo)出Excel的操作封裝成一個(gè)公用的輔助來調(diào)用,如我封裝的Aspose.Cell的導(dǎo)入導(dǎo)出處理函數(shù)如下所示:
public class AsposeExcelTools
{
public static bool DataTableToExcel(DataTable datatable, string filepath, out string error)
{
error = "";
try
{
if (datatable == null)
{
error = "DataTableToExcel:datatable 為空";
return false;
}
Aspose.Cells.Workbook workbook = new Aspose.Cells.Workbook();
Aspose.Cells.Worksheet sheet = workbook.Worksheets[0];
Aspose.Cells.Cells cells = sheet.Cells;
int nRow = 0;
foreach (DataRow row in datatable.Rows)
{
nRow++;
try
{
for (int i = 0; i < datatable.Columns.Count; i++)
{
if (row[i].GetType().ToString() == "System.Drawing.Bitmap")
{
//------插入圖片數(shù)據(jù)-------
System.Drawing.Image image = (System.Drawing.Image)row[i];
MemoryStream mstream = new MemoryStream();
image.Save(mstream, System.Drawing.Imaging.ImageFormat.Jpeg);
sheet.Pictures.Add(nRow, i, mstream);
}
else
{
cells[nRow, i].PutValue(row[i]);
}
}
}
catch (System.Exception e)
{
error = error + " DataTableToExcel: " + e.Message;
}
}
workbook.Save(filepath);
return true;
}
catch (System.Exception e)
{
error = error + " DataTableToExcel: " + e.Message;
return false;
}
}
public static bool DataTableToExcel2(DataTable datatable, string filepath, out string error)
{
error = "";
Aspose.Cells.Workbook wb = new Aspose.Cells.Workbook();
try
{
if (datatable == null)
{
error = "DataTableToExcel:datatable 為空";
return false;
}
//為單元格添加樣式
Aspose.Cells.Style style = wb.Styles[wb.Styles.Add()];
//設(shè)置居中
style.HorizontalAlignment = Aspose.Cells.TextAlignmentType.Center;
//設(shè)置背景顏色
style.ForegroundColor = System.Drawing.Color.FromArgb(153, 204, 0);
style.Pattern = BackgroundType.Solid;
style.Font.IsBold = true;
int rowIndex = 0;
for (int i = 0; i < datatable.Columns.Count; i++)
{
DataColumn col = datatable.Columns[i];
string columnName = col.Caption ?? col.ColumnName;
wb.Worksheets[0].Cells[rowIndex, i].PutValue(columnName);
wb.Worksheets[0].Cells[rowIndex, i].Style = style;
}
rowIndex++;
foreach (DataRow row in datatable.Rows)
{
for (int i = 0; i < datatable.Columns.Count; i++)
{
wb.Worksheets[0].Cells[rowIndex, i].PutValue(row[i].ToString());
}
rowIndex++;
}
for (int k = 0; k < datatable.Columns.Count; k++)
{
wb.Worksheets[0].AutoFitColumn(k, 0, 150);
}
wb.Worksheets[0].FreezePanes(1, 0, 1, datatable.Columns.Count);
wb.Save(filepath);
return true;
}
catch (Exception e)
{
error = error + " DataTableToExcel: " + e.Message;
return false;
}
}
/// <summary>
/// Excel文件轉(zhuǎn)換為DataTable.
/// </summary>
/// <param name="filepath">Excel文件的全路徑</param>
/// <param name="datatable">DataTable:返回值</param>
/// <param name="error">錯(cuò)誤信息:返回錯(cuò)誤信息,沒有錯(cuò)誤返回""</param>
/// <returns>true:函數(shù)正確執(zhí)行 false:函數(shù)執(zhí)行錯(cuò)誤</returns>
public static bool ExcelFileToDataTable(string filepath, out DataTable datatable, out string error)
{
error = "";
datatable = null;
try
{
if (File.Exists(filepath) == false)
{
error = "文件不存在";
datatable = null;
return false;
}
Aspose.Cells.Workbook workbook = new Aspose.Cells.Workbook();
workbook.Open(filepath);
Aspose.Cells.Worksheet worksheet = workbook.Worksheets[0];
datatable = worksheet.Cells.ExportDataTable(0, 0, worksheet.Cells.MaxRow + 1, worksheet.Cells.MaxColumn + 1);
//-------------圖片處理-------------
Aspose.Cells.Pictures pictures = worksheet.Pictures;
if (pictures.Count > 0)
{
string error2 = "";
if (InsertPicturesIntoDataTable(pictures, datatable, out datatable, out error2) == false)
{
error = error + error2;
}
}
return true;
}
catch (System.Exception e)
{
error = e.Message;
return false;
}
}
public static bool ExcelFileToLists(string filepath, out IList[] lists, out string error)
{
error = "";
lists = null;
DataTable datatable = new DataTable();
IList list = new ArrayList();
Pictures[] pictures;
if (ExcelFileToDataTable(filepath, out datatable, out error) && GetPicturesFromExcelFile(filepath, out pictures, out error))
{
lists = new ArrayList[datatable.Rows.Count];
//------------DataTable轉(zhuǎn)換成IList[]--------------
//數(shù)據(jù)
int nRow = 0;
foreach (DataRow row in datatable.Rows)
{
lists[nRow] = new ArrayList(datatable.Columns.Count);
for (int i = 0; i <= datatable.Columns.Count - 1; i++)
{
lists[nRow].Add(row[i]);
}
nRow++;
}
//圖片
for (int i = 0; i < pictures.Length; i++)
{
foreach (Picture picture in pictures[i])
{
try
{
//----把圖片轉(zhuǎn)換成System.Drawing.Image----
//MemoryStream mstream = new MemoryStream();
//mstream.Write(picture.Data, 0, picture.Data.Length);
//System.Drawing.Image image = System.Drawing.Image.FromStream(mstream);
//----Image放入IList------
//圖片有可能越界
if (picture.UpperLeftRow <= datatable.Rows.Count && picture.UpperLeftColumn <= datatable.Columns.Count)
{
lists[picture.UpperLeftRow][picture.UpperLeftColumn] = picture.Data;
}
}
catch (System.Exception e)
{
error = error + e.Message;
}
}
}
}
else
{
return false;
}
return true;
}
public static bool ListsToExcelFile(string filepath, IList[] lists, out string error)
{
error = "";
//----------Aspose變量初始化----------------
Aspose.Cells.Workbook workbook = new Aspose.Cells.Workbook();
Aspose.Cells.Worksheet sheet = workbook.Worksheets[0];
Aspose.Cells.Cells cells = sheet.Cells;
//-------------輸入數(shù)據(jù)-------------
int nRow = 0;
sheet.Pictures.Clear();
cells.Clear();
foreach (IList list in lists)
{
for (int i = 0; i <= list.Count - 1; i++)
{
try
{
System.Console.WriteLine(i.ToString() + " " + list[i].GetType());
if (list[i].GetType().ToString() == "System.Drawing.Bitmap")
{
//插入圖片數(shù)據(jù)
System.Drawing.Image image = (System.Drawing.Image)list[i];
MemoryStream mstream = new MemoryStream();
image.Save(mstream, System.Drawing.Imaging.ImageFormat.Jpeg);
sheet.Pictures.Add(nRow, i, mstream);
}
else
{
cells[nRow, i].PutValue(list[i]);
}
}
catch (System.Exception e)
{
error = error + e.Message;
}
}
nRow++;
}
//-------------保存-------------
workbook.Save(filepath);
return true;
}
這樣封裝了Aspose.Cell的操作,每次生成Excel文件或者導(dǎo)入Excel內(nèi)容,就非常方便,只需要如下調(diào)用方式即可完成:
private void button1_Click(object sender, EventArgs e)
{
DataTable dt = CreateTable("測(cè)試1,測(cè)試2,Test1,Test2", "testTable");
for (int i = 0; i < 100; i++)
{
DataRow dr = dt.NewRow();
for (int j = 0; j < dt.Columns.Count; j++)
{
dr[j] = i.ToString();
}
dt.Rows.Add(dr);
}
string outError = "";
string fileName = @"C:\test.xls";
AsposeExcelTools.DataTableToExcel2(dt, fileName, out outError);
if (!string.IsNullOrEmpty(outError))
{
MessageBox.Show(outError);
}
else
{
Process.Start(fileName);
}
}
public DataTable CreateTable(string nameString, string tableName)
{
string[] nameArray = nameString.Split(new char[] { ',', ';' });
List<string> nameList = new List<string>();
foreach (string item in nameArray)
{
if (!string.IsNullOrEmpty(item))
{
nameList.Add(item);
}
}
return CreateTable(nameList, tableName);
}
另外一種是以Excel文件作為模板,然后填入必要的內(nèi)容,形成比較綜合性,復(fù)雜性較高的報(bào)表,這種報(bào)表一般比較專業(yè)、比較規(guī)范好看,在一些特殊的場(chǎng)合,必須使用這些固定格式的報(bào)表,如下所示:
或者這樣的報(bào)表格式
這些報(bào)表,基本上就是用到了變量、函數(shù)等的概念才能處理好這些數(shù)據(jù),如上面的出庫單,里面的成本中心、部門、庫房編號(hào)等,這些通過變量綁定應(yīng)該就可以了,而里面的列表,則可以通過集合綁定實(shí)現(xiàn),Aspose.Cell控件功能非常強(qiáng)大,很好支持這些操作,下面一步步介紹該控件制作這類報(bào)表的實(shí)現(xiàn)代碼。
Aspose.Cell控件支持多種參數(shù)變量的綁定操作,如支持DataSet、Datatable、IList集合,實(shí)體類集合、類對(duì)象等。
DataSet ds = LoadDataSet();//使用DataSet對(duì)象
List<Customers> entity = GetCustomers();//使用實(shí)體類對(duì)象
DataTable dt = GetCustomersTable();//使用DataTable對(duì)象
//創(chuàng)建一個(gè)workbookdesigner對(duì)象
WorkbookDesigner designer = new WorkbookDesigner();
//制定報(bào)表模板
string path = System.IO.Path.Combine(Application.StartupPath,"SmartMarkerDesigner.xls");
designer.Open(path);
//設(shè)置DataSet對(duì)象
//designer.SetDataSource(ds);
//設(shè)置實(shí)體類對(duì)象
//designer.SetDataSource("Customers", entity);
//設(shè)置Datatable對(duì)象
designer.SetDataSource(dt);
designer.SetDataSource(ds.Tables["Order Details"]);
//設(shè)置變量對(duì)象
designer.SetDataSource("Variable", "Single Variable");
//設(shè)置集合變量
designer.SetDataSource("MultiVariable", new string[] { "Variable 1", "Variable 2", "Variable 3" });
//設(shè)置集合變量
designer.SetDataSource("MultiVariable2", new string[] { "Skip 1", "Skip 2", "Skip 3" });
//根據(jù)數(shù)據(jù)源處理生成報(bào)表內(nèi)容
designer.Process();
//保存Excel文件
string fileToSave = System.IO.Path.Combine(Application.StartupPath, "SmartMarker.xls");
if (File.Exists(fileToSave))
{
File.Delete(fileToSave);
}
designer.Save(fileToSave, FileFormatType.Excel2003);
//打開Excel文件
Process.Start(fileToSave);
以上的代碼說明了改控件支持的各種參數(shù)變量,我們先看看報(bào)表的模板,然后看看報(bào)表的生成內(nèi)容,對(duì)比一下就更直觀了。
報(bào)表1模板如下所示(其中通過引用集合的對(duì)象是通過&=來引用,對(duì)象的屬性或者列名,通過如&=Customer.City方式引用,非常直觀方便:
成的效果如下所示(Customers可以使DataTable對(duì)象,也可以List<Customer>實(shí)體對(duì)象集合。
報(bào)表2的模板如下所示,對(duì)象也可以通過&=[Order Detail]方式引用,另外模板支持一些參數(shù),其中{r}為當(dāng)行的變量,翻譯到實(shí)際的報(bào)表可能就是C4*D4這樣的格式了,其中兩個(gè)&=表示動(dòng)態(tài)公式引用,區(qū)別于普通的變量和字符,如&=&=C{r}*D{r}后者匯總函數(shù)&=&=Sum(C{r}:D{r})等等。
報(bào)表2的生成效果如下所示
報(bào)表3的模板如下所示,這個(gè)報(bào)表模板使用了對(duì)象變量,對(duì)象變量引用方式如&=$Variable這樣格式,比集合對(duì)象或者DataTable對(duì)象多了一個(gè)$符號(hào),其中集合支持一些遍歷參數(shù),如Skip,Horiontal等等。
報(bào)表3的生成效果如下所示
綜上所述,模板報(bào)表的變量綁定方式有以下幾種方式:
&=DataSource.FieldName
&=[Data Source].[Field Name]
&=$VariableName
&=$VariableArray
&==DynamicFormula
&=&=RepeatDynamicFormula
另外,模板報(bào)表支持一些參數(shù)進(jìn)行輔助使用,如下所示:
noadd
適應(yīng)數(shù)據(jù)而不添加額外的行(不知道是不是這樣表達(dá))
skip:n
每行記錄跳過的數(shù)量,n=1代表依次遍歷N=2則跳一個(gè)遍歷
ascending:n / descending:n
排序數(shù)據(jù)供. 如果n=1,那么該列就是排序的第一個(gè)關(guān)鍵字,例子: &=Table1.Field3(ascending:1)
horizontal
默認(rèn)是上下垂直方式輸出,如果設(shè)置為horizontal,則是橫著輸出內(nèi)容,見上面的例子
動(dòng)態(tài)公式變量
另外,上面模板中看到&=&=C{r}*D{r}這樣的動(dòng)態(tài)公式,用于對(duì)列的應(yīng)用,動(dòng)態(tài)公式支持下面的引用變量:
{r} - 當(dāng)前行變量
{2}, {-1} - 當(dāng)前行的偏移位置
如果要匯總一些行列,可以使用&=&=Sum(C{r}:F{r})這樣的動(dòng)態(tài)變量來實(shí)現(xiàn)。
那如果是對(duì)同一列,不同行的字段進(jìn)行匯總呢?,那樣就更方便,不用這么復(fù)雜了,你只要使用普通的匯總函數(shù)如=Sum(C3:C4)這樣的格式,就可以了,如果行動(dòng)態(tài)增加,Excel會(huì)自動(dòng)調(diào)整Sum函數(shù)里面的行列引用了,可能最后輸出會(huì)變?yōu)?Sum(C3:C11)這樣了。
匯總格式變量
可以通過group:normal/merge/repeat 來控制匯總合并等格式的輸出,如使用兩者的例子:
&=Customers.CustomerID(group:merge)
&=Employees.EmployeeID(group:normal,skip:1)
出來的報(bào)表如下所示:
subtotalN函數(shù)
分別代表1=AVERAGE, 2=COUNT,3=COUNTA, 4=MAX, 5=MIN,...9=SUM等等
該函數(shù)是用來執(zhí)行一系列匯總計(jì)算的函數(shù),N從1~11subtotalN:Ref,其中Ref代表匯總的指定列
例如,&=Products.Units(subtotal9:Products.ProductID) 表示基于Units列進(jìn)行數(shù)據(jù)匯總統(tǒng)計(jì),統(tǒng)計(jì)到ProductID上來。
例如,&=Table1.ColumnD(subtotal9:Table1.ColumnA&Table1.ColumnB) ,則表示基于ColumnD列進(jìn)行匯總統(tǒng)計(jì),統(tǒng)計(jì)到ColumnA和ColumnB的分組條件上。
本篇由于篇幅原因,介紹到這里,下篇繼續(xù)探討基于模板生成的報(bào)表內(nèi)容,包括利用對(duì)象動(dòng)態(tài)創(chuàng)建行列以及公式,使用Style等方面,并結(jié)合實(shí)際復(fù)雜的報(bào)表例子,對(duì)基于Aspose.Cell報(bào)表內(nèi)容進(jìn)行進(jìn)一步的實(shí)戰(zhàn)分析探討。
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請(qǐng)務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請(qǐng)郵件反饋至chenjj@fc6vip.cn
文章轉(zhuǎn)載自:網(wǎng)絡(luò)轉(zhuǎn)載