Excel (VBA)

Excel VBAに関するフォーラムです。
  • 解決済みのトピックにはコメントできません。
このトピックは解決済みです。
質問

 
(Windows 7 Home Premium : Excel 2010)
プログラム実行中に進捗状況を表示
投稿日時: 18/07/16 23:09:36
投稿者: shimoichimabu

下記のプログラム実行中に、進捗状況Formで処理の進捗状況を表示したいですが、
表示しているときも・・・・の部分のプログラムも進行したいです。
・・・・部分のプログラムの実行時間は少なくとも10秒くらいは要しています。
薬品数が多いので、プログラムが終了するのに12分くらいかかります。
下記のプログラムでは、進捗状況Formが表示している間は
・・・・部分のプログラムは止まっていますね?
何か、いい方法はありませんか? (バーに表示させる方法ではなく)
 
For N = 1 To 薬品数
  ・・・・・・・・・・・・・・・・・・・・・
 ・・・・・・・・・・・・・・・・・・・・・
     With 進捗状況Form
        .進捗状況Label = N & " 品目 / " & 薬品数 & " 品目中"
        .進捗率Label = "(" & Round(100 * N / 薬品数, 0) & " %)"
        .入所者処理中Label = Range("A" & N).Value & "  処理中・・・"
        .経過時間Label = "経過時間:" & Format(Now() - t, "n分ss秒")
        .Show vbModeless
    End With
     
    Start = Timer
     
    Do While Timer < Start + 2 ' UserFormを2秒間表示
        DoEvents
    Loop
     
    Unload 進捗状況Form '進捗画面を閉じる
Next

回答
投稿日時: 18/07/16 23:47:58
投稿者: simple

>バーに表示させる方法ではなく
なぜですか?
ステータスバーに処理済み薬品の数を 処理済み/全体数 の形式で表示する方法が、
一番簡単にできて一番効果がありますよ。
それが、ダメだ、気に入らんというなら、
どんなもの望んでいるのか説明が必要でしょう。

回答
投稿日時: 18/07/17 02:26:06
投稿者: hatena
投稿者のウェブサイトに移動

shimoichimabu さんの引用:
下記のプログラムでは、進捗状況Formが表示している間は
・・・・部分のプログラムは止まっていますね?

 
.Show vbModeless とモードレスで開いているので、プログラムは止まりません。
    Do While Timer < Start + 2 ' UserFormを2秒間表示 
        DoEvents 
    Loop

で、強制的に2秒待機しているので、止まっているようにみえるだけです。
このコードは不要です。
 
ユーザーフォームを開いたり閉じたりを、ループ回数分繰り返す必要はないと思います。
ループ前に開いて、ループ後に閉じればいいでしょう。
 
上記を考慮すると下記のようなコードになります。
 
With 進捗状況Form
    .Show vbModeless
    For N = 1 To 薬品数
        ・・・・・・・・・・・・・・・・・・・・・ 
       ・・・・・・・・・・・・・・・・・・・・・ 
        
        .進捗状況Label = N & " 品目 / " & 薬品数 & " 品目中" 
        .進捗率Label = "(" & Round(100 * N / 薬品数, 0) & " %)" 
        .入所者処理中Label = Range("A" & N).Value & "  処理中・・・" 
        .経過時間Label = "経過時間:" & Format(Now() - t, "n分ss秒") 
        .Repaint '再描画 これがないとラベルが更新されない。
    Next
End With
Unload 進捗状況Form

回答
投稿日時: 18/07/17 07:17:38
投稿者: WinArrow
投稿者のウェブサイトに移動

進捗状況を表示する
ことそのものが処理時間短縮に逆行しています。
その辺は理解していますよね?
 
そのような観点から、極力時間が掛からないような
装備をすることです。
 
ユーザーフォームではなくて、ステータスバーが望ましいです。
数字で表示するよりも■文字(1文字を10%とか・・・)を使って
バーに見えるように表示する工夫もありと思います。

回答
投稿日時: 18/07/17 09:47:49
投稿者: Suzu

引用:
・・・・部分のプログラムの実行時間は少なくとも10秒くらいは要しています。

 
処理内容が判りませんが、
その処理の処理時間の短縮を検討した上での進捗表示でしょうか。
 
検討していないのであれば、その部分の検討が先だと思いますよ。
 
処理効率化が上手く進まないのであれば
処理内容、コードを提示し、短縮のアドバイスを求めるのも一つの方法でしょう。

回答
投稿日時: 18/07/17 10:17:23
投稿者: WinArrow
投稿者のウェブサイトに移動

そもそもの話ですが、
 
処理の「進捗状況を表示する」目的は、
処理時間が長く、オペレータへの不安をとり除くために使うものと考えます。
処理している経過を表示することそのものが処理時間を引き延ばすことに繋がります。
 
説明から
1件10秒・・・合計で12分
 
ということから単純計算すると、
12分x60秒=720秒/10秒で
72件になります。
 
この分析で、あっていますか?
 
100件くらいの件数で、12分も掛かり過ぎとは、思いませんか?
それに、2秒/件 → 約2分を加算するつもり?
 
 
 
 

回答
投稿日時: 18/07/17 10:43:30
投稿者: hatena
投稿者のウェブサイトに移動

他に方も言われている通り、1件10秒は、処理内容にもよりますが、かかりすぎだと思います。改善の余地はあるでしょう。処理の高速化を十分吟味されていないのなら、別にスレッドを立てて、1件分の処理内容、コードを提示して、高速化できないか質問されたらいいと思います。
 
それとは別に、どうしても時間のかかる処理はあると思います。私自身は、全体で10秒以上かかる処理はユーザーに進捗状況を表示すべきだと思います。そういう場合の進捗状況表示について議論するスレッドは有用だと思います。
 
処理の高速化と進捗状況表示は、まったくの別件ですので、スレッドは分けたほうがいいと思いますが、どうでしょうか。

回答
投稿日時: 18/07/17 10:59:01
投稿者: hatena
投稿者のウェブサイトに移動

進捗状況を表示する方法はいろいろ考えられます。
 
ステータスバーに表示する。
 
ワークシート上に表示する。
 
ユーザーフォーム上に表示する。
 
それぞれメリット、デメリットがあると思います。
 
ステータスバーだと、表示領域の関係で表示できる情報量に制限があります。
 
ユーザーフォームに表示する場合、そのような制限もないし、また、シート上に表示するよりよりユーザーに訴求できるというメリットがあります。
 
もちろん、そのことで全体の処理速度が遅くなるようなら、本末転倒です。
最初の質問のコードがそのようなコードになってますね。
1件当たり2秒も待機していますので。
 
上の私の回答のコードなら、
ループ前にユーザーフォームを開く、
ループ中にラベルのCaptionの更新 .Repaint
ループ後にユーザーフォームを閉じる
だけです。
数百件ぐらいのループなら1秒もかかりません。
 
これなら、十分有用だと思います。

回答
投稿日時: 18/07/17 12:50:55
投稿者: もこな2

既に確認されているのかもしれませんが、参考になりそうなサイトを紹介します。
 
まず、単純に処理状況をユーザーにお知らせしたいだけなら、やはりステータスバー使うのがお手軽なんじゃないかとおもいます。
【参考】ステータスバーを使う
http://officetanaka.net/excel/vba/tips/tips13.htm
 
凝ったデザインや、中断ボタン作りたいというのであれば、ユーザーフォームを使うようになるとおもいます。
【参考】「お待ちください」メッセージの表示
http://officetanaka.net/excel/vba/tips/tips23.htm

投稿日時: 18/07/17 23:26:05
投稿者: shimoichimabu

たくさんの人からの回答を頂き、ありがとうございます。
 
simpleさんからもご指摘があったステータスバーの件は、今回の進捗状況の
情報量が多いため、UserFormに表示させることを考えました。
また、1件当たりの処理時間が長すぎるとの指摘がありますが、確かにその通り
で、この点はもっと改善する方がいいと思いました。
ステータスバーも検討の余地もあり、進捗状況の内容も簡便化すれば、
有用と思いました。
結論として、PRGの高速化も考慮し、表示方法も再検討したいと思います。
 
>.Show vbModeless とモードレスで開いているので、プログラムは止まりません。
>ユーザーフォームを開いたり閉じたりを、ループ回数分繰り返す必要はないと思います。
>ループ前に開いて、ループ後に閉じればいいでしょう。
勉強になりました。ありがとうございました。