UNIQUE 関数


ここで解説する UNIQUE関数 は、Office InsiderのProPlusに追加された関数です。執筆時点(2019年8月)で、製品版のExcelにはまだ実装されていません。ただし、Microsoftがこの関数を実装すると公にアナウンスしたのは、2018年の11月です。おそらく現在は、さまざまな動作検証をしたり、細かい修正などを行っているところでしょうけど、近い将来Excelに実装されるのは間違いありません。そうなったら、もうExcelの使い方が大きく変わります。そんな画期的な関数です。なお、Office Insiderに関しては、ご自身でググってください。また、この関数では「スピル」という機能が使われています。スピルに関しては「Excel 2016レビュー[Excelの使い方が激変する「スピル」]」をご覧ください。

UNIQUE関数

重複しないデータ(ユニークデータ)を作成する関数です。この関数も、実務では役立ちそうですね。

使い方は簡単ですが、ちょっとクセのある関数です。引数は、次のように考えましょう。

引数「範囲」には、元データの範囲を指定します。複数列や複数行も指定できますが、一般的には1列や1行を指定することが多いでしょう。

引数「方向」は、元データが"行方向"に入力されているか、"列方向"に入力されているかを指定します。一般的な"行方向"のときはFALSEを指定し、"列方向"に入力されているときはTRUEを指定します。引数「方向」を省略するとFALSEを指定したとみなされます。

分かりにくい引数が「1回のみ」です。この引数、正式には「回数」という名前ですが、しばらく試してみるまで意味が分かりませんでした。「1回のみ」という表現も、決して分かりやすいとは思いませんが、実際の動作で理解してください。

たとえば、
田中
広瀬
桜井
桜井
というデータがあったとします。

この4件のデータで、重複しているデータを1件と考えれば、重複しないデータ(ユニークデータ)は、全部で3件です。こういう使い方をするときは、引数「1回のみ」にFALSEを指定します。

この4件のデータで、1回だけ登場しているのは、"田中"と"広瀬"の2つです。"桜井"は2回登場しています。そのように、"1回だけ登場する"データだけのリストを作りたいときは、引数「1回のみ」にTRUEを指定します。

複数列を指定したとき

引数「範囲」に複数列を指定したときは、それぞれの列を合わせたデータで判断します。

UNIQUE関数の注意点

UNIQUE関数には、いろいろなクセがあります。使用するときには、あれこれと工夫が必要になるかもしれません。たとえば、元データにブランクセルが含まれている場合です。

ブランクセルは0と表示されます。元データが文字列だったら、次のようにして0を空欄にすることも可能ですが、

それだけで済む話ではありません。元データが数値だったら、結果がすべて文字列になってしまいます。

あるいは、次のようなときにも困ります。

それに、そもそも重複しないユニークデータで空欄は不要です。UNIQUE関数に「ブランクセルは除外する」みたいなオプションがあればいいのに。どうしても空欄を除いたユニークデータが欲しいのなら、たとえば次のようにFILTER関数でブランクセルを取り除いてからUNIQUE関数に渡します。

あと、細かい話ですが、日付は書式を引き継ぎません。

もちろん、動的配列範囲に書式を設定すればいいのですが、

新しいデータが追加されたら、また書式設定しなければなりません。

C列全体に書式設定すればいいのですけど、ちょっと乱暴ですし、発想が美しくありませんね。

あとこれは、仕様と言われてしまえばそれまでなんですけど。半角/全角や大文字/小文字は同一視されます。

最後に、VBAからWorksheetFunctionでUNIQUE関数を呼び出すときの注意です。

この[名前]列でユニークデータを作成し、それを何かに使おうと、次のように書くとエラーになります。

Sub Macro1()
    Dim A, i As Long
    A = WorksheetFunction.Unique(Range("テーブル1[名前]"))
    For i = LBound(A) To UBound(A)
        Debug.Print A(i)
    Next i
End Sub

UNIQUE関数(だけでなく、SORT関数もFILTER関数もですが)は、1次元配列ではなくセル範囲を返します。セル範囲は2次元配列です。ですから、ここは次のようにしなければなりません。

Sub Macro1()
    Dim A, i As Long
    A = WorksheetFunction.Unique(Range("テーブル1[名前]"))
    For i = LBound(A) To UBound(A)
        Debug.Print A(i, 1)
    Next i
End Sub

あるいはどうしても1次元配列の結果が欲しいのでしたら、UNIQUE関数の結果をTRANSPOSE関数で変換しましょう。この考え方は「VBA Tips「配列をセルに代入する」」をご覧ください。かなり昔に書いたコンテンツですけどw

Sub Macro1()
    Dim A, i As Long
    With WorksheetFunction
        A = .Transpose(.Unique(Range("テーブル1[名前]")))
        For i = LBound(A) To UBound(A)
            Debug.Print A(i)
        Next i
    End With
End Sub