VBAでSheet1とSheet2のリンクを比較する方法

このQ&Aのポイント
  • VBAを使用してSheet1とSheet2の表を比較し、同じ名称の場合にSheet1のD列とSheet2のD列をリンクさせたい。
  • 現在は関数を使用しているが、数が多くなってきたためVBAで処理しようとしている。
  • 組んでみたコードでは、一部の結果が意図しないものになっているため、正しいコードに修正したい。
回答を見る
  • ベストアンサー

VBA 比較してリンク

初めまして。VBA初心者です。 まずはこちらを見て下さい。   Sheet1                Sheet2             A     B    C   D        A     B    C   D 1 大区分 中区分 名称       20 大区分 中区分 名称 2  A     a    あ   1    21  A     a   あ   1 3            い  2    22            い   2 4            う   3    23            う   3 5            え  4    24            お   5 6            お  5    25        b    あ   1→6 7        b    あ  6    26            い   2→7 8            い  7    27            う    3→8 9            う   8    28            お   5→10 10            え  9    29  B     a    か   11 11            お  10   30            き   12 12  B    a    か  11    31            け   14 13            き  12    32            こ    15 14            く   13    33       b    か    11→16 15            け  14    34            き    12→17 16            こ   15    35           け    14→19 17       b    か   16    36           こ    15→20 18            き   17 19            く   18 20            け   19 21            こ   20 元々関数を使用していたのですが、数があまりに多くなってきたため、VBAで処理できればと初めて作ってみましたが、途中で行き詰った為ご教授お願いします。 Sheet1,2にそれぞれ表があり、Sheet1が元となります。(行は1000行以上になることもあります。) それで、Sheet2の名称をSheet1の名称と比べ同じ場合、Sheet1のD列をSheet2のD列にリンクさせたいのです。 一応、色々見ながら下記のように組んでみたのですが、矢印の左側のようになってしまいます。 これを、右側のような結果にしたいのですが、なんとなく間違ってる箇所は分かるものの、どのようにしていいか分かりません。 これをどのようにしたらよろしいでしょうか?若しくは、他にやり方があれば教えて頂きたいです。 分かりづらい説明で申し訳ないですが、よろしくお願い致します。 sub test()  Dim i As Integer,maxrow As Integer  maxrow = Sheet2.Range("C" : Rows.Count).End(xlup).Row    For i = 1 To maxrow - 19      If Sheet1.Cells (1+i,3)=Sheet2.Cells(19+i,3) Then        Sheet2.Cells(19+i,4)="=Sheet1" & Sheet1.Cells(1 + i,3).Offset(0,1).Address      Else        Sheet2.Cells(19+i,4)="=Sheet1" & Sheet1.Cells.Find(Sheet2.Cells(19+i,3)) _                        .Offset(0,1).Address      End if    Next i End sub

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

  • ベストアンサー
  • end-u
  • ベストアンサー率79% (496/625)
回答No.2

ふむ。失礼。 方針変更です。test1、test2は無かった事にしてください。 以下、■箇所のみ設定して後は相対関係で処理。 Sub test3()   Dim r(1 To 2) As Range '起点セル|Key列   Dim tmp    As Range 'xlCellTypeBlanks用   Dim s     As String 'R1C1数式共通文字用   Dim i     As Long   Dim x     As Long  '列指定用   Dim y     As Long  '行指定用   Dim v          'Application.Match用配列   '各シートのデータの起点セルを指定   Set r(1) = Excel.Range("Sheet1!A2") '■   Set r(2) = Excel.Range("Sheet2!A21") '■   x = r(1).Column + 3   y = r(1).Row - 1   For i = 1 To 2     With Excel.Range(r(i), r(i).Range("C1").EntireColumn.Cells(Rows.Count).End(xlUp))       '空白セルだけを取得[ctrl]+[g]ジャンプ機能       Set tmp = .Columns("A:B").SpecialCells(xlCellTypeBlanks)       '直上の値をセット       tmp.FormulaR1C1 = "=R[-1]C"       'rにE列を再セット       Set r(i) = .Columns("E")     End With     'E列を作業エリアとして A列&B列&C列 のキーを作る     r(i).FormulaR1C1 = "=RC[-4]&RC[-3]&RC[-2]"     r(i).Value = r(i).Value     '空白セル式クリア     tmp.ClearContents   Next   'Match関数で行位置取得   v = Application.Match(r(2), r(1), 0)   '作業エリアクリア   r(1).ClearContents   r(2).ClearContents   s = "='" & r(1).Worksheet.Name & "'!R"   'Loopして数式セット   With r(2).Offset(, -1).Cells     For i = 1 To UBound(v)       If IsNumeric(v(i, 1)) Then         .Item(i).FormulaR1C1 = s & v(i, 1) + y & "C" & x       End If     Next   End With End Sub

ga74235
質問者

お礼

お返事遅くなりました。今回のは思っていた通りのものでした。 本当にありがとうございました。すごく助かりました。 また、質問させて頂くことがあると思いますが、よろしくお願い致します。 (というより、同じ仕事の系列でもう出ていますが…^^;)

その他の回答 (1)

  • end-u
  • ベストアンサー率79% (496/625)
回答No.1

効率を考えれば、セルのデータ範囲を一旦、配列に取得し、 Loop処理で空白データの場合は直上のデータを見るようにし、 とにかくA列&B列&C列で、参照キーとなるデータを作る事です。 その後の照合については、MATCH関数を使っても良いし。 Sub test1()   Dim i As Long   Dim j As Long   Dim v, w, x, y, z, a, b   For i = 1 To 2     With Sheets("Sheet" & i)       With .Range("A1", .Cells(.Rows.Count, "C").End(xlUp))         v = .Columns("A:B").Value         w = .Columns("C").Value       End With       For j = 1 To UBound(v)         If Not IsEmpty(v(j, 1)) Then           a = v(j, 1)         End If         If Not IsEmpty(v(j, 2)) Then           b = v(j, 2)         End If         w(j, 1) = a & b & w(j, 1)       Next     End With     If i = 2 Then Exit For     x = w   Next   y = Application.Match(w, x, 0)   z = Application.Index(Sheets("Sheet1").Columns("D"), y)   Sheets("Sheet2").Range("D1").Resize(UBound(z)).Value = z End Sub 作業エリアとして、E列が使えるのなら、数式を埋め込んで処理するほうが簡単です。 Sub test2()   Dim rng As Range   Dim rs As Range   Dim x  As Long   Dim i  As Long   For i = 1 To 2     With Sheets("Sheet" & i)       'A2セルからC列最終データまでの範囲       Set rng = .Range("A1", .Cells(.Rows.Count, "C").End(xlUp).Offset(, -1))     End With     '後で使うからsheet1の最終行を覚えておく     If i = 1 Then x = rng.Rows.Count     '空白セルだけを取得[ctrl]+[g]ジャンプ機能     Set rs = rng.SpecialCells(xlCellTypeBlanks)     '直上の値をセット     rs.FormulaR1C1 = "=R[-1]C"     'E列を作業エリアとして A列&B列&C列 のキーを作る     With rng.Columns("E")       .Formula = "=A2&B2&C2"       .Value = .Value     End With     rs.ClearContents   Next   'Sheet2のD列にINDEX(..(MATCH..))関数で値を引っ張ってくる   With rng.Columns("D")     .Formula = "=index(sheet1!$D$1:$D$" & x & ",match(E2,sheet1!$E$1:$E$" & x & ",0))"     .Value = .Value   End With End Sub

ga74235
質問者

お礼

ありがとうございます。早速検証させて頂きました。 一応Test1のほうは結果通りでしたが、Test2の方は1行ずれた(?)状態で表記されてるみたいでした。自分なりに考えてみましたが、どこを触っていいか分かりません。。。 後、説明の仕方が良くなかったですね。 Sheet2のD列には数値をそのまま入れるのではなく、=Sheet1!$D$2と入れる形にしたかったのです。 また、Sheet1とSheet2のそれぞれの開始行が違うのですが、Sheet2の上の方にエラー値が入ってしまいます。この場合でもなんとかなりますでしょうか? 度々のご質問で申し訳ないですが、よろしくお願い致します。

関連するQ&A

  • VBAで実行時エラー'13': がでます

    初歩の初歩ですいません。 VBAで Dim A As Integer Dim B As Integer Dim C As Integer Dim gokei As Integer For i = 8 To 70 A = Cells(i, 4).Value B = Cells(i, 5).Value C = Cells(i, 6).Value goukei = A + B + C Cells(i, 7) = goukei Next i としていますが A = Cells(i, 4).Value のところで今使っているシートだと止まってしまいます。 新規でワークシートを使って仮に数字を代入すると普通に動きます。 今使っているシートもセル内には =100 と入力して 100 と表示され セルの書式設定も数値になってるんですがどうしてでしょうか?

  • Excel VBA; 複数のループ処理

    ↓のようなコードがあります。 Dim i As Long, MaxRow1 As Long, MaxRow2 As Long MaxRow1 = Worksheets("Sheet1").Cells(Rows.Count, 1).End(xlUp).Row MaxRow2 = Worksheets("Sheet2").Cells(Rows.Count, 1).End(xlUp).Row For i = 1 To MaxRow1 Worksheets("Sheet1").Cells(i, 1).Value = i . Next i For i = 1 To MaxRow2 Worksheets("Sheet2").Cells(i, 1).Value = i . Next i これらを最大行の多いシートに合わせて、パフォーマンスを良くしたいと思います。 同様の処理をシート1、シート2で実施しているので纏めて記述したいです。 シート1、シート2に対する処理をサブルーチンにする方法しかありませんか? どなたかお願いします。 If MaxRow1 >= MaxRow2 Then For i = 1 To MaxRow1 Else For i = 1 To MaxRow2 End If Worksheets("Sheet1").Cells(i, 1).Value = i Worksheets("Sheet2").Cells(i, 1).Value = i . Next i

  • VBAで空欄にデータに表示

    エクセルVBAのIFを使って、シートaのA列に値があって、B列が空欄の場合のみ、空欄のセルにシートbの値を表示させたいです。 上手くできませんでしたので、教えてください。 Sub Do文2() Dim i As Integer i = 1 If Worksheets("a").Cells(i, 2) = "" Then Do While Worksheets("a").Cells(i, 1) <> "" Worksheets("a").Cells(i, 2) = Worksheets("b").Cells(1, 1) i = i + 1 Loop End If End Sub

  • 下記エクセルVBAコード:改良 表

    下記エクセルVBAコードの中で Case "a" Case "b" Case "c" などの情報を処理していますが、その”a”、"b"、"c"の代わりに、$A$50~$A$52の表の中(ここにaとか入っている)のデータを用いて処理できるようにするには、どのようにコードを変更すべきでしょうか。よろしくお願いします。 Sub test01() d = Range("A65536").End(xlUp).Row j = 1 For i = 1 To d Select Case Cells(i, "a") Case "a" Case "b" Case "c" '---XXX Case Else Worksheets("Sheet2").Cells(j, "A") = Cells(i, "A") Worksheets("Sheet2").Cells(j, "B") = Cells(i, "b") 列や行やシートが変わっても、類推で変えられるでしょう。 '---YYY j = j + 1 End Select Next i End Sub

  • VBAでの拡散計算

    エクセルのVBAを使って添付画像のようなグラフを作成しようと考えています。 以下の計算で作成できそうなのですが、⊿tを10-5より小さく設定し、1000sec~の濃度変化が知りたいため表計算ではなくVBAを使ってみました。 表計算では、 t=0のときx0=C0(飽和濃度)、x>x0でC=0とし(初期条件) x0では、 C(j+1,i) = C(j,i) +D * ( C(j,i-1) - C(j,i) ) / dx / dx * dt x >x0では、 C(j+1,i) = C(j,i) +D * ( C(j,i-1) - 2 * C(j,i) + C(j,i+1) ) / dx / dx * dt の計算を行い、セル表記が以下のようになりました。どの時間も物質量は一定です。(たぶん・・・)   t0、t1、t2、t3t、・・・ x1,60、58.8、57.6・・・ x2, 0、 1.2、2.38・・・ x3, 0、 0、0.02・・・ 上の計算をVBAで以下のように書いてみました。 Sub diffusion_dry_up2() Dim n As Integer, nt As Integer Dim i As Integer, j As Integer Dim b As Double, te As Double, dt As Double Dim c0 As Double, cs As Double, d As Double Dim x As Double, dx As Double, t As Double Dim a As Double, cjp As Double, cj0 As Double Dim cjm As Double b = InputBox("配管の長さb(m)") n = InputBox("配管の長さの方向分割数n") te = InputBox("計算する時間長t(sec)") dt = InputBox("時間増分dt(m)") c0 = InputBox("配管底部の濃度c0(vol.%)") cs = InputBox("時刻t=0の時の配管内の濃度cs(vol.%)") d = InputBox("拡散係数d(m^2/sec)") Sheet1.Cells(1, 2) = "配管の長さb(m)" Sheet1.Cells(2, 2) = "配管の長さの方向分割数n" Sheet1.Cells(3, 2) = "計算する時間長t(sec)" Sheet1.Cells(4, 2) = "時間増分dt(sec)" Sheet1.Cells(5, 2) = "配管底部の濃度c0(vol.%)" Sheet1.Cells(6, 2) = "時刻t=0の時の配管内の濃度cs(vol.%)" Sheet1.Cells(7, 2) = "拡散係数(m^2/sec)" Sheet1.Cells(1, 3) = b Sheet1.Cells(2, 3) = n Sheet1.Cells(3, 3) = t Sheet1.Cells(4, 3) = dt Sheet1.Cells(5, 3) = c0 Sheet1.Cells(6, 3) = cs Sheet1.Cells(7, 3) = d nt = te / dt dx = b / n Sheet1.Cells(1, 1) = nt t = 0 a = d * dt / dx ^ 2 Sheet1.Cells(1, 5) = t Sheet1.Cells(1 + 1, 4) = -dx Sheet1.Cells(1 + 2, 5) = c0 Sheet1.Cells(1 + n + 2, 4) = b + dx Sheet1.Cells(1 + n + 3, 5) = cs Sheet1.Cells(3, 5 + i) = a * (-cj0 + cjp) + cj0 For i = 1 To nt t = t + dt Sheet1.Cells(1, 5 + i) = t Sheet1.Cells(1 + n + 3, 5 + i) = a * (cjp - 2 * cjo + cjm) + cj0 For j = 2 To n + 2 cjp = Sheet1.Cells(1 + j + 1, 5 + i - 1) cj0 = Sheet1.Cells(1 + j + 0, 5 + i - 1) cjm = Sheet1.Cells(1 + j - 1, 5 + i - 1) Next j Next i linegraph 2, 4, 4 + n, nt + 2 End Sub Sub linegraph(sr As Integer, sc As Integer, lr As Integer, lc As Integer) ActiveSheet.ChartObjects.Add(200, 10, 240, 200).Select ActiveChart.ChartWizard _ Source:=Range(Cells(sr, sc), Cells(lr, lc)), _ gallery:=xlXYScatter, _ Format:=3, _ PlotBy:=xlColumns, _ categoryLabels:=1, _ SeriesLabels:=0, _ HasLegend:="false", _ Title:="ex2", _ categoryTitle:="t", _ ValueTitle:="y", _ ExtraTitle:="" End Sub しかしまったく表計算のようになりませんでした。 a = d * dt / dx^2以降の書き込みが変だと思うのですが、どのようにすればよいのでしょうか。 また、上のような表記ではtを大きくdtを小さくするとエラーになってしまいます。 質問項目が多いですが、よろしくお願いします。

  • VBA【dictionary勉強中ですが・・・】集計マクロ

    いつもお世話になっております。 現在dictionary勉強中ですが、なかなかコツをつかめず 思ったとおりのマクロを作成することができません(ノ_;) ところで、今回作成しているのは 元データ.xlsというファイルのシート(データ)に   |【A】| B | C |【D】| E | F |・・・|H|I|【J】|K 3  【顧客ID】|顧客|受付日|【担当】|・・・|【会場名】|(見出し) 4  データの始まり↓ と、ありまして、 集計データ.xlsのシート(集計)に  | A | B | C | D | E | F | 1 顧客ID|担当|会場名| と二行目から一覧表があります。 A列のIDが一致するものに Sheet(データ)  →  Sheet(集計)  セル( i, "D")の値 → セル( j, "B") に セル( i, "J")の値 → セル( j, "C")に     セル(j,"C")に値が入っているとき、セル(j,"D")に→Fまで(4回のみ) A列のIDが一致するものがない時 セル( i, "A")の値 → セル( 最終,"A")に  セル( i, "D")の値 → セル( 最終, "B") に セル( i, "J")の値 → セル( 最終,"C")に追加 というように、入れたいのですが、 以下のようなコードをネットで見つけ自分なりに考えて変更を加えてみましたが あまり分かっていないためどのように変更すればいいのかよく分かりません。どなたかご教授ください。お願いします。 Sub Try() Dim data_1() As String Dim data As Long Dim maxrow As Long Dim t As Integer, f As Integer, y As Integer Set ws1 = Worksheets("集計") Set ws2 = Worksheets("データ") Application.ScreenUpdating = False maxrow = ws2.Range("a65536").End(xlUp).Row With ws1 For i = 2 To Range("a65536").End(xlUp).Row data = .Cells(i, 1) f = 0 t = 0 With ws2 t = Application.WorksheetFunction.CountIf(.Range("a4:a" & maxrow), data) If t > 0 Then For n = 1 To maxrow ReDim Preserve data_1(f) If data = .Cells(n, 1) Then data_1(f) = .Cells(n, 10) f = f + 1 If t = f Then Exit For Else 'A列にIDが存在しなければ追加する:ここの記述がよく分かりません。 data_1(f) = .Cells(n, 1) End If Next n For y = 0 To UBound(data_1) ws1.Cells(i, maxcol(i)) = data_1(y) Next y End If End With Next i End With Application.ScreenUpdating = True End Sub '-------------------------- Private Function maxcol(ByVal i As Long) As Integer Dim j As Integer With Worksheets("集計") j = 4 Do While .Cells(i, j) <> "" j = j + 1 Loop maxcol = j End With End Function

  • VBAを勉強し始めた者です。

    VBAを勉強し始めた者です。 Private Sub スタート_Click() Dim myKey As String Dim maxrow As Long myKey = 入力値.Value maxrow = Worksheets("sheet1").Cells(Rows.Count, 1).End(xlUp).Row If flag = False Then '初めての検索処理 (1) Set c = Worksheets("sheet1").Range(Cells(2, 1), Cells(maxrow, 1)).Find(What:=myKey, LookIn:=xlValues, lookat:=xlPart, SearchOrder:=xlByRows) c.Interior.ColorIndex = 4 '初めての結果(range)を保存しておく Set d = c flag = True Else '2回目以降の検索処理 (2) Set d = Worksheets("sheet1").Range(Cells(2, 1), Cells(maxrow, 1)).Find(What:=myKey, LookIn:=xlValues, lookat:=xlPart, SearchOrder:=xlByRows) d.Interior.ColorIndex = 4 '保存しておいた結果と今回の検索結果を比較して1周してきたと判断して終了を表示 If c.Address = d.Address Then MsgBox "検索終了" End If End Sub 現在データはA1がデータ名(名前、番号、住所など)、A2からA11までデータが入っています。テキストボックス(以下TB)に入力された文字を含むセルに着色する、というものです。検索、着色部分は成功しています。 これにB1にデータ名、さらにB2からB11まで新たにデータを加えました。 本来はA列だけ検索の対象にしたいのですが後で他の機能を追加するためB列にもデータを加えました。 たとえばテキストボックスに入力した文字を三とします。三を含むデータがA2、A11、B2、B11にあったとします。 上記のプログラムだと、なぜかA11だけ着色され、終了します。本来はA2から下に向かって検索してほしいのですが。 試行錯誤した中には、B2→A11の二つのセルだけ、TBに入力された文字が含まれるセルに着色していきました。 11行以降もデータが増えることを想定して、 maxrow = Worksheets("sheet1").Cells(Rows.Count, 1).End(xlUp).Row で最終行を取得し、(1)、(2)を、 Set d = Worksheets("sheet1").Range("A2:"A" & maxrow).以下省略 としましたが、エラーが出ました。 手直しして、(1)(2)を最終行をカウントしてA2から始まって、A11まで検索できるようにしたはずなのですが、やはりダメでした。Range("A2:"A" & maxrow)の部分と上記のプログラムの不具合を教えてください。よろしくお願いします。

  • VBA Next For でのコピペについて

    EXCEL VBA初心者です。 AシートEW44からGD44までをコピーしてBというシートの最終行へコピーしたいです。 今下記のように組んでいるのですが、うまく作動しません。 Private Sub CommandButton1_Click() Dim i As Integer For i = 153 To 186 row1 = Worksheets("B").Cells(Rows.Count, 27).End(xlUp).Row Worksheets("A").Cells(i, 44).Value = Worksheets("B").Cells(row1 + 1, 27).Value Next i End Sub アドバイスいただけませんでしょうか。

  • エクセルVBAで、分岐がうまくできません。

    A,B,,Cのりんごとみかんの3種類の仕入れパターンがあり仕入の数量を算出したいですが、適正値が算出されません。 どのようにしたら、適正値を算出できるにのか教えてください。 Sub test() Dim i As Integer 'A リンゴは、500以下になったら1000個になるように仕入 'A みかんは、500以下になったら1000個になるように仕入 'A みかんまたはりんごの片方が500以下になったらみかんとりんごを1000個になるように仕入 i = 2 Do While Worksheets("sheet1").Cells(i, 1) <> "" If Cells(i, 1) = "A" And Cells(i, 2) <= 500 Or Cells(i, 3) <= 500 Then Worksheets("sheet1").Cells(i, 4) = 1000 - Cells(i, 2) Worksheets("sheet1").Cells(i, 5) = 1000 - Cells(i, 3) 'End If 'i = i + 1 'Loop 'B リンゴは、400以下になったら2000個になるように仕入 'B みかんは、400以下になったら2000個になるように仕入 'A みかんまたはりんごの片方が400以下になったらみかんとりんごを2000個になるように仕入 i = 2 'Do While Worksheets("sheet1").Cells(i, 1) <> "" ElseIf Cells(i, 1) = "B" And Cells(i, 2) <= 400 Or Cells(i, 3) <= 400 Then Worksheets("sheet1").Cells(i, 4) = 2000 - Cells(i, 2) Worksheets("sheet1").Cells(i, 5) = 2000 - Cells(i, 3) 'End If 'i = i + 1 'Loop ''C リンゴは、300以下になったら3000個になるように仕入 ''C みかんは、300以下になったら3000個になるように仕入 'A みかんまたはりんごの片方が300以下になったらみかんとりんごを3000個になるように仕入 i = 2 'Do While Worksheets("sheet1").Cells(i, 1) <> "" ElseIf Cells(i, 1) = "C" And Cells(i, 2) <= 300 Or Cells(i, 3) <= 300 Then Worksheets("sheet1").Cells(i, 4) = 3000 - Cells(i, 2) Worksheets("sheet1").Cells(i, 5) = 3000 - Cells(i, 3) End If i = i + 1 Loop End Sub

  • VBA 初心者です シートの指定がうまくいかない

    初めまして!VBAを利用してあるシートにある人の名前を他のシートに入力するマクロを組んでいるのですが、この方法でやるとシートの指定がうまくいかず実行時エラーになってしまいます。A個人というシートでボタンを押したら大丈夫なのですが、他のシートにボタンを設置し、押すとエラーになってしまいます…どなたか詳しい方、どうしてこうなるのか、また、どうすればうまく動いてくれるのか教えていただきたいです。 Dim fa As Integer Dim namae As String Dim n As Integer On Error Resume Next n = Worksheets("ランニングスコア").Range("C100000").End(xlUp).Offset(0, 0) With Sheets("A個人") fa = WorksheetFunction.Match(n, Columns(1), 0) namae = Cells(fa, 2) End With Worksheets("ランニングスコア").Range("D100000").End(xlUp).Offset(2, 0) = namae

専門家に質問してみよう