web-dev-qa-db-ja.com

数式のみを使用してExcelで一意の値を取得する

Excelで一意の値のリストを数式で「計算」する方法を知っていますか?

例:範囲に値が含まれる"red""blue""red""green"、- "blue""black"
そして結果として欲しい"red"blue""green""black" +やがて2他の空白セル。

インデックスと組み合わせてSMALLまたはLARGEを使用して計算済みの並べ替えられたリストを取得する方法を既に見つけましたが、VBAを使用せずにこの計算済みの並べ替えも行いたいです。

73
Patrick Honorez

これは古いものであり、いくつかの解決策がありますが、私が遭遇した他のどのものよりも短くて単純な式を思い付きました。

色リストにColors(A2:A7)という名前を付けました。array formula put in cell C2 is this(fixed):

=IFERROR(INDEX(Colors,MATCH(SUM(COUNTIF(C$1:C1,Colors)),COUNTIF(Colors,"<"&Colors),0)),"")

Ctrl+Shift+Enterを使用してC2に式を入力し、C2をC3:C7にコピーします。

サンプルデータ{"赤"の説明; "青"; "赤"; "緑"; "青"; "黒"}:

  1. COUNTIF(Colors,"<"&Colors)は、データ{4; 1; 4; 3; 1; 0}の各アイテムよりも小さい値のカウントを持つ配列(#1)を返します(黒= 0アイテム、青= 1アイテム、赤= 4アイテム)。これは、各アイテムのsort valueに変換できます。
  2. COUNTIF(C$1:C...,Colors)は、並べ替えられた結果に既にあるデータ項目ごとに1の配列(#2)を返します。 C2では{0; 0; 0; 0; 0; 0}を返し、C3では{0; 0; 0; 0; 0; 1}を返します。これは、「黒」がソートの最初でデータの最後であるためです。 C4 {0; 1; 0; 0; 1; 1}では、「黒」を示し、「青」の出現はすべてすでに存在します。
  3. SUMは、すでに存在する小さい値の出現をすべてカウントすることで、k-thソート値を返します(配列#2の合計)。
  4. MATCHは、k番目のソート値の最初のインデックス(配列#1のインデックス)を見つけます。
  5. IFERRORは、ソートされた一意のリストが完成したときに、一番下のセルで#N/Aエラーを非表示にするためのものです。

あなたが持っているユニークなアイテムの数を知るために、あなたはこれを使うことができます正規式

=SUM(IF(FREQUENCY(COUNTIF(Colors,"<"&Colors),COUNTIF(Colors,"<"&Colors)),1))
28
dePatinkin

わかりました、2つのアイデアがあります。うまくいけば、そのうちの1つがあなたが行く必要がある場所にあなたを連れて行くでしょう。最初のものは、式としてこれを行う要求を無視することに注意してください。その解決策はきれいではないからです。簡単な方法が本当にうまくいかないことを確認しました; ^)。

高度なフィルターコマンドを使用する

  1. リストを選択します(または、リストにヘッダーが含まれているかどうかがExcelにわからないというダイアログが表示された場合は、リスト内の任意の場所に選択を置き、[OK]をクリックします)
  2. データ/高度なフィルターを選択
  3. [リストのフィルタリング、インプレース]または[別の場所にコピー]を選択します
  4. 「一意のレコードのみ」をクリックします
  5. OKをクリック
  6. できました。固有のリストは、所定の場所または新しい場所に作成されます。このアクションを記録して、これを行う1行のVBAスクリプトを作成し、それを他の状況で機能するように一般化することができることに注意してください(たとえば、上記の手動手順なし)。

数式の使用(Locksfreeソリューションに基づいて、穴のないリストを作成していることに注意してください)

このソリューションは、次の注意事項で機能します。

  • リストはソートする必要があります(昇順または降順は関係ありません)。実際には、要件は実際にはすべての同様のアイテムが連続している必要があるためです。しかし、ソートはその状態に到達する最も簡単な方法です。
    • 3つの新しい列が必要です(計算用の2つの新しい列と新しいリスト用の1つの新しい列)。 2番目と3番目の列は組み合わせることができますが、読者への演習として残しておきます。

      ソリューションの概要は次のとおりです。

      1. リスト内の各アイテムについて、その上の重複の数を計算します。
      2. 一意のリスト内の各場所について、次の一意のアイテムのインデックスを計算します。
      3. 最後に、インデックスを使用して、一意のアイテムのみを含む新しいリストを作成します。

      そして、ここにステップバイステップの例があります:

      1. 新しいスプレッドシートを開く
      2. A1:a6に、元の質問で与えられた例を入力します( "red"、 "blue"、 "red"、 "green"、 "blue"、 "black")
      3. リストを並べ替える:リストに選択を入れて、並べ替えコマンドを選択します。
      4. 列Bで、重複を計算します:
        1. B1に「= IF(COUNTIF($ A $ 1:A1、A1)= 1,0、COUNTIF(A1:$ A $ 6、A1))」と入力します。セル参照の「$」は、次のステップ(列の残りの部分にデータを取り込む)をはるかに簡単にするため、非常に重要です。 「$」は絶対参照を示し、セルの内容がコピー/貼り付けされたときに参照が更新されないようにします(更新される相対参照とは対照的です)。
        2. スマートコピーを使用して、列Bの残りにデータを入力します。B1を選択します。選択範囲の右下隅にある黒い四角の上にマウスを移動します。クリックしてリストの一番下までドラッグします(B6)。リリースすると、相対参照が更新された数式がB2:B6にコピーされます。
        3. B1:B6の値は「0,0,1,0,0,1」になります。 「1」エントリは重複を示していることに注意してください。
      5. 列Cで、一意のアイテムのインデックスを作成します:
        1. C1に「= Row()」と入力します。本当に必要なのはC1 = 1だけですが、Row()を使用すると、リストが行1で始まっていなくてもこのソリューションが機能します。
        2. C2に「= IF(C1 + 1 <= ROW($ B $ 6)、C1 + 1 + INDEX($ B $ 1:$ B $ 6、C1 + 1)、C1 + 1)」と入力します。 「if」は、インデックスがリストの最後に到達したときに#REFの生成を停止するために使用されています。
        3. スマートコピーを使用してC3:C6を設定します。
        4. C1:C6の値は「1,2,4,5,7,8」でなければなりません
      6. 列Dで、新しい一意のリストを作成します。
        1. D1に「= IF(C1 <= ROW($ A $ 6)、INDEX($ A $ 1:$ A $ 6、C1)、 "")」と入力します。また、インデックスがリストの末尾を超えたときに#REFケースを停止するために「if」が使用されています。
        2. スマートコピーを使用してD2:D6を設定します。
        3. D1:D6の値は、「黒」、「青」、「緑」、「赤」、「」、「」になります。

      お役に立てれば....

  • 53
    Drew Sherman

    溶液

    VBAで関数を作成したので、簡単にこれを行うことができます。
    このチュートリアル でわかるように、VBAコードモジュール(マクロ)を作成します。

    1. 押す Alt+F11
    2. ModuleInsertをクリックします。
    3. コードを貼り付けます。
    4. ファイル形式がマクロに適していないとExcelが言った場合は、Excel Macro-EnabledSave Asとして保存します。

    ソースコード

    Function listUnique(rng As Range) As Variant
        Dim row As Range
        Dim elements() As String
        Dim elementSize As Integer
        Dim newElement As Boolean
        Dim i As Integer
        Dim distance As Integer
        Dim result As String
    
        elementSize = 0
        newElement = True
    
        For Each row In rng.Rows
            If row.Value <> "" Then
                newElement = True
                For i = 1 To elementSize Step 1
                    If elements(i - 1) = row.Value Then
                        newElement = False
                    End If
                Next i
                If newElement Then
                    elementSize = elementSize + 1
                    ReDim Preserve elements(elementSize - 1)
                    elements(elementSize - 1) = row.Value
                End If
            End If
        Next
    
        distance = Range(Application.Caller.Address).row - rng.row
    
        If distance < elementSize Then
            result = elements(distance)
            listUnique = result
        Else
            listUnique = ""
        End If
    End Function
    

    使用法

    セルに=listUnique(range)と入力するだけです。唯一のパラメーターはrangeで、これは通常のExcelの範囲です。例:A$1:A$28またはH$8:H$30

    条件

    • rangeは列でなければなりません。
    • 関数を呼び出す最初のセルは、rangeが始まる同じ行になければなりません。

    レギュラーケース

    1. データを入力して関数を呼び出します。
      Enter data and call function
    2. それを成長させます。
      Grow it
    3. ほら.
      Voilà

    空のセルケース

    空のセルが含まれる列で機能します。また、前の例の「2. Grow it」の部分で行ったように、セルを出力しないはずの場所に(関数を呼び出して)オーバーワインドしても、関数は(エラーではなく)何も出力しません。

    Empty cell case

    22
    totymedli

    ラウンドアバウトの方法は、ExcelスプレッドシートをGoogleスプレッドシートにロードし、GoogleのUNIQUE(範囲)関数を使用して(希望どおりに機能する)、GoogleスプレッドシートをExcel形式に保存し直すことです。

    これはExcelユーザーにとって実行可能なソリューションではないことを認めますが、このアプローチは機能を必要とし、Googleスプレッドシートを使用できる人にとっては便利です。

    17
    yoyo

    ソートされた一意の値を取得する場合でも、式を使用して実行できます。これは使用できるオプションです。

    =INDEX($A$2:$A$18,MATCH(SUM(COUNTIF($A$2:$A$18,C$1:C1)),COUNTIF($A$2:$A$18,"<" &$A$2:$A$18),0))
    

    範囲データ:A2:A18

    セルC2の数式

    これは配列式です

    3
    new bie

    その非常に古い質問に気づきましたが、人々はまだユニークなアイテムを抽出するための式を使用するのに苦労しているようです。ここに、それらの値を返すソリューションがあります。

    列A2:A7に「赤」、「青」、「赤」、「緑」、「青」、「黒」があるとします

    次に、これを配列式としてB2に入れ、=IFERROR(INDEX(A$2:A$7;SMALL(IF(FREQUENCY(MATCH(A$2:A$7;A$2:A$7;0);ROW(INDIRECT("1:"&COUNTA(A$2:A$7))));ROW(INDIRECT("1:"&COUNTA(A$2:A$7)));"");ROW(A1)));"")をコピーします

    次に、このようになります。 enter image description here

    3
    Jimmy

    B2セルでこの式を試してください

    =IFERROR(INDEX($A$2:$A$7,MATCH(0,COUNTIF(B$1:$B1,$A$2:$A$7),0),1),"")
    

    F2をクリックしてCtrl + Shift + Enterを押した後

    enter image description here

    3
    Hariharan G R

    COUNTIFを使用して、範囲内の値の出現回数を取得できます。そのため、値がA3の場合、範囲はA1:A6であり、次の列ではIF(EXACT(COUNTIF(A3:$ A $ 6、A3)、1)、A3、 "")を使用します。 A4の場合、IF(EXACT(COUNTIF(A4:$ A $ 6、A3)、1)、A4、 "")

    これにより、すべての一意の値が重複しない列が得られます

    2
    Locksfree

    列Aには単一の一意のインスタンスを検索する値が含まれており、次の式を使用した見出し行があるとします。予測できない行数でスケーリングしたい場合は、A772(私のデータが終了した場所)を= ADDRESS(COUNTA(A:A)、1)に置き換えることができます。

    = IF(COUNTIF(A5:$ A $ 772、A5)= 1、A5、 "")

    これにより、列の各値の最後のインスタンスに一意の値が表示され、並べ替えは行われません。絶対数が不足していることを利用して、カウントするデータの「スライディングウィンドウ」を減らします。縮小ウィンドウのcountifが1に等しい場合、その行は列のその値の最後のインスタンスです。

    2
    Geoff Still

    ピボットテーブルに頼ることは、数式のみを使用してとしてカウントされない場合がありますが、これまでの他のほとんどの提案よりも実用的と思われます。

    SO1429899 example

    1
    pnuts

    Excelファイルで使用するものを以下に貼り付けました。これにより、範囲L11:L300から一意の値が取得され、V列以降のV11以降に入力されます。この場合、v11にこの式があり、それを下にドラッグしてすべての一意の値を取得します。

    =INDEX(L$11:L$300,MATCH(0,COUNTIF(V$10:V10,L$11:L$300),0))
    

    または

    =INDEX(L$11:L$300,MATCH(,COUNTIF(V$10:V10,L$11:L$300),))
    

    これは配列式です

    1
    user3404344

    この方法でもできます。

    次の名前付き範囲を作成します。

    nList = the list of original values
    nRow = ROW(nList)-ROW(OFFSET(nList,0,0,1,1))+1
    nUnique = IF(COUNTIF(OFFSET(nList,nRow,0),nList)=0,COUNTIF(nList, "<"&nList),"")
    

    これらの3つの名前付き範囲を使用すると、以下の式で一意の値の順序付きリストを生成できます。昇順で並べ替えられます。

    IFERROR(INDEX(nList,MATCH(SMALL(nUnique,ROW()-?),nUnique,0)),"")
    

    「?」を一意の順序付きリストの最初の要素のすぐ上のセルの行番号に置き換える必要があります。キャラクター。

    例えば。一意の順序付きリストがセルB5で始まる場合、式は次のようになります。

    IFERROR(INDEX(nList,MATCH(SMALL(nUnique,ROW()-4),nUnique,0)),"")
    
    1
    dm64

    このソリューションがまだ登場していないことに驚いています。一番簡単だと思う

    データに見出しを付けて、動的な名前付き範囲に入れます(つまり、データがcol Aにある場合)

    =OFFSET($A$2,0,0,COUNTA($A:$A),1)
    

    次に、ピボットテーブルを作成して、ソースを名前付き範囲にします。

    見出しを行セクションに配置するだけで、一意の値が得られます。組み込みの機能で好きなように並べ替えることができます。

    1
    CallumDA

    Drew Shermanのソリューションは非常に優れていますが、リストは連続している必要があります(手動でソートすることを提案しますが、それは私には受け入れられません)。 Guitarthrowerのソリューションは、アイテムの数が多く、元のリストの順序を尊重しない場合、少し遅くなります。つまり、ソートされたリストを出力します。

    アイテムの元の順序(別の列の日付で並べ替えられた)が必要でした。さらに、アイテムが重複している場合だけでなく、さまざまな理由で最終リストからアイテムを除外したかったのです。

    私の解決策は、ドリュー・シャーマンの解決策の改善です。同様に、このソリューションでは中間計算に2つの列を使用します。

    列A:

    重複する可能性のあるリスト、およびフィルタリングしたいブランク。例としてA11:A1100間隔に配置します。これは、Drew Shermanのソリューションを最初の行で開始されない状況に移行するのに問題があったためです。

    列B:

    この式は、この行の値が有効な場合(重複していない値が含まれる場合)0を出力します。最初のIF、またはさらに別の外部IFに必要な他の除外条件を追加できることに注意してください。

    =IF(ISBLANK(A11);1;IF(COUNTIF($A$11:A11;A11)=1;0;COUNTIF($A11:A$1100;A11)))
    

    スマートコピーを使用して列に入力します。

    列C:

    最初の行には、最初の有効な行があります。

    =MATCH(0;B11:B1100;0)
    

    その位置から、次の式で次の有効な値を検索します。

    =C11+MATCH(0;OFFSET($B$11:$B$1100;C11;0);0)
    

    2行目に入力し、スマートコピーを使用して残りの列を埋めます。この式は、ポイントする一意の要素がなくなったときに#N/Dエラーを出力します。次のコラムでこれを活用します。

    列D:

    ここで、列Cが指す値を取得する必要があります。

    =IFERROR(INDEX($A$11:$A$1100; C11); "")
    

    スマートコピーを使用して列に入力します。これは出力固有リストです。

    1
    ReneSac

    複数の行と列の値に対して機能するソリューションの場合、次の式が非常に便利であることがわかりました http://www.get-digital-help.com/2009/03/16/unique-values- from-multiple-columns-using-array-formulas / get-digital.help.comのオスカーは、ステップバイステップで視覚化された例で説明しています。

    1)値の範囲にラベルtbl_textを付けます

    2)この場合、セルB13に次の配列数式をCTRL + SHIFT + ENTERで適用します。 $ B $ 12:B12を変更して、この数式を入力するセルの上のセルを参照します。

        =INDEX(tbl_text, MIN(IF(COUNTIF($B$12:B12, tbl_text)=0, ROW(tbl_text)-MIN(ROW(tbl_text))+1)), MATCH(0, COUNTIF($B$12:B12, INDEX(tbl_text, MIN(IF(COUNTIF($B$12:B12, tbl_text)=0, ROW(tbl_text)-MIN(ROW(tbl_text))+1)), , 1)), 0), 1)
    

    3)N/Aが表示されるまでコピー/ドラッグします。

    0
    Arthur Yip

    すべてのデータを同じ列に配置し、次の式を使用する場合式の例:=IF(C105=C104,"Duplicate","Not a Duplicate")

    手順

    1. データを並べ替える
    2. 数式の列を追加
    3. セルがその上のセルと等しいかどうかを確認します
    4. 次に、Not a Duplicateをフィルタリングします
    5. オプション:数式列で計算されたデータをコピーし、値としてのみ貼り付けます(データの削除を開始した場合、エラーが発生しなくなります
    6. 注/警告:これは、最初にデータをソートした場合にのみ機能します

    数式の例:=IF(C105=C104,"Duplicate","Not a Duplicate")

    0
    Joseph A

    最適化されたVBScriptソリューション

    Totymedliのコードを使用しましたが、大きな範囲を使用すると(他の人が指摘したように)動きが取れなくなるので、彼のコードを少し最適化しました。 VBScriptを使用して一意の値を取得することに興味があるが、更新時にtotymedliのコードが遅い場合は、これを試してください。

        Function listUnique(rng As Range) As Variant
            Dim val As String
            Dim elements() As String
            Dim elementSize As Integer
            Dim newElement As Boolean
            Dim i As Integer
            Dim distance As Integer
            Dim allocationChunk As Integer
            Dim uniqueSize As Integer
            Dim r As Long
            Dim lLastRow  As Long
    
            lLastRow = rng.End(xlDown).row
    
            elementSize = 1
            unqueSize = 0
    
            distance = Range(Application.Caller.Address).row - rng.row
    
            If distance <> 0 Then
                If Cells(Range(Application.Caller.Address).row - 1, Range(Application.Caller.Address).Column).Value = "" Then
                    listUnique = ""
                    Exit Function
                End If
            End If
    
            For r = 1 To lLastRow
                val = rng.Cells(r)
                If val <> "" Then
                    newElement = True
                    For i = 1 To elementSize - 1 Step 1
                        If elements(i - 1) = val Then
                            newElement = False
                            Exit For
                        End If
                    Next i
                    If newElement Then
                        uniqueSize = uniqueSize + 1
                        If uniqueSize >= elementSize Then
                            elementSize = elementSize * 2
                            ReDim Preserve elements(elementSize - 1)
                        End If
                        elements(uniqueSize - 1) = val
                    End If
                End If
            Next
    
    
            If distance < uniqueSize Then
                listUnique = elements(distance)
            Else
                listUnique = ""
            End If
        End Function
    
    0
    Meir Shachar

    私は最近同じ問題に遭遇し、ついにそれを見つけました。

    リストを使用して、Excelから式を貼り付けます。

    たとえば、私の例のセルC6のように、リストの中央のどこかに数式を記​​述し、それをコピーして列の上下に貼り付けることをお勧めします。数式は再入力することなく自動的に調整されるはずです。

    一意に異なる数式を持つ唯一のセルは、最初の行にあります。

    リストを使用する(「赤」、「青」、「赤」、「緑」、「青」、「黒」);結果は次のとおりです:(画像を投稿するのに十分なレベルがないので、このtxtバージョンが理にかなっていることを願っています

    • [列A:元のリスト]
    • [列B:一意のリストの結果]
    • [列C:一意のリスト式]

      1. 赤、赤、=A3
      2. 青、青、=IF(ISERROR(MATCH(A4,A$3:A3,0)),A4,"")
      3. 赤、、 =IF(ISERROR(MATCH(A5,A$3:A4,0)),A5,"")
      4. 緑、緑、=IF(ISERROR(MATCH(A6,A$3:A5,0)),A6,"")
      5. 青、、 =IF(ISERROR(MATCH(A7,A$3:A6,0)),A7,"")
      6. 黒、黒、=IF(ISERROR(MATCH(A8,A$3:A7,0)),A8,"")
    0
    Chris Reedy

    これは、値が順番に並んでいる場合にのみ機能します。つまり、すべての「赤」がすべてで、すべての「青」が一緒などです。データがA2から始まる列Aにあると仮定します-(1行目から開始しないでください) B2 type in 1 b3 type = if(A2 = A3、B2、B2 + 1)でデータの最後まで数式をドラッグします。すべての「赤」が1になり、すべての「青」が2になり、すべてが「緑」になります3など.

    C2では、1、2、3などと入力し、列を下に移動しますD2 = OFFSET($ A $ 1、MATCH(c2、$ B $ 2:$ B $ x、0)、0)-xは最後のセルドラッグダウン、一意の値のみが表示されます。 -エラーチェックを行う

    0
    Brian