2

私の大きなスプレッドシートで問題が発生しています。大量の生データをデータ シートに取り込んでから、データ全体を何度も検索します。私が思いついた組み込み関数を使用する

=IF(ISNA(INDEX(Data!$L$7:$L$1100,MATCH(Data!$I$2&$B$199&$B29&Data!$J$5,Data!$K$7:$K$1100&Data!$J$7:$J$1100&Data!$I$7:$I$1100&Data!$N$7:$N$1100,0))),"0",INDEX(Data!$L$7:$L$1100,MATCH(Data!$I$2&$B$199&$B29&Data!$J$5,Data!$K$7:$K$1100&Data!$J$7:$J$1100&Data!$I$7:$I$1100&Data!$N$7:$N$1100,0)))

かわいくない!基本的に、同じルックアップを 2 回実行して 4 つの変数を取得し、それらを 4 つの連結された配列と照合してから、そのポイントを必要な値のインデックスとして使用します。

4 シートの各行に 8 つ (わずかに異なります)、各シートに 96 行あります。それらを編集するのは面倒です!

今月はデータセットが大幅に増加したため、外側のバンド (x1100) を超えました (教訓、大規模では決して十分ではありません)。残念ながら、関数の制限により、L:L やそのような便利なものは使用できません。

4 つの変数を入力して答えを返すことができるユーザー定義関数としてコードを書き直そうとしましたが、配列の結合に失敗しました。

物事を簡単にするために、元の関数名に上記の範囲を指定しました (さらに、より広い範囲の値を使用するようにそれらを拡張しました)。そのため、名前付き範囲のみを使用するようにすべての関数を書き直すことができましたが、それでもスタックしたままになります。コードを変更する必要がある場合。

これが私がこれまでに持っているものです:

    Function Windows_Util(itma As String, env As String)

v = "Windows Server" & env & itma & ""
r = Concat(Range("Utilchassis"))
r = r & Concat(Range("Utilenv"))
r = r & Concat(Range("UtilITMA"))
r = r & Concat(Range("UtilOS"))

m = WorksheetFunction.Match(v, r, 0)

i = WorksheetFunction.Index(Range("Utilavg"), m)


If WorksheetFunction.IsNA(i) Then
    Windows_Util = 0
Else
    Windows_Util = i
End If

End Function


Function Concat(myRange As Range, Optional myDelimiter As String)

Dim r As Range

Application.Volatile

For Each r In myRange
   If Len(r.Text) Then
       Concat = Concat & IIf(Concat <> "", myDelimiter, "") & r.Text
   End If
Next

End Function

これはうまくいきません!正しく連結されないだけでなく (各範囲が個別に連結され、行ごとに結合されません)、クエリの 1 つの型が気に入りません。(関数が実際に完了するため(構文エラーがないため)、これらのデバッグは簡単ではありません。そのため、使用できる組み込みのステップスルーはありません。

どんな助けでも大歓迎です。

うまくいけば、私がやろうとしていることを理解するのに十分な詳細を提供できました.

乾杯、

スティーブ

4

3 に答える 3

1

どうですか:

r = Range("Utilchassis,Utilenv,UtilITMA,UtilOS")

それはあなたの Concat 関数と同じことを達成するようです

于 2009-01-10T04:30:55.547 に答える
1

Ranges をどのように連結したいか正確にはわかりませんが、Application.Union(Range, Range, ...) methodを確認する必要があると思います。

記事の例では:

Set bigRange = Application.Union(Range("Range1"), Range("Range2"))

Tushar Mehta による Daily Dose of Excelの記事も参照してください。彼は、'Nothing' (null) 入力をより適切に処理できる次のカスタム Union(Range, Range) メソッドについて説明しています。

Function Union(Rng1 As Range, Rng2 As Range) As Range
    If Rng1 Is Nothing Then
        Set Union = Rng2
    ElseIf Rng2 Is Nothing Then
        Set Union = Rng1
    Else
        Set Union = Application.Union(Rng1, Rng2)
    End If
End Function

代わりに、アドレス範囲の文字列連結を使用する場合は、Barrowc が投稿で示しているように、カンマを追加する必要があります。たとえばRange("MyRange1, MyRange2")、"MyRange1" と "MyRange2" という名前の 2 つの範囲を結合しますが、コンマを含まないスペース区切り文字はRange("MyRange1 MyRange2")、これら 2 つの範囲の INTERSECTION (重複) を返します。

ただし、文字列アドレスの連結を避け、Application.Union(Range, Range)代わりにメソッドを使用することをお勧めします。

お役に立てれば...

于 2009-01-11T02:22:21.330 に答える
0

一致する基準が複数ある場合、MATCH関数をVBAで使用するのは難しい場合があります。ワークシートで行われること(異なるセルから連結された一致基準を、両方の場合で&演算子を使用して、同じ数の連結範囲に対して)は、VBAの「&」演算子は文字列のみを引数として受け取るため、VBAでは達成できません。 VBAで範囲を連結する他の方法、Union関数、およびRangeへの複数のアドレス引数を介した割り当ては、VBA一致関数で機能する配列を生成しないようです。

ただし、MATCHと配列の比較を組み合わせたワークシートの数式を作成し、VBA Evaluate関数を使用して数式を実行することで、同じ効果を得ることができます。このアプローチがどのように機能するかの詳細については、このSOの質問に対する私の回答を参照してください 。

次のコードは、基本的に、ワークシート内の以前に名前が付けられた範囲やコードで指定された基準値(ワークシート内の特定のセルではなく)に依存せずに、Steveによって提供された元のワークシート式を再実装します。サブとして記述されていますが、ユーザー定義関数に簡単に変換できます。

  Sub x4match()

    Dim adr1 As String, adr2 As String, adr3 As String, adr4 As String
    Dim Rng1 As Range, Rng2 As Range, Rng3 As Range, Rng4 As Range
    Dim name1 As String, name2 As String, name3 As String, name4 As String
    Dim idx As Variant
    Dim resultRng As Range
    Dim result As Variant

    With ThisWorkbook.Worksheets("Data")

       adr1 = "I2"
       adr2 = "B199"
       adr3 = "B29"
       adr4 = "J5"

       Set Rng1 = .Range("K7:K1100")
       Set Rng2 = .Range("J7:J1100")
       Set Rng3 = .Range("I7:I1100")
       Set Rng4 = .Range("N7:N1100")
       Set resultRng = .Range("L7:L1100")

       .Names.Add Name:="name1", RefersTo:=Rng1
       .Names.Add Name:="name2", RefersTo:=Rng2
       .Names.Add Name:="name3", RefersTo:=Rng3
       .Names.Add Name:="name4", RefersTo:=Rng4

       idx = Evaluate("IFERROR( MATCH(1, --(" & adr1 & "=name1) * --(" & _
                     adr2 & "=name2) * --(" & adr3 & "=name3) * --(" & _ 
                     adr4 & "=name4), 0), 0)")

       If idx <> 0 Then
          result = .Cells(resultRng.Row + idx - 1, resultRng.Column).Value
       End If

      .Names("name1").Delete
      .Names("name2").Delete
      .Names("name3").Delete
      .Names("name4").Delete

    End With

  End Sub
于 2013-01-19T06:27:20.040 に答える