重要なお知らせ

「教えて! goo」は2025年9月17日(水)をもちまして、サービスを終了いたします。詳細はこちら>

【GOLF me!】初月無料お試し

教えて下さい。

下のような元表があり、これを利用して日付と個数を把握したいと思ってます。
これはひと月のもので、配達は0回もあれば、複数回ある事も。(最大で15回程度)
VBAで結果シートに名前別で、配達があった日付順に個数を表示したいのです。

元表(月)
      A  B  C     J     AG
   1 名前 番号 配達日1  配達日8  配達日31
   2  あ           3
   3  い     6      
   4  う                  7
   5  お

この表で、配達日8がその月の8日の事で、3が個数の事です。

C2~AG2の合計が0より大きければ入力があるとして
この範囲の最初に入力があるセルを特定(J2)して個数(3)を転記
セルの列番号を知る(Jだと10)
基準のセルを決めておいて(Bだと2)、その列番号との差で日付(10-2)で8を出して転記
次の入力があるセルから順次、配達回数分繰り返す(15回)
これを人数分繰り返す
配達先(名前)の増減もあり


結果シート(結果)

     A   B   C ― D   E ― F      AE ― AF   
   1名前  番号    1回目     2回目        15回目 
   2        日付  個数  日付  個数      日付   個数        
   3 あ       8   3   
   4 い       1   6
   5 う      31   7
   6 え
   7 お

上記のように結果シートには出力したいのです。 1回目~15回目のところは結合セルのつもりです。

   
Dim ZZZ As Long

ZZZ = Worksheets("月").Range("A" & Rows.Count).End(xlUp).Row

Worksheets("結果").Range("A2:A" & ZZZ + 2).Value = Worksheets("月").Range("A1:A" & ZZZ + 2).Value

など、増減は出来たのですが、その先がどうもうまくいきません。(ここが重要ですが・・・)
変数、条件分岐 繰り返し等

詳しい方どうぞ教えてください。

質問者からの補足コメント

  • お世話になりました。 初心者として大変勉強になります。 しかし、全部は理解できませんでした。
    わからなかった所は、’元表をループ の所で、Do While の行です。 
    初めにr=2とあるので、シート1の(2,1)のセルが、つまりA2が・・・で詰まりました。 A2が空白?でない時だけ、下の行If~以降の命令を実行せよ? だから名前が無い人(A列の空欄)はシート2に出ない であってますか? 
    それと、お答え頂いたこの回答コード? VBA? 何と言えばいいのか・・・、ともかく最大15回の配達を超えても対応しているので、凄いです。 

    また、シート2に結果を出す時にA3から表示したい時、又は配達0回の人も表示したい場合はどうなるのでしょうか? 聞いてばかりで申し訳ないですが、よろしくお願いします。

    No.3の回答に寄せられた補足コメントです。 補足日時:2015/10/28 00:55

A 回答 (4件)

補足を拝見しました。



Do While の行ですが、ご認識は違います。
Do While は、〜している間はループし続けろという構文ですから、
ここでは、シート1のA列が空白でない間はループし続けろ、
つまり、データがなくなるまで処理せよ、という文です。

今回は配達先の増減がある、つまり、何人分かは不定ですから、
Do While 〜 Loopで回しています。
もし、配達先が20人で固定なのであれば、
For r=2 To 21 などのように、For Next で回せばよいですが。
で、Do Loop の場合は、For Nextのようにカウンタの初期値や、
増加は勝手にしませんから、2行めから処理を開始ということで、
ループ開始前に、r=2 で初期値を与え、最後のLoop の前に、
r=r+1 として、カウンタを増加させています。

1行目は見出し、データは2行めから開始という認識で組んだ
コードですが、A列(配達先)において、途中で空白セルは
存在するのでしょうか。
それは想定していませんでした。A列は2行めから最後まで空白無しを
前提としています。
A2セルが空白ということは、1行めが見出しとして、いきなり空白?
ならばコードは変わります。
最初に、シート1の最終行を取って、For r=2 To 最終行 〜Next
で回すとか。

>シート2に結果を出すときA3から
TgtRow を取得する時にIf分岐をかまして、TgtRow <3 なら、TgtRow=3 としとけば
良いと思います。
で、Else それ以外なら今の取得方法。

>配達0回の人も表示
これは、CからAGの合計が>0なら、というIf文を外せばよいでしょう。


今回のコードは良く見ていただくと分かると思いますが、
この作業を、人間が手作業でやった時の動きをコードにした
だけのものてす。
特に複雑なロジックは無いと思います。

データの始まりから順に下に見ていく。データの終わりまで。
これがDo Loop。
2行めから1行づつ見て、配達回数(CからAGの合計)が、一回以上ならシート2に名前を転記。
(書いてませんけど、配達回数がゼロならスルー)
これが、If 文のところ。

転記する先は、シート2で、今データが入っている最終行の次に
なるわけですから、これの取得が、TgtRow。

データの転記については、回数があるセルだけ、日付と回数を、
シート2の該当行に、左詰めで書いていくわけなので、左詰めは
どこかを探すのが、TgtCol。
で、そこに、日付と回数を転記していく。

結局、手作業でやる時も、こうやって処理するはずです。
あまり難しく考えなくていいですよ。
ご不明点あればまたどうぞ。
    • good
    • 0
この回答へのお礼

また、丁寧な回答ありがとうございます。 完璧になりました。 ちなみに途中の空白はありません。 配達無しを表示も、=を追加でOKでした。 自分が思ったように出来るよう、もっと勉強します。 本当にありがとうございました。

お礼日時:2015/10/28 23:41

#2です。


1枚目を元表、2枚目を結果シートとして。
1か月間配達ゼロの人は表示していません。
以下でどうでしょうか。

'------------------------------------------------------
Option Explicit

Sub Tenki()
'変数宣言とセット
Dim Ws1 As Worksheet, Ws2 As Worksheet
Dim WSF As Object
Dim r As Long, c As Integer
Dim TgtRow As Long, TgtCol As Integer
Dim Hiduke As Integer, Kosu As Integer

Set Ws1 = Worksheets(1)
Set Ws2 = Worksheets(2)
Set WSF = Application.WorksheetFunction

'元表をループ
r = 2
With Ws1
Do While .Cells(r, 1).Value <> ""
If WSF.Sum(.Range(.Cells(r, 3), .Cells(r, 33))) > 0 Then 'C~AG計が0以上なら
TgtRow = Ws2.Cells(Rows.Count, 1).End(xlUp).Row + 1 '結果シートの最終行を取得
Ws2.Cells(TgtRow, 1).Value = .Cells(r, 1).Value '結果のA列に名前
Ws2.Cells(TgtRow, 2).Value = .Cells(r, 2).Value '結果のB列に番号

For c = 3 To 33 'C列からAG列までループ
If .Cells(r, c).Value > 0 Then '配達個数が0以上なら
Hiduke = c - 2 '日付は列番-2
Kosu = .Cells(r, c).Value '個数
TgtCol = Ws2.Cells(TgtRow, Columns.Count).End(xlToLeft).Column + 1 '結果シートの最終列
Ws2.Cells(TgtRow, TgtCol).Value = Hiduke '日付を入れる
Ws2.Cells(TgtRow, TgtCol + 1).Value = Kosu 'その右に個数を入れる
End If
Next c
End If

r = r + 1
Loop
End With

MsgBox "End."

End Sub
'------------------------------------------------------
この回答への補足あり
    • good
    • 0

ちょっといまPCの前じゃないんで、ざっくりですけど、



元表の二行目から最後までループ
その中でC列からAG列までループ。
値がゼロ以上なら、というIf分岐を入れる。
結果シートの最終行、最終列を取り、そこに、日にち、値(個数)を入れる。
そこの c から2を引けば日にちが出る。

これの繰り返し。

ではどうでしょう?

r=2
Do While Worksheets("元表").Cells(r,1).Value<>""
For c=3 To 33
If Worksheets("元表").Cells(r,c).Value>0 Then

って感じ。
配達ゼロの人は結果シートには出さない?

イメージだけで実際に回してないんで、うまく回るか分かりませんが、
ご参考まで。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。この回答を念頭に置きながら、自分で色々やってみて、やはり少し無理かなと思ってページに戻ってきたら・・・なんかすごい答えが待ってました。 
ありがとうございます。ちょっと自分なりに検討(解読)してみます。 私には難易度が高そうなので・・・。  後日、分からな所をここで質問させてください。 よろしくお願いします。

お礼日時:2015/10/27 01:23
    • good
    • 0
この回答へのお礼

ありがとうございます。すごく参考になります。もう少し勉強します。

お礼日時:2015/10/26 23:23

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