Excel VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


5964 / 13644 ツリー ←次へ | 前へ→

【47910】マクロをバックグラウンドで実行 VBA初心者 07/3/26(月) 13:43 質問[未読]
【47921】Re:マクロをバックグラウンドで実行 Jaka 07/3/26(月) 17:14 発言[未読]
【47923】Re:マクロをバックグラウンドで実行 VBA初心者 07/3/26(月) 18:29 発言[未読]
【47925】Re:マクロをバックグラウンドで実行 ichinose 07/3/26(月) 20:06 発言[未読]
【47927】Re:マクロをバックグラウンドで実行 VBA初心者 07/3/26(月) 23:34 お礼[未読]
【47928】Re:マクロをバックグラウンドで実行 iino 07/3/27(火) 1:45 質問[未読]
【47930】Re:マクロをバックグラウンドで実行 ichinose 07/3/27(火) 7:46 発言[未読]
【47940】Re:マクロをバックグラウンドで実行 iino 07/3/27(火) 10:45 発言[未読]
【47942】Re:マクロをバックグラウンドで実行 Jaka 07/3/27(火) 11:02 発言[未読]
【47945】Re:マクロをバックグラウンドで実行 iino 07/3/27(火) 13:40 発言[未読]
【47947】Re:マクロをバックグラウンドで実行 Jaka 07/3/27(火) 15:01 発言[未読]
【47949】Re:マクロをバックグラウンドで実行 ichinose 07/3/27(火) 19:46 発言[未読]
【47953】Re:マクロをバックグラウンドで実行 iino 07/3/27(火) 20:45 お礼[未読]

【47910】マクロをバックグラウンドで実行
質問  VBA初心者  - 07/3/26(月) 13:43 -

引用なし
パスワード
   はじめて投稿します。
VBA初心者です。

処理結果が出るまでに時間がかかるため、
UserFormでプログレスバーを表示して
処理状況を表示するマクロを作成しています。

プログレスバーフォームを以下のモーダレスで起動してます。
Formプログレスバー.Show vbModeless

プログレスバーの更新は以下の関数を処理中に起動して、
DoEventsによって再描画してます。

Sub pro_bar(i, cend, label)
  Dim j As Integer
    
  j = i / cend * 100
  With Formプログレスバー
    .状態ラベル.Caption = label
    .パーセントラベル.Caption = Int(j) & "%"
    .プログレスバーラベル.Width = .パーセントラベル.Width * j / 100
  End With
  DoEvents
  
End Sub

しかし、この方法ですとマクロ実行中にプログレスバー及びExcelがActiveの場合は処理が続行されるのですが、
別のアプリ(メールやエクスプローラー等)にアクティブウィンドウを
移すと、プログレスバーの更新だけでなく、マクロの実行自体も
中断されてしまいます。(CPU使用率が0%になる)。
DoEventsによってOSに一度処理が戻るためだと思うのですが、
メーラー等を見ているときでも、マクロをバックグラウンドで実行し、
プログレスバーも更新されるような実装はできないのでしょうか?
プログレスバーを常にActiveフォーカスにしておかないと処理されないのでは
とても不便でして。。

ご教授よろしくお願い致します。

【47921】Re:マクロをバックグラウンドで実行
発言  Jaka  - 07/3/26(月) 17:14 -

引用なし
パスワード
   簡単なコードで試してみたら、バックグランドで動いてました。
バックグランドで動くと思っていなかったので収穫です。
by Win2000 and EXCL2002SP3

標準モジュール

Sub dkdldl()
UserForm1.Show
End Sub

フォームモジュール

Private Sub CommandButton1_Click()
Range("A20").Value = 0
For i = 1 To 20000
Range("A20").Value = Range("A20").Value + 1
DoEvents
Next
End Sub

【47923】Re:マクロをバックグラウンドで実行
発言  VBA初心者  - 07/3/26(月) 18:29 -

引用なし
パスワード
   Jakaさん。
早急なコメントありがとうございます。

確かに添付されているコードであれば処理がバックグラウンドで
処理されることは確認できたのですが、
プログレスバーのようなフォーカスをフォームに
ロックせずにメインの処理を実施したい場合には、
vbModeless指定が必須かと思っています。
vbModelessをはずすと、フォームに何も表示されないままダンマリになって
メインの処理が何も動かない状態になりました。。。
(何か致命的な勘違いがあるようでしたらご指摘ください)

vbModelessでメインの処理を随時プログレスフォームに
更新しながら、フォーカスを他のアプリに移しても
そのまま動き続けれてくれるように
できないものでしょうか?

【47925】Re:マクロをバックグラウンドで実行
発言  ichinose  - 07/3/26(月) 20:06 -

引用なし
パスワード
   こんばんは。

見ている方が全員同じものを見ていないと中々こういう
問題は処理しづらい と思いませんか?

新規ブックにユーザーフォーム(Userform1)だけ作成してください。
(コントロールは、動的に作成しますから、要りません)

標準モジュールに

'===========================================================
Sub main()
  Dim i As Long
  With Cells(1, 1)
    .value = 0
    Call init_progress_form
    Do Until .value = 20000
     Call set_progress_form(.value, 20000, "実行中")
     .value = .value + 1
     Loop
    Call term_progress_form
    End With
End Sub

別の標準モジュールに
'===============================================================
Option Explicit
Sub init_progress_form()
  With UserForm1
    .Width = 270
    .Height = 114
    With .Controls.Add("Forms.Label.1", , True)
     .Name = "Lbl状態"
     .Left = 12
     .Top = 12
     .Width = 60
     .Height = 18
     .Font.Size = 14
     .TextAlign = 2
     .SpecialEffect = 2
     End With
    With .Controls.Add("Forms.Label.1", , True)
     .Name = "Lbl総計"
     .Left = 12
     .Top = 42
     .Width = 200
     .Height = 18
     .SpecialEffect = 2
     .ForeColor = &HFFFFFF
     .TextAlign = 2
     End With
    With .Controls.Add("Forms.Label.1", , True)
     .Name = "Lblパーセント"
     .Left = 216
     .Top = 48
     .Width = 30
     .Height = 12
     .SpecialEffect = 0
     .TextAlign = 3
     End With
   
    With .Controls.Add("Forms.Label.1", , True)
     .Name = "Lblバー"
     .Left = 12
     .Top = 42
     .Width = 0
     .Height = 18
     .SpecialEffect = 0
     .BackColor = &H800000
     End With
    .Show vbModeless
    End With
End Sub
'===============================================================
Sub set_progress_form(value As Variant, amount As Variant, Optional status As Variant = "")
  With UserForm1
    .Controls("LBl状態").Caption = status
    .Controls("Lblパーセント").Caption = Format(value / amount, "0%")
    .Controls("Lblバー").Width = .Controls("Lbl総計").Width * value / amount
    DoEvents
  End With
End Sub
'===============================================================
Sub term_progress_form()
  Unload UserForm1
End Sub


これでmainを実行して別のタスクをアクティブにして試してください。
勿論、アクティブにしたタスクがCPUを握りっぱなしなら、そりゃあ動作は止まりますが、
通常のHPを表示しているIE等に切り替えても上記のmainは作動していますよ!!

尚、バックグラウンドのプログラムについて

HTTP://winxp.1123.info/010/post_2.html
(頭のHTTPは直してください)

こんな情報もありますから、参考にしてください。

【47927】Re:マクロをバックグラウンドで実行
お礼  VBA初心者  - 07/3/26(月) 23:34 -

引用なし
パスワード
   ご教授ありがとうございました。

下記方法にて新規に作成して実行した結果、
イメージしているようにバッググラウンドで動作しました。

ご紹介していただいた処理をこちらのマクロに移植してみましたが、
やはりすぐにExcelの使用率が0%に落ちてしまいます。
こちらのメインの処理からCallする
プログレスバーの更新間隔が一定ではないのが問題なのかもしれません。

また、ご紹介していただいた以下のページ書かれていた
レジストリ設定のCPU占有率を2:1に変更したら
バッググラウンドでもそれなりに動いてくれました。

>HTTP://winxp.1123.info/010/post_2.html
>(頭のHTTPは直してください)

プログレスバー自体は同様の処理なのに
マクロによって動きっぷりが異なるのが
なぜなのかわかりませんが、とても参考になりました。
いろいろとご教授ありがとうございました。

【47928】Re:マクロをバックグラウンドで実行
質問  iino  - 07/3/27(火) 1:45 -

引用なし
パスワード
   ▼ichinose さん:
こんばんは。
よこからすみませんiinoです。
興味がわいたので
下記プログレスバーを実行してみました

そこで質問ですが バー作動中に
他のコードを実行させるにはどのように
このコードに当てたらいいのですか?
教えて下さい。
初心者なので・・・明瞭にお願いできますか。

>見ている方が全員同じものを見ていないと中々こういう
>問題は処理しづらい と思いませんか?
>
>新規ブックにユーザーフォーム(Userform1)だけ作成してください。
>(コントロールは、動的に作成しますから、要りません)
>
>標準モジュールに
>
>'===========================================================
>Sub main()
>  Dim i As Long
>  With Cells(1, 1)
>    .value = 0
>    Call init_progress_form
>    Do Until .value = 20000
>     Call set_progress_form(.value, 20000, "実行中")
>     .value = .value + 1
>     Loop
>    Call term_progress_form
>    End With
>End Sub
>
>別の標準モジュールに
>'===============================================================
>Option Explicit
>Sub init_progress_form()
>  With UserForm1
>    .Width = 270
>    .Height = 114
>    With .Controls.Add("Forms.Label.1", , True)
>     .Name = "Lbl状態"
>     .Left = 12
>     .Top = 12
>     .Width = 60
>     .Height = 18
>     .Font.Size = 14
>     .TextAlign = 2
>     .SpecialEffect = 2
>     End With
>    With .Controls.Add("Forms.Label.1", , True)
>     .Name = "Lbl総計"
>     .Left = 12
>     .Top = 42
>     .Width = 200
>     .Height = 18
>     .SpecialEffect = 2
>     .ForeColor = &HFFFFFF
>     .TextAlign = 2
>     End With
>    With .Controls.Add("Forms.Label.1", , True)
>     .Name = "Lblパーセント"
>     .Left = 216
>     .Top = 48
>     .Width = 30
>     .Height = 12
>     .SpecialEffect = 0
>     .TextAlign = 3
>     End With
>   
>    With .Controls.Add("Forms.Label.1", , True)
>     .Name = "Lblバー"
>     .Left = 12
>     .Top = 42
>     .Width = 0
>     .Height = 18
>     .SpecialEffect = 0
>     .BackColor = &H800000
>     End With
>    .Show vbModeless
>    End With
> End Sub
>'===============================================================
>Sub set_progress_form(value As Variant, amount As Variant, Optional status As Variant = "")
>  With UserForm1
>    .Controls("LBl状態").Caption = status
>    .Controls("Lblパーセント").Caption = Format(value / amount, "0%")
>    .Controls("Lblバー").Width = .Controls("Lbl総計").Width * value / amount
>    DoEvents
>  End With
>End Sub
>'===============================================================
>Sub term_progress_form()
>  Unload UserForm1
>End Sub
>
>
>これでmainを実行して別のタスクをアクティブにして試してください。
>勿論、アクティブにしたタスクがCPUを握りっぱなしなら、そりゃあ動作は止まりますが、
>通常のHPを表示しているIE等に切り替えても上記のmainは作動していますよ!!
>
>尚、バックグラウンドのプログラムについて
>
>HTTP://winxp.1123.info/010/post_2.html
>(頭のHTTPは直してください)
>
>こんな情報もありますから、参考にしてください。

【47930】Re:マクロをバックグラウンドで実行
発言  ichinose  - 07/3/27(火) 7:46 -

引用なし
パスワード
   おはようございます。

>そこで質問ですが バー作動中に
>他のコードを実行させるにはどのように
>このコードに当てたらいいのですか?
>教えて下さい。
う〜ん、具体的にどのようなことがしたいのか
例を挙げてください。

上記の記述から、はっきりと何が知りたいの特定できません。


>>新規ブックにユーザーフォーム(Userform1)だけ作成してください。
>>(コントロールは、動的に作成しますから、要りません)
>>
>>標準モジュールに
>>
>>'===========================================================
>>Sub main()
>>  Dim i As Long
>>  With Cells(1, 1)
>>    .value = 0
>>    Call init_progress_form
>>    Do Until .value = 20000
>>     Call set_progress_form(.value, 20000, "実行中")
>>     .value = .value + 1
>>     Loop
>>    Call term_progress_form
>>    End With
>>End Sub

このコードは、セルA1(Cells(1,1))に初期値0を与え、
+1ずつ20000になるまで加算する、

というプログラムです。

この実行過程をラベルで表示しようとした例です。

本来の仕様は、あくまでも

「セルA1(Cells(1,1))に初期値0を与え、
+1ずつ20000になるまで加算する」

なのです。

コードは、セルA1に20000回、 1を加算するループ内で
途中経過をユーザーフォームのラベルに表示していますよね?

この関係を知りたいということですか?

だとしたら、角田さんのHPで詳しく説明されていますから、
これを参考にしてください。

www.h3.dion.ne.jp/~sakatsu/ProgressBarTopic.htm

↑の特に「2.プログレスバーを作るのに必要な事」を
をよく読んでみてください。


そうではなく別の意味ですか(ひとつ心当たりがありますが)?

だとしたら、冒頭で申し上げたとおり、具体例を挙げて
知りたいことを説明してください。

【47940】Re:マクロをバックグラウンドで実行
発言  iino  - 07/3/27(火) 10:45 -

引用なし
パスワード
   ▼ichinose さん:
返事ありがとうございます。

>おはようございます。
>
>>そこで質問ですが バー作動中に
>>他のコードを実行させるにはどのように
>>このコードに当てたらいいのですか?
>>教えて下さい。
>う〜ん、具体的にどのようなことがしたいのか
>例を挙げてください。
>
>上記の記述から、はっきりと何が知りたいの特定できません。
現在プログレスバーが作動中はその作業のみですが
単純に、この作動中にもバックでは他のマクロが動くように
できる?かの質問なんですが・・・
その場合下記のコードにCall・・・等を組み込むことで
実現できるのでしょうか?
'===========================================================
Sub main()
  Dim i As Long
  With Cells(1, 1)
    .value = 0
    Call init_progress_form
    Do Until .value = 20000
     Call set_progress_form(.value, 20000, "実行中")
     .value = .value + 1
     Loop
    Call term_progress_form
    End With
End Sub

>そうではなく別の意味ですか(ひとつ心当たりがありますが)?
たぶん心当たりではないかと思うのですが?
>
>だとしたら、冒頭で申し上げたとおり、具体例を挙げて
>知りたいことを説明してください。

【47942】Re:マクロをバックグラウンドで実行
発言  Jaka  - 07/3/27(火) 11:02 -

引用なし
パスワード
   ▼iino さん:
>現在プログレスバーが作動中はその作業のみですが
>単純に、この作動中にもバックでは他のマクロが動くように
>できる?かの質問なんですが・・・

>その場合下記のコードにCall・・・等を組み込むことで
>>そうではなく別の意味ですか(ひとつ心当たりがありますが)?
>たぶん心当たりではないかと思うのですが?
心当たりの見当が全くついてませんが、
プログレスバーってこんな感じですよ!

Sub prog()
 Application.DisplayStatusBar = True
 cnt = 20999
 Joz = 1000
 moji = String(Int(cnt \ Joz), "□")
 Application.StatusBar = moji
 For i = 1 To cnt
   Cells(1, 1).Value = i
   If i Mod Joz = 0 Then
    moji = Application.Substitute(moji, "□", "■", 1)
    Application.StatusBar = moji
   End If
 Next
 MsgBox "終了"
 Application.StatusBar = Empty
End Sub

【47945】Re:マクロをバックグラウンドで実行
発言  iino  - 07/3/27(火) 13:40 -

引用なし
パスワード
   ▼Jaka さん:
>>現在プログレスバーが作動中はその作業のみですが
>>単純に、この作動中にもバックでは他のマクロが動くように
>>できる?かの質問なんですが・・・
>
>>その場合下記のコードにCall・・・等を組み込むことで
>>>そうではなく別の意味ですか(ひとつ心当たりがありますが)?
>>たぶん心当たりではないかと思うのですが?
>心当たりの見当が全くついてませんが、
>プログレスバーってこんな感じですよ!
jakaさん下動かしてみました。
感じはわかりますが
出来るかどうかは解りませんがこのバーが
作動中に他のvbaを動かし、プログレスバー終了と同時に
他のvbaコードも終了する。とういう動作を想定してます。
いかがでしょうか?
例えば下記コードをプログレスバー表示中に実行する。
ということなのですが
Sub 月曜日()
  Dim 日付 As Date

  ActiveSheet.Unprotect
   Range("J6,D10:G30,J10:Q30,I11:I12,I14:I30,D32:D38").Select
    Selection.ClearContents
  日付 = Now()
  Do Until Weekday(日付) = 2
    日付 = 日付 + 1
  Loop
  With Range("J6")
    .value = Format(日付, "yyyy/mm/dd")
    .Select
  End With
 
  Dim II As Integer, RR As Long, CC As Long
  For II = 1 To 14
   Select Case II
     Case 1 To 7: RR = 7 + II * 3: CC = 6
     Case Else:  RR = 24 + II:  CC = 4
   End Select
   Worksheets("スケ調").Cells(RR, CC) _
       .value = "=Calendar!H" & (4 + II)
   If II < 8 Then
     Worksheets("スケ調").Cells(RR, 10) _
       .value = "=Calendar!I" & (4 + II)
   End If
  Next

>
>Sub prog()
> Application.DisplayStatusBar = True
> cnt = 20999
> Joz = 1000
> moji = String(Int(cnt \ Joz), "□")
> Application.StatusBar = moji
> For i = 1 To cnt
>   Cells(1, 1).Value = i
>   If i Mod Joz = 0 Then
>    moji = Application.Substitute(moji, "□", "■", 1)
>    Application.StatusBar = moji
>   End If
> Next
> MsgBox "終了"
> Application.StatusBar = Empty
>End Sub

【47947】Re:マクロをバックグラウンドで実行
発言  Jaka  - 07/3/27(火) 15:01 -

引用なし
パスワード
   いまだによく解ってません。
因みにたったこれだけの処理で毎回DoEvents入れると余計に遅くなると思うけど。

Private Sub CommandButton1_Click()
ct = 20000
ProgressBar1.Max = Int(ct / 100)
ProgressBar1.Scrolling = ccScrollingSmooth
ProgressBar1.Value = 0
For i = 1 To ct
  Cells(1, 1).Value = i
  DoEvents
  If i Mod 100 = 0 Then
    ProgressBar1.Value = Int(i / 100)
  End If
Next
End Sub

【47949】Re:マクロをバックグラウンドで実行
発言  ichinose  - 07/3/27(火) 19:46 -

引用なし
パスワード
   こんばんは。
47945投稿も拝見しましたが、
必要性に疑問がありますが、可能か否かということだと
まず、難しいでしょうね!!


私が前回の47925で投稿したmainを以下のように変更してください。

Sub main()
  Dim i As Long
  i = 0
  Cells(1, 1).value = 0
  Call init_progress_form
  Do Until i = 20000
    Call set_progress_form(i, 20000, "実行中")
    i = i + 1
    Cells(1, 2).Select
    Cells(1, 1).Select
    Loop
  Call term_progress_form
End Sub

'次いで同じ標準モジュールに
'=========================
Sub subproc()
  With Cells(1, 1)
    .value = .value + 1
    End With
End Sub

↑これを追加してください。

47925で投稿した他のプロシジャーとUserform1は勿論必要ですよ!!

更に
Sheet1のモジュールに
'==========================================================
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
  If Target.Address = "$A$1" Then
    Call subproc
    End If
End Sub

コードは以上です。

Sheet1をアクティブにした状態でmainを実行してください。

mainとsubprocが同時動いているように見えませんか?
(subprocを作動させるには、何かをトリガーにしなければなりません。
今回は、シートのイベントを使いました)

動作とコードをよく照らし合わせてください。

Excelで出来るのはせいぜいこの程度です。
(色々と試してみるとわかりますが、
この程度の動作だって場合によれば止まってしまいます)

【47953】Re:マクロをバックグラウンドで実行
お礼  iino  - 07/3/27(火) 20:45 -

引用なし
パスワード
   ▼ichinose さん:
ありがとうございます。

>47945投稿も拝見しましたが、
>必要性に疑問がありますが、可能か否かということだと
>まず、難しいでしょうね!!
私にも内容が難しかったみたいです。
いろいろ試してみます。

>
>
>私が前回の47925で投稿したmainを以下のように変更してください。
>
>Sub main()
>  Dim i As Long
>  i = 0
>  Cells(1, 1).value = 0
>  Call init_progress_form
>  Do Until i = 20000
>    Call set_progress_form(i, 20000, "実行中")
>    i = i + 1
>    Cells(1, 2).Select
>    Cells(1, 1).Select
>    Loop
>  Call term_progress_form
>End Sub
>
>'次いで同じ標準モジュールに
>'=========================
>Sub subproc()
>  With Cells(1, 1)
>    .value = .value + 1
>    End With
>End Sub
>
>↑これを追加してください。
>
>47925で投稿した他のプロシジャーとUserform1は勿論必要ですよ!!
>
>更に
>Sheet1のモジュールに
>'==========================================================
>Private Sub Worksheet_SelectionChange(ByVal Target As Range)
>  If Target.Address = "$A$1" Then
>    Call subproc
>    End If
>End Sub
>
>コードは以上です。
>Sheet1をアクティブにした状態でmainを実行してください。
>
>mainとsubprocが同時動いているように見えませんか?
>(subprocを作動させるには、何かをトリガーにしなければなりません。
>今回は、シートのイベントを使いました)
>
>動作とコードをよく照らし合わせてください。
>
>Excelで出来るのはせいぜいこの程度です。
>(色々と試してみるとわかりますが、
>この程度の動作だって場合によれば止まってしまいます)
↑実行してみました・・・かなり微妙な状態です。
アドバイス本当にありがとうございました。
マスター出来ませんが終了としたいと思います。

5964 / 13644 ツリー ←次へ | 前へ→
ページ:  ┃  記事番号:
2610219
(SS)C-BOARD v3.8 is Free