C#でExcelをPDFに変換する

###１．はじめに

C#で書かれてるプログラムに改修要件でExcelをPDFに変換する機能を追加してほしいと要望があったので、備忘録として書いておきたいと思います。
ここに書いたコードは機能についてお客さんに確認したいことがいくつかあったので、デモとして持って行ったものになります。(Pathとかはさすがに変えてます)

先に断らせていただきたいのですが、私はエンジニアとして2年目に突入したばかりで、C#は今回が初めての使用になります。
コード的に読みにくいところや、その書き方信じられない…ってところもあるとは思うのですが、そういったところはぜひご指摘いただければと思います。
ちなみに一番使い慣れている言語はJavaです。


###２．実際のコード

今回はCドライブ直下にPDFTestというフォルダを作成して、その中に変換したいExcelファイルを配置しておくという前提になります。
また、参照の追加＞COM　でMicrosoft Excel 14.0 Object Libraryってのを追加しておかなければいけません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302561/184abfa2-ff41-6939-9963-bdf6bb516e52.png)



```c#:ComRelese.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
namespace Excel2PDF
{
    public static class ComRelease
    {
        public static void FinalReleaseComObjects(params object[] objects)
        {
            foreach(object o in objects)
            {
                try
                {
                    if (o == null)
                    {
                        continue;
                    }
                    if(Marshal.IsComObject(o) == false)
                    {
                        continue;
                    }
                    Marshal.FinalReleaseComObject(o);
                }
                catch(Exception)
                {

                }
            }
        }
    }
}
```
```c#:Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Diagnostics;

namespace Excel2PDF
{
    class Program
    {
        static void Main(string[] args)
        {
            //ディレクトリの指定
            const string Dir = @"C:\PDFTest";
            string OutDir = Path.Combine(Dir, "PDF");

            Console.WriteLine("----------ディレクトリ内のファイル名一覧取得----------");
            //ディレクトリ内のファイル名一覧を取得する。
            string[] files = System.IO.Directory.GetFiles(Dir, "*", System.IO.SearchOption.AllDirectories);
            List<String> filePathList = new List<String>();
            filePathList.AddRange(files);

            //出力先フォルダがない場合は作成
            if (!(Directory.Exists(Dir + "\\PDF"))) {
                Directory.CreateDirectory(Dir + "\\PDF");
            }

            foreach (string filePath in filePathList)
            {
                if (filePath.EndsWith(".xlsx"))
                {
                    string fileName = Path.GetFileName(filePath);
                    string fileNamePdf = fileName.Substring(0, fileName.IndexOf("."))+".pdf";
                    string fileTmp = Path.Combine(OutDir, fileNamePdf);
                ExcelSave.SaveAsPdf(Path.Combine(Dir, fileName), Path.Combine(OutDir ,fileNamePdf));
                }
            }
            //エクセルのプロセスが残っているか確認して、残っていたら終了する。
            var excels = Process.GetProcessesByName("EXCEL");
            foreach(var x in excels)
            {
                x.Kill();
            }
            
            
        }
    }
}
```
```c#:ExcelSave.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Office.Interop.Excel;

namespace Excel2PDF
{
    public static class ExcelSave
    {public static void SaveAsPdf(string excelFilePathName, string saveAsPathName)
        {
            Application application = null;
            Workbooks workbooks = null;
            Workbook workbook = null;
            try
            {
                //Applicationクラスのインスタンス作成
                application = new Application();

                workbooks = application.Workbooks;

                //Excelファイルを開く
                Console.WriteLine("----------Excelファイル展開開始----------");
                Console.WriteLine("ファイルパス：" + excelFilePathName);
                workbook = workbooks.Open(
                    excelFilePathName, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing
                    , Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
                Console.WriteLine("----------Excelファイル展開完了----------");
                Console.WriteLine("----------PDF出力開始----------");
                //Excelのシート全てをPDFとして出力
                if (!(System.IO.File.Exists(saveAsPathName)))
                {

                    Console.WriteLine("ファイルパス：" + saveAsPathName);
                    workbook.ExportAsFixedFormat(XlFixedFormatType.xlTypePDF,
                        saveAsPathName,
                        XlFixedFormatQuality.xlQualityStandard,
                        true,
                        false,
                        Type.Missing,
                        Type.Missing,
                        false,
                        Type.Missing);

                }
                else
                {
                    Console.WriteLine("すでに存在するファイルなので出力を中止します。");
                }
                Console.WriteLine("----------PDF出力終了----------");
            }
            catch
            {
                var excels = Process.GetProcessesByName("EXCEL");
                foreach (var x in excels)
                {
                    x.Kill();
                }

            }
            finally
            {
                if (workbook != null)
                {
                    try
                    {
                        //workbookをClose
                        workbook.Close(true, Type.Missing, Type.Missing);
                    }
                    catch
                    {

                    }
                }
                if (application != null)
                {
                    try
                    {
                        //applicationをClose
                        application.Quit();
                    }
                    catch
                    {

                    }
                }
                Excel2PDF.ComRelease.FinalReleaseComObjects(workbook, workbooks, application);
            }
        }
    }
}

```

###３．感想とか
C#初めて触りましたが、結構Microsoftが出してる製品との相性はいいのかなって感じでした。(当たり前ですが…笑)
あと、最後にコード自分で書いたのは10月だったんですが、思ってる以上に命名規則のひどさとかクラスの構成とかめちゃくちゃだな…と思ってしまいました。
コード書かなくなると衰えるというかなんというかって感じだったので今後はもっと定期的にコード書いていきたいなと思います。