【VBA】種目別に自動採番(別解)
コロ子さん(id:SNegishi)のところで、自動採番処理をやっているのを見て、ちょっと気がついた点をコメントしました。
すぐに修正版がアップされて「おぉ~、仕事はえぇなぁ」と感心していました。
koroko.hatenablog.com
そんな中で、
「Worksheet_SelectionChangeイベントで変更前の値を保持しておいく」のところを静的変数Staticを使おうとしたけど、モジュール変数として使う事がでなかった。
「プローシシャーの外では使えません」のエラーメッセージが出た。
結局上手くできず、いつもの仮置き方式。
仮置き方式でないなら、どのように作るものなのでしょうか・・・?
多分、Worksheet_SelectionChangeの中にStatic変数を置いちゃったんでしょうね。
そのままでは、他のプロシージャからは、そのStatic変数にはアクセス出来ないので、
もう少し工夫が必要ですね。
私の場合、Static変数はほとんど使うことがなくて、大抵の場合、モジュールレベルのPrivate変数で処理しちゃいます。
下記のソースの vPrevValue_ がそれに当たります。
そいつに、Worksheet_SelectionChangeイベントで、必要な条件に一致した時に値を突っ込みます。
あと、Application.EnableEvents で処理中のイベントを抑止してあげないと、不要な処理が走るようです。
あと、先頭部分で処理不要なら、即 Exit Sub するように
以下の理由により、変えてあります。
- それ以降、何も処理が無いのが明確になる
- If でくくった場合、「Ifの後に何か処理があるかもしれない」ので確認が必要。プロシージャが長いほど、スクロールが面倒くさい(私の場合)
- If によるインデントが不要になる
Private変数を使って処理したソースがこれ
Private vPrevValue_ As Variant Private Sub Worksheet_Change(ByVal Target As Range) Dim buf As Range If Target.Column <> 1 Then '1列目(A列)以外でイベントが発生した場合は、処理を抜ける Exit Sub ElseIf vPrevValue_ = Target.Value Then 'データが変わっていなければ、処理を抜ける Exit Sub End If Application.ScreenUpdating = False Application.EnableEvents = False '初期化 Range("B" & Target.Row).Value = "" 'A列でフィルタ Range("A1").AutoFilter Field:=1, Criteria1:=Range("A" & Target.Row).Value 'アクティブセル領域の可視範囲を取得 Set buf = Range("A1").CurrentRegion.Columns(2).SpecialCells(xlCellTypeVisible) '最大値+1を取得 Range("B" & Target.Row).Value = Application.WorksheetFunction.Max(buf) + 1 'フィルター条件解除 ActiveSheet.ShowAllData Application.EnableEvents = True Application.ScreenUpdating = True End Sub Private Sub Worksheet_SelectionChange(ByVal Target As Range) '複数セルを選択している中に、未入力セルが含まれていても処理できるように 'Target.Count = 1 'は含めない ' If Target.Column = 1 And Target.Count = 1 Then If Target.Column = 1 Then '複数のセルが選択されている場合、Target.Valueを代入すると、 'vPrevValueは配列になるのでActiveCellを指定する ' vPrevValue_ = Target.Value vPrevValue_ = ActiveCell.Value End If End Sub