アプリ版:「スタンプのみでお礼する」機能のリリースについて

マクロを使った集計システムを作成することになったのですが、マクロのマの字も知らない初心者です。
以下の表を集計するマクロを初心者向けで教えてください。

氏名        作業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」の作業を複数行っていたら、合計します。

すみませんが、よろしくお願いします。

A 回答 (2件)

こんにちは!


一例です。

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
    • good
    • 0

私が読んだ過去の本には


「プログラミングはデータ構造の設計とアルゴリズムの選択でほぼ終わる」
と、書いていました。

これをお示し頂いたものに当てはめると
データ構造の設計は、
主キーの配下に
氏名データ、社員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行少なくリサイズし
このレンジについて行全体を削除処理すれば良いでしょうか?


実際のプログラミングは「仕事」ですのでご自身でお願いしますね。



如何でしょうか?
お役に立てていたならば幸いです。
    • good
    • 0
この回答へのお礼

ありがとうございます。
サッパリ分かりませんが、おっしゃる通り仕事ですので、調べて見ます。

お礼日時:2013/05/14 13:48

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!