Excelには縦方向のフィルタ機能がありますが、横方向のフィルタがありません。
横方向のフィルタはVBA(マクロ)を使って実現できますので、紹介します。
たとえば、こんなエクセルのデータがあるとしましょう。
これは所属システムエンジニアのスキル表サンプルです。
例ではメンバーが数人ですが、100人も1000人もいたら大きなデータになります。
たとえば、円屋さんがプロジェクトから離任することになりましたという時、似たスキルセットのメンバーを代理で参加させたいとなると、大きなデータから探すのは大変ですね。
上記の表でフィルタができれば、簡単に見つけることができると思います。
一番ポピュラーな方法は、Excelのこの表をコピーして、別シートに張り付ける時に行と列を入れ替えます。そして、Excelデフォルトのオートフィルタで絞り込めばいいですね。
ですが、今回は行と列を入れ替えることなく実現するために横フィルタをVBAで作成してみます。
VBAで作成したSampleコード
色々コントロールができるようにしたいので、右図のようなユーザーフォームを作成します。
ListBox1には、選択した行に含まれる値のリストを表示させます。
CommandButton1はフィルタの実行をさせるAction処理を実装します。
CommandButton2はフィルタを解除するAction処理を実装します。
以下はVBAコードです。
Dim rowno, colno As Integer
'=================================================
'フィルタ処理
'=================================================
Private Sub CommandButton1_Click()
Dim colAlfa, compData As String
With UserForm1.ListBox1
If .ListIndex < 0 Then
.ListIndex = 0
End If
selectedvalue = .List(.ListIndex, 0)
For i = colno To Columns.Count
nowcol = Cells(1, i).Address(True, False)
colAlfa = Left(nowcol, InStr(nowcol, "$") - 1)
If Columns(colAlfa).Hidden = False Then
If TypeName(Cells(rowno, i).Value) = "Integer"
Then
compData = Trim(Str(Cells(rowno,
i).Value))
Else
compData = Cells(rowno,
i).Value
End If
If compData = selectedvalue Then
Columns(colAlfa).Hidden =
False
Else
Columns(colAlfa).Hidden =
True
End If
End If
Next i
End With
Unload UserForm1
End Sub
'=================================================
'クリア処理
'=================================================
Private Sub CommandButton2_Click()
Dim colAlfa As String
For i = 1 To Columns.Count
nowcol = Cells(1, i).Address(True, False)
colAlfa = Left(nowcol, InStr(nowcol, "$") - 1)
Columns(colAlfa).Hidden = False
Next i
Unload UserForm1
End Sub
'=================================================
'初期化処理
'=================================================
Private Sub UserForm_Initialize()
'選択行
rowno = ActiveCell.Row
'初期カラム
colno = ActiveCell.Column + 1
'リスト作成
For i = colno To Columns.Count
If UserForm1.ListBox1.ListCount = 0 Then
UserForm1.ListBox1.AddItem Cells(rowno, i).Value
Else
flg = False
For j = 0 To UserForm1.ListBox1.ListCount - 1
If Cells(rowno, i).Value = UserForm1.ListBox1.List(j)
Then
flg = True
Exit For
End If
Next
If flg = False Then UserForm1.ListBox1.AddItem Cells(rowno, i).Value
End If
Next i
End Sub
<簡単にコードを解説>
UserFrom_Initialize()
UserFormを表示直後に、Selectされている行ナンバーと、フィルタ対象のカラムの初期値(初期カラム)をグローバル変数にセットします。
初期カラムから最大カラムまでをループさせ、Selectされている行の値をListBoxに追加していきます。
この時、重複する値は追加しません。
CommandButton1_Click()
ListBoxの選択値を取得します。選択がされていない場合は、初期カラムの値を選択させます。
初期カラムから最大カラムまでをループさせ、表示カラムであれば、ListBoxの選択値と比較させます。
ListBoxの選択値と不一致ならば、カラムを非表示状態に変更します。
CommandButton2_Click()
初期カラムから最大カラムまでをループさせ、カラムを表示状態に変更します。
Sampleコードの挙動説明
1.右図の表で黄色のセルを選択した状態でマクロを実行すると、緑色の範囲の値がリストボックスに追加されます。
2.UserFormを表示し、リストから値「〇」を選択して、Filterボタンをクリックします。
3.値「〇」が含まれているカラムだけ表示され、フィルタができました。
今回は円屋メンバーでフィルタしましたので、植原メンバーがスキルが合致していそうですね。
4.さらに来舘メンバーを選択して、〇がついていない行で絞り込んでみます。
5.円屋メンバーの保有スキルのうち、来舘メンバーの未保有スキルで絞ることができます。
今回は選択した値と一致するものをフィルタするコードを作りましたが、以下のコード部分をカスタマイズすると、不一致のものや値の大小でのフィルタも可能であると思います。
If compData = selectedvalue Then
Columns(colAlfa).Hidden = False
Else
Columns(colAlfa).Hidden = True
End If