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

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

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

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

Q&A

解決済

VBAでFOR文を回してデータを突合させたい

Kazuhiro-ch
Kazuhiro-ch

総合スコア82

VBA

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

2回答

0グッド

0クリップ

514閲覧

投稿2022/11/23 23:59

前提

Sheet1(start)とSheet2(goal)からそれぞれ日付データを取得し、FOR文で突合させて、足りない部分をSheet1からSheet2へコピーしたいです。

詳細

日付データAデータB
11/2210002000

以上のようなデータが入ったシートが2枚あり、日付の部分を突合させ、不足分をコピペするといったものです。ただこれまでPythonしか使ったことがないため、データの型定義など慣れないことが多く、うまくいかないため質問いたしました。

発生している問題・エラーメッセージ

アプリケーション定義またはオブジェクト定義のエラーです

該当のソースコード

VB

1 2Sub compare_date() 3 4Dim L, lRow, M, mRow As Long 5 6lRow = Sheets("start").Cells(Rows.Count, "A").End(xlUp).Row '日付データの最終行 7mRow = Sheets("goal").Cells(Rows.Count, "A").End(xlUp).Row '比較先の日付データの最終行 8 9For L = 2 To lRow 10 If L >= Sheets("goal").Cells(M, "A") Then 11 MsgBox L 12 End If 13Next L 14 15End Sub 16

試したこと

MsgBoxを使っているのはコピーする前に、とりあえず値が適切か拾いたいためです。

試したこととしては、For Each などにして、FOR文を回しましたが、Variant型にしないといけずうまくいきませんでした。

以下のような質問にはグッドを送りましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

回答2

1

ベストアンサー

変数Mが未定義です。また、Lはただの行数を表す数値なので時刻比較をしたいならば正しいとは言えません。

Sub compare_date() Dim L as long , lRow as long, M as long, mRow As Long dim wsStart as worksheet:set wsStart=thisworkbook.Sheets("start") dim wsGoal as worksheet:set wsGoal=thisworkbook.Sheets("goal") lRow = wsStart.Cells(Rows.Count, "A").End(xlUp).Row '日付データの最終行 mRow = wsGoal.Cells(Rows.Count, "A").End(xlUp).Row '比較先の日付データの最終行 For L = 2 To lRow for M= 2 to mRow If wsStart.cells(L,1).value >= wsGoal.Cells(M, 1).value Then MsgBox L '時刻を出したいならwsStart.cells(L,1).value '処理的に一行一回ずつしか表示させなくていい気がするので内側のループを飛ばす Exit For End If nest M Next L End Sub

範囲セル指定でfor each を使う場合は変数にrangeオブジェクトが代入されるためrange型でないとエラーが出るのが原因です(variantは自動解釈してくれるので問題ありませんが、Long型だと型違いでエラーが出たということです)

for eachを使う場合

```ここに言語を入力 Sub compare_date() Dim L as Range , lRow as long, Dim M as Range, mRow As Long dim wsStart as worksheet:set wsStart=thisworkbook.Sheets("start") dim wsGoal as worksheet:set wsGoal=thisworkbook.Sheets("goal") lRow = wsStart.Cells(Rows.Count, "A").End(xlUp).Row '日付データの最終行 mRow = wsGoal.Cells(Rows.Count, "A").End(xlUp).Row '比較先の日付データの最終行 For each L in wsStart.Range(wsStart.cells(2,1),wsStart.cells(LRow,1) for M= 2 to mRow '一応、for each分は順番の保障がされてないので比較側は普通に回す If L.value >= wsGoal.Cells(M, 1).value Then MsgBox L.value Exit For End If nest M Next L End Sub

ただ、同じ時刻のデータがあるかどうかを比較するならばVBAにもDictionaryがあるのでこちらを使ったほうが簡潔で便利だと思います。
https://daitaideit.com/vba-dictionary/

投稿2022/11/24 00:26

編集2022/11/24 01:14
pig_vba

総合スコア668

spoofy_dragon👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

0

型定義以前にロジックの問題ですね。

L >= Sheets("goal").Cells(M, "A")
L(行番号)と日付(A列の値)を比較しても無意味です。

突合するなら、2つのシートの値を二重ループして比較する必要があります。

下記のようなコードになるでしょう。

vba

1Sub compare_date() 2 3 Dim L As Long, lRow As Long, M As Long, mRow As Long '型宣言は一つずつする必要がある 4 5 lRow = Sheets("start").Cells(Rows.Count, "A").End(xlUp).Row '日付データの最終行 6 mRow = Sheets("goal").Cells(Rows.Count, "A").End(xlUp).Row '比較先の日付データの最終行 7 8 For L = 2 To lRow 9 For M = 2 To mRow 10 If Sheets("start").Cells(L, "A") = Sheets("goal").Cells(M, "A") Then 11 Exit For 12 End If 13 Next M 14 If M > mRow Then MsgBox L 'カウンターが最終行より上なら一致する値無し 15 Next L 16 17End Sub

ただ、Excelなので、関数を使えば2重ループする必要はないです。
あるいは、連想配列(Dictionaryオブジェクト)を使うと高速化できます。

エクセルのMatch関数を使って検索するコード例

vba

1Sub compare_date2() 2 3 Dim rStart As Range, rGoal As Range 4 With Sheets("start") 5 Set rStart = .Range(.Cells(2, "A"), .Cells(Rows.Count, "A").End(xlUp)) '日付データのセル範囲 6 End With 7 With Sheets("goal") 8 Set rGoal = .Range(.Cells(2, "A"), .Cells(Rows.Count, "A").End(xlUp)) '比較先の日付データのセル範囲 9 End With 10 11 Dim l As Variant, i As Long 12 For Each l In rStart 13 On Error Resume Next 14 i = WorksheetFunction.Match(l, rGoal, 0) 'Matchで一致データを検索 15 If Err.Number <> 0 Then MsgBox l.Row '一致データがないとエラーになるのでメッセージ表示 16 On Error GoTo 0 17 Next l 18 19End Sub

投稿2022/11/24 01:11

編集2022/11/24 01:33
hatena19

総合スコア32016

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

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

ただいまの回答率
86.02%

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

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

質問する

関連した質問

同じタグがついた質問を見る

VBA

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