Function add_item_list(level As Long, item1 As String, item2 As String, item3 As String) As String
'====================================================================================================
' マスタシートにある項目マスタから入力規則用の配列形式の文字列を返すサブルーチン
' 重複しないリストにしたいのでDictionary型で重複除外しながら値を収集する仕様
' level:取得したい項目「中項目→1、小項目→2、欠番→3、結果→4」
' item1:大項目の値
' item2:中項目の値
' item3:小項目の値
'====================================================================================================
Dim lngRow As Long
Dim objDic As New Scripting.Dictionary
With Sheet2
' ---表の一番上から一番下までループして一致している値だけ収集する ※テーブル化した方が良いかもしれない
For lngRow = 2 To .Cells(Rows.Count, 2).End(xlUp).Row
' ---対象の項目の値が一致するかlevelより大きい場合に次のレベルとの照合をする
If .Cells(lngRow, lngCol.item1).Value = item1 Or level < 1 Then
If .Cells(lngRow, lngCol.item2).Value = item2 Or level < 2 Then
If .Cells(lngRow, lngCol.item3).Value = item3 Or level < 3 Then
'--- まだ取得していない項目なら追加する
If objDic.Exists(.Cells(lngRow, level + 2).Value) = False Then
'--- 列の位置は表に合わせて調整 ※今回はA列を空けているのでlevel+2が対象列になる
objDic.Add .Cells(lngRow, level + 2).Value, .Cells(lngRow, level + 2).Value
End If
End If
End If
End If
Next
End With
' ---結果を取得する時に該当がなかったら"-"を返すようにしておく
If level = 4 And objDic.Count = 0 Then objDic.Add "-", "-"
' --- 最後にカンマ区切りでJoinしてあげると入力規則用で使える配列形式の文字列にできる
add_item_list = Join(objDic.Keys, ",")
End Function
Option Explicit
'--- 列挙型で列番号を定めておく
Enum lngCol
item1 = 2
item2
item3
result = 6
End Enum
Private Sub Worksheet_Change(ByVal Target As Range)
'====================================================================================================
' 処理がわかりやすいようにセルに名前をつけて連動するプルダウン項目を作る
' Worksheet_Changeを発火トリガーにしてセルの値が変わったら動くプログラムにする
'====================================================================================================
'更新されたセルが名前を付けたセルと一致していたらプログラム実行する
On Error GoTo ErrLabel
Select Case Target.Address
Case Range("ITEM1").Address
'--- 大項目のセルが更新されたら中項目の入力規則を変更する
With Range("ITEM2").Validation
'--- 一旦入力規則を削除
.Delete
'--- DeleteやBackSpaceでセルがクリアされたら処理しない
If Len(Target.Value) > 0 Then
'--- 入力値の種類をリスト形式にして、リストの値はサブルーチンで生成する ※入力規則の設定は最低限にしているので他項目はお好みで
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:=xlBetween, Formula1:=add_item_list(1, Range("ITEM1").Value, Range("ITEM2").Value, Range("ITEM3").Value)
End If
End With
'--- 大項目が更新されたら中項目・小項目と結果の値をクリアする ※イベントを一時的に無効化しないと動きがおかしくなる
Application.EnableEvents = False
Range("ITEM2").ClearContents
Range("ITEM3").ClearContents
Range("ITEM3").Validation.Delete
Range("RESULT").Value = "-"
Application.EnableEvents = True
Case Range("ITEM2").Address
'--- 中項目のセルが更新されたら小項目の入力規則を変更する
With Range("ITEM3").Validation
'--- 一旦入力規則を削除
.Delete
'--- DeleteやBackSpaceでセルがクリアされたら処理しない
If Len(Target.Value) > 0 Then
'--- 入力値の種類をリスト形式にして、リストの値はサブルーチンで生成する ※入力規則の設定は最低限にしているので他項目はお好みで
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:=xlBetween, Formula1:=add_item_list(2, Range("ITEM1").Value, Range("ITEM2").Value, Range("ITEM3").Value)
End If
End With
'--- 中項目が更新されたら小項目と結果の値をクリアする ※イベントを一時的に無効化しないと動きがおかしくなる
Application.EnableEvents = False
Range("ITEM3").ClearContents
Range("RESULT").Value = "-"
Application.EnableEvents = True
Case Range("ITEM3").Address
'--- DeleteやBackSpaceでセルがクリアされた場合の処理
Range("RESULT").Value = add_item_list(4, Range("ITEM1").Value, Range("ITEM2").Value, Range("ITEM3").Value)
End Select
On Error GoTo 0
Exit Sub
ErrLabel:
Application.EnableEvents = True
MsgBox "予期せぬエラーが発生しました", vbCritical
End Sub
Function add_item_list(level As Long, item1 As String, item2 As String, item3 As String) As String
'====================================================================================================
' マスタシートにある項目マスタから入力規則用の配列形式の文字列を返すサブルーチン
' 重複しないリストにしたいのでDictionary型で重複除外しながら値を収集する仕様
' level:大項目→1、中項目→2、小項目→3
' item1:大項目の値
' item2:中項目の値
' item3:小項目の値
'====================================================================================================
Dim lngRow As Long
Dim objDic As New Scripting.Dictionary
With Sheet2
' ---表の一番上から一番下までループして一致している値だけ収集する ※テーブル化した方が良いかもしれない
For lngRow = 2 To .Cells(Rows.Count, 2).End(xlUp).Row
' ---対象の項目の値が一致するかlevelより大きい場合に次のレベルとの照合をする
If .Cells(lngRow, lngCol.item1).Value = item1 Or level < 1 Then
If .Cells(lngRow, lngCol.item2).Value = item2 Or level < 2 Then
If .Cells(lngRow, lngCol.item3).Value = item3 Or level < 3 Then
'--- まだ取得していない項目なら追加する
If objDic.Exists(.Cells(lngRow, level + 2).Value) = False Then
'--- 列の位置は表に合わせて調整 ※今回はA列を空けているのでlevel+2が対象列になる
objDic.Add .Cells(lngRow, level + 2).Value, .Cells(lngRow, level + 2).Value
End If
End If
End If
End If
Next
End With
' ---結果を取得
If level = 4 And objDic.Count = 0 Then objDic.Add "-", "-"
'--- 最後にカンマ区切りでJoinしてあげると入力規則用で使える配列形式の文字列にできる
add_item_list = Join(objDic.Keys, ",")
End Function
コメント