none
VBからExcelの印刷プレビューを表示した場合の戻り値 RRS feed

  • 質問

  • Vb.netアプリからExcelの印刷プレビューを表示し、
    印刷を行ったか否かによって後続の処理を分けているのですが、
    印刷プレビューの戻り値が環境によって違うものが返ってきており困っています。

    ソースコードは下記の通りです。
    --
    Dim isPrintout As Boolean = False
    isPrintout = Excel.Application.Dialogs(Excel.XlBuiltInDialog.xlDialogPrintPreview).Show()
    If isPrintout = True Then
        '印刷を行った場合の処理
    Else
        '印刷をしなかった場合の処理
    End If
    --

    windows7(32bit) + Excel2010(環境1とします) だと想定した結果になりますが。
    windows10(64bit) + Excel2010(環境2とします) だとまれに印刷を行わなかった場合でも
    Trueが返ってくることがあります。

    また上記のコードをExcelのVBAで動作させてみたところ
    環境1ではやはり想定通りなのですが、環境2では印刷するまでは想定通りですが、
    一度でも印刷すると、印刷を行ったか否かにかかわらず、必ずTrueが返ってきます。

    その他の情報として
    ・前提としてユーザー要件としてExcelのシートがテンプレートとなっているため
     他のオブジェクトに変えることは不可能。
     (代替策としてActiveReportやPrintDocumentなどが使えない)
    ・Dialogs.Showの部分をPrintPreviewに変えても同じ結果となる
    ・環境2では「管理者として実行を行う」と必ずTrueが返ってくる

    何が原因と考えられるでしょうか?
    また環境に左右されない方法はありますでしょうか?

    もし足りない情報がございましたら、返信いただけると幸いです。
    2017年4月10日 10:47

すべての返信

  • 『Excel.Application.Dialogs』という表記が気にかかりました。

    Excel VBA 環境において、イミディエイト ウィンドウ上で

    Set X = Application.Dialogs
    Set Y = Application.Dialogs
    Debug.Print X Is Y

    を実行すると「False」が出力されます。これはつまり、Dialogs プロパティは、アクセスするたびに新しいインスタンスを作成するプロパティであるということです。このようなオブジェクト操作は、特に外部アプリから制御するような場合に、問題を引き起こしやすくなります。併せて、下記のサポート技術情報もご覧ください。

    KB178510:2 回目のコード実行時に Excel のオートメーションが失敗する

    今回御提示頂いたコードで省略されている箇所も含めて、このような記述が残っていないかを確認してみてください。基本的には、COM オブジェクトそれぞれを変数に取得し、それらのプロパティ等を通じてアクセスするようにします。たとえば先の xlDialogPrintPreview なら、VBA では下記のようにする…ということです。(VB.NET も概ね同様に) 

    Set oApp = Excel.Application
    Set oDialogs = oApp.Dialogs
    Set oDialog = oDialogs(XlBuiltInDialog.xlDialogPrintPreview)
    oDialog.Show()

    それから、VB.NET からの呼び出し時においてオブジェクト解放処理(Marshal.ReleaseComObject)が正しく行われていない点も問題があると思います。このようなコードも、同様の理由で二回目以降の実行の際に不具合を生じる危険性があります。

    KB317109:Visual Studio .NET クライアントで自動化した Office アプリケーションが終了しない

    それ以外の要因としては、たとえば、誤動作する方は過去に別バージョンの Office が導入されていた経歴があり、旧バージョンがアンインストールされきっていなかったために、軽微なバージョン不整合を生じているという可能性もあるかもしれません。

    2017年4月10日 12:11
  • 魔界の仮面弁士様

    返信ありがとうございます!

    確かに質問に記述していないコード部に思い当たる箇所があります。

    ご提示いただいたページとサンプルコードを元に、もう一度ソースを見直して書き直してみようと思います。

    結果はまた後日ここに書き込みいたします。

    (職場からの書き込みが出来ないため、提示していただいた内容を試して返信するのに1〜2日かかると思います。)

    2017年4月10日 13:20
  • 魔界の仮面弁士様

    >基本的には、COM オブジェクトそれぞれを変数に取得し、それらのプロパティ等を通じてアクセスするようにします。たとえば先の xlDialogPrintPreview なら、VBA では下記のようにする…ということです。(VB.NET も概ね同様に)

    ご提示いただきましたコードをVBAで記述し、実行させていただきました。

    結果から言うとやはり「環境1では想定通りの動作で、環境2では同じ現象(印刷するまでは想定通り、一度でも印刷すると必ずTrueが返る)」となりました。

    その後も調査してみましたがどうも"Microsoft Print to PDF"で印刷すると、この現象が発生するようです。

    他の仮想プリンタ(Microsoft XPS Document Writer)や実際のプリンタでは発生しておりません。

    プリンタによってダイアログから戻り値が変わることがあるんでしょうか?

    2017年4月11日 21:58