2

VBA のループ内で case ステートメント (または複数の if ステートメント) を作成するにはどうすればよいですか?

この例では、4 つの異なるグループに対応する 4 つの名前のリストがあります。名前はスプレッドシートの列「C」にあり、各個人のグループ名がリストされている列「D」という新しい列を作成したいと思います。

現時点で作業しているコードは次のとおりです。

Sub AddGroupColumn()
   'Counts number of rows in sheet. Loops through rows.
   For i = 1 To Range("C1048576").End(xlUp).Row
       If Range("C2:C" & i).Value = "john.doe" Then
          Set Range("D2:D" & i).Value = "group 1"
       If Range("C2:C" & i).Value = "jane.doe" Then
          Range("D2:D" & i).Value = "group 2"
       If Range("C2:C" & i).Value = "james.doe" Then
          Range("D2:D" & i).Value = "group 3"
       If Range("C2:C" & i).Value = "jenn.doe" Then
          Range("D2:D" & i).Value = "group 4"
    Next i 
 End Sub

上記のコードを修正する方法について提案をお願いします。構文が正しくないことはわかっていますが、「If/Then/Else/Elseif」の「Case」ステートメントを使用する必要があるかどうかはわかりません。現在受け取っているエラーは次のとおりです。

コンパイル エラー: For なしの Next

また、この問題を解決するためのより効率的な方法があれば教えてください。実際には、12 個の名前、12 個のグループ、および 100,000 行の名前があります。

4

3 に答える 3

3

記述IFされたステートメントはすべてELSE IF、2 番目のステートメントが必要であり、その後にグループ化の最後にステートメントIFが続きます。END IF

次のように、確かにCASEステートメントを実行できます。

Sub AddGroupColumn()
   'Counts number of rows in sheet. Loops through rows.
   For i = 1 To Range("C1048576").End(xlUp).Row
       Select Case Range("C2:C" & i).Value
           Case "john.doe"
                Range("D2:D" & i).Value = "group 1"
           Case "jane.doe"
                Range("D2:D" & i).Value = "group 2"
           ' The rest of your case statements go here ...
       End Select
    Next i 
End Sub
于 2012-08-06T18:21:11.607 に答える
2

名前とグループを配列に入れることができます。

Sub AddGroupColumn()

    Dim rCell As Range
    Dim rRng As Range
    Dim vaNames As Variant
    Dim vaGroups As Variant
    Dim lMatch As Long

    vaNames = Array("john.doe", "jane.doe", "james.doe", "jenn.doe")
    vaGroups = Array("group 1", "group 2", "group 3", "group 4")

    With Sheet1
        Set rRng = .Range("C1", .Cells(.Rows.Count, 3).End(xlUp))
    End With

    For Each rCell In rRng.Cells
        lMatch = Application.WorksheetFunction.Match(rCell.Value, vaNames, False)
        rCell.Offset(0, 1).Value = vaGroups(lMatch - 1)
    Next rCell

End Sub

この例では、範囲が適用されるシートを指定していないことに注意してください。これらは修飾されていない範囲参照と呼ばれ、予期しない動作を引き起こす可能性があります。コードが標準モジュールにある場合、修飾されていない範囲は ActiveSheet を参照します。コードがシート クラス モジュール内にある場合、修飾されていない範囲はそのシートを参照します。

列 C の一部の名前にグループがない場合は、それを考慮してループを変更する必要があります。このような

For Each rCell In rRng.Cells
    On Error Resume Next
        lMatch = Application.WorksheetFunction.Match(rCell.Value, vaNames, False)
    On Error GoTo 0

    If lMatch - 1 > LBound(vaGroups) Then
        rCell.Offset(0, 1).Value = vaGroups(lMatch - 1)
    Else
        rCell.Offset(0, 1).Value = "No group"
    End If
Next rCell
于 2012-08-06T19:16:45.320 に答える
1

配列を使用してこれらすべてを実行できます。IfまたはSelect Caseステートメントは必要ありません。これにより、各値を一度に1つずつワークシートに書き込む必要がなくなります。

サンプル入力を使用してテストおよび動作します(入力データの単一列を想定):

Sub AddGroupColumn()

Dim inputRange As Excel.Range
Dim inputData As Variant
Dim outputData As Variant
Dim i As Long, j As Long
Dim nameslist As Variant
Dim groupslist As Variant

' **** EDIT THESE AS NEEDED, however they MUST correspond
Const NAMES_LIST As String = "john.doe,jane.doe,james.doe,jenn.doe"
Const GROUPS_LIST As String = "group 1,group 2,group 3,group 4"

' create arrays of names and groups
nameslist = Split(NAMES_LIST, ",")
groupslist = Split(GROUPS_LIST, ",")

' define input range
Set inputRange = Range("C2:C" & Range("C" & Rows.Count).End(xlUp).row)

' read column C values into array
inputData = inputRange.value
' resize output array to match input array
ReDim outputData(LBound(inputData) To UBound(inputData), 1 To 1)

' evaluate input array, output to another array
For i = LBound(inputData) To UBound(inputData)
  For j = LBound(nameslist) To UBound(nameslist)
    If inputData(i, 1) = nameslist(j) Then ' given input value is matched on the names list
      outputData(i, 1) = groupslist(j) ' output array is the corresponding group name
      Exit For ' exit loop since we found what we need in this loop
    End If
  Next j
Next i

  ' write output data to output range
  inputRange.Offset(, 1).value = outputData

End Sub

この手順は、実際のデータに適用するとスケーリングされます。2つの定数を編集して、それらの値が対応していることを確認してください。

Rows.Countを使用すると、Excelのバージョンに関係なく、常に正しい範囲が取得されます。データの量に関係なく、配列のサイズは自動的に変更されます。それが行う唯一の仮定は、入力データが1つの列にあるということです。

また、ワークシートに触れるのは3回だけであることに注意してください。1回は入力範囲を定義するため、1回は列Cの値を取得するため、もう1回は計算値を列Dに書き戻すためです。

サンプル入力

サンプル入力

コードを実行した後

サンプル出力

于 2012-08-06T18:58:25.523 に答える