ASP.NETでExcelを生成する際の問題点と改善方法

4185 ワード

まず方法を見てみましょう(その中でいくつかの判断と拡張を省略しました):
Excelの古いコードを生成
 
  
///
/// EXCEL
///

///
///
///
///
public static void ExExcel(List objList, string FileName, Dictionary columnInfo)
{

if (columnInfo.Count == 0) { return; }
if (objList.Count == 0) { return; }
// EXCEL HTML
string excelStr = "";

Type myType = objList[0].GetType();
//
List myPro = new List();
foreach (string cName in columnInfo.Keys)
{
PropertyInfo p = myType.GetProperty(cName);
if (p != null)
{
myPro.Add(p);
excelStr += columnInfo[cName] + "\t";
}
}
//
if (myPro.Count == 0) { return; }
excelStr += "
";

foreach (T obj in objList)
{
foreach (PropertyInfo p in myPro)
{
excelStr += p.GetValue(obj, null) + "\t";
}
excelStr += "
";
}

// EXCEL
HttpResponse rs = System.Web.HttpContext.Current.Response;
rs.ContentEncoding = System.Text.Encoding.GetEncoding("GB2312");
rs.AppendHeader("Content-Disposition", "attachment;filename=" + FileName);
rs.ContentType = "application/ms-excel";
rs.Write(excelStr);
rs.End();
}

この時になったら、問題の所在を見抜く友达がいると思います.
この方法では,Excelのデータ量が大きくない場合は問題なく,データ量が大きくなると問題が発生する.メソッドにはstringタイプの変数が定義されているので、Excelに埋め込む必要がある内容を重ね合わせます.stringタイプのデータに対して+=操作を用いることはstringを用いることに相当する.Concatメソッド接続文字列.+=操作を1回行うたびに、新しい文字列が生成されます.必然的にメモリが開きます.このような操作が多ければメモリが消費され、OutOfMemoryExceptionが生成されます.
問題点が分かりました.改善も簡単です.それはStringBuilderを利用してExcelに記入する必要がある内容を重ねて、改善後のコードは以下の通りです.
改良後のExcelのコード生成
 
  
///
/// EXCEL
///

///
///
///
///
public static void ExExcel(List objList, string FileName, Dictionary columnInfo)
{

if (columnInfo.Count == 0) { return; }
if (objList.Count == 0) { return; }
// EXCEL HTML
StringBuilder excelStr = new StringBuilder(objList.Count * columnInfo.Count);

Type myType = objList[0].GetType();
//
List myPro = new List();
foreach (string cName in columnInfo.Keys)
{
PropertyInfo p = myType.GetProperty(cName);
if (p != null)
{
myPro.Add(p);
excelStr.Append(columnInfo[cName]).Append("\t");
}
}
//
if (myPro.Count == 0) { return; }
excelStr.Append("
");

foreach (T obj in objList)
{
foreach (PropertyInfo p in myPro)
{
excelStr.Append(p.GetValue(obj, null)).Append("\t");
}
excelStr.Append("
");
}

// EXCEL
HttpResponse rs = System.Web.HttpContext.Current.Response;
rs.ContentEncoding = System.Text.Encoding.GetEncoding("GB2312");
rs.AppendHeader("Content-Disposition", "attachment;filename=" + FileName);
rs.ContentType = "application/ms-excel";
rs.Write(excelStr);
rs.End();
}
}

StringBuilder excelStr=new StringBuilder(objList.Count*columnInfo.Count);StringBuilderをよりよく使用できるように、事前割り当ての開始サイズを指定します.これで、改善が完了しました.
また、反射がパフォーマンスに影響すると思う場合は、式ツリーに変更したり、limitを使用したりすることができます.