Architect's Log

I'm a Cloud Architect. I'm highly motivated to reduce toils with driving DevOps.

C#でExcelファイルをPDFに変換する

C#でExcelファイルをPDFに変換するサンプルです。

検証環境

Visual Studio 2010 SP1、.NET Framework 4、Excel 2007、Office 2007 SP2

プロジェクトの作成

プロジェクトテンプレートはコンソールアプリケーションを選択します。

参照の追加

以下のスクリーンショットは「Productivity Power Tools」の「Searchable Add Reference Dialog」機能を使用したものになっています。
Productivity Power Tools 拡張機能
不正使用をマイクロソフトに報告する その他の Microsoft - Visual Studio Platform Team Microsoft Visual Studio フィードバック ツール (21)   Microsoft Visual Studio 2013 フィードバック ツール (2) Productivity Power Tools 無料 A set of extensions to Visual Studio Professional (and above) which improves developer productivity.

右クリックでコンテキストメニューを表示します。

[COM] - [Microsoft Excel 12.0 Object Library]を選択し、[Add]をクリックします。

チェックマークの表示を確認したら[Close]をクリックします。

参照が追加されたことを確認します。

ソースコード

Program.cs
using System.IO;

namespace ExcelToPdf {
    class Program {
        static void Main(string[] args) {
            const string Dir = @"D:\Sandbox\Console\ExcelToPdf";
            ExcelSave.SaveAsPdf(Path.Combine(Dir, "TS0100738771.xlsx"), Path.Combine(Dir, "TS0100738771.pdf"));
        }
    }
}
ExcelSave.cs
using System;
using Microsoft.Office.Interop.Excel;

namespace ExcelToPdf {
    /// <summary>
    /// Excelファイルを保存する機能を提供します。
    /// </summary>
    public static class ExcelSave {
        /// <summary>
        /// ExcelファイルをPDFとして保存します。
        /// </summary>
        /// <param name="excelFilePathName">Excelファイルのパス付きファイル名。</param>
        /// <param name="saveAsPathName">保存するPDFのパス付きファイル名。</param>
        /// <remarks>
        /// <para>
        /// Excel 2007がインストールされている必要があります。
        /// </para>
        /// <para>
        /// Office 2007のSP2、またはPDF保存アドインがインストールされている必要があります。</ br>
        /// http://support.microsoft.com/kb/953195/ja</ br>
        /// http://www.microsoft.com/downloads/ja-jp/details.aspx?FamilyId=F1FC413C-6D89-4F15-991B-63B07BA5F2E5&displaylang=ja
        /// </para>
        /// </remarks>
        public static void SaveAsPdf(string excelFilePathName, string saveAsPathName) {
            Application application = null;
            Workbooks workbooks = null;
            Workbook workbook = null;

            try {
                application = new Application();

                /*
                 * application.Workbooks.Open(...は、Workbooksオブジェクトの解放処理ができないので不可。
                 * 必ず変数経由でComRelease.FinalReleaseComObjectsを呼び出すこと。
                 */
                workbooks = application.Workbooks;

                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);

                // http://msdn.microsoft.com/ja-jp/library/microsoft.office.tools.excel.workbook.exportasfixedformat(v=vs.90).aspx
                workbook.ExportAsFixedFormat(
                    XlFixedFormatType.xlTypePDF,
                    saveAsPathName,
                    XlFixedFormatQuality.xlQualityStandard,
                    true,
                    true,
                    Type.Missing,
                    Type.Missing,
                    false,
                    Type.Missing);
            } finally {
                if (workbook != null) {
                    try {
                        workbook.Close(true, Type.Missing, Type.Missing);
                    } catch {
                    }
                }

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

                Com.ComRelease.FinalReleaseComObjects(workbook, workbooks, application);
            }
        }
    }
}
ComRelease.cs
using System;
using System.Runtime.InteropServices;

namespace Com {
    /// <summary>
    /// COMオブジェクトを解放する機能を提供します。
    /// </summary>
    public static class ComRelease {
        /// <summary>
        /// 複数のCOMオブジェクトの参照カウントを0までデクリメントし、解放します。
        /// </summary>
        /// <param name="objects">解放するCOMオブジェクトの配列。</param>
        /// <remarks>解放は配列の要素順に行います。</remarks>
        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) {
                }
            }
        }
    }
}

変換前Excelファイル

変換後PDFファイル


ご注意

デスクトップアプリケーション以外でのOfiiceオートメーションは推奨されていません。
Office のサーバーサイド オートメーションについて
開発者は、Microsoft Office のオートメーションを使用して、Office 製品に組み込まれている機能を使用したカスタム ソリューションを構築できます。このようなプログラムの開発は、クライアント システム上では比較的簡単ですが、Microsoft Active Server Pages (ASP)、ASP.NET、DCOM、Windows NT サービスなど、サーバーサイドのコードからオートメーションを実行する場合はさまざまな課題が生じる可能性があります。 ...

マイクロソフトは、現在のところ、無人の非対話型クライアント アプリケーションまたはコンポーネント (ASP、ASP.NET、DCOM、および NT サービスを含む) からの Microsoft Office アプリケーションのオートメーションに関して、推奨もサポートも行っていません。それは、このような環境で Office を実行した場合、Office で不安定な動作やデッドロックが発生する可能性があるためです。