質問
2019年1月30日水曜日 3:06
EXCELマクロの処理時間が遅いです。
動作環境
・OS Windows8.1(64bit)、Offce2013(32bit)
・OS Windows10(64bit)、Office2016(32bit)
なお、いずれも、会社が提供する仮想PC上で動作しています。
マクロ実行中にタスクマネージャで確認したところ、全体のCPUは20%~30%程度の割り当てられているようです。
(仮想PCは共有リソースにつき、この程度になるということです)
そして、この貴重なCPU20%~30%程度のうち、「Print driver host for applications」なるもののCPU使用率が0%~10%程度の間をふらふらと変動していて、EXCELが3%~5%程度しか使えていません。これが処理時間がかかる原因かと思います。
以下は、「Print driver host for applications」 について、タスクマネージャを眺めなら気づいた点です
①「Print driver host for applications」 は、EXCELタスクの起動のみや、プレーンなファイルをオープンしただけでは起動されない
②「Print driver host for applications」 は、EXCELのページレイアウトや表示(印刷範囲)の操作で起動される。また、印刷系のみでなく、プレーンなシートに数式(Σ)を挿入しただけでも起動される。
③「Print driver host for applications」 は、マクロのステップ実行しながら状況をみると、特定の命令でCPU率が変動するようでもない(例えば変数への値の代入だけでも変動する)
④「Print driver host for applications」を手動で終了させてたとき、マクロは正常に動く時もあれば、異常終了する場合もある
⑤「Print driver host for applications」を手動で終了させても、繰り返し処理の中で、またこのプロセスが復活しCPU使用率が高まる
⑥「Print driver host for applications」を手動により、何度も終了させながら、マクロを実行していくと、このプロセスが復活しなくなるときがあり、マクロの処理が正常終了となった場合、27秒で完了しました(通常は1分15秒ほどかかる処理)
Q1.ネットで調べると、「Print driver host for applications」とは、64bitOS、32bitのアプリの構成で印刷するための何からしいですが、なぜ、EXCELからこのプロセスが起動されてしまうのでしょうか?
上記③⑥からマクロの命令とは直接関係もなさそうですし、②からも、VBAからではなく、EXCELが勝手に起動しているようにも見えます。
Q2.不要な時には、EXCELからこのプロセスを起動しないようにするにはどうすればよいのでしょうか?
【追記】
その後、以下のことを実施して、どこでこのプロセスが生成されているかを探ってみました。
a)まず、マクロのEXCELファイルをオープンした後、「Print driver host for applications」タスクを終了させる
b) 当該タスクが消えた状態で、マクロをステップ実行していき、「Print driver host for applications」が表示される箇所を特定する。
この結果、ピボットの列フィールドを削除するところで、最初に生成されているようです。
命令は"~~~.PivotTables(ピボットテーブル名).PivotFields(フィールド名).Orientation = xlHidden"で、これ以前にはピボット操作する行はありませんが、以降にはピボット列を挿入したり、編集する処理があります。
c)そして、再度「Print driver host for applications」のタスクを消去して、引き続き、マクロをステップ実行していくと、「Print driver host for applications」は生成されません。繰り返し処理で上の処理に戻ってきても生成されません。
d)ところが、マクロをステップ実行ではなく連続実行すると、どこかのステップで当該プロセスが生成されてしまいます。
e)一度、このタスクが生成されてしまうと、一定の間隔でCPUの使用率が高くなるようですので、おそらくピボットテーブルを操作する処理でこのタスクが実行されるのかもしれません。(例えば、後続には、.PivotFields(フィールド名).Function = xlSum、.PivotFields(フィールド名).NumberFormat などの処理があります。
ステップ実行しながら、途中で当該プロセスを一度消すと、このプロセスは復活しないのですが、連続実行すると復活してしまいます。
また、実験的にピボット操作を含まない処理を作り、最初にΣ関数なおで、当該プロセスを生成したのち、マクロを連続実行す¥してみると、CPU使用率は0%のまま変更はないので、やはりVBAによるピボット操作が怪しいです。
すべての返信 (10)
2019年1月31日木曜日 9:11
A1.
"Print driver host for applications" の実態は "splwow64.exe" で、このプロセスは印刷機能を有する 32 ビット アプリから起動される。
で、32 ビット アプリがなぜ "splwow64.exe" を起動させるかというと。。。
アプリから印刷処理を実行する際には、プリンタ ドライバが提供する機能を呼び出す必要がある。
64 ビット環境の場合 32 ビットのプリンタ ドライバはインストール出来ないので、32 ビット アプリは 64 ビットのプリンタ ドライバを使用して印刷処理を行う必要があるが、32 ビット アプリは 32 ビット プロセス空間で動くので、64 ビット空間にはアクセスできない。
従って 32 ビット アプリは、64 ビット プリンタ ドライバを直接利用することはできない。
なので、別途 64 ビット プロセスである "splwow64.exe" を起動させ、32 ビット アプリからの印刷関連処理を "splwow64.exe" に肩代わりさせることで、64 ビット環境での 32 ビット アプリ印刷関連処理を実現している。
A2.
"splwow64.exe" プロセスは、32 ビット アプリがプリンタ ドライバを必要としたときに動的に起動されるので、起動させないことは基本的に不可能。
そして一度起動された "splwow64.exe" プロセスは、複数の 32 ビット アプリから利用される可能性がある。
つまり "splwow64.exe" の親プロセスである 32 ビット アプリが終了したとしても、別の 32 ビット アプリが引き続き "splwow64.exe" プロセスを必要とする場合もあるので、一概に「不要な時」というのを判断するのは難しい。
かつ、32 ビット アプリの起動/終了をいちいちチェックするのはそれなりに CPU リソースを食う処理なので、パフォーマンスの観点からも、"splwow64.exe" プロセスをその都度終了させるのはメリットがあるとも思えない。
そもそも提示されている調査内容だけで、"splwow64.exe" プロセスの存在がマクロ実行時におけるパフォーマンス低下の主要因と断定するのは、ちょっと無理があるような気がする。
例えば、"Print Spooler" サービスを停止させると "splwow64.exe" プロセスも起動されなくなるので、そーいった検;も行うべきでは?
P.S.
こんな↓レジストリ設定もあるので、(ダメだと思うけど) ダメ元で試してみては?
Splwow64.exe process does not end after a print job finishes in Windows 8 or Windows Server 2012
https://support.microsoft.com/en-us/help/2856657/splwow64-exe-process-does-not-end-after-a-print-job-finishes-in-window
2019年2月7日木曜日 3:34
ありがとうございます。
>"splwow64.exe" プロセスの存在がマクロ実行時におけるパフォーマンス低下の主要因と断定するのは、ちょっと無理があるような気がする。
ですが、会社が提供する仮想PCなので、そもそもCPUの割り当てが限られている中、他のアプリを起動していない状態で、マクロを実行すると、CPUを使用しているのは、EXCELタスク、splwow64.exe、Systemが主要なものとなっており、splwow64.exeが10%程度を占めてしまうため、EXCELに割り当てがいかないのが遅延の原因と考えています。
なので、なんとか、splwow64.exeを起動しないようにしたいと考えています。
マクロで複数シートに配置されたピボットテーブルを繰り返し操作をしていて印刷処理などは一切していないのですが、ページ設定(ヘッダー、フッター)や印刷範囲が設定されているシート(一度印刷したことがあるシート)で、ピボット操作を行うと、セルなどがずれて、都度splwow64.exeが実行されてしまうのかもしれないと考えているところです。
VBAの高速化テクニックで、以下のようなものを一通り入れてみても効果なしで手詰まりです。
Application.EnableEvents = False 'イベント発生制御
Application.Calculation = xlCalculationManual '自動計算停止
Application.ScreenUpdating = False '画面切り替え停止
Application.DisplayStatusBar = False 'ステータスバー更新制御
Application.PrintCommunication = False 'プリンター通信無効化
2019年2月7日木曜日 6:00
Excel に限らず Office アプリケーションは画面表示の際にプリンター ドライバーから得られる情報を利用しますので、随時プリンター ドライバーへのアクセスが発生します。その際に splwow64.exe が経由されますから、これを起動しないようにするには Office 自体を 64ビット版にするしかないと考えられます。
ただしそうしたからマクロの処理が早くなるかどうかは分かりません。試してみる価値はあると思いますが。
Hebikuzure aka Murachi Akira
2019年2月7日木曜日 6:32
先の返信でも説明したように、"splwow64.exe" は 32 ビット アプリから 64 ビット プリンタ ドライバを利用するためのプロセスです。
ですので、32 ビット アプリ側から印刷関連 (e.g. "印刷プレビュー", etc.) 処理が発生しない限り、"splwow64.exe" が自発的に何かの処理を行うことは無いはずです。
試しに、Word でも Excel でも Outlook でも何でもいいので、32 ビット アプリから "印刷" メニューを選択し "splwow64.exe" がロードされた状態にして、"splwow64.exe" の CPU 占有率を観察されることをお勧めします。
私の PC 環環境で観察した限りでは、32 ビット アプリ側からの印刷関連処理が実行されない限り、"splwow64.exe" の CPU 占有率は 0 でした。
つまり、"splwow64.exe" が 10% 程度の CPU 占有率で推移するということは、継続的に 32 ビット アプリ側から印刷関連処理リクエストが発生し続けていることを意味し、今回のケースの場合、それが VBA マクロ側に起因している可能性が高いと思います。
「印刷処理などは一切していない」とのことですが、間接的に印刷関連処理が発生するケースは多々あると思います。
「ピボットテーブルを繰り返し操作をして」とのことですが、もしこの「繰り返しの操作」の中に間接的な印刷関連処理が含まれている場合、そのリクエストはその都度 "splwow64.exe" プロセスを経由するはずなので、"splwow64.exe" は継続的に CPU リソースを消費することになります。
今回のケースもこれに該当しているのでは?
ちなみに、先の返信でも書いたように、32 ビット Excel が印刷機能を提供する限り、"splwow64.exe" プロセスの起動を抑止することは不可能だと思います。
先の返信で提案した「"Print Spooler" サービスを停止させた場合の検;」は実施されたのでしょうか?
追記
もしかして、VBA マクロ側でデバイス コンテキスト (hDC) を操作していませんか?
2019年2月7日木曜日 6:43
ありがとうございます。
>Office アプリケーションは画面表示の際にプリンター ドライバーから得られる情報を利用しますので、随時プリンター ドライバーへのアクセスが発生します
splwow64.exe が起動されない場合もあるので困っています。
例えば、新たなブックを作成し、これに同じマクロ移植して、ピボットテーブルのシートを作り直して実行したところ、
splwow64.exe が起動されず、処理時間も数秒で終わります。
また旧ファイルでも、手動でsplwow64.exe を停止させながら実行すると、正常終了した場合は処理時間が数秒で終わります。(この場合異常終了する場合のありますが・・・)
切り分けとして、新たなブックを作成してマクロを実行する際、事前にページ設定(ヘッダー、フッター)を設定した場合、splwow64.exe は起動されませんでした。さらに、これに加えて印刷範囲を設定した場合(一度印刷をした場合)は、splwow64.exe が起動され、CPU使用率が向上し、マクロ処理時間も遅くなりました。なので、画面表示の都度というよりは、印刷範囲が設定されたシートを操作するとこのタスクが実行されるように思います。
また、splwow64.exe が起動されている状態で、印刷範囲が設定されていない方のファイルでマクロを実行すると、splwow64.exe のCPU使用率は0%のままで、処理時間も数秒で完了します。
ということは、印刷範囲を設定しても(一度印刷したことがあるシートでも)、このsplwow64.exe を実行しない(タスクは起動されていてもされていなくてもよい)ような方法があれば問題は解決すると考えます。
2019年2月7日木曜日 7:14
> 例えば、新たなブックを作成し、これに同じマクロ移植して、ピボットテーブルのシートを
> 作り直して実行したところ、 splwow64.exe が起動されず、処理時間も数秒で
> 終わります。
であれば特定の(未知、未確認の)条件のブック依存の問題ということなので、ブックの作り直しが現実的では?
Hebikuzure aka Murachi Akira
2019年2月7日木曜日 9:49
> 例えば、新たなブックを作成し、これに同じマクロ移植して、ピボットテーブルのシートを
> 作り直して実行したところ、 splwow64.exe が起動されず、処理時間も数秒で
> 終わります。であれば特定の(未知、未確認の)条件のブック依存の問題ということなので、ブックの作り直しが現実的では?
Hebikuzure aka Murachi Akira
新しいブックを作り直した後に、マクロを実行しても、splwow64.exe が起動されないのですが、
一度印刷設定をしてしまうと、以降、splwow64.exe が実行されてしまうようです。印刷範囲が設定されている状態で、何らかのイベント(例えばピボット処理)が発生すると、splwow64.exe が実行されているようにも見えます。
2019年2月7日木曜日 10:06
>「印刷処理などは一切していない」とのことですが、間接的に印刷関連処理が発生するケースは多々あると思います。
>「ピボットテーブルを繰り返し操作をして」とのことですが、もしこの「繰り返しの操作」の中に間接的な印刷関連処理が含まれ>ている場合、そのリクエストはその都度 "splwow64.exe" プロセスを経由するはずなので、"splwow64.exe" は継続的に CPU >リソースを消費することになります。
実験として、新しいブックを作りなおして、マクロを実行すると、splwow64.exeは起動されず、処理も早く完了します。
さらに、この状態で印刷設定すると、おっしゃる通りsplwow64.exeは起動されます。この状態で、マクロを実行すると、splwow64.exeのCPU率が上がっていきます。
なので、処理そのものではなく、印刷範囲指定や改ページ指定といったことと、ピボットテーブルのフィールド操作をマクロで行うという条件が重なると、splwow64.exeが実行されてしまうように見えます。
ピボットテーブルを囲むように改ページを設定した状態で、手動でフィールドを追加すると、改ページが自動調整されて splwow64.exeが実行されます。一方、splwow64.exeのタスクを停止した状態で、同じ操作をすると、改ページが自動調整されずに、splwow64.exeのCPU使用率はゼロのままです。改ページの自動調整をしないように制御できればよいのですが。。。
2019年2月7日木曜日 12:33
splwow64.exe が起動されることは、Excel がプリンターの何らかの情報にアクセスした時点ということで、制御不可能な範囲にあるわけです。
その制御を VBA で解決したいと願うと、出口のない迷路にはまる可能性が高いです。
理想的には splwow64.exe の CPU 使用率が高くなる問題を解決することでしょうけれども、有償サポートを;るなど、かなりハードルの高いことだと思います。
一番負担が少ない道は、印刷設定を諦めるでしょうね。
どちらもいやだと言われると、手詰まり感がありますが…。
2019年2月8日金曜日 1:02
以前から提案していますが、「"Print Spooler" サービスを停止させた場合の検;」を実施されないのはなぜでしょうか?
"Print Spooler" サービスを停止させた場合、質問者さんが切望している "splwow64.exe" プロセスが起動しない状態を作り出せます。
ただし印刷に関連するすべての機能が停止されるので、現実的な対応策にはなり得ません。
ですが VBA マクロ側で「印刷処理などは一切していない」のであれば、"Print Spooler" サービスを停止させても、マクロ処理内でエラーが発生することは無いはずです。
逆に "Print Spooler" サービスの停止でマクロ内でのエラーが発生するのであれば、そこが印刷関連処理と「間接的」に関係しているということですから、それを特定できれば実装を見直すことで回避できる可能性も出てくると思います。
それ以外にも、自力で調べられる方法はいくらでもあると思います。
例えば Excel プロセスにデバッガをアタッチさせ、このプロセスがインポートしている印刷関連の API を洗い出して Breakpoint を設定し、問題現象が発生するときにどこが呼び出されているのかを特定できれば、それが問題解決への重要なヒントになるはずです。
「難しそうだから出来ない」というのであれば、Azulean さんが仰っているように諦めた方がいいと思います。
ちなみに、この「マクロ処理が遅くなる」問題は 64 ビット Excel でも起きるのでは?
なぜなら、問題の本質は「"splwow64.exe" プロセスが CPU リソースを食っている」のではなく、「印刷関連処理が CPU リソースを食っている」と考えられるため。
なので office 64 ビット版への移行も、本質的な問題解決にならないと思います。
いずれにせよ、推測に基づいた対応策の模索は、結局のところ問題解決への「遠回り」をしているのでは。。。と思うのです。
推測が当たれば「近道」になりますが、外れを引いている限り答えにたどり着けない訳ですから、当たりが出るまでの博打をしているのと同じような気がします。
(あくまでも個人的な見解ですか、私だったら迷わず原因究明のための調査を優先させます。)