---
lang: ja-jp
breaks: true
---
# C# NPOI を使用したExcelファイルに関するユーティリティークラス 2021-04-15
## 環境
* Visual Studio 2017
* Windows Server 2019
* Excel2007
* .Net Framework 4.7.2
* NPOI 2.4.1
## NPOIExcelUtil
```csharp=
/// <summary>
///
/// </summary>
public static class NPOIExcelUtil
{
public const int DefExcelMaxColNumber = 16384;
private static readonly Dictionary<string/*項目名英字*/, int/*インデックス*/> DicXlsColIndex = CreateDicXlsColIndex();
private static Dictionary<string/*項目名英字*/, int/*インデックス*/> CreateDicXlsColIndex()
{
var dicXlsColIndex = new Dictionary<string, int>();
for (int i = 0; i < DefExcelMaxColNumber; i++)
{
string ascii = GetStrColumnName(i + 1);
dicXlsColIndex.Add(ascii, i);
}
return dicXlsColIndex;
}
/// <summary>
/// 1→A、2→B
/// </summary>
/// <param name="lngColNum"></param>
/// <returns></returns>
public static string GetStrColumnName(long lngColNum)
{
string str = "";
// インデックス数値に変換
lngColNum--;
do
{
str = Convert.ToChar(lngColNum % 26 + 0x41) + str;
}
while ((lngColNum = lngColNum / 26 - 1) != -1);
return str;
}
public static int GetIdxColumn(string ascii)
{
return DicXlsColIndex[ascii];
}
public static int GetIdxRow(int intRowNum)
{
return intRowNum - 1;
}
/// <summary>
///
/// </summary>
/// <param name="xlsFile"></param>
/// <param name="intMaxRowNumber"></param>
/// <param name="intColCount"></param>
/// <returns></returns>
public static List<ExcelRow> GetXlsData(
FileInfo xlsFile,
int? intMaxRowNumber = null,
int? intColCount = null
)
{
// 開いている場合もあるので、TEMPにコピーしてから読み取る。
var datetime = DateTime.Now.ToString("yyyyMMddHHmmssfff");
var tempdir = Path.GetTempPath() + datetime;
var tempPath = tempdir + Path.DirectorySeparatorChar + xlsFile.Name;
// 一時ファイル用のディレクトリを作成する。
if (Directory.Exists(tempdir) == false)
{
Directory.CreateDirectory(tempdir);
}
FileInfo fInfoTempXlsFile = xlsFile.CopyTo(tempPath);
List<NPOIExcelRow> lstRows = new List<NPOIExcelRow>();
using (FileStream stream = fInfoTempXlsFile.OpenRead())
{
IWorkbook hssfworkbook = WorkbookFactory.Create(stream);
try
{
ISheet sheet = hssfworkbook.GetSheetAt(0);
int intLastRowNumber = sheet.LastRowNum;
if ( intMaxRowNumber != null
&& intMaxRowNumber < intLastRowNumber
)
{
intLastRowNumber = intMaxRowNumber.Value;
}
for (int i = 0; i < intLastRowNumber; i++)
{
IRow row = sheet.GetRow(i);
float heightInPoints = row.HeightInPoints;
List<ICell> cells = new List<ICell>();
if (row != null)
{
foreach (ICell cell in row)
{
while (cells.Count < cell.ColumnIndex)
{
cells.Add(null as ICell);
}
cells.Insert(cell.ColumnIndex, cell);
}
}
lstRows.Add(
new NPOIExcelRow(
cells,
heightInPoints
)
);
}
}
finally
{
hssfworkbook.Close();
}
}
int intMaxCol = lstRows.Max(n => n.LstCell.Count);
if ( intColCount != null
&& intColCount > intMaxCol
)
{
intMaxCol = intColCount.Value;
}
List<ExcelRow> xlsData = new List<ExcelRow>();
foreach (NPOIExcelRow row in lstRows)
{
string[] strings = new string[intMaxCol];
Color?[] colorFillForegrounds = new Color?[intMaxCol];
Color?[] colorFillBackgrounds = new Color?[intMaxCol];
int idxCol = 0;
foreach (ICell cell in row.LstCell)
{
if (strings.Length <= idxCol)
{
break;
}
if (cell != null)
{
// セルの値を取得
if (cell.CellType == CellType.Formula)
{
if (cell.CachedFormulaResultType == CellType.Numeric)
{
strings[idxCol] = cell.NumericCellValue.ToString();
}
else if (cell.CachedFormulaResultType == CellType.String)
{
strings[idxCol] = cell.StringCellValue;
}
else
{
strings[idxCol] = cell.ToString();
}
}
else if (cell.CellType == CellType.Numeric)
{
string val = null;
string strTemp = cell.ToString();
long lngTemp = 0;
if (long.TryParse(strTemp, out lngTemp))
{
val = lngTemp.ToString();
}
else
{
if (cell.DateCellValue != null)
{
if (cell.DateCellValue.TimeOfDay == new TimeSpan(0))
{
if (cell.DateCellValue.Ticks != 0)
{
val = cell.DateCellValue.ToShortDateString();
}
}
}
}
if (val == null)
{
val = cell.ToString();
}
strings[idxCol] = val;
}
else
{
strings[idxCol] = cell.ToString();
}
// セルの背景色を取得
{
Color? color = NPOIExcelUtil.GetColorFromICell(cell, n => n.FillForegroundColorColor);
if (color != null)
{
colorFillForegrounds[idxCol] = color;
}
}
{
Color? color = NPOIExcelUtil.GetColorFromICell(cell, n => n.FillBackgroundColorColor);
if (color != null)
{
colorFillBackgrounds[idxCol] = color;
}
}
}
idxCol++;
}
xlsData.Add(new ExcelRow(
strings,
row.FltHeightInPoints,
colorFillForegrounds,
colorFillBackgrounds
)
);
}
// 作成した一時ディレクトリを削除。
if (Directory.Exists(tempdir))
{
Directory.Delete(tempdir, true);
}
return xlsData;
}
public static IWorkbook GetWorkbook_Write(
FileInfo filExcel
)
{
IWorkbook writeBook = null;
// 書込用Excelファイルの読込
using (FileStream fstream = filExcel.OpenRead())
{
writeBook = WorkbookFactory.Create(fstream);
}
return writeBook;
}
public static void WriteWorkbook(
IWorkbook writeBook,
FileInfo xlsxNew
)
{
if (xlsxNew.Exists)
{
xlsxNew.Delete();
}
using (FileStream fstream = xlsxNew.OpenWrite())
{
writeBook.Write(fstream);
}
}
public static void WriteWorkbook(
FileInfo filExcelInput,
FileInfo filExcelOutput,
Action<IWorkbook, ISheet> actWriteWorkbook
)
{
IWorkbook writeBook = GetWorkbook_Write(filExcelInput);
try
{
ISheet sheet = writeBook.GetSheetAt(0);
if (actWriteWorkbook != null)
{
actWriteWorkbook(writeBook, sheet);
}
//sheet.ShiftRows(10, sheet.LastRowNum, 1, true, false);
//IRow rowOrg = sheet.GetRow(9);
//IRow rowNew = sheet.CreateRow(10);
//for (int i = 0; i< rowOrg.LastCellNum; i++)
//{
// rowNew.CreateCell(i);
//}
//rowOrg.CopyRowTo(10);
//for (int i=0; i<30; i++)
//{
// CopyRow(writeBook, sheet, 6, 7, 30);
//}
// 属性のコピー
//row2.CreateCell(3).CellStyle = row1.GetCell(0).CellStyle()
//string strNewExcelFile = filExcelInput.Directory.FullName + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(filExcelInput.FullName) + "_New" + Path.GetExtension(filExcelInput.FullName);
FileInfo xlsxNew = filExcelOutput;// new FileInfo(strNewExcelFile);
WriteWorkbook(writeBook, xlsxNew);
}
finally
{
writeBook.Close();
}
}
/// <summary>
/// HSSFRow Copy Command
///
/// Description: Inserts a existing row into a new row, will automatically push down
/// any existing rows. Copy is done cell by cell and supports, and the
/// command tries to copy all properties available (style, merged cells, values, etc...)
/// </summary>
/// <param name="workbook">Workbook containing the worksheet that will be changed</param>
/// <param name="worksheet">WorkSheet containing rows to be copied</param>
/// <param name="sourceRowNum">Source Row Number</param>
/// <param name="destinationRowNum">Destination Row Number</param>
public static void CopyRow(
IWorkbook workbook,
ISheet worksheet,
int sourceRowNum,
int destinationRowNum,
float? heightInPoints = null,
Color? fillForegroundColor = null,
Color? fillBackgroundColor = null,
Dictionary<int/* 項目のインデックス */, Color> fillForegroundColors = null,
Dictionary<int/* 項目のインデックス */, Color> fillBackgroundColors = null
)
{
// Get the source / new row
IRow newRow = worksheet.GetRow(destinationRowNum);
IRow sourceRow = worksheet.GetRow(sourceRowNum);
// If the row exist in destination, push down all rows by 1 else create a new row
if (newRow != null)
{
// コピー先にデータが存在している場合は、行を新たに追加する。
worksheet.ShiftRows(destinationRowNum, worksheet.LastRowNum, 1, copyRowHeight: true, resetOriginalRowHeight: false);
}
// 新しい行を生成する。
newRow = worksheet.CreateRow(destinationRowNum);
if (heightInPoints != null)
{
newRow.HeightInPoints = heightInPoints.Value;
}
// Loop through source columns to add to new row
for (int i = 0; i < sourceRow.LastCellNum; i++)
{
// Grab a copy of the old/new cell
ICell oldCell = sourceRow.GetCell(i);
ICell newCell = newRow.CreateCell(i);
// If the old cell is null jump to next cell
if (oldCell == null)
{
newCell = null;
continue;
}
// Copy style from old cell and apply to new cell
ICellStyle newCellStyle = workbook.CreateCellStyle();
{
newCellStyle.CloneStyleFrom(oldCell.CellStyle);
NPOIExcelUtil.SetICellStyleColor(newCellStyle, fillForegroundColor, (s, c) => s.SetFillForegroundColor(c));
NPOIExcelUtil.SetICellStyleColor(newCellStyle, fillBackgroundColor, (s, c) => s.SetFillBackgroundColor(c));
if (fillForegroundColors != null)
{
Color color;
if (fillForegroundColors.TryGetValue(newCell.ColumnIndex, out color))
{
NPOIExcelUtil.SetICellStyleColor(newCellStyle, color, (s, c) => s.SetFillForegroundColor(c));
}
}
if (fillBackgroundColors != null)
{
Color color;
if (fillBackgroundColors.TryGetValue(newCell.ColumnIndex, out color))
{
NPOIExcelUtil.SetICellStyleColor(newCellStyle, color, (s, c) => s.SetFillBackgroundColor(c));
}
}
newCell.CellStyle = newCellStyle;
//newCell.CellStyle = oldCell.CellStyle;
}
// If there is a cell comment, copy
if (oldCell.CellComment != null)
{
newCell.CellComment = oldCell.CellComment;
}
// If there is a cell hyperlink, copy
if (oldCell.Hyperlink != null)
{
newCell.Hyperlink = oldCell.Hyperlink;
}
// Set the cell data type
newCell.SetCellType(oldCell.CellType);
// Set the cell data value
switch (oldCell.CellType)
{
case CellType.Blank:
newCell.SetCellValue(oldCell.StringCellValue);
break;
case CellType.Boolean:
newCell.SetCellValue(oldCell.BooleanCellValue);
break;
case CellType.Error:
newCell.SetCellErrorValue(oldCell.ErrorCellValue);
break;
case CellType.Formula:
newCell.SetCellFormula(oldCell.CellFormula);
break;
case CellType.Numeric:
newCell.SetCellValue(oldCell.NumericCellValue);
break;
case CellType.String:
newCell.SetCellValue(oldCell.RichStringCellValue);
break;
case CellType.Unknown:
newCell.SetCellValue(oldCell.StringCellValue);
break;
}
}
// If there are are any merged regions in the source row, copy to new row
// セルの結合をコピー
for (int i = 0; i < worksheet.NumMergedRegions; i++)
{
CellRangeAddress cellRangeAddress = worksheet.GetMergedRegion(i);
if (cellRangeAddress != null)
{
if (cellRangeAddress.FirstRow == sourceRow.RowNum)
{
CellRangeAddress newCellRangeAddress = new CellRangeAddress(
newRow.RowNum,
newRow.RowNum + (cellRangeAddress.FirstRow - cellRangeAddress.LastRow),
cellRangeAddress.FirstColumn,
cellRangeAddress.LastColumn
);
worksheet.AddMergedRegion(newCellRangeAddress);
}
}
}
// 条件付き書式のコピー
ISheetConditionalFormatting iConditions = worksheet.SheetConditionalFormatting;
for (int i = 0; i < iConditions.NumConditionalFormattings; i++)
{
IConditionalFormatting cond = iConditions.GetConditionalFormattingAt(i);
if (cond != null)
{
CellRangeAddress[] rangs = cond.GetFormattingRanges();
List<CellRangeAddress> lstRangeNew = new List<CellRangeAddress>();
foreach (CellRangeAddress rang in rangs)
{
if (rang.FirstRow == sourceRow.RowNum)
{
CellRangeAddress newCellRangeAddress = new CellRangeAddress(
newRow.RowNum,
newRow.RowNum + (rang.FirstRow - rang.LastRow),
rang.FirstColumn,
rang.LastColumn
);
lstRangeNew.Add(newCellRangeAddress);
}
}
if (lstRangeNew.Any())
{
List<IConditionalFormattingRule> lstRuleNew = new List<IConditionalFormattingRule>();
for (int j = 0; j < cond.NumberOfRules; j++)
{
IConditionalFormattingRule rule = cond.GetRule(j);
lstRuleNew.Add(rule);
}
iConditions.AddConditionalFormatting(lstRangeNew.ToArray(), lstRuleNew.ToArray());
}
}
}
}
public static Color? GetColorFromICell(
ICell cell,
Func<XSSFCellStyle, IColor> fncGetIColor
)
{
Color? color = null;
if ( cell != null
&& cell.CellStyle is XSSFCellStyle
)
{
var cellStyle = cell.CellStyle as XSSFCellStyle;
if (fncGetIColor != null)
{
IColor iColor = fncGetIColor(cellStyle);
if ( iColor != null
&& iColor.RGB != null
)
{
color = Color.FromArgb(
red : iColor.RGB[0],
green : iColor.RGB[1],
blue : iColor.RGB[2]
);
}
}
}
return color;
}
public static void SetICellStyleColor(
ICellStyle iCelStylel,
Color? color,
Action<XSSFCellStyle, XSSFColor> actSetColor
)
{
if (iCelStylel is XSSFCellStyle)
{
var cellStyle = iCelStylel as XSSFCellStyle;
if (actSetColor != null)
{
if (color != null)
{
actSetColor(cellStyle, new XSSFColor(color.Value));
}
}
}
}
}
```
## ExcelRow
```csharp=
public class ExcelRow
{
private string[] m_rows;
private float m_heightInPoints;
private Color?[] m_colorFillForegrounds;
private Color?[] m_colorFillBackgrounds;
/// <summary>
///
/// </summary>
/// <param name="rows "></param>
/// <param name="heightInPoints "></param>
/// <param name="colorFillForegrounds "></param>
/// <param name="colorFillBackgrounds "></param>
public ExcelRow(
string[] rows,
float heightInPoints,
Color?[] colorFillForegrounds,
Color?[] colorFillBackgrounds
)
: base()
{
this.m_rows = rows;
this.m_heightInPoints = heightInPoints;
this.m_colorFillForegrounds = colorFillForegrounds;
this.m_colorFillBackgrounds = colorFillBackgrounds;
}
/// <summary>
///
/// </summary>
/// <param name="org"></param>
public ExcelRow(
ExcelRow org
)
: base()
{
this.m_rows = org.m_rows;
this.m_heightInPoints = org.m_heightInPoints;
this.m_colorFillForegrounds = org.m_colorFillForegrounds;
this.m_colorFillBackgrounds = org.m_colorFillBackgrounds;
}
public string[] Rows { get { return this.m_rows; } protected set { this.m_rows = value; } }
public float HeightInPoints { get { return this.m_heightInPoints; } protected set { this.m_heightInPoints = value; } }
public Color?[] ColorFillForegrounds { get { return this.m_colorFillForegrounds; } protected set { this.m_colorFillForegrounds = value; } }
public Color?[] ColorFillBackgrounds { get { return this.m_colorFillBackgrounds; } protected set { this.m_colorFillBackgrounds = value; } }
public override string ToString()
{
return new StringBuilder()
.Append("rows:").Append(m_rows).AppendLine("、")
.Append("heightInPoints:").Append(m_heightInPoints).AppendLine("、")
.Append("colorFillForegrounds:").Append(m_colorFillForegrounds).AppendLine("、")
.Append("colorFillBackgrounds:").Append(m_colorFillBackgrounds).AppendLine("、")
.ToString();
}
}
```
## IndexCell
```csharp=
public class IndexCell
{
public IndexCell(
int rowNum,
string colName
)
: base()
{
this.m_row = NPOIExcelUtil.GetIdxRow(rowNum);
this.m_col = NPOIExcelUtil.GetIdxColumn(colName);
}
private int m_row;
private int m_col;
/// <summary>
///
/// </summary>
/// <param name="row "></param>
/// <param name="col "></param>
public IndexCell(
int row,
int col
)
: base()
{
this.m_row = row;
this.m_col = col;
}
/// <summary>
///
/// </summary>
/// <param name="org"></param>
public IndexCell(
IndexCell org
)
: base()
{
this.m_row = org.m_row;
this.m_col = org.m_col;
}
public int Row { get { return this.m_row; } protected set { this.m_row = value; } }
public int Col { get { return this.m_col; } protected set { this.m_col = value; } }
public override string ToString()
{
return new StringBuilder()
.Append("row:").Append(m_row).AppendLine("、")
.Append("col:").Append(m_col).AppendLine("、")
.ToString();
}
}
```
## NPOIExcelRow
```csharp=
class NPOIExcelRow
{
private List<ICell> m_lstCell;
private float m_fltHeightInPoints;
/// <summary>
///
/// </summary>
/// <param name="lstCell "></param>
/// <param name="fltHeightInPoints "></param>
public NPOIExcelRow(
List<ICell> lstCell,
float fltHeightInPoints
)
: base()
{
this.m_lstCell = lstCell;
this.m_fltHeightInPoints = fltHeightInPoints;
}
/// <summary>
///
/// </summary>
/// <param name="org"></param>
public NPOIExcelRow(
NPOIExcelRow org
)
: base()
{
this.m_lstCell = org.m_lstCell;
this.m_fltHeightInPoints = org.m_fltHeightInPoints;
}
public List<ICell> LstCell { get { return this.m_lstCell; } protected set { this.m_lstCell = value; } }
public float FltHeightInPoints { get { return this.m_fltHeightInPoints; } protected set { this.m_fltHeightInPoints = value; } }
public override string ToString()
{
return new StringBuilder()
.Append("lstCell:").Append(m_lstCell != null ? "[" + string.Join("][", m_lstCell) + "]" : "").AppendLine("、")
.Append("fltHeightInPoints:").Append(m_fltHeightInPoints).AppendLine("、")
.ToString();
}
}
```
###### tags: `NPOI` `C#` `Excel2007`