C#でNPOIを使ってみる

# 1. はじめに

* JavaのApache POIと同じように帳票を作成したい
* NPOIを使ってExcel帳票を作成したい



# 2. 開発環境

* C#
* .NET 6.0
* NPOI
* Windows 10



# 3. 事前準備

* NuGetからNPOIをインストールする



# 4. Excelファイルの操作

## 4.1. Excelファイルを作成する

```csharp
static void Main(string[] args)
{
    // ワークブックを作成
    var wb = CreateWorkbook("sample.xlsx");
    
    // シートを作成
    CreateSheet(wb,"Sheet1");
    
    // Excelファイルを保存する
    OutputFile("sample.xlsx", wb);
}

public static IWorkbook CreateWorkbook(string pName)
{
    IWorkbook wb;
    var extension = Path.GetExtension(pName);

    // HSSF => Microsoft Excel(xls形式)(excel 97-2003)
    // XSSF => Office Open XML Workbook形式(xlsx形式)(excel 2007以降)
    if (extension == ".xls")
    {
        wb = new HSSFWorkbook();
    }
    else if (extension == ".xlsx")
    {
        wb = new XSSFWorkbook();
    }
    else
    {
        throw new ApplicationException("CreateNewBook: invalid extension");
    }

    return wb;
}

public static ISheet CreateSheet(IWorkbook pWb, string pName)
{
    return pWb.CreateSheet(pName);
}

public static void OutputFile(string pFile, IWorkbook pWb)
{
    try
    {
        using (var fs = new FileStream(TemplatePath + pFile, FileMode.Create))
        {
            pWb.Write(fs);
        }
    }
    catch (Exception ex)
    {
        throw new ApplicationException("OutputFile: " + ex);
    }
}
```



## 4.2. Excelファイルを読み込む

```csharp
static void Main(string[] args)
{
    // テンプレートファイルを読み込む
    var wb = GetWorkbook("Sample.xlsx");

    // シートを読み込む
    var sheet = GetSheet(wb, 0);

    // 値を取得する（文字列）
    var a1 = GetCellValueString(sheet, 0, 0);
    var b1 = GetCellValueString(sheet, 0, 1);
    var b2 = GetCellValueString(sheet, 1, 1);

    // Console出力
    Console.WriteLine("A1: " + a1);
    Console.WriteLine("B1: " + b1);
    Console.WriteLine("B2: " + b2);
}

public static IWorkbook GetWorkbook(string pFile)
{
    // 返却値
    IWorkbook wb;

    // テンプレートファイルを読み込む
    try
    {
        wb = WorkbookFactory.Create(TemplatePath + pFile);
    }
    catch (Exception ex)
    {
        throw new ApplicationException("GetWorkbook: " + ex);
    }

    return wb;
}

public static ISheet GetSheet(IWorkbook pWb, int pIndex)
{
    return pWb.GetSheetAt(pIndex);
}

public static string GetCellValueString(ISheet pSheet, int pRowNum, int pColumnNum)
{
    string result = string.Empty;

    var cell = GetCell(pSheet, pRowNum, pColumnNum);
    if (cell.CellType == CellType.String)
    {
        result = cell.StringCellValue;
    }

    return result;
}

public static IRow GetRow(ISheet pSheet, int pRowNum)
{
    return pSheet.GetRow(pRowNum) ?? pSheet.CreateRow(pRowNum);
}

public static ICell GetCell(ISheet pSheet, int pRowNum, int pColumnNum)
{
    return GetCell(GetRow(pSheet, pRowNum), pColumnNum);
}

public static ICell GetCell(IRow pRow, int pColumnNum)
{
    return pRow.GetCell(pColumnNum) ?? pRow.CreateCell(pColumnNum);
}
```

* Excelのセルタイプを判定して取得メソッドを変更する必要がある

| セルタイプ | セルからの値取得メソッド |
| ---------- | ------------------------ |
| 文字列     | cell.StringCellValue     |
| 数値型     | cell.NumericCellValue    |
| 日付型     | cell.DateCellValue       |
| boolean型  | cell.BooleanCellValue    |
| 関数型     | cell.CellFormula         |



## 4.3. Excelファイルに書き込む

```csharp
static void Main(string[] args)
{
    // Excelファイルを読み込む
    var wb = GetWorkbook("Sample.xlsx");

    // シートを読み込む
    var sheet = GetSheet(wb, 0);

    // 値を設定する
    SetCellValue(sheet, 0, 0, "AA1");
    SetCellValue(sheet, 0, 1, "BB1");
    SetCellValue(sheet, 1, 1, "BB2");

    // Excelファイルを保存する
    OutputFile("sample.xlsx", wb);
}

public static IWorkbook GetWorkbook(string pFile)
{
    // 返却値
    IWorkbook wb;

    // テンプレートファイルを読み込む
    try
    {
        wb = WorkbookFactory.Create(TemplatePath + pFile);
    }
    catch (Exception ex)
    {
        throw new ApplicationException("GetWorkbook: " + ex);
    }

    return wb;
}

public static ISheet GetSheet(IWorkbook pWb, int pIndex)
{
    return pWb.GetSheetAt(pIndex);
}

public static IRow GetRow(ISheet pSheet, int pRowNum)
{
    return pSheet.GetRow(pRowNum) ?? pSheet.CreateRow(pRowNum);
}

public static ICell GetCell(ISheet pSheet, int pRowNum, int pColumnNum)
{
    return GetCell(GetRow(pSheet, pRowNum), pColumnNum);
}

public static ICell GetCell(IRow pRow, int pColumnNum)
{
    return pRow.GetCell(pColumnNum) ?? pRow.CreateCell(pColumnNum);
}

public static void SetCellValue(ISheet pSheet, int pRowNum, int pColumnNum,  object pValue)
{
    var cell = GetCell(pSheet, pRowNum, pColumnNum);
    SetCellValue(cell, pValue);
}

private static void SetCellValue(ICell pCell, object pValue)
{
    // 引数で渡された型を判定
    Type type = pValue.GetType();

    // 文字列の場合
    if (type == typeof(string))
    {
        pCell.SetCellValue((string)pValue);
    }

    // 数値型 (int, long) の場合
    else if (type == typeof(int) || type == typeof(long))
    {
        pCell.SetCellValue((int)pValue);
    }

    // 実数型 (double, float) の場合
    else if (type == typeof(double) || type == typeof(float))
    {
        pCell.SetCellValue((double)pValue);
    }

    // Boolean型の場合;
    else if (type == typeof(bool))
    {
        pCell.SetCellValue((bool)pValue);
    }

    // 日付型の場合
    else if (type == typeof(DateTime))
    {
        pCell.SetCellValue((DateTime)pValue);
    }

    // リッチテキスト型の場合
    else if (type == typeof(XSSFRichTextString))
    {
        pCell.SetCellValue((XSSFRichTextString)pValue);
    }

    // DataTable型 (DBNull) の場合
    else if (type == typeof(DBNull))
    {
        pCell.SetCellValue(string.Empty);
    }
}
```



# 5. Excelの印刷設定

```c#
// 印刷範囲
wb.SetPrintArea(
  0,	// sheet index
  0,	//start column
  10,	//end column
  0,	//start row
  100	//end row
);

// 印刷時の用紙サイズ等の設定
var printSetting = writeSheet.PrintSetup;

// 印刷用紙：A4
printSetting.PaperSize = (short)PaperSize.A4;

// 印刷方向：横
printSetting.Landscape = true;

// ページ数に合わせて印刷(横)：1
printSetting.FitWidth = (short)1;

// ページ数に合わせて印刷(縦)：0(フリー)
printSetting.FitHeight = (short)0;

// 印刷出力を1ページ幅に収める
sheet.FitToPage = true;
```



# 6. 参考文献



https://www.sejuku.net/blog/100771#index_id5



https://resanaplaza.com/2021/01/30/%E3%80%90c%E3%80%91npoi%E3%81%A7excel%E7%B0%A1%E5%8D%98%E6%93%8D%E4%BD%9C%EF%BC%88%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E4%BB%98%E3%81%8D%EF%BC%89/



https://note.com/waiting4ufo/n/nc32f70337559



https://qiita.com/hukatama024e/items/37427f2578a8987645dd



https://qiita.com/iijijii/items/9981652a48708bfcacc2



https://docs.aspose.com/cells/ja/java/set-print-area/