Sheet1・・・保護なし(保護に使用)
Sheet2・・・保護なし(保護に使用)
Sheet3・・・保護あり・パスなし(保護解除に使用)
Sheet4・・・保護あり・パスあり(保護解除に使用)

ExcelVBA

Sub Sample()
    Dim BookObj     As Workbook
    Dim FilePath    As String
    Dim SheetObj    As Worksheet
    
    'ファイルパス作成
    FilePath = ThisWorkbook.Path & "\sample.xlsx"
    
    'ブックを開く
    Set BookObj = Workbooks.Open(FilePath)
    
    'パスワード無し保護
    Set SheetObj = BookObj.Sheets(1)
    SheetObj.Protect ("")
    
    'パスワード有り保護
    Set SheetObj = BookObj.Sheets(2)
    SheetObj.Protect ("pass")
    
    'パスワード無し解除
    Set SheetObj = BookObj.Sheets(3)
    SheetObj.Unprotect ("")
    
    'パスワード有り解除
    Set SheetObj = BookObj.Sheets(4)
    SheetObj.Unprotect ("pass")
    
    '保存
    BookObj.Save
    
    '閉じる
    BookObj.Close
    
    Set BookObj = Nothing
End Sub

Excel(COM)

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

namespace SampleCode; // C#10~

internal class SampleExcel
{
    static void Main(string[] args)
    {
        Excel.Application? application = null;
        Excel.Workbooks? workbooks = null;
        Excel.Workbook? workbook = null;
        Excel.Sheets? worksheets = null;
        Excel.Worksheet? worksheet = null;

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // Excelを開く
            application = new Excel.Application();
            application.Visible = true;

            // ブックを開く
            workbooks = application.Workbooks;
            workbook = workbooks.Open(filePath);

            // シートを取得
            worksheets = workbook.Sheets;

            // パスワード無し保護
            worksheet = worksheets[1];
            worksheet.Protect("");
            CleanUpComObject(ref worksheet);

            // パスワード有り保護
            worksheet = worksheets[2];
            worksheet.Protect("pass");
            CleanUpComObject(ref worksheet);

            // パスワード無し解除
            worksheet = worksheets[3];
            worksheet.Unprotect("");
            CleanUpComObject(ref worksheet);

            // パスワード有り保護
            worksheet = worksheets[4];
            worksheet.Unprotect("pass");
            CleanUpComObject(ref worksheet);

            // 保存
            workbook.Save();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        finally
        {
            CleanUpComObject(ref worksheet);
            CleanUpComObject(ref worksheets);
            CleanUpComObject(ref workbook);
            CleanUpComObject(ref workbooks);
            CleanUpComObject(ref application);
        }
    }

    static void CleanUpComObject<T>(ref T comObject, bool shouldClose = true, bool saveChanges = false)
    {
        // フラグによってWorkbookはClose / ApplicationはQuitする
        if (shouldClose && comObject != null)
        {
            // 型をチェックする
            if (comObject is Microsoft.Office.Interop.Excel.Workbook workbook)
            {
                // Workbookの場合
                workbook.Close(saveChanges);
            }
            else if (comObject is Microsoft.Office.Interop.Excel.Application application)
            {
                // Applicationの場合
                application.Quit();
            }
        }

        // Objectを解放
        if (comObject != null && Marshal.IsComObject(comObject))
        {
            Marshal.ReleaseComObject(comObject);
            comObject = default!;
        }
    }
}

補足:Microsoft.Office.Interop.Excel でオブジェクトの解放について

ClosedXML

using ClosedXML.Excel;
using DocumentFormat.OpenXml.Spreadsheet;
using System;
using System.IO;
using System.Linq;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleClosedXML
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // ブックを開く、読み書きモード、共有なし(排他)
            using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            using (var workbook = new XLWorkbook(fileStream))
            {
                // パスワード無し保護
                var sheet1 = workbook.Worksheet(1);
                sheet1.Protect(); 

                // パスワード有り保護
                var sheet2 = workbook.Worksheet(2);
                sheet2.Protect("pass"); 

                // パスワード無し解除
                var sheet3 = workbook.Worksheet(3);
                sheet3.Unprotect();

                // パスワード有り解除
                var sheet4 = workbook.Worksheet(4);
                sheet4.Unprotect("pass");

                // 保存
                workbook.Save();
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

EPPlus

using OfficeOpenXml;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleEPPlus
{
    static void Main(string[] args)
    {
        // Ver8.0のソースです
        // 非商用個人利用の場合 名前を設定
        ExcelPackage.License.SetNonCommercialPersonal("SampleTarou");

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // メモリにすべて取り込む。これなら遅延でStreamにアクセスするような問題が発生しない
            byte[] fileBytes = File.ReadAllBytes(filePath);
            using (var readStream = new MemoryStream(fileBytes))
            using (var package = new ExcelPackage(readStream))
            {
                // パスワード無し保護
                var sheet1 = package.Workbook.Worksheets[0];
                sheet1.Protection.IsProtected = true;

                // パスワード有り保護
                var sheet2 = package.Workbook.Worksheets[1];
                sheet2.Protection.SetPassword("pass"); // IsProtectedは指定しなくてもパスがかかる

                // パスワード無し解除
                var sheet3 = package.Workbook.Worksheets[2];
                sheet3.Protection.IsProtected = false;

                // パスワード有り解除
                var sheet4 = package.Workbook.Worksheets[3];
                sheet4.Protection.IsProtected = false; // パスが設定されていてもこれで解除
                
                // あらためて書き込み用としてStreamを開く
                using (var writeStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    // 書き込み
                    package.SaveAs(writeStream);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"エラー: {ex.Message}");
        }
    }
}

ExcelDataReader

読み取りのみのライブラリのためなし

NPOI

□xls

using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleNPOI_xls
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xls");

            // メモリにすべて取り込む。これなら遅延でStreamにアクセスするような問題が発生しない
            byte[] fileBytes = File.ReadAllBytes(filePath);
            using (var readStream = new MemoryStream(fileBytes))
            using (var workbook = new HSSFWorkbook(readStream))
            {
                // パスワード無し保護
                var sheet1 = workbook.GetSheetAt(0);
                sheet1.ProtectSheet("");

                // パスワード有り保護
                var sheet2 = workbook.GetSheetAt(1);
                sheet2.ProtectSheet("pass");

                // パスワード無し解除
                var sheet3 = workbook.GetSheetAt(2);
                sheet3.ProtectSheet(null); // パスワード無しなら解除できた

                // パスワード有り解除
                var sheet4 = workbook.GetSheetAt(3);
                // ※解除方法はなさそう

                // あらためて書き込み用としてStreamを開く
                using (var writeStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    // 書き込み
                    workbook.Write(writeStream);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

□xlsx

using NPOI.XSSF.UserModel;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleNPOI_xlsx
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // メモリにすべて取り込む。これなら遅延でStreamにアクセスするような問題が発生しない
            byte[] fileBytes = File.ReadAllBytes(filePath);
            using (var readStream = new MemoryStream(fileBytes))
            using (var workbook = new XSSFWorkbook(readStream))
            {
                // パスワード無し保護
                var sheet1 = workbook.GetSheetAt(0);
                sheet1.ProtectSheet("");

                // パスワード有り保護
                var sheet2 = workbook.GetSheetAt(1);
                sheet2.ProtectSheet("pass");

                // パスワード無し解除
                var sheet3 = workbook.GetSheetAt(2);
                sheet3.ProtectSheet(null); // パスワード無しなら解除できた

                // パスワード有り解除
                var sheet4 = workbook.GetSheetAt(3);
                // ※解除方法はなさそう

                // あらためて書き込み用としてStreamを開く
                using (var writeStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    // 書き込み
                    workbook.Write(writeStream);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

□xlsもxlsxも扱う場合
Program.cs

using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleNPOI
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            var extension = Path.GetExtension(filePath);

            // メモリにすべて取り込む。これなら遅延でStreamにアクセスするような問題が発生しない
            byte[] fileBytes = File.ReadAllBytes(filePath);
            using (var readStream = new MemoryStream(fileBytes))
            using (var workbook = WorkbookFactory.Create(readStream, extension))
            {
                // パスワード無し保護
                var sheet1 = workbook.GetSheetAt(0);
                sheet1.ProtectSheet("");

                // パスワード有り保護
                var sheet2 = workbook.GetSheetAt(1);
                sheet2.ProtectSheet("pass");

                // パスワード無し解除
                var sheet3 = workbook.GetSheetAt(2);
                sheet3.ProtectSheet(null); // パスワード無しなら解除できた

                // パスワード有り解除
                var sheet4 = workbook.GetSheetAt(3);
                // ※解除方法はなさそう

                // あらためて書き込み用としてStreamを開く
                using (var writeStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    // 書き込み
                    workbook.Write(writeStream);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

WorkbookFactory.cs

using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.IO;

namespace SampleCode
{
    public class WorkbookFactory
    {
        public static IWorkbook Create(Stream stream, string extension)
        {
            extension = extension.ToLower();

            return extension switch
            {
                ".xls" => new HSSFWorkbook(stream),
                ".xlsx" => new XSSFWorkbook(stream),
                _ => throw new NotSupportedException("対象外の拡張子です")
            };
        }

        public static IWorkbook Create(string extension)
        {
            extension = extension.ToLower();

            return extension switch
            {
                ".xls" => new HSSFWorkbook(),
                ".xlsx" => new XSSFWorkbook(),
                _ => throw new NotSupportedException("対象外の拡張子です")
            };
        }
    }
}
投稿日時: 2025-05-28 14:55:28

カレントの表示倍率を取得と設定

ExcelVBA

Sub Sample()
    Dim BookObj     As Workbook
    Dim FilePath    As String
    
    'ファイルパス作成
    FilePath = ThisWorkbook.Path & "\sample.xlsx"
    
    'ブックを開く
    Set BookObj = Workbooks.Open(FilePath)
    
    '表示倍率の取得
    Debug.Print ActiveWindow.Zoom

    '表示倍率の設定
    ActiveWindow.Zoom = 200
    
    '保存
    BookObj.Save
    
    '閉じる
    BookObj.Close
    
    Set BookObj = Nothing
End Sub

Excel(COM)

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

namespace SampleCode; // C#10~

internal class SampleExcel
{
    static void Main(string[] args)
    {
        Excel.Application? application = null;
        Excel.Workbooks? workbooks = null;
        Excel.Workbook? workbook = null;
        Excel.Sheets? worksheets = null;
        Excel.Worksheet? worksheet1 = null;
        Excel.Worksheet? worksheet2 = null;

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // Excelを開く
            application = new Excel.Application();
            application.Visible = true;

            // ブックを開く
            workbooks = application.Workbooks;
            workbook = workbooks.Open(filePath);

            // 表示倍率の取得
            Console.WriteLine(application.ActiveWindow.Zoom);

            // 表示倍率の設定
            application.ActiveWindow.Zoom = 200;

            // 保存
            workbook.Save();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        finally
        {
            CleanUpComObject(ref worksheet1);
            CleanUpComObject(ref worksheet2);
            CleanUpComObject(ref worksheets);
            CleanUpComObject(ref workbook);
            CleanUpComObject(ref workbooks);
            CleanUpComObject(ref application);
        }
    }

    static void CleanUpComObject<T>(ref T comObject, bool shouldClose = true, bool saveChanges = false)
    {
        // フラグによってWorkbookはClose / ApplicationはQuitする
        if (shouldClose && comObject != null)
        {
            // 型をチェックする
            if (comObject is Microsoft.Office.Interop.Excel.Workbook workbook)
            {
                // Workbookの場合
                workbook.Close(saveChanges);
            }
            else if (comObject is Microsoft.Office.Interop.Excel.Application application)
            {
                // Applicationの場合
                application.Quit();
            }
        }

        // Objectを解放
        if (comObject != null && Marshal.IsComObject(comObject))
        {
            Marshal.ReleaseComObject(comObject);
            comObject = default!;
        }
    }
}

補足:Microsoft.Office.Interop.Excel でオブジェクトの解放について

ClosedXML

using ClosedXML.Excel;
using System;
using System.IO;
using System.Linq;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleClosedXML
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // ブックを開く、読み書きモード、共有なし(排他)
            using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            using (var workbook = new XLWorkbook(fileStream))
            {
                // 表示倍率の取得
                var activeSheet = workbook.Worksheets.First(ws => ws.TabActive);
                Console.WriteLine(activeSheet.SheetView.ZoomScale);

                // 表示倍率の設定
                activeSheet.SheetView.ZoomScale = 200;

                // 保存
                workbook.Save();
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

EPPlus

using OfficeOpenXml;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleEPPlus
{
    static void Main(string[] args)
    {
        // Ver8.0のソースです
        // 非商用個人利用の場合 名前を設定
        ExcelPackage.License.SetNonCommercialPersonal("SampleTarou");

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // メモリにすべて取り込む。これなら遅延でStreamにアクセスするような問題が発生しない
            byte[] fileBytes = File.ReadAllBytes(filePath);
            using (var readStream = new MemoryStream(fileBytes))
            using (var package = new ExcelPackage(readStream))
            {
                // Activeなシートを取得
                var sheetNo = package.Workbook.View.ActiveTab;
                var sheet = package.Workbook.Worksheets[sheetNo];

                // 表示倍率の取得
                Console.WriteLine(sheet.View.ZoomScale);

                // 表示倍率の設定
                sheet.View.ZoomScale = 200;

                // あらためて書き込み用としてStreamを開く
                using (var writeStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    // 書き込み
                    package.SaveAs(writeStream);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"エラー: {ex.Message}");
        }
    }
}

ExcelDataReader

読み取りのみのライブラリのためなし

NPOI

□xls

using NPOI.HSSF.UserModel;
using System;
using System.IO;
using System.Reflection;


namespace SampleCode; // C#10~

internal class SampleNPOI_xls
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xls");

            // メモリにすべて取り込む。これなら遅延でStreamにアクセスするような問題が発生しない
            byte[] fileBytes = File.ReadAllBytes(filePath);
            using (var readStream = new MemoryStream(fileBytes))
            using (var workbook = new HSSFWorkbook(readStream))
            {
                // Activeなシートを取得
                var sheetNo = workbook.ActiveSheetIndex;
                var sheet = workbook.GetSheetAt(sheetNo);

                // 表示倍率の取得(標準APIで提供されていない)

                // 表示倍率の設定
                sheet.SetZoom(200);

                // あらためて書き込み用としてStreamを開く
                using (var writeStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    // 書き込み
                    workbook.Write(writeStream);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

□xlsx

using NPOI.XSSF.UserModel;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleNPOI_xlsx
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // メモリにすべて取り込む。これなら遅延でStreamにアクセスするような問題が発生しない
            byte[] fileBytes = File.ReadAllBytes(filePath);
            using (var readStream = new MemoryStream(fileBytes))
            using (var workbook = new XSSFWorkbook(readStream))
            {
                // Activeなシートを取得
                var sheetNo = workbook.ActiveSheetIndex;
                var sheet = workbook.GetSheetAt(sheetNo);

                // 表示倍率の取得(標準APIで提供されていない)

                // 表示倍率の設定
                sheet.SetZoom(200);

                // あらためて書き込み用としてStreamを開く
                using (var writeStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    // 書き込み
                    workbook.Write(writeStream);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

□xlsもxlsxも扱う場合
Program.cs

using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleNPOI
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            var extension = Path.GetExtension(filePath);

            // メモリにすべて取り込む。これなら遅延でStreamにアクセスするような問題が発生しない
            byte[] fileBytes = File.ReadAllBytes(filePath);
            using (var readStream = new MemoryStream(fileBytes))
            using (var workbook = WorkbookFactory.Create(readStream, extension))
            {
                // Activeなシートを取得
                var sheetNo = workbook.ActiveSheetIndex;
                var sheet = workbook.GetSheetAt(sheetNo);

                // 表示倍率の取得(標準APIで提供されていない)

                // 表示倍率の設定
                sheet.SetZoom(200);

                // あらためて書き込み用としてStreamを開く
                using (var writeStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    // 書き込み
                    workbook.Write(writeStream);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

WorkbookFactory.cs

using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.IO;

namespace SampleCode
{
    public class WorkbookFactory
    {
        public static IWorkbook Create(Stream stream, string extension)
        {
            extension = extension.ToLower();

            return extension switch
            {
                ".xls" => new HSSFWorkbook(stream),
                ".xlsx" => new XSSFWorkbook(stream),
                _ => throw new NotSupportedException("対象外の拡張子です")
            };
        }

        public static IWorkbook Create(string extension)
        {
            extension = extension.ToLower();

            return extension switch
            {
                ".xls" => new HSSFWorkbook(),
                ".xlsx" => new XSSFWorkbook(),
                _ => throw new NotSupportedException("対象外の拡張子です")
            };
        }
    }
}
投稿日時: 2025-05-27 15:14:27

3つシートがあり、Sheet1とSheet2をIndexと名前を指定して削除してみます

ExcelVBA

Sub Sample()
    Dim BookObj     As Workbook
    Dim FilePath    As String
    
    'ファイルパス作成
    FilePath = ThisWorkbook.Path & "\sample.xlsx"
    
    'ブックを開く
    Set BookObj = Workbooks.Open(FilePath)
    
    
    Application.DisplayAlerts = False 'ダイアログ表示抑制
    
    'Index番号を指定して削除
    BookObj.Worksheets(1).Delete
    
    '名前を指定して削除
    BookObj.Sheets("Sheet2").Delete
    
    Application.DisplayAlerts = True 'ダイアログ表示抑制解除

    '閉じる
    BookObj.Save
    
    Set BookObj = Nothing
End Sub

Excel(COM)

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

namespace SampleCode; // C#10~

internal class SampleExcel
{
    static void Main(string[] args)
    {
        Excel.Application? application = null;
        Excel.Workbooks? workbooks = null;
        Excel.Workbook? workbook = null;
        Excel.Sheets? worksheets = null;
        Excel.Worksheet? worksheet1 = null;
        Excel.Worksheet? worksheet2 = null;

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // Excelを開く
            application = new Excel.Application();
            application.Visible = true;

            // ブックを開く
            workbooks = application.Workbooks;
            workbook = workbooks.Open(filePath);

            // シートを取得
            worksheets = workbook.Sheets;

            application.DisplayAlerts = false; // ダイアログ表示抑制

            // Index番号で取得して削除
            worksheet1 = worksheets[1];
            worksheet1.Delete();

            // 名前で取得して削除
            worksheet2 = worksheets["Sheet2"];
            worksheet2.Delete();

            application.DisplayAlerts = true; // ダイアログ表示抑制解除

            // 保存
            workbook.Save();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        finally
        {
            CleanUpComObject(ref worksheet1);
            CleanUpComObject(ref worksheet2);
            CleanUpComObject(ref worksheets);
            CleanUpComObject(ref workbook);
            CleanUpComObject(ref workbooks);
            CleanUpComObject(ref application);
        }
    }

    static void CleanUpComObject<T>(ref T comObject, bool shouldClose = true, bool saveChanges = false)
    {
        // フラグによってWorkbookはClose / ApplicationはQuitする
        if (shouldClose && comObject != null)
        {
            // 型をチェックする
            if (comObject is Microsoft.Office.Interop.Excel.Workbook workbook)
            {
                // Workbookの場合
                workbook.Close(saveChanges);
            }
            else if (comObject is Microsoft.Office.Interop.Excel.Application application)
            {
                // Applicationの場合
                application.Quit();
            }
        }

        // Objectを解放
        if (comObject != null && Marshal.IsComObject(comObject))
        {
            Marshal.ReleaseComObject(comObject);
            comObject = default!;
        }
    }
}

補足:Microsoft.Office.Interop.Excel でオブジェクトの解放について

ClosedXML

using ClosedXML.Excel;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleClosedXML
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // ブックを開く、読み書きモード、共有なし(排他)
            using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            using (var workbook = new XLWorkbook(fileStream))
            {
                // Index番号で取得して削除
                workbook.Worksheet(1).Delete();

                // 名前で取得して削除
                workbook.Worksheet("Sheet2").Delete();

                // 保存
                workbook.Save();
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

EPPlus

using OfficeOpenXml;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleEPPlus
{
    static void Main(string[] args)
    {
        // Ver8.0のソースです
        // 非商用個人利用の場合 名前を設定
        ExcelPackage.License.SetNonCommercialPersonal("SampleTarou");

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // メモリにすべて取り込む。これなら遅延でStreamにアクセスするような問題が発生しない
            byte[] fileBytes = File.ReadAllBytes(filePath);
            using (var readStream = new MemoryStream(fileBytes))
            using (var package = new ExcelPackage(readStream))
            {
                // Index番号で取得して削除
                package.Workbook.Worksheets.Delete(0);

                // 名前で取得して削除
                package.Workbook.Worksheets.Delete("Sheet2");

                // あらためて書き込み用としてStreamを開く
                using (var writeStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    // 書き込み
                    package.SaveAs(writeStream);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"エラー: {ex.Message}");
        }
    }
}

ExcelDataReader

読み取りのみのライブラリのためなし

NPOI

□xls

using NPOI.HSSF.UserModel;
using System;
using System.IO;
using System.Reflection;


namespace SampleCode; // C#10~

internal class SampleNPOI_xls
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xls");

            // メモリにすべて取り込む。これなら遅延でStreamにアクセスするような問題が発生しない
            byte[] fileBytes = File.ReadAllBytes(filePath);
            using (var readStream = new MemoryStream(fileBytes))
            using (var workbook = new HSSFWorkbook(readStream))
            {
                // Index番号を指定して削除
                workbook.RemoveSheetAt(0);

                // 名前を指定して直接削除はできないっぽい
                var index = workbook.GetSheetIndex("Sheet2");
                workbook.RemoveSheetAt(index); // 名前→Index番号→Index番号で削除

                // あらためて書き込み用としてStreamを開く
                using (var writeStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    // 書き込み
                    workbook.Write(writeStream);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

□xlsx

using NPOI.XSSF.UserModel;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleNPOI_xlsx
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // メモリにすべて取り込む。これなら遅延でStreamにアクセスするような問題が発生しない
            byte[] fileBytes = File.ReadAllBytes(filePath);
            using (var readStream = new MemoryStream(fileBytes))
            using (var workbook = new XSSFWorkbook(readStream))
            {
                // Index番号を指定して削除
                workbook.RemoveSheetAt(0);

                // 名前を指定して直接削除はできないっぽい
                var index = workbook.GetSheetIndex("Sheet2");
                workbook.RemoveSheetAt(index); // 名前→Index番号→Index番号で削除

                // あらためて書き込み用としてStreamを開く
                using (var writeStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    // 書き込み
                    workbook.Write(writeStream);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

□xlsもxlsxも扱う場合
Program.cs

using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleNPOI
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            var extension = Path.GetExtension(filePath);

            // メモリにすべて取り込む。これなら遅延でStreamにアクセスするような問題が発生しない
            byte[] fileBytes = File.ReadAllBytes(filePath);
            using (var readStream = new MemoryStream(fileBytes))
            using (var workbook = WorkbookFactory.Create(readStream, extension))
            {
                // Index番号を指定して削除
                workbook.RemoveSheetAt(0);

                // 名前を指定して直接削除はできないっぽい
                var index = workbook.GetSheetIndex("Sheet2");
                workbook.RemoveSheetAt(index); // 名前→Index番号→Index番号で削除

                // あらためて書き込み用としてStreamを開く
                using (var writeStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    // 書き込み
                    workbook.Write(writeStream);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

WorkbookFactory.cs

using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.IO;

namespace SampleCode
{
    public class WorkbookFactory
    {
        public static IWorkbook Create(Stream stream, string extension)
        {
            extension = extension.ToLower();

            return extension switch
            {
                ".xls" => new HSSFWorkbook(stream),
                ".xlsx" => new XSSFWorkbook(stream),
                _ => throw new NotSupportedException("対象外の拡張子です")
            };
        }

        public static IWorkbook Create(string extension)
        {
            extension = extension.ToLower();

            return extension switch
            {
                ".xls" => new HSSFWorkbook(),
                ".xlsx" => new XSSFWorkbook(),
                _ => throw new NotSupportedException("対象外の拡張子です")
            };
        }
    }
}
投稿日時: 2025-05-27 14:33:27

シート名を変更する

ExcelVBA

Sub Sample()
    Dim BookObj     As Workbook
    Dim FilePath    As String
    Dim SheetObj    As Worksheet
    
    'ファイルパス作成
    FilePath = ThisWorkbook.Path & "\sample.xlsx"
    
    'ブックを開く
    Set BookObj = Workbooks.Open(FilePath)
    
    '最初のシートを取得
    Set SheetObj = BookObj.Sheets(1)
    
    'シート名を変更
    SheetObj.Name = "abc"
    
    '閉じる
    BookObj.Save
    
    Set BookObj = Nothing
    Set SheetObj = Nothing
End Sub

Excel(COM)

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

namespace SampleCode; // C#10~

internal class SampleExcel
{
    static void Main(string[] args)
    {
        Excel.Application? application = null;
        Excel.Workbooks? workbooks = null;
        Excel.Workbook? workbook = null;
        Excel.Sheets? worksheets = null;
        Excel.Worksheet? worksheet = null;

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // Excelを開く
            application = new Excel.Application();
            application.Visible = true;

            // ブックを開く
            workbooks = application.Workbooks;
            workbook = workbooks.Open(filePath);

            // シートを取得
            worksheets = workbook.Sheets;

            // 最初のシートを取得
            worksheet = worksheets[1];

            // シート名変更
            worksheet.Name = "abc";

            // 保存
            workbook.Save();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        finally
        {
            CleanUpComObject(ref worksheet);
            CleanUpComObject(ref worksheets);
            CleanUpComObject(ref workbook);
            CleanUpComObject(ref workbooks);
            CleanUpComObject(ref application);
        }
    }

    static void CleanUpComObject<T>(ref T comObject, bool shouldClose = true, bool saveChanges = false)
    {
        // フラグによってWorkbookはClose / ApplicationはQuitする
        if (shouldClose && comObject != null)
        {
            // 型をチェックする
            if (comObject is Microsoft.Office.Interop.Excel.Workbook workbook)
            {
                // Workbookの場合
                workbook.Close(saveChanges);
            }
            else if (comObject is Microsoft.Office.Interop.Excel.Application application)
            {
                // Applicationの場合
                application.Quit();
            }
        }

        // Objectを解放
        if (comObject != null && Marshal.IsComObject(comObject))
        {
            Marshal.ReleaseComObject(comObject);
            comObject = default!;
        }
    }
}

補足:Microsoft.Office.Interop.Excel でオブジェクトの解放について

ClosedXML

using ClosedXML.Excel;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleClosedXML
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // ブックを開く、読み書きモード、共有なし(排他)
            using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            using (var workbook = new XLWorkbook(stream))
            {
                // 最初のシートを取得
                var worksheet = workbook.Worksheet(1);

                // シート名変更
                worksheet.Name = "abc";

                // 上書き保存
                workbook.Save();
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

EPPlus

using OfficeOpenXml;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleEPPlus
{
    static void Main(string[] args)
    {
        // Ver8.0のソースです
        // 非商用個人利用の場合 名前を設定
        ExcelPackage.License.SetNonCommercialPersonal("SampleTarou");

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // メモリにすべて取り込む。これなら遅延でStreamにアクセスするような問題が発生しない
            byte[] fileBytes = File.ReadAllBytes(filePath);
            using (var readStream = new MemoryStream(fileBytes))
            using (var package = new ExcelPackage(readStream))
            {
                // シートを取得
                var worksheet = package.Workbook.Worksheets[0];
                worksheet.Name = "abc";

                // あらためて書き込み用としてStreamを開く
                using (var writeStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    // 書き込み
                    package.SaveAs(writeStream);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"エラー: {ex.Message}");
        }
    }
}

ExcelDataReader

読み取りのみのライブラリのためなし

NPOI

□xls

using NPOI.HSSF.UserModel;
using System;
using System.IO;
using System.Reflection;


namespace SampleCode; // C#10~

internal class SampleNPOI_xls
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xls");

            // メモリにすべて取り込む。これなら遅延でStreamにアクセスするような問題が発生しない
            byte[] fileBytes = File.ReadAllBytes(filePath);
            using (var readStream = new MemoryStream(fileBytes))
            using (var workbook = new HSSFWorkbook(readStream))
            {
                // 最初のシートの名前を変える
                workbook.SetSheetName(0, "abc");

                // あらためて書き込み用としてStreamを開く
                using (var writeStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    // 書き込み
                    workbook.Write(writeStream);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

□xlsx

using NPOI.XSSF.UserModel;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleNPOI_xlsx
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // メモリにすべて取り込む。これなら遅延でStreamにアクセスするような問題が発生しない
            byte[] fileBytes = File.ReadAllBytes(filePath);
            using (var readStream = new MemoryStream(fileBytes))
            using (var workbook = new XSSFWorkbook(readStream))
            {
                // 最初のシートの名前を変える
                workbook.SetSheetName(0, "abc");

                // あらためて書き込み用としてStreamを開く
                using (var writeStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    // 書き込み
                    workbook.Write(writeStream);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

□xlsもxlsxも扱う場合
Program.cs

using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleNPOI
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            var extension = Path.GetExtension(filePath);

            // メモリにすべて取り込む。これなら遅延でStreamにアクセスするような問題が発生しない
            byte[] fileBytes = File.ReadAllBytes(filePath);
            using (var readStream = new MemoryStream(fileBytes))
            using (var workbook = WorkbookFactory.Create(readStream, extension))
            {
                // 最初のシートの名前を変える
                workbook.SetSheetName(0, "abc");

                // あらためて書き込み用としてStreamを開く
                using (var writeStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    // 書き込み
                    workbook.Write(writeStream);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

WorkbookFactory.cs

using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.IO;

namespace SampleCode
{
    public class WorkbookFactory
    {
        public static IWorkbook Create(Stream stream, string extension)
        {
            extension = extension.ToLower();

            return extension switch
            {
                ".xls" => new HSSFWorkbook(stream),
                ".xlsx" => new XSSFWorkbook(stream),
                _ => throw new NotSupportedException("対象外の拡張子です")
            };
        }

        public static IWorkbook Create(string extension)
        {
            extension = extension.ToLower();

            return extension switch
            {
                ".xls" => new HSSFWorkbook(),
                ".xlsx" => new XSSFWorkbook(),
                _ => throw new NotSupportedException("対象外の拡張子です")
            };
        }
    }
}
投稿日時: 2025-05-27 11:57:27
更新日時: 2025-05-27 12:10:27

ExcelVBA

Sub Sample()
    Dim BookObj     As Workbook
    Dim FilePath    As String
    
    'ファイルパス作成
    FilePath = ThisWorkbook.Path & "\sample.xlsx"
    
    'ブックを開く
    Set BookObj = Workbooks.Open(FilePath)
    
    '上書き保存
    BookObj.Save
    
    '閉じる
    BookObj.Close
    
    Set BookObj = Nothing
End Sub

Excel(COM)

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

namespace SampleCode; // C#10~

internal class SampleExcel
{
    static void Main(string[] args)
    {
        Excel.Application? application = null;
        Excel.Workbooks? workbooks = null;
        Excel.Workbook? workbook = null;
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // Excelを開く
            application = new Excel.Application();
            application.Visible = true;

            // ブックを開く
            workbooks = application.Workbooks;
            workbook = workbooks.Open(filePath);

            // 上書き保存
            workbook.Save();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        finally
        {
            CleanUpComObject(ref workbook);
            CleanUpComObject(ref workbooks);
            CleanUpComObject(ref application);

            // RCW強制解放(残留プロセス対策)
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            GC.WaitForPendingFinalizers();
        }
    }

    static void CleanUpComObject<T>(ref T comObject, bool shouldClose = true, bool saveChanges = false)
    {
        // フラグによってWorkbookはClose / ApplicationはQuitする
        if (shouldClose && comObject != null)
        {
            // 型をチェックする
            if (comObject is Microsoft.Office.Interop.Excel.Workbook workbook)
            {
                // Workbookの場合
                workbook.Close(saveChanges);
            }
            else if (comObject is Microsoft.Office.Interop.Excel.Application application)
            {
                // Applicationの場合
                application.Quit();
            }
        }

        // Objectを解放
        if (comObject != null && Marshal.IsComObject(comObject))
        {
            Marshal.ReleaseComObject(comObject);
            comObject = default!;
        }
    }
}

補足:Microsoft.Office.Interop.Excel でオブジェクトの解放について

ClosedXML

ファイルパスでもFileStreamでもSaveで上書きできる
□ファイルパス

using ClosedXML.Excel;
using System;
using System.IO;
using System.Linq;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleClosedXML
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            using (var workbook = new XLWorkbook(filePath))
            {
                // 上書き保存
                workbook.Save();
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

□FileStream

using ClosedXML.Excel;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleClosedXML
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // ブックを開く、読み書きモード、共有なし(排他)
            using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            using (var workbook = new XLWorkbook(stream))
            {
                // 上書き保存
                workbook.Save();
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

EPPlus

□ファイルパス

using OfficeOpenXml;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleEPPlus
{
    static void Main(string[] args)
    {
        // Ver8.0のソースです
        // 非商用個人利用の場合 名前を設定
        ExcelPackage.License.SetNonCommercialPersonal("SampleTarou");

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            using (var package = new ExcelPackage(filePath))
            {
                // 上書き保存
                package.Save();
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

□FileInfo

using OfficeOpenXml;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleEPPlus
{
    static void Main(string[] args)
    {
        // Ver8.0のソースです
        // 非商用個人利用の場合 名前を設定
        ExcelPackage.License.SetNonCommercialPersonal("SampleTarou");

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");
            var fileInfo = new FileInfo(filePath);

             // 上書き保存
            using (var package = new ExcelPackage(fileInfo))
            {
                package.Save();
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

□FileStream

using Microsoft.Extensions.FileProviders;
using OfficeOpenXml;
using System;
using System.IO;
using System.IO.Pipes;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleEPPlus
{
    static void Main(string[] args)
    {
        // Ver8.0のソースです
        // 非商用個人利用の場合 名前を設定
        ExcelPackage.License.SetNonCommercialPersonal("SampleTarou");

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // メモリにすべて取り込む。これなら遅延でStreamにアクセスするような問題が発生しない
            byte[] fileBytes = File.ReadAllBytes(filePath);
            using( var readStream = new MemoryStream(fileBytes))
            using (var package = new ExcelPackage(readStream))
            {
                package.Workbook.Worksheets[0].Cells["A1"].Value = DateTime.Now.ToString("HH:mm:ss");

                // あらためて書き込み用としてStreamを開く
                using (var writeStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    // 書き込み
                    package.SaveAs(writeStream);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

ExcelDataReader

読み取りのみのライブラリのためなし

NPOI

□xls

using NPOI.HSSF.UserModel;
using System;
using System.IO;
using System.Reflection;


namespace SampleCode; // C#10~

internal class SampleNPOI_xls
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xls");

            // メモリにすべて取り込む。これなら遅延でStreamにアクセスするような問題が発生しない
            byte[] fileBytes = File.ReadAllBytes(filePath);
            using (var readStream = new MemoryStream(fileBytes))
            using (var workbook = new HSSFWorkbook(readStream))
            {
                // シートを取得
                var worksheet = workbook.GetSheetAt(0);

                var row = worksheet.GetRow(0) ?? worksheet.CreateRow(0);
                var cell = row.GetCell(0) ?? row.CreateCell(0);
                cell.SetCellValue(DateTime.Now.ToString("HH:mm:ss"));

                // あらためて書き込み用としてStreamを開く
                using (var writeStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    // 書き込み
                    workbook.Write(writeStream);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

□xlsx

using NPOI.XSSF.UserModel;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleNPOI_xlsx
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // メモリにすべて取り込む。これなら遅延でStreamにアクセスするような問題が発生しない
            byte[] fileBytes = File.ReadAllBytes(filePath);
            using (var readStream = new MemoryStream(fileBytes))
            using (var workbook = new XSSFWorkbook(readStream))
            {
                // シートを取得
                var worksheet = workbook.GetSheetAt(0);

                var row = worksheet.GetRow(0) ?? worksheet.CreateRow(0);
                var cell = row.GetCell(0) ?? row.CreateCell(0);
                cell.SetCellValue(DateTime.Now.ToString("HH:mm:ss"));

                // あらためて書き込み用としてStreamを開く
                using (var writeStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    // 書き込み
                    workbook.Write(writeStream);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

□xls/xlsx対応版
Program.cs

using NPOI.XSSF.UserModel;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleNPOI
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            var extension = Path.GetExtension(filePath);

            // メモリにすべて取り込む。これなら遅延でStreamにアクセスするような問題が発生しない
            byte[] fileBytes = File.ReadAllBytes(filePath);
            using (var readStream = new MemoryStream(fileBytes))
            using (var workbook = WorkbookFactory.Create(readStream, extension))
            {
                // シートを取得
                var worksheet = workbook.GetSheetAt(0);

                var row = worksheet.GetRow(0) ?? worksheet.CreateRow(0);
                var cell = row.GetCell(0) ?? row.CreateCell(0);
                cell.SetCellValue(DateTime.Now.ToString("HH:mm:ss"));

                // あらためて書き込み用としてStreamを開く
                using (var writeStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    // 書き込み
                    workbook.Write(writeStream);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

WorkbookFactory.cs

using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.IO;

namespace SampleCode
{
    public class WorkbookFactory
    {
        public static IWorkbook Create(Stream stream, string extension)
        {
            extension = extension.ToLower();

            return extension switch
            {
                ".xls" => new HSSFWorkbook(stream),
                ".xlsx" => new XSSFWorkbook(stream),
                _ => throw new NotSupportedException("対象外の拡張子です")
            };
        }

        public static IWorkbook Create(string extension)
        {
            extension = extension.ToLower();

            return extension switch
            {
                ".xls" => new HSSFWorkbook(),
                ".xlsx" => new XSSFWorkbook(),
                _ => throw new NotSupportedException("対象外の拡張子です")
            };
        }
    }
}
投稿日時: 2025-05-25 03:38:25
更新日時: 2025-05-26 14:27:26

シートが3つあり、Sheet3がアクティブな状態のExcelを使用

ExcelVBA

Sub Sample()
    Dim BookObj     As Workbook
    Dim FilePath    As String
    Dim SheetObj    As Worksheet
    
    'ファイルパス作成
    FilePath = ThisWorkbook.Path & "\sample.xlsx"
    
    'ブックを開く
    Set BookObj = Workbooks.Open(FilePath)
    
    'Activeなシートを取得
    Set SheetObj = BookObj.ActiveSheet
    Debug.Print "Activeなシート名:" & SheetObj.Name ' Activeなシート名:Sheet3
    
    'Activeなシートを変更
    BookObj.Sheets(2).Activate
    
    'Activeなシートを取得
    Set SheetObj = BookObj.ActiveSheet
    Debug.Print "Activeなシート名:" & SheetObj.Name ' Activeなシート名:Sheet2
    
    BookObj.Close (False)
    
    Set BookObj = Nothing
    Set SheetObj = Nothing
End Sub

Excel(COM)

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

namespace SampleCode; // C#10~

internal class SampleExcel
{
    static void Main(string[] args)
    {
        Excel.Application? application = null;
        Excel.Workbooks? workbooks = null;
        Excel.Workbook? workbook = null;
        Excel.Sheets? worksheets = null;
        Excel.Worksheet? worksheet = null;
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // Excelを開く
            application = new Excel.Application();
            application.Visible = true;

            // ブックを開く
            workbooks = application.Workbooks;
            workbook = workbooks.Open(filePath);

            // Activeなシートを取得
            worksheet = workbook.ActiveSheet;
            Console.WriteLine($"Activeなシート名:{worksheet.Name}"); // Activeなシート名:Sheet3
            CleanUpComObject(ref worksheet);

            // Activeなシートを変更
            worksheets = workbook.Sheets;
            worksheet = worksheets[2];
            worksheet.Activate();
            CleanUpComObject(ref worksheet);

            // Activeなシートを取得
            worksheet = workbook.ActiveSheet;
            Console.WriteLine($"Activeなシート名:{worksheet.Name}"); // Activeなシート名:Sheet2
            CleanUpComObject(ref worksheet);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        finally
        {
            CleanUpComObject(ref worksheet);
            CleanUpComObject(ref worksheets);
            CleanUpComObject(ref workbook, true, false);
            CleanUpComObject(ref workbooks);
            CleanUpComObject(ref application);

            // RCW強制解放(残留プロセス対策)
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            GC.WaitForPendingFinalizers();
        }
    }

    static void CleanUpComObject<T>(ref T comObject, bool shouldClose = true, bool saveChanges = false)
    {
        // フラグによってWorkbookはClose / ApplicationはQuitする
        if (shouldClose && comObject != null)
        {
            // 型をチェックする
            if (comObject is Microsoft.Office.Interop.Excel.Workbook workbook)
            {
                // Workbookの場合
                workbook.Close(saveChanges);
            }
            else if (comObject is Microsoft.Office.Interop.Excel.Application application)
            {
                // Applicationの場合
                application.Quit();
            }
        }

        // Objectを解放
        if (comObject != null && Marshal.IsComObject(comObject))
        {
            Marshal.ReleaseComObject(comObject);
            comObject = default!;
        }
    }
}

補足:Microsoft.Office.Interop.Excel でオブジェクトの解放について

ClosedXML

using ClosedXML.Excel;
using System;
using System.IO;
using System.Linq;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleClosedXML
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // ブックを開く、読み書きモード、共有なし(排他)
            using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            using (var workbook = new XLWorkbook(fileStream))
            {
                // Activeなシートを取得
                var sheet = workbook.Worksheets.First(ws => ws.TabActive);
                Console.WriteLine($"Activeなシート名:{sheet.Name}"); // Activeなシート名:Sheet3

                // Activeなシートを変更
                workbook.Worksheet("Sheet2").SetTabActive();

                // Activeなシートを取得
                sheet = workbook.Worksheets.First(ws => ws.TabActive);
                Console.WriteLine($"Activeなシート名:{sheet.Name}"); // Activeなシート名:Sheet2
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

EPPlus

using OfficeOpenXml;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleEPPlus
{
    static void Main(string[] args)
    {
        // Ver8.0のソースです
        // 非商用個人利用の場合 名前を設定
        ExcelPackage.License.SetNonCommercialPersonal("SampleTarou");

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // ブックを開く、読み書きモード、共有なし(排他)
            using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            using (var package = new ExcelPackage(stream))
            {
                // Activeなシート番号を取得(シート番号は0から)
                var sheetNo = package.Workbook.View.ActiveTab; // 2

                // Activeなシートを取得
                var sheet = package.Workbook.Worksheets[sheetNo];
                Console.WriteLine($"Activeなシート名:{sheet.Name}"); // Activeなシート名:Sheet3

                // Activeなシートを変更(シート番号は0から)
                sheetNo = 1;
                package.Workbook.View.ActiveTab = sheetNo;

                // Activeなシートだけtrueにし、それ以外はfalseにする
                for(var n = 0; n < package.Workbook.Worksheets.Count; n++)
                {
                    package.Workbook.Worksheets[n].View.TabSelected = (n == sheetNo);
                }

                // Activeなシートを取得
                sheet = package.Workbook.Worksheets[sheetNo];
                Console.WriteLine($"Activeなシート名:{sheet.Name}"); // Activeなシート名:Sheet2
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

ExcelDataReader

該当機能なし

NPOI

□xls

using NPOI.HSSF.UserModel;
using System;
using System.IO;
using System.Reflection;


namespace SampleCode; // C#10~

internal class SampleNPOI_xls
{
    static void Main(string[] args)
    {
        var filePath = "";

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            filePath = Path.Combine(folderPath, "sample.xls");

            // ブックを開く、読み書きモード、共有なし(排他)
            using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            using (var workbook = new HSSFWorkbook(fileStream))
            {
                // ■Activeなシートの取得
                // Activeなシート番号を取得(シート番号は0から)
                var sheetNo = workbook.ActiveSheetIndex; // 2

                // Activeなシートを取得
                var sheet = workbook.GetSheetAt(sheetNo);
                Console.WriteLine($"Activeなシート名:{sheet.SheetName}");

                // ■Activeなシートの変更
                // Activeなシートを変更
                sheetNo = 1;
                workbook.SetActiveSheet(sheetNo); // Sheet2をActiveに設定する(これを変えただけじゃかわらない)
                workbook.SetSelectedTab(sheetNo); //こちらも変えるといいとのこと

                // 上記2つの設定で変わったが・・・
                // IsSelectedまで返ると完璧とのこと
                for(var n = 0; n < workbook.NumberOfSheets; n++)
                {
                    workbook.GetSheetAt(n).IsSelected = (n == sheetNo);
                }

                // Activeなシートを取得
                sheet = workbook.GetSheetAt(sheetNo);
                Console.WriteLine($"Activeなシート名:{sheet.SheetName}");
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

□xlsx

using NPOI.XSSF.UserModel;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleNPOI_xlsx
{
    static void Main(string[] args)
    {
        var filePath = "";

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            filePath = Path.Combine(folderPath, "sample.xlsx");

            // ブックを開く、読み書きモード、共有なし(排他)
            using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            using (var workbook = new XSSFWorkbook(fileStream))
            {
                // ■Activeなシートの取得
                // Activeなシート番号を取得(シート番号は0から)
                var sheetNo = workbook.ActiveSheetIndex; // 2

                // Activeなシートを取得
                var sheet = workbook.GetSheetAt(sheetNo);
                Console.WriteLine($"Activeなシート名:{sheet.SheetName}");

                // ■Activeなシートの変更
                // Activeなシートを変更
                sheetNo = 1;
                workbook.SetActiveSheet(sheetNo); // Sheet2をActiveに設定する(これを変えただけじゃかわらない)
                workbook.SetSelectedTab(sheetNo); //こちらも変えるといいとのこと

                // 上記2つの設定で変わったが・・・
                // IsSelectedまで返ると完璧とのこと
                for (var n = 0; n < workbook.NumberOfSheets; n++)
                {
                    workbook.GetSheetAt(n).IsSelected = (n == sheetNo);
                }

                // Activeなシートを取得
                sheet = workbook.GetSheetAt(sheetNo);
                Console.WriteLine($"Activeなシート名:{sheet.SheetName}");
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

□xlsもxlsxも扱う場合
Program.cs

using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleNPOI
{
    static void Main(string[] args)
    {
        var filePath = "";

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            filePath = Path.Combine(folderPath, "sample.xlsx");

            var extension = Path.GetExtension(filePath);

            // ブックを開く、読み書きモード、共有なし(排他)
            using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            using (var workbook = WorkbookFactory.Create(fileStream, extension))
            {
                // ■Activeなシートの取得
                // Activeなシート番号を取得(シート番号は0から)
                var sheetNo = workbook.ActiveSheetIndex; // 2

                // Activeなシートを取得
                var sheet = workbook.GetSheetAt(sheetNo);
                Console.WriteLine($"Activeなシート名:{sheet.SheetName}");

                // ■Activeなシートの変更
                // Activeなシートを変更
                sheetNo = 1;
                workbook.SetActiveSheet(sheetNo); // Sheet2をActiveに設定する(これを変えただけじゃかわらない)
                workbook.SetSelectedTab(sheetNo); //こちらも変えるといいとのこと

                // 上記2つの設定で変わったが・・・
                // IsSelectedまで返ると完璧とのこと
                for (var n = 0; n < workbook.NumberOfSheets; n++)
                {
                    workbook.GetSheetAt(n).IsSelected = (n == sheetNo);
                }

                // Activeなシートを取得
                sheet = workbook.GetSheetAt(sheetNo);
                Console.WriteLine($"Activeなシート名:{sheet.SheetName}");
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

WorkbookFactory.cs

using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.IO;

namespace SampleCode
{
    public class WorkbookFactory
    {
        public static IWorkbook Create(Stream stream, string extension)
        {
            extension = extension.ToLower();

            return extension switch
            {
                ".xls" => new HSSFWorkbook(stream),
                ".xlsx" => new XSSFWorkbook(stream),
                _ => throw new NotSupportedException("対象外の拡張子です")
            };
        }

        public static IWorkbook Create(string extension)
        {
            extension = extension.ToLower();

            return extension switch
            {
                ".xls" => new HSSFWorkbook(),
                ".xlsx" => new XSSFWorkbook(),
                _ => throw new NotSupportedException("対象外の拡張子です")
            };
        }
    }
}
投稿日時: 2025-05-24 18:23:24
更新日時: 2025-05-27 15:13:27

Sheet1シートがあるファイルを開き、
シート名で参照する方法と、シート番号で参照する方法
また、存在しないシート名を指定するとどうなるか確認

ExcelVBA

シート番号と名前でアクセスする方法
シート番号は1から始まることに注意
存在しない場合はエラーとなるので例外の対応を行っておく

Sub Sample()
    Dim BookObj     As Workbook
    Dim FilePath    As String
    Dim SheetObj    As Worksheet
    
    'ファイルパス作成
    FilePath = ThisWorkbook.Path & "\sample.xlsx"
    
    'ブックを開く
    Set BookObj = Workbooks.Open(FilePath)
    
    'シート番号で参照
    Set SheetObj = BookObj.Sheets(1)
    Debug.Print "シート番号で参照:" & SheetObj.Name
    
    '名前で参照
    Set SheetObj = BookObj.Sheets("Sheet1")
    Debug.Print "シート名で参照:" & SheetObj.Name
    
    On Error Resume Next
    '存在しない名前を指定して参照 => 例外が発生する
    Set SheetObj = BookObj.Sheets("AAA")
    
    If ERR.Number <> 0 Then
        Debug.Print ERR.Description 'インデックスが有効範囲にありません。
    End If
    
    On Error GoTo 0 'On Error Resume Next解除
    
    '保存せず閉じる
    BookObj.Close (False)
    
    Set BookObj = Nothing
    Set SheetObj = Nothing
End Sub

Excel(COM)

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

namespace SampleCode; // C#10~

internal class SampleExcel
{
    static void Main(string[] args)
    {
        Excel.Application? application = null;
        Excel.Workbooks? workbooks = null;
        Excel.Workbook? workbook = null;
        Excel.Sheets? worksheets = null;
        Excel.Worksheet? worksheet = null;
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // Excelを開く
            application = new Excel.Application();
            application.Visible = true;

            // ブックを開く
            workbooks = application.Workbooks;
            workbook = workbooks.Open(filePath);

            // シートを取得
            worksheets = workbook.Sheets;

            // シート番号で参照
            worksheet = worksheets[1];
            Console.WriteLine($"シート番号で参照:{worksheet.Name}");
            CleanUpComObject(ref worksheet);

            // シート名で参照
            worksheet = worksheets["Sheet1"];
            Console.WriteLine($"シート名で参照:{worksheet.Name}");
            CleanUpComObject(ref worksheet);

            try
            {
                // 存在しない名前を指定して参照 => 例外が発生する
                worksheet = worksheets["AAA"];
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message); // インデックスが無効です。 (0x8002000B (DISP_E_BADINDEX))
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        finally
        {
            CleanUpComObject(ref worksheet);
            CleanUpComObject(ref worksheets);
            CleanUpComObject(ref workbook, true, false);
            CleanUpComObject(ref workbooks);
            CleanUpComObject(ref application);

            // RCW強制解放(残留プロセス対策)
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            GC.WaitForPendingFinalizers();
        }
    }

    static void CleanUpComObject<T>(ref T comObject, bool shouldClose = true, bool saveChanges = false)
    {
        // フラグによってWorkbookはClose / ApplicationはQuitする
        if (shouldClose && comObject != null)
        {
            // 型をチェックする
            if (comObject is Microsoft.Office.Interop.Excel.Workbook workbook)
            {
                // Workbookの場合
                workbook.Close(saveChanges);
            }
            else if (comObject is Microsoft.Office.Interop.Excel.Application application)
            {
                // Applicationの場合
                application.Quit();
            }
        }

        // Objectを解放
        if (comObject != null && Marshal.IsComObject(comObject))
        {
            Marshal.ReleaseComObject(comObject);
            comObject = default!;
        }
    }
}

補足:Microsoft.Office.Interop.Excel でオブジェクトの解放について

ClosedXML

using ClosedXML.Excel;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleClosedXML
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // ブックを開く、読み書きモード、共有なし(排他)
            using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            using (var workbook = new XLWorkbook(fileStream))
            {
                // シート番号で参照
                var sheet = workbook.Worksheet(1);
                Console.WriteLine($"シート番号で参照:{sheet.Name}");

                // シート名で参照
                sheet = workbook.Worksheet("Sheet1");
                Console.WriteLine($"シート名で参照:{sheet.Name}");

                // 存在しない名前を指定して参照 => 例外発生する
                try
                {
                    sheet = workbook.Worksheet("AAA"); // There isn't a worksheet named 'AAA'.
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }

                // TryGetWorksheetを使うのも一つの手
                IXLWorksheet? worksheet = null;
                if (!workbook.TryGetWorksheet("AAA", out worksheet))
                {
                    Console.WriteLine("AAAシートないよ");
                }

                // 存在しないシートについては、Containsでtrue/falseを返してくれる
                if (!workbook.Worksheets.Contains("AAA"))
                {
                    Console.WriteLine("AAAシートないよ");
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

EPPlus

using OfficeOpenXml;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleEPPlus
{
    static void Main(string[] args)
    {
        // Ver8.0のソースです
        // 非商用個人利用の場合 名前を設定
        ExcelPackage.License.SetNonCommercialPersonal("SampleTarou");

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // ブックを開く、読み書きモード、共有なし(排他)
            using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            using (var package = new ExcelPackage(stream))
            {
                // シート番号で参照(シート番号は0から)
                var sheet = package.Workbook.Worksheets[0];
                Console.WriteLine($"シート番号で参照:{sheet.Name}");

                // シート名で参照
                sheet = package.Workbook.Worksheets["Sheet1"];
                Console.WriteLine($"シート名で参照:{sheet.Name}");

                // 存在しない名前を指定して参照 => nullを返す
                sheet = package.Workbook.Worksheets["AAA"];
                if(sheet == null)
                {
                    Console.WriteLine("AAAシートないよ");
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

ExcelDataReader

using ExcelDataReader;
using System;
using System.Data;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleExcelDataReader
{
    static void Main(string[] args)
    {
        // デフォルトでは、エンコード(CP1252)がサポートされておらずエラーになるのでこれが必要
        System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // ファイル開く、読み書きモード、共有なし(排他)
            using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
            using (var reader = ExcelReaderFactory.CreateReader(fileStream))
            {
                // DataSetに変換(シート情報を取得)
                var result = reader.AsDataSet();

                // シート番号で参照(シート番号は0から)
                var sheet = result.Tables[0];
                Console.WriteLine($"シート番号で参照:{sheet.TableName}");

                // シート名で参照
                sheet = result.Tables["Sheet1"];
                Console.WriteLine($"シート名で参照:{sheet.TableName}");

                // 存在しない名前を指定して参照 => nullを返す
                sheet = result.Tables["AAA"];
                if (sheet == null)
                {
                    Console.WriteLine("AAAシートないよ");
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

NPOI

□xls

using NPOI.HSSF.UserModel;
using System;
using System.IO;
using System.Reflection;


namespace SampleCode; // C#10~

internal class SampleNPOI_xls
{
    static void Main(string[] args)
    {
        var filePath = "";

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            filePath = Path.Combine(folderPath, "sample.xls");

            // ブックを開く、読み書きモード、共有なし(排他)
            using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            using (var workbook = new HSSFWorkbook(fileStream))
            {
                // シート番号で参照(シート番号は0から)
                var sheet = workbook.GetSheetAt(0);
                Console.WriteLine($"シート番号で参照:{sheet.SheetName}");

                // シート名で参照
                sheet = workbook.GetSheet("Sheet1");
                Console.WriteLine($"シート名で参照:{sheet.SheetName}");

                // 存在しない名前を指定して参照 => nullを返す
                sheet = workbook.GetSheet("AAA");
                if (sheet == null)
                {
                    Console.WriteLine("AAAシートないよ");
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

□xlsx

using NPOI.XSSF.UserModel;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleNPOI_xlsx
{
    static void Main(string[] args)
    {
        var filePath = "";

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            filePath = Path.Combine(folderPath, "sample.xlsx");

            // ブックを開く、読み書きモード、共有なし(排他)
            using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            using (var workbook = new XSSFWorkbook(fileStream))
            {
                // シート番号で参照(シート番号は0から)
                var sheet = workbook.GetSheetAt(0);
                Console.WriteLine($"シート番号で参照:{sheet.SheetName}");

                // シート名で参照
                sheet = workbook.GetSheet("Sheet1");
                Console.WriteLine($"シート名で参照:{sheet.SheetName}");

                // 存在しない名前を指定して参照 => nullを返す
                sheet = workbook.GetSheet("AAA");
                if (sheet == null)
                {
                    Console.WriteLine("AAAシートないよ");
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

□xlsもxlsxも扱う場合
Program.cs

using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleNPOI
{
    static void Main(string[] args)
    {
        var filePath = "";

        try
        {   // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            filePath = Path.Combine(folderPath, "sample.xlsx");

            var extension = Path.GetExtension(filePath);

            // ブックを開く、読み書きモード、共有なし(排他)
            using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            using (var workbook = WorkbookFactory.Create(fileStream, extension))
            {
                // シート番号で参照(シート番号は0から)
                var sheet = workbook.GetSheetAt(0);
                Console.WriteLine($"シート番号で参照:{sheet.SheetName}");

                // シート名で参照
                sheet = workbook.GetSheet("Sheet1");
                Console.WriteLine($"シート名で参照:{sheet.SheetName}");

                // 存在しない名前を指定して参照 => nullを返す
                sheet = workbook.GetSheet("AAA");
                if (sheet == null)
                {
                    Console.WriteLine("AAAシートないよ");
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

WorkbookFactory.cs

using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.IO;

namespace SampleCode
{
    public class WorkbookFactory
    {
        public static IWorkbook Create(Stream stream, string extension)
        {
            extension = extension.ToLower();

            return extension switch
            {
                ".xls" => new HSSFWorkbook(stream),
                ".xlsx" => new XSSFWorkbook(stream),
                _ => throw new NotSupportedException("対象外の拡張子です")
            };
        }

        public static IWorkbook Create(string extension)
        {
            extension = extension.ToLower();

            return extension switch
            {
                ".xls" => new HSSFWorkbook(),
                ".xlsx" => new XSSFWorkbook(),
                _ => throw new NotSupportedException("対象外の拡張子です")
            };
        }
    }
}
投稿日時: 2025-05-24 16:47:24
更新日時: 2025-05-27 14:33:27

ExcelVBA

Sub Sample()
    Dim BookObj         As Workbook
    Dim c               As Long
    Dim FilePath        As String
    Dim r               As Long
    Dim SheetObj        As Worksheet
        
    'ファイルパス作成
    FilePath = ThisWorkbook.Path & "\sample.xlsx"
    
    'ブックを開く
    Set BookObj = Workbooks.Open(FilePath)
    
    'シート取得
    Set SheetObj = BookObj.Sheets("Sheet1")
    
    SheetObj.Range("A1").Value = 1
    SheetObj.Range("A2").Value = 1.1
    SheetObj.Range("A3").Value = "abc"
    SheetObj.Range("A4").Value = Now
        
    '閉じる
    BookObj.Close
    
    Set BookObj = Nothing
    Set RangeData = Nothing
    Set SheetObj = Nothing
End Sub

Excel(COM)

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

namespace SampleCode; // C#10~

internal class SampleExcel
{
    static void Main(string[] args)
    {
        Excel.Application? application = null;
        Excel.Workbooks? workbooks = null;
        Excel.Workbook? workbook = null;
        Excel.Sheets? worksheets = null;
        Excel.Worksheet? worksheet = null;
        Excel.Range? cellData = null;

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");
            
            // Excelを開く
            application = new Excel.Application();
            application.Visible = true;

            // ブックを開く
            workbooks = application.Workbooks;
            workbook = workbooks.Open(filePath);

            // シートを取得
            worksheets = workbook.Sheets;
            worksheet = worksheets["Sheet1"];

            cellData = worksheet.Range["A1"];
            cellData.Value = 1;
            CleanUpComObject(ref cellData);

            cellData = worksheet.Range["A2"];
            cellData.Value = 1.1;
            CleanUpComObject(ref cellData);

            cellData = worksheet.Range["A3"];
            cellData.Value = "abc";
            CleanUpComObject(ref cellData);

            cellData = worksheet.Range["A4"];
            cellData.Value = DateTime.Now;
            CleanUpComObject(ref cellData);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        finally
        {
            CleanUpComObject(ref cellData);
            CleanUpComObject(ref worksheet);
            CleanUpComObject(ref worksheets);
            CleanUpComObject(ref workbook, true, true);
            CleanUpComObject(ref workbooks);
            CleanUpComObject(ref application);
        }
    }

    static void CleanUpComObject<T>(ref T comObject, bool shouldClose = true, bool saveChanges = false)
    {
        // フラグによってWorkbookはClose / ApplicationはQuitする
        if (shouldClose && comObject != null)
        {
            // 型をチェックする
            if (comObject is Microsoft.Office.Interop.Excel.Workbook workbook)
            {
                // Workbookの場合
                workbook.Close(saveChanges);
            }
            else if (comObject is Microsoft.Office.Interop.Excel.Application application)
            {
                // Applicationの場合
                application.Quit();
            }
        }

        // Objectを解放
        if (comObject != null && Marshal.IsComObject(comObject))
        {
            Marshal.ReleaseComObject(comObject);
            comObject = default!;
        }
    }
}

補足:Microsoft.Office.Interop.Excel でオブジェクトの解放について

ClosedXML

using ClosedXML.Excel;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleClosedXML
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");
            
            // ブックを開く、読み書きモード、共有なし(排他)
            using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            using (var workbook = new XLWorkbook(stream))
            {
                IXLWorksheet? worksheet = null;

                if(!workbook.TryGetWorksheet("Sheet1", out worksheet))
                {
                    throw new Exception("Sheet1シートがありませんでした");
                }

                worksheet.Cell("A1").Value = 1;
                worksheet.Cell("A2").Value = 1.1;
                worksheet.Cell("A3").Value = "abc";
                worksheet.Cell("A4").Value = DateTime.Now;

                workbook.Save();
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

EPPlus

using OfficeOpenXml;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleEPPlus
{
    static void Main(string[] args)
    {
        // Ver8.0のソースです
        // 非商用個人利用の場合 名前を設定
        ExcelPackage.License.SetNonCommercialPersonal("SampleTarou");

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // メモリにすべて取り込む。これなら遅延でStreamにアクセスするような問題が発生しない
            byte[] fileBytes = File.ReadAllBytes(filePath);
            using (var readStream = new MemoryStream(fileBytes))
            using (var package = new ExcelPackage(readStream))
            {
                // シートを取得
                var worksheet = package.Workbook.Worksheets["Sheet1"];

                worksheet.Cells["A1"].Value = 1;
                worksheet.Cells["A2"].Value = 1.1;
                worksheet.Cells["A3"].Value = "abc";
                worksheet.Cells["A4"].Value = DateTime.Now.ToString("yyyy/MM/dd");

                // あらためて書き込み用としてStreamを開く
                using (var writeStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    // 書き込み
                    package.SaveAs(writeStream);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"エラー: {ex.Message}");
        }
    }
}

ExcelDataReader

読み取りのみのライブラリのためなし

NPOI

□xls

using NPOI.HSSF.UserModel;
using System;
using System.IO;
using System.Reflection;


namespace SampleCode; // C#10~

internal class SampleNPOI_xls
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xls");

            // メモリにすべて取り込む。これなら遅延でStreamにアクセスするような問題が発生しない
            byte[] fileBytes = File.ReadAllBytes(filePath);
            using (var readStream = new MemoryStream(fileBytes))
            using (var workbook = new HSSFWorkbook(readStream))
            {
                // シートを取得
                var worksheet = workbook.GetSheet("Sheet1");

                // xls,xlsx共通で該当セルの情報がなければnullになるとのこと
                // 空=nullではないとのこと

                // A1セル
                var row = worksheet.GetRow(0) ?? worksheet.CreateRow(0);
                var cell = row.GetCell(0) ?? row.CreateCell(0);
                cell.SetCellValue(1);

                // A2セル
                row = worksheet.GetRow(1) ?? worksheet.CreateRow(1);
                cell = row.GetCell(0) ?? row.CreateCell(0);
                cell.SetCellValue(1.1);

                // A3セル
                row = worksheet.GetRow(2) ?? worksheet.CreateRow(2);
                cell = row.GetCell(0) ?? row.CreateCell(0);
                cell.SetCellValue("abc");

                // A4セル
                row = worksheet.GetRow(3) ?? worksheet.CreateRow(3);
                cell = row.GetCell(0) ?? row.CreateCell(0);
                cell.SetCellValue(DateTime.Now);

                // あらためて書き込み用としてStreamを開く
                using (var writeStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    // 書き込み
                    workbook.Write(writeStream);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

□xlsx

using NPOI.XSSF.UserModel;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleNPOI_xlsx
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // メモリにすべて取り込む。これなら遅延でStreamにアクセスするような問題が発生しない
            byte[] fileBytes = File.ReadAllBytes(filePath);
            using (var readStream = new MemoryStream(fileBytes))
            using (var workbook = new XSSFWorkbook(readStream))
            {
                // シートを取得
                var worksheet = workbook.GetSheet("Sheet1");

                // xls,xlsx共通で該当セルの情報がなければnullになるとのこと
                // 空=nullではないとのこと

                // A1セル
                var row = worksheet.GetRow(0) ?? worksheet.CreateRow(0);
                var cell = row.GetCell(0) ?? row.CreateCell(0);
                cell.SetCellValue(1);

                // A2セル
                row = worksheet.GetRow(0) ?? worksheet.CreateRow(0);
                cell = row.GetCell(0) ?? row.CreateCell(0);
                cell.SetCellValue(1.1);

                // A3セル
                row = worksheet.GetRow(0) ?? worksheet.CreateRow(0);
                cell = row.GetCell(0) ?? row.CreateCell(0);
                cell.SetCellValue("abc");

                // A4セル
                row = worksheet.GetRow(0) ?? worksheet.CreateRow(0);
                cell = row.GetCell(0) ?? row.CreateCell(0);
                cell.SetCellValue(DateTime.Now);

                // あらためて書き込み用としてStreamを開く
                using (var writeStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    // 書き込み
                    workbook.Write(writeStream);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

□xls/xlsx対応版

Program.cs

using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleNPOI
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            var extension = Path.GetExtension(filePath);

            // メモリにすべて取り込む。これなら遅延でStreamにアクセスするような問題が発生しない
            byte[] fileBytes = File.ReadAllBytes(filePath);
            using (var readStream = new MemoryStream(fileBytes))
            using (var workbook = WorkbookFactory.Create(readStream, extension))
            {
                // シートを取得
                var worksheet = workbook.GetSheet("Sheet1");

                // xls,xlsx共通で該当セルの情報がなければnullになるとのこと
                // 空=nullではないとのこと

                // A1セル
                var row = worksheet.GetRow(0) ?? worksheet.CreateRow(0);
                var cell = row.GetCell(0) ?? row.CreateCell(0);
                cell.SetCellValue(1);

                // A2セル
                row = worksheet.GetRow(0) ?? worksheet.CreateRow(0);
                cell = row.GetCell(0) ?? row.CreateCell(0);
                cell.SetCellValue(1.1);

                // A3セル
                row = worksheet.GetRow(0) ?? worksheet.CreateRow(0);
                cell = row.GetCell(0) ?? row.CreateCell(0);
                cell.SetCellValue("abc");

                // A4セル
                row = worksheet.GetRow(0) ?? worksheet.CreateRow(0);
                cell = row.GetCell(0) ?? row.CreateCell(0);
                cell.SetCellValue(DateTime.Now);

                // あらためて書き込み用としてStreamを開く
                using (var writeStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    // 書き込み
                    workbook.Write(writeStream);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

WorkbookFactory.cs

using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.IO;

namespace SampleCode; // C#10

public class WorkbookFactory
{
    public static IWorkbook Create(Stream stream, string extension)
    {
        extension = extension.ToLower();

        return extension switch
        {
            ".xls" => new HSSFWorkbook(stream),
            ".xlsx" => new XSSFWorkbook(stream),
            _ => throw new NotSupportedException("対象外の拡張子です")
        };
    }

    public static IWorkbook Create(string extension)
    {
        extension = extension.ToLower();

        return extension switch
        {
            ".xls" => new HSSFWorkbook(),
            ".xlsx" => new XSSFWorkbook(),
            _ => throw new NotSupportedException("対象外の拡張子です")
        };
    }
}
投稿日時: 2025-05-23 23:56:23
更新日時: 2025-05-26 14:57:26

ログを出力する際に、 "3行14列"というよりは、"N3" といった方がわかりやすいだろうから、
アドレスの取得方法について

ExcelVBA

Sub Sample()
    Dim BookObj         As Workbook
    Dim c               As Long
    Dim FilePath        As String
    Dim r               As Long
    Dim SheetObj        As Worksheet
        
    'ファイルパス作成
    FilePath = ThisWorkbook.Path & "\sample.xlsx"
    
    'ブックを開く
    Set BookObj = Workbooks.Open(FilePath)
    
    'シート取得
    Set SheetObj = BookObj.Sheets("Sheet1")
    
    '2行、3列の各セルのアドレスを出力
    For r = 1 To 2
        For c = 1 To 3
            Debug.Print r & "行" & c & "列 => " & SheetObj.Cells(r, c).Address
        Next
    Next
        
    '閉じる
    BookObj.Close
    
    Set BookObj = Nothing
    Set RangeData = Nothing
    Set SheetObj = Nothing
End Sub

Excel(COM)

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

namespace SampleCode; // C#10~

internal class SampleExcel
{
    static void Main(string[] args)
    {
        Excel.Application? application = null;
        Excel.Workbooks? workbooks = null;
        Excel.Workbook? workbook = null;
        Excel.Sheets? worksheets = null;
        Excel.Worksheet? worksheet = null;
        Excel.Range? cellData = null;

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");
            
            // Excelを開く
            application = new Excel.Application();
            application.Visible = true;

            // ブックを開く
            workbooks = application.Workbooks;
            workbook = workbooks.Open(filePath);

            // シートを取得
            worksheets = workbook.Sheets;
            worksheet = worksheets["Sheet1"];

            // 2行、3列の各セルのアドレスを出力
            for (var r = 1; r <= 2; r++)
            {
                for(var c = 1; c <= 3; c++)
                {
                    cellData = worksheet.Cells[r, c];
                    Console.WriteLine($"{r}行{c}列 => {cellData.Address}");

                    CleanUpComObject(ref cellData);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        finally
        {
            CleanUpComObject(ref cellData);
            CleanUpComObject(ref worksheet);
            CleanUpComObject(ref worksheets);
            CleanUpComObject(ref workbook);
            CleanUpComObject(ref workbooks);
            CleanUpComObject(ref application);
        }
    }

    static void CleanUpComObject<T>(ref T comObject, bool shouldClose = true, bool saveChanges = false)
    {
        // フラグによってWorkbookはClose / ApplicationはQuitする
        if (shouldClose && comObject != null)
        {
            // 型をチェックする
            if (comObject is Microsoft.Office.Interop.Excel.Workbook workbook)
            {
                // Workbookの場合
                workbook.Close(saveChanges);
            }
            else if (comObject is Microsoft.Office.Interop.Excel.Application application)
            {
                // Applicationの場合
                application.Quit();
            }
        }

        // Objectを解放
        if (comObject != null && Marshal.IsComObject(comObject))
        {
            Marshal.ReleaseComObject(comObject);
            comObject = default!;
        }
    }
}

補足:Microsoft.Office.Interop.Excel でオブジェクトの解放について

ClosedXML

using ClosedXML.Excel;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleClosedXML
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");
            
            // ブックを開く、読み書きモード、共有なし(排他)
            using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            using (var workbook = new XLWorkbook(stream))
            {
                IXLWorksheet? worksheet = null;

                if(!workbook.TryGetWorksheet("Sheet1", out worksheet))
                {
                    throw new Exception("Sheet1シートがありませんでした");
                }

                // 2行、3列の各セルのアドレスを出力
                for (var r = 1; r <= 2; r++)
                {
                    for (var c = 1; c <= 3; c++)
                    {
                        Console.WriteLine(worksheet.Cell(r, c).Address);
                    }
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

EPPlus

using OfficeOpenXml;
using System;
using System.IO;
using System.IO.Pipes;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleEPPlus
{
    static void Main(string[] args)
    {
        // Ver8.0のソースです
        // 非商用個人利用の場合 名前を設定
        ExcelPackage.License.SetNonCommercialPersonal("SampleTarou");

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");
            
            using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            using (var package = new ExcelPackage(stream))
            {
                // シートを取得
                var worksheet = package.Workbook.Worksheets["Sheet1"];

                // 2行、3列の各セルのアドレスを出力
                for (var r = 1; r <= 2; r++)
                {
                    for (var c = 1; c <= 3; c++)
                    {
                        Console.WriteLine(worksheet.Cells[r, c].Address); // 行, 列
                    }
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"エラー: {ex.Message}");
        }
    }
}

ExcelDataReader

※ライブラリ側にはアドレスを出力する方法はないので、自作する

using ExcelDataReader;
using System;
using System.Data;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleExcelDataReader
{
    static void Main(string[] args)
    {
        // デフォルトでは、エンコード(CP1252)がサポートされておらずエラーになるのでこれが必要
        System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");
            
            // ファイル開く、読み書きモード、共有なし(排他)
            using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
            using (var reader = ExcelReaderFactory.CreateReader(fileStream))
            {
                // DataSetに変換(シート情報を取得)
                var result = reader.AsDataSet();
                
                // シート取得
                var worksheet = result.Tables["Sheet1"];

                if(worksheet == null)
                {
                    throw new Exception("Sheet1シートは存在しません");
                }

                // アドレスを出すような仕組みはなし。
                // もしログにA1形式で出力したければ、自分で作ること

                // 2行、3列の各セルのアドレスを出力
                for (var r = 1; r <= 2; r++)
                {
                    for (var c = 1; c <= 3; c++)
                    {
                        var cellAddress = CellAddress(r, c);
                        Console.WriteLine($"{r}行{c}列 => {cellAddress}");
                    }
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }

    static string CellAddress(int row, int col)
    {
        string colStr = "";

        while (0 < col)
        {
            col--; // Aのアスキーコードに足すので1減らしておく
            int remainder = col % 26;
            colStr = (char)('A' + remainder) + colStr;
            col /= 26;
        }

        return $"{colStr}{row}";
    }
}

NPOI

※ライブラリ側にはアドレスを出力する方法はないので、自作する

xls

using NPOI.HSSF.UserModel;
using NPOI.SS.Formula.Functions;
using NPOI.SS.UserModel;
using NPOI.SS.Util;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleNPOI_xls
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xls");
            
            // ブックを開く、読み取りモード、共有なし(排他)
            using (var stRead = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.None))
            using (var workbook = new HSSFWorkbook(stRead))
            {
                // シートを取得
                var worksheet = workbook.GetSheet("Sheet1");

                // アドレスを出すような仕組みはなし。
                // もしログにA1形式で出力したければ、自分で作ること

                // 2行、3列の各セルのアドレスを出力
                for (var r = 1; r <= 2; r++)
                {
                    for (var c = 1; c <= 3; c++)
                    {
                        var cellAddress = CellAddress(r, c);
                        Console.WriteLine($"{r}行{c}列 => {cellAddress}");
                    }
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }

    static string CellAddress(int row, int col)
    {
        string colStr = "";

        while (0 < col)
        {
            col--; // Aのアスキーコードに足すので1減らしておく
            int remainder = col % 26;
            colStr = (char)('A' + remainder) + colStr;
            col /= 26;
        }

        return $"{colStr}{row}";
    }
}

xlsx

using NPOI.SS.Util;
using NPOI.XSSF.UserModel;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleNPOI_xlsx
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");
            
            // ブックを開く、読み取りモード、共有なし(排他)
            using (var stRead = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.None))
            using (var workbook = new XSSFWorkbook(stRead))
            {
                // シートを取得
                var worksheet = workbook.GetSheet("Sheet1");

                // アドレスを出すような仕組みはなし。
                // もしログにA1形式で出力したければ、自分で作ること

                // 2行、3列の各セルのアドレスを出力
                for (var r = 1; r <= 2; r++)
                {
                    for (var c = 1; c <= 3; c++)
                    {
                        var cellAddress = CellAddress(r, c);
                        Console.WriteLine($"{r}行{c}列 => {cellAddress}");
                    }
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }

    static string CellAddress(int row, int col)
    {
        string colStr = "";

        while (0 < col)
        {
            col--; // Aのアスキーコードに足すので1減らしておく
            int remainder = col % 26;
            colStr = (char)('A' + remainder) + colStr;
            col /= 26;
        }

        return $"{colStr}{row}";
    }
}

xls/xlsx対応版

Program.cs

using NPOI.SS.Util;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleNPOI
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            var extension = Path.GetExtension(filePath);

            using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.None))
            using (var workbook = WorkbookFactory.Create(fileStream, extension))
            {
                // シートを取得
                var worksheet = workbook.GetSheet("Sheet1");

                // アドレスを出すような仕組みはなし。
                // もしログにA1形式で出力したければ、自分で作ること

                // 2行、3列の各セルのアドレスを出力
                for (var r = 1; r <= 2; r++)
                {
                    for (var c = 1; c <= 3; c++)
                    {
                        var cellAddress = CellAddress(r, c);
                        Console.WriteLine($"{r}行{c}列 => {cellAddress}");
                    }
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }

    static string CellAddress(int row, int col)
    {
        string colStr = "";

        while (0 < col)
        {
            col--; // Aのアスキーコードに足すので1減らしておく
            int remainder = col % 26;
            colStr = (char)('A' + remainder) + colStr;
            col /= 26;
        }

        return $"{colStr}{row}";
    }
}

WorkbookFactory.cs

using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.IO;

namespace SampleCode; // C#10

public class WorkbookFactory
{
    public static IWorkbook Create(Stream stream, string extension)
    {
        extension = extension.ToLower();

        return extension switch
        {
            ".xls" => new HSSFWorkbook(stream),
            ".xlsx" => new XSSFWorkbook(stream),
            _ => throw new NotSupportedException("対象外の拡張子です")
        };
    }

    public static IWorkbook Create(string extension)
    {
        extension = extension.ToLower();

        return extension switch
        {
            ".xls" => new HSSFWorkbook(),
            ".xlsx" => new XSSFWorkbook(),
            _ => throw new NotSupportedException("対象外の拡張子です")
        };
    }
}
投稿日時: 2025-05-21 12:50:21
更新日時: 2025-05-21 12:57:21

ExcelVBA

Sub Sample()
    Dim BookObj         As Workbook
    Dim CellData        As Range
    Dim FilePath        As String
    Dim RangeData       As Range
    Dim SheetObj        As Worksheet
        
    'ファイルパス作成
    FilePath = ThisWorkbook.Path & "\sample.xlsx"
    
    'ブックを開く
    Set BookObj = Workbooks.Open(FilePath)
    
    'シート取得
    Set SheetObj = BookObj.Sheets("Sheet1")
    
    'A1形式
    Debug.Print SheetObj.Range("A1").Value
    
    'R1C1形式
    Debug.Print SheetObj.Cells(1, 1).Value
        
    '閉じる
    BookObj.Close
    
    Set BookObj = Nothing
    Set CellData = Nothing
    Set RangeData = Nothing
    Set SheetObj = Nothing
End Sub

Excel(COM)

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

namespace SampleCode; // C#10~

internal class SampleExcel
{
    static void Main(string[] args)
    {
        Excel.Application? application = null;
        Excel.Workbooks? workbooks = null;
        Excel.Workbook? workbook = null;
        Excel.Sheets? worksheets = null;
        Excel.Worksheet? worksheet = null;
        Excel.Range? cellData1 = null;
        Excel.Range? cellData2 = null;

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");
            
            // Excelを開く
            application = new Excel.Application();
            application.Visible = true;

            // ブックを開く
            workbooks = application.Workbooks;
            workbook = workbooks.Open(filePath);

            // シートを取得
            worksheets = workbook.Sheets;
            worksheet = worksheets["Sheet1"];

            // A1形式
            cellData1 = worksheet.Range["A1"];
            Console.WriteLine(cellData1.Value);

            // R1C1形式
            cellData2 = worksheet.Cells[1, 1];
            Console.WriteLine(cellData2.Value);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        finally
        {
            CleanUpComObject(ref cellData1);
            CleanUpComObject(ref cellData2);
            CleanUpComObject(ref worksheet);
            CleanUpComObject(ref worksheets);
            CleanUpComObject(ref workbook);
            CleanUpComObject(ref workbooks);
            CleanUpComObject(ref application);
        }
    }

    static void CleanUpComObject<T>(ref T comObject, bool shouldClose = true, bool saveChanges = false)
    {
        // フラグによってWorkbookはClose / ApplicationはQuitする
        if (shouldClose && comObject != null)
        {
            // 型をチェックする
            if (comObject is Microsoft.Office.Interop.Excel.Workbook workbook)
            {
                // Workbookの場合
                workbook.Close(saveChanges);
            }
            else if (comObject is Microsoft.Office.Interop.Excel.Application application)
            {
                // Applicationの場合
                application.Quit();
            }
        }

        // Objectを解放
        if (comObject != null && Marshal.IsComObject(comObject))
        {
            Marshal.ReleaseComObject(comObject);
            comObject = default!;
        }
    }
}

補足:Microsoft.Office.Interop.Excel でオブジェクトの解放について

ClosedXML

using ClosedXML.Excel;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleClosedXML
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");
            
            // ブックを開く、読み書きモード、共有なし(排他)
            using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            using (var workbook = new XLWorkbook(stream))
            {
                IXLWorksheet? worksheet = null;

                if(!workbook.TryGetWorksheet("Sheet1", out worksheet))
                {
                    throw new Exception("Sheet1シートがありませんでした");
                }
                
                // A1形式
                Console.WriteLine(worksheet.Cell("A1").Value);

                // R1C1形式
                Console.WriteLine(worksheet.Cell(1, 1).Value);

            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

EPPlus

using OfficeOpenXml;
using System;
using System.IO;
using System.IO.Pipes;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleEPPlus
{
    static void Main(string[] args)
    {
        // Ver8.0のソースです
        // 非商用個人利用の場合 名前を設定
        ExcelPackage.License.SetNonCommercialPersonal("SampleTarou");

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            using (var package = new ExcelPackage(stream))
            {
                // シートを取得
                var worksheet = package.Workbook.Worksheets["Sheet1"];

                // A1形式
                Console.WriteLine(worksheet.Cells["A1"].Value);

                // R1C1形式
                Console.WriteLine(worksheet.Cells[1, 1].Value); // 行, 列
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"エラー: {ex.Message}");
        }
    }
}

ExcelDataReader

using ExcelDataReader;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleExcelDataReader
{
    static void Main(string[] args)
    {
        // デフォルトでは、エンコード(CP1252)がサポートされておらずエラーになるのでこれが必要
        System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");
            
            // ファイル開く、読み書きモード、共有なし(排他)
            using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
            using (var reader = ExcelReaderFactory.CreateReader(fileStream))
            {
                // DataSetに変換(シート情報を取得)
                var result = reader.AsDataSet();
                
                // シート取得
                var worksheet = result.Tables["Sheet1"];

                // A1形式は存在しない

                // R1C1形式(0から始まる)
                Console.WriteLine(worksheet.Rows[0][0]);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }

    // 列を表す数値から列を表す文字列に変換する
    static string ConvertColumnNumToStr(int colNum)
    {
        var colStr = string.Empty;

        while (colNum > 0)
        {
            int modulo = (colNum - 1) % 26;
            colStr = Convert.ToChar('A' + modulo) + colStr;
            colNum = (colNum - modulo) / 26;
        }

        return colStr;
    }
}

NPOI

xls

using NPOI.HSSF.UserModel;
using NPOI.SS.Formula.Functions;
using NPOI.SS.UserModel;
using NPOI.SS.Util;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleNPOI_xls
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xls");
            
            // ブックを開く、読み取りモード、共有なし(排他)
            using (var stRead = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.None))
            using (var workbook = new HSSFWorkbook(stRead))
            {
                // シートを取得
                var worksheet = workbook.GetSheet("Sheet1");

                // A1形式は存在しない

                // R1C1形式(0から始まる)
                Console.WriteLine(worksheet.GetRow(0).GetCell(0).StringCellValue);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

xlsx

using NPOI.SS.Util;
using NPOI.XSSF.UserModel;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleNPOI_xlsx
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");
            
            // ブックを開く、読み取りモード、共有なし(排他)
            using (var stRead = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.None))
            using (var workbook = new XSSFWorkbook(stRead))
            {
                // シートを取得
                var worksheet = workbook.GetSheet("Sheet1");

                // A1形式は存在しない

                // R1C1形式(0から始まる)
                Console.WriteLine(worksheet.GetRow(0).GetCell(0).StringCellValue);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

xlsもxlsxも扱う場合

Program.cs

using NPOI.SS.Util;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleNPOI
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            var extension = Path.GetExtension(filePath);

            using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.None))
            using (var workbook = WorkbookFactory.Create(fileStream, extension))
            {
                // シートを取得
                var worksheet = workbook.GetSheet("Sheet1");

                // A1形式は存在しない

                // R1C1形式(0から始まる)
                Console.WriteLine(worksheet.GetRow(0).GetCell(0).StringCellValue);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

WorkbookFactory.cs

using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.IO;

namespace SampleCode; // C#10

public class WorkbookFactory
{
    public static IWorkbook Create(Stream stream, string extension)
    {
        extension = extension.ToLower();

        return extension switch
        {
            ".xls" => new HSSFWorkbook(stream),
            ".xlsx" => new XSSFWorkbook(stream),
            _ => throw new NotSupportedException("対象外の拡張子です")
        };
    }

    public static IWorkbook Create(string extension)
    {
        extension = extension.ToLower();

        return extension switch
        {
            ".xls" => new HSSFWorkbook(),
            ".xlsx" => new XSSFWorkbook(),
            _ => throw new NotSupportedException("対象外の拡張子です")
        };
    }
}
投稿日時: 2025-05-19 16:19:19
更新日時: 2025-05-21 03:57:21

ExcelVBA

Sub Sample()
    Dim BookObj         As Workbook
    Dim CellData        As Range
    Dim FilePath        As String
    Dim RangeData       As Range
    Dim SheetObj        As Worksheet
        
    'ファイルパス作成
    FilePath = ThisWorkbook.Path & "\sample.xlsx"
    
    'ブックを開く
    Set BookObj = Workbooks.Open(FilePath)
    
    'シート取得
    Set SheetObj = BookObj.Sheets("Sheet1")
    
    '範囲セル取得
    Set RangeData = SheetObj.Range("A1:C2")
    
    '範囲のセルを一つずつ取り出す
    For Each CellData In RangeData
        Debug.Print "アドレス:" & CellData.Address & "/値:" & CellData.Value
    Next
        
    '閉じる
    BookObj.Close
    
    Set BookObj = Nothing
    Set CellData = Nothing
    Set RangeData = Nothing
    Set SheetObj = Nothing
End Sub

Excel(COM)

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

namespace SampleCode; // C#10~

internal class SampleExcel
{
    static void Main(string[] args)
    {
        Excel.Application? application = null;
        Excel.Workbooks? workbooks = null;
        Excel.Workbook? workbook = null;
        Excel.Sheets? worksheets = null;
        Excel.Worksheet? worksheet = null;
        Excel.Range? rangeData = null;
        Excel.Range? cellData = null;

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");
            
            // Excelを開く
            application = new Excel.Application();
            application.Visible = true;

            // ブックを開く
            workbooks = application.Workbooks;
            workbook = workbooks.Open(filePath);

            // シートを取得
            worksheets = workbook.Sheets;
            worksheet = worksheets["Sheet1"];

            // 範囲セル取得
            rangeData = worksheet.Range["A1", "C2"];

            for (var n = 1; n <= rangeData.Count; n++)
            {
                cellData = rangeData[n];

                Console.WriteLine($"アドレス:{cellData.Address}/値:{cellData.Value}");

                CleanUpComObject(ref cellData);
            }

        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        finally
        {
            CleanUpComObject(ref cellData);
            CleanUpComObject(ref rangeData);
            CleanUpComObject(ref worksheet);
            CleanUpComObject(ref worksheets);
            CleanUpComObject(ref workbook);
            CleanUpComObject(ref workbooks);
            CleanUpComObject(ref application);
        }
    }

    static void CleanUpComObject<T>(ref T comObject, bool shouldClose = true, bool saveChanges = false)
    {
        // フラグによってWorkbookはClose / ApplicationはQuitする
        if (shouldClose && comObject != null)
        {
            // 型をチェックする
            if (comObject is Microsoft.Office.Interop.Excel.Workbook workbook)
            {
                // Workbookの場合
                workbook.Close(saveChanges);
            }
            else if (comObject is Microsoft.Office.Interop.Excel.Application application)
            {
                // Applicationの場合
                application.Quit();
            }
        }

        // Objectを解放
        if (comObject != null && Marshal.IsComObject(comObject))
        {
            Marshal.ReleaseComObject(comObject);
            comObject = default!;
        }
    }
}

補足:Microsoft.Office.Interop.Excel でオブジェクトの解放について

ClosedXML

using ClosedXML.Excel;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleClosedXML
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");
            
            // ブックを開く、読み書きモード、共有なし(排他)
            using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            using (var workbook = new XLWorkbook(stream))
            {
                IXLWorksheet? worksheet = null;

                if(!workbook.TryGetWorksheet("Sheet1", out worksheet))
                {
                    throw new Exception("Sheet1シートがありませんでした");
                }

                var rangeData = worksheet.Range("A1:C2");

                foreach (var cellData in rangeData.Cells())
                {
                    Console.WriteLine($"アドレス:{cellData.Address}/値:{cellData.Value}");
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

EPPlus

using OfficeOpenXml;
using System;
using System.IO;
using System.IO.Pipes;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleEPPlus
{
    static void Main(string[] args)
    {
        // Ver8.0のソースです
        // 非商用個人利用の場合 名前を設定
        ExcelPackage.License.SetNonCommercialPersonal("SampleTarou");

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");
            
            using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            using (var package = new ExcelPackage(stream))
            {
                // シートを取得
                var worksheet = package.Workbook.Worksheets["Sheet1"];

                // 範囲セルを取得
                var rangeData = worksheet.Cells["A1:C2"];

                foreach (var cellData in rangeData)
                {
                    Console.WriteLine($"アドレス:{cellData.Address}/値:{cellData.Value}");
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"エラー: {ex.Message}");
        }
    }
}

ExcelDataReader

using ExcelDataReader;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleExcelDataReader
{
    static void Main(string[] args)
    {
        // デフォルトでは、エンコード(CP1252)がサポートされておらずエラーになるのでこれが必要
        System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");
            
            // ファイル開く、読み書きモード、共有なし(排他)
            using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
            using (var reader = ExcelReaderFactory.CreateReader(fileStream))
            {
                // DataSetに変換(シート情報を取得)
                var result = reader.AsDataSet();
                
                // シート取得
                var worksheet = result.Tables["Sheet1"];
            
                for(var r = 0; r <= 1; r++)
                {
                    for(var c = 0; c <= 2; c++)
                    {
                        // セルの値
                        var value = worksheet.Rows[r][c];

                        // 列名
                        var colStr = ConvertColumnNumToStr(c + 1);
                        var address = $"{colStr}{r + 1}";

                        Console.WriteLine($"アドレス:{address}/値:{value}");
                    }
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }

    // 列を表す数値から列を表す文字列に変換する
    static string ConvertColumnNumToStr(int colNum)
    {
        var colStr = string.Empty;

        while (colNum > 0)
        {
            int modulo = (colNum - 1) % 26;
            colStr = Convert.ToChar('A' + modulo) + colStr;
            colNum = (colNum - modulo) / 26;
        }

        return colStr;
    }
}

NPOI

xls

using NPOI.HSSF.UserModel;
using NPOI.SS.Formula.Functions;
using NPOI.SS.UserModel;
using NPOI.SS.Util;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleNPOI_xls
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xls");
            
            // ブックを開く、読み取りモード、共有なし(排他)
            using (var stRead = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.None))
            using (var workbook = new HSSFWorkbook(stRead))
            {
                // シートを取得
                var worksheet = workbook.GetSheet("Sheet1");

                for(var r = 0; r <= 1; r++)
                {
                    for(var c = 0; c <= 2; c++)
                    {
                        // セルを取得
                        var cellData = worksheet.GetRow(r).GetCell(c);

                        // アドレスを取得
                        var address = new CellReference(r, c).FormatAsString();

                        // 値を取得
                        var value = cellData.StringCellValue;

                        Console.WriteLine($"アドレス:{address}/値:{value}");
                    }
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

xlsx

using NPOI.SS.Util;
using NPOI.XSSF.UserModel;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleNPOI_xlsx
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");
            
            // ブックを開く、読み取りモード、共有なし(排他)
            using (var stRead = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.None))
            using (var workbook = new XSSFWorkbook(stRead))
            {
                // シートを取得
                var worksheet = workbook.GetSheet("Sheet1");

                for (var r = 0; r <= 1; r++)
                {
                    for (var c = 0; c <= 2; c++)
                    {
                        // セルを取得
                        var cellData = worksheet.GetRow(r).GetCell(c);

                        // アドレスを取得
                        var address = new CellReference(r, c).FormatAsString();

                        // 値を取得
                        var value = cellData.StringCellValue;

                        Console.WriteLine($"アドレス:{address}/値:{value}");
                    }
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

xls/xlsx対応版

Program.cs

using NPOI.SS.Util;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleNPOI
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            var extension = Path.GetExtension(filePath);

            using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.None))
            using (var workbook = WorkbookFactory.Create(fileStream, extension))
            {
                // シートを取得
                var worksheet = workbook.GetSheet("Sheet1");

                for (var r = 0; r <= 1; r++)
                {
                    for (var c = 0; c <= 2; c++)
                    {
                        // セルを取得
                        var cellData = worksheet.GetRow(r).GetCell(c);

                        // アドレスを取得
                        var address = new CellReference(r, c).FormatAsString();

                        // 値を取得
                        var value = cellData.StringCellValue;

                        Console.WriteLine($"アドレス:{address}/値:{value}");
                    }
                }
            }

        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

WorkbookFactory.cs

using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.IO;

namespace SampleCode; // C#10

public class WorkbookFactory
{
    public static IWorkbook Create(Stream stream, string extension)
    {
        extension = extension.ToLower();

        return extension switch
        {
            ".xls" => new HSSFWorkbook(stream),
            ".xlsx" => new XSSFWorkbook(stream),
            _ => throw new NotSupportedException("対象外の拡張子です")
        };
    }

    public static IWorkbook Create(string extension)
    {
        extension = extension.ToLower();

        return extension switch
        {
            ".xls" => new HSSFWorkbook(),
            ".xlsx" => new XSSFWorkbook(),
            _ => throw new NotSupportedException("対象外の拡張子です")
        };
    }
}
投稿日時: 2025-05-19 14:33:19
更新日時: 2025-05-21 03:57:21

ExcelVBA

Sub Sample()
    Dim AddSheetObj     As Worksheet
    Dim BookObj         As Workbook
    Dim FilePath        As String
    Dim SheetCount      As Long
    Dim LastSheetObj    As Worksheet
    
    'ファイルパス作成
    FilePath = ThisWorkbook.Path & "\sample.xlsx"
    
    'ブックを開く
    Set BookObj = Workbooks.Open(FilePath)
    
    'シート数を取得
    SheetCount = BookObj.Sheets.Count
    
    '最後のシートを取得
    Set LastSheetObj = BookObj.Sheets(SheetCount)
    
    '渡し、その後ろに追加するよう指示する
    Set AddSheetObj = BookObj.Sheets.Add(After:=LastSheetObj)
    
    '追加されたシートの名前を変える
    AddSheetObj.Name = "sample"

    '保存
    BookObj.Save
        
    '閉じる
    BookObj.Close
    
    
    Set BookObj = Nothing
End Sub

Excel(COM)

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

namespace SampleCode; // C#10~

internal class SampleExcel
{
    static void Main(string[] args)
    {
        Excel.Application? application = null;
        Excel.Workbooks? workbooks = null;
        Excel.Workbook? workbook = null;
        Excel.Sheets? worksheets = null;
        Excel.Worksheet? addWorksheet = null;
        Excel.Worksheet? lastWorksheet = null;

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // Excelを開く
            application = new Excel.Application();
            application.Visible = true;

            // ブックを開く
            workbooks = application.Workbooks;
            workbook = workbooks.Open(filePath);

            // シートを取得
            worksheets = workbook.Sheets;

            // 最後のシートを取得
            var sheetCount = worksheets.Count;
            lastWorksheet = worksheets[sheetCount];

            // シート追加
            addWorksheet = worksheets.Add(After: lastWorksheet);

            // シート名変更
            addWorksheet.Name = "sample";

            // 保存
            workbook.Save();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        finally
        {
            CleanUpComObject(ref addWorksheet);
            CleanUpComObject(ref lastWorksheet);
            CleanUpComObject(ref worksheets);
            CleanUpComObject(ref workbook, true, true);
            CleanUpComObject(ref workbooks);
            CleanUpComObject(ref application);
        }
    }

    static void CleanUpComObject<T>(ref T comObject, bool shouldClose = true, bool saveChanges = false)
    {
        // フラグによってWorkbookはClose / ApplicationはQuitする
        if (shouldClose && comObject != null)
        {
            // 型をチェックする
            if (comObject is Microsoft.Office.Interop.Excel.Workbook workbook)
            {
                // Workbookの場合
                workbook.Close(saveChanges);
            }
            else if (comObject is Microsoft.Office.Interop.Excel.Application application)
            {
                // Applicationの場合
                application.Quit();
            }
        }

        // Objectを解放
        if (comObject != null && Marshal.IsComObject(comObject))
        {
            Marshal.ReleaseComObject(comObject);
            comObject = default!;
        }
    }
}

ClosedXML

using ClosedXML.Excel;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleClosedXML
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // ブックを開く、読み書きモード、共有なし(排他)
            using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            using (var workbook = new XLWorkbook(stream))
            {
                // 一番最後にsampleシート追加
                workbook.Worksheets.Add("sample");

                // 上書き保存
                workbook.Save();
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

EPPlus

using OfficeOpenXml;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleEPPlus
{
    static void Main(string[] args)
    {
        // Ver8.0のソースです
        // 非商用個人利用の場合 名前を設定
        ExcelPackage.License.SetNonCommercialPersonal("SampleTarou");

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // メモリにすべて取り込む。これなら遅延でStreamにアクセスするような問題が発生しない
            byte[] fileBytes = File.ReadAllBytes(filePath);
            using (var readStream = new MemoryStream(fileBytes))
            using (var package = new ExcelPackage(readStream))
            {
                // シートを追加
                var worksheet = package.Workbook.Worksheets.Add("sample");

                // あらためて書き込み用としてStreamを開く
                using (var writeStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    // 書き込み
                    package.SaveAs(writeStream);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"エラー: {ex.Message}");
        }
    }
}

ClosedXMLだと、直接Streamを使って上書きしているのに対し、
EPPlusだと、別のStreamに保存し元のStreamを空にしてからコピーをする手段をとっています
ライブラリ内部の設計の違いからくるもののそうです

ExcelDataReader

読み取りのみのためなし

NPOI

□xls

using NPOI.HSSF.UserModel;
using System;
using System.IO;
using System.Reflection;


namespace SampleCode; // C#10~

internal class SampleNPOI_xls
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xls");

            // メモリにすべて取り込む。これなら遅延でStreamにアクセスするような問題が発生しない
            byte[] fileBytes = File.ReadAllBytes(filePath);
            using (var readStream = new MemoryStream(fileBytes))
            using (var workbook = new HSSFWorkbook(readStream))
            {
                // シートを追加
                workbook.CreateSheet("sample");

                // あらためて書き込み用としてStreamを開く
                using (var writeStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    // 書き込み
                    workbook.Write(writeStream);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

□xlsx

using NPOI.XSSF.UserModel;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleNPOI_xlsx
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // メモリにすべて取り込む。これなら遅延でStreamにアクセスするような問題が発生しない
            byte[] fileBytes = File.ReadAllBytes(filePath);
            using (var readStream = new MemoryStream(fileBytes))
            using (var workbook = new XSSFWorkbook(readStream))
            {
                // シートを追加
                workbook.CreateSheet("sample");

                // あらためて書き込み用としてStreamを開く
                using (var writeStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    // 書き込み
                    workbook.Write(writeStream);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

□xls/xlsx対応版

Program.cs

using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleNPOI
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            var extension = Path.GetExtension(filePath);

            // メモリにすべて取り込む。これなら遅延でStreamにアクセスするような問題が発生しない
            byte[] fileBytes = File.ReadAllBytes(filePath);
            using (var readStream = new MemoryStream(fileBytes))
            using (var workbook = WorkbookFactory.Create(readStream, extension))
            {
                // シートを追加
                workbook.CreateSheet("sample");

                // あらためて書き込み用としてStreamを開く
                using (var writeStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    // 書き込み
                    workbook.Write(writeStream);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

WorkbookFactory.cs

using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.IO;

namespace SampleCode
{
    public class WorkbookFactory
    {
        public static IWorkbook Create(Stream stream, string extension)
        {
            extension = extension.ToLower();

            return extension switch
            {
                ".xls" => new HSSFWorkbook(stream),
                ".xlsx" => new XSSFWorkbook(stream),
                _ => throw new NotSupportedException("対象外の拡張子です")
            };
        }

        public static IWorkbook Create(string extension)
        {
            extension = extension.ToLower();

            return extension switch
            {
                ".xls" => new HSSFWorkbook(),
                ".xlsx" => new XSSFWorkbook(),
                _ => throw new NotSupportedException("対象外の拡張子です")
            };
        }
    }
}
投稿日時: 2025-05-18 04:38:18
更新日時: 2025-05-26 14:47:26

シートが3つ入っているExcelを開いて、シートの数を取得し出力します

ExcelVBA

Sub Sample()
    Dim BookObj     As Workbook
    Dim FilePath    As String
    Dim SheetObj    As Variant
    
    'ファイルパス作成
    FilePath = ThisWorkbook.Path & "\sample.xlsx"
    
    'ブックを開く
    Set BookObj = Workbooks.Open(FilePath)
    
    'シート数出力
    Debug.Print BookObj.Sheets.Count
        
    '保存せずに閉じる
    BookObj.Close (False)
    
    
    Set BookObj = Nothing
End Sub

Excel(COM)

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

namespace SampleCode; // C#10~

internal class SampleExcel
{
    static void Main(string[] args)
    {
        Excel.Application? application = null;
        Excel.Workbooks? workbooks = null;
        Excel.Workbook? workbook = null;
        Excel.Sheets? worksheets = null;

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // Excelを開く
            application = new Excel.Application();
            application.Visible = true;

            // ブックを開く
            workbooks = application.Workbooks;
            workbook = workbooks.Open(filePath);

            // シートを取得
            worksheets = workbook.Sheets;

            // シート数出力
            Console.WriteLine(worksheets.Count);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        finally
        {
            CleanUpComObject(ref worksheets);
            CleanUpComObject(ref workbook);
            CleanUpComObject(ref workbooks);
            CleanUpComObject(ref application);
        }
    }

    static void CleanUpComObject<T>(ref T comObject, bool shouldClose = true, bool saveChanges = false)
    {
        // フラグによってWorkbookはClose / ApplicationはQuitする
        if (shouldClose && comObject != null)
        {
            // 型をチェックする
            if (comObject is Microsoft.Office.Interop.Excel.Workbook workbook)
            {
                // Workbookの場合
                workbook.Close(saveChanges);
            }
            else if (comObject is Microsoft.Office.Interop.Excel.Application application)
            {
                // Applicationの場合
                application.Quit();
            }
        }

        // Objectを解放
        if (comObject != null && Marshal.IsComObject(comObject))
        {
            Marshal.ReleaseComObject(comObject);
            comObject = default!;
        }
    }
}

補足:Microsoft.Office.Interop.Excel でオブジェクトの解放について

ClosedXML

using ClosedXML.Excel;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleClosedXML
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // ブックを開く、読み書きモード、共有なし(排他)
            using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            using (var workbook = new XLWorkbook(stream))
            {
                // シート数出力
                Console.WriteLine(workbook.Worksheets.Count);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

EPPlus

using OfficeOpenXml;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleEPPlus
{
    static void Main(string[] args)
    {
        // Ver8.0のソースです
        // 非商用個人利用の場合 名前を設定
        ExcelPackage.License.SetNonCommercialPersonal("SampleTarou");

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // ブックを開く、読み書きモード、共有なし(排他)
            using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            using (var package = new ExcelPackage(stream))
            {
                // シート数出力
                Console.WriteLine(package.Workbook.Worksheets.Count);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

ExcelDataReader

using ExcelDataReader;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleExcelDataReader
{
    static void Main(string[] args)
    {
        // デフォルトでは、エンコード(CP1252)がサポートされておらずエラーになるのでこれが必要
        System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // ファイル開く、読み書きモード、共有なし(排他)
            using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
            using (var reader = ExcelReaderFactory.CreateReader(fileStream))
            {
                // DataSetに変換(シート情報を取得)
                var result = reader.AsDataSet();

                // シート数出力
                Console.WriteLine(result.Tables.Count);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

NPOI

□xls

using NPOI.HSSF.UserModel;
using System;
using System.IO;
using System.Reflection;


namespace SampleCode; // C#10~

internal class SampleNPOI_xls
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xls");

            // ブックを開く、読み書きモード、共有なし(排他)
            using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            {
                using (var workbook = new HSSFWorkbook(fileStream))
                {
                    // シート数出力
                    Console.WriteLine(workbook.NumberOfSheets);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

□xlsx

using NPOI.XSSF.UserModel;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleNPOI_xlsx
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // ブックを開く、読み書きモード、共有なし(排他)
            using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            {
                using (var workbook = new XSSFWorkbook(fileStream))
                {
                    // シート数出力
                    Console.WriteLine(workbook.NumberOfSheets);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

□xlsもxlsxも扱う場合

Program.cs

using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleNPOI
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            var extension = Path.GetExtension(filePath);

            using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            using (var workbook = WorkbookFactory.Create(fileStream, extension))
            {
                // シート数出力
                Console.WriteLine(workbook.NumberOfSheets);
            }

        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

WorkbookFactory.cs

using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.IO;

namespace SampleCode
{
    public class WorkbookFactory
    {
        public static IWorkbook Create(Stream stream, string extension)
        {
            extension = extension.ToLower();

            return extension switch
            {
                ".xls" => new HSSFWorkbook(stream),
                ".xlsx" => new XSSFWorkbook(stream),
                _ => throw new NotSupportedException("対象外の拡張子です")
            };
        }

        public static IWorkbook Create(string extension)
        {
            extension = extension.ToLower();

            return extension switch
            {
                ".xls" => new HSSFWorkbook(),
                ".xlsx" => new XSSFWorkbook(),
                _ => throw new NotSupportedException("対象外の拡張子です")
            };
        }
    }
}
投稿日時: 2025-05-17 05:31:17
更新日時: 2025-05-26 13:43:26

シートが3つ入っているExcelを開いて、各ワークシートを取得し名前を出力します

ExcelVBA

Sub Sample()
    Dim BookObj     As Workbook
    Dim FilePath    As String
    Dim SheetObj    As Variant
    
    'ファイルパス作成
    FilePath = ThisWorkbook.Path & "\sample.xlsx"
    
    'ブックを開く
    Set BookObj = Workbooks.Open(FilePath)
    
    '全シート取得し、それぞれの名前を出力する
    For Each SheetObj In BookObj.Sheets
        Debug.Print SheetObj.Name
    Next
    
    '保存せずに閉じる
    BookObj.Close (False)
    
    Set BookObj = Nothing
End Sub

Excel(COM)

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

namespace SampleCode; // C#10~

internal class SampleExcel
{
    static void Main(string[] args)
    {
        Excel.Application? application = null;
        Excel.Workbooks? workbooks = null;
        Excel.Workbook? workbook = null;
        Excel.Sheets? worksheets = null;
        Excel.Worksheet? worksheet = null;

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // Excelを開く
            application = new Excel.Application();
            application.Visible = true;

            // ブックを開く
            workbooks = application.Workbooks;
            workbook = workbooks.Open(filePath);

            // シートを取得
            worksheets = workbook.Sheets;

            // 各シートの名前を出力
            for (var i = 1; i <= worksheets.Count; i++)
            {
                // 各シートを取得して名前を表示
                worksheet = worksheets[i];
                Console.WriteLine(worksheet.Name);

                CleanUpComObject(ref worksheet);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        finally
        {
            CleanUpComObject(ref worksheet);
            CleanUpComObject(ref worksheets);
            CleanUpComObject(ref workbook);
            CleanUpComObject(ref workbooks);
            CleanUpComObject(ref application);
        }
    }

    static void CleanUpComObject<T>(ref T comObject, bool shouldClose = true, bool saveChanges = false)
    {
        // フラグによってWorkbookはClose / ApplicationはQuitする
        if (shouldClose && comObject != null)
        {
            // 型をチェックする
            if (comObject is Microsoft.Office.Interop.Excel.Workbook workbook)
            {
                // Workbookの場合
                workbook.Close(saveChanges);
            }
            else if (comObject is Microsoft.Office.Interop.Excel.Application application)
            {
                // Applicationの場合
                application.Quit();
            }
        }

        // Objectを解放
        if (comObject != null && Marshal.IsComObject(comObject))
        {
            Marshal.ReleaseComObject(comObject);
            comObject = default!;
        }
    }
}

補足:Microsoft.Office.Interop.Excel でオブジェクトの解放について

ClosedXML

using ClosedXML.Excel;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleClosedXML
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // ブックを開く、読み書きモード、共有なし(排他)
            using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            using (var workbook = new XLWorkbook(stream))
            {
                // ワークシートをループで処理
                foreach (var worksheet in workbook.Worksheets)
                {
                    // シート名を出力
                    Console.WriteLine(worksheet.Name);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

EPPlus

using OfficeOpenXml;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleEPPlus
{
    static void Main(string[] args)
    {
        // Ver8.0のソースです
        // 非商用個人利用の場合 名前を設定
        ExcelPackage.License.SetNonCommercialPersonal("SampleTarou");

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // ブックを開く、読み書きモード、共有なし(排他)
            using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            using (var package = new ExcelPackage(stream))
            {
                // ワークシートをループで処理
                foreach (var worksheet in package.Workbook.Worksheets)
                {
                    // シート名を出力
                    Console.WriteLine(worksheet.Name);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

ExcelDataReader

using ExcelDataReader;
using System;
using System.Data;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleExcelDataReader
{
    static void Main(string[] args)
    {
        // デフォルトでは、エンコード(CP1252)がサポートされておらずエラーになるのでこれが必要
        System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // ファイル開く、読み書きモード、共有なし(排他)
            using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
            using (var reader = ExcelReaderFactory.CreateReader(fileStream))
            {
                // DataSetに変換(シート情報を取得)
                var result = reader.AsDataSet();

                // DataTableCollectionからDataTable(シート情報)を一つずつ取り出す
                foreach (DataTable table in result.Tables)
                {
                    // シート名を出力
                    Console.WriteLine(table.TableName);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

NPOI

□xls

using NPOI.HSSF.UserModel;
using System;
using System.IO;
using System.Reflection;


namespace SampleCode; // C#10~

internal class SampleNPOI_xls
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xls");

            // ブックを開く、読み書きモード、共有なし(排他)
            using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            {
                using (var workbook = new HSSFWorkbook(fileStream))
                {
                    // foreachはない。シート数からシート番号としてシートを受け取りシート名を表示
                    for (var i = 0; i < workbook.NumberOfSheets; i++)
                    {
                        var worksheet = workbook.GetSheetAt(i);

                        Console.WriteLine(worksheet.SheetName);
                    }
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

□xlsx

using NPOI.XSSF.UserModel;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleNPOI_xlsx
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // ブックを開く、読み書きモード、共有なし(排他)
            using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            {
                using (var workbook = new XSSFWorkbook(fileStream))
                {
                    // foreachはない。シート数からシート番号としてシートを受け取りシート名を表示
                    for (var i = 0; i < workbook.NumberOfSheets; i++)
                    {
                        var worksheet = workbook.GetSheetAt(i);

                        Console.WriteLine(worksheet.SheetName);
                    }
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

□xlsもxlsxも扱う場合

Program.cs

using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleNPOI
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // 拡張子取得
            var extension = Path.GetExtension(filePath);

            // ブックを開く
            using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            using (var workbook = WorkbookFactory.Create(fileStream, extension))
            {
                // foreachはない。シート数からシート番号としてシートを受け取りシート名を表示
                for (var i = 0; i < workbook.NumberOfSheets; i++)
                {
                    var worksheet = workbook.GetSheetAt(i);

                    Console.WriteLine(worksheet.SheetName);
                }
            }

        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

WorkbookFactory.cs

using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.IO;

namespace SampleCode
{
    public class WorkbookFactory
    {
        public static IWorkbook Create(Stream stream, string extension)
        {
            extension = extension.ToLower();

            return extension switch
            {
                ".xls" => new HSSFWorkbook(stream),
                ".xlsx" => new XSSFWorkbook(stream),
                _ => throw new NotSupportedException("対象外の拡張子です")
            };
        }

        public static IWorkbook Create(string extension)
        {
            extension = extension.ToLower();

            return extension switch
            {
                ".xls" => new HSSFWorkbook(),
                ".xlsx" => new XSSFWorkbook(),
                _ => throw new NotSupportedException("対象外の拡張子です")
            };
        }
    }
}
投稿日時: 2025-05-17 04:53:17
更新日時: 2025-05-26 14:21:26

シートが3つ入っているExcelを開いて、各ワークシートを取得し名前を出力します

ExcelVBA

Sub Sample()
    Dim BookObj     As Workbook
    Dim FilePath    As String
    Dim SheetObj    As Variant
    
    'ファイルパス作成
    FilePath = ThisWorkbook.Path & "\sample.xlsx"
    
    'ブックを開く
    Set BookObj = Workbooks.Open(FilePath)
    
    '全シート取得し、それぞれの名前を出力する
    For Each SheetObj In BookObj.Sheets
        Debug.Print SheetObj.Name
    Next
    
    '保存せずに閉じる
    BookObj.Close (False)
    
    Set BookObj = Nothing
End Sub

Excel(COM)

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

namespace SampleCode
{
    internal class SampleExcel
    {
        static void Main(string[] args)
        {
            Excel.Application? application = null;
            Excel.Workbooks? workbooks = null;
            Excel.Workbook? workbook = null;
            Excel.Sheets? worksheets = null;
            Excel.Worksheet? worksheet = null;

            try
            {
                // 実行ファイルのあるフォルダパス取得
                var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
                if (folderPath == null) { return; }

                // Excelファイルパスを作成
                var filePath = Path.Combine(folderPath, "sample.xlsx");
                
                // Excelを開く
                application = new Excel.Application();
                application.Visible = true;

                // ブックを開く
                workbooks = application.Workbooks;
                workbook = workbooks.Open(filePath);

                // シートを取得
                worksheets = workbook.Sheets;

                // 各シートの名前を出力
                for (var i = 1; i <= worksheets.Count; i++)
                {
                    // 各シートを取得して名前を表示
                    worksheet = worksheets[i];
                    Console.WriteLine(worksheet.Name);

                    CleanUpComObject(ref worksheet);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            finally
            {
                CleanUpComObject(ref worksheet);
                CleanUpComObject(ref worksheets);
                CleanUpComObject(ref workbook);
                CleanUpComObject(ref workbooks);
                CleanUpComObject(ref application);
            }
        }

        static void CleanUpComObject<T>(ref T comObject, bool shouldClose = true, bool saveChanges = false)
        {
            // フラグによってWorkbookはClose / ApplicationはQuitする
            if (shouldClose && comObject != null)
            {
                // 型をチェックする
                if (comObject is Microsoft.Office.Interop.Excel.Workbook workbook)
                {
                    // Workbookの場合
                    workbook.Close(saveChanges);
                }
                else if (comObject is Microsoft.Office.Interop.Excel.Application application)
                {
                    // Applicationの場合
                    application.Quit();
                }
            }

            // Objectを解放
            if (comObject != null && Marshal.IsComObject(comObject))
            {
                Marshal.ReleaseComObject(comObject);
                comObject = default!;
            }
        }
    }
}

補足:Microsoft.Office.Interop.Excel でオブジェクトの解放について

ClosedXML

using ClosedXML.Excel;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode
{
    internal class SampleClosedXML
    {
        static void Main(string[] args)
        {
            try
            {
                // 実行ファイルのあるフォルダパス取得
                var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
                if (folderPath == null) { return; }

                // Excelファイルパスを作成
                var filePath = Path.Combine(folderPath, "sample.xlsx");
                
                // ブックを開く、読み書きモード、共有なし(排他)
                using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
                using (var workbook = new XLWorkbook(stream))
                {
                    // ワークシートをループで処理
                    foreach (var worksheet in workbook.Worksheets)
                    {
                        // シート名を出力
                        Console.WriteLine(worksheet.Name);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }
}

EPPlus

using OfficeOpenXml;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode
{
    internal class SampleEPPlus
    {
        static void Main(string[] args)
        {
            // Ver8.0のソースです
            // 非商用個人利用の場合 名前を設定
            ExcelPackage.License.SetNonCommercialPersonal("SampleTarou");

            try
            {
                // 実行ファイルのあるフォルダパス取得
                var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
                if (folderPath == null) { return; }

                // Excelファイルパスを作成
                var filePath = Path.Combine(folderPath, "sample.xlsx");
                
                // ブックを開く、読み書きモード、共有なし(排他)
                using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
                using (var package = new ExcelPackage(stream))
                {
                    // ワークシートをループで処理
                    foreach(var worksheet in package.Workbook.Worksheets)
                    {
                        // シート名を出力
                        Console.WriteLine(worksheet.Name);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }
}

ExcelDataReader

using ExcelDataReader;
using System;
using System.Data;
using System.IO;
using System.Reflection;

namespace SampleCode
{
    internal class SampleExcelDataReader
    {
        static void Main(string[] args)
        {
            // デフォルトでは、エンコード(CP1252)がサポートされておらずエラーになるのでこれが必要
            System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);

            try
            {
                // 実行ファイルのあるフォルダパス取得
                var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
                if (folderPath == null) { return; }

                // Excelファイルパスを作成
                var filePath = Path.Combine(folderPath, "sample.xlsx");
                filePath = @"c:\temp\sample.xlsx"; //////////////////////////////////////////////ここ消す
                // ファイル開く、読み書きモード、共有なし(排他)
                using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
                using (var reader = ExcelReaderFactory.CreateReader(fileStream))
                {
                    // DataSetに変換(シート情報を取得)
                    var result = reader.AsDataSet();

                    // DataTableCollectionからDataTable(シート情報)を一つずつ取り出す
                    foreach (DataTable table in result.Tables)
                    {
                        // シート名を出力
                        Console.WriteLine(table.TableName);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }
}

NPOI

xls

using NPOI.HSSF.UserModel;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode
{
    internal class SampleNPOI_xls
    {
        static void Main(string[] args)
        {
            try
            {
                // 実行ファイルのあるフォルダパス取得
                var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
                if (folderPath == null) { return; }

                // Excelファイルパスを作成
                var filePath = Path.Combine(folderPath, "sample.xls");
                
                // ブックを開く、読み書きモード、共有なし(排他)
                using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
                {
                    using (var workbook = new HSSFWorkbook(fileStream))
                    {
                        // foreachはない。シート数からシート番号としてシートを受け取りシート名を表示
                        for (var i = 0; i < workbook.NumberOfSheets; i++)
                        {
                            var worksheet = workbook.GetSheetAt(i);

                            Console.WriteLine(worksheet.SheetName);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }
}

xlsx

using NPOI.XSSF.UserModel;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode
{
    internal class SampleNPOI_xlsx
    {
        static void Main(string[] args)
        {
            try
            {
                // 実行ファイルのあるフォルダパス取得
                var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
                if (folderPath == null) { return; }

                // Excelファイルパスを作成
                var filePath = Path.Combine(folderPath, "sample.xlsx");
                
                // ブックを開く、読み書きモード、共有なし(排他)
                using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
                {
                    using (var workbook = new XSSFWorkbook(fileStream))
                    {
                        // foreachはない。シート数からシート番号としてシートを受け取りシート名を表示
                        for (var i = 0; i < workbook.NumberOfSheets; i++)
                        {
                            var worksheet = workbook.GetSheetAt(i);

                            Console.WriteLine(worksheet.SheetName);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }
}

xlsもxlsxも扱う場合

Program.cs

using System;
using System.IO;
using System.Reflection;

namespace SampleCode
{
    internal class SampleNPOI
    {
        static void Main(string[] args)
        {
            try
            {
                // 実行ファイルのあるフォルダパス取得
                var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
                if (folderPath == null) { return; }

                // Excelファイルパスを作成
                var filePath = Path.Combine(folderPath, "sample.xlsx");
                filePath = @"c:\temp\sample.xlsx";
                
                var extension = Path.GetExtension(filePath);

                using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
                using (var workbook = WorkbookFactory.Create(fileStream, extension))
                {
                    for(var i = 0; i < workbook.NumberOfSheets; i++)
                    {
                        var worksheet = workbook.GetSheetAt(i);

                        Console.WriteLine(worksheet.SheetName);
                    }
                }

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }
}

WorkbookFactory.cs

using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.IO;

namespace SampleCode
{
    public class WorkbookFactory
    {
        public static IWorkbook Create(Stream stream, string extension)
        {
            extension = extension.ToLower();

            return extension switch
            {
                ".xls" => new HSSFWorkbook(stream),
                ".xlsx" => new XSSFWorkbook(stream),
                _ => throw new NotSupportedException("対象外の拡張子です")
            };
        }

        public static IWorkbook Create(string extension)
        {
            extension = extension.ToLower();

            return extension switch
            {
                ".xls" => new HSSFWorkbook(),
                ".xlsx" => new XSSFWorkbook(),
                _ => throw new NotSupportedException("対象外の拡張子です")
            };
        }
    }
}
投稿日時: 2025-05-17 04:52:17

ExcelVBA

SaveAsでファイルパスを指定する

Sub Sample()
    Dim BookObj     As Workbook
    Dim FilePath    As String
    
    '新規ブック作成
    Set BookObj = Workbooks.Add
    
    '保存するファイルパス
    FilePath = ThisWorkbook.Path & "\sample.xlsx"
    
    '名前つけて保存
    BookObj.SaveAs Filename:=FilePath
    
    Set BookObj = Nothing
End Sub

ただし、ファイルが既にある場合は「この場所に 'XXXX'という名前のファイルが既にあります。置き換えますか?」
と表示されるため、ファイルがある場合も上書きするのであれば、以下のようにします

Sub Sample()
    Dim BookObj     As Workbook
    Dim FilePath    As String
    
    '新規ブック作成
    Set BookObj = Workbooks.Add
    
    '保存するファイルパス
    
    'ファイルパス作成
    FilePath = ThisWorkbook.Path & "\sample.xls"
    
    '同一ファイルがあった場合の警告表示を無効とする
    Application.DisplayAlerts = False
    
    '名前つけて保存
    BookObj.SaveAs Filename:=FilePath
    
    '警告表示を有効に戻す
    Application.DisplayAlerts = True
    
    Set BookObj = Nothing
End Sub

もし、ファイルが既にある場合に上書きしたくない場合は事前にファイル存在チェックをして処理を止めればよいでしょう

Excel(COM)

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

namespace SampleCode; // C#10~

internal class SampleExcel
{
    static void Main(string[] args)
    {
        Excel.Application? application = null;
        Excel.Workbooks? workbooks = null;
        Excel.Workbook? workbook = null;

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // Excelを開く
            application = new Excel.Application();
            application.Visible = true;

            workbooks = application.Workbooks;
            workbook = workbooks.Add();

            // 警告表示を無効にする
            application.DisplayAlerts = false;

            // 名前つけて保存
            workbook.SaveAs2(filePath);

            // 警告表示を有効に戻す
            application.DisplayAlerts = false;
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        finally
        {
            CleanUpComObject(ref workbook, true, false);
            CleanUpComObject(ref workbooks);
            CleanUpComObject(ref application);

            // RCW強制解放(残留プロセス対策)
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            GC.WaitForPendingFinalizers();
        }
    }

    static void CleanUpComObject<T>(ref T comObject, bool shouldClose = true, bool saveChanges = false)
    {
        // フラグによってWorkbookはClose / ApplicationはQuitする
        if (shouldClose && comObject != null)
        {
            // 型をチェックする
            if (comObject is Microsoft.Office.Interop.Excel.Workbook workbook)
            {
                // Workbookの場合
                workbook.Close(saveChanges);
            }
            else if (comObject is Microsoft.Office.Interop.Excel.Application application)
            {
                // Applicationの場合
                application.Quit();
            }
        }

        // Objectを解放
        if (comObject != null && Marshal.IsComObject(comObject))
        {
            Marshal.ReleaseComObject(comObject);
            comObject = default!;
        }
    }
}

ClosedXML

ファイルパスと、Streamを使った方法

□ファイルパスで名前を付けて保存

using ClosedXML.Excel;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleClosedXML
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            using (var workbook = new XLWorkbook())
            {
                // シートが一つもないブックは保存でエラーになるので追加
                var sheet = workbook.AddWorksheet("Sheet1");

                // 名前をつけて保存
                workbook.SaveAs(filePath);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

□FileStreamで名前を付けて保存

using ClosedXML.Excel;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleClosedXML
{
    static void Main(string[] args)
    {
        var filePath = string.Empty;

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            filePath = Path.Combine(folderPath, "sample.xlsx");

            // ファイル出力用のストリームを作成(まだ中身は空のものが作られる)
            using (var stream = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite, FileShare.None))
            // メモリ上にワークブックを作成(この時点ではストリームとは未接続)
            using (var workbook = new XLWorkbook())
            {
                // シートが一つもないブックは保存でエラーになるので追加
                var sheet = workbook.AddWorksheet("Sheet1");

                // 作成したワークブックをストリームに保存(初めてファイルと紐づく)
                workbook.SaveAs(stream);
            }
        }
        catch (Exception ex)
        {
            // エラーが発生し、保存ができていなければ、空ファイルを作っただけなので、紛らわしいので消しておく
            if (!string.IsNullOrEmpty(filePath) && File.Exists(filePath))
            {
                File.Delete(filePath);
            }

            Console.WriteLine(ex.Message);
        }
    }
}

EPPlus

□ファイルパスで名前を付けて保存

using OfficeOpenXml;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleEPPlus
{
    static void Main(string[] args)
    {
        // Ver8.0のソースです
        // 非商用個人利用の場合 名前を設定
        ExcelPackage.License.SetNonCommercialPersonal("SampleTarou");

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            using (var package = new ExcelPackage())
            {
                // シートが一つもないブックは保存でエラーになるので追加
                var worksheet = package.Workbook.Worksheets.Add("sample");

                // 保存
                package.SaveAs(filePath);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

FileStreamを使った場合は、ClosedXMLと同じなのでそちらを参照

ExcelDataReader

読み取りのみのライブラリのため保存はありません

NPOI

NPOIは、ファイルパスをうけとれないので、FileStreamで処理する

□xls

using NPOI.HSSF.UserModel;
using System.Reflection;

var filePath = "";
try
{
    // 実行ファイルのあるフォルダパス取得
    var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
    if (folderPath == null) { return; }

    // Excelファイルパスを作成
    filePath = Path.Combine(folderPath, "sample.xls");
    
    using (var stream = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite, FileShare.None))
    using (var workbook = new HSSFWorkbook())
    {
        // シートが一つもないブックは保存でエラーになるので追加
        workbook.CreateSheet("Sheet1");

        // 作成したワークブックをストリームに保存
        workbook.Write(stream);
    }
}
catch (Exception ex)
{
    // エラーが発生し、保存ができていなければ、空ファイルを作っただけなので、紛らわしいので消しておく
    if (!string.IsNullOrEmpty(filePath) && File.Exists(filePath))
    {
        File.Delete(filePath);
    }

    Console.WriteLine(ex.Message);
}

□xlsx

using NPOI.XSSF.UserModel;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleNPOI_xlsx
{
    static void Main(string[] args)
    {
        var filePath = "";

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            filePath = Path.Combine(folderPath, "sample.xlsx");

            using (var stream = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite, FileShare.None))
            using (var workbook = new XSSFWorkbook())
            {
                // シートなしでも保存はできてしまう
                // sample.xlsxの一部の内容に問題が見つかりました。と出るのでシートは追加すること
                workbook.CreateSheet("Sheet1");

                // 作成したワークブックをストリームに保存
                workbook.Write(stream);
            }
        }
        catch (Exception ex)
        {
            // エラーが発生し、保存ができていなければ、空ファイルを作っただけなので、紛らわしいので消しておく
            if (!string.IsNullOrEmpty(filePath) && File.Exists(filePath))
            {
                File.Delete(filePath);
            }

            Console.WriteLine(ex.Message);
        }
    }
}

□xls/xlsx対応版

Program.cs

using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleNPOI
{
    static void Main(string[] args)
    {
        var filePath = "";

        try
        {   // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            filePath = Path.Combine(folderPath, "sample.xlsx");

            var extension = Path.GetExtension(filePath);

            // ブックを開く、読み取りモード、共有は読み取りのみOK
            using (var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite, FileShare.None))
            using (var workbook = WorkbookFactory.Create(fileStream, extension))
            {
                // シートなしでも保存はできてしまう
                // sample.xlsxの一部の内容に問題が見つかりました。と出るのでシートは追加すること
                workbook.CreateSheet("Sheet1");

                // 作成したワークブックをストリームに保存
                workbook.Write(fileStream);
            }
        }
        catch (Exception ex)
        {
            // エラーが発生し、保存ができていなければ、空ファイルを作っただけなので、紛らわしいので消しておく
            if (!string.IsNullOrEmpty(filePath) && File.Exists(filePath))
            {
                File.Delete(filePath);
            }

            Console.WriteLine(ex.Message);
        }
    }
}

WorkbookFactory.cs

using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.IO;

namespace SampleCode; // C#10

public class WorkbookFactory
{
    public static IWorkbook Create(Stream stream, string extension)
    {
        extension = extension.ToLower();

        return extension switch
        {
            ".xls" => new HSSFWorkbook(stream),
            ".xlsx" => new XSSFWorkbook(stream),
            _ => throw new NotSupportedException("対象外の拡張子です")
        };
    }

    public static IWorkbook Create(string extension)
    {
        extension = extension.ToLower();

        return extension switch
        {
            ".xls" => new HSSFWorkbook(),
            ".xlsx" => new XSSFWorkbook(),
            _ => throw new NotSupportedException("対象外の拡張子です")
        };
    }
}
投稿日時: 2025-05-11 10:19:11
更新日時: 2025-05-24 11:45:24

ExcelVBA

Open関数のPasswordに設定

Sub Sample()
    Dim BookObj     As Workbook
    Dim FilePath    As String
    Dim ReadPass    As String: ReadPass = "test"
    
    'ファイルパス作成
    FilePath = ThisWorkbook.Path & "\sample.xlsx"
    
    'パスワード付きExcelを開く
    Set BookObj = Workbooks.Open(FilePath, Password:=ReadPass)
    
    Set BookObj = Nothing
End Sub

Excel(COM)

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

namespace SampleCode; // C#10~

internal class SampleExcel
{
    static void Main(string[] args)
    {
        Excel.Application? application = null;
        Excel.Workbooks? workbooks = null;
        Excel.Workbook? workbook = null;

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // Excelを開く
            application = new Excel.Application();
            application.Visible = true;
            workbooks = application.Workbooks;

            // 書き込みパスワード
            var pass = "test";

            // 書き込みパスワードでブックを開く
            workbook = workbooks.Open(Filename: filePath, Password: pass);  // 名前付き引数がおすすめ
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        finally
        {
            CleanUpComObject(ref workbook, true, false);
            CleanUpComObject(ref workbooks);
            CleanUpComObject(ref application);

            // RCW強制解放(残留プロセス対策)
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            GC.WaitForPendingFinalizers();
        }
    }

    static void CleanUpComObject<T>(ref T comObject, bool shouldClose = true, bool saveChanges = false)
    {
        // フラグによってWorkbookはClose / ApplicationはQuitする
        if (shouldClose && comObject != null)
        {
            // 型をチェックする
            if (comObject is Microsoft.Office.Interop.Excel.Workbook workbook)
            {
                // Workbookの場合
                workbook.Close(saveChanges);
            }
            else if (comObject is Microsoft.Office.Interop.Excel.Application application)
            {
                // Applicationの場合
                application.Quit();
            }
        }

        // Objectを解放
        if (comObject != null && Marshal.IsComObject(comObject))
        {
            Marshal.ReleaseComObject(comObject);
            comObject = default!;
        }
    }
}

ClosedXML

未対応

EPPlus

未対応

ExcelDataReader

未対応

NPOI

未対応

参考:
ClosedXML, ExcelDataReader, EPPlus, NPOIがパスワード解除について

投稿日時: 2025-05-11 07:00:11
更新日時: 2025-05-24 09:47:24

ExcelVBA

VBAだとWritePasswordにパスを設定しておけば、開いた際にパスを求められるようになります

Sub Sample()
    Dim BookObj     As Workbook
    Dim FilePath    As String
    Dim WritePass   As String: Pass = "test"
    
    'ファイルパス作成
    FilePath = ThisWorkbook.Path & "\sample.xlsx"
    
    '書き込みパスワード付きExcelを開く
    Set BookObj = Workbooks.Open(FilePath, WriteResPassword:=WritePass)
    
    Set BookObj = Nothing
End Sub

Excel(COM)

Excel(COM)も同様です。

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

namespace SampleCode; // C#10~

internal class SampleExcel
{
    static void Main(string[] args)
    {
        Excel.Application? application = null;
        Excel.Workbooks? workbooks = null;
        Excel.Workbook? workbook = null;

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");
            // Excelを開く
            application = new Excel.Application();
            application.Visible = true;
            workbooks = application.Workbooks;

            // 書き込みパスワード
            var writePass = "test";

            // 書き込みパスワードでブックを開く
            workbook = workbooks.Open(Filename: filePath, WriteResPassword: writePass);  // 名前付き引数がおすすめ
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        finally
        {
            CleanUpComObject(ref workbook, true, false);
            CleanUpComObject(ref workbooks);
            CleanUpComObject(ref application);

            // RCW強制解放(残留プロセス対策)
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            GC.WaitForPendingFinalizers();
        }
    }

    static void CleanUpComObject<T>(ref T comObject, bool shouldClose = true, bool saveChanges = false)
    {
        // フラグによってWorkbookはClose / ApplicationはQuitする
        if (shouldClose && comObject != null)
        {
            // 型をチェックする
            if (comObject is Microsoft.Office.Interop.Excel.Workbook workbook)
            {
                // Workbookの場合
                workbook.Close(saveChanges);
            }
            else if (comObject is Microsoft.Office.Interop.Excel.Application application)
            {
                // Applicationの場合
                application.Quit();
            }
        }

        // Objectを解放
        if (comObject != null && Marshal.IsComObject(comObject))
        {
            Marshal.ReleaseComObject(comObject);
            comObject = default!;
        }
    }
}

ClosedXML

未対応

EPPlus

未対応

ExcelDataReader

未対応

NPOI

未対応

参考:
ClosedXML, ExcelDataReader, EPPlus, NPOIがパスワード解除について

投稿日時: 2025-05-10 18:18:10
更新日時: 2025-05-24 09:25:24

通常のxlsxのファイルは拡張子をzipにし、展開するとファイルの中身が確認できます

それに対し、読み取りパスワードを設定すると、ファイル全体が暗号化されるため、同様のことはできません。

暗号化されているためzip構造になっていないということですね。

GPTの予想では、ファイル全体の暗号化/複合化の対応まで対処するのが大変なので、これらのライブラリでは読み取りパスワードの解除機能はないのではないかとのこと。

書き込みパスワードの場合はどうかというと、書き込みパスワードであれば閲覧できないわけではないので、
zip化して開いて中身をみることができます

xl/workbook.xml を開くと以下のように埋め込まれていて

<fileSharing userName="ユーザー名" algorithmName="SHA-512" hashValue="/Sjoy10H3uY10Lh1Ew7UkIlk8b6ZAVNvvpd6LUsgoFJFYrkn7QJ2e2nAgguO1gdRRWwK9NrGpaduJG5y6nZsLA==" saltValue="3GWq9TRXLA7h35x78qzkHQ==" spinCount="100000"/>

ざっくりとした解釈では、入力された書き込みパスワードにsaltをつけてハッシュ化し、
もとまった値に対してもsaltをつけてハッシュ化することを100000をくりかえした結果をhasValueに設定している

詳細の仕様については、 以下に仕様ありとのこと
MS-OFFCRYPTO
https://learn.microsoft.com/en-us/openspecs/office_file_formats/ms-offcrypto/3c34d72a-1a61-4b52-a893-196f9157f083

生成AIにいろいろ確認した内容のまとめ

ライブラリ 読み取りパスワード解除 書き込みパスワード解除 書き込みパスワード設定 シートの保護設定 シート保護解除して書き込み
ClosedXML ×非対応 ×非対応 ×非対応 〇対応 〇対応
EPPlus ×非対応 ×非対応 〇対応 〇対応 〇対応
ExcelDataReader ×非対応 ×非対応 ×非対応 ×非対応 ×非対応
NPOI ×非対応 ×非対応 ×非対応 〇対応 〇対応

EPPlusにおいては、書き込みパスワードの設定が可能であり、
シートの保護関係については、ExcelDataReader以外は対応している様子です

極論をいえば、XMLファイルを操作するだけなので、ファイル全体が暗号化されていなければ、ただの文字列が書き込まれているだけなので
ライブラリ側で無視してしまえば、書き込みパスワードもシートの保護もなかったことになってしまうという話ですが・・・

実際は、シートの保護は対応しても、書き込みパスワードについては対応していないのが現状のようです。。

生成AIの予想では倫理的なものではという話ですが、ちょっと謎です

投稿日時: 2025-05-10 18:17:10
更新日時: 2025-05-11 05:53:11

ExcelVBA

Open時、ReadOnlyをTrueにすることで読み取り専用で開く

Sub Sample()
    Dim BookObj As Workbook
    Dim FilePath    As String
    
    'ファイルパス作成
    FilePath = ThisWorkbook.Path & "\sample.xlsx"
    
    'ブックを開く
    Set BookObj = Workbooks.Open(FilePath, ReadOnly:=True)
    
    Set BookObj = Nothing
End Sub

Excel(COM)

VBA同様 ReadOnlyにTrueを指定して、読み取り専用で開く

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

namespace SampleCode; // C#10~

internal class SampleExcel
{
    static void Main(string[] args)
    {
        Excel.Application? application = null;
        Excel.Workbooks? workbooks = null;
        Excel.Workbook? workbook = null;

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // Excelを開く
            application = new Excel.Application();
            application.Visible = true;
            workbooks = application.Workbooks;
            // ブックを開く(ReadOnlyの項目をtrue)
            workbook = workbooks.Open(Filename: filePath, ReadOnly: true); // 名前付き引数がおすすめ
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        finally
        {
            CleanUpComObject(ref workbook, true, false);
            CleanUpComObject(ref workbooks);
            CleanUpComObject(ref application);

            // RCW強制解放(残留プロセス対策)
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            GC.WaitForPendingFinalizers();
        }
    }

    static void CleanUpComObject<T>(ref T comObject, bool shouldClose = true, bool saveChanges = false)
    {
        // フラグによってWorkbookはClose / ApplicationはQuitする
        if (shouldClose && comObject != null)
        {
            // 型をチェックする
            if (comObject is Microsoft.Office.Interop.Excel.Workbook workbook)
            {
                // Workbookの場合
                workbook.Close(saveChanges);
            }
            else if (comObject is Microsoft.Office.Interop.Excel.Application application)
            {
                // Applicationの場合
                application.Quit();
            }
        }

        // Objectを解放
        if (comObject != null && Marshal.IsComObject(comObject))
        {
            Marshal.ReleaseComObject(comObject);
            comObject = default!;
        }
    }
}

ClosedXML

FileStreamで読み取り専用で開く

using ClosedXML.Excel;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleClosedXML
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // ブックを開く、読み取りモード、共有なし(排他)
            using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
            using (var workbook = new XLWorkbook(stream))
            {
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

EPPlus

FileStreamで読み取り専用で開く

using OfficeOpenXml;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleEPPlus
{
    static void Main(string[] args)
    {
        // Ver8.0のソースです
        // 非商用個人利用の場合 名前を設定
        ExcelPackage.License.SetNonCommercialPersonal("SampleTarou");

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // ブックを開く、読み取りモード、共有は読み取りのみOK
            using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
            using (var package = new ExcelPackage(stream))
            {
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

ExcelDataReader

FileAccessがReadであろうがなかろうが、読み取りのみのライブラリのため書き込む機能なし

using ExcelDataReader;
using System;
using System.Data;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleExcelDataReader
{
    static void Main(string[] args)
    {
        // デフォルトでは、エンコード(CP1252)がサポートされておらずエラーになるのでこれが必要
        System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // ブックを開く、読み取りモード、共有は読み取りのみOK
            using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
            using (var reader = ExcelReaderFactory.CreateReader(fileStream))
            {
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

NPOI

FileStreamで読み取り専用で開く
□xls

using NPOI.HSSF.UserModel;
using System;
using System.IO;
using System.Reflection;


namespace SampleCode; // C#10~

internal class SampleNPOI_xls
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xls");

            // ブックを開く、読み取りモード、共有は読み取りのみOK
            using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                var workbook = new HSSFWorkbook(fileStream);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

□xlsx

using NPOI.XSSF.UserModel;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleNPOI_xlsx
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // ブックを開く、読み取りモード、共有は読み取りのみOK
            using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                var workbook = new XSSFWorkbook(fileStream);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

□xls/xlsx対応版

Program.cs

using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleNPOI
{
    static void Main(string[] args)
    {
        try
        {   // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            var extension = Path.GetExtension(filePath);

            // ブックを開く、読み取りモード、共有は読み取りのみOK
            using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
            using (var workbook = WorkbookFactory.Create(fileStream, extension))
            { 
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

WorkbookFactory.cs

using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.IO;

namespace SampleCode; // C#10

public class WorkbookFactory
{
    public static IWorkbook Create(Stream stream, string extension)
    {
        extension = extension.ToLower();

        return extension switch
        {
            ".xls" => new HSSFWorkbook(stream),
            ".xlsx" => new XSSFWorkbook(stream),
            _ => throw new NotSupportedException("対象外の拡張子です")
        };
    }

    public static IWorkbook Create(string extension)
    {
        extension = extension.ToLower();

        return extension switch
        {
            ".xls" => new HSSFWorkbook(),
            ".xlsx" => new XSSFWorkbook(),
            _ => throw new NotSupportedException("対象外の拡張子です")
        };
    }
}
投稿日時: 2025-05-10 16:10:10
更新日時: 2025-05-24 09:06:24

既存ファイルを開く

ExcelVBA

Sub Sample()
    Dim BookObj As Workbook
    Dim FilePath    As String
    
    'ファイルパス作成
    FilePath = ThisWorkbook.Path & "\sample.xlsx"
    
    'ブックを開く
    Set BookObj = Workbooks.Open(FilePath)
    
    Set BookObj = Nothing
End Sub

Excel(COM)

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

namespace SampleCode; // C#10~

internal class SampleExcel
{
    static void Main(string[] args)
    {
        Excel.Application? application = null;
        Excel.Workbooks? workbooks = null;
        Excel.Workbook? workbook = null;

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // Excelを開く
            application = new Excel.Application();
            application.Visible = true;
            workbooks = application.Workbooks;
            // ブックを開く
            workbook = workbooks.Open(filePath);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        finally
        {
            CleanUpComObject(ref workbook, true, false);
            CleanUpComObject(ref workbooks);
            CleanUpComObject(ref application);

            // RCW強制解放(残留プロセス対策)
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            GC.WaitForPendingFinalizers();
        }
    }

    static void CleanUpComObject<T>(ref T comObject, bool shouldClose = true, bool saveChanges = false)
    {
        // フラグによってWorkbookはClose / ApplicationはQuitする
        if (shouldClose && comObject != null)
        {
            // 型をチェックする
            if (comObject is Microsoft.Office.Interop.Excel.Workbook workbook)
            {
                // Workbookの場合
                workbook.Close(saveChanges);
            }
            else if (comObject is Microsoft.Office.Interop.Excel.Application application)
            {
                // Applicationの場合
                application.Quit();
            }
        }

        // Objectを解放
        if (comObject != null && Marshal.IsComObject(comObject))
        {
            Marshal.ReleaseComObject(comObject);
            comObject = default!;
        }
    }
}

補足:Microsoft.Office.Interop.Excel でオブジェクトの解放について

ClosedXML

ファイルパス、FileStreamを使った開き方

□ファイルパスを使って開く

using ClosedXML.Excel;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleClosedXML
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            using (var workbook = new XLWorkbook(filePath))
            {
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

□FileStreamを使って開く

using ClosedXML.Excel;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleClosedXML
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // ブックを開く、読み書きモード、共有なし(排他)
            using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            using (var workbook = new XLWorkbook(fileStream))
            {
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

fileStreamを使えば、ファイルへのアクセス方法(読み書き)や他プロセスへの共有方法も制御できるので細かい制御が必要であればこちらを使う

EPPlus

ファイルパス、FileInfo、FileStreamを使った開き方

□ファイルパスを使って開く

using OfficeOpenXml;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleEPPlus
{
    static void Main(string[] args)
    {
        // Ver8.0のソースです
        // 非商用個人利用の場合 名前を設定
        ExcelPackage.License.SetNonCommercialPersonal("SampleTarou");

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // ファイルパスで開く
            using (var package = new ExcelPackage(filePath))
            {
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

□FileInfoを使って開く

using OfficeOpenXml;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleEPPlus
{
    static void Main(string[] args)
    {
        // Ver8.0のソースです
        // 非商用個人利用の場合 名前を設定
        ExcelPackage.License.SetNonCommercialPersonal("SampleTarou");

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // ファイルの情報を使う予定があるならfleinfoで開く
            var fileInfo = new FileInfo(filePath);

            // ファイルパスで開く
            using (var package = new ExcelPackage(fileInfo))
            {
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

更新日時とかファイルの情報を使う予定ならFileInfoを使って開く


□FileStreamを使って開く

using OfficeOpenXml;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleEPPlus
{
    static void Main(string[] args)
    {
        // Ver8.0のソースです
        // 非商用個人利用の場合 名前を設定
        ExcelPackage.License.SetNonCommercialPersonal("SampleTarou");

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // ブックを開く、読み書きモード、共有なし(排他)
            using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            using (var package = new ExcelPackage(fileStream))
            {
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

fileStreamを使えば、ファイルへのアクセス方法(読み書き)や他プロセスへの共有方法も制御できるので細かい制御が必要であればこちらを使う

ExcelDataReader

Streamのみ

using ExcelDataReader;
using System;
using System.Data;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleExcelDataReader
{
    static void Main(string[] args)
    {
        // デフォルトでは、エンコード(CP1252)がサポートされておらずエラーになるのでこれが必要
        System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);

        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // ブックを開く、読み取りモード、共有は読み取りのみOK
            using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
            using (var reader = ExcelReaderFactory.CreateReader(fileStream))
            {
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

NPOI

Streamのみ

□xls

using NPOI.HSSF.UserModel;
using System;
using System.IO;
using System.Reflection;


namespace SampleCode; // C#10~

internal class SampleNPOI_xls
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xls");

            // ブックを開く、読み書きモード、共有なし(排他)
            using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            using (var workbook = new HSSFWorkbook(fileStream))
            {
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

□xlsx

using NPOI.XSSF.UserModel;
using System;
using System.IO;
using System.Reflection;

namespace SampleCode; // C#10~

internal class SampleNPOI_xlsx
{
    static void Main(string[] args)
    {
        try
        {
            // 実行ファイルのあるフォルダパス取得
            var folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (folderPath == null) { return; }

            // Excelファイルパスを作成
            var filePath = Path.Combine(folderPath, "sample.xlsx");

            // ブックを開く、読み書きモード、共有なし(排他)
            using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            using (var workbook = new XSSFWorkbook(fileStream))
            {
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

□xls/xlsx対応版

Program.cs

using System;
namespace SampleCode; // C#10~

internal class SampleNPOI
{
    static void Main(string[] args)
    {
        try
        {   // xls
            using (var workbook_xls = WorkbookFactory.Create(".xls"))
            {
            }

            // xlsx
            using (var workbook_xlsx = WorkbookFactory.Create(".xlsx"))
            {
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

WorkbookFactory.cs

using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.IO;

namespace SampleCode; // C#10

public class WorkbookFactory
{
    public static IWorkbook Create(Stream stream, string extension)
    {
        extension = extension.ToLower();

        return extension switch
        {
            ".xls" => new HSSFWorkbook(stream),
            ".xlsx" => new XSSFWorkbook(stream),
            _ => throw new NotSupportedException("対象外の拡張子です")
        };
    }

    public static IWorkbook Create(string extension)
    {
        extension = extension.ToLower();

        return extension switch
        {
            ".xls" => new HSSFWorkbook(),
            ".xlsx" => new XSSFWorkbook(),
            _ => throw new NotSupportedException("対象外の拡張子です")
        };
    }
}
投稿日時: 2025-05-08 16:15:08
更新日時: 2025-05-24 11:51:24

新規にブックを作成する

ExcelVBA

Sub Sample()
    Dim bookObj As workbook
    
    Set bookObj = Workbooks.Add
    
    Set bookObj = Nothing
End Sub

Excel(COM)

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

namespace SampleCode; // C#10~

internal class SampleExcel
{
    static void Main(string[] args)
    {
        Excel.Application? application = null;
        Excel.Workbooks? workbooks = null;
        Excel.Workbook? workbook = null;

        try
        {
            // Excelが起動
            application = new Excel.Application();

            // 表示
            application.Visible = true; // 処理を確認したいときだけtrueにする

            // ブックを追加
            workbooks = application.Workbooks;
            workbook = workbooks.Add();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        finally
        {
            CleanUpComObject(ref workbook, true, false);
            CleanUpComObject(ref workbooks);
            CleanUpComObject(ref application);

            // RCW強制解放(残留プロセス対策)
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            GC.WaitForPendingFinalizers();
        }
    }

    static void CleanUpComObject<T>(ref T comObject, bool shouldClose = true, bool saveChanges = false)
    {
        // フラグによってWorkbookはClose / ApplicationはQuitする
        if (shouldClose && comObject != null)
        {
            // 型をチェックする
            if (comObject is Microsoft.Office.Interop.Excel.Workbook workbook)
            {
                // Workbookの場合
                workbook.Close(saveChanges);
            }
            else if (comObject is Microsoft.Office.Interop.Excel.Application application)
            {
                // Applicationの場合
                application.Quit();
            }
        }

        // Objectを解放
        if (comObject != null && Marshal.IsComObject(comObject))
        {
            Marshal.ReleaseComObject(comObject);
            comObject = default!;
        }
    }
}

補足:Microsoft.Office.Interop.Excel でオブジェクトの解放について

ClosedXML

using ClosedXML.Excel;
using System;

namespace SampleCode; // C#10~

internal class SampleClosedXML
{
    static void Main(string[] args)
    {
        try
        {
            using (var workbook = new XLWorkbook())
            {
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

EPPlus

using OfficeOpenXml;
using System;
namespace SampleCode; // C#10~

internal class SampleEPPlus
{
    static void Main(string[] args)
    {
        // Ver8.0のソースです
        // 非商用個人利用の場合 名前を設定
        ExcelPackage.License.SetNonCommercialPersonal("SampleTarou");

        try
        {
            using (var package = new ExcelPackage())
            {
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

ExcelDataReader

読み取りのみのライブラリのためなし

NPOI

□xls

using NPOI.HSSF.UserModel;
using System;


namespace SampleCode; // C#10~

internal class SampleNPOI_xls
{
    static void Main(string[] args)
    {
        try
        {
            using (var workbook = new HSSFWorkbook())
            {
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

□xlsx

using NPOI.XSSF.UserModel;
using System;

namespace SampleCode; // C#10~

internal class SampleNPOI_xlsx
{
    static void Main(string[] args)
    {
        try
        {
            // xlsx形式
            using (var workbook = new XSSFWorkbook())
            {
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

□xls/xlsx対応版

Program.cs

using System;
namespace SampleCode; // C#10~

internal class SampleNPOI
{
    static void Main(string[] args)
    {
        try
        {   // xls
            using (var workbook_xls = WorkbookFactory.Create(".xls"))
            {
            }

            // xlsx
            using (var workbook_xlsx = WorkbookFactory.Create(".xlsx"))
            {
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

WorkbookFactory.cs

using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.IO;

namespace SampleCode; // C#10

public class WorkbookFactory
{
    public static IWorkbook Create(Stream stream, string extension)
    {
        extension = extension.ToLower();

        return extension switch
        {
            ".xls" => new HSSFWorkbook(stream),
            ".xlsx" => new XSSFWorkbook(stream),
            _ => throw new NotSupportedException("対象外の拡張子です")
        };
    }

    public static IWorkbook Create(string extension)
    {
        extension = extension.ToLower();

        return extension switch
        {
            ".xls" => new HSSFWorkbook(),
            ".xlsx" => new XSSFWorkbook(),
            _ => throw new NotSupportedException("対象外の拡張子です")
        };
    }
}
投稿日時: 2025-05-08 15:05:08
更新日時: 2025-05-24 01:57:24

参考になりそうなサイト

ClosedXML

github
https://github.com/ClosedXML/ClosedXML

旧wiki
https://github.com/closedxml/closedxml/wiki

徐々に移行しているというwiki
https://docs.closedxml.io/en/latest/

ExcelDataReader

github
https://github.com/ExcelDataReader/ExcelDataReader

ドキュメントっぽいものがみあたらなかったのでwikiくらいしかみるとこはないかも

EPPlus

github
https://github.com/EPPlusSoftware/EPPlus

公式サイト https://www.epplussoftware.com/ja ※いろいろ情報があるのでみるとよいかも

ドキュメント
https://www.epplussoftware.com/ja/Developers

EPPlus source code docsから使用するバージョンを選択するとそのドキュメントが見れます。

NPOI

github
https://github.com/nissl-lab/npoi

チュートリアル
https://github.com/nissl-lab/npoi-tutorial

投稿日時: 2025-05-08 13:02:08

COM経由でExcelを操作するための準備

依存関係から右クリックでCOM参照の追加を選択

Microsoft.Excel XX.X ObjectLibrary を選択(要Excelインストール)

OKで閉じる

ClosedXMLでExcelを操作するための準備

Nugetから ClosedXML をインストール

ExcelDataReaderでExcelを操作するための準備

Nugetから ExcelDataReader をインストール

ExcelDataReader.DataSetもインストールしてください
AsDataSet() を使うのに必要になってきます

EPPlusでExcelを操作するための準備

Nugetから EPPlus をインストール

NPOIでExcelを操作するための準備

Nugetから NPOIをインストール

投稿日時: 2025-05-07 13:02:07
更新日時: 2025-05-17 04:16:17

C#からExcel操作方法のメモ

ライブラリ .xls .xlsx 読み 書き ライセンス
ClosedXML × MIT
ExcelDataReader × MIT
NPOI Apache 2.0
EPPlus × Polyform Noncommercial License 1.0.0

ClosedXML、ExcelDataReader、EPPlus、NPOIのドキュメント・チュートリアル

Excel(COM)、ClosedXML、ExcelDataReader、NPOI、EPPlusを使えるようにする


早見表

項目 Excel(COM) ClosedXML EPPlus ExcelDataReader NPOI
ファイルパスオープン × ×
FileInfoオープン × × × ×
FileStreamオープン ×
行列番号 1~ 1~ 1~ 0~ 0~
シート番号 1~ 1~ 0~ 0~ 0~
シート取得 Sheets変数[ ] Worksheet() Worksheets() - GetSheetAt()/GetSheet()
存在しないシート 例外 例外 null null null

ワークブック

処理 Excel(COM) ClosedXML EPPlus ExcelDataReader NPOI
ブックを作成 ×
ブックを開く
ブックを開く(読み取り専用)
ブックを開く(書き込みパスワード付き) × × × ×
ブックを開く(開くパスワード付き) × × × ×
ブックを保存(名前をつけて保存) ×
上書き保存 ×

ワークシート

処理 Excel(COM) ClosedXML EPPlus ExcelDataReader NPOI
シートの数を取得する
全てのシートを取得しその名前を出力する
シート名を変更 ×
シートを追加する(一番最後) ×
シートの削除 ×
ワークシートの参照
アクティブなシートを取得/設定 ×
表示倍率の取得 × ×
表示倍率の設定 ×
シートの保護 ×
シートの解除 ×

(補足)シートの解除は、NPOIだとパス無し保護は解除できても、パス有り保護は解除できなさそう


セル

処理 Excel(COM) ClosedXML EPPlus ExcelDataReader NPOI
A1形式でセルの値取得 × ×
R1C1形式でセルの値取得
複数のセルを範囲で取得し、1つずつ取り出し値を出力
セルのアドレス × ×
セルに値を設定する ×

参考

ClosedXML, ExcelDataReader, EPPlus, NPOIがパスワード解除について

Officeのサーバー上でのCOM経由による自動操作について

Microsoft.Office.Interop.Excel でオブジェクトの解放について

解放ヘルパークラスを使ったオブジェクトの解放

R1C1情報からA1形式への変換

EPPlus/NPOIで既存ファイルを開き、保存する方法

EPPlusでファイル作成、保存方法

投稿日時: 2025-05-07 12:05:07
更新日時: 2025-05-28 14:58:28

最近の投稿

最近のコメント

タグ

アーカイブ

その他