Excel VBA質問箱 IV

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

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


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

【75838】パターン別に集計したいです。 初心者 14/7/13(日) 0:10 質問[未読]
【75839】Re:パターン別に集計したいです。 kanabun 14/7/13(日) 0:19 発言[未読]
【75840】Re:パターン別に集計したいです。 初心者 14/7/13(日) 0:33 発言[未読]
【75841】Re:パターン別に集計したいです。 kanabun 14/7/13(日) 0:48 発言[未読]
【75842】Re:パターン別に集計したいです。 kanabun 14/7/13(日) 0:54 発言[未読]
【75843】Re:パターン別に集計したいです。 kanabun 14/7/13(日) 10:49 発言[未読]
【75844】Re:パターン別に集計したいです。 kanabun 14/7/13(日) 11:56 発言[未読]
【75845】Re:パターン別に集計したいです。 初心者 14/7/13(日) 20:16 お礼[未読]
【75846】Re:パターン別に集計したいです。 γ 14/7/13(日) 20:31 発言[未読]
【75849】Re:パターン別に集計したいです。 14/7/14(月) 7:26 発言[未読]
【75847】Re:パターン別に集計したいです。 γ 14/7/13(日) 23:07 回答[未読]
【75848】Re:パターン別に集計したいです。 γ 14/7/13(日) 23:25 発言[未読]

【75838】パターン別に集計したいです。
質問  初心者  - 14/7/13(日) 0:10 -

引用なし
パスワード
   以下のとおりパターン別に集計するにはどのように処理を組めば良いかご教示願います。
大変恐れ入りますが当方初心者で勉強中のため、処理内容についてコメント補則いただけるとありがたいです。
よろしくお願いいたします。

《やりたいこと》
Sheet1のデータを、Sheet2に、データ種類別・パターン別に集計したい。
※「パターン列=空白」&「対象外列=S」のときは、対象外として集計する。
※「パターン列=空白」&「対象外列=空白」のときは、調査中として集計する。

《イメージ》
【Sheet1】
  1. 2. 3. パターン 対象外
A 1        あ
A 1        あ
A   1      い
B   1  1   う
B   1            S
C       1            (・・調査中)

【Sheet2(出力イメージ)】
      1. 2. 3.
A   
 あ    2
 い      1
 う
対象外
調査中
B   
 あ   
 い     
 う       1  1
対象外    1
調査中
C  
 あ   
 い      
 う
対象外
調査中      1

以上、よろしくお願いいたします。

【75839】Re:パターン別に集計したいです。
発言  kanabun  - 14/7/13(日) 0:19 -

引用なし
パスワード
   ▼初心者 さん:


>大変恐れ入りますが当方初心者で勉強中のため、処理内容についてコメント補則いただけるとありがたいです。

いきなりコードを書こうとしないで、
処理内容を順に 日本語の「疑似コード」で書いてみたらどうですか?

【75840】Re:パターン別に集計したいです。
発言  初心者  - 14/7/13(日) 0:33 -

引用なし
パスワード
   ▼kanabun さん:
>いきなりコードを書こうとしないで、
>処理内容を順に 日本語の「疑似コード」で書いてみたらどうですか?

早速のご連絡ありがとうございます。
ご指摘につきましてはおっしゃるとおりです。。。
フローを書いて整理したのですが、VBAについてまったくの初心者で関数がわからず、コーディングも初めてですので、お恥ずかしいのですが、まずはサンプルコードを読んで理解するところから始めたいと思いました。
パターン別にデータ行単位で加算していきたいのですが、その処理関数がわからず行き詰っています。
よろしくお願いいたします。

【75841】Re:パターン別に集計したいです。
発言  kanabun  - 14/7/13(日) 0:48 -

引用なし
パスワード
   ▼初心者 さん:

>フローを書いて整理したのですが、VBAについてまったくの初心者で関数がわからず、コーディングも初めてですので、お恥ずかしいのですが、まずはサンプルコードを読んで理解するところから始めたいと思いました。

逆です。

>パターン別にデータ行単位で加算していきたいのですが、

「パターン別」→ これをもっと具体的に、あなたが手動でやるとき、
あるいは だれか配下の人に手順を教えるとき、
「ここをどうして... つぎに、これをなんたらして...」と説明すると
思います。
これを文章にしてみるのです。
具体的な手順が日本語で書けるようになる方が、コードを書くよりか
よほど難しいのです。

「ぐだぐだ言ってないで、コードをくれ!」

というのは、思考放棄です。

【75842】Re:パターン別に集計したいです。
発言  kanabun  - 14/7/13(日) 0:54 -

引用なし
パスワード
   別件ですが、
ピボットテーブルはお得意ですか?

【75843】Re:パターン別に集計したいです。
発言  kanabun  - 14/7/13(日) 10:49 -

引用なし
パスワード
   ▼初心者 さん:

>《やりたいこと》
> Sheet1のデータを、Sheet2に、データ種類別・パターン別に集計したい。
>※「パターン列=空白」&「対象外列=S」のときは、対象外として集計する。
>※「パターン列=空白」&「対象外列=空白」のときは、調査中として集計する。

《イメージ》
【Sheet1】                → パターン仕訳け
-------------------------------------
種別 1. 2. 3. パターン 対象外
A   1       あ         →A の「あ」の行
A   1       あ         →A の「あ」の行
A     1     い         →A の 「い」の行
B     1  1   う         →B の 「う」の行
B     1          S     →B の「対象外」の行
C       1             →C の「調査中」の行

(1) 種別の種類を調べる → A,B,C
(2) パターンの種類を調べる → 「あ」,「い」,「う」
       パターンとしてはこれ以外に「対象外」「調査中」を追加。

(3) 以上が分ったら、
  種別の数だけ大きい箱を用意する
  箱の中に パターンの数だけの小さい箱を入れる
  そのパターン用の小さい箱のなかは 1. | 2. | 3. の仕切りを入れる

(4) もう一度Sheet1の表を上から順に読んでいって、データを仕分ける
  たとえば、一行目データは種別A で パターンが「あ」のカードの
  「1.」の列に 1 と書きこむ。
  たとえばに行目のデータは一行目と同じ位置なので、カードAのその位置に
  1 を加算する。
  たとえば5行目データは種別Bのカードのパターン「対象外」なので
  「対象外」行の「2.」の列に1 を加える。

(5) Sheet2に 種別の数だけカード型データベースを発行する
┌────────────────┐
│種別A パターン  1. 2. 3.   │
│    あ            │
│    い            │
│    う            │
│   対象外          │
│   調査中          │
└────────────────┘

【75844】Re:パターン別に集計したいです。
発言  kanabun  - 14/7/13(日) 11:56 -

引用なし
パスワード
   ▼初心者 さん:

>《イメージ》
>【Sheet1】                → パターン仕訳け
>-------------------------------------
>種別 1. 2. 3. パターン 対象外
>A   1       あ         →A の「あ」の行
>A   1       あ         →A の「あ」の行
>A     1     い         →A の 「い」の行
>B     1  1   う         →B の 「う」の行
>B     1          S     →B の「対象外」の行
>C       1             →C の「調査中」の行
'

Sub Try1()
  Dim i As Long, n As Long, m As Long
  Dim dic As Object '種別を調べるための箱を用意します。
  Set dic = CreateObject("Scripting.Dictionary")
  
  Dim r As Object
  Dim v
  Set r = Worksheets(1).[A1].CurrentRegion '表データを配列に入れる
  v = Intersect(r, r.Offset(1)).Value   '入れる(一行目は除く)

'(1) 種別の種類を調べる → A,B,C
  For i = 1 To UBound(v)
    If Not dic.Exists(v(i, 1)) Then
      n = n + 1
      dic(v(i, 1)) = n
    End If
  Next  '以上で 種別 A(1), B(2), C(3) が完成()内は行番号
  
'(2) パターンの種類を調べる → 「あ」,「い」,「う」
  Dim dic2 As Object
  Set dic2 = CreateObject("Scripting.Dictionary")
  m = 0
  For i = 1 To UBound(v)  '5列目を調べる
    If Not IsEmpty(v(i, 5)) Then
      If Not dic2.Exists(v(i, 5)) Then
        m = m + 1
        dic2(v(i, 5)) = m
      End If
    End If
  Next
' パターンとしてはこれ以外に「対象外」「調査中」を追加。
  Dim mout&, mcho&
  m = m + 1
  dic2("対象外") = m: mout = m
  m = m + 1
  dic2("調査中") = m: mcho = m
  
'(3) 以上が分ったら、
'  種別の数だけ大きい箱を用意する
'  箱の中に パターンの数だけの小さい箱を入れる
'  そのパターン用の小さい箱のなかは 1. | 2. | 3. の仕切りを入れる
  ReDim Ot(1 To n, 1 To m, 1 To 3)
'  ┌────────────────┐
'n=1│種別A パターン  1. 2. 3.   │
'  │   1 あ            │
'  │   2 い            │
'  │   3 う            │
'  │   4 対象外         │
'  │   5 調査中         │
'  └────────────────┘
  
'(4) もう一度Sheet1の表を上から順に読んでいって、データを仕分ける
  Dim j As Long, x As Long
  For i = 1 To UBound(v)
    n = dic(v(i, 1))
    If Not IsEmpty(v(i, 5)) Then
      m = dic2(v(i, 5))
    Else
      If v(i, 6) = "S" Then
        m = mout
      Else
        m = mcho
      End If
    End If
    '[1.][2.][3.]列の値1を調べる(あれば配列要素位置に加算)
    For j = 1 To 3
      x = j + 1
      If v(i, x) > 0 Then
        Ot(n, m, j) = Ot(n, m, j) + v(i, x)
      End If
    Next
  Next
  
'(5) Sheet2に 種別の数だけカード型データベースを発行する
  Sheet2.Select
  Sheet2.UsedRange.ClearContents
  Dim a, b, c
  Dim y As Long
  y = 1
  [A1:E1].Value = Split("種別 パターン 1. 2. 3.")
  For Each a In dic.Keys()
    y = y + 1
    Cells(y, 1).Value = a
    n = dic(a)
    For Each b In dic2.Keys()
      y = y + 1
      Cells(y, 2).Value = b
      m = dic2(b)
      For j = 1 To 3
        If Ot(n, m, j) > 0 Then
         Cells(y, j + 2).Value = Ot(n, m, j)
        End If
      Next
    Next
  Next
End Sub

【75845】Re:パターン別に集計したいです。
お礼  初心者  - 14/7/13(日) 20:16 -

引用なし
パスワード
   ▼kanabun さん:
ご返信、ご回答本当にありがとうございました。
当方、記憶マクロしか使ったことがなく、本集計も当初ピボットテーブルの記憶マクロで行おうと思っていたのですが、これを機にVBAについて勉強しようと思い、本照会をさせていただきました。
いただいたご回答について、私の考えていた処理よりシンプルでとても参考になります。そもそものロジックの考え方から勉強しなおすべきだと痛感しました。
ご指摘は真摯に受け止め、今後は基礎から勉強いたしたいと思います。ありがとうございます。
最後になりますが、本質問にてご気分を害された方がいらっしゃいましたら申し訳ございませんでした。

【75846】Re:パターン別に集計したいです。
発言  γ  - 14/7/13(日) 20:31 -

引用なし
パスワード
   横から失礼します。

>今後は基礎から勉強いたしたいと思います。
と将来のことのように言わずに、

> まずはサンプルコードを読んで理解するところから始めたいと思いました。
とおっしゃったのですから、これを読まれて不明な点のひとつも
質問したらどうでしょう。

【75847】Re:パターン別に集計したいです。
回答  γ  - 14/7/13(日) 23:07 -

引用なし
パスワード
   記憶マクロではなく、マクロ記録です。
これだって、十分使えるものになるはずですし、
VBAの立派な教材になります。
(下記のコードも、マクロ記録を修正したものです。)

Sheet1をSheet2のような形にいったん変換して、
Sheet2を ピボットテーブルにすれば
Sheet3のような表が得られます。

【Sheet1】
  A  B  C  D  E    F
1 分類 1. 2. 3. パターン 対象外
2 A  1      あ
3 A  1      あ
4 A    1    い
5 B    1  1  う
6 B    1        S
7 C      1

【Sheet2】
  A列   B列   C列
1 分類  種類  パターン
2 A    1    あ
3 A    1    あ
4 A    2    い
5 B    2    う
6 B    3    う
7 B    2    対象外
8 C    3    調査中

【Sheet3】
     列ラベル      
行ラベル 1   2  3
A              
 あ   2         
 い      1    
 う             
 対象外           
 調査中           
B              
 あ             
 い             
 う      1  1
 対象外    1    
 調査中           
C              
 あ             
 い             
 う             
 対象外           
 調査中       1

(コード参考例)

Option Explicit

Dim ws1 As Worksheet
Dim ws2 As Worksheet
Dim ws3 As Worksheet

Sub test()
  Dim category As String
  Dim goods As String
  Dim pattern As String
  Dim k As Long, j As Long
  Dim p As Long

  Set ws1 = Worksheets("Sheet1")
  Set ws2 = Worksheets("Sheet2")
  Set ws3 = Worksheets("Sheet3")
  p = 1

  '(1)Sheet2に別フォーマットで転記
  For k = 2 To ws1.Range("A1").End(xlDown).Row
    category = ws1.Cells(k, 1).Text
    pattern = getPattern(k)
    For j = 2 To 4
      If ws1.Cells(k, j).Value = 1 Then
        goods = getGoods(j)
        p = p + 1
        Call writeToSheet2(p, category, goods, pattern)
      End If
    Next
  Next

  '(2)それをもとにピボットテーブルをSheet3に作成
  makePivotTable

End Sub

Function getPattern(k As Long) As String
  If Len(ws1.Cells(k, 5).Value) > 0 Then
    getPattern = ws1.Cells(k, 5).Value
  ElseIf ws1.Cells(k, 6).Value = "S" Then
    getPattern = "対象外"
  Else
    getPattern = "調査中"
  End If
End Function

Function getGoods(j As Long) As String
  getGoods = CStr(j - 1)
End Function

Function writeToSheet2(p As Long, category As String, goods As String, pattern As String)
  ws2.Cells(p, 1).Value = category
  ws2.Cells(p, 2).Value = goods
  ws2.Cells(p, 3).Value = pattern
End Function

Sub makePivotTable()
  Dim myRange As Range
  Dim pvCache
  Dim pbTable
  
  Set myRange = ws2.Range("A1").CurrentRegion
  Set pvCache = ActiveWorkbook.PivotCaches.Create(SourceType:=xlDatabase, _
    SourceData:=myRange.Address(external:=True), _
    Version:=xlPivotTableVersion14)
  Set pbTable = pvCache.CreatePivotTable _
      (TableDestination:=ws3.Range("A1"), _
      DefaultVersion:=xlPivotTableVersion14)
  With pbTable
    With .PivotFields("分類")
      .Orientation = xlRowField
      .Position = 1
    End With
    With .PivotFields("パターン")
      .Orientation = xlRowField
      .Position = 2
    End With
    With .PivotFields("種類")
      .Orientation = xlColumnField
      .Position = 1
    End With

    .AddDataField .PivotFields("種類"), "データの個数 / 種類", xlCount
    
    With .PivotFields("種類")
      .Orientation = xlColumnField
      .Position = 1
    End With

    .SortUsingCustomLists = False
    .PivotFields("分類").AutoSort xlAscending, "分類"
    .PivotFields("パターン").ShowAllItems = True
    
    .ColumnGrand = False
    .RowGrand = False
    .PivotFields("分類").Subtotals = Array( _
        False, False, False, False, False, False, False, False, False, False, False, False)
  End With
End Sub

【75848】Re:パターン別に集計したいです。
発言  γ  - 14/7/13(日) 23:25 -

引用なし
パスワード
   >Sub makePivotTable()
>  Dim myRange As Range
>  Dim pvCache
>  Dim pbTable
pbTable は すべて
pvTable に読み替えてください。タイプミスに気づかず。

【75849】Re:パターン別に集計したいです。
発言    - 14/7/14(月) 7:26 -

引用なし
パスワード
   横から失礼します。

>当方、記憶マクロしか使ったことがなく、(中略)これを機にVBAについて勉強しようと思い

ご存じない方が誤解されるといけないので。
「マクロの記録」とVBAは、別物ではありません。

「マクロの記録」の初心者は、ともすれば記録したマクロをそのまま
使おうとされますが、そしてそれ以外の使い方があるとは思いもよらない
ようですが。

「マクロの記録」は、エクセル本人にサンプルコードを作らせるための
ものです。そして、作られたコードを見て、コードの書き方を理解する
ためのものです。あるいは、作られたコード(の一部)を、自分が書いて
いるコードの部品として使うためのネタ取り用です。

VBAを勉強すると言いながらマクロの記録を軽視するのは
宝の持ち腐れです。

弱点もありますけどw
上手に使えば大きな武器になります。


▼初心者 さん:
>▼kanabun さん:
>ご返信、ご回答本当にありがとうございました。
>当方、記憶マクロしか使ったことがなく、本集計も当初ピボットテーブルの記憶マクロで行おうと思っていたのですが、これを機にVBAについて勉強しようと思い、本照会をさせていただきました。
>いただいたご回答について、私の考えていた処理よりシンプルでとても参考になります。そもそものロジックの考え方から勉強しなおすべきだと痛感しました。
>ご指摘は真摯に受け止め、今後は基礎から勉強いたしたいと思います。ありがとうございます。
>最後になりますが、本質問にてご気分を害された方がいらっしゃいましたら申し訳ございませんでした。

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