讀取或生成EXCEL資料的方法有很多,一般常見的有:
1.通過OFFICE EXCEL元件,優點:讀取與生成EXCEL檔案友善,缺點:伺服器上必須安裝OFFICE軟體,且程序無法及時釋放
2.通過第三方元件(比如:NPOI),優點:無需安裝OFFICE軟體,缺點:需要引入第三方元件,當然這個還是比較強的
3.通過把EXCEL當成資料庫,連接配接後運用SQL語句讀取,寫入的話就自行拼接成HTML表格,優點:無需另外的元件,缺點:需要會SQL及拼接HTML表格較麻煩;
三種方法我都有用過,若開發BS網站程式,建議采用第二種、第三種方法,若開發CS結構,建議采用第一種或第二種;
以下是我針對BS端寫的一個ExcelHelper通用類,可用于讀取或生成資料,比較友善,技術原理是上述的第三種方法,代碼如下,可能存在缺陷,高手見諒:
namespace ASOTS.Models
{
public abstract class ExcelHelper
{
/// <summary>
/// 擷取EXCEL中指定sheet内容
/// </summary>
/// <returns></returns>
public static DataTable GetTableFromExcel(string filePath, string fileExt, string tableName, int colsCount)
{
string connstr = null;
if (fileExt == ".xls")
{
connstr = "Provider = Microsoft.Jet.OLEDB.4.0 ; Data Source =" + filePath + ";Extended Properties='Excel 8.0;HDR=Yes;IMEX=1'";
}
else
{
connstr = "Provider = Microsoft.ACE.OLEDB.12.0 ; Data Source =" + filePath + ";Extended Properties='Excel 12.0;HDR=Yes;IMEX=1'";
}
using (OleDbConnection excelConn = new OleDbConnection(connstr))
{
excelConn.Open();
//擷取EXCEL架構資訊
DataTable schemaTable = excelConn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new Object[] { null, null, null, "TABLE" });
//判斷指定sheet名是否存在
DataView schemaView = new DataView(schemaTable);
schemaView.RowFilter = "TABLE_NAME='" + tableName + "$'";
schemaTable = schemaView.ToTable();
if (schemaTable != null && schemaTable.Rows.Count > 0)
{
DataTable schemaTable_Cols = excelConn.GetOleDbSchemaTable(OleDbSchemaGuid.Columns, new object[] { null, null, tableName + "$", null });
schemaView = new DataView(schemaTable_Cols);
schemaView.RowFilter = "ORDINAL_POSITION<=" + colsCount.ToString();
schemaView.Sort = "ORDINAL_POSITION asc";
schemaTable_Cols = schemaView.ToTable();
string selectCols = "";
for (int i = 0; i < schemaTable_Cols.Rows.Count; i++)
{
selectCols += "," + schemaTable_Cols.Rows[i]["COLUMN_NAME"].ToString();
}
selectCols = selectCols.Substring(1);
//查詢sheet中的資料
string strSql = "select " + selectCols + " from [" + tableName + "$]";
OleDbDataAdapter da = new OleDbDataAdapter(strSql, excelConn);
DataSet ds = new DataSet();
da.Fill(ds, tableName);
excelConn.Close();
return ds.Tables[tableName];
}
else
{
excelConn.Close();
return null;
}
}
}
/// <summary>
/// 将資料模型集合對象生成HTML表格字元串
/// </summary>
/// <param name="data"></param>
/// <param name="tableAttributes"></param>
/// <param name="headers"></param>
/// <returns></returns>
public static string SetDataToHtmlTable(IEnumerable data, string tableAttributes, params KeyValuePair<string, string>[] headers)
{
StringBuilder htmlTableBuilder = new StringBuilder();
htmlTableBuilder.AppendFormat("<table {0}>", tableAttributes);
if (data.GetEnumerator().Current == null)
{
throw new Exception("沒有擷取到任何資料!");
}
Type t = data.GetEnumerator().Current.GetType();
string[] cellIndexs = new string[headers.Count()];
htmlTableBuilder.Append("<tr>");
for (int i = 0; i < headers.Count(); i++)
{
cellIndexs[i] = headers[i].Key;
htmlTableBuilder.AppendFormat("<th>{0}</th>", headers[i].Value);
}
htmlTableBuilder.Append("</tr>");
foreach (var item in data)
{
htmlTableBuilder.Append("<tr>");
for (int i = 0; i < cellIndexs.Length; i++)
{
object pValue = t.GetProperty(cellIndexs[i]).GetValue(item, null);
htmlTableBuilder.AppendFormat("<td>{0}</td>", pValue);
}
htmlTableBuilder.Append("</tr>");
}
htmlTableBuilder.Append("</table>");
return htmlTableBuilder.ToString();
}
/// <summary>
/// 将DataTable對象生成HTML表格字元串
/// </summary>
/// <param name="data"></param>
/// <param name="tableAttributes"></param>
/// <param name="headers"></param>
/// <returns></returns>
public static string SetDataToHtmlTable(DataTable dataTable, string tableAttributes, params KeyValuePair<string, string>[] headers)
{
StringBuilder htmlTableBuilder = new StringBuilder();
htmlTableBuilder.AppendFormat("<table {0}>", tableAttributes);
htmlTableBuilder.Append("<tr>");
for (int i = 0; i < headers.Count(); i++)
{
htmlTableBuilder.AppendFormat("<th>{0}</th>", headers[i].Value);
}
htmlTableBuilder.Append("</tr>");
foreach (DataRow row in dataTable.Rows)
{
htmlTableBuilder.Append("<tr>");
for (int i = 0; i < headers.Count(); i++)
{
htmlTableBuilder.AppendFormat("<td>{0}</td>", row[headers[i].Key]);
}
htmlTableBuilder.Append("</tr>");
}
htmlTableBuilder.Append("</table>");
return htmlTableBuilder.ToString();
}
}
public class KeyValueList<TKey, TValue> : List<KeyValuePair<TKey, TValue>>
{
public void Add(TKey key, TValue value)
{
base.Add(new KeyValuePair<TKey, TValue>(key, value));
}
}
}
調用方法如下:
//讀資料
DataTable resultTable = ExcelHelper.GetTableFromExcel(saveFilePath, fileExt, "data", 10);
//生成表格(以下是MVC調用,WEBFORM同理)
KeyValueList<string, string> headers = new KeyValueList<string, string>() {
{"year","年 份"},
{"month","月 份"},
{"stage1count","一 階"},
{"stage2count","二 階"},
{"stage3count","三 階"},
{"stage4count","四 階"},
{"yearincount","一年内進廠"},
{"stagetotalcount","基盤客戶總數"},
{"stage1rate","一階占比"},
{"stage2rate","二階占比"},
{"stage3rate","三階占比"},
{"stage4rate","四階占比"}
};
string tableAttributes = "border='1' cellspacing='3' cellpadding='3'";
string htmlTable=ExcelHelper.SetDataToHtmlTable(model, tableAttributes, headers.ToArray());
byte[] b = System.Text.Encoding.UTF8.GetBytes(htmlTable);
return File(b, "application/vnd.ms-excel", string.Format("StageSummary_{0}_{1}_{2}.xls",orgcode,startym,endym));
其中:KeyValueList是我建立的一個集合類,主要用于生成表頭,以及表頭與資料列對應,之是以寫成類,是因為若直接使用:List<KeyValuePair<TKey, TValue>>,則無法直接使用集合初始化器,就必需得一個一個的添加對象,有些繁瑣,增加了ADD方法後,就可以直接用:new KeyValueList<string, string>() {{"",""},...}很友善,有人可能說為什麼不用SortedDictionary等現有排序類,原因是SortedDictionary是基于Key排序,而此處是采用ADD的先後順序來固定順序的。
更多IT相關資訊與技術文章,歡迎光臨我的個人網站:http://www.zuowenjun.cn/