2

私のデータは以下の通りです。

更新された質問

Sub Solution()
  Dim shData As Worksheet
  Set shData = Sheets("Sheet1")    'or other reference to data sheet
  Dim coll As Collection, r As Range, j As Long
  Dim myArr As Variant
  Dim shNew As Worksheet

  shData.Activate

  'get unique values based on Excel features
  Range("a1").AutoFilter

  Set coll = New Collection

  On Error Resume Next

  For Each r In Range("A1:A10")
    coll.Add r.Value, r.Value
  Next r

  On Error GoTo 0
  'Debug.Print coll.Count

  For j = 1 To coll.Count
    MsgBox coll(j)
    myArr = coll(j)
  Next j

  Range("a1").AutoFilter

  Dim i As Long

  For i = 0 To UBound(myArr)
    shData.Range("$A$1").AutoFilter Field:=1, Criteria1:=myArr(i), _
      Operator:=xlAnd
    On Error Resume Next
    Sheets(myArr(i)).Range("A1").CurrentRegion.ClearContents

    If Err.Number = 0 Then
      Range("A1").CurrentRegion.Copy Sheets(myArr(i)).Range("A1")
    Else
      Set shNew = Sheets.Add(After:=Sheets(Sheets.Count))
      shData.Range("A1").CurrentRegion.Copy shNew.Range("A1")
      shNew.Name = myArr(i)
      Err.Clear
    End If
 Next i

 'removing filter in master sheet
 shData.Range("a1").AutoFilter

 End Sub

Type Mismatch Error上記のマクロを実行すると、 afterが与えられる理由がわかりませんMsgBox coll(j)。単純にデータを Array に格納したいので、その data を渡します。ここではFor Each r In Range("A1:A10")Where A10length is static を使用しています 最後に書き込まれた列を見つけるにはどうすればよいですか?

4

2 に答える 2

3

この質問に答える前に、あなたが達成しようとしていると私が信じていることを書きたいと思います。これがあなたがやろうとしていることであると確認したら、それを達成するためのコードを動作させる手助けをしようとします。これは通常コメントで行われますが、これまでのコメントのスレッドは少しバラバラで、コードは非常に複雑です...

  1. シートにデータがあります(「sheet1」と呼ばれます-それは別のものかもしれません)
  2. 最初の列には、繰り返される可能性のある特定の値が含まれています
  3. いくつの列があるかわかりません...でもそれを知りたいです
  4. 列 A で一意の値 (「キー値」と呼びます) を見つけて、メッセージ ボックスに (一度に 1 つずつ) 表示しようとします。これは、最終的なプログラムの実際の機能というよりも、デバッグ ステップのように見えます。
  5. 次に、列 A でオートフィルターをオンにします。特定の値に一致する行のみを選択する
  6. シートの名前と同じ値を使用して、そのようなシートが存在するかどうかを確認します。存在する場合は、その内容をクリアします。そうでない場合は、ワークブックの最後に作成します (キーの名前を付けます)。
  7. シート 1 の列 A で同じ (キー) 値を持つすべての行を選択し、フィルター処理した列 A の値と同じ名前のシートにそれらをコピーします。
  8. 列 A の一意の (キー) 値ごとに手順 5 ~ 8 を繰り返します。
  9. すべてが完了すると、列 A のキー値よりも (少なくとも) 1 つ多いシートがあると思います (最初のデータシートもあります)。ただし、「余分な」シート (他の名前のシート) は削除しません。各シートには、シート 1 の現在の内容に対応するデータ行のみが含まれます (以前のデータは削除されています)。
  10. 操作中に、オートフィルタリングのオンとオフを切り替えます。自動フィルターを無効にして終了したい。

これが本当にあなたがやろうとしていることであることを確認してください。列 A の値の形式を教えていただけると助かります。いくつかのことは、あなたが現在行っているよりも効率的に行うことができるのではないかと思います. 最後に、この方法でデータを整理する全体的な目的は、データを特定の方法で整理し、さらに計算/グラフなどを実行することであるかどうか疑問に思います。Excel (VBA) には、作成するためのあらゆる種類の関数が組み込まれています。データ抽出の作業がより簡単になります。特定の作業を完了するために、この種のデータの再配置が必要になることはめったにありません。その点についてコメントをいただければ...

次のコードは、上記のすべてを実行します。特定のタスク ( 、、および) を処理するためのFor Each、および関数/サブルーチンの使用に注意してください。これにより、トップレベルのコードが読みやすく理解しやすくなります。また、エラー トラップは、ワークシートが存在するかどうかを確認する小さなセクションに限定されていることに注意してください。私にとっては、問題なく実行されました。エラーが発生した場合は、ワークシートの内容が影響する可能性があるため、ワークシートの内容をお知らせください (たとえば、列のセルにシート名で許可されていない文字が含まれている場合など)。また、コードが「達成しようとしているものによっては、「UsedRange」の方が良いかもしれません...uniquecreateOrClearworksheetExistsA/\!

Option Explicit

Sub Solution()
  Dim shData As Worksheet
  Dim nameRange As Range
  Dim r As Range, c As Range, A1c As Range, s As String
  Dim uniqueNames As Variant, v As Variant

  Set shData = Sheets("Sheet1")  ' sheet with source data
  Set A1c = shData.[A1]          ' first cell of data range - referred to a lot...
  Set nameRange = Range(A1c, A1c.End(xlDown)) ' find all the contiguous cells in the range

  ' find the unique values: using custom function
  ' omit second parameter to suppress dialog
  uniqueNames = unique(nameRange, True)

  Application.ScreenUpdating = False ' no need for flashing screen...

  ' check if sheet with each name exists, or create it:
  createOrClear uniqueNames

  ' filter on each value in turn, and copy to corresponding sheet:
  For Each v In uniqueNames
    A1c.AutoFilter Field:=1, Criteria1:=v, _
      Operator:=xlAnd
    A1c.CurrentRegion.Copy Sheets(v).[A1]
  Next v

  ' turn auto filter off
  A1c.AutoFilter

  ' and screen updating on
  Application.ScreenUpdating = True

End Sub

Function unique(r As Range, Optional show)
  ' return a variant array containing unique values in range
  ' optionally present dialog with values found
  ' inspired by http://stackoverflow.com/questions/3017852/vba-get-unique-values-from-array
  Dim d As Object
  Dim c As Range
  Dim s As String
  Dim v As Variant

  If IsMissing(show) Then show = False

  Set d = CreateObject("Scripting.Dictionary")

  ' dictionary object will create unique keys
  ' have to make it case-insensitive
  ' as sheet names and autofilter are case insensitive
  For Each c In r
    d(LCase("" & c.Value)) = c.Value
  Next c

  ' the Keys() contain unique values:
  unique = d.Keys()

  ' optionally, show results:
  If show Then
    ' for debug, show the list of unique elements:
    s = ""
    For Each v In d.Keys
      s = s & vbNewLine & v
    Next v
    MsgBox "unique elements: " & s
  End If

End Function

Sub createOrClear(names)
  Dim n As Variant
  Dim s As String
  Dim NewSheet As Worksheet

  ' loop through list: add new sheets, or delete content
  For Each n In names
    s = "" & n ' convert to string
    If worksheetExists(s) Then
      Sheets(s).[A1].CurrentRegion.Clear ' UsedRange might be better...?
    Else
      With ActiveWorkbook.Sheets
        Set NewSheet = .Add(after:=Sheets(.Count))
        NewSheet.Name = s
      End With
    End If
  Next n

End Sub

Function worksheetExists(wsName)
' adapted from http://www.mrexcel.com/forum/excel-questions/3228-visual-basic-applications-check-if-worksheet-exists.html
  worksheetExists = False
  On Error Resume Next
  worksheetExists = (Sheets(wsName).Name <> "")
  On Error GoTo 0
End Function
于 2013-04-09T03:33:33.597 に答える
2

コレクションに何かを追加する場合、キーは文字列である必要があるため、次を使用します。

coll.Add r.Value, CStr(r.Value)

それ以外の:

coll.Add r.Value, r.Value

あなたはまだ配列ではないに割り当てcoll(j)ています。必要がある:Variant

ReDim myArr(1 to coll.Count)

forループの前とループ内:

myArr(j) = coll(j)
于 2013-04-06T12:58:35.657 に答える