C#でExcelファイル印刷を自動化してみる

# 1. はじめに
* Excelファイルの印刷を自動で実行したい
* タスクスケジューラーから定時起動したい

# 2. 開発環境
* Visual Stduio 2022
* .NET 8
* Windows 11
* Excel 2021

# 3. 自動処理の内容
* コンソールアプリとして作成する
* ファイル名、プリンタ名は一旦固定とする
* Excelファイルが複数シートある場合、シート分印刷する
* タスクスケジューラから起動できるようにする

# 4. 事前準備
## 4.1. Visual Stduioの設定
* 「Microsoft Excel 16.0 Object Library」の参照設定を追加する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/0fb20f71-f52d-78c1-de9d-68ff3a528322.png)

## 4.2. コンポーネントサービスの設定 (Excel)
* 設定を変更しない場合、タスクスケジューラから起動できない。

### 1. マイ コンピューター > DCOM構成 > Microsoft Excel Applicationを右クリックして、プロパティを選択する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/2d23e7ba-e6f0-e52d-fa87-bf9696f979a8.png)

### 2.  IDタブを開いて、対話ユーザーに変更する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/69813e71-b706-c7f3-906f-9d1130c7318e.png)

# 5. ソースコード
```C#:Program.cs
using System.Runtime.InteropServices;
using Excel = Microsoft.Office.Interop.Excel;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {

            Excel.Application? app = null;

             try
            {
                // Excelオブジェクトを生成する
                app = new Excel.Application();

                Excel.Workbook? wb = null;

                try
                {
                    // 印刷ファイルを開く
                    wb = app.Workbooks.Open(@"D:\Book1.xlsx");

                    // 全シートを印刷する
                    foreach (Excel.Worksheet sh in wb.Sheets)
                    {
                        try
                        {
                            // 固定のプリンタへ印刷する
                            sh.PrintOutEx(ActivePrinter: "Microsoft Print to PDF");
                        }
                        catch (Exception ex)
                        {
                            throw new ApplicationException(sh.Name, ex);
                        }
                    }
                }
                finally
                {
                    if (wb != null)
                    {
                        // Excelファイルを閉じる
                        wb.Close();
                    }
                }
            }
            catch (Exception ex)
            {
                // エラーメッセージを出力
                Console.WriteLine(ex.ToString());
            }
            finally
            {
                if (app != null)
                {
                    // Excelオブジェクトを終了する
                    GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect();
                    app.Quit();
                    Marshal.ReleaseComObject(app); app = null;
                    GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect();
                }
            }
        }

   }
}
```

# 6. 注意事項

## 6.1. Excelオブジェクトの開放
* 単純にExcelオブジェクトをQuitしただけだとプロセスが残るため、後処理が必要になる。

https://learn.microsoft.com/en-us/archive/blogs/office_client_development_support_blog/office-5

https://learn.microsoft.com/ja-jp/archive/blogs/office_client_development_support_blog/office-3

## 6.2. タスクスケジューラの利用可能ユーザ
* タスクスケジューラのユーザーではプリンタへの印刷ができないため、DCOMの設定変更をしておく必要がある。

https://www.yo3.dev/%E3%80%90c%E3%80%91%E3%82%A8%E3%82%AF%E3%82%BB%E3%83%AB%E3%82%92pdf%E3%81%AB%E5%A4%89%E6%8F%9B%E3%81%99%E3%82%8B%EF%BC%88office%E4%BD%BF%E7%94%A8%EF%BC%89

## 6.3. Office のオートメーションをサーバーサイドで使用する際の問題
* Windows Server上で実行する場合、複雑な問題があるので利用しないほうがよい。

https://stackoverflow.com/questions/36085083/automatically-print-excel-from-windows-service

https://support.microsoft.com/ja-jp/topic/office-%E3%81%AE%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E3%82%B5%E3%82%A4%E3%83%89-%E3%82%AA%E3%83%BC%E3%83%88%E3%83%A1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6-48bcfe93-8a89-47f1-0bce-017433ad79e2

# 7. 参考文献

http://nonsoft.la.coocan.jp/SoftSample/CS.NET/SampleExcelPrint.html

https://mseeeen.msen.jp/printer-selector-in-wpf/