ExcelのPowerQueryで複数の列が同値か判定する

# はじめに
PowerQuery初心者です。
単純な、複数列の同値判定で色々な方法を試したため、備忘録として記事を投稿します。

# 前提
<システム環境>
- Windows OS
- Microsoft Excel 2019
本記事ではMicrosoft 365版のExcelを使用します。
Excel for Macは、PowerQueryの機能に制限があるため使用しません。

# 使用するデータと目的
下記の表を使用します。

|A  |B  |C  |
|---|---|---|
|a  |b  |c  |
|a  |a  |A  |
|A  |A  |A  |

ヘッダを除く1〜2行目がFALSE、3行目がTRUEとなる比較列を追加します。

# まずは数式と関数
PowerQueryを使う前に、まずは数式と関数で比較列を追加する例を見ます。

同値判定に比較演算子(=)を使用するとアルファベットの大文字小文字が区別されないため、ここではEXACT関数[^exact]を使用して判定しています。

## IFネスト
IFネストで作成する場合。

D2の数式 = IF(EXACT(A2,B2),IF(EXACT(A2,C2), "TRUE", "FALSE"), FALSE)

![スクリーンショット 2021-07-03 21.51.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490699/3acd53ea-e093-bbe0-584b-9d3e64d314ce.png)

## 配列数式
配列数式(CSE)で作成する場合。[^cse]

D2の数式 = IF(AND(EXACT(A2:C2,A2)), TRUE, FALSE)
* 数式はCtrl + Shift + Enterキーで確定操作する。式が{}で囲まれる。

![スクリーンショット 2021-07-05 15.14.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490699/29747dba-3481-799d-824e-013a9a0751a6.png)

## スピル [^spill]
Microsoft 365のExcelに実装されたスピルを使う場合。

D2の数式のみ = IF(EXACT(A2:A4,B2:B4),IF(EXACT(A2:A4,C2:C4), "TRUE", "FALSE"), FALSE)

![スクリーンショット 2021-07-04 22.16.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490699/d2ce08ce-32f3-d959-9b2a-b31670a06a47.png)

配列数式のように短縮できそうですが、試した範囲では実現できませんでした。

## 構造化参照
表をテーブルへ変換し、構造化参照[^structref]を使用する場合。

![スクリーンショット 2021-07-04 22.33.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490699/156491f0-b32a-ea6a-1112-547aad29ffe3.png)

テーブルの名前に「テーブル1」を付けています。

D2の数式 =IF(AND(EXACT(テーブル1[@[A]:[C]],[@A])),TRUE,FALSE)

![スクリーンショット 2021-07-04 22.45.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490699/b70d05fa-2c4d-6a56-c9dc-274223e0aab3.png)

# PowerQuery
比較列をPowerQueryで作成してみます。

## クエリ作成
表をテーブルへ変換して、テーブルの名前に「テーブル2」を付けます。

テーブルを選択した状態で「データの取得」→「その他のデータソースから」→「テーブルまたは範囲から」を実行し、クエリを作成します。

![スクリーンショット 2021-07-03 16.16.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490699/ab0202b7-8ead-45f8-544c-541dc558305c.png)

データはテキストのみのため、テキスト型としてPowerQueryに認識されています。
もし数値も含まれていた場合は、any型として認識されます。

![スクリーンショット 2021-07-04 23.03.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490699/a30b4ee8-67d7-ae9b-7053-9b0f09ec17ae.png)

「列の追加」→「カスタム列」からカスタム列を新規に追加し、IFネストで式を作成します。

```
if [A]=[B] then
  if [A]=[C] then
    true
  else
    false
else
  false
```

![スクリーンショット 2021-07-03 16.36.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490699/f3fd991a-3ae2-60c6-4f88-ae006dadbcc8.png)

結果は画像の通り、アルファベットの大文字小文字が別個の値として認識されています。

![スクリーンショット 2021-07-04 23.20.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490699/faff1eb7-a1d7-d26d-e326-8c3523d3002d.png)

記号=は、PowerQueryのM言語[^mlang]では等値演算子[^eqop]として定義されています。

余談ですが、「カスタム列」ではなく「条件列」の作成でも同様の結果を得られます。

![スクリーンショット 2021-07-04 23.34.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490699/ad77546f-7b62-ed8f-69e5-24546e140e40.png)

# クエリの改良
IFネストは、比較対象の列が増えるとif-expressionも増えるため、改良の余地があります。
EXACT関数の範囲指定のように短縮ができれば良いのですが、探した範囲では見当たりませんでした。

このため、関数とListを使って作成します。

カスタム列を新規に追加し、下記式を作成します。

```
((s) => List.MatchesAll({[A],[B],[C]}, each _ = s))([A])
```
![スクリーンショット 2021-07-04 23.52.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490699/5f1a28ae-d512-d4bd-4085-dc0513fbd343.png)

範囲指定は出来ませんが、データの列が増えた場合はListである{}内の項目を増やすだけで対応できます。

## コメントより
本記事のコメント欄に下記の方法をご紹介いただきました。
・Record.ToListを使って全ての列を指定する。

![スクリーンショット 2021-07-06 22.14.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490699/c6b2bd4b-f350-6097-b412-fccbbd867f2a.png)


他にも、良い方法があればシェア頂ければありがたいです。

# おわりに
バージョンを重ねるに連れExcelの機能も増えており、単純な列の同値判定だけでも、過去より書き方のバリエーションが増えていました。
VBAやカスタム関数を含めると更にバリエーションが増えそうですが、PowerQueryで複数列の同値判定はこの方法だと言うものが、見つかればいいなと思っております。

# 参考
[^mlang]: Power Query Formula Languageが正式名称です。https://qiita.com/spumoni/items/9b89555dfd8b550c177f
[^spill]: https://support.microsoft.com/ja-jp/office/%E5%8B%95%E7%9A%84%E9%85%8D%E5%88%97%E6%95%B0%E5%BC%8F%E3%81%A8%E3%80%81%E3%81%93%E3%81%BC%E3%82%8C%E3%81%9F%E9%85%8D%E5%88%97%E5%8B%95%E4%BD%9C-205c6b06-03ba-4151-89a1-87a7eb36e531
[^structref]: https://support.microsoft.com/ja-jp/office/excel-%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E3%81%A7%E3%81%AE%E6%A7%8B%E9%80%A0%E5%8C%96%E5%8F%82%E7%85%A7%E3%81%AE%E4%BD%BF%E3%81%84%E6%96%B9-f5ed2452-2337-4f71-bed3-c8ae6d2b276e
[^ifand]: https://nyanto.jimdofree.com/%EF%BD%B4%EF%BD%B8%EF%BD%BE%EF%BE%99%E9%96%A2%E6%95%B0-%E5%95%8F%E9%A1%8C%E8%A7%A3%E6%B1%BA/if%E9%96%A2%E6%95%B0%E3%81%AE%E8%AB%96%E7%90%86%E5%BC%8F%E3%81%A7%E8%A4%87%E6%95%B0%E5%88%97%E5%85%A8%E3%81%A6%E3%81%8C%E4%B8%80%E8%87%B4%E3%81%AE%E6%9D%A1%E4%BB%B6%E3%82%92%E7%B0%A1%E5%8D%98%E3%81%AB%E6%8C%87%E5%AE%9A%E3%81%99%E3%82%8B%E3%83%86%E3%82%AF%E3%83%8B%E3%83%83%E3%82%AF/
[^exact]: https://office-hack.com/excel/exact/
[^eqop]: https://docs.microsoft.com/ja-jp/powerquery-m/m-spec-operators#equality-operators
[^cse]: https://nyanto.jimdofree.com/%EF%BD%B4%EF%BD%B8%EF%BD%BE%EF%BE%99%E9%96%A2%E6%95%B0-%E5%95%8F%E9%A1%8C%E8%A7%A3%E6%B1%BA/if%E9%96%A2%E6%95%B0%E3%81%AE%E8%AB%96%E7%90%86%E5%BC%8F%E3%81%A7%E8%A4%87%E6%95%B0%E5%88%97%E5%85%A8%E3%81%A6%E3%81%8C%E4%B8%80%E8%87%B4%E3%81%AE%E6%9D%A1%E4%BB%B6%E3%82%92%E7%B0%A1%E5%8D%98%E3%81%AB%E6%8C%87%E5%AE%9A%E3%81%99%E3%82%8B%E3%83%86%E3%82%AF%E3%83%8B%E3%83%83%E3%82%AF/