スピンボタンで条件付き書式のPriorityを変更する

昨日は条件付き書式のPriorityをマクロで指定し、そのときの実際の挙動を実験的に確認してみた。
infoment.hatenablog.com
本来は仕様書で確認すべきなのだろうが、今回は(も)手探りで、ちょこっとずつ前進と後退を繰り返してきた。

いよいよ今日は、スピンボタンの上下で、選択した条件式に紐づく条件付き書式のPriorityを変化させることに挑戦する。
f:id:Infoment:20181227231149p:plain

今回の作戦は、こうだ。

  1. スピンボタンを設置する。
  2. スピンボタンを押すごとに、リストを更新する仕様とする。
    そのために、ユーザーフォーム初期化時にリストをクリアすることとする。
  3. スピンボタンを押した際の処理を追加する。

1.スピンボタンを設置する。

↓ 設置した。
f:id:Infoment:20181227231444p:plain
大きすぎず、小さすぎず。個人的には、これぐらいが丁度いい。

2.リストを更新する仕様に変更。

変更したのは、この2点。

  1. 変数FCは他でも使用するので、モジュールレベル変数に変更。
    (つまり今回、下記コードから変数宣言の一行が消えている)。
  2. ListBox1.Clearの一文を追加。
Private Sub UserForm_Initialize()
    Dim seq() As Variant
    ReDim seq(1 To ActiveSheet.Cells.FormatConditions.Count, 1 To 3)
    Dim i As Long
    For i = 1 To UBound(seq)
        Set FC = ActiveSheet.Cells.FormatConditions(i)
            seq(i, 1) = FC.AppliesTo.Address
            seq(i, 2) = FC.Formula1
            seq(i, 3) = FC.Priority
    Next
    ListBox1.Clear
    ListBox1.List = seq
End Sub

3.スピンボタンを押した際の処理を追加

昨夜の試みどおり、まず並び替え後のPriority再設定用サブプロシージャを作成。

Private Sub ResetPriority()
    Dim i As Long
    i = 1
    For Each FC In ActiveSheet.Cells.FormatConditions
        FC.Priority = i
        i = i + 1
    Next
End Sub

スピンボタンの上と下を押したときの挙動で、同じようなサブプロシージャを二つ作るのは忍びない。そこで、共通のサブプロシージャを一つ作成することにした。

まず引数用に、列挙型を準備する。

Enum SpinDirection
    mySpinUp = 1
    mySpinDown = -1
End Enum


スピンボタンの、上を押したときのイベントがこちら。

Private Sub SpinButton1_SpinUp()
    Call Spinbutton1_Spin(SpinDirection.mySpinUp)
End Sub


スピンボタンの、下を押したときのイベントがこちら。

Private Sub SpinButton1_SpinDown()
    Call Spinbutton1_Spin(SpinDirection.mySpinDown)
End Sub


今回の肝となる、Priorityの設定部分がこちら。
ややこしいので、解説用に、いつもよりコメントを増やしている。

Private Sub Spinbutton1_Spin(Optional spin_index As Long = 1)

    ' 選ばれた項目が何番目かを取得して、何番目の条件付き書式の
    ' Priorityを変更するか決定する。
    ' リストボックス(0始まり)とコレクション(1始まり)の
    ' 違いから、i+1としている。
    Dim myIndex As Long
    Dim i As Long
        For i = 0 To ListBox1.ListCount - 1
            If ListBox1.Selected(i) = True Then
                myIndex = i + 1
                Exit For
            End If
        Next

    ' 未選択の場合、ここで処理終了。
        If myIndex = 0 Then Exit Sub
        
    ' リスト範囲からのはみだし防止。
    Select Case myIndex
        ' リストの一番上が選択されている場合、↑の押下無効。
        Case 1
            If spin_index = SpinDirection.mySpinUp Then Exit Sub
        ' リストの一番下が選択されている場合、↓の押下無効。
        Case ListBox1.ListCount
            If spin_index = SpinDirection.mySpinDown Then Exit Sub
    End Select
    
    ' Priorityを変更する条件付き書式を、変数FCにセット。
    ' Priorityを+1することは出来ないようなので、下に下げたい場合は、
    ' 一つ下の条件付き書式を選択したうえで、それを一つ上にあげている。
    Select Case spin_index
        Case SpinDirection.mySpinUp
            Set FC = ActiveSheet.Cells.FormatConditions(myIndex)
        Case SpinDirection.mySpinDown
            Set FC = ActiveSheet.Cells.FormatConditions(myIndex + 1)
    End Select
    
    ' Priorityの変更。
    FC.Priority = FC.Priority - 1
    
    ' 全体のPriorityの再設定(欠番等防止のため)。
    Call ResetPriority
    
    ' リストの更新。
    Call UserForm_Initialize
    
        ' 先ほど動かした項目を再選択。
        ListBox1.Selected(myIndex - spin_index - 1) = True
    
End Sub

結果

Priorityの変更がどのように影響するか、シートを見ながら操作することが出来た。
f:id:Infoment:20181227234114g:plain

一応イメージどおりのものが出来た(野望達成)。ただし、実務における有効性は未知数だ。


実際に使って、ある程度洗練されてきたら、こちらで紹介するかもしれません。

参考まで。