Excel VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


1972 / 13645 ツリー ←次へ | 前へ→

【70611】列で連続している値のカウント (m´・ω・`)m 11/12/6(火) 17:22 質問[未読]
【70612】Re:列で連続している値のカウント kanabun 11/12/6(火) 19:02 発言[未読]
【70613】Re:列で連続している値のカウント とおりすぎ 11/12/6(火) 19:18 回答[未読]
【70614】Re:列で連続している値のカウント kanabun 11/12/6(火) 19:50 発言[未読]
【70615】Re:列で連続している値のカウント kanabun 11/12/6(火) 20:10 発言[未読]
【70617】Re:列で連続している値のカウント kanabun 11/12/7(水) 10:45 発言[未読]
【70738】Re:列で連続している値のカウント (m´・ω・`)m 11/12/21(水) 16:17 お礼[未読]
【70616】Re:列で連続している値のカウント Hirofumi 11/12/6(火) 20:20 発言[未読]
【70628】Re:列で連続している値のカウント UO3 11/12/9(金) 10:21 回答[未読]
【70629】Re:列で連続している値のカウント Yuki 11/12/9(金) 13:15 発言[未読]
【70631】Re:列で連続している値のカウント kanabun 11/12/10(土) 10:20 発言[未読]
【70633】Re:列で連続している値のカウント UO3 11/12/10(土) 16:29 発言[未読]
【70737】Re:列で連続している値のカウント (m´・ω・`)m 11/12/21(水) 16:07 お礼[未読]
【70634】Re:列で連続している値のカウント UO3 11/12/10(土) 16:41 発言[未読]
【70635】Re:列で連続している値のカウント UO3 11/12/10(土) 21:16 発言[未読]
【70736】Re:列で連続している値のカウント (m´・ω・`)m 11/12/21(水) 13:52 お礼[未読]

【70611】列で連続している値のカウント
質問  (m´・ω・`)m  - 11/12/6(火) 17:22 -

引用なし
パスワード
   列で連続している(行はバラバラ)値をカウントして下記の様に集計する方法はありますか?(列が連続しているものだけで空いているものは対象外)
集計の順はなんでも良いです。

NO.    NO.    NO.
りんご    らっぱ    ぱんつ
ごりら    りんご    らっぱ
らっぱ    ごりら    りんご
つみき    きんにく    つみき
くつした    たぶれっとくつした

↓↓↓↓

りんご    3
ごりら    2
らっぱ    3

【70612】Re:列で連続している値のカウント
発言  kanabun  - 11/12/6(火) 19:02 -

引用なし
パスワード
   ▼(m´・ω・`)m さん:
>列で連続している(行はバラバラ)値をカウントして下記の様に集計する方法はありますか?

簡単な例から。
サンプルデータのように、A,B,C列と連続してる3列のばあい、
同じ列であるアイテムがダブって入力されていることはありますか?

なければ、3列ひっくるめて各アイテムの出現回数を求めるだけなので
Dictionaryなどを使えば 簡単ですけど?

【70613】Re:列で連続している値のカウント
回答  とおりすぎ  - 11/12/6(火) 19:18 -

引用なし
パスワード
   >Dictionaryなどを使えば 簡単ですけど?
AとCに有る場合とかは?

【70614】Re:列で連続している値のカウント
発言  kanabun  - 11/12/6(火) 19:50 -

引用なし
パスワード
   簡単と言いましたけど、ちょっと書いてみたらこんなに長くなっちゃった Orz

Sub Try2()
  Dim dic As Object
  Dim r As Range
  Dim i As Long
  Dim j As Long, jj As Long
  Dim ss As String
  Dim zz As String
  
  Set dic = CreateObject("Scripting.Dictionary")
  Set r = Range("A1").CurrentRegion
  Set r = Intersect(r, r.Offset(1)) '1行目を削除
  jj = r.Columns.Count
  For j = 1 To jj '最終列まで繰り返し
    For i = 1 To r.Rows.Count
      ss = r(i, j).Value
      If Len(ss) > 0 Then
        If Not dic.Exists(ss) Then'初めてのアイテムのとき
          zz = Space$(jj) '列数分のスペース
        Else
          zz = dic(ss)   '既出アイテムのとき
        End If
        Mid(zz, j, 1) = "●" 'j列目に●を書き込む
        dic(ss) = zz
      End If
    Next
  Next
  
  Dim key
  Dim k As Long
  For Each key In dic.Keys()
    zz = dic(key)
    j = InStr(zz, "●●")
    If j > 0 Then
      k = 2
      For i = j + 2 To Len(zz)
        If Mid$(zz, i, 1) = "●" Then
          k = k + 1
        Else
          Exit For
        End If
      Next
      Debug.Print key, k
    End If
  Next
End Sub

'●●が含まれているアイテムだけとりだし、
 りんご ●●● ←3列ともある
 ごりら ●●   ←どこか2列連続してある
 らっぱ ●●● ←3列ともある

連続する●の数を数えます

 りんご 3
 ごりら 2
 らっぱ 3

【70615】Re:列で連続している値のカウント
発言  kanabun  - 11/12/6(火) 20:10 -

引用なし
パスワード
   ↑ちょっと説明を端折っちゃいましたけど、
プログラムの途中(各セルを走査してDictionaryにキーと値を入れる
ところ)までの処理で、

      A B C
りんご   ●●●
ごりら   ●●
らっぱ   ●●●
つみき   ● ●
くつした  ● ●
きんにく  ●
たぶれっと ●
ぱんつ    ●

のような対応表ができあがります。
「連続する2列以上」のアイテムというのが条件ですから、
少なくとも"●●"という文字列が辞書の値の中にあるもの
ということになります。

たとえば最初の「りんご」のばあい
> りんご   ●●●
>  j = InStr(zz, "●●")
で"●●"の位置をさがすとj = 1(1文字目)が返ってきますので、
●は 少なくとも2つあることになります。
で3文字目はどうか調べ、3文字目も●なので、Countは 3 となります。


> ごりら   ●●
のばあいは、3文字目はスペースなので Count は 2 のままです。

【70616】Re:列で連続している値のカウント
発言  Hirofumi  - 11/12/6(火) 20:20 -

引用なし
パスワード
   'こんな事?

Option Explicit

Public Sub Sample()

  Dim i As Long
  Dim j As Long
  Dim vntData As Variant
  Dim dicIndex As Object
  Dim vntResult As Variant
  Dim strProm As String

  'Dictionaryオブジェクトを取得
  Set dicIndex = CreateObject("Scripting.Dictionary")
  
  vntData = Range(Cells(2, "B"), Cells(Rows.Count, "B").End(xlUp)).Value
  With dicIndex
    For i = 1 To UBound(vntData, 1)
      .Item(vntData(i, 1)) = 1
    Next i
  End With
  
  vntData = Range(Cells(2, "A"), Cells(Rows.Count, "A").End(xlUp)).Value
  With dicIndex
    For i = 1 To UBound(vntData, 1)
      If .Exists(vntData(i, 1)) Then
        .Item(vntData(i, 1)) = .Item(vntData(i, 1)) + 1
      End If
    Next i
  End With
  
  vntData = Range(Cells(2, "C"), Cells(Rows.Count, "C").End(xlUp)).Value
  With dicIndex
    For i = 1 To UBound(vntData, 1)
      If .Exists(vntData(i, 1)) Then
        .Item(vntData(i, 1)) = .Item(vntData(i, 1)) + 1
      End If
    Next i
  End With
  
  With dicIndex
    vntData = .Keys
    ReDim vntResult(1 To UBound(vntData) + 1, 1 To 2)
    For i = 0 To UBound(vntData)
      If .Item(vntData(i)) > 1 Then
        j = j + 1
        vntResult(j, 1) = vntData(i)
        vntResult(j, 2) = .Item(vntData(i))
      End If
    Next i
  End With
  
  Cells(2, "E").Resize(j, 2).Value = vntResult
     
  Set dicIndex = Nothing
   
  MsgBox "処理が完了しました", vbInformation
     
End Sub

【70617】Re:列で連続している値のカウント
発言  kanabun  - 11/12/7(水) 10:45 -

引用なし
パスワード
   こんにちは〜

Try2()方式で、
シートに書き出すようにしてみました。
Hirofumiさんが E,F列に書き出してらっしゃいますので、
こちらは [G2]以降に出力です。

Sub Try2c()
  Dim dic As Object
  Dim r As Range
  Dim i As Long
  Dim j As Long, jx As Long
  Dim ss As String
  Dim zz As String
  
  Set dic = CreateObject("Scripting.Dictionary")
  Set r = Range("A1").CurrentRegion
  Set r = Intersect(r, r.Offset(1)) '1行目を削除
  jx = r.Columns.Count
  For j = 1 To jx '最終列まで繰り返し
    For i = 1 To r.Rows.Count 'j列を最終行まで繰り返し
      ss = r(i, j).Value
      If Len(ss) > 0 Then '行数が列によって異なることがある
        If Not dic.Exists(ss) Then
          zz = Space$(jx) '列数分のスペースを準備
        Else
          zz = dic(ss)  '辞書内の現在の文字列
        End If
        Mid(zz, j, 1) = "●" 'j桁目に●を書き込む
        dic(ss) = zz
      End If
    Next
  Next
  
  '連続する●をカウントする
  Dim key
  Dim k As Long, ok As Boolean
  For Each key In dic.Keys()
    ss = dic(key)
    ok = False
    For k = Len(ss) To 2 Step -1
      If InStr(ss, String$(k, "●")) Then
        dic(key) = k
        ok = True
        Exit For
      End If
    Next
    If Not ok Then dic.Remove key '辞書から削除
  Next
  '結果をシートに書き出す
  [G2].Resize(dic.Count, 2).Value = _
    Application.Transpose(Array(dic.Keys(), dic.Items()))
End Sub

【70628】Re:列で連続している値のカウント
回答  UO3  - 11/12/9(金) 10:21 -

引用なし
パスワード
   ▼(m´・ω・`)m さん:

すごく遅いかもしれません。
kanabunさんのアイデアを借用しています。
シート上のデータ最終列から1列あけて、結果を列挙しています。

Sub Sample()
  Dim x As Long
  Dim y As Long
  Dim z As Long
  Dim i As Long
  Dim j As Long
  Dim c As Range
  Dim r As Range
  Dim dic As Object
  Dim dk As Variant
  Dim s As String
  Dim f As String
  Dim v() As Variant
  
  Set dic = CreateObject("Scripting.Dictionary")
  
  With ActiveSheet.UsedRange
    x = .Columns.Count
    y = .Rows.Count
    Set r = .Cells.Offset(1).Resize(.Rows.Count - 1)
    
  End With
  
  For Each c In r
    dk = c.Value
    If Len(dk) > 0 Then
      If Not dic.exists(dk) Then
        s = Empty
        For j = 1 To x
          f = " "
          If IsNumeric(Application.Match(dk, Columns(j), 0)) Then f = "●"
          s = s & f
        Next
        dic(dk) = s
      End If
    End If
  Next
  
  ReDim v(1 To dic.Count, 1 To 2)
  
  For Each dk In dic
    For j = x To 1 Step -1
      z = InStr(dic(dk), WorksheetFunction.Rept("●", j))
      If z > 0 Then Exit For
    Next
    
    i = i + 1
    v(i, 1) = dk
    v(i, 2) = j
        
  Next
  
  Cells(1, x + 2).Resize(UBound(v, 1), 2).Value = v
  
  Set dic = Nothing
  Set r = Nothing
  
End Sub

【70629】Re:列で連続している値のカウント
発言  Yuki  - 11/12/9(金) 13:15 -

引用なし
パスワード
   ▼(m´・ω・`)m さん:
こんにちは。

最終列の横に出力しています。
Sub TESTa()
  Dim i    As Long
  Dim j    As Long
  Dim k    As Long
  Dim cnt   As Long
  Dim tol   As Variant
  Dim eRow  As Long
  Dim eCol  As Long
  
  With Worksheets("Sheet1")
    eRow = .Range("A" & .Rows.Count).End(xlUp).Row
    eCol = .Cells(1, .Columns.Count).End(xlToLeft).Column
    ReDim col(1 To eRow, 1 To 2)
    For i = 2 To eRow
      cnt = 0
      For j = 2 To eCol
        If WorksheetFunction.CountIf(.Columns(j), .Cells(i, 1).Value) > 0 Then
          cnt = cnt + 1
        Else
          Exit For
        End If
      Next
      If cnt > 0 Then
        k = k + 1
        col(k, 1) = .Cells(i, 1).Value
        col(k, 2) = cnt + 1
      End If
    Next
    .Cells(2, eCol + 2).Resize(k, 2).Value = col
  End With
End Sub

【70631】Re:列で連続している値のカウント
発言  kanabun  - 11/12/10(土) 10:20 -

引用なし
パスワード
   こんなデータだったばあいは?

NO.    NO.    NO.
りんご  らっぱ   ぱんつ
ごりら  りんご   らっぱ
らっぱ  ごりら   りんご
つみき  きんにく  つみき
くつした たぶれっと くつした
バナナ  虫     虫
りんご  

(列によりデータ数がまちまち)
(「虫」はB列とC列にあり、A列にはない)
(ある列に重複したアイテムがある)

↓↓↓↓

【70633】Re:列で連続している値のカウント
発言  UO3  - 11/12/10(土) 16:29 -

引用なし
パスワード
   ▼kanabun さん:

kanabunさんのレスが気になりましたので以下実行してみました。
私のは、カウントが1でも列挙対象にしていますが、それをカッとして比べますと

Sample

りんご    3
らっぱ    3
ごりら    2
虫    2

TESTa

りんご    3
ごりら    2
らっぱ    3
りんご    3

Try2c

りんご    3
ごりら    2
らっぱ    3
虫    2

TESTaは、【虫】がなく、【りんご】が2度登場してますね。

【70634】Re:列で連続している値のカウント
発言  UO3  - 11/12/10(土) 16:41 -

引用なし
パスワード
   ▼(m´・ω・`)m さん:

皆さんと同じく、2つ以上連続しているもののみ列挙のバージョンです。

Sub Sample2()
  Dim x As Long
  Dim y As Long
  Dim z As Long
  Dim i As Long
  Dim j As Long
  Dim c As Range
  Dim r As Range
  Dim dic As Object
  Dim dk As Variant
  Dim s As String
  Dim f As String
  Dim v() As Variant
 
  Set dic = CreateObject("Scripting.Dictionary")
 
  With ActiveSheet.UsedRange
    x = .Columns.Count
    y = .Rows.Count
    Set r = .Cells.Offset(1).Resize(.Rows.Count - 1)
  
  End With
 
  For Each c In r
    dk = c.Value
    If Len(dk) > 0 Then
      If Not dic.Exists(dk) Then
        s = Empty
        For j = 1 To x
          f = " "
          If IsNumeric(Application.Match(dk, Columns(j), 0)) Then f = "●"
          s = s & f
        Next
        dic(dk) = s
      End If
    End If
  Next
 
  ReDim v(1 To dic.Count, 1 To 2)
 
  For Each dk In dic
    For j = x To 2 Step -1
      z = InStr(dic(dk), WorksheetFunction.Rept("●", j))
      If z > 0 Then Exit For
    Next
  
    If j > 1 Then
      i = i + 1
      v(i, 1) = dk
      v(i, 2) = j
    End If
    
  Next
 
  Cells(1, x + 2).Resize(UBound(v, 1), 2).Value = v
 
  Set dic = Nothing
  Set r = Nothing
 
End Sub

【70635】Re:列で連続している値のカウント
発言  UO3  - 11/12/10(土) 21:16 -

引用なし
パスワード
   ▼(m´・ω・`)m さん:

連投の参加賞狙いで恐縮です。
Dictionaryを使わず、ループ数もちょっと減らしました。

Sub Sample3()
  Dim x As Long
  Dim y As Long
  Dim j As Long
  Dim c As Range
  Dim r As Range
  Dim dk As Variant
  Dim v() As Variant
  Dim m As Long
  Dim n As Long
  Dim k As Long
  
  With ActiveSheet.UsedRange
    x = .Columns.Count
    y = .Rows.Count
    Set r = .Cells.Offset(1).Resize(.Rows.Count - 1)
  End With
  
  ReDim v(1 To x * y, 1 To 2)
  
  For Each c In r
    dk = c.Value
    If Not IsNumeric(Application.Match(dk, WorksheetFunction.Index(v, 0, 1), 0)) And Len(dk) > 0 Then
      m = 0
      n = 0
      For j = 1 To x
        If IsNumeric(Application.Match(dk, Columns(j), 0)) Then
          n = n + 1
        Else
          n = 0
        End If
        m = WorksheetFunction.Max(m, n)
      Next
      If m > 1 Then
        k = k + 1
        v(k, 1) = dk
        v(k, 2) = m
      End If
    End If
  Next

  If k > 0 Then Cells(1, x + 2).Resize(k, 2).Value = v
  
  Set r = Nothing

End Sub

【70736】Re:列で連続している値のカウント
お礼  (m´・ω・`)m  - 11/12/21(水) 13:52 -

引用なし
パスワード
   すいません、質問していて今日まで忘れてました。
こちら全然分かりませんのでとりあえず皆さんのコピペしてみたいと思います。
本当に有難うございました。
まだベターな方法ありましたらドシドシお願いします。

【70737】Re:列で連続している値のカウント
お礼  (m´・ω・`)m  - 11/12/21(水) 16:07 -

引用なし
パスワード
   有難うございました。
とにかく試してみますm(_ _)m

【70738】Re:列で連続している値のカウント
お礼  (m´・ω・`)m  - 11/12/21(水) 16:17 -

引用なし
パスワード
   ▼kanabun さん:
結局こちら使わせて頂きます。
有難うございました(m´・ω・`)m

1972 / 13645 ツリー ←次へ | 前へ→
ページ:  ┃  記事番号:
2610219
(SS)C-BOARD v3.8 is Free