C#でExcelをCOM操作する方法|参照設定からEXCEL.EXEが残る原因・解放処理まで徹底解説

using System;using System.IO;using System.Runtime.InteropServices;using Excel = Microsoft.Office.Interop.Excel;

internal static class Program{[STAThread]private static void Main(){string inputPath =Path.GetFullPath(@"C:\Work\input.xlsx");

    string outputPath =Path.GetFullPath(@"C:\Work\output.xlsx");Excel.Application? excelApp = null;Excel.Workbooks? workbooks = null;Excel.Workbook? workbook = null;Excel.Sheets? sheets = null;Excel.Worksheet? worksheet = null;Excel.Range? writeRange = null;Excel.Range? readRange = null;try{if (!File.Exists(inputPath)){throw new FileNotFoundException("入力ファイルが見つかりません。",inputPath);}string? outputDirectory =Path.GetDirectoryName(outputPath);if (string.IsNullOrWhiteSpace(outputDirectory)){throw new InvalidOperationException("出力先フォルダーを取得できません。");}Directory.CreateDirectory(outputDirectory);excelApp = new Excel.Application{Visible = false,DisplayAlerts = false,ScreenUpdating = false};workbooks = excelApp.Workbooks;workbook = workbooks.Open(inputPath,UpdateLinks: 0,ReadOnly: false);sheets = workbook.Worksheets;worksheet = (Excel.Worksheet)sheets<span data-placeholder-token="true" class="text-token-text-primary cursor-text rounded-sm" style="background-color: color-mix(in srgb, var(--theme-user-selection-bg, var(--selection)) 30%, transparent); padding-top: 4px; padding-bottom: 4px;">[1]</span>;object<span data-placeholder-token="true" class="text-token-text-primary cursor-text rounded-sm" style="background-color: color-mix(in srgb, var(--theme-user-selection-bg, var(--selection)) 30%, transparent); padding-top: 4px; padding-bottom: 4px;">[,]</span> data ={{ "商品名", "金額" },{ "商品A", 1200 },{ "商品B", 3000 }};writeRange = worksheet.Range<span data-placeholder-token="true" class="text-token-text-primary cursor-text rounded-sm" style="background-color: color-mix(in srgb, var(--theme-user-selection-bg, var(--selection)) 30%, transparent); padding-top: 4px; padding-bottom: 4px;">["A1", "B3"]</span>;writeRange.Value2 = data;readRange = worksheet.Range<span data-placeholder-token="true" class="text-token-text-primary cursor-text rounded-sm" style="background-color: color-mix(in srgb, var(--theme-user-selection-bg, var(--selection)) 30%, transparent); padding-top: 4px; padding-bottom: 4px;">["B2", "B3"]</span>;if (readRange.Value2 is object<span data-placeholder-token="true" class="text-token-text-primary cursor-text rounded-sm" style="background-color: color-mix(in srgb, var(--theme-user-selection-bg, var(--selection)) 30%, transparent); padding-top: 4px; padding-bottom: 4px;">[,]</span> values){Console.WriteLine(values<span data-placeholder-token="true" class="text-token-text-primary cursor-text rounded-sm" style="background-color: color-mix(in srgb, var(--theme-user-selection-bg, var(--selection)) 30%, transparent); padding-top: 4px; padding-bottom: 4px;">[1, 1]</span>);Console.WriteLine(values<span data-placeholder-token="true" class="text-token-text-primary cursor-text rounded-sm" style="background-color: color-mix(in srgb, var(--theme-user-selection-bg, var(--selection)) 30%, transparent); padding-top: 4px; padding-bottom: 4px;">[2, 1]</span>);}workbook.SaveAs(outputPath,Excel.XlFileFormat.xlOpenXMLWorkbook);}finally{ReleaseComObject(ref readRange);ReleaseComObject(ref writeRange);ReleaseComObject(ref worksheet);ReleaseComObject(ref sheets);if (workbook != null){try{workbook.Close(SaveChanges: false);}catch (COMException ex){Console.Error.WriteLine($"Workbook.Closeに失敗しました: {ex}");}finally{ReleaseComObject(ref workbook);}}ReleaseComObject(ref workbooks);if (excelApp != null){try{excelApp.ScreenUpdating = true;excelApp.DisplayAlerts = true;excelApp.Quit();}catch (COMException ex){Console.Error.WriteLine($"Application.Quitに失敗しました: {ex}");}finally{ReleaseComObject(ref excelApp);}}}}private static void ReleaseComObject&lt;T&gt;(ref T? comObject)where T : class{if (comObject != null &amp;&amp;Marshal.IsComObject(comObject)){Marshal.ReleaseComObject(comObject);}comObject = null;}

}