[Excel]データを絞り込んで別シートに表示する（データ数が1万件以下の場合）

夏休みの自由研究で比較的お手軽に絞り込みを行う方法を作ってみました。
スライサーを使用すれば簡単にデータを絞り込みで来ますが、データと出力機能を分けたいときには便利かと思います。

# やったこと
検索条件を指定して該当するデータを一覧で表示しました

↓実装した結果
![絞り込み動画.gif](https://qiita-image-store.s3.amazonaws.com/0/97601/a35e5884-ac1c-cc6b-4876-c31e1bcf9f2b.gif)

# サンプルデータ
[こちら](https://www.ksp-sp.com/open_data/)のデータの一部を使用しました。

- JANCD
- メーカー名
- 商品名称
- 保管場所
![商品データ1.png](https://qiita-image-store.s3.amazonaws.com/0/97601/196a49de-8204-1042-f0a0-cd8065f7405f.png)

# 実装のポイント
- 検索条件に該当するデータに印をつけます
- その後、印を探し出して表示します

# 前提
今回の方法はデータ件数が少ない場合に有用です。データ件数が多くなると少しずつ動作が遅くなります。
1万件で約2秒程度の計算が走りました。

※データ件数が多い場合の実装方法は別記事にします。

# 実装方法
## 1. スライサーによる絞り込み
### 1.1 スライサーを表示
サンプルデータをテーブルに変換しておくことでスライサーが使えるようになります。
テーブル名は「商品データ」にしておきます。
![テーブル.png](https://qiita-image-store.s3.amazonaws.com/0/97601/885f2d0a-3300-a584-cb76-97c0a1ca61ff.png)
![テーブル名.png](https://qiita-image-store.s3.amazonaws.com/0/97601/9db8a292-bbc3-2cb4-56af-a181bd2ca251.png)
![スライサー.png](https://qiita-image-store.s3.amazonaws.com/0/97601/2ca189f9-adc5-792a-ea67-46f623e2869a.png)

スライサーでメーカー名を１つ選択するとデータがフィルタリングされます。
ここで表示されているデータを出力用の表に転記すればよいわけです。
### 1.2 フィルタリングされたデータに印をつける
**[SUBTOTAL](https://support.office.com/ja-jp/article/subtotal-%E9%96%A2%E6%95%B0-7b027003-f060-4ade-9040-e478765b9939)**を使うと表示された行に印をつけられます。
商品データに「メーカー」の列を追加して下記式を入力します。

```
=SUBTOTAL(103,[@JANCD])>0
```
![メーカー式.png](https://qiita-image-store.s3.amazonaws.com/0/97601/1ea8e40d-ff6d-ead5-1e6c-f5ec4b200782.png)
表示行がTRUE、非表示行がFALSEになります。

## 2. オプションボタンによる絞り込み
### 2.1 オプションボタンを表示
開発タブのフォームコントロールからオプションボタンを複数個追加しておきます。
![ラジオボタン.png](https://qiita-image-store.s3.amazonaws.com/0/97601/3fa3da36-ab67-2788-f617-92606dc04757.png)
今回のサンプルでは9個の保管場所と「全て」がありますので合計10追加します。
また、オプションボタンの書式設定を開きリンクするセルをどこかに設定しておきます。
![オプションボタンリンクするセル.png](https://qiita-image-store.s3.amazonaws.com/0/97601/a16bd41b-785f-17ee-d47f-a99cee17ec8b.png)
リンクするセルを指定することでオプションボタンを選択したときにそのボタンの番号が指定したセルに書き込まれます。
この値をもとに保管場所を見つけます。
このとき、番号と保管場所を紐づけるテーブルが必要になりますので「見取り図データ」を作っておきます。
![見取り図データ.png](https://qiita-image-store.s3.amazonaws.com/0/97601/bf0058b2-5d5c-d145-5ee0-7a3d0a897fd2.png)

あとは[VLOOKUP](https://support.office.com/ja-jp/article/VLOOKUP-%E9%96%A2%E6%95%B0-0BBC8083-26FE-4963-8AB8-93A18AD188A1)等で番号から保管場所を拾ってきます。

```
=VLOOKUP($AF$2,見取り図データ,2,FALSE)
```
![オプションボタン_VLOOKUP.png](https://qiita-image-store.s3.amazonaws.com/0/97601/28f57937-ca04-5d1a-9d32-42b1d88aba2a.png)
これで選択中の保管場所が明らかになりました。

### 2.2 印をつける

商品データに「見取り図」の列を追加し下記式を入力します。

```
=OR([@保管場所]=検索!$AG$2,検索!$AG$2="全て")
```
![見取り図式.png](https://qiita-image-store.s3.amazonaws.com/0/97601/ef38ef29-e232-1792-8c7d-8656bad8f910.png)

## 3. キーワードによる絞り込み
### 3.1 入力欄の作成
ここは普通のセルで十分です。今回はExcel方眼紙にしたので結合セルにしていますが単一セルでも十分です。
![キーワード.png](https://qiita-image-store.s3.amazonaws.com/0/97601/69e0bd3d-ddc1-f266-21b4-6ec80e6d68a7.png)

### 3.2 印をつける
商品データに「キーワード」の列を追加し下記式を入力します。
**[FIND](https://support.office.com/ja-jp/article/FIND-%E9%96%A2%E6%95%B0%E3%80%81FINDB-%E9%96%A2%E6%95%B0-c7912941-af2a-4bdf-a553-d0d89b0a0628)**でキーワードを見つけます。商品名に含まれていたらTRUE、含まれていなかったらFALSEを返すようにします。

```
=NOT(ISERROR(FIND(検索!$C$12,[@商品名称])))
```
![キーワード式v2.png](https://qiita-image-store.s3.amazonaws.com/0/97601/797c7d9e-43a2-8c7a-2cb7-6c1a89f0ae06.png)

## 4. 検索条件全てを満たすデータの抽出
検索条件全てを満たすデータに1を付与します。それ以外は0とします。
商品データに「出力対象」の列を追加し下記式を入力します。

```
==[@メーカー]*[@見取り図]*[@キーワード]
```
![出力対象v3.png](https://qiita-image-store.s3.amazonaws.com/0/97601/2ae51cf0-3df1-955c-6700-54a99583cbeb.png)

## 5.出力対象を上から採番
出力対象を1から連番で採番します。
採番するための式はSUMでもMAXでもVLOOKUPでも何でも構いません。
この連番をキーとして検索結果を表示することになります。

```
=IF([@出力対象]=1,SUM($H$2:H2),"")
```
![出力対象キーV3.png](https://qiita-image-store.s3.amazonaws.com/0/97601/6aeb3c31-c270-93c9-8ab9-885b07cb5f17.png)

**補足：**今回、タイトルにあるように「データ数が1万件以下の場合」と制限をかけた理由がここにあります。SUMやMAXはデータ量が多くなると計算対象が増えるため指数的に計算量が増えてしまいます。1万行程度なら許容範囲ですが10万行を超えると1分以上待たされたり最悪Excelがフリーズします。
データ数が増えても計算量が変わらないようにするためには結構な工夫が必要になります。それについては後日、別の記事でまとめます。

## 6. 該当データを検索結果に表示
出力対象キーが付いたデータを表示します。
出力対象キーが1からの連番になっているのでVLOOKUPやINDEX+MATCHの関数で抽出することは容易です。
今回は出力対象キーが商品データの中で一番最後にあるためVLOOKUPが使えませんのでINDEXとMATCHで抽出します。

検索結果には作業用に隠してある数値もあるのですべて出すとこのような形です。
![出力1.png](https://qiita-image-store.s3.amazonaws.com/0/97601/497896a1-a5c1-0d4d-9b51-0a25480cf124.png)

各セルの式は以下のようになっています。
![出力2.png](https://qiita-image-store.s3.amazonaws.com/0/97601/1b5efb07-b562-2cc2-096f-50a1a1bb7576.png)

- 総ページ：一度に表示する数を10にしたので、データ数を10で割ってページ数を求めておきます。
- 現在ページ数：検索結果の右上に配置したスクロールバーとリンクしているセルを総ページ数で割ったときの余りを使って現在ページ数を表現しています。これにより最終ページまで行くと最初のページに戻ることができます。
- #：1からの連番です。ページが切り替わるごとに+10していきます。
- 対象行：商品データの出力対象キーから#のデータの位置を探しています。
- JANCD,名称,保管場所：対象行のデータを表示しています。

実際にページを切り替えたときの動作はこのようになっています。
![表示動画.gif](https://qiita-image-store.s3.amazonaws.com/0/97601/bfbf74bd-6fb2-2f4c-7363-187aa0740886.gif)


データの絞り込みから表示までは以上になります。
VBAを使わなくても関数の機能でなんとかなるものですね。

# その他
過去に似たような記事を書いてますので興味のある方はご参考ください。

- [[Excel]1万件以上のデータから条件に一致するレコードを爆速で表示する](https://qiita.com/tomikiya/items/a3ae9c3bb3abecf2a819)
- [[Excel]VLOOKUPを構造化参照+INDEX+MATCHで置き換えて保守力を上げる](https://qiita.com/tomikiya/items/da8884acdfaa12b981b0)
- [[Excel]スライサーで選択中の項目を取得する　単一選択編](https://qiita.com/tomikiya/items/a2d856a24905fbc82c54)
- [[Excel]セルをクリックしたときに他のセルの値を変える（VBA未使用）](https://qiita.com/tomikiya/items/70d419f2448ad1f438e7)