問題なければ「実行時バインド」に移してみます。

「紙」への印刷はもちろん、最初から「Excel出力」を実装させることは多いと思います。
「参照設定」のままではいけないのでしょうか?   この章では「参照設定」で動作確認をしてから「実行時バインド」に移行させるように説明しています。
では「参照設定」にままで実行環境にリリースしてはいけないのでしょうか。
「実行時バインド」の場合は、参照オブジェクトが「Excelなのか」は実行して初めてプログラム側で認識されるので プロパティやメソッドの構文も実行するまでチェックされません。 つまり、誤字があってもコンパイルエラーにならないのです。
このため、事前に「参照設定」で動作確認をしてから「実行時バインド」に移すように説明しているのです。

「実行時バインド」に移行させるという要件は、Microsoft Excelの実行側とのバージョン互換の問題をを意識したことによります。
「参照設定」の場合は、前ページ4番目の画像のように参照名にバージョンがつきまといます。 「実行時バインド」の方がこれによる問題は回避できるだろうというのが現在の考え方です。

このコラムは20174月に書き直していますが、この時点ではOffice2003はすでに全サポートが終了しており、 Office2007201710月に全サポートが終了します。
サポート切れのバージョンは即座に使えなくなるわけではありませんが、セキュリティ更新が行なわれなくなるために危険度が上がってしまうことから、 ほとんどの企業では使用禁止となることがほとんどだと思います。

Office2007が利用率が低かったことも含めると、この段階でもほとんどがOffice2010以降だということになり、 バージョン互換のために「実行時バインド」に移行しなければならないという要件はほとんどないだろうという現在の私の見識でした。
ですが、Office2013(Microsoft Excel 15.0 Object Library)環境の参照設定で作成したものを、 Office2010(Microsoft Excel 14.0 Object Library)環境で実行させると、 Excelに関する記述の先頭で例外処理(Try ~ Catch)にも進まずに異常終了してしまうようなので、やはり必要なことのようです。
(下位Ver側で作成)は可能かも知れませんが、当方では確認できていません。
特段にバージョンに依存した記述がある場合は「実行時バインド」にしたとしても記述に対応したバージョンでないと動作しないので、これはここでの話からは「論外」です。

このページでは、前ページと全く同じ動作になるように「実行時バインド」に変更した状態を紹介します。変更点の説明のみになります。

まずは実行状態の紹介です。

Excel出力付きの一覧表示
(画像をクリックすると、このサンプルがダウンロードできます)

このように見た目も操作も前ページと変わりません。違うのはタイトルの「④」が「⑤」になったくらいです。
Excel出力」メニューをクリックした時のメッセージも、

Excel出力付きの一覧表示

このように全く変わりません。
Excelに出力した状態も

Excel出力付きの一覧表示

これはテンプレートが同じものなので当たり前ですが、何も変わりません。

「実行時バインド」ですからExcelの「参照設定」は外します。

Excel出力付きの一覧表示

前ページにあった「Microsoft Excel 1x.0 Object Library」の参照がない状態で用います。 今回は前ページのプロジェクトのコピー転用なのでこの参照を削除して用いています。

正しく動作するように作成されたプログラムでは動作に失敗がない限り何も違いはありません。 但し、例外が発生する時はそのエラーメッセージに若干の違いがあり、非補足例外でも発生元の記述に「Excel」があったりするので 「参照設定」の方が、そのエラー表示を見てエンドユーザーが対処しやすいのかも知れません。

「参照設定」から「実行時バインド」にあえて移すのは、「参照設定」にExcelのバージョンが表意していることから来る危惧による対応です。 社内で利用するExcelのバージョンについて先に作成している「参照設定版」で動作確認ができているならこのページの作業は必要ありません。

では、変更があったモジュールのソースコードを紹介します。
実は一覧画面についてもIDが「frmGetMdbDataTest04」から「frmGetMdbDataTest05」に変わっており、 全く同一ではないのですが、これは「タイトル」と「Excel出力」メニューの呼び出しフォームIDを換えているだけなので紹介は割愛します。

ソースコードとして変更があるのは「Excel出力フォーム(dlgOutputExcel2.vb)」と「Excel関連クラス(clsAboutExcel2.vb)」のみです。 一旦、「参照設定」で作成して動作確認を終えているので「実行時バインド」への移行はある程度決まった変更点を変更するという作業なのですが、 最初から「実行時バインド」で作成しようとするのは結構ベテランの領域を要求されます。

では、「Excel出力フォーム(dlgOutputExcel2.vb)」のコードです。

'***************************************************************************************************
'   配属一覧サンプル(Excel出力②:実行時バインド版)             dlgOutputExcel2(Form)
'
'   作成者:井上治  URL:https://www.ne.jp/asahi/excel/inoue/ [Excelでお仕事!]
'***************************************************************************************************
' 変更日付 Rev     変更履歴内容-------------------------------------------------------------------->
' 17/02/26(1.0.4.0)新規作成
' 17/03/01(1.0.4.0)作成途中⇒処理例外等を1箇所で処置するように対応中
' 17/04/02(1.0.5.0)Excelのインスタンス(新規・既存)指定機能を追加、拡張メッセージボックスの対応
' 17/04/06(1.0.5.0)実行時バインド版として再作成
'***************************************************************************************************
Imports System.IO
Friend Class dlgOutputExcel2
    '===============================================================================================
    Private Const g_cnsTitle As String = "配属一覧サンプル(Excel出力②)"
    Private Const g_cnsTemplate As String = "ExcelSample1.xltx"
    Private Const g_cnsTempPath As String = "..\..\ExcelTemplate"
    Private Const g_cnsColMax As Integer = 5
    '-----------------------------------------------------------------------------------------------
    ' 共通クラス
    Private g_objAboutMDB As clsAboutMDB3                           ' データベースI/Oクラス(MDB用)
    '-----------------------------------------------------------------------------------------------
    ' フォーム間受け渡し変数
    Private g_strSQL As String = String.Empty                       ' 抽出SQL文
    Private g_blnNewInstance As Boolean = False                     ' 新規インスタンス指定

    '***********************************************************************************************
    ' ■■■ フォームイベント ■■■
    '***********************************************************************************************
    '* 処理名 :Form_Load
    '* 機能  :フォーム初期化(Load)
    '-----------------------------------------------------------------------------------------------
    '* 返り値 :(なし)
    '* 引数  :(デフォルト)
    '-----------------------------------------------------------------------------------------------
    '* 作成日 :2017年02月26日
    '* 作成者 :井上 治
    '* 更新日 :2017年02月26日
    '* 更新者 :井上 治
    '* 機能説明:
    '* 注意事項:
    '***********************************************************************************************
    Private Sub Form_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        '-------------------------------------------------------------------------------------------
        ' データベースI/Oクラスの初期化
        g_objAboutMDB = New clsAboutMDB3(Me, g_cnsMdbFileame, g_cnsMdbSubFolder)
    End Sub

    '***********************************************************************************************
    '* 処理名 :Form_Shown
    '* 機能  :フォーム表示完了(Shown)
    '-----------------------------------------------------------------------------------------------
    '* 返り値 :(なし)
    '* 引数  :(デフォルト)
    '-----------------------------------------------------------------------------------------------
    '* 作成日 :2017年02月26日
    '* 作成者 :井上 治
    '* 更新日 :2017年04月06日
    '* 更新者 :井上 治
    '* 機能説明:
    '* 注意事項:
    '***********************************************************************************************
    Private Sub Form_Shown(ByVal sender As Object, _
                           ByVal e As System.EventArgs) Handles Me.Shown
        '-------------------------------------------------------------------------------------------
        Application.DoEvents()
        '-------------------------------------------------------------------------------------------
        Dim objWbk As Object = Nothing                          ' Excel.Workbook
        ' Excel出力クラスの初期化(Escキーのイベントはクラス側に実装済)
        Using clsExcel = New clsAboutExcel2(Me, True)
            '---------------------------------------------------------------------------------------
            Dim strMSGHeader As String = String.Empty               ' メッセージヘッダ
            Try
                '-------------------------------------------
                ' Excel出力(処理本体)
                Call GP_MakeExcelSheet(clsExcel, objWbk, strMSGHeader)

            Catch ex As Exception
                '-------------------------------------------
                ' 処理中例外メッセージの表示
                Call clsExcel.ShowFatalMessage(g_cnsTitle, strMSGHeader, ex.Message)
                ' 例外時後始末(但しExcel応答無しなどではここでの対応は働かない!)
                Call clsExcel.SuspendExcelProc(objWbk)
            End Try
            '---------------------------------------------------------------------------------------
        End Using
        '-------------------------------------------------------------------------------------------
        ' 閉じる
        Me.Close()
    End Sub

    '***********************************************************************************************
    ' ■■■ サブ処理 ■■■
    '***********************************************************************************************
    '* 処理名 :GP_MakeExcelSheet
    '* 機能  :Excel出力(処理本体)
    '-----------------------------------------------------------------------------------------------
    '* 返り値 :(なし)
    '* 引数  :Arg1 = Excel出力クラス(Object)
    '*      Arg2 = Excel.Workbook(Object)
    '*      Arg3 = 例外時メッセージヘッダ(String)          ※Ref参照
    '-----------------------------------------------------------------------------------------------
    '* 作成日 :2017年02月26日
    '* 作成者 :井上 治
    '* 更新日 :2017年04月06日
    '* 更新者 :井上 治
    '* 機能説明:
    '* 注意事項:本処理中の例外は上位でトラップされる(この処理内ではトラップしない)
    '***********************************************************************************************
    Private Sub GP_MakeExcelSheet(ByRef clsExcel As clsAboutExcel2, _
                                  ByRef objWbk As Object, _
                                  ByRef strMSGHeader As String)
        '-------------------------------------------------------------------------------------------
        strMSGHeader = "データ抽出中"
        ' 配属情報の抽出
        Dim dbTbl As DataTable = Nothing                            ' DataTable
        ' DataTable取得
        If Not g_objAboutMDB.GetDataTableOle(dbTbl, g_strSQL, g_cnsMST_HAIZOKU) Then Exit Sub
        '-------------------------------------------------------------------------------------------
        Dim intCntRec As Integer = 0                                ' レコードカウンタ
        Dim intIx As Integer = 0                                    ' テーブルINDEX
        Dim intIxMax As Integer = dbTbl.Rows.Count - 1              ' テーブルINDEX上限
        Dim tblRec(intIxMax, g_cnsColMax) As Object                 ' 2次元配列テーブル
        PRB_SYORICHU.Maximum = intIxMax + 1
        ' 全レコードを巡回
        Do While intIx <= intIxMax
            intCntRec += 1
            ' プログレスバーの処置
            Call GP_SetProgressBarValue(PRB_SYORICHU, intCntRec)
            ' 2次元配列テーブルに配置
            For intIx2 As Integer = 0 To g_cnsColMax
                tblRec(intIx, intIx2) = dbTbl.Rows(intIx)(intIx2)
            Next intIx2
            ' 次へ
            intIx += 1
        Loop
        ' データテーブルをクリア
        dbTbl.Clear()
        dbTbl.Reset()
        '-------------------------------------------------------------------------------------------
        strMSGHeader = "Excel起動中"
        Dim strFilename As String                                   ' ファイル名
        ' フルパステンプレート名(実行EXEの2階層上のExcelTemplateフォルダになっています)
        Dim objUri1 As New Uri(My.Application.Info.DirectoryPath)
        Dim objUri2 As New Uri(objUri1, g_cnsTempPath)
        strFilename = Path.Combine(objUri2.LocalPath, g_cnsTemplate)
        ' テンプレートOPEN
        If Not clsExcel.GetWorkbook(strFilename, _
                                    objWbk, _
                                    strMSGHeader, _
                                    g_blnNewInstance) Then Exit Sub
        '-------------------------------------------------------------------------------------------
        strMSGHeader = "Excel出力中"
        ' ワークシートに貼り付け(矩形貼り付け)
        With objWbk.Worksheets(1)
            Dim intRow As Integer = intIxMax + 2                    ' 行INDEX
            Dim intCol As Integer = g_cnsColMax + 1                 ' カラムINDEX
            .Range(.Cells(2, 1), .Cells(intRow, intCol)).Value = tblRec
        End With
        '-------------------------------------------------------------------------------------------
        strMSGHeader = "終了処理"
        ' 終了(Excelを表示)
        Call clsExcel.SuspendExcelProc(objWbk, True)
    End Sub

    '***********************************************************************************************
    ' ■■■ 受け渡しプロパティ ■■■
    '***********************************************************************************************
    ' 抽出SQL文(String)
    '-----------------------------------------------------------------------------------------------
    Friend WriteOnly Property prpSQL() As String
        Set(ByVal value As String)
            g_strSQL = value
        End Set
    End Property

    '===============================================================================================
    ' 新規インスタンス指定(Boolean)
    '-----------------------------------------------------------------------------------------------
    Friend WriteOnly Property prpNewInstance() As Boolean
        Set(ByVal value As Boolean)
            g_blnNewInstance = value
        End Set
    End Property

    '----------------------------------------<< End of Source >>------------------------------------
End Class
まず「Microsoft.Office.Interop」のインポートがなくなります。
またExcel関連のオブジェクトのデータ型は単にAs Objectに変更することになります。
これによるプロパティ等の自動メンバ表示がなくなることも直接「実行時バインド」を開発する場合の難しさの一因になっています。
一旦「参照設定」で作成して動作確認を終えていれば、この程度の変更箇所だけで「実行時バインド」として動作できると思います。

次は「Excel関連クラス(clsAboutExcel2.vb)」です。

'***************************************************************************************************
'   サンプル用Excel関連定数                                  modAboutExcel2(Module)
'
'   作成者:井上治  URL:https://www.ne.jp/asahi/excel/inoue/ [Excelでお仕事!]
'***************************************************************************************************
'   [参照追加]・Microsoft Excel 1x.0 Object Library
'   ※この下に「Excel関連クラス(clsAboutExcel1)」があります
'***************************************************************************************************
' 変更日付 Rev     変更履歴内容-------------------------------------------------------------------->
' 17/02/26(1.0.0.0)新規作成
' 17/04/02(1.0.0.0)Excelの既存インスタンス指定機能の追加対応
' 17/04/06(1.0.0.0)実行時バインド版として再作成
' 17/04/22(1.0.2.0)不要インポートの削除(System.Net、System.Runtime.InteropServices.ComTypes)
'***************************************************************************************************
Imports System.IO
Imports System.Runtime.InteropServices
Imports Microsoft.Win32.SafeHandles
Module modAboutExcel2
    '===============================================================================================
    ' Excel処理関連定数
    Friend Const g_cnsExcelApplication As String = "Excel.Application"
    Friend Const xlCalculationAutomatic As Int16 = -4105
    Friend Const xlCalculationManual As Int16 = -4135
    Friend Const xlSheetVisible As Int16 = -1
    Friend Const xlSheetHidden As Int16 = 0
    Friend Const xlSheetVeryHidden As Int16 = 2
    Friend Const xlMaximized As Int16 = -4137
    Friend Const xlMinimized As Int16 = -4140
    Friend Const xlNormal As Int16 = -4143
    '-----------------------------------------------------------------------------------------------
    ' 保存ファイル形式定数
    Friend Const xlExcel8 As Int16 = 56                         ' 旧xls形式
    Friend Const xlTemplate8 As Int16 = 17                      ' 旧xlt形式
    Friend Const xlOpenXMLWorkbook As Int16 = 51                ' xlsx形式
    Friend Const xlOpenXMLWorkbookMacroEnabled As Int16 = 52    ' xlsm形式
    Friend Const xlOpenXMLTemplate As Int16 = 54                ' xltx形式
    Friend Const xlOpenXMLTemplateMacroEnabled As Int16 = 53    ' xltm型式
    Friend Const xlAddIn8 As Int16 = 18                         ' xla型式
    Friend Const xlOpenXMLAddIn As Int16 = 55                   ' xlam型式
    '-----------------------------------------------------------------------------------------------
    ' セル収容可能文字数(矩形転記時上限)
    Friend Const g_cnsCellStringLengthMax As Integer = 911
    '-----------------------------------------------------------------------------------------------
    ' 拡張メッセージボックス用ガイド(Excel処理専用:参照系用)
    Friend ReadOnly g_tblExcelButtonText() As String = {"新規にExcelを起動して出力", _
                                                        "開いているExcelに出力", _
                                                        "キャンセル"}
    Friend ReadOnly g_cnsExcelMessageGuide As String = _
        "新規にExcelを起動して出力するか、開いている(実行中)Excelに出力するかの指定です。" & ControlChars.CrLf & _
        "「開いているExcelに出力」を選択してもExcelが起動していない場合は新規に起動して出力されます。" & ControlChars.CrLf & _
        "※特に指定がない場合は「新規にExcelを起動して出力」を選択して下さい。" & ControlChars.CrLf & _
        "※出力処理中はExcelを操作しないで下さい。"
    '-----------------------------------------------------------------------------------------------
    ' メッセージボックスコントロール(OwnerParent版)
    Friend MessageBox2 As New clsMessageBox2Ex

    '---------------------------------------<< End of Source >>-------------------------------------
End Module

'***************************************************************************************************
'   サンプル用Excel関連クラス(実行時バインド版)               clsAboutExcel2(Class)
'
'   作成者:井上治  URL:https://www.ne.jp/asahi/excel/inoue/ [Excelでお仕事!]
'***************************************************************************************************
' 変更日付 Rev     変更履歴内容-------------------------------------------------------------------->
' 17/02/26(1.0.0.0)新規作成
' 17/04/02(1.0.0.0)Excelの既存インスタンス指定機能の追加対応
' 17/04/06(1.0.0.0)実行時バインド版として再作成
' 17/04/11(1.0.0.0)ブックOPEN時のイベント制御の不備を修正
'***************************************************************************************************
Friend Class clsAboutExcel2
    Implements IDisposable
    '===============================================================================================
    ' テンプレート形式拡張子
    Private Const g_cnsXLT As String = ".XLT"                   ' 97-2003形式テンプレート
    Private Const g_cnsXLTM As String = ".XLTM"                 ' 2007形式テンプレート(マクロ有効)
    Private Const g_cnsXLTX As String = ".XLTX"                 ' 2007形式テンプレート(マクロ無効)
    '-----------------------------------------------------------------------------------------------
    ' Field to handle multiple calls to Dispose gracefully.
    Private g_blnDisposed As Boolean = False                    ' 破棄判定
    ' SafeHandleインスタンス
    Private handle As SafeHandle = New SafeFileHandle(IntPtr.Zero, True) ' SafeHandleインスタンス
    '-----------------------------------------------------------------------------------------------
    ' Excel関連オブジェクト
    Private g_objExcel As Object = Nothing                      ' Excel.Application
    Private g_objWorkbooks As Object = Nothing                  ' Excel.Workbooks
    '-----------------------------------------------------------------------------------------------
    ' MessageBoxのOwnerWindow指定のための現在フォーム
    Private g_objOwnerForm As Object = Nothing                  ' Ownerフォーム
    ' 各スイッチ
    Private g_swNewInstance As Boolean = False                  ' 新規インスタンス
    Private g_swPrintCancel As Boolean = False                  ' 処理中断スイッチ
    Private g_swExcelDuringProc As Boolean = False              ' 出力処理中スイッチ
    Private g_blnUseKeyDown As Boolean = False                  ' KeyDownイベント使用
    ' ブックOPEN時のイベント状態(イベント停止する場合はFP_GetWorkbookを呼ぶ前にFalseにする)
    Private g_swExcelEnableEvents As Boolean = True             ' [初期値]True

    '***********************************************************************************************
    ' ■■■ クラス初期化メソッド ■■■
    '***********************************************************************************************
    '* 処理名 :New
    '* 機能  :初期化
    '-----------------------------------------------------------------------------------------------
    '* 返り値 :(なし)
    '* 引数  :Arg1 = Ownerフォーム(Object)
    '*      Arg2 = KeyDownイベント使用(Boolean)        ※Option
    '-----------------------------------------------------------------------------------------------
    '* 作成日 :2017年02月26日
    '* 作成者 :井上 治
    '* 更新日 :2017年02月26日
    '* 更新者 :井上 治
    '* 機能説明:
    '* 注意事項:KeyDownイベント使用の時はフォームデザイナでKeyPreviewをTrueにして下さい
    '***********************************************************************************************
    Friend Sub New(ByRef objOwner As Object, _
                   Optional ByVal blnUseKeyDown As Boolean = False)
        '-------------------------------------------------------------------------------------------
        g_objOwnerForm = objOwner                               ' Ownerフォーム
        g_blnUseKeyDown = blnUseKeyDown                         ' KeyDownイベント使用
        g_swNewInstance = False
        g_swExcelEnableEvents = True
        g_swPrintCancel = False
        'g_strFatalErrMSG = String.Empty
        ' KeyDownイベント使用
        If g_blnUseKeyDown Then
            ' KeyDownイベントハンドラ追加
            AddHandler CType(objOwner, Form).KeyDown, AddressOf Form_KeyDown
        End If
    End Sub

    '***********************************************************************************************
    '   ■■■ 破棄 ■■■
    '***********************************************************************************************
    '* 処理名 :Dispose、Finalize
    '* 機能  :クラス破棄
    '-----------------------------------------------------------------------------------------------
    '* 返り値 :(なし)
    '* 引数  :(なし)
    '-----------------------------------------------------------------------------------------------
    '* 作成日 :2017年02月26日
    '* 作成者 :井上 治
    '* 更新日 :2017年02月26日
    '* 更新者 :井上 治
    '* 機能説明:
    '* 注意事項:
    '***********************************************************************************************
    Friend Overloads Sub Dispose() Implements IDisposable.Dispose
        '-------------------------------------------------------------------------------------------
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub

    Protected Friend Overloads Sub Dispose(ByVal blnDisposing As Boolean)
        '-------------------------------------------------------------------------------------------
        ' 既に破棄されていないか
        If Not g_blnDisposed Then
            ' Dispose呼び出しか
            If blnDisposing Then
                handle.Dispose()
                g_blnDisposed = True
            End If
            If g_blnUseKeyDown Then
                ' KeyDownイベントハンドラ開放
                RemoveHandler CType(g_objOwnerForm, Form).KeyDown, AddressOf Form_KeyDown
            End If
            ' 確保しているExcel関連全てオブジェクトの解放
            Call GP_ReleaseAllExObject()
            ' 参照破棄
            g_objOwnerForm = Nothing
        End If
    End Sub

    '***********************************************************************************************
    ' ■■■ フォームイベント ■■■
    '***********************************************************************************************
    '* 処理名 :Form_KeyDown
    '* 機能  :キー押下イベント(Form_KeyDown)
    '-----------------------------------------------------------------------------------------------
    '* 返り値 :(なし)
    '* 引数  :(デフォルト)
    '-----------------------------------------------------------------------------------------------
    '* 作成日 :2017年02月26日
    '* 作成者 :井上 治
    '* 更新日 :2017年02月26日
    '* 更新者 :井上 治
    '* 機能説明:
    '* 注意事項:
    '***********************************************************************************************
    Friend Sub Form_KeyDown(ByVal sender As Object, _
                            ByVal e As System.Windows.Forms.KeyEventArgs)
        '-------------------------------------------------------------------------------------------
        ' Escキーは中断指示とみなす
        If ((e.KeyCode = Keys.Escape) AndAlso (Not e.Shift)) Then
            ' 処理中断スイッチをセット
            g_swPrintCancel = True
        End If
    End Sub

    '***********************************************************************************************
    ' ■■■ 公開メソッド ■■■
    '***********************************************************************************************
    '* 処理名 :GetWorkbook
    '* 機能  :Excelのインスタンスを生成してワークブックを開く
    '-----------------------------------------------------------------------------------------------
    '* 返り値 :処理正否(Boolean)
    '* 引数  :Arg1 = ワークブックファイル名(String)          ※フルパスで指定
    '*      Arg2 = Excel.Workbook(Object)                  ※Ref参照
    '*      Arg3 = 例外時メッセージヘッダ(String)          ※Ref参照
    '*      Arg4 = 新規インスタンス指定(Boolean)
    '*      Arg5 = 引数UpdateLinks(Int16)                  ※Option:Workbook時の引数
    '*      Arg6 = 引数ReadOnly(Boolean)                   ※Option:Workbook時の引数
    '-----------------------------------------------------------------------------------------------
    '* 作成日 :2017年02月26日
    '* 作成者 :井上 治
    '* 更新日 :2017年04月06日
    '* 更新者 :井上 治
    '* 機能説明:
    '* 注意事項:ファイル名ブランク時は新規ブックを返す
    '***********************************************************************************************
    Friend Function GetWorkbook(ByVal strFileName As String, _
                                ByRef objWBK As Object, _
                                ByRef strMSGHeader As String, _
                                ByVal blnNewInstance As Boolean, _
                                Optional ByVal intUpdateLinks As Int16 = 0, _
                                Optional ByVal blnReadOnly As Boolean = True) As Boolean
        '-------------------------------------------------------------------------------------------
        Dim blnTemplate As Boolean = False                      ' テンプレート判定
        Dim strBooknameU As String = String.Empty               ' ブック名(大文字変換)
        Dim strMSG As String = String.Empty                     ' メッセージ
        g_swNewInstance = False
        GetWorkbook = False
        objWBK = Nothing
        '-------------------------------------------------------------------------------------------
        ' ファイル名の指定があるか
        If strFileName.Length <> 0 Then
            ' ファイル存在確認
            If Not FP_CheckExistsFile(strFileName, _
                                      blnTemplate, _
                                      strBooknameU, _
                                      strMSGHeader) Then Return False
        End If
        '-------------------------------------------------------------------------------------------
        ' Excel.Applicationのインスタンス取得(又は生成)
        strMSGHeader = "Excel.Applicationのインストール確認"
        Dim typType As Type = Nothing                           ' Type
        Try
            typType = Type.GetTypeFromProgID(g_cnsExcelApplication)
            ' 取得不可
            If typType Is Nothing Then
                strMSG = strMSGHeader & ControlChars.CrLf
                strMSG &= "Excelがインストールされていません。"
                ' エラーを表示
                MessageBox2.DialogShow(g_objOwnerForm, _
                                       strMSG, _
                                       g_objOwnerForm.Text, _
                                       MessageBoxButtons.OK, _
                                       MessageBoxIcon.Error)
                Return False
            End If
        Catch ex As Exception
            strMSG = strMSGHeader & ControlChars.CrLf
            strMSG &= ex.Message
            ' エラーを表示
            MessageBox2.DialogShow(g_objOwnerForm, _
                                   strMSG, _
                                   g_objOwnerForm.Text, _
                                   MessageBoxButtons.OK, _
                                   MessageBoxIcon.Error)
            Return False
        End Try
        '-------------------------------------------------------------------------------------------
        ' Excel.Applicationのインスタンス生成
        strMSGHeader = "Excel.Applicationのインスタンス生成"
        ' 新規インスタンス指定か
        If blnNewInstance Then
            ' Excelの新規インスタンスを生成
            g_objExcel = Activator.CreateInstance(typType)
        Else
            ' Excelが実行中の場合は実行中のインスタンスを取得
            ' ここで'System.Exception'の初回例外が発生しますがTry捕捉内なので無視します
            Try
                ' Excelが実行中の場合は実行中のインスタンスを取得
                ' ここで'System.Exception'の初回例外が発生しますがTry捕捉内なので無視します
                g_objExcel = GetObject(, g_cnsExcelApplication)
            Catch ex As Exception
                ' Excelが実行中でない(又は取得失敗)場合は新規にインスタンスを生成
                g_objExcel = Activator.CreateInstance(typType)
            End Try
        End If
        '-------------------------------------------------------------------------------------------
        ' Excel.Workbooksの取得
        strMSGHeader = "Excel.Workbooksの取得"
        g_objWorkbooks = g_objExcel.Workbooks
        '-------------------------------------------------------------------------------------------
        ' ワークブックの指定がない場合は新規ブックを返す
        If strFileName.Length = 0 Then
            ' 新規ワークブックを開く
            Return FP_OpenNewWorkbook(objWBK, strMSGHeader)
        Else
            ' 既存のワークブックを開く
            Return FP_OpenExiWorkbook(strFileName, _
                                      blnTemplate, _
                                      strBooknameU, _
                                      intUpdateLinks, _
                                      blnReadOnly, _
                                      objWBK, _
                                      strMSGHeader)
        End If
    End Function

    '***********************************************************************************************
    '* 処理名 :SuspendExcelProc
    '* 機能  :Excel出力の終了
    '-----------------------------------------------------------------------------------------------
    '* 返り値 :(なし)
    '* 引数  :Arg1 = Excel.Workbook(Object)           ※Option
    '*      Arg2 = 終了回避スイッチ(Boolean)        ※Option:True=Excel終了しない
    '*      Arg3 = 保存済回避スイッチ(Boolean)      ※Option:True=保存済にしない
    '*      Arg4 = COMオブジェクト解放スイッチ(Boolean) ※Option:True=解放する
    '-----------------------------------------------------------------------------------------------
    '* 作成日 :2017年03月01日
    '* 作成者 :井上 治
    '* 更新日 :2017年04月06日
    '* 更新者 :井上 治
    '* 機能説明:WorkbookのCloseやExcelの終了を含む(Excelを表示させて終了も可)
    '* 注意事項:この処理中での例外は無視される
    '***********************************************************************************************
    Friend Sub SuspendExcelProc(Optional ByRef objWbk As Object = Nothing, _
                                Optional ByVal blnOmitQuit As Boolean = False, _
                                Optional ByVal blnOmitSaved As Boolean = False, _
                                Optional ByVal blnReleaseComObject As Boolean = True)
        '-------------------------------------------------------------------------------------------
        ' 閉じない指定でなければブックを閉じる
        If objWbk IsNot Nothing AndAlso Not blnOmitQuit AndAlso blnReleaseComObject Then
            Try
                Call StartScreenUpdate()
                objWbk.Saved = True                     ' 展開ブックは保存済み属性とする
                objWbk.Close(False)
            Finally
                ' COMオブジェクト解放
                Call GP_ReleaseComObject(objWbk)
            End Try
        End If
        '-------------------------------------------------------------------------------------------
        ' Workbooks解放
        If g_objWorkbooks IsNot Nothing Then
            Try
                ' 別のワークブックが存在するか
                blnOmitQuit = g_objWorkbooks.Count <> 0
                ' COMオブジェクト解放
                Call GP_ReleaseComObject(g_objWorkbooks)
            Finally
                ' 無視
            End Try
        End If
        '-------------------------------------------------------------------------------------------
        Try
            ' Application解放
            If Not blnOmitQuit AndAlso blnReleaseComObject Then
                ' Excelの終了
                g_objExcel.Quit()
                Application.DoEvents()
            Else
                ' Excelの現状復帰(表示再開等)
                g_objExcel.Visible = True             ' Excelウィンドウを表示
                If g_objExcel.WindowState = xlMinimized Then
                    ' 最小化状態だったら通常に復帰
                    g_objExcel.WindowState = xlNormal
                End If
                Call StartScreenUpdate()
                If ((Not objWbk Is Nothing) AndAlso (Not blnOmitSaved)) Then
                    objWbk.Saved = True             ' 展開ブックは保存済み属性とする
                End If
            End If
        Finally
            ' COMオブジェクト解放
            If Not blnOmitQuit AndAlso blnReleaseComObject Then
                Call GP_ReleaseComObject(g_objExcel)
            End If
        End Try
    End Sub

    '***********************************************************************************************
    '* 処理名 :StopScreenUpdate
    '* 機能  :Excelの画面描画停止
    '-----------------------------------------------------------------------------------------------
    '* 返り値 :(なし)
    '* 引数  :(なし)
    '-----------------------------------------------------------------------------------------------
    '* 作成日 :2017年03月01日
    '* 作成者 :井上 治
    '* 更新日 :2017年03月01日
    '* 更新者 :井上 治
    '* 機能説明:
    '* 注意事項:
    '***********************************************************************************************
    Friend Sub StopScreenUpdate()
        '-------------------------------------------------------------------------------------------
        With g_objExcel
            .ScreenUpdating = False
            .Calculation = xlCalculationManual
            .EnableEvents = False
        End With
    End Sub

    '***********************************************************************************************
    '* 処理名 :StartScreenUpdate
    '* 機能  :Excelの画面描画再開
    '-----------------------------------------------------------------------------------------------
    '* 返り値 :(なし)
    '* 引数  :(なし)
    '-----------------------------------------------------------------------------------------------
    '* 作成日 :2017年03月01日
    '* 作成者 :井上 治
    '* 更新日 :2017年03月01日
    '* 更新者 :井上 治
    '* 機能説明:
    '* 注意事項:
    '***********************************************************************************************
    Friend Sub StartScreenUpdate()
        '-------------------------------------------------------------------------------------------
        With g_objExcel
            .Calculation = xlCalculationAutomatic
            .EnableEvents = True
            .ScreenUpdating = True
        End With
    End Sub

    '***********************************************************************************************
    '* 処理名 :ReleaseComObject
    '* 機能  :COMオブジェクトの解放
    '-----------------------------------------------------------------------------------------------
    '* 返り値 :(なし)
    '* 引数  :Arg1 = COMオブジェクト(Object)
    '-----------------------------------------------------------------------------------------------
    '* 作成日 :2017年02月26日
    '* 作成者 :井上 治
    '* 更新日 :2017年02月26日
    '* 更新者 :井上 治
    '* 機能説明:
    '* 注意事項:
    '***********************************************************************************************
    Friend Sub ReleaseComObject(ByRef objCOM As Object)
        '-------------------------------------------------------------------------------------------
        ' COMオブジェクトの解放(共通処理)
        Call GP_ReleaseComObject(objCOM)
    End Sub

    '***********************************************************************************************
    '* 処理名 :ShowFatalMessage
    '* 機能  :致命例外メッセージ編集
    '-----------------------------------------------------------------------------------------------
    '* 返り値 :(なし)
    '* 引数  :Arg1 = プログラムタイトル(String)
    '*      Arg2 = メッセージヘッダ(String)
    '*      Arg3 = 例外メッセージ(String)
    '-----------------------------------------------------------------------------------------------
    '* 作成日 :2017年03月02日
    '* 作成者 :井上 治
    '* 更新日 :2017年04月02日
    '* 更新者 :井上 治
    '* 機能説明:
    '* 注意事項:
    '***********************************************************************************************
    Friend Sub ShowFatalMessage(ByVal strTitle As String, _
                                ByVal strMSGHeader As String, _
                                ByVal strExMessage As String)
        '-------------------------------------------------------------------------------------------
        Dim strErrMSG As String = strMSGHeader                      ' メッセージ
        ' ヘッダ無し
        If strMSGHeader.Length = 0 Then
            strErrMSG = strExMessage
        Else
            strErrMSG &= "でエラーが発生しました。" & ControlChars.CrLf & strExMessage
            strErrMSG &= ControlChars.CrLf & ControlChars.CrLf
            strErrMSG &= "Excelプロセスが残存する場合があります。" & ControlChars.CrLf
            strErrMSG &= "不具合が解消しない場合はWindowsを再起動して下さい。"
        End If
        MessageBox2.DialogShow(g_objOwnerForm, _
                               strErrMSG, _
                               strTitle, _
                               MessageBoxButtons.OK, _
                               MessageBoxIcon.Error)
    End Sub

    '***********************************************************************************************
    ' ■■■ 共通サブ処理(Private) ■■■
    '***********************************************************************************************
    '* 処理名 :GP_ReleaseComObject
    '* 機能  :COMオブジェクトの解放
    '-----------------------------------------------------------------------------------------------
    '* 返り値 :(なし)
    '* 引数  :Arg1 = COMオブジェクト(Object)
    '-----------------------------------------------------------------------------------------------
    '* 作成日 :2017年02月26日
    '* 作成者 :井上 治
    '* 更新日 :2017年02月26日
    '* 更新者 :井上 治
    '* 機能説明:
    '* 注意事項:
    '***********************************************************************************************
    Private Sub GP_ReleaseComObject(ByRef objCOM As Object)
        '-------------------------------------------------------------------------------------------
        ' 明示的にCOMオブジェクトへの参照を解放する
        Try
            ' ランタイム呼び出し可能ラッパーの参照カウントをデクリメント
            If ((Not objCOM Is Nothing) AndAlso (Marshal.IsComObject(objCOM))) Then
                Marshal.FinalReleaseComObject(objCOM)
            End If
        Finally
            ' 参照を解除する
            objCOM = Nothing
        End Try
    End Sub

    '***********************************************************************************************
    '* 処理名 :GP_ReleaseAllExObject
    '* 機能  :確保しているExcel関連全てオブジェクトの解放
    '-----------------------------------------------------------------------------------------------
    '* 返り値 :(なし)
    '* 引数  :(なし)
    '-----------------------------------------------------------------------------------------------
    '* 作成日 :2017年02月26日
    '* 作成者 :井上 治
    '* 更新日 :2017年04月06日
    '* 更新者 :井上 治
    '* 機能説明:
    '* 注意事項:
    '***********************************************************************************************
    Private Sub GP_ReleaseAllExObject()
        '-------------------------------------------------------------------------------------------
        ' 新規インスタンスか
        If g_swNewInstance Then
            Try
                ' Excel.Workbooksが確保されている場合は全てのWorkbookを強制的に閉じる
                For Each objWbk As Object In g_objWorkbooks
                    ' 強制的に閉じる
                    objWbk.Saved = True
                    objWbk.Close(False)
                    ' Excel.Workbookの解放
                    Call GP_ReleaseComObject(objWbk)
                Next objWbk
            Catch ex As Exception
                ' 無視
            End Try
        End If
        ' Excel.Workbooksの解放
        Call GP_ReleaseComObject(g_objWorkbooks)
        ' Excel.Applicationの解放
        Call GP_ReleaseComObject(g_objExcel)
    End Sub

    '***********************************************************************************************
    '* 処理名 :FP_CheckExistsFile
    '* 機能  :ファイル存在確認
    '-----------------------------------------------------------------------------------------------
    '* 返り値 :チェック成否(Boolean)
    '* 引数  :Arg1 = 存在チェックするファイル名(String)   ※フルパスで指定
    '*      Arg2 = テンプレート判定(Boolean)            ※Ref参照
    '*      Arg3 = ブック名(大文字変換)(String)         ※Ref参照
    '*      Arg4 = 例外時メッセージヘッダ(String)       ※Ref参照
    '-----------------------------------------------------------------------------------------------
    '* 作成日 :2017年02月26日
    '* 作成者 :井上 治
    '* 更新日 :2017年04月02日
    '* 更新者 :井上 治
    '* 機能説明:
    '* 注意事項:URL上のファイルには対応しません、例外処理はありません
    '***********************************************************************************************
    Private Function FP_CheckExistsFile(ByVal strFilename As String, _
                                        ByRef blnTemplate As Boolean, _
                                        ByRef strBooknameU As String, _
                                        ByRef strMSGHeader As String) As Boolean
        '-------------------------------------------------------------------------------------------
        Dim objFileInfo As FileInfo = New FileInfo(strFilename)     ' FileInfo
        Dim strExt As String = objFileInfo.Extension.ToUpper        ' 拡張子
        Dim strMSG As String = String.Empty                         ' メッセージ
        strMSGHeader = "ファイル存在チェック"
        strBooknameU = objFileInfo.Name.ToUpper
        ' 拡張子判定
        If ((strExt = g_cnsXLT) OrElse (strExt = g_cnsXLTM) OrElse (strExt = g_cnsXLTX)) Then
            blnTemplate = True
        End If
        ' ファイルが見つからない
        If Not objFileInfo.Exists Then
            ' 拡張子判定
            If blnTemplate Then
                strMSG = "指定のテンプレートが存在しません。"
            Else
                strMSG = "指定のワークブックが存在しません。"
            End If
            strMSG &= ControlChars.CrLf & strFilename
            MessageBox2.DialogShow(g_objOwnerForm, _
                                   strMSG, _
                                   g_objOwnerForm.Text, _
                                   MessageBoxButtons.OK, _
                                   MessageBoxIcon.Error)
            Return False
        Else
            Return True
        End If
    End Function

    '***********************************************************************************************
    '* 処理名 :FP_OpenNewWorkbook
    '* 機能  :新規ワークブックを開く
    '-----------------------------------------------------------------------------------------------
    '* 返り値 :処理成否(Boolean)
    '* 引数  :Arg1 = Excel.Workbook(Object)                  ※Ref参照
    '*      Arg2 = 例外時メッセージヘッダ(String)          ※Ref参照
    '-----------------------------------------------------------------------------------------------
    '* 作成日 :2017年02月26日
    '* 作成者 :井上 治
    '* 更新日 :2017年04月06日
    '* 更新者 :井上 治
    '* 機能説明:
    '* 注意事項:
    '***********************************************************************************************
    Private Function FP_OpenNewWorkbook(ByRef objWBK As Object, _
                                        ByRef strMSGHeader As String) As Boolean
        '-------------------------------------------------------------------------------------------
        strMSGHeader = "新規ワークブックを開く"
        ' 新規インスタンスか?
        If (g_swNewInstance AndAlso (g_objWorkbooks.Count <> 0)) Then
            objWBK = g_objWorkbooks(1)
        Else
            objWBK = g_objWorkbooks.Add
        End If
        Return True
    End Function

    '***********************************************************************************************
    '* 処理名 :FP_OpenExiWorkbook
    '* 機能  :既存ワークブックを開く
    '-----------------------------------------------------------------------------------------------
    '* 返り値 :処理成否(Boolean)
    '* 引数  :Arg1 = ワークブックファイル名(String)   ※フルパスで指定
    '*      Arg2 = テンプレート判定(Boolean)
    '*      Arg3 = ブック名(大文字変換)(String)
    '*      Arg4 = 引数UpdateLinks(Int16)
    '*      Arg5 = 引数ReadOnly(Boolean)
    '*      Arg6 = Excel.Workbook(Object)                  ※Ref参照
    '*      Arg7 = 例外時メッセージヘッダ(String)          ※Ref参照
    '-----------------------------------------------------------------------------------------------
    '* 作成日 :2017年02月26日
    '* 作成者 :井上 治
    '* 更新日 :2017年04月11日
    '* 更新者 :井上 治
    '* 機能説明:
    '* 注意事項:
    '***********************************************************************************************
    Private Function FP_OpenExiWorkbook(ByVal strFileName As String, _
                                        ByVal blnTemplate As Boolean, _
                                        ByVal strBooknameU As String, _
                                        ByVal intUpdateLinks As Int16, _
                                        ByVal blnReadOnly As Boolean, _
                                        ByRef objWBK As Object, _
                                        ByRef strMSGHeader As String) As Boolean
        '-------------------------------------------------------------------------------------------
        strMSGHeader = "既存ワークブックを開く"
        ' テンプレートか
        If blnTemplate Then
            ' 初期イベント状態(モジュール変数にて設定)
            g_objExcel.EnableEvents = g_swExcelEnableEvents
            ' テンプレート(*.xlt,*.xltm,*.xltx)時は新規ブックで開く
            objWBK = g_objWorkbooks.Add(strFileName)
        Else
            ' ワークブック(*.xls,*.xlsm,*.xlsx)等の場合は既に開いているか判断
            If Not g_swNewInstance Then
                ' 開いているブックを巡回
                For Each objWBK2 As Object In g_objWorkbooks
                    ' フルネームの一致はそのファイルの処理とする(正常扱い)
                    If objWBK2.FullName.ToUpper = strFileName.ToUpper Then
                        objWBK = objWBK2
                        Return True
                    End If
                Next objWBK2
                ' 開いているブックを巡回
                For Each objWBK2 As Object In g_objWorkbooks
                    ' ブック名のみ一致はNG
                    If objWBK2.Name.ToUpper = strBooknameU Then
                        ' ブック名の衝突
                        Dim strMSG As String = _
                            "指定ワークブックと同じブック名のファイルが開かれています。" ' メッセージ
                        MessageBox2.DialogShow(g_objOwnerForm, _
                                               strMSG, _
                                               g_objOwnerForm.Text, _
                                               MessageBoxButtons.OK, _
                                               MessageBoxIcon.Error)
                        ' Excel.Workbookの解放
                        Call GP_ReleaseComObject(objWBK)
                        Return False
                    End If
                Next objWBK2
            End If
            ' 初期イベント状態(モジュール変数にて設定)
            g_objExcel.EnableEvents = g_swExcelEnableEvents
            ' ワークブック(*.xls等)時は開く
            objWBK = g_objWorkbooks.Open(strFileName, intUpdateLinks, blnReadOnly)
        End If
        Return True
    End Function

    '***********************************************************************************************
    '   ■■■ プロパティ ■■■
    '***********************************************************************************************
    '   処理中断スイッチ(Boolean)
    '-----------------------------------------------------------------------------------------------
    Friend Property prpPrintCancel() As Boolean
        Get
            Return g_swPrintCancel
        End Get
        Set(ByVal value As Boolean)
            g_swPrintCancel = value
        End Set
    End Property

    '===============================================================================================
    '   出力処理中スイッチ(Boolean)
    '-----------------------------------------------------------------------------------------------
    Friend Property prpExcelDuringProc() As Boolean
        Get
            Return g_swExcelDuringProc
        End Get
        Set(ByVal value As Boolean)
            g_swExcelDuringProc = value
        End Set
    End Property

    '===============================================================================================
    '   ブックOPEN時のイベント状態(イベント停止する場合はFP_GetWorkbookを呼ぶ前にFalseにする)
    '-----------------------------------------------------------------------------------------------
    Friend Property prpExcelEnableEvents() As Boolean
        Get
            Return g_swExcelEnableEvents
        End Get
        Set(ByVal value As Boolean)
            g_swExcelEnableEvents = value
        End Set
    End Property

    '===============================================================================================
    '   Excel.Application(Obnject)      ※既にExcelインスタンスが確保されている前提
    '-----------------------------------------------------------------------------------------------
    Friend ReadOnly Property ExApp As Object
        Get
            Return g_objExcel
        End Get
    End Property

    '===============================================================================================
    '   Excel.Workbooks(Obnject)        ※既にExcelインスタンスが確保されている前提
    '-----------------------------------------------------------------------------------------------
    Friend ReadOnly Property ExWorkbooks As Object
        Get
            Return g_objWorkbooks
        End Get
    End Property

    '---------------------------------------<< End of Source >>-------------------------------------
End Class
このクラスでも「Microsoft.Office.Interop」のインポートがなくなり、Excel関連のオブジェクトのデータ型は単にAs Objectに変更することになります。
ここまでは同じですが、これ以外にExcelのインスタンス取得方法が変わります。
例えば、新規インスタンス指定の場合、「参照設定」であれば、

    g_objExcel = New Excel.Application
これだけで済みますが「実行時バインド」では「Excelとは何か」から始めることになります。

    ' Excel.Applicationのインスタンス取得(又は生成)
    Dim typType As Type Type.GetTypeFromProgID(g_cnsExcelApplication) ' Type
    g_objExcel = Activator.CreateInstance(typType)
エラー処置を除いて記述するとこのようになります。
このような違いはありますが、共通クラスとしての記述なのでこの記述における動作確認は初回利用時のみにできるでしょう。
フォーム画面が崩れる時は...   近年の「高DPIノートPC」をWindows7以前のバージョンで使用している場合は、 フォームやコントロールの大きさが変わらないのに文字だけ大きくなってしまうのでフォーム画面が崩れた状態に表示されてしまいます。
Windows8.1以降ではOS側がスクリーンごとのDPI設定を含めて補正してしまうので問題ないのですが、 Windows7以前ではプログラム側で対策を講じる必要があります。
本件についてはDPI制御の問題」をご覧下さい。