在開發.NET應用中可能會遇到需要生成帶圖表(Chart)的Excel報表的需求,特別是在一些ASP.NET網站中,有時候我們并不能保證Web服務器上一定安裝了Office組件,所以使用微軟的Office來生成Excel并不保證在所有情況下都使用,有時候即使Web服務器上安裝了Office也會出現一些運行權限方面的原因到導致調用Excel組件生成Excel失敗,所以在這里介紹一種無需安裝Office并且無需較高權限就能生成Excel的方法。
EPPlus簡介
在介紹EPPlus之前,首先要介紹一下Office Open XML。以下文字來自于維基百科(網址:Office Open XML,有刪節):
Office Open XML(縮寫:Open XML、OpenXML或OOXML),是由Microsoft開發的一種以XML為基礎并以ZIP格式壓縮的電子文件,支持Word、Excel、Office Note、PPT等文件格式。OOXML在2006年12月成為了ECMA規范的一部分,編號為ECMA-376;并于2008年4月國際標準化組織(ISO)的表決,在兩個月公布為ISO/IEC 29500國際標準。從Microsoft Office 2007開始,Office Open XML文件格式已經成為Microsoft Office默認的文件格式。Microsoft Office 2010支持對ECMA-376標準文檔的讀操作,ISO/IEC 29500 Transitional的讀/寫,ISO/IEC 29500 Strict的讀取。Microsoft Office 2013同時支持ISO/IEC 29500 Strict的讀寫操作。
EPPlus就是一個通過Open XML方式來讀寫Office文件的開源.NET類庫,所以使用它生成Office文件完全不需要Microsoft Office(當然如果你需需要查看生成的文件就需要Office了)。它的官方網址是:http://epplus.codeplex.com/。如果需要體驗本文中提到的效果,需要從這個網址下載最新版本的類庫,我現在使用的這個名為EPPlus.dll類庫僅658K,非常方便部署。
代碼示例
為了演示EPPlus的用法,這里寫了一個簡單的例子,在這個例子里演示模擬了幾大公司實際業績與計劃業績的百分比,如果這個百分比大于95%則會將所在的單元格顯示為綠色,如果小于90%則會顯示為紅色,否則就顯示為黃色,并且還會生成一個圖標來直觀表示每月實際完成情況與計劃的百分比。
完整代碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | /* ? ******************************************************************************** ? * ? *????Project???????????A?report?project ? *????Module?Name???????Excel?Report ? *????Author????????????Zhou,?Jin-Qiao?(周金橋) ? *????Creation?Date?????[11/03/2013] ? *????Description???????Generate?Excel?Report?with?Chat?demo?by?Epplus ? *?? ? *?????Copyright?2013?zhoufoxcn. ? *?? ? ******************************************************************************** ? */ using ?System; using ?System.Data; using ?System.Drawing; using ?System.IO; using ?OfficeOpenXml; using ?OfficeOpenXml.Drawing.Chart; using ?OfficeOpenXml.Style; namespace ?ExcelReportApplication { ???? ///?<summary> ???? ///?使用EPPlus生成帶圖表(Chart)的Excel文件的例子,注意在運行的機器上無需安裝Office,因為EPPlus是使用基于OpenXML技術生成的Excel文件。 ???? ///?任何網站和個人均可在不對本代碼做任何修改的情況下轉載本文及本文中示例的代碼用于非商業用途,任何除去版權的行為均為侵權。 ???? ///?作者:周公(周金橋)? ???? ///?創建日期:2013-11-03? ???? ///?博客地址:http://blog.csdn.net/zhoufoxcn?http://zhoufoxcn.blog.51cto.com? ???? ///?新浪微博地址:http://weibo.com/zhoufoxcn ???? public ?class ?ExcelExportPage ???? { ???????? private ?static ?readonly ?string []?MonthNames?=? new ?string []?{? "一月" ,? "二月" ,? "三月" ,? "四月" ,? "五月" ,? "六月" ,? "七月" ,? "八月" ,? "九月" ,? "十月" ,? "十一月" ,? "十二月" }; ???????? //private?static?readonly?string[]?CommpanyNames?=?new?string[]?{?"Microsoft",?"IBM",?"Oracle",?"Amazon",?"Google",?"Facebook",?"Twitter",?"Paypal",?"Yahoo",?"HP"?}; ???????? private ?static ?readonly ?string []?CommpanyNames?=? new ?string []?{? "Microsoft" ,? "IBM" ,? "Oracle" ,? "Google" , "Yahoo" ,? "HP" ?}; ???????? static ?void ?Main( string []?args) ???????? { ???????????? ExcelExportPage.GenerateExcelReport(); ???????? } ???????? ///?<summary> ???????? ///?周公(周金橋)說明:這個方法就是主要演示如何生成帶圖表(Chart)的Excel文件的例子 ???????? ///?</summary> ???????? public ?static ?void ?GenerateExcelReport() ???????? { ???????????? string ?fileName?=? "ExcelReport-" +DateTime.Now.ToString( "yyyy_MM_dd_HHmmss" )?+? ".xlsx" ; ???????????? string ?reportTitle?=? "2013年度五大公司實際情況與原計劃的百分比" ; ???????????? FileInfo?file?=? new ?FileInfo( "C:\\" +fileName); ???????????? using ?(ExcelPackage?package?=? new ?ExcelPackage(file)) ???????????? { ???????????????? ExcelWorksheet?worksheet?=? null ; ???????????????? ExcelChartSerie?chartSerie?=? null ; ???????????????? ExcelLineChart?chart?=? null ; ???????????????? #region?research ???????????????? worksheet?=?package.Workbook.Worksheets.Add( "Data" ); ???????????????? DataTable?dataPercent?=?GetDataPercent(); ???????????????? //chart?=?Worksheet.Drawings.AddChart("ColumnStackedChart",?eChartType.Line)?as?ExcelLineChart; ???????????????? chart?=?worksheet.Drawings.AddChart( "ColumnStackedChart" ,?eChartType.LineMarkers)? as ?ExcelLineChart; //設置圖表樣式 ???????????????? chart.Legend.Position?=?eLegendPosition.Right; ???????????????? chart.Legend.Add(); ???????????????? chart.Title.Text?=?reportTitle; //設置圖表的名稱 ???????????????? //chart.SetPosition(200,?50);//設置圖表位置 ???????????????? chart.SetSize(800,?400); //設置圖表大小 ???????????????? chart.ShowHiddenData?=? true ; ???????????????? //chart.YAxis.MinorUnit?=?1; ???????????????? chart.XAxis.MinorUnit?=?1; //設置X軸的最小刻度 ???????????????? //chart.DataLabel.ShowCategory?=?true; ???????????????? chart.DataLabel.ShowPercent?=? true ; //顯示百分比 ???????????????? //設置月份 ???????????????? for ?( int ?col?=?1;?col?<=?dataPercent.Columns.Count;?col++) ???????????????? { ???????????????????? worksheet.Cells[1,?col].Value?=?dataPercent.Columns[col?-?1].ColumnName; ???????????????? } ???????????????? //設置數據 ???????????????? for ?( int ?row?=?1;?row?<=?dataPercent.Rows.Count;?row++) ???????????????? { ???????????????????? for ?( int ?col?=?1;?col?<=?dataPercent.Columns.Count;?col++) ???????????????????? { ???????????????????????? string ?strValue?=?dataPercent.Rows[row?-?1][col?-?1].ToString(); ???????????????????????? if ?(col?==?1) ???????????????????????? { ???????????????????????????? worksheet.Cells[row?+?1,?col].Value?=?strValue; ???????????????????????? } ???????????????????????? else ???????????????????????? { ???????????????????????????? double ?realValue?=? double .Parse(strValue); ???????????????????????????? worksheet.Cells[row?+?1,?col].Style.Fill.PatternType?=?ExcelFillStyle.Solid; ???????????????????????????? worksheet.Cells[row?+?1,?col].Style.Numberformat.Format?=? "#0\\.00%" ; //設置數據的格式為百分比 ???????????????????????????? worksheet.Cells[row?+?1,?col].Value?=?realValue; ???????????????????????????? if ?(realValue<?0.90d) //如果小于90%則該單元格底色顯示為紅色 ???????????????????????????? { ???????????????????????????????? worksheet.Cells[row?+?1,?col].Style.Fill.BackgroundColor.SetColor(Color.Red); ???????????????????????????? } ???????????????????????????? else ?if ?(realValue>=?0.90d?&&?realValue?<=?0.95d) //如果在90%與95%之間則該單元格底色顯示為黃色 ???????????????????????????? { ???????????????????????????????? worksheet.Cells[row?+?1,?col].Style.Fill.BackgroundColor.SetColor(Color.Yellow); ???????????????????????????? } ???????????????????????????? else ???????????????????????????? { ???????????????????????????????? worksheet.Cells[row?+?1,?col].Style.Fill.BackgroundColor.SetColor(Color.Green); //如果大于95%則該單元格底色顯示為綠色 ???????????????????????????? } ???????????????????????? } ???????????????????? } ???????????????????? //chartSerie?=?chart.Series.Add(worksheet.Cells["A2:M2"],?worksheet.Cells["B1:M1"]); ???????????????????? //chartSerie.HeaderAddress?=?worksheet.Cells["A2"]; ???????????????????? //chart.Series.Add()方法所需參數為:chart.Series.Add(X軸數據區,Y軸數據區) ???????????????????? chartSerie?=?chart.Series.Add(worksheet.Cells[row?+?1,?2,?row?+?1,?2?+?dataPercent.Columns.Count?-?2],?worksheet.Cells[ "B1:M1" ]); ???????????????????? chartSerie.HeaderAddress?=?worksheet.Cells[row?+?1,?1]; //設置每條線的名稱 ???????????????? } ???????????????? //因為假定每家公司至少完成了80%以上,所以這里設置Y軸的最小刻度為80%,這樣使圖表上的折線更清晰 ???????????????? chart.YAxis.MinValue?=?0.8d; ???????????????? //chart.SetPosition(200,?50);//可以通過制定左上角坐標來設置圖表位置 ???????????????? //通過指定圖表左上角所在的行和列及對應偏移來指定圖表位置 ???????????????? //這里CommpanyNames.Length?+?1及3分別表示行和列 ???????????????? chart.SetPosition(CommpanyNames.Length?+?1,?10,?3,?20); ???????????????? #endregion?research ???????????????? package.Save(); //保存文件 ???????????? } ???????? } ???????? ///?<summary> ???????? ///?生成數據,由于這一步不是主要邏輯,所以采用隨機生成數據的方式,實際中可根據需要從數據庫或其它數據源中讀取需要的數據 ???????? ///?</summary> ???????? ///?<returns></returns> ???????? private ?static ?DataTable?GetDataPercent() ???????? { ???????????? DataTable?data?=? new ?DataTable(); ???????????? DataRow?row?=? null ; ???????????? Random?random= new ?Random(); ???????????? data.Columns.Add( new ?DataColumn( "公司名" ,? typeof ( string ))); ???????????? foreach ( string ?monthName? in ?MonthNames){ ???????????????? data.Columns.Add( new ?DataColumn(monthName,? typeof ( double ))); ???????????? } ???????????? //每個公司每月的百分比表示完成的業績與計劃的百分比 ???????????? for ?( int ?i?=?0;?i?<?CommpanyNames.Length;?i++) ???????????? { ???????????????? row?=?data.NewRow(); ???????????????? row[0]?=?CommpanyNames[i]; ???????????????? for ?( int ?j?=?1;?j?<=?MonthNames.Length;?j++) ???????????????? { ???????????????????? //這里采用了隨機生成數據,但假定每家公司至少完成了計劃的85%以上 ???????????????????? row[j]?=?0.85d?+?random.Next(0,?15)?/?100d; ???????????????? } ???????????????? data.Rows.Add(row); ???????????? } ????????????????????????? ????????????? return ?data; ???????? } ???? } } |
最終生成的Excel文件內容如下:
本文轉自周金橋51CTO博客,原文鏈接:http://blog.51cto.com/zhoufoxcn/1319741?,如需轉載請自行聯系原作者