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

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

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

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

VBA

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

Q&A

解決済

2回答

974閲覧

キーの重複があった場合にレコードの削除をしたい

taku-s

総合スコア12

CSV

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

VBA

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

1グッド

0クリップ

投稿2022/10/03 09:33

実現したいこと

イメージ説明

VBAを仕事で使用することになり学習をしています。学習中の初心者です。

上記画像のCSVファイルがありますが、IDが重複しているレコードがあった場合(画像でいうa1、a3、a4)点検に〇がついているレコードを残し、実施に〇がついているレコードを削除したいです。

以下画像のようにしたいです。
イメージ説明
レコード数は画像では9件になっていますが、実際には万単位の件数となる予定です。また、列数も増減します。

考えていること

レコード数が多い場合は、配列をした方が高速化するということも聞いたのですが、今回のように重複をチェックする際には逆に処理に時間がかかってしまうのではないかと考えました。
なので、ネットで調べ
以下の関数を使用してプログラムを組むと便利なのではないかと考えました。

VBA

1RemoveDuplicates Columns:=Array(1), Header:=xlYes

しかし、うまく実現できません。

該当のソースコード

VBA

1Sub duplicateDelete() 2 3 Dim rowsData As Integer 4 Dim columnsData As Integer 5 Dim MasterWs As Worksheet 6 Dim Region As Variant 7 8 Set MasterWs = Worksheets("test") 9 10 rowsData = MasterWs.Cells(Rows.Count, 1).End(xlUp).Row 11 12 Region = MasterWs.Range("A2" & rowsData).CurrentRegion.Select 13 Region.RemoveDuplicates Columns:=Array(1), Header:=xlYes 14 15 16End Sub

試したこと

上記のコードを使用するとエラーが発生します。
.CurrentRegion.Selectでレコードを選択をし、変数に代入しました。
その上で.RemoveDuplicates Columns:=Array(1), Header:=xlYesを使用
するとエラーが発生します。
.CurrentRegion.Selectを変数にいれず、

VBA

1MasterWs.Range("A2" & rowsData).CurrentRegion.Select.RemoveDuplicates Columns:=Array(1), Header:=xlYes

と書いてもエラーが出てしまいます。
ただもしこの関数が使用できたとしても、点検実施の条件式を使うことも
難しそうなので、この関数を使用すること自体が適切ではないのではないかと思い始めました。

もしご助言やオススメの書き方などがあれば、ご教授頂けると幸いです。

Cocode👍を押しています

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

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

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

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

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

guest

回答2

0

点検と実施が1:1のデータが前提のコードになります。

vba

1Sub test() 2 3 Dim jisshi As Object 4 Dim tenken As Object 5 Dim delete As Collection 6 Dim sht As Worksheet 7 Dim i As Double 8 9 Set jisshi = CreateObject("Scripting.Dictionary") 10 Set tenken = CreateObject("Scripting.Dictionary") 11 Set sht = ActiveWorkbook.Worksheets(1) 12 13 With sht 14 For i = .Cells(1, 1).End(xlDown).Row To 2 Step -1 15 If .Cells(i, 3).Value = "〇" Then 16 jisshi.Add .Cells(i, 1).Value, .Cells(i, 1).Row 17 If tenken.exists(.Cells(i, 1).Value) Then 18 .Rows(i).delete 19 End If 20 ElseIf .Cells(i, 4).Value = "〇" Then 21 tenken.Add .Cells(i, 1).Value, .Cells(i, 1).Row 22 If jisshi.exists(.Cells(i, 1).Value) Then 23 .Rows(jisshi.Item(.Cells(i, 1).Value)).delete 24 End If 25 End If 26 Next i 27 End With 28 29End Sub

投稿2022/10/03 11:52

編集2022/10/03 11:57
meg_

総合スコア10579

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

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

taku-s

2022/10/04 07:18

連想配列を2つ使用し、確認し合っていくんですね! 普段別のプログラミング言語を使用していますが、この方法は自分の引き出しにはなかったです。 処理も無事実現できました、ありがとうございます!
guest

0

ベストアンサー

データ件数が多い重複チェックは連想配列(Dictionary)を使うと高速処理できます。

vba

1Sub duplicateDelete() 2 Application.ScreenUpdating = False 3 4 Dim rng As Range 5 Set rng = Cells(1).CurrentRegion 6 Set rng = rng.Offset(1).Resize(rng.Rows.Count - 1, 4) '表のデータ範囲(D列まで) 7 Dim ary() 8 ary = rng.Value 'データ範囲を配列に 9 10 Dim dic As Object 11 Set dic = CreateObject("Scripting.Dictionary") 12 13 'C列が〇のIDをDictionaryに登録 14 Dim i As Long 15 For i = 1 To UBound(ary) 16 If ary(i, 4) = "〇" Then dic(ary(i, 1)) = i 17 Next 18 19 'D列が〇でかつIDがDictionaryに存在するときA列を"×"に 20 For i = 1 To UBound(ary) 21 If ary(i, 3) = "〇" Then 22 If dic.Exists(ary(i, 1)) Then ary(i, 1) = "×" 23 End If 24 Next 25 rng.Value = ary '配列をデータ範囲に代入 26 27 Cells(1).AutoFilter Field:=1, Criteria1:="×" 'A列が×の行を抽出 28 Cells(1).CurrentRegion.Offset(1).EntireRow.Delete '行削除 29 Cells(1).AutoFilter 30 31 Application.ScreenUpdating = True 32End Sub

投稿2022/10/03 11:32

編集2022/10/04 07:40
hatena19

総合スコア33699

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

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

taku-s

2022/10/04 07:25

Application.ScreenUpdating = True を調べてみたのですが、処理を高速化する記述の一つなんですね。細やかに対応していただきありがとうございます。 上記のプログラムを動かしてみたのですが、aryとrngでエラーが発生してしまいました。 aryは二次元配列として宣言し直しエラー解消の対応ができたのですが、「rng」がエラー解消ができません。ここで使用されている「rng」は何を宣言しているのでしょうか。
hatena19

2022/10/04 07:42

コードを修正したときに、コピーミスしていたようです。 回答のコードを修正しましたので、確認ください。 サンプルで動作確認済みです。 行削除も1行ずつするのではなく、削除行にしるしをつけて、それでフィルターをかけて一気に削除することで高速化してます。
taku-s

2022/10/04 08:53

ご返答ありがとうございます。 私の環境でも、動作ができました。 フィルターで削除するなど、SQLのようなこともできるんですね。 全くの別件ですが今後仕事をする上で、VBAでもSQLでいうINNER JOINみたいなことができないか検討しておりました。 そういう意味でも今後に繋がるヒントのようなものも感じました。 ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問