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

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

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

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

Q&A

解決済

5回答

2114閲覧

データーチェックロジック

退会済みユーザー

退会済みユーザー

総合スコア0

VBA

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

0グッド

0クリップ

投稿2017/01/04 08:34

編集2017/01/04 08:46

毎度毎度、お世話になっております。

データーのチェックロジックについてご教授下さい。
D列にあるMACアドレスがK列に存在しない場合は、H列にNo_matchと記入するように
データーのチェックを行いたいのですが、

下記コードだと、上手く行きません。。。。
K列内に絶対にあるのに、最初のデーターチェックでNo_matchとなってしまいます。。。
ただ単に、ループで各データーを見るだけじゃダメなんですね。。。
VBAの中で、ワークシート関数を使うとか・・・。。。

vba

1'作業前後でMACアドレスの差分チェックを行う。 2'作業前のMACアドレス(D列)を元に作業後のMACアドレ(K列)スの比較を行う。 3'K列にD列のMACアドレスが無かった場合には、H列にNo_matchと入力する。 4 5 i = 3 6 Do While Cells(i, "D").Value <> "" 7 j = 3 8 Do While Cells(j, "K").Value <> "" 9 If Cells(i, "D").Value <> Cells(j, "K").Value Then 10 Cells(i, "H").Value = "No_match" 11 End If 12 j = j + 1 13 Loop 14 i = i + 1 15 Loop

イメージ説明

どなたかご教授下さい。

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

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

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

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

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

guest

回答5

0

問題点の整理

まず提示コードの処理を整理すると、以下のような流れになっています。

①D列取得行を先頭に設定 (D列ループを開始) ②K列取得行を先頭に設定 (K列ループ開始) ③D列・K列から1セルずつ取り出す ④D列から取り出したセルの値とK列から取り出したセルの値を比較 ⇒一致していれば何もしない ⇒不一致なら"No_match" ⑤K列取得行カウントアップ (K列ループここまで) ⑥D列取得行カウントアップ (D列ループここまで)

やりたいことは
「K列に一致するセルを見つけたら空欄、見つからなければ"No_match"を記述する処理」
だと思いますが、提示コードの処理の流れは、
「K列に不一致セルが(1つでも)あれば"No_Match"を記述し、一致するセルがあっても何もしない処理」
となっています。

④でセルの一致判定をしていますが、ループを抜ける処理は特にないためすべての行に対して処理が行われます。

つまり、途中で一致するセルを見つけたとしてもK列の次以降のセルとの比較を続けてしまうため、どこかで不一致セルを見つけた時点で"No_match"を書き込んでしまいます。
ほとんどが不一致のものの中から一致するものの有無を探すわけですから、ほぼ必ず"No-match"となってしまうのではないでしょうか?

修正案①

今のコードをベースに修正するのなら、④の判定部分を
⇒一致していれば空欄にしてExitDo
⇒不一致なら"No_match"を記述
という流れに変更すればいいでしょう。

修正案②

提示コードをベースにせず、私が独自で作成するとしたら、NuuさんのアドバイスにもあるFindを使うと思います。

Sub test() Dim rngSrchArea As Range '検索範囲 Set rngSrchArea = Range("K:K") 'D列をループ処理 Dim iRow As Integer For iRow = 3 To Cells(Rows.Count, "D").End(xlUp).Row 'D列の値を検索範囲から検索 If rngSrchArea.Find(What:=Cells(iRow, "D").Value) Is Nothing Then '一致するものがなければH列に"No_match"を記述 Cells(iRow, "H").Value = "No_match" End If Next End Sub

別案(Excel関数)

今回やりたい内容は、VBAを使わずに実現することもできます。
たとえばH3セルに=IF(COUNTIF(K:K,D3)>0,"","No_match")と記述し、この式をH列の対象範囲にコピーすれば、目的の結果が得られると思います。

「セルに式は残したくない、値で入れたい」とか「ほかでもマクロを使っているからこれもマクロの方がラクチン!」というのであれば選択肢には入りませんが、一応別案として紹介しました。

参考になれば幸いです。

投稿2017/01/05 02:13

編集2017/01/05 02:15
jawa

総合スコア3013

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

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

退会済みユーザー

退会済みユーザー

2017/01/05 09:58

アドバイス有難うございます。
guest

0

Findを使ったコードを書いてみました。動作検証済みです。
参考になりましたら幸いです。

VBA

1'作業前MACアドレス 2D_FirstRow = 3 3D_LastRow = Cells(Rows.Count, "D").End(xlUp).Row 4Set BeforeWork = Range(Cells(D_FirstRow, "D"), Cells(D_LastRow, "D")) 5 6'作業後MACアドレス 7K_FirstRow = 3 8K_LastRow = Cells(Rows.Count, "K").End(xlUp).Row 9Set AfterWork = Range(Cells(K_FirstRow, "K"), Cells(K_LastRow, "K")) 10 11'データチェック 12For Each target In AfterWork 13 Set result = BeforeWork.Find(What:=target.Value) 14 '作業前MACアドレスと一致しなかった場合 15 If result Is Nothing Then 16 Cells(target.Row, "H").Value = "No_match" 17 '作業前MACアドレスと一致した場合 18 Else 19 Cells(target.Row, "H").Value = "" 20 End If 21Next

投稿2017/01/04 13:10

N-u-u

総合スコア113

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

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

退会済みユーザー

退会済みユーザー

2017/01/05 09:59

少しずつ勉強し、今後の参考にさせていただきます。
guest

0

数式を貼り付けちゃうとか
マクロより数式なら結構わかる人がいるような気がする

ExcelVba

1**間違い** 2Application.ScreenUpdating = False 3 For i = 3 To 16 4 Cells(i, "H") = "=IF(" & Cells(i, "K").Address & ">0,IF(ISERROR(MATCH(" & Cells(i, "K").Address & ",$D$3:$D$14,0)),""No_match"",IF(MATCH(" & Cells(i, "K").Address & ",$D$3:$D$14,0),"""",""No_match"")),""No_match"")" 5 Next i

参照列逆だった

ExcelVba

1**修正** 2Application.ScreenUpdating = False 3 For i = 3 To 14 4 Cells(i, "H") = "=IF(" & Cells(i, "D").Address & ">0,IF(ISERROR(MATCH(" & Cells(i, "D").Address & ",$k$3:$k$15,0)),""No_match"",IF(MATCH(" & Cells(i, "D").Address & ",$k$3:$k$15,0),"""",""No_match"")),""No_match"")" 5 Next i

投稿2017/01/04 13:43

編集2017/01/04 22:29
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

0

WorksheetFunctionを使うと遅くなるとか賛否両論あると思いますが、コードをすっきりさせるので以下のようなコードに直してみました。End(xlUp)を使うとセルの終わりのチェックが省けるのとCOUNTIF関数の範囲指定が確定できます。

EXCEL

1 MaxRow = Range("K65536").End(xlUp).Row 2 For i = 3 To MaxRow 3 cnt = Application.WorksheetFunction.COUNTIF(Range("D3:D" & Trim(str(MaxRow))),Range("K" & Trim(str(i))) 4 If cnt = 0 Then 5 Cells(i, "H").Value = "No_match" 6 End if 7 Next

投稿2017/01/04 11:52

seastar3

総合スコア2285

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

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

0

ベストアンサー

コードをパッと見ると、ループが必ず最後まで回っているので、K列の一番最後と比べる様になっていますね…
こんな形で如何でしょうか?
この様なループを回さなくてもfindを使ったり、色々な手立てもあると思いますよ。

'作業前後でMACアドレスの差分チェックを行う。 '作業前のMACアドレス(D列)を元に作業後のMACアドレス(K列)の比較を行う。 'K列にD列のMACアドレスが無かった場合には、H列にNo_matchと入力する。 i = 3 Do While Cells(i, "D").Value <> "" j = 3 Cells(i, "H").Value = "No_match" Do While Cells(j, "K").Value <> "" If Cells(i, "D").Value = Cells(j, "K").Value Then Cells(i, "H").Value = "" exit Do End If j = j + 1 Loop i = i + 1 Loop

投稿2017/01/04 08:43

編集2017/01/04 09:07
motuo

総合スコア3027

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

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

退会済みユーザー

退会済みユーザー

2017/01/04 08:59

H列のMACアドレスが、K列で見つかった場合、exit doをするとのことですが、この場合、 if文を抜けて、jが+1カウントアップされるのでしょうか? iがカウントアップされないといけないような気がしますが・・・・。
motuo

2017/01/04 09:07 編集

見つかった時点でK列のループを抜ける、というつもりで書いてみました。その意味で変数jのカウントアップは不要ですよね? また、書いたexit doはK列のDo whileに対して有効なのでiはカウントアップされますよ。
jawa

2017/01/05 01:59

横から失礼しますm(__)m 処理をわかりやすくするコツとして、わかりやすい変数名を命名するというものがあります。 iやjという変数名でもプログラムは動いてくれますが、人が見た時に直観的ではないですよね? 今回の場合、たとえばi⇒iRow_D、j⇒iRow_Kのような名前にすると、iRow_KはK列ループを抜けた後D列ループの先頭でリセットされるのでカウントアップは不要ということがわかりやすくなると思いますよ。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問