前提
以前にこちらで質問をしたのですが、少し内容が変わってしまい解消できないでいます。
https://teratail.com/questions/k87k27iad1j3pc
以前の質問では、CSVファイルでの重複処理を目標としていましたが、今回悩んでいるのは二次元配列内での重複処理の方法です。
以前質問した内容は以下となります。
ーーーーーーーーーーーーーーーーーー
上記ファイルの画像があります。
IDが重複しているレコードがあった場合(画像でいうa1、a3、a4)点検に〇がついているレコードを残し、実施に〇がついているレコードを削除したいです。
以下画像のようにしたいです。
画像では9行までしかデータがありませんが、実際には10万行以上のデータがある為高速化の重複加工作業を目指しています。
ーーーーーーーーーーーーーーーーーーーーーーーー
以前考えていた手順
スタート:データの入った二次元配列がある。
1 :二次元配列を一度CSVファイルに出力する。
2 :以前teratailで質問した方法でCSVファイルの重複除去を行う。
3 :重複除去後に再度CSVファイルを二次元配列に読み込み次の処理を行っていく・・・。
前回はCSVファイルを直接加工する方法で、重複があった場合にレコードの削除をしていたのですが、二次元配列にデータが入っている状態で重複除去ができないかと考えました。
なぜなら一度出力してから再度読み込むのは効率が悪いのではないかと考えたからです。
速度のことを考えても以下の手順が実現できるのであれば、速度アップが見込めるのではないかと考えました。
スタート:データの入った二次元配列がある。
1 :二次元配列内で、重複除去を行う。
2 :次の処理を行っていく。
そこで以前の質問の返答から、連想配列を使用すれば二次元配列のままでも高速化ができるのではないかと考えました。
しかし、重複があった際に二次元配列で行を削除しようとすると.deleteが使用できませんでした。
実現したいこと
二次元配列内でIDの値に重複があった場合、
点検に〇がついているレコードを残し、実施に〇がついているレコードを削除したい。
出来る限り高速で実現したい。
発生している問題・エラーメッセージ
以下2つのスクリプトを実行させると、.deleteの箇所でエラーが発生してしまう。
この部分のエラーを解消できないでしょうか。
高速化の観点から全く別の書き方があれば教えていただきたいです。
該当のソースコード
vba
1'こちらが二次元配列の変数aryです。 2 Dim ary(8, 6) As Variant 3 ary(0, 0) = "ID" 4 ary(0, 1) = "都道府県" 5 ary(0, 2) = "実施" 6 ary(0, 3) = "点検" 7 ary(0, 4) = "備考1" 8 ary(0, 5) = "備考2" 9 ary(0, 6) = "備考3" 10 ary(1, 0) = "a1" 11 ary(1, 1) = "東京" 12 ary(1, 2) = "〇" 13 ary(1, 3) = "" 14 ary(1, 4) = "-" 15 ary(1, 5) = "-" 16 ary(1, 6) = "-" 17 ary(2, 0) = "a2" 18 ary(2, 1) = "埼玉" 19 ary(2, 2) = "〇" 20 ary(2, 3) = "" 21 ary(2, 4) = "-" 22 ary(2, 5) = "-" 23 ary(2, 6) = "-" 24 ary(3, 0) = "a3" 25 ary(3, 1) = "神奈川" 26 ary(3, 2) = "〇" 27 ary(3, 3) = "" 28 ary(3, 4) = "-" 29 ary(3, 5) = "-" 30 ary(3, 6) = "-" 31 ary(4, 0) = "a4" 32 ary(4, 1) = "千葉" 33 ary(4, 2) = "〇" 34 ary(4, 3) = "" 35 ary(4, 4) = "-" 36 ary(4, 5) = "-" 37 ary(4, 6) = "-" 38 ary(5, 0) = "a5" 39 ary(5, 1) = "山梨" 40 ary(5, 2) = "" 41 ary(5, 3) = "〇" 42 ary(5, 4) = "-" 43 ary(5, 5) = "-" 44 ary(5, 6) = "-" 45 ary(6, 0) = "a1" 46 ary(6, 1) = "東京" 47 ary(6, 2) = "" 48 ary(6, 3) = "〇" 49 ary(6, 4) = "-" 50 ary(6, 5) = "-" 51 ary(6, 6) = "-" 52 ary(7, 0) = "a3" 53 ary(7, 1) = "神奈川" 54 ary(7, 2) = "" 55 ary(7, 3) = "〇" 56 ary(7, 4) = "-" 57 ary(7, 5) = "-" 58 ary(7, 6) = "-" 59 ary(8, 0) = "a4" 60 ary(8, 1) = "千葉" 61 ary(8, 2) = "" 62 ary(8, 3) = "〇" 63 ary(8, 4) = "-" 64 ary(8, 5) = "-" 65 ary(8, 6) = "-" 66
vba
1Sub duplicateDelete() 2 3 Application.ScreenUpdating = False 4 5 Dim jisshi As Object 6 Dim tenken As Object 7 Dim delete As Collection 8 Dim i As Double 9 Dim max_row As Long 10 11 Set jisshi = CreateObject("Scripting.Dictionary") 12 Set tenken = CreateObject("Scripting.Dictionary") 13 14 max_row = UBound(ary, 1) 15 For i = 1 To max_row 16 If ary(i, 2) = "〇" Then 17 jisshi.Add ary(i, 0), i 18 19 If tenken.exists(ary(i, 0)) Then 20 ary.Rows(i).delete 21 End If 22 ElseIf ary(i, 3) = "〇" Then 23 tenken.Add ary(i, 0), i 24 If jisshi.exists(ary(i, 0)) Then 25 ary.Rows(tenken.Item(ary(i, 0))).delete 26 End If 27 End If 28 Next i 29 30End Sub
こちらのスクリプトでも、やはり.deleteの部分でエラーとなってしまいます。
vba
1 Dim dic As Object 2 Set dic = CreateObject("Scripting.Dictionary") 3 4 'C列が〇のIDをDictionaryに登録 5 Dim i As Long 6 For i = 1 To UBound(ary) 7 If ary(i, 3) = "〇" Then dic(ary(i, 0)) = i 8 Next 9 10 'D列が〇でかつIDがDictionaryに存在するときA列を"×"に 11 For i = 1 To UBound(ary) 12 If ary(i, 2) = "〇" Then 13 If dic.Exists(ary(i, 0)) Then ary(i, 0) = "×" 14 End If 15 Next 16 17 Cells(1).AutoFilter Field:=1, Criteria1:="×" 'A列が×の行を抽出 18 Cells(1).CurrentRegion.Offset(1).EntireRow.delete '行削除 19 Cells(1).AutoFilter 20
調べたこと
ネットで調べた限りでは、二次元配列での行指定の削除に関して.deleteのようなものはないらしく、
以下のURLに書かれているようにプロシージャを使用するしかなさそうです。
http://blog.livedoor.jp/aero_iki-jibundakemacro/archives/30587497.html
ただ、高速の観点から考えるとこれが正解と言ってよいのかはなはだ疑問です。
補足情報(FW/ツールのバージョンなど)
MicroSoftOffice2019

回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2022/10/24 23:54
2022/10/25 00:37
2022/10/26 01:38