Excel (VBA)

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

 
(Windows 10 Home : Excel 2010)
Enabled操作後の画面表示が遅いです
投稿日時: 17/12/11 22:39:03
投稿者: pyonpyon

■ 質問
下記の条件の場合、メッセージボックスに表示される時間は0.08秒前後なのですが、
体感では1秒半くらいかかって表示されるので少し違和感があります。
表示が遅い原因は何でしょうか?また、早く表示する方法はありますか?
 
■ 条件
ワークシート上にA、B、Cの3つのグループがあります。
Aグループはオプションボタンが5個、
Bグループはチェックボックスが20個あります。
Cグループはラベルが2個、テキストボックスが1個、
例えば、Bグループのオプションボタンが押下された場合はBグループを活性化し、他グループは非活性化します。
 
■ プログラム
Private Sub Bラジオボタン_Click()
     
    Dim StartTime, StopTime As Single
 
    StartTime = Timer 'Debug
 
    With Application
        .EnableEvents = False
        .ScreenUpdating = False
        .Calculation = xlCalculationManual
    End With
     
    Call Aグループ非活性化 ←.Enabled=Falseの処理
    Call Bグループ活性化 ←.Enabled=Trueの処理
    Call Cグループ非活性化 ←.Enabled=Falseの処理
         
    With Application
        .EnableEvents = True
        .ScreenUpdating = True
        .Calculation = xlCalculationAutomatic
    End With
 
    StopTime = Timer 'Debug
    MsgBox "Bラジオボタンの所要時間は" & Round(StopTime - StartTime, 6) & "秒 でした" 'Debug
 
End Sub

回答
投稿日時: 17/12/12 10:40:45
投稿者: mattuwan44

ちと、確認です。

>ワークシート上にA、B、Cの3つのグループがあります。

切り替え用のラジオボタンがあるから、4つのグループですよね?
で、グループとは、各プロパティのgroupnameのことですよね?

回答
投稿日時: 17/12/12 14:03:24
投稿者: mattuwan44

あ、図形のグループ化の話だろうという想像で描きました。
 

Option Explicit

Sub 切り替え(ByVal n As Long)
    Dim i As Long
    Dim flg As Boolean
    
    Application.ScreenUpdating = False
    For i = 1 To 3
        flg = IIf(n = i, True, False)
        活性化 i, flg
    Next
End Sub

Sub 活性化(ByVal ix As Long, ByVal flg As Boolean)
    Dim s As Shape
    
    For Each s In Me.Shapes(ix).GroupItems
        s.OLEFormat.Object.Enabled = flg
    Next
End Sub

Private Sub OptionButton6_Click()
    切り替え 1
End Sub

Private Sub OptionButton7_Click()
    Dim t
    t = Timer
    
    切り替え 2
    
    Debug.Print Timer - t
End Sub

Private Sub OptionButton8_Click()
        切り替え 3
End Sub

こちらの環境では、体感的に表示の切り替えに一呼吸掛かりますが、
1秒よりは速いかなと、、、、
これで遅いなら機械の性能なので、コードで高速化は難しいかと、、、、
もっと速いコードはあるかもですが、体感的に変わるとは思えない。。。です。
(個人の感想なので、工夫の余地が必ずないとは言えないので、他の方の意見も待ってみてください。)
 

投稿日時: 17/12/12 21:28:53
投稿者: pyonpyon

mattuwan44 さん、回答ありがとうございます。
 
私のやってることは図形のグループ化などの難しいことではなく、一般的な簡単なことです(^^;。
 
まず、3つのグループという表現がまずかったです。言いたかったのは下図のようなレイアウトです。
オプションボタンA、B、Cのいずれかを押した場合、押したオプションボタン配下のコントロールのEnabled = Trueにし、他はFalseを設定したいだけです。
ちなみに、オプションボタンA、B、CのGroupNameは同じです。
 
〇オプションボタンA    〇オプションボタンB    〇オプションボタンC
 〇オプションボタン1    □チェックボックス1    テキストボックス
 〇オプションボタン2    □チェックボックス2
     〜            〜
 〇オプションボタン5    □チェックボックス20
 
最初の質問にも書きましたが、Enabledの設定処理は0.08秒前後で早いのですが、見た感じではオプションボタンを押してから各コントロールの活性/非活性がワンテンポ遅れるので少し気になった次第です。

回答
投稿日時: 17/12/13 13:41:09
投稿者: baoo

pyonpyon さんの引用:
まず、3つのグループという表現がまずかったです。
そうですね。
質問される方は回答者の画面を想像せずにされることが多いです。
私も最初ご質問を見たとき、グループって何だと思って回答に参加する気になりませんでした。
 
さて、計測時間や体感は動作させるPC環境によって変わりますが、
私の環境では計測時間も体感時間ももっと短いです。
Application.EnableEventsやApplication.ScreenUpdating、Application.Calculationを
活性化、非活性化の前後で設定されていますが特別な理由が無い限り、
この設定は速度を低下させると思います。
これらは無条件に速度向上させるわけではありません。
きちんと意味を捉えるべきかと思います。
もちろん、他の要因(提示コードからは見えないセル操作などのコードが動いている等)、
環境などで速度を向上させる場合もありますので一概には言えないのですが。
 
ご指摘の体感時間が計測時間より遅いのは実際の活性化、非活性化が
その描画終了まで待って完了しているわけではないからだと思います。
実際、私の環境では活性化へ切り替わり中で表示上チェックボックスが
グレーアウトしている時にチェックを付けることが出来るように見えます。
 
提示のコードでは活性化、非活性化処理がありませんのでコードを統一する意味で、
私のシートを作成するコードとそのシートモジュールのコードを下記に挙げます。
なお、Application.EnableEventsのみはあえて設定しています。
動作上、問題なければこれも外した方が速度が向上すると思います。
'シート作成
Sub MakeSheet()
    
    Dim sht As Worksheet
    Dim i As Long
    
    Set sht = Worksheets.Add
    With sht.OLEObjects
        'OptionButton
        For i = 1 To 8
            With .Add(ClassType:="Forms.OptionButton.1", Width:=100, Height:=15)
                .Name = "OptionButton" & i
                If i < 4 Then
                    'OptionButton1-OptionButton3
                    .Left = 30 + (i - 1) * 100
                    .Top = 30
                    .Object.GroupName = "A"
                Else
                    'GoupB(OptionButton1)
                    .Left = 30
                    .Top = 30 + (i - 3) * 15
                    .Object.GroupName = "B"
                End If
            End With
        Next i
        
        'GroupC(OptionButton2)
        For i = 1 To 20
            With .Add(ClassType:="Forms.CheckBox.1", Left:=130, Width:=100, Height:=15)
                .Name = "CheckBox" & i
                .Top = 30 + (21 - i) * 15
                .Object.GroupName = "C"
            End With
        Next i
        
        'NoGroup(OptionButton3)
        With .Add(ClassType:="Forms.TextBox.1", Left:=230, Width:=100, Height:=15)
            .Name = "TextBox1"
            .Top = 30 + 15
        End With
        With .Add(ClassType:="Forms.Label.1", Left:=230, Width:=100, Height:=15)
            .Name = "Label1"
            .Top = 30 + 15 * 2
        End With
        With .Add(ClassType:="Forms.Label.1", Left:=230, Width:=100, Height:=15)
            .Name = "Label2"
            .Top = 30 + 15 * 3
        End With
        
    End With
    
End Sub

'作成されたシートモジュールに貼り付ける
Option Explicit
Private Sub OptionButton1_Click()
    
    Dim t As Double
    
    t = Timer
    With Application
        .EnableEvents = False
'        .ScreenUpdating = False
'        .Calculation = xlCalculationManual
    End With
    
    ChangeOpt 1
    
    With Application
        .EnableEvents = True
'        .ScreenUpdating = True
'        .Calculation = xlCalculationAutomatic
    End With
    
    Debug.Print Timer - t
    

End Sub

Private Sub OptionButton2_Click()

    Dim t As Double
    
    t = Timer
    With Application
        .EnableEvents = False
'        .ScreenUpdating = False
'        .Calculation = xlCalculationManual
    End With
    
    ChangeOpt 2
    
    With Application
        .EnableEvents = True
'        .ScreenUpdating = True
'        .Calculation = xlCalculationAutomatic
    End With
    Debug.Print Timer - t

End Sub

Private Sub OptionButton3_Click()

    Dim t As Double
    
    t = Timer
    With Application
        .EnableEvents = False
'        .ScreenUpdating = False
'        .Calculation = xlCalculationManual
    End With
    
    ChangeOpt 3
    
    With Application
        .EnableEvents = True
'        .ScreenUpdating = True
'        .Calculation = xlCalculationAutomatic
    End With
    Debug.Print Timer - t

End Sub
Private Sub ChangeOpt(lngOpt As Long)
    
    Select Case lngOpt
    Case 1
        If TextBox1.Enabled Then
            GrpNOnOff False
        End If
        If CheckBox1.Enabled Then
            GrpCOnOff False
        End If
        GrpBOnOff True
    Case 2
        If TextBox1.Enabled Then
            GrpNOnOff False
        End If
        If OptionButton4.Enabled Then
            GrpBOnOff False
        End If
        GrpCOnOff True
    Case 3
        GrpNOnOff True
        If OptionButton4.Enabled Then
            GrpBOnOff False
        End If
        If CheckBox1.Enabled Then
            GrpCOnOff False
        End If
    End Select
    
End Sub
Private Sub GrpBOnOff(blStatus As Boolean)
    OptionButton4.Enabled = blStatus
    OptionButton5.Enabled = blStatus
    OptionButton6.Enabled = blStatus
    OptionButton7.Enabled = blStatus
    OptionButton8.Enabled = blStatus
End Sub
Private Sub GrpCOnOff(blStatus As Boolean)
    CheckBox1.Enabled = blStatus
    CheckBox2.Enabled = blStatus
    CheckBox3.Enabled = blStatus
    CheckBox4.Enabled = blStatus
    CheckBox5.Enabled = blStatus
    CheckBox6.Enabled = blStatus
    CheckBox7.Enabled = blStatus
    CheckBox8.Enabled = blStatus
    CheckBox9.Enabled = blStatus
    CheckBox10.Enabled = blStatus
    CheckBox11.Enabled = blStatus
    CheckBox12.Enabled = blStatus
    CheckBox13.Enabled = blStatus
    CheckBox14.Enabled = blStatus
    CheckBox15.Enabled = blStatus
    CheckBox16.Enabled = blStatus
    CheckBox17.Enabled = blStatus
    CheckBox18.Enabled = blStatus
    CheckBox19.Enabled = blStatus
    CheckBox20.Enabled = blStatus
End Sub
Private Sub GrpNOnOff(blStatus)
    TextBox1.Enabled = blStatus
    Label1.Enabled = blStatus
    Label2.Enabled = blStatus
End Sub

 

投稿日時: 17/12/14 00:59:27
投稿者: pyonpyon

baoo さん、ご丁寧にコードを提示していただきありがとうございます。
やりたい処理も私と同様でしたので早速実行させてもらいました。
baoo さんのコードでもオプションボタンを押してからチェックボックス等が表示されるまでにはやはり1呼吸ある感じで私のものと同じ感じでしたので少し納得しました。やはりPCスペックに起因しているかもしれません。
あと、baoo さん指摘の、Application.EnableEventsやApplication.ScreenUpdating、Application.Calculationの設定ですが、特別な理由がないので削除しましたら少し早くなった気がします。(^^;
 
ご親切にご教示くださりありがとうございました。