- 締切済み
超初心者がマクロ集計をすることになりました
マクロを使った集計システムを作成することになったのですが、マクロのマの字も知らない初心者です。 以下の表を集計するマクロを初心者向けで教えてください。 氏名 作業No 月No 時間内 時間外 社員No 山本太郎 3210 5 8 0 120 山本太郎 5120 8 8 12 120 山本太郎 3210 5 4 0 120 山田花子 1203 4 8 2 320 山田花子 3210 5 8 12 320 佐藤治郎 5201 10 8 8 91 佐藤治郎 3210 5 8 8 91 佐藤治郎 3210 5 8 12 91 という表があるとします。 これを、以下のようにしたい場合のマクロを教えてください。 氏名 社員No 作業No 時間内 時間外 山本太郎 120 3210-10 12 0 山本太郎 120 5120-8 8 12 山田花子 320 1203-4 8 2 山田花子 320 3210-5 8 12 佐藤治郎 91 5201-10 8 8 佐藤治郎 91 3210-10 16 20 ※作業Noと月Noのデータを“-”をつけて結合しています。 ※1人が同じ「作業No+月No」の作業を複数行っていたら、合計します。 すみませんが、よろしくお願いします。
- みんなの回答 (2)
- 専門家の回答
みんなの回答
- tom04
- ベストアンサー率49% (2537/5117)
こんにちは! 一例です。 Sheet1のデータをSheet2に表示するようにしてみました。 尚、Sheet2の1行目項目は入力済みだとします。 Alt+F11キー → メニュー → 挿入 → 標準モジュールに↓のコードをコピー&ペーストして マクロを実行してみてください。 (Alt+F8キー → マクロ → マクロ実行です) Sub Sample1() 'この行から Dim i As Long, endRow As Long, c As Range, wS1 As Worksheet, wS2 As Worksheet Set wS1 = Worksheets("Sheet1") Set wS2 = Worksheets("Sheet2") Application.ScreenUpdating = False endRow = wS2.Cells(Rows.Count, 1).End(xlUp).Row If endRow > 1 Then wS2.Rows(2 & ":" & endRow).ClearContents End If endRow = wS1.Cells(Rows.Count, 1).End(xlUp).Row wS1.Range("A:A").Insert With Range(wS1.Cells(2, 1), wS1.Cells(endRow, 1)) .Formula = "=B2&C2" .Value = .Value End With wS2.Range("A:A").Insert For i = 2 To endRow Set c = wS2.Range("A:A").Find(what:=wS1.Cells(i, 1), LookIn:=xlValues, lookat:=xlWhole) If c Is Nothing Then With wS2.Cells(Rows.Count, "A").End(xlUp).Offset(1) .Value = wS1.Cells(i, "A") .Offset(, 1) = wS1.Cells(i, "B") .Offset(, 2) = wS1.Cells(i, "G") .Offset(, 3) = wS1.Cells(i, "C") & "-" End With End If Next i For i = 2 To wS2.Cells(Rows.Count, 1).End(xlUp).Row With wS2.Cells(i, "D") .Value = .Value & WorksheetFunction.SumIf(wS1.Range("A:A"), wS2.Cells(i, 1), wS1.Range("D:D")) .Offset(, 1) = WorksheetFunction.SumIf(wS1.Range("A:A"), wS2.Cells(i, 1), wS1.Range("E:E")) .Offset(, 2) = WorksheetFunction.SumIf(wS1.Range("A:A"), wS2.Cells(i, 1), wS1.Range("F:F")) End With Next i wS1.Range("A:A").Delete wS2.Range("A:A").Delete Application.ScreenUpdating = True End Sub 'この行まで ※ 細かい説明は割愛します。考え方として・・・ (1)Sheet1・Sheet2ともA列を挿入 → 作業列として使用 → 元データのA列とB列を「&」でつなげています。 (2)あとはそれぞれのA列を使って、SUMIF関数で対応できると思います。 参考になりますかね?m(_ _)m
- Nouble
- ベストアンサー率18% (330/1783)
私が読んだ過去の本には 「プログラミングはデータ構造の設計とアルゴリズムの選択でほぼ終わる」 と、書いていました。 これをお示し頂いたものに当てはめると データ構造の設計は、 主キーの配下に 氏名データ、社員No.、作業No.、時間内勤務時間、時間外勤務時間、 この5つのデータがあれば、1件のデータが成立すると解ります。 折角のVBAなのですから これを隠し作業用シートに縦に並べれば仕事が楽でしょう 次にアルゴリズムですが 考えるべきは追加、削除、統合、でしょうか? 追加は 折角のシートなのでソート機能を使っても良いのですが、 MAX(INDEX((社員No.の列=追加する社員No.)*(作業No.の列=追加する作業No.)*ROW(社員No.の列),,)) これを評価し自然数だった場合はその次に挿入 そうじゃなかった場合 MAX(INDEX((社員No.の列=追加する社員No.)*ROW(社員No.の列),,)) これを評価し自然数だった場合はその次に挿入 そうじゃなかった場合 データの一番下に挿入 削除は 削除済み値用データ群に移動(カット&ペースト) して件数を減少 集計、統合、は WITH 隠しシート名 LARGE(INDEX((社員No.の列=追加する社員No.)*(作業No.の列=追加する作業No.)*ROW(社員No.の列),,),ROW(.RANGE(.CELLS(1,1),.CELLS(COUNTA(社員No.の列),1)))) END WITH これを評価し (※注:動作未確認です) RANGEで返させて 次男内の列と時間外の列にオフセットし 総和を取り RANGえの.ROWの値のセルに書き込み Rengeを1つオフセットし、1行少なくリサイズし このレンジについて行全体を削除処理すれば良いでしょうか? 実際のプログラミングは「仕事」ですのでご自身でお願いしますね。 如何でしょうか? お役に立てていたならば幸いです。
お礼
ありがとうございます。 サッパリ分かりませんが、おっしゃる通り仕事ですので、調べて見ます。