テンプレートを使ったexcelファイル出力方法(C#)-3.実装篇(続き)
テンプレート(excelファイル)でフォーマット(見た目)を定義し、該当テンプレートで定義した項目にデータを書き込むことによってexcelファイルを作成するプログラムの設計方法
「テンプレートを使ったexcelファイル出力方法(C#)-1.設計」と
実装方法
「テンプレートを使ったexcelファイル出力方法(C#)-2.実装篇」
について解説しました。
今回は残りのクラス「CTemplatedExcelUtil」と、せっかく作ったこのプログラムの使用方法について解説していきます。
クラスCTemplatedExcelUtil
■ CTemplatedExcelUtil.cs
今回開発する機能で、このクラスは一番重要なクラスです。
「呼出し側」のソースでは、このクラスの使い方さえマスタすれば十分です。
又、インタフェース(Interface、他のモジュールに提供する「公開メソッド」のこと。)は「簡単、簡潔」に定義する考え方により、
このクラスでは「CreateExcel()」メソッドのみ外部に公開しています。
□ソース抜粋1 ==========
/// <summary>
/// テンプレートexcelファイルからexcelファイルを新規作成する。
/// ※テンプレートexcelのfmt: excel97-2003(.xls) / excel2007以降(.xlsx)
/// 作成するexcelのfmt: excel2007以降(.xlsx)のみ
///
/// テンプレート ------------> 新しいexcel
/// ↑
/// データ
/// ※データを書き込むセルの定義方法:
/// ${groupName.dataName} : 単項目の場合
/// ${groupName[].dataName} : リスト項目の場合
/// eg.
/// ${header.title}
/// ${header.createDate}
/// ${dtl[].itmName} / ${dtl[].color
///
/// ※isMergeCol:bool
/// リスト項目の場合、縦方向で隣接するセルの値が空(null/"")の場合について、
/// true: 合併する (e.g. itm列の1,2,3行目 / clr列の1,2行目)
/// false: 合併しない
///
/// No. itm. clr. 1 2 3 4 5
/// 1 AAA red 78 90 88 69 80
/// 2 90
/// 3 blue 90
/// 4 BBB red 50
///
/// </summary>
/// <param name="templateExcelPath">テンプレートexcelファイルのフルーパス</param>
/// <param name="newExcelPath">新規作成するexcelファイルのフルーパス</param>
/// <param name="data">データ</param>
/// <param name="isMergeCol">リスト項目の場合、縦方向で隣接する空値(""/null)のセルを合併するかどうか
/// true:合併する; false:合併しない
/// </param>
public void CreateExcel( string templateExcelPath,
string newExcelPath,
CTemplatedExcelData data,
bool isMergeCol=true)
{
...
CreateExcel()メソッドの定義部分です。
テンプレートファイルパス、新規作成するexcelファイルパス、出力するデータ格納インスタンス、isMergeColを引数として呼び出すことができます。
最終的にはDLLを作成するので、「呼出し側」では、このメソッドを呼び出すだけで、「テンプレートを使ったexcelファイルの作成」処理ができるようになります。
メソッドの上部にコメントを長く書いていますが、これは筆者の習慣です。
本機能を利用するためには、テンプレートファイルを先に作成する必要があるが、どうやって作成するか?などコメントに記載しておくと、後々便利になります。
このように、本機能を呼び出す場合に必要なことは、基本的にコメントに書くことにしています。
□ソース抜粋2 ==========
//引数チェック
isExcelFile(templateExcelPath);
isExcelFile(newExcelPath);
//存在チェック
if (!File.Exists(templateExcelPath))
{
//存在しない
string classFullName = this.GetType().Name;
string curMethodName = "CreateExcel()"; // MethodBase.GetCurrentMethod().Name;
string msg = CCommon.GetMessage(CConst.RK_E20002, templateExcelPath);
//エラーログ
CLogger.ErrorLog(CLogLevel.ERROR,
classFullName,
curMethodName,
msg,
null);
throw new ApplicationException(CConst.RK_E20002 + " - " + msg);
}//end if
テンプレートファイルパス、結果excelファイルパスを引数としてもらうので、ここでは渡されたパスがexcel形式のファイルかどうかのチェックと、テンプレートファイルの存在チェックを行っています。
□ソース抜粋3 ==========
File.Copy(templateExcelPath, newExcelPath, true);
テンプレートファイルをコピーし、newExcelPathで指定したexcelファイルを新規作成しています。
□ソース抜粋4 ==========
if (!data.HaveData(CItemType.Any)) //データ無し
{
string classFullName = this.GetType().Name;
string curMethodName = "CreateExcel()"; // MethodBase.GetCurrentMethod().Name;
string msg = CCommon.GetMessage(CConst.RK_E20003, null);
//警告ログ
CLogger.ErrorLog(CLogLevel.WARN,
classFullName,
curMethodName,
msg,
null);
return;
}//end if
出力するデータがない場合は、もう処理続行する意味ないので、エラーメッセージを出してから処理終了させています。
□ソース抜粋5 ==========
//テンプレート解析
CTemplatedExcel template = null;
analysisTemplatedExcel(workbook, out template);
テンプレートを解析し、結果をCTemplatedExcel型の変数templateに保存します。
□ソース抜粋6 ==========
//テンプレート解析結果をもとに、値を設定
setValueBasedTemplatedExcel(workbook, template, data, isMergeCol);
//ブック保存
try
{
using (FileStream fs = new FileStream(newExcelPath, FileMode.Create))
{
workbook.Write(fs);
workbook.Close();
workbook = null;
}
}
テンプレート解析結果をもとに、データを設定し、最後にworkbook.Write(fs)で結果excelファイルを作成しています。
□全体ソース ==========
using NPOI.SS.UserModel;
using NPOI.SS.Util;
using NPOI.XSSF.UserModel;
using System;
using System.Collections.Generic;
using System.IO;
namespace jdr_core.templatedExcel
{
/// <summary>
/// テンプレートExcel用utility
/// </summary>
public class CTemplatedExcelUtil
{
/// <summary>
/// テンプレートexcelファイルからexcelファイルを新規作成する。
/// ※テンプレートexcelのfmt: excel97-2003(.xls) / excel2007以降(.xlsx)
/// 作成するexcelのfmt: excel2007以降(.xlsx)のみ
///
/// テンプレート ------------> 新しいexcel
/// ↑
/// データ
/// ※データを書き込むセルの定義方法:
/// ${groupName.dataName} : 単項目の場合
/// ${groupName[].dataName} : リスト項目の場合
/// eg.
/// ${header.title}
/// ${header.createDate}
/// ${dtl[].itmName} / ${dtl[].color
///
/// ※isMergeCol:bool
/// リスト項目の場合、縦方向で隣接するセルの値が空(null/"")の場合について、
/// true: 合併する (e.g. itm列の1,2,3行目 / clr列の1,2行目)
/// false: 合併しない
///
/// No. itm. clr. 1 2 3 4 5
/// 1 AAA red 78 90 88 69 80
/// 2 90
/// 3 blue 90
/// 4 BBB red 50
///
/// </summary>
/// <param name="templateExcelPath">テンプレートexcelファイルのフルーパス</param>
/// <param name="newExcelPath">新規作成するexcelファイルのフルーパス</param>
/// <param name="data">データ</param>
/// <param name="isMergeCol">リスト項目の場合、縦方向で隣接する空値(""/null)のセルを合併するかどうか
/// true:合併する; false:合併しない
/// </param>
public void CreateExcel( string templateExcelPath,
string newExcelPath,
CTemplatedExcelData data,
bool isMergeCol=true)
{
//Properties.Resource1.E20001
//引数チェック
isExcelFile(templateExcelPath);
isExcelFile(newExcelPath);
//存在チェック
if (!File.Exists(templateExcelPath))
{
//存在しない
string classFullName = this.GetType().Name;
string curMethodName = "CreateExcel()"; // MethodBase.GetCurrentMethod().Name;
string msg = CCommon.GetMessage(CConst.RK_E20002, templateExcelPath);
//エラーログ
CLogger.ErrorLog(CLogLevel.ERROR,
classFullName,
curMethodName,
msg,
null);
throw new ApplicationException(CConst.RK_E20002 + " - " + msg);
}//end if
//テンプレートをコピーし、出力excelファイルを動的に新規作成
if (!newExcelPath.Equals(templateExcelPath))
{
try
{
File.Copy(templateExcelPath, newExcelPath, true);
}
catch(Exception e) //コピーエラー
{
string classFullName = this.GetType().Name;
string curMethodName = "CreateExcel()"; // MethodBase.GetCurrentMethod().Name;
string msg = CCommon.GetMessage(CConst.RK_E20005, templateExcelPath, newExcelPath);
//エラーログ
CLogger.ErrorLog(CLogLevel.ERROR,
classFullName,
curMethodName,
msg,
e);
throw new ApplicationException(CConst.RK_E20005 + "-" + msg);
}
}//end if
if (!data.HaveData(CItemType.Any)) //データ無し
{
string classFullName = this.GetType().Name;
string curMethodName = "CreateExcel()"; // MethodBase.GetCurrentMethod().Name;
string msg = CCommon.GetMessage(CConst.RK_E20003, null);
//警告ログ
CLogger.ErrorLog(CLogLevel.WARN,
classFullName,
curMethodName,
msg,
null);
return;
}//end if
//open the excel file
//IWorkbook workbook = WorkbookFactory.Create(newExcelPath);
IWorkbook workbook = null;
try
{
using (FileStream fs = new FileStream(newExcelPath, FileMode.Open, FileAccess.ReadWrite))
{
workbook = WorkbookFactory.Create(fs);
}
}
catch(Exception e) //ファイル読み込みエラー
{
string classFullName = this.GetType().Name;
string curMethodName = "CreateExcel()"; // MethodBase.GetCurrentMethod().Name;
string msg = CCommon.GetMessage(CConst.RK_E20006, newExcelPath);
//エラーログ
CLogger.ErrorLog(CLogLevel.ERROR,
classFullName,
curMethodName,
msg,
e);
throw new ApplicationException(CConst.RK_E20006 + "-" + msg);
}
int sheetCnt = workbook.NumberOfSheets;
//テンプレート解析
CTemplatedExcel template = null;
analysisTemplatedExcel(workbook, out template);
if (!template.HaveData()) //定義情報無し
{
string classFullName = this.GetType().Name;
string curMethodName = "CreateExcel()"; // MethodBase.GetCurrentMethod().Name;
string msg = CCommon.GetMessage(CConst.RK_E20004, null);
//警告ログ
CLogger.ErrorLog(CLogLevel.WARN,
classFullName,
curMethodName,
msg,
null);
return;
}
//テンプレート解析結果をもとに、値を設定
setValueBasedTemplatedExcel(workbook, template, data, isMergeCol);
//ブック保存
try
{
using (FileStream fs = new FileStream(newExcelPath, FileMode.Create))
{
workbook.Write(fs);
workbook.Close();
workbook = null;
}
}
catch(Exception e) //書き込みエラー
{
string classFullName = this.GetType().Name;
string curMethodName = "CreateExcel()"; // MethodBase.GetCurrentMethod().Name;
string msg = CCommon.GetMessage(CConst.RK_E20007, newExcelPath);
//エラーログ
CLogger.ErrorLog(CLogLevel.ERROR,
classFullName,
curMethodName,
msg,
e);
throw new ApplicationException(CConst.RK_E20007 + "-" + msg);
}
}//end createExcel()
/// <summary>
/// テンプレートのセルを解析
/// </summary>
/// <param name="rowIdx"></param>
/// <param name="colIdx"></param>
/// <param name="curCell"></param>
/// <param name="templatedCell"></param>
/// <param name="itmTyp"></param>
/// <returns></returns>
private bool AnalysisTemplatedCell(int rowIdx,
int colIdx,
ICell curCell,
out CTemplatedCell templatedCell,
out CItemType itmTyp)
{
bool ret = true;
itmTyp = CItemType.Normal;
templatedCell = null;
//テンプレート定義のセルは必ず ${grpName.valueName}形式なので、セルタイプは文字列に決まってる
if (!curCell.CellType.Equals(CellType.String))
{
return false;
}
string cellVal = curCell.StringCellValue;
if(CString.IsNullOrEmpty(cellVal, true))
{
return false;
}
cellVal = cellVal.Trim();
if(!(cellVal.StartsWith(CConst.TEMPLATE_CELL_ST)
&& cellVal.EndsWith(CConst.TEMPLATE_CELL_ED)))
{
return false;
}
string tmpVal = cellVal.Replace(CConst.TEMPLATE_CELL_ST, "").Replace(CConst.TEMPLATE_CELL_ED, "");
string[] sep = new string[] { CConst.TEMPLATE_CELL_SEPARATOR };
string[] tmpStr = tmpVal.Split(sep, StringSplitOptions.None);
if (tmpStr.Length < 2)
return false;
string groupName = tmpStr[0];
string valueName = tmpStr[1];
if (groupName.EndsWith(CConst.TEMPLATE_CELL_LISTGROUP))
{
//リスト項目
groupName = groupName.Replace(CConst.TEMPLATE_CELL_LISTGROUP, "");
itmTyp = CItemType.List;
}
templatedCell = new CTemplatedCell(groupName, valueName, rowIdx, colIdx);
return ret;
}
/// <summary>
/// テンプレートexcelを解析する
/// </summary>
/// <param name="workbook">テンプレートexcel</param>
/// <param name="template">解析結果(null:結果無し; 以外:解析結果)</param>
private void analysisTemplatedExcel(IWorkbook workbook, out CTemplatedExcel template)
{
int sheetCnt = workbook.NumberOfSheets;
if (sheetCnt == 0)
{
template = null;
return;
}
else
{
template = new CTemplatedExcel();
}
//テンプレートexcel解析
for(int sheetIdx=0; sheetIdx < sheetCnt; sheetIdx++)
{
ISheet curSheet = workbook.GetSheetAt(sheetIdx);
for(int rowIdx = 0; rowIdx < curSheet.LastRowNum; rowIdx++)
{
IRow curRow = curSheet.GetRow(rowIdx);
if (curRow == null) //該当行定義なし
{
continue;
}//end if
//該当行を解析
for(int colIdx = 0; colIdx < curRow.LastCellNum; colIdx++)
{
ICell curCell = curRow.GetCell(colIdx);
if (curCell == null) //該当cell定義なし
{
continue;
}
//該当セルを解析
CTemplatedCell templatedCell = null;
CItemType itmTyp = CItemType.Any;
if (!AnalysisTemplatedCell(rowIdx, colIdx, curCell, out templatedCell, out itmTyp))
continue;
//セル定義を登録
switch (itmTyp)
{
case CItemType.Normal:
template.AddNormalData(sheetIdx, templatedCell);
break;
case CItemType.List:
template.AddListData(sheetIdx, templatedCell);
break;
}//end switch
}//col loop
}//行loop
}//シートloop
}
/// <summary>
/// 指定したcellに値を設定する
/// </summary>
/// <param name="cell"></param>
/// <param name="value"></param>
private void SetCellValue(ICell cell, CTemplatedExcelDataValue value)
{
//該当セルに値を設定
//cell.SetCellValue(val);
switch (value.ValueType)
{
case CTemplatedExcelDataValueType.B:
cell.SetCellValue(value.BoolValue);
break;
case CTemplatedExcelDataValueType.DT:
cell.SetCellValue(value.DateTimeValue);
break;
case CTemplatedExcelDataValueType.DB:
cell.SetCellValue(value.DoubleValue);
break;
default: //string型
cell.SetCellValue(value.StringValue);
break;
}//end switch
}
/// <summary>
/// 普通項目値を設定する
/// </summary>
/// <param name="curSheet">シートobj</param>
/// <param name="templatedItemOfCurSheet">テンプレート定義情報</param>
/// <param name="data">データ情報</param>
private void setNormalValue(ISheet curSheet,
CTemplatedItem templatedItemOfCurSheet,
CTemplatedExcelData data)
{
List<int> normalItmRowLst = templatedItemOfCurSheet.NormalItemRow;
foreach(int rowIdx in normalItmRowLst)
{
//行obj取得
IRow curRow = curSheet.GetRow(rowIdx);
if (curRow == null)
continue;
List<CTemplatedCell> itmLst = templatedItemOfCurSheet.GetNormalItem(rowIdx);
foreach(CTemplatedCell tc in itmLst)
{
int colIdx = tc.ColIndex;
//セル取得
ICell cell = curRow.GetCell(colIdx);
if (cell == null)
continue;
//該当セルの値を取得
CTemplatedExcelDataValue val = data.GetNormalData(tc.GroupName, tc.ValueName);
//該当セルに値を設定
//cell.SetCellValue(val);
if (val != null)
SetCellValue(cell, val);
}//end foreach
}//end foreach
}//end setNormalValue()
/// <summary>
/// リスト項目値を設定する
/// </summary>
/// <param name="curSheet">シートobj</param>
/// <param name="templatedItemOfCurSheet">テンプレート定義情報</param>
/// <param name="data">データ情報</param>
/// <param name="isMergeCol">縦方向隣接セル結合フラグ</param>
private void setListValue(ISheet curSheet,
CTemplatedItem templatedItemOfCurSheet,
CTemplatedExcelData data,
bool isMergeCol)
{
//リスト項目の行番リスト(昇順)
List<int> listItmRowLst = templatedItemOfCurSheet.ListItemRow;
for(int iLoop = listItmRowLst.Count - 1; iLoop >= 0; iLoop--)
{
//リスト項目の行番
int curRowIdx = listItmRowLst[iLoop];
//行obj取得
IRow curRow = curSheet.GetRow(curRowIdx);
if (curRow == null) //解析結果なので、該当行がないはず無いが、念のため
continue;
//該当行でのリスト項目の定義情報すべて
List<CTemplatedCell> itmLst = templatedItemOfCurSheet.GetListItem(curRowIdx);
if (itmLst.Count == 0) //リスト項目無し時、次の行へ
continue;
//1行に定義するリスト項目は、すべて同じグループ名である前提
//先頭項目のグループ名を取得し、全項目に適用する
string grpName = itmLst[0].GroupName; //リスト項目のグループ名
//リスト項目のグループ名を指定し、該当グループの値をすべて取得
IList<IDictionary<string, CTemplatedExcelDataValue>> listData4CurGrp =
data.GetListData(grpName);
if (listData4CurGrp==null || listData4CurGrp.Count == 0) //該当グループの値がない場合、処理無し
continue;
//リスト行の場合、追加した行の各セルのスタイルは真上のセルに準拠するため、真上の行を一旦保持する必要がある
IRow preRow = null;
List<CMergeBlock> mergeHori = new List<CMergeBlock>(); //横方向の行結合情報
List<CMergeBlock> mergeVer = new List<CMergeBlock>(); //縦方向の行結合情報
//該当リストの値の行数で、作成すべきリストの行数を決定
int listRowCnt = listData4CurGrp.Count; //リスト行数
for(int rowOffset=0; rowOffset < listRowCnt; rowOffset++) //リスト行数分ループ(base行番:curRowIdxに対するoffset数)
{
if (rowOffset == 0) //リスト行の先頭行
{
//先頭行の場合(上で取得したcurRowを使用)
//横方向の結合情報取得
int mbCnt = curSheet.NumMergedRegions;
for(int i=0; i < mbCnt; i++)
{
CellRangeAddress cra = curSheet.GetMergedRegion(i);
if(cra.FirstRow==curRowIdx && cra.LastRow == curRowIdx)
{
CMergeBlock cmb = new CMergeBlock();
cmb.StRowIdx = curRowIdx;
cmb.EdRowIdx = curRowIdx;
cmb.StColIdx = cra.FirstColumn;
cmb.EdColIdx = cra.LastColumn;
mergeHori.Add(cmb);
}
}//end for
}
else //リスト行の先頭行以外
{
//先頭行以外(直前の行をコピー、追加)
//curSheet.CreateRow(curRowIdx + rowOffset);
//curRow = curSheet.CopyRow(curRowIdx + rowOffset - 1, curRowIdx + rowOffset); //NG
curSheet.ShiftRows(curRowIdx + rowOffset, curSheet.LastRowNum + 1, 1);
curRow = curSheet.GetRow(curRowIdx + rowOffset);
if (curRow == null)
{
curRow = curSheet.CreateRow(curRowIdx + rowOffset);
}
//横方向の行結合
foreach(CMergeBlock mb in mergeHori)
{
CellRangeAddress cra = new CellRangeAddress(curRowIdx + rowOffset,
curRowIdx + rowOffset,
mb.StColIdx,
mb.EdColIdx);
curSheet.AddMergedRegion(cra);
}
}//end if
foreach(CTemplatedCell tc in itmLst) //リストの行内の項目数分loop
{
//リスト行の全セルのgroup nameは同じである前提
if (!tc.GroupName.Equals(grpName))
continue;
//該当項目の列番
int colIdx = tc.ColIndex;
//セル取得
ICell cell = curRow.GetCell(colIdx);
if (cell == null)
{
//直全の行のコピーinsertなので、あるはずたが、念のため
cell = curRow.CreateCell(colIdx);
}
//先頭行以外、追加作成した行なので、スタイルは真上の行を継承
if (rowOffset > 0)
{
if (preRow != null)
{
ICell preCell = preRow.GetCell(colIdx);
if (preCell != null)
{
cell.CellStyle = preCell.CellStyle;
}
}
//結合セルの場合、ほかの結合セルのスタイルもすべて継承>>>>>>>>>>>>>>>
CMergeBlock tmpMb = null;
foreach (CMergeBlock mb in mergeHori)
{
//該当セルが結合セルなのかを判定
//定義情報のあるセルをメインに処理するので、結合セルだとしたら、必ず先頭セルである。
if(mb.StColIdx == colIdx)
{
tmpMb = mb;
break;
}
}
if (tmpMb != null) //結合セルである場合
{
// 結合セルが、 A B C Dである例
// _________________________
// | A | B | C | D |
// ------------------------------------
// 先頭セルAは上でスタイル継承済みなので処理しない
// B, C, Dセルのスタイルを継承
for (int tmpColIdx = tmpMb.StColIdx + 1; tmpColIdx <= tmpMb.EdColIdx; tmpColIdx++)
{
//真上のセル取得
ICell tmpPreCell = preRow.GetCell(tmpColIdx);
if (tmpPreCell == null) //ないはずないが、念のため
continue;
//該当行の対象セル取得
ICell tmpCell = curRow.GetCell(tmpColIdx);
if (tmpCell == null) //ない可能性有、新規作成
{
tmpCell = curRow.CreateCell(tmpColIdx);
}
//スタイル継承
tmpCell.CellStyle = tmpPreCell.CellStyle;
}//end for
}//end if
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
}
//該当行・該当セルの値を取得
CTemplatedExcelDataValue val = null;
listData4CurGrp[rowOffset].TryGetValue(tc.ValueName, out val);
//cell.SetCellValue(val);
if (val != null)
SetCellValue(cell, val);
}//end foreach
preRow = curRow;
}//end for
}//end for
}//end setListValue()
/// <summary>
/// 解析結果をもとに、値を設定する
/// ※縦方向隣接セル結合フラグ : true時
/// 縦方向隣接セルの値がnull or 空("")時、直上の値有セルと結合する
/// XXXX -
/// "" | 結合
/// "" _|
/// XXXX - 結合
/// "" _|
/// XXXX
/// XXXX
/// </summary>
/// <param name="workbook"></param>
/// <param name="template">テンプレート情報</param>
/// <param name="data">テンプレートデータ</param>
/// <param name="isMergeCol">縦方向隣接セル結合フラグ</param>
private void setValueBasedTemplatedExcel(IWorkbook workbook,
CTemplatedExcel template,
CTemplatedExcelData data,
bool isMergeCol)
{
List<int> sheetNumLst = template.SheetNumber;
foreach(int sheetNum in sheetNumLst)
{
//該当シートobj
ISheet curSheet = workbook.GetSheetAt(sheetNum);
//該当シートの定義情報
CTemplatedItem templatedItemOfCurSheet = template[sheetNum];
//普通項目定義情報設定
setNormalValue(curSheet, templatedItemOfCurSheet, data);
//リスト項目の値を設定
setListValue(curSheet, templatedItemOfCurSheet, data, isMergeCol);
}//シートloop
}
/// <summary>
/// excelファイルか?をチェック
/// </summary>
/// <param name="filePath">チェックするファイルフルーパス</param>
private void isExcelFile(string filePath)
{
string ext = Path.GetExtension(filePath);
ext = ext.ToUpper();
if(!ext.Equals(CConst.EXCEL_EXT_2003) && !ext.Equals(CConst.EXCEL_EXT_2007))
{
string classFullName = this.GetType().Name;
string curMethodName = "isExcelFile()"; // MethodBase.GetCurrentMethod().Name;
string msg = CCommon.GetMessage(CConst.RK_E20001, filePath);
//エラーログ
CLogger.ErrorLog(CLogLevel.ERROR,
classFullName,
curMethodName,
msg,
null);
throw new ApplicationException(CConst.RK_E20001 + " - " + msg);
}//end if
}//end isExcelFile()
}//end class
}//end namespace
これで、プログラム開発は完了しました。
まとめ
ソースを張り付けると文字数は一気に増えちゃいますね。この記事の文字数は35000を超えています。
というわけで、本機能を利用し、excelファイルを作成する方法は次回の記事にします。
では、バイバイ! Have a nice day!