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にあるために必要に応じて繰り返されます。
さて、この次の画像には、私が使用したいレポート形式があります。いくつかの階層レベルからのデータが必要な場合もあれば、他のレベルからのデータが必要な場合もあります。
最終的に、スプレッドシートには、必要なカスタマイズされたレポートカテゴリが入力されます(その後、集計データ用にそれらのカテゴリをピボットできます)。
私はこれをモンスターの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)
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:コードを機能させる]
これにはマクロソリューションは必要ありません。配列数式を使用できます。
{=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
を使用してデフォルトを返します。値。