質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Q&A

解決済

3回答

4156閲覧

ループ処理がうまくいかない

退会済みユーザー

退会済みユーザー

総合スコア0

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

0グッド

0クリップ

投稿2020/05/20 07:28

ここで教えて頂きながら、下記作業のマクロを作っているのですが、わからないところが出てきました。
コード内のコメント部分なのですが、自分でコードを書いてみましたがうまくいきません。
どなたかご教授いただけないでしょうか。

①Sheet1の品番とSheet2の品番が一致すれば、Sheet2の日付に本日を入れる
②Sheet1の品番がSheet2に存在しなければ、Sheet2の最終行をコピーして、Sheet2の最終行+1に貼り付ける
Sheet2に貼り付けた行のセル値をSheet1の値に書き換える
※数式をコピーしたいので、上記手順をとっています。
Sheet1
品番|名称|コメント|
001|aaa|あああ|
003|ccc|ううう|/
004|ddd|えええ|
005|eee|かかか|
Sheet2
日付|品番|名称|コメント|数式|数式2|・・・続く
0512|001|aaa|あああ|数式|数式2|・・・続く
|002|bbb|いいい|数式|数式2|・・・続く
0512|003|ccc|ううう|数式|数式2|・・・続く
0512|004|ddd|えええ|数式|数式2|・・・続く

下記コードでうまくいかないこと
・Elseの場合に、1つ目しかコピーできない。n=n+1といれてみたがうまくいかない
・最終行をコピーして、最終行+1に貼り付けた行のセル値を書き換えたいがうまくいかない

sub test() dim i as long dim j as long Set ws1 = Worksheets("Sheet1") Set ws2 = Worksheets("Sheet2") n = ws2.Cells(ws2.Rows.Count, 2).End(xlUp).Row + 1 For i = 2 To ws1.Cells(ws1.Rows.Count, 1).End(xlUp).Row For j = 2 To ws2.Cells(ws2.Rows.Count, 2).End(xlUp).Row If ws1.Cells(i, 1).Value = ws2.Cells(j, 2).Value Then ws2.Cells(j, 1).Value = Date Else ’品番が一致しなければ、最終行をコピーして、+1行目に貼り付ける ’※1つ目しか貼りつかない(ループ処理がうまくいかない) ws2.Rows(n - 1).Copy Destination:=ws2.Rows(n) ’貼り付けた行のセルの値をSheet1の品番、名称、コメントに書き換えたいがうまくいかない ws2.cells(j,2).value = ws1.cells(i,1).value ws2.cells(j,3).value = ws1.cells(i,2).value ws2.cells(j,4).value = ws1.cells(i,3).value    ’ここに n = n + 1 をいれたりしてみたがうまくいかない End If Exit For Next j Next i End Sub

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

ExcelVBA

1Sub test() 2 Dim ws1 As Worksheet 3 Dim ws2 As Worksheet 4 Dim i As Long 5 Dim j As Long 6 Dim k As Long 7 8 Set ws1 = Worksheets("Sheet1") 9 Set ws2 = Worksheets("Sheet2") 10 11 For i = 2 To ws1.Cells(ws1.Rows.Count, 1).End(xlUp).Row 12 k = ws2.Cells(ws2.Rows.Count, 2).End(xlUp).Row '最終行番号を記憶 13 For j = 2 To k 14 If ws1.Cells(i, 1).Value = ws2.Cells(j, 2).Value Then 15 ws2.Cells(j, 1).Value = Date 16 Exit For 17 End If 18 Next j 19 20 'ループが最後まで回った(=jの値がkの値を越えた)ら新規データとして追記 21 If j > k Then 22 '品番が一致しなければ、最終行をコピーして、+1行目に貼り付ける 23 '※1つ目しか貼りつかない(ループ処理がうまくいかない) 24 ws2.Rows(j - 1).Copy Destination:=ws2.Rows(j) 25 '貼り付けた行のセルの値をSheet1の品番、名称、コメントに書き換えたいがうまくいかない 26 ws2.Cells(j, 2).Value = ws1.Cells(i, 1).Value 27 ws2.Cells(j, 3).Value = ws1.Cells(i, 2).Value 28 ws2.Cells(j, 4).Value = ws1.Cells(i, 3).Value 29 End If 30 Next i 31End Sub

If ws1.Cells(i, 1).Value = ws2.Cells(j, 2).Value Then

の時には、「あった」は解りますが、「なかった」は確定してません。
「あった」の時にはそこでループを抜けて、
最後までループを回ったら、「なかった」と判断したらいいと思います。

少ないサンプルデータで、
ステップインで1行ずつ実行してみて、
変数「J」の値の変化をローカルウィンドウで確認してみてください。

あと、コード見て
変数を上手く使えるとより良いと思いました。(特にオブジェクト型の変数)
今の書き方だと、たくさんのデータ量の時に動作が重くなる可能性があります。
以下サンプル
(処理速度がどれくらい改善されるかわかりませんが^^;)

ExcelVBA

1Sub test2() 2 Dim rngNew As Range 3 Dim rngList As Range 4 Dim c As Range 5 Dim ixRow As Long 6 7 Set rngNew = Worksheets("Sheet1").Range("A1").CurrentRegion 8 9 For Each c In rngNew.Columns(1).Cells 10 Set rngList = Worksheets("Sheet2").Range("A1").CurrentRegion 11 On Error GoTo ErrLabel 12 ixRow = WorksheetFunction.Match(c, rngList.Columns(2), 0) 13 On Error GoTo 0 14 15 With rngList.Rows(ixRow) 16 .Cells(1).Value = Date 17 .Range("B1:D1").Value = c.Resize(, 3).Value 18 End With 19 Next 20 21 Exit Sub 22 23ErrLabel: 24 With rngList 25 .Rows(ixRow).Resize(2).AutoFill .Cells, xlFillFormats 26 ixRow = .Rows.Count + 1 27 Resume Next 28 End With 29End Sub

エクセルにはたくさんの関数が内包されています。
それを利用するとVBAでループ処理を書かなくて済むようになります。

勉強中なので何回でも0から書き直したほうがいいと思います。
結果が早く欲しいのは解りますが、
間違ったロジックで書いているものを部分部分で直していくと、
結局後で直したくなった時に読んでみてわからなくて、
1から書き直しになるので、、、
これくらいのマクロなら1からでも、サクッと書けるように、
何度でも1から書き直してみてはいかがでしょう?

※コンパイル&動作確認してないので、バグがある可能性があります。

参考になれば。

投稿2020/05/21 00:18

mattuwan

総合スコア2163

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2020/05/21 03:10

大変分かりやすくご説明いただき、ありがとうございます。 If j > k Thenの使い方もとても勉強になりました。 2つ目のコードも理解できるように、何度も0から書き直して勉強していきたいと思います。
guest

0

入力箇所間違えました。

投稿2020/05/20 09:29

編集2020/05/20 11:28
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

さくっと見た限り
Sheet1の品番がSheet2に存在しなければ
って書いてますので

vba

1For i = 2 To ws1.Cells(ws1.Rows.Count, 1).End(xlUp).Row 2 ' 存在チェックフラグ初期化(off) 3For j = 2 To ws2.Cells(ws2.Rows.Count, 2).End(xlUp).Row 4 ' 存在チェックしてフラグOnなどする(存在したらとっととjのループ抜けてもいいかと 5Next j 6 7 ' 存在チェック用フラグがOn/Offで処理を分ける 8Next i

が正解なのではないでしょうか?
あとws1.Cells(ws1.Rows.Count, 1).End(xlUp).Rowなどは動的に変更しそうな気がするから変数代入してそれを利用したほうがいいかも

投稿2020/05/20 07:59

rururu3

総合スコア5545

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2020/05/20 09:30

ありがとうございます。 elseの前まではうまく動いています。 マクロを勉強中で、いちから変更するのは時間的に厳しいです。else以降のコード修正では難しいでしょうか… ws1.Cells(ws1.Rows.Count, 1).End(xlUp).Rowを変数代入するやり方は取り入れたいと思います。勉強になります。
rururu3

2020/05/20 10:06

ws2.cells(j,2).value = ws1.cells(i,1).value ws2.cells(j,3).value = ws1.cells(i,2).value ws2.cells(j,4).value = ws1.cells(i,3).value jではなくnではとも思う
退会済みユーザー

退会済みユーザー

2020/05/20 10:38

確かにそうでした。 貼りつけ先はnとしているのでnでした。少し進めました。ありがとうございます!! else以降の作業を繰り返し行いたいのですが、n=n+1でいけないのでしょうか…
rururu3

2020/05/20 10:47

最初の回答通りFor処理で間違えてるから1つ目しか貼り付けないとおもう…
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問