web-dev-qa-db-ja.com

Excelで、2つの配列(水平方向と垂直方向)の間で一致するデータを見つける必要があります

Excel 2010(または2007-両方ありますが、実行する一部のレガシーアプリケーションの制限としてOSはWin7 32ビットのみです)では、2つのデータ配列から一致する値を見つけて返す方法を見つける必要があります。

2つのスプレッドシートがあります。 1つは階層からの巨大なフラットファイルOLAPキューブディメンション(SAP BPCからの37,000行)。もう1つは、照合する必要のある値のテーブルです。一致する値を返す必要があります。 2番目のスプレッドシートから最初のシートのColumnAへ-フラットファイル。

課題は、それが階層構造であるため、一致するSheet1から単一の列を選択できないことです。一致は各行のどの列でも発生する可能性があります。したがって、基本的には、シート1の単一行を配列として、シート2の列を配列として一致するものをすべて取得する必要があると考えています(私は思います)。

英語で、Excelに次のことを実行してもらいます。データがあるSheet1の各行について、行全体を確認します(たとえば、範囲B2:R2-数式/一致値の列Aを空白のままにしました)。レポートカテゴリリスト(シート2の列A、範囲A1:A42)に一致するものがある場合は、Sheet2の値をSheet1!A2(一致のために作成した空白の列)に返します。

これは、食べ物の寓話を含むデータのサンプルです。空白のColumnAを作成し、各行のデータが分類の階層を上っていくことに注意してください。ここで、ColBは基本レベルであり、ターミナルの親がColFにあるために必要に応じて繰り返されます。

enter image description here

さて、この次の画像には、私が使用したいレポート形式があります。いくつかの階層レベルからのデータが必要な場合もあれば、他のレベルからのデータが必要な場合もあります。

enter image description here

最終的に、スプレッドシートには、必要なカスタマイズされたレポートカテゴリが入力されます(その後、集計データ用にそれらのカテゴリをピボットできます)。enter image description here

私はこれをモンスターのvlookup式で実現してきましたが、vlookupステートメントが8つの深さでネストされた37,000行でExcelが頻繁にクラッシュするため、別の、より簡単な、または少なくともリソースをあまり消費しない方法があるかどうか疑問に思いました。したがって、実際のレポートカテゴリ(sheet2はAll_Budget_Unitsと呼ばれます)を使用して、現在使用しているものは次のとおりです。

= IFERROR(VLOOKUP(IFERROR(VLOOKUP(IFERROR(VLOOKUP(IFERROR(VLOOKUP(IFERROR(VLOOKUP(IFERROR(VLOOKUP(C2、All_Budget_Units!$ A $ 1:$ A $ 39,1、FALSE)、D2)、All_Budget_Units!$ A $ 1 :$ A $ 39,1、FALSE)、E2)、All_Budget_Units!$ A $ 1:$ A $ 39,1、FALSE)、F2)、All_Budget_Units!$ A $ 1:$ A $ 39,1、FALSE)、G2)、All_Budget_Units !$ A $ 1:$ A $ 39,1、FALSE)、H2)、All_Budget_Units!$ A $ 1:$ A $ 39,1、FALSE)、I2)

1
ppfooie

YMMVですが、[表示]-> [マクロ]で、マクロを追加します。これを試してください(必要に応じてセル参照を変更してください):

Dim data, reference As Range

Set reference = Worksheets("Sheet2").Range("A1", "A42")
Set data = Worksheets("Sheet1").Range("B2", "F6")

For Each dataCell In data
    For Each referenceCell In reference
        If dataCell.Value = referenceCell.Value Then
                Worksheets("Sheet1").Cells(dataCell.Row, 1).Value = dataCell.Value
        End If
    Next
Next

[編集:これが機能する場合は、一致するものが見つかったときに行の検索を停止することで、少し高速化できます。 (行ごとに一致する可能性があるのは1つだけであると想定)。例えば。:

Sub newtest()
    Dim data, reference As Range
    Dim skipsome As Boolean
    skipsome = False

    Set reference = Worksheets("Sheet2").Range("A1", "A7")

    Set data = Worksheets("Sheet1").Range("B2", "F6")
    For Each dataCell In data
        For Each referenceCell In reference
            If dataCell.Value = referenceCell.Value Then
                    Worksheets("Sheet1").Cells(dataCell.Row, 1).Value = dataCell.Value
                    skipsome = True
                    Exit For
            End If

            If skipsome = True Then
                skipsome = False
                Exit For
            End If
        Next
    Next
End Sub

5行のテストデータだけで、これによりセル比較テストが175から132にノックダウンされます。] [Edit2:コードを機能させる]

0

これにはマクロソリューションは必要ありません。配列数式を使用できます。

{=INDEX(All_Budget_Units!$A$1:$A$39, MAX(IFERROR(MATCH(C2:I2, All_Budget_Units!$A$1:$A$39, 0), 0)))}

これは、I2の値がマスターリストにもあることを前提としていますが、元の式では想定されていません。存在しない、または存在しない可能性がある場合は、代わりにこれを使用してください。

{=IFERROR(INDEX(All_Budget_Units!$A$1:$A$39, MAX(IFERROR(MATCH(C2:H2, All_Budget_Units!$A$1:$A$39, 0), -1))), I2)}

以前に配列数式を使用したことがない場合は、中括弧{}を自分で入力しないでください。数式の残りの部分を入力し、CTRL + SHIFT + ENTERを押して配列数式として入力します。正しく行うと、中括弧が数式ボックスに表示されます。

これが機能する方法は、MATCH関数を使用して一致結果の配列を作成することです。これらの1つを除くすべてが#N/Aなので、IFERRORでラップして、これらを0(または2番目のバージョンでは-1)に変換します。実際の一致は正の数になるため、配列のMAXを取得すると、単一の一致が見つかります。次に、INDEX関数を使用してこれを値に変換します。 2番目のバージョンでは、一致するものがまったくない場合、位置が-1のINDEXを使用しようとするとエラーが発生するため、IFERRORを使用してデフォルトを返します。値。

3
Scarlet Manuka