[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『データの一致、不一致』(あめ)
2つの表を比較を照合して名前と金額が一致していたら「OK」、
不一致の場合は「FALSE」としたいです。
参考になりそうなコードを見つけたのですがマクロが始めてで
自分のやりたいことへの直し方が分かりません。
どこを直した方がよいのか教えていただけないでしょうか。
参照先シートの表のそれぞれの項目の金額が正しいことを各検証シートで
検証しております。
検証シートのA列とB列は検証結果です。
この検証結果と参照先シートが一致しているかどうか、検証シートのC列に
結果を表示させたいです。
検証シートで名前と金額が漏れている場合、何か知る方法はあるのでしょうか。
どんなことでもよいので ご指導お願いいたします。
(参照先シート)
____A____B____C___D_____E___
1 名前 りんご ばなな いちご みかん
2 田中 100 80 60
3 松田 20 50 100
4 佐藤
5 山田 30 130 60 80
6 鈴木 70 150
(りんご検証シート)
____A____B____C___D_____E___
1 名前 りんご 結果
2 田中 100 OK
3 松田 20 OK
4 山田 30 OK
Sub sample2_2() Dim hida As Long Dim migi As Long Dim ws1 As Worksheet Dim ws2 As Worksheet
Set ws1 = Worksheets("sample2_1") Set ws2 = Worksheets("sample2_2")
For migi = 2 To 11 For hida = 2 To 21 If ws2.Range("A" & migi).Value = ws1.Range("B" & hida).Value Then ws1.Range("C" & hida).Value = "OK" Exit For End If Next Next
For hida = 2 To 21 If ws1.Range("C" & hida).Value = "" Then ws1.Range("C" & hida).Interior.Color = vbYellow Else ws1.Range("C" & hida).Interior.Color = xlNone End If Next End Sub
< 使用 Excel:Excel2010、使用 OS:Windows7 >
> If ws2.Range("A" & migi).Value = ws1.Range("B" & hida).Value Then 一方のA列と他方のB列を比較していますが、A列は名前、B列は数値なので、一致するはずはないですよね? ws1とws2のA列同士、B列同士が両方共一致して、初めてOKになるのでは? (???) 2019/01/31(木) 14:47
ぶつかり。
マクロが良いんでしょうか? Vlookupで、すみそうな気もします。 因みに、マクロで書けと言われたら、やっぱりVlookup使っちゃいます。 (BJ) 2019/01/31(木) 14:52
数式だと、こんな感じ?? =IF(VLOOKUP($A2,参照先シート!$A$1:$E$6,MATCH($B$1,参照先シート!$1:$1,0),0)=$B2,"OK",False) (BJ) 2019/01/31(木) 15:08
>検証シートで名前と金額が漏れている場合、何か知る方法はあるのでしょうか。 これって、検証シートには名前・商品名・金額があらかじめ入力されていて、 参照先シートに「無い」ものを見つけるんですか? それとも 検証シートに「無い」ものを見つけるんですか?
田中さんが二人いたりしませんか?
二人いた場合、合算でしょうか? 別の場合、どのように見分けたらよいですか? (稲葉) 2019/01/31(木) 15:15
今はVLOOKUPでやっているのですが式を壊す人がいるので毎回修正しておりましたら
データも多く時間がかかるのでマクロで作成するように言われました。
でもマクロ作ったことが無いので このコードで大丈夫かも分からず
こちらに相談させていただきました。
どんなことでもよいので教えていただけないでしょうか。
よろしくお願いいたします。
>これって、検証シートには名前・商品名・金額があらかじめ入力されていて、 参照先シートに「無い」ものを見つけるんですか? それとも検証シートに「無い」ものを見つけるんですか?
検証シートには名前・商品名・金額があらかじめ入力されております。
検証シートに無いものを見つけたいです。
>田中さんが二人いたりしませんか?
いません。
(あめ) 2019/01/31(木) 16:42
>今はVLOOKUPでやっているのですが式を壊す人がいるので毎回修正しておりましたら >検証シートに無いものを見つけたいです。 ん?
Vlookupでチェックしたときに、BJさんの数式でチェックしたとして、検証シートにない人はチェックできなくないですか? 仮に参照先シートに鈴木さんがりんごを10円買っていたとして 今回の検証シートに鈴木さんは居ないので、すべてOKとなってしまいますよね? 本来は鈴木さんがいなくてはいけないわけですよね?
現在使っている数式を提示していただけませんか? (稲葉) 2019/01/31(木) 16:55
ご回答ありがとうございます。
>仮に参照先シートに鈴木さんがりんごを10円買っていたとして 今回の検証シートに鈴木さんは居ないので、すべてOKとなってしまいますよね? 本来は鈴木さんがいなくてはいけないわけですよね?
そうなのです。
これだと漏れていることになるので何か分かる方法があればと思ったのですが。
>現在使っている数式を提示していただけませんか?
式を壊すというのは式を消すという意味です。
関数だと使えない人がいるのでマクロで見えなくしてほしいとの要望です。
IF(O24='◎(検証!Q11,"OK")
どんなことでもよいので教えていただけないでしょうか。
よろしくお願いいたします。
(あめ) 2019/01/31(木) 17:12
ご回答ありがとうございます。
>一方のA列と他方のB列を比較していますが、A列は名前、B列は数値なので、一致するはずはないですよね? ws1とws2のA列同士、B列同士が両方共一致して、初めてOKになるのでは?
こういうことでしょうか。
If ws2.Range("A" & migi).Value = ws1.Range("A" & hida).Value Then
A列とB列セットで一致した場合にOKとしたいのですが大丈夫でしょうか。
どんなことでもよいので教えていただけないでしょうか。
よろしくお願いいたします。
(あめ) 2019/01/31(木) 17:17
これだと =IF(VLOOKUP($A2,参照先シート!$A$1:$E$6,MATCH($B$1,参照先シート!$1:$1,0),0)=$B2,"OK",False)
名前がない場合、 #N/A 数値が無い場合、FALSE となって、区別がつきませんか。 数式の入っているセルは、シート保護するか、入力規則で対応。
>関数だと使えない人がいるので どういう意味で言っているのか良くわからないです。 (BJ) 2019/01/31(木) 17:24
> If ws2.Range("A" & migi).Value = ws1.Range("A" & hida).Value Then これだと、名前が一致しただけでOKになっちゃいますよね? なので、このIf文に引っかかったならば、続けてB列も同様に比較しましょう。
If ws2.Range("A" & migi).Value = ws1.Range("A" & hida).Value Then If ws2.Range("B" & migi).Value = ws1.Range("B" & hida).Value Then ws1.Range("C" & hida).Value = "OK" Else ws1.Range("C" & hida).Value = "FALSE" End If Exit For End If (???) 2019/01/31(木) 17:28
私の認識で書きました。 下記のような結果でよければ、お試しください。 |[A] |[B] |[C] [1]|名前|りんご|山田さんがいません [2]|田中| 100|OK [3]|松田| 10|金額が違っています。
|[A] |[B] |[C] [1]|名前|ばなな| [2]|田中| 80|OK [3]|松田| |参照先に名前がありません [4]|佐藤| |参照先に名前がありません [5]|山田| 130|OK [6]|鈴木| 70|OK
■前提条件 各検証シート名は、参照先シートの1行目に入力があること。(りんご、ばなな、いちご、みかん) 各検証シートが保護されていないこと Sub 検証() Dim tbl As Variant Dim f As Range Dim msg As String Dim i As Long Dim n As Long Dim r As Range Dim ws As Worksheet tbl = Sheets("参照先").Range("A1").CurrentRegion.Value For i = 2 To UBound(tbl, 2) Set ws = Nothing On Error Resume Next Set ws = Sheets(tbl(1, i)) On Error GoTo 0 If Not ws Is Nothing Then msg = "" '//C列のリセット ws.Range("C:C").ClearContents
'//参照先にデータがある人を、検証から探す For n = 2 To UBound(tbl, 1) If tbl(n, i) > 0 Then Set f = ws.Range("A:A").Find(tbl(n, 1)) If f Is Nothing Then '★参照先に金額があるが、検証にない場合 msg = msg & "," & tbl(n, 1) ElseIf f.Offset(, 1).Value <> tbl(n, i) Then '★参照先金額と、検証の金額が異なる場合 f.Offset(, 2).Value = "金額が違っています。" Else '★参照先と検証の金額が一致している場合 f.Offset(, 2).Value = "OK" End If End If Next n
'★検証に名前があり、参照先に金額がない場合 ※シートが保護されているとエラーになります。 Set r = ws.Range("C2:C" & ws.Cells(Rows.Count, "A").End(xlUp).Row) If WorksheetFunction.CountBlank(r) > 0 Then r.SpecialCells(xlCellTypeBlanks).Value = "参照先に名前がありません" End If Else Debug.Print tbl(1, i) & "のシートが見当たりません" End If If msg <> "" Then ws.Range("C1").Value = Mid$(msg, 2) & "さんがいません" Next i End Sub
(稲葉) 2019/01/31(木) 18:17
ご回答ありがとうございます。
教えていただいた式だと区別できますね。
でも今回はマクロで作成しようと思います。
今後の為に参考にさせていただきます。
〉どういう意味で言っているのか良くわからないです。
私の周りは関数のエラーが出た時、対処できない方ばかりなんです。
コメントど対処方を入力していてもダメなのです。
ご丁寧にご指摘いただきまして ありがとうございました。
(あめ) 2019/01/31(木) 20:36
ご回答ありがとうございます。
〉これだと、名前が一致しただけでOKになっちゃいますよね?
そうだったのですね すいません。
IfでAの時と同じようにしたらよいのですね。
勉強になりました。
明日 会社で試してみます。
(あめ) 2019/01/31(木) 20:47
ご回答ありがとうございます。
ご丁寧にコードの解説までしていただきまして助かります。
明日 会社で試してみます。
とり急ぎご連絡いたします。
(あめ) 2019/01/31(木) 20:54
横から失礼します。 勉強させてもらっております。
稲葉さんのコードで試してみたのですが一部できませんでした。
参照先と一致しているのに「金額が違ってます」と「参照先に名前がありません」 と結果が出てしまいました。
簡単なテストデータでは大丈夫でしたが、自分の持っているデータで試してみたらダメでした。
何か考えられる原因がありましたら ご教授ください。
(初心者) 2019/02/01(金) 16:34
データがないのに検証できないです。 こちらではテストデータで問題ないものを提供しています。 (稲葉) 2019/02/01(金) 17:08
Dim c As Range, dic As Object Set dic = CreateObject("Scripting.Dictionary") For Each c In Sheets("参照先").Range("A1").CurrentRegion dic(c.EntireRow.Cells(1) & "|" & c.EntireColumn.Cells(1) & "|" & c.Value) = True Next c For Each c In Sheets("りんご検証").Range("A2:A" & Rows.Count).SpecialCells(2) If dic(c.Value & "|" & Range("b1").Value & "|" & c.Offset(, 1).Value) Then c.Offset(, 2).Value = "OK" Else c.Offset(, 2).Value = "FALSE" End If Next c End Sub (mm) 2019/02/01(金) 17:18
(初心者) 2019/02/01(金) 16:34さんあて もし心当たりがあるなら、Findのところです。 Findメソッドは、前回の設定を引き継ぐため、引数を省略した場合は前回の設定のままになります。 ですので、手動で検索したときに引っ掛からない場合もございます。(値ではなく、計算式の中を検索するなど) Dictionary版を作りましたので、ご確認ください。 Sub 検証2() Dim w As Variant Dim dic As Object Dim i As Long Dim j As Long Dim r As Range Dim k As Variant Dim kk As Variant Dim ws As Worksheet Dim msg As String '項目別に金額が入っている人をdicに登録する 例:dic(りんご)(田中) = 80 w = Sheets("参照先").Range("A1").CurrentRegion.Value Set dic = CreateObject("Scripting.Dictionary") For j = 2 To UBound(w, 2) Set dic(w(1, j)) = CreateObject("Scripting.Dictionary") For i = 2 To UBound(w, 1) If w(i, j) <> "" Then dic(w(1, j))(w(i, 1)) = w(i, j) End If Next i Next j
'項目名でループする For Each k In dic.keys 'シートの有無チェック Set ws = Nothing On Error Resume Next Set ws = Sheets(k) On Error GoTo 0 If Not ws Is Nothing Then 'C列のリセット ws.Range("C:C").ClearContents 'A2からA列の最終行までループ For Each r In ws.Range("A2", ws.Cells(Rows.Count, "A").End(xlUp)) Select Case True Case Not dic(k).exists(r.Value) '★参照先に金額がない場合 r.Offset(, 2).Value = "参照先に金額がありません"
Case dic(k)(r.Value) = r.Offset(, 1).Value '★金額が一致していた場合 r.Offset(, 2).Value = "OK"
Case Else '★参照先と金額が異なる場合 r.Offset(, 2).Value = "参照先と金額が合いません" End Select If dic(k).exists(r.Value) Then dic(k).Remove (r.Value) Next r
'★参照先に金額があるが、検証にない場合(一度も名前を呼ばれていない人) If dic(k).Count > 0 Then msg = "" For Each kk In dic(k).keys msg = msg & "," & kk Next kk ws.Range("C1").Value = Mid$(msg, 2) & "さんがいません" End If Else Debug.Print k & "のシートが見当たりません" End If Next k Set dic = Nothing End Sub
(稲葉) 2019/02/01(金) 19:00
遅くなりまして申し訳ございません。
自分仕様に変更するのに手間取ってしまい、お礼が遅れてしまいました。
まだ分からない所がありますが少しづつ勉強してみようと思います。
どうもありがとうございます。
(あめ) 2019/02/04(月) 09:55
参考までに、どこを直したか教えていただけますか? 自分の認識とあっていたかどうかくらい、教えていただきたいです。 (稲葉) 2019/02/04(月) 10:12
(稲葉) 2019/02/01(金) 19:00さんあて
初心者です。 度々、横から失礼いたします。
>Dictionary版を作りましたので、ご確認ください。
質問者ではないのにご対応いただきまして、ありがとうございます。 自分の持っているデータでも大丈夫でした。
>もし心当たりがあるなら、Findのところです。
前回の設定を引き継ぐとは知らなかったです。 勉強になります。 何度も繰り返す場合はFind使わない方が良いですね。 他のコードも見直してみます。
まだまだ教えていただきたいことがあるのですが、こちらあめさんの 質問なので新しく登録させていただきます。
どうもお邪魔いたしました。
(初心者) 2019/02/04(月) 13:09
> 何度も繰り返す場合はFind使わない方が良いですね。 いえ、Findもすべての引数を省略しなければ、希望通りの結果になります。 今回はさぼっただけです。
もこな2さんも度々ご指摘されておりますが、Findに関しては名前付き引数の名前の省略や、 引数そのものの省略はしないほうが良いというのが認識です。
> まだまだ教えていただきたいことがあるのですが、こちらあめさんの >質問なので新しく登録させていただきます。 よろしければ一般名称(初心者)ではない、一意のハンドルネームでお願いします。 私でよければ付き合います。
(稲葉) 2019/02/04(月) 18:36
(稲葉) 2019/02/04(月) 18:36さんあて
お邪魔します。 初心者です。
>Findに関しては名前付き引数の名前の省略や、引数そのものの省略は しないほうが良いというのが認識です。
私の勘違いを教えていただきましてありがとうございます。 またまた勉強になりました。 マクロノート(勉強用)に記録しておきます。
>よろしければ一般名称(初心者)ではない、一意のハンドルネームでお願いします。 私でよければ付き合います。
ご親切にありがとうございます。 自分でもDictionaryやFind勉強しておきます。
ハンドルネーム失礼しました「初心者」似た方が何人もいらっしゃいますね。 ハンドルネームは「すもも」でお邪魔する予定です。 機会がありましたら又よろしくお願いいたします。
ご厚意に感謝いたします。
(初心者) 2019/02/05(火) 16:36
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.