Microsoft.Office.Interop.Excelで複数Excelファイルの一括編集

###まず実行結果を確認したい　　→　　[実行結果](#5実行結果)
##開発環境
- Microsoft Visual Studio Community 2019
- Microsoft .NET Framework 4.8.04084
- Microsoft Excel 2016

##開発言語
- C#

##1.新しいプロジェクトの作成
「C#コンソールアプリケーション」プロジェクトを作成します。
作成方法は下記を参照してください。
[Visual Studio での新しいプロジェクトの作成](https://docs.microsoft.com/ja-jp/visualstudio/ide/create-new-project?view=vs-2019)

##2.参照の追加
「Microsoft Excel 16.0 Object Library」COM参照を追加します。
追加方法は下記を参照してください。
[.NET 5プロジェクトでのCOM参照の追加](https://opcdiary.net/net-5%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%A7%E3%81%AEcom%E5%8F%82%E7%85%A7%E3%81%AE%E8%BF%BD%E5%8A%A0/)
##3.ソースコード
```C#:Program.cs
using System.IO;
using System.Runtime.InteropServices;
using Excel = Microsoft.Office.Interop.Excel;

namespace ExcelEdit
{
    class Program
    {
        static void Main(string[] args)
        {
            // 色んなオブジェクトの定義
            Excel.Application excel = null;
            Excel.Workbooks books = null;
            Excel.Workbook book = null;
            Excel.Sheets sheets = null;
            Excel.Worksheet sheet = null;
            Excel.Range cells = null;
            Excel.Range range = null;
            // フォルダの取得
            string folderPath = @"C:\Users\xyy\Desktop\Folder";
            // フォルダの中の拡張子が.xlsxのファイルの取得
            string[] files = Directory.GetFiles(Path.GetFullPath(folderPath), "*.xlsx");
            try
            {
                // Excelを起動する
                excel = new Excel.Application();
                // ブック一覧の定義
                books = excel.Workbooks;
                // 各ファイルに対して下記処理を繰り返し行う
                foreach (string file in files)
                {
                    try
                    {
                        // ブックを開く
                        book = books.Open(file);
                        // シート一覧の定義
                        sheets = book.Worksheets;
                        // 最初のシートの選択
                        sheet = sheets[1];
                        // セル一覧の定義
                        cells = sheet.Cells; 
                        // セル[2,1]の選択
                        // range = sheet.Cells[2, 1] という書き方だと、sheet.Cellsとsheet.Cells[2, 1]という二つのExcel.Rangeオブジェクトが隠れて、
                        // オブジェクトの解放漏れが発生するので、注意してください。    
                        range = cells[2, 1];
                        // セル[2,1]の値をtestに設定する
                        range.Value = "test";
                        // ブックを保存して閉じる
                        book.Close(true);
                        // Excelを終了する
                        excel.Quit();
                    }
                    finally
                    {
                        // 定義されたオブジェクトの解放、ループのたびに毎回解放しないとExcelのプロセスが残り続ける
                        Marshal.FinalReleaseComObject(range);
                        Marshal.FinalReleaseComObject(cells);
                        Marshal.FinalReleaseComObject(sheet);
                        Marshal.FinalReleaseComObject(sheets);
                        Marshal.FinalReleaseComObject(book);
                    }
                }
            }
            finally
            {
                // ブック一覧とExcelオブジェクトの解放は最後に一回行っていい
                Marshal.FinalReleaseComObject(books);
                Marshal.FinalReleaseComObject(excel);
            }
        }
    }
}

```
##4.編集対象とするファイルの作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1628646/48ae9c3a-cc34-8712-68c0-9bedbba71f4e.png)
##5.実行結果
実行前　　　　　　　　　　　　実行後
Book1 & Book2　　　　　　　　 Book1 & Book2
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1628646/b01b2864-8c52-1ebc-026e-610644cfb8d4.png)　　　　　　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1628646/4cd5dc3c-6ba2-d5bd-1eef-070456fbe507.png)
##6.異常時対応
実行中のプログラムを強制終了させる場合、オブジェクトの解放ができなくて、Excelのプロセスが残り続けます。
プログラムを再実行したら、エラーが発生する可能性が高いです。
対応方法について、タスクマネージャーで残り続けるExcelプロセスを終了させてからプログラムの再実行してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1628646/b8d89f0c-fec4-f793-cf7f-c93f77d04262.png)
##7.値の編集以外の機能
###7.1.列の挿入
```C#:Program.cs
// 列一覧の定義
cells = sheet.Columns;
// 2列目の選択
range = cells[2];
// 3列を挿入する
for (int i = 0; i < 3; i++)
{
    range.Insert();
}                                               
```
実行前　　　　　　　　　　　　　　　　　　
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1628646/0a35a7f7-eb86-ad7d-76dc-6d5a133a2c9f.png)　
実行後　　　　
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1628646/f8e722cb-db73-830f-0814-39b73c26b2cf.png)
###7.2.セルの結合
```C#:Program.cs
// セル一覧の定義
cells = sheet.Cells;
// セル[2, 2]の選択
range1 = cells[2, 2];
// セル[2, 4]の選択
range2 = cells[2, 4];
// セル[2, 2]から[2, 4]までの範囲の選択
range3 = sheet.Range[range1,range2];
// セルの結合
range3.Merge();                                           
```

もしくは

```C#:Program.cs
// セル[B2]から[D2]までの範囲の選択
range = sheet.Range["B2:D2"];
// セルの結合
range.Merge();                                                                  
```                
実行前　　　　　　　　　　　　　　　　　　                   
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1628646/9d36830b-82cc-9a10-e36d-54d28c0cad3e.png)   
実行後  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1628646/433e1113-1090-81cd-a504-c3c2610c3bf2.png)
###7.3.文字色の変更    
```C#:Program.cs
// フォントオブジェクトの定義
Excel.Font font = null;    
// ... 略
// セル一覧の定義
cells = sheet.Cells;
// セル[2,1]の選択
range = cells[2, 1];
// セル[2,1]のフォントの選択
font = range.Font;
// 文字色を赤にする
font.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Red);                                                            
```
実行前　　　　　　　　 実行後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1628646/4de9aaed-d47b-8229-5574-7de236ef1d4c.png)　　　　　　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1628646/0c7c805c-9200-e910-f95a-331a04ff3613.png)
###7.4.罫線の設定
```C#:Program.cs
// 罫線オブジェクトの定義
Excel.Borders border = null;  
// ... 略
// セル一覧の定義
cells = sheet.Cells;
// セル[2,2]の選択
range = cells[2, 2];
// セル[2,2]の罫線選択
border = range.Borders;
// 罫線を実線に設定する
border.LineStyle = Excel.XlLineStyle.xlContinuous;
// 罫線の太さの設定
border.Weight = 2d;                                                          
```
実行前　　　　　　　　　　　　　　　実行後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1628646/8bce43be-1eb8-2cf3-5018-34acdf38b2ce.png)　　　　　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1628646/76b2b97e-279f-d272-40a5-6cb7c531de60.png)

##参考文献

この記事は以下の情報を参考にして執筆しました。

- [C#: Excelファイルを読み書きする (COM)](https://knooto.info/csharp-excel-com/)
- [c#でExcelをOpenするとプロセスが残る(Microsoft.Office.Interop.Excel使用)](https://teratail.com/questions/154464)
- [Microsoft.Office.Interop.Excel: How to Apply a border to ONE CELL](https://stackoverflow.com/questions/17751192/microsoft-office-interop-excel-how-to-apply-a-border-to-one-cell/39163653#)

##最後に
在日中国人エンジニアです。技術的な指摘もしくは日本語の指摘がございましたら、教えてください。