Excel VBAで二つのシートを比較して合致するレコードを別のシートに抽出する方法

このQ&Aのポイント
  • Excel VBAを使用して、二つのシートを比較し、合致するレコードを別のシートに抽出する方法をご紹介します。
  • fax1シートとfax2シートのデータを比較し、合致するfax_idを持つレコードをfax3シートにコピーします。
  • 具体的な手順としては、まずfax1シートとfax2シートのデータを範囲指定し、次に比較処理を行います。合致するレコードはfax3シートにコピーされ、最後にセルの幅を自動調整します。
回答を見る
  • ベストアンサー

Excel VBA で二つのシートを比較して合致するレコードを別のシー

Excel VBA で二つのシートを比較して合致するレコードを別のシートに抽出する方法 全然詳しくはありません。 やりたいこととしては、fax1,fax2,fax3のシートがありまして、 fax1:a列にfax_id fax2:fax1同様に、c列にfax_id のようなExcelのデータがあります。 ここから、fax1のシートのidを一つ一つ読み込みながら、fax2のidと比較して、合致したらfax3シートにコピーするようなプログラムを作りたいです。 やり方はいろいろあるみたいなのですが、どうしても下記の記述をベースに作ってみたいのですが、単純にfax1からfax3にコピーするのはわかるのですが、ここから先がよくわかりません。 基本的なことで申し訳ないのですが、どなたかご教授いただけませんでしょうか。 よろしくお願いいたします。 Public Sub copy() Dim tempRange As Range Dim fax1Table As Range Dim fax2Table As Range Dim dst As Range 'fax1範囲指定 Worksheets("Fax1").Activate Set fax1Table = Range("a1").CurrentRegion Set fax1Table = fax1Table.Offset(1) Set fax1Table = fax1Table.Resize(fax1Table.Rows.Count - 1) 'fax2範囲指定 Worksheets("Fax2").Activate Set fax2Table = Range("a1").CurrentRegion Set fax2Table = fax2Table.Offset(1) Set fax2Table = fax2Table.Resize(fax2Table.Rows.Count - 1) '比較開始 Worksheets("fax1").Activate '見出しコピー Set dst = Worksheets("fax3").Range("a1") Range("a1:g1").Copy dst 'レコード抽出 For Each tempRange In fax1Table.Rows Set dst = dst.Offset(1) tempRange.Copy dst Next '比較終了 'セル幅自動調整 Worksheets("fax3").Range("a:g").Columns.AutoFit Worksheets("fax3").Activate End Sub

  • asheh
  • お礼率66% (14/21)

質問者が選んだベストアンサー

  • ベストアンサー
  • myRange
  • ベストアンサー率71% (339/472)
回答No.1

抽出部分だけのコードです。。。 '---------------------------------------- '●スピードが速い(FINDメソッド使用) Dim FoundCell As Range For Each tempRange In fax1Table.Rows   Set FoundCell = fax2Table.Columns(3).Find(tempRange.Columns(1).Value, , xlValues, xlWhole)     If Not FoundCell Is Nothing Then       Set dst = dst.Offset(1)       tempRange.copy dst     End If Next tempRange '-------------------------------- ●スピード遅い(Fax2TableのC列をひとつずつ全て比較するので)  Dim Fax2C As Range For Each tempRange In fax1Table.Rows   For Each Fax2C In fax2Table.Columns(3).Cells     If tempRange.Columns(1).Value = Fax2C.Value Then       Set dst = dst.Offset(1)       tempRange.copy dst       Exit For     End If   Next Fax2C Next tempRange '---------------------------------------- このような処理では、Activateの必要はありませんので 実際のコードではそこらあたりに考慮したコードにした方がいいでしょう。 以上です。  

asheh
質問者

お礼

ありがとうございました。 教えていただきました考え方で意図したことができるような動きになってます。 一つ一つみていくと数千件あるデータの場合、かなり遅くなるんですね。 ただ、コピーはされるのですが、なんでかレコードの途中までしかデータがコピーされなくて、もう少し考えてます。ちょっとお待ちください。

asheh
質問者

補足

お世話になっております。 返信が遅くなりましてすみません。 まだつっかかっているのと、閉じてしまったらやり取りができなくなってしまうのかと思って、まだ閉じていませんでした。 ここまで教えてもらったので、ここから先は自分でとおもってまして。 もう少しだけまっててもらえませんでしょうか。 よろしくお願いいたします。

関連するQ&A

  • VBAの比較削除マクロ

    Sheet1とSheet2のB列を参照して同じ値が存在する場合は、Sheet1の行を削除するマクロを作成したいのですがどのように記述したらよいか分かりません。 Sheet1とSheet2のB列を参照して同じ値が存在する場合は、Sheet3にSheet1の行をコピーするマクロはホームページ等を参照して下記のように記述できました。 Public Sub copy() Dim tempRange As Range Dim fax1Table As Range Dim fax2Table As Range Dim dst As Range Dim FoundCell As Range 'fax1範囲指定 Worksheets("Fax1").Activate Set fax1Table = Range("a1").CurrentRegion Set fax1Table = fax1Table.Offset(1) Set fax1Table = fax1Table.Resize(fax1Table.Rows.Count - 1) 'fax2範囲指定 Worksheets("Fax2").Activate Set fax2Table = Range("a1").CurrentRegion Set fax2Table = fax2Table.Offset(1) Set fax2Table = fax2Table.Resize(fax2Table.Rows.Count - 1) '比較開始 Worksheets("fax1").Activate '見出しコピー Set dst = Worksheets("fax3").Range("a1") Range("a1:ad1").copy dst 'レコード抽出 For Each tempRange In fax1Table.Rows Set FoundCell = fax2Table.Columns(2).Find(tempRange.Columns(2).Value, , xlValues, xlWhole) If Not FoundCell Is Nothing Then Set dst = dst.Offset(1) tempRange.copy dst End If Next tempRange '比較終了 'セル幅自動調整 Worksheets("fax3").Range("a:g").Columns.AutoFit Worksheets("fax3").Activate End Sub

  • Excel VBA で二つのシートを比較して合致しないレコードを別のシ

    Excel VBA で二つのシートを比較して合致しないレコードを別のシートに抽出する方法 とっても初心者です。 以前合致するレコードの抽出する際、FINDメソッドを使用した抽出方法(下記ソース)を教えてもらったのですが、同じ流れで、一致しないものだけを抽出するにはどうするのが一番良いのでしょうか。 一致するレコードをいったん削除して、残りをコピーするか、1レコードずつ確認しながら処理をすることが思いつくのですが、後者の場合はデータ数が多いと恐ろしく時間がかかるのと、前者の場合データを削除してしまうので、それは避けたく。 一般的にどのように組むものなのかがよくわからなくて。よろしくお願いいたします。 ●FINDメソッド使用 Dim FoundCell As Range For Each tempRange In fax1Table.Rows   Set FoundCell = fax2Table.Columns(3).Find(tempRange.Columns(1).Value, , xlValues, xlWhole)     If Not FoundCell Is Nothing Then       Set dst = dst.Offset(1)       tempRange.copy dst     End If Next tempRange

  • VBA シート指定とファイル名入力

    部署ごとに分割し、ブックで保存するコードです。 sheet名は「部署」です。 Sub macro1() Dim w As Worksheet Dim n As Long Dim r As Long Dim s As String Dim WSH As Variant Dim myPath As String Set w = ActiveSheet n = Worksheets.Count Application.ScreenUpdating = False On Error GoTo errhandle For r = 5 To w.Range("B65536").End(xlUp).Row s = w.Cells(r, "B") w.Rows(r).Copy Worksheets(s).Range("B65536").End(xlUp).Offset(1, -1) Next r On Error GoTo 0 Set WSH = CreateObject("Wscript.Shell") myPath = ActiveWorkbook.Path & "\1\" For r = Worksheets.Count To n + 1 Step -1 Worksheets(Worksheets.Count).Copy ActiveSheet.Columns.AutoFit ActiveWorkbook.SaveAs Filename:=myPath & ActiveSheet.Name ActiveWorkbook.Close False Application.DisplayAlerts = False Worksheets(Worksheets.Count).Delete Application.DisplayAlerts = True Next r w.Select Exit Sub errhandle: Worksheets.Add after:=Worksheets(Worksheets.Count) ActiveSheet.Name = s w.Rows(1).Copy Range("A1") w.Rows(2).Copy Range("A2") w.Rows(3).Copy Range("A3") w.Rows(4).Copy Range("A4") Resume Application.ScreenUpdating = True End Sub (1)sheet1にマクロ実行ボタンを配置し、部署seedにマクロ実行命令をする。 (2)sheet1のB2セルにファイル名を入力して、そのファイルに保存する。(例部署ファイル) (1)Dim w As Worksheets("部署")と変更したのですが、エラーが出ました。 (2)myPath = ActiveWorkbook.Path & "\部署ファイル\"   ↑ これをsheet1のB2セルから指定できるようにしたいです。 宜しくお願いします。

  • EXCEL VBA  任意のシートに貼りつけ

    御世話になります。おしえて下さい。 データPCのexcelデータからオートフィルタでデータを抽出して任意の列を 抽出するところまでは出来ているようですが、その先が付け焼刃ですので、 さっぱり解決策がみつけられません。 データをオートフィルタにて抽出→帳票ブックの任意のシートに張り付け 帳票のシート名はユーザフォームのリストボックスから代入してるつもりです。 宜しくお願い致します。 Option Explicit Sub Macro3_2() Dim myRL As Date Dim MyRow As Long Dim Window1 As Window Dim buf As String myRL = UserForm1.TextBox1 buf = UserForm1.ListBox1 Workbooks.Open Filename:= _ "\\WPCABC\Users\hoge\Documents\hogehoge\データ.xlsx" ActiveSheet.ListObjects("テーブル_PCABC_からのクエリ") _ .Range.AutoFilter Field:=9, _ Criteria1:="=" & myRL ActiveSheet.ListObjects("テーブル_PCABC_からのクエリ") _ .Range.AutoFilter Field:=12, _ Criteria1:=">=1" MyRow = Worksheets("sheet1") _ .Range("A" & Rows.Count).End(xlUp).Row Worksheets("sheet1").Activate Range("B2:B" & MyRow).Select Selection.Copy ------------------------------------------------------↓上手く出来ません Workbooks("帳票.xlsm").Worksheets("buf") _ .Range("Y3" & MyRow) _ .PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _ :=False, Transpose:=False Workbooks("帳票.xlsx").Worksheets("sheet1").Activate Range("L2:L" & MyRow).Select Selection.Copy Workbooks("帳票.xlsm").Worksheets("buf") _ .Range("Z3" & MyRow) _ .PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _ :=False, Transpose:=False Set Window1 = Application.Windows("クエリデータ.xlsm") Window1.Activate End Sub

  • エクセルVBA の変数を使うべきでしょうか?

    はじめまして。エクセル初心者です。 書籍やサイトで勉強させてもらっていますが、VBAがなかなか難しくてすぐに壁にぶつかってしまいます。少々困ってしまい、詳しい方のアドバイスを頂ければと質問を投稿させていただきました。 どうか宜しくお願い致します。質問ですが、 以下のようなコードで、sheet5のB列の任意のセルをダブルクリックした場合、sheet5のBCD列の同じ行のセル値がsheet1の指定した列に入力されるという処理を作りました。 これで一応目的の動作はするのですが、数が増えると「コンパイルエラー・プロシージャが大きすぎます」というメッセージがでてしまいます。列や行には規則性があるので、もしかしたら変数というものを使ってコードを書き直せばいいのかなと思いネットで調べてみたのですが、今のところさっぱり理解できません。 申し訳ありませんが、分かりやすくご教授いただけないでしょうか。バージョンは2003を使っています。 また、下のコードですと、sheet5のBCDいずれかのセルに空白があった場合、sheet1の列に入力されるときに入力される行がずれてしまいます。今は空白を何かで埋めて対処しているのですが、この問題の解決策も教えて頂けると助かります。どうか宜しくお願い致します。 Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Excel.Range, cancel As Boolean) If Target.Address = "$B$2" Then Worksheets("sheet1").Range("B" & Rows.Count).End(xlUp).Offset(1).Value = Target.Value Worksheets("sheet1").Range("H" & Rows.Count).End(xlUp).Offset(1).Value = Worksheets("sheet5").Range("B2") Worksheets("sheet1").Range("K" & Rows.Count).End(xlUp).Offset(1).Value = Worksheets("sheet5").Range("C2") Worksheets("sheet1").Range("M" & Rows.Count).End(xlUp).Offset(1).Value = Worksheets("sheet5").Range("D2") Worksheets("sheet1").Activate cancel = True End If If Target.Address = "$B$3" Then Worksheets("sheet1").Range("B" & Rows.Count).End(xlUp).Offset(1).Value = Target.Value Worksheets("sheet1").Range("H" & Rows.Count).End(xlUp).Offset(1).Value = Worksheets("sheet5").Range("B3") Worksheets("sheet1").Range("K" & Rows.Count).End(xlUp).Offset(1).Value = Worksheets("sheet5").Range("C3") Worksheets("sheet1").Range("M" & Rows.Count).End(xlUp).Offset(1).Value = Worksheets("sheet5").Range("D3") Worksheets("sheet1").Activate cancel = True End If If Target.Address = "$B$4" Then Worksheets("sheet1").Range("B" & Rows.Count).End(xlUp).Offset(1).Value = Target.Value Worksheets("sheet1").Range("H" & Rows.Count).End(xlUp).Offset(1).Value = Worksheets("sheet5").Range("B4") Worksheets("sheet1").Range("K" & Rows.Count).End(xlUp).Offset(1).Value = Worksheets("sheet5").Range("C4") Worksheets("sheet1").Range("M" & Rows.Count).End(xlUp).Offset(1).Value = Worksheets("sheet5").Range("D4") Worksheets("sheet1").Activate cancel = True End If   ・     ・   ・     ・   ・     ・ End Sub

  • Excel VBA 配列による複数セルへの入力

    VBA初心者です.よろしくお願いいたします. 用語の読みを自動で振るシートを作成しているのですが,Do Loop部分が一行ずつの入力となっていて,時間がかかっています. これを配列等の方法を用いて高速化したいと思って,試行錯誤したのですが,うまくいきません. 何卒お教えくださいますようお願いいたします. 用語の読みを生成する手順ですが, 1.シート1に用語をペーストする 2.ペーストされた用語をシート2にある用語のDB(用語と読みが入力されています.重複レコードなし)にコピー 3.コピーされたシート2をピボットにして個数が2以上あった場合,その用語と読みを返します. 4.Do Loopで最初にヒットした用語に戻るまでループ となっています. 3までの手順に修正の必要はないのですが,4の手順でかなり時間をロスしております. ここを配列等の方法で一度に書き込むことができればと思っています. Sub test() i = 8 L_Row04 = 180188 Dim S1 As Worksheet '読みを振る用語をペーストするシート Dim S2 As Worksheet '読み用の用語のDB Dim S3 As Worksheet 'ピボット Dim L_Row01 As Long 'S1にペーストされた用語の最下行 Dim L_Row02 As Long 'S1の用語をs2にペーストしたときの最下行 Dim L_Row03 As Long 'ピボットの用語の最下行 Dim Rng01 As Range 'S1にペーストされた用語の範囲 Dim Rng02 As Range 'S2にペーストされた用語の範囲 Dim Rng03 As Range 'ピボットの範囲 Dim Str01 As Variant 'ピボットで2以上あったときの用語 Dim Str02 As Variant 'ピボットで2以上あったときの読み Dim firstcell As Range Dim Foundcell01 As Range Set S1 = Worksheets(1) Set S2 = Worksheets(2) Set S3 = Worksheets(3) S1.Activate L_Row01 = S1.Cells(Rows.Count, 2).End(xlUp).Row L_Row02 = S2.Cells(Rows.Count, 3).End(xlUp).Row Set Rng01 = S1.Range(Cells(i, 2), Cells(L_Row01, 2)) Rng01.Copy Destination:=S2.Cells(L_Row02 + 1, 2 + 1) S3.PivotTables("ピボットテーブル2").RefreshTable S2.Activate L_Row02 = S2.Cells(Rows.Count, 3).End(xlUp).Row Set Rng02 = S2.Range(Cells(L_Row04, 3), Cells(L_Row02, 3)) Rng02.Delete S3.Activate L_Row03 = S3.Cells(Rows.Count, 2).End(xlUp).Row Set Rng03 = S3.Range(Cells(4, 2), Cells(L_Row03, 2)) For Each a In Rng03 If a >= 2 And a.Offset(0, -1).Value <> "(空白)" And a.Offset(1, -1).Value <> "(空白)" Then Str01 = a.Offset(0, -1) Str02 = a.Offset(1, -1) S1.Activate Set Foundcell01 = Rng01.Find(What:=Str01, searchorder:=xlByRows, LookIn:=xlValues, lookat:=xlWhole) Do Selection.Offset(0, 1).Value = Str02 Selection.Offset(0, 2).Value = "●" Loop Until ActiveCell.Address = firstcell.Address End If End If Next End Sub

  • エクセル VBA シート名を別シートにコピー

    早速の質問ですが エクセルVBAで シート名を別シートにコピーなのですが 10個のシートを順にシート名をコピー&ペーストしたいのです。 Dim aworkbook As Workbook Dim bworkbook As Workbook Set bworkbook = ActiveWorkbook Workbooks.Add Set aworkbook = ActiveWorkbook for i=1 to 10 bworkbook.Activate Worksheets(i).Select Application.CutCopyMode = False aworkbook.Activate Worksheets(i).Select ここに入る文章がわかりません Range("A1").Select next と以上な感じで作ってみたのですが どう貼り付けして良いかわからない状況です nextでまわす以上変数でなければだめなんでしょうけれども 構文が思いつきません。 皆様よろしくお願いいたします。

  • VBAエクセルにて開いてないエクセルシートを開いてるシートに所得

    お世話になります。 「同じフォルダー内にBOOKが2つ有ります。1つ(AK.xls)を立上げて もう1つの(EX.xls)を立上げずに、EX.xls内のSheet1をコピーして AK.xlsのシート(STEP1)に貼り付けようとしています。」 どうしてもエラーが出てしまいます。 何方か、分かる方教えて下さい。 また記述して戴ければもっと助かります。 エラーは”1004”EX.xlsが見つかりません。と出てしまいます。 Sub ST() Dim wsSrc As Worksheet, WS As Worksheet Dim PasteR As Range Dim x As Long Sheets("STEP1").Select Cells.Select Selection.Delete Shift:=xlUp Range("A1").Select   Set wsSrc = ActiveSheet Workbooks.Open "EX.xls" For Each WS In Worksheets x = WS.Range("A1").CurrentRegion.Rows.Count If WS.Index = 1 Then Set PasteR = wsSrc.Range("A1") Else Set PasteR = wsSrc.Range("A65536").End(xlUp).Offset(1) End If WS.Range(WS.Cells(1, 1), WS.Cells(x, 44)).Copy PasteR Set PasteR = Nothing Next ActiveWorkbook.Close False Set wsSrc = Nothing End Sub デバックでは Workbooks.Open "EX.xls"この部分が黄色になります。 是非、回答を宜しくお願い致します。

  • ExcelのVBAについてです。シート1と2を作成

    ExcelのVBAについてです。シート1と2を作成し、シート1にバーコードまたはキーボードで入力します。シート1は入力専用かつ入力した分の早見表で、実際にはシート2に転記仕訳して、シート3以降に表を作成したいです。使い方はシート1に入力またはシート2をタップまたはクリックすると入力(画面)になります。以前の質問の回答を参考に必要最低限に改良しています。パッと見で構いません、何か不具合は見付からないでしょうか? '///Sheet1/// Private Sub Worksheet_Change(ByVal Target As Excel.Range) Dim time7 As Range For Each time7 In Target If time7.Column = 1 Then time7.Offset(0, 4).Value = Format(Now, "Short Time") & vbCrLf & _ Format(Now, "yyyy/mm/dd hh:nn:ss AM/PM") End If Application.EnableEvents = False Application.EnableEvents = True Next time7 '(1)シートを変数にセット Dim ws1 As Worksheet Dim ws2 As Worksheet Set ws1 = Worksheets("Sheet1") Set ws2 = Worksheets("Sheet2") '(2)シートを指定してデータを転記 ws2.Range("A3:H3").Value = ws1.Range("A3:H3 ").Value End Sub Private Sub Worksheet_Activate() ' ' 新規行挿入 ' ' Worksheets("Sheet2").Range("3:3").Insert Sheets("Sheet1").Range("H3").Select ActiveCell.FormulaR1C1 = "5" Sheets("Sheet1").Range("E3").Select Selection.ClearContents Dim str_Left As String 'セルE4に文字列、セルH4に数字を予め入れておくこと。 str_Left = Left(Cells(4, 5), Cells(4, 8)) MsgBox str_Left & vbCrLf & " " & "OKボタンを押してください!" Sheets("Sheet1").Range("A3").Select Dim se_r As String se_r = Application.InputBox("バーコードを入力してください") Select Case se_r Case "False" MsgBox "キャンセルされました" Case "" MsgBox "空欄が入力されました" Case Else Range("A3").Value = se_r End Select End Sub ' ///Sheet2/// Private Sub Worksheet_Activate() Dim Emp(1 To 300) As String Dim msg As String Dim i, i2, Cnt As Integer Dim N_In As Variant For i = 3 To 3 If IsEmpty(Cells(i, 1).Value) = False Then 'ここで空欄判定 Worksheets("Sheet1").Range("3:3").Insert '対象セルアドレスを改行処理 End If '(1)シートを変数にセット Dim ws1 As Worksheet Dim ws2 As Worksheet Dim st1, s, i3 As Long Dim Bst As Range Set ws1 = Worksheets("Sheet1") Set ws2 = Worksheets("Sheet2") '(2)シートを指定してデータを転記 st1 = ws1.Cells(Rows.Count, "E").End(xlUp).Row 'A列の最終行を設定する s = 3 For i3 = 3 To st1 Set Bst = ws2.Columns("E").Find(What:=ws1.Cells(i3, "E"), LookIn:=xlFormulas, _ LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False) シート間のE列を比較 If Bst Is Nothing Then '比較して無い場合は、下記を実行 ws1.Cells(s, "A") = ws1.Cells(i3, "A") '追加する文字を転記する。(コード) s = s + 1 End If Next i3 Next i '(1)シートを変数にセット Dim ws1_ As Worksheet Set ws1_ = Worksheets("Sheet1") ws1_.Activate End Sub

  • VBA(エクセル)で教えて下さい。開いていないBOOKの貼り付け

    VBA(エクセル)で教えて下さい。開いていないBOOKのシートを開いているBOOKのシートに貼り付けで、開いているBOOKから開いていないBOOK名を指定したいのですが、 現在開いているエクセルです。 SHEETS(Type)のRANGE(A1)に閉じているBOOK名を入力します。 SHEETS(In)に閉じているBOOKのSHEETSを貼り付けたいのですが、 Ex = Sheets("Type").Range("A1")  が無いと閉じているEx.xlsを貼り付けます。 このExと言うBOOK以外も多々コピーしたいのですが、どのように書けば良いか分からず、 是非、教えて下さい。 Sub a1() Dim wsSrc As Worksheet, WS As Worksheet Dim PasteR As Range Dim x As Long Sheets("In").Select Cells.Select Selection.Delete Shift:=xlUp Range("A1").Select 'If Worksheets(1).Name = "STEP1" Then ' Worksheets(1).Activate ' Cells.ClearContents ' Else 'Worksheets.Add(Before:=Worksheets(1)).Name = "一覧" 'End If   Ex = Sheets("Type").Range("A1")   Set wsSrc = ActiveSheet Workbooks.Open "C:\WINDOWS\デスクトップ\test\Ex.xls" For Each WS In Worksheets x = WS.Range("A1").CurrentRegion.Rows.Count If WS.Index = 1 Then Set PasteR = wsSrc.Range("A1") Else Set PasteR = wsSrc.Range("A65536").End(xlUp).Offset(1) End If WS.Range(WS.Cells(1, 1), WS.Cells(x, 44)).Copy PasteR Set PasteR = Nothing Next ActiveWorkbook.Close False Set wsSrc = Nothing End Sub

専門家に質問してみよう