![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?8acaa2e)
シート(最初)のA,B,C列を連結した値と
シート(残)のA,B,C列を連結した値を照合させ
同じ値の場合は
シート(残)の該当行を削除です。
シート(最初)は6,182行
シート(残)は7,561行です。
VLookupを使って処理時間5分です。
VLookupを使わない記述で25分です。
20,000行位のデータを処理したいのですが時間が不安です。
別スレで
「VLookupで処理3分をdictionaryオブジェクトで1秒以内にする方法」を
教えていただきましたが、流用ができません。
シート(残)内にもシート(最初)内にも重複行はありません。
私の記述は「F列を検索用に使用」となっていて
F列にデータがある場合、都度記述を書換えないと
使えないので、そこも対応したいです。
照合させる値はA,B,Cの連結値というのは変わらないのですが
データがある範囲は都度変化する為です。
・A~E列とかA~H列とか
・シート残はA~E列、シート最初はA~G列とか
記述そのものを教えてください。よろしくお願いします。
Sub 自動重複削除F列使用()
'シート(最初)のA,B,C列とシート(残)のA,B,C列が一致した行は
'シート残の行を削除
'F列を検索値として使用。
Dim Line As Long
Dim LastRow As Long
Dim myRange As Range
Dim Flag
'シート「最初」のF1に、A,B,C列を結合した値を転記
With Sheets("最初")
Set myRange = .Range("F2:F" & .Cells(Rows.Count, "A").End(xlUp).Row)
.Range("F2").FormulaR1C1 = "=RC[-5]&RC[-4]&RC[-3]"
'シート「最初」のF2からデータのあるところまで
'F1の規則でデータ貼付
.Range("F2").AutoFill Destination:=myRange
End With
'シート「残」のF1に、A,B,C列を結合した値を転記
Sheets("残").Select
LastRow = Cells(Rows.Count, "A").End(xlUp).Row
Range("F2").FormulaR1C1 = "=RC[-5]&RC[-4]&RC[-3]"
'シート「最初」のF2からデータのあるところまで
'F1の規則でデータ貼付
Range("F2").AutoFill Destination:=Range("F2:F" & LastRow)
On Error Resume Next
'双方のシートのF列を照合させ、ヒットした行は
'シート「残」から行削除をする
For Line = LastRow To 2 Step -1
Flag = WorksheetFunction.VLookup(Cells(Line, 6).Value, myRange, 1, 0)
If Err.Number = 0 Then
Rows(Line).Delete xlUp
Else
Err.Clear
End If
Next Line
'検索に使用したF列を削除
Sheets("残").Select
Columns("F:F").Select
Selection.Delete Shift:=xlToLeft
Sheets("最初").Select
Columns("F:F").Select
Selection.Delete Shift:=xlToLeft
Sheets("残").Select
Range("A1").Select
End Sub
●別方法
Sub 自動重複行削除F列未使用超遅()
'VLOOKUP無
'シート(最初)のA,B,C列とシート(残)の
'A,B,C列が一致した行はシート(残)の行を削除
Dim ws1, ws2 As Worksheet
Dim i, j As Long
Set ws1 = Worksheets("最初")
Set ws2 = Worksheets("残")
For i = 2 To ws1.Cells(Rows.Count, 1).End(xlUp).Row
For j = ws2.Cells(Rows.Count, 1).End(xlUp).Row To 2 Step -1
If ws1.Cells(i, 1) = ws2.Cells(j, 1) And ws1.Cells(i, 2) = ws2.Cells(j, 2) And _
ws1.Cells(i, 3) = ws2.Cells(j, 3) Then
ws2.Rows(j).Delete (xlUp)
End
No.9
- 回答日時:
こんばんは
実際のデータでのスピードの検証はしていないのですが
Couontif関数
が使えるかもしれません。
シート(最初)とシート(残)のZ列にそれぞれ
ABCを連結した値を入れておきます。
シート(残)のAA2に
=COUNTIF(最初!Z:Z,残!Z2)
以下オートフィル
としますと、シート(最初)と重複なしなら0、あれば1以上となります。
オートフィルタを使用すれば、0の行を抽出できますので、別のシートやブックに抽出結果をコピー&ペーストします。
この回答への補足
これは基幹システムが自動ではきだしたデータです。
でセルの書式設定は全て標準です。
B,C列は必ず数字4ケタです。
ただし「数値が文字列として保存されています」
となっています。
A列は英数字混在で10桁~14桁です。
で数字のみの場合も有り、
同じく「数値が文字列として保存されています」となっています。
このA列が数字のみで「数値が文字列として保存されています」と
なっていると、
=COUNTIF(最初!Z:Z,残!Z2)
以下オートフィルで、
シート(最初)と重複なしなら0、あれば1以上が
重複なのに0になってしまい漏れてしまいます。
また
シート最初が10,046行
シートが11,425行だと
=COUNTIF(最初!Z:Z,残!Z2)
以下オートフィル
した時にCPU使用率100%でしばらくPCが
はまってしまいました。
どうもありがとうございました。
マクロ作成以前はこの方法をマニュアルで行っていました。
・シート(最初)と重複なしなら0、あれば1
が精度が悪く漏れがある
・計算式を入れて値が出たら
値貼付で式を消さないと、シート最初→シート残に
動かすと「再計算」でしばらくとまる
・同じく計算式で出た列の値優先で並び変えて
1の行だけを一気に削除の時、
「再計算」となる
などで使用者から
「値貼付って意味わからないし他の編集作業のように
ボタン1個クリックでできるようにしてほしい」
と言われてマクロにしました。
どうもありがとうございます。
No.8
- 回答日時:
>・1件ずつ重複チェックをするのではなく別作業列に数式を入れてまとめてチェックする。
ここ、遅いですね。使い物にならないです。失礼しました..orz
この部分だけDictionaryを使った折衷案。
#シート名やデータ範囲などは実状に合わせて適宜、手を入れてください。
Sub try_1()
'VBE[ツール]-[参照設定]で"Microsoft Scripting Runtime"参照
Dim dic As Dictionary
Dim r1 As Range '照合元(残)
Dim r2 As Range '照合先(最初)
Dim r As Range '削除起点
Dim i As Long
Dim v() As Variant '照合元
Dim w() As Variant '照合先
Dim flg() As Boolean '照合結果
'データ範囲のIV列を取得
With Sheets("sheet1").Range("A1").CurrentRegion.EntireRow
Set r1 = Intersect(.Cells, .Offset(1), .Columns("IV"))
End With
With Sheets("sheet2").Range("A1").CurrentRegion.EntireRow
Set r2 = Intersect(.Cells, .Offset(1), .Columns("IV"))
End With
r1.Formula = "=A2&B2&C2"
v() = r1.Value
ReDim flg(1 To UBound(v), 0) As Boolean
r1.ClearContents
r2.Formula = "=A2&B2&C2"
w() = r2.Value
'作業列削除
r2.EntireColumn.Delete
Set dic = New Dictionary
'Dictionaryに照合先を登録
For i = 1 To UBound(w)
dic(CStr(w(i, 1))) = Empty
Next
'照合元と照合先の重複チェック
For i = 1 To UBound(v)
flg(i, 0) = dic.Exists(CStr(v(i, 1)))
Next
'照合結果をIV列に書き戻し
r1.Value = flg()
'データ範囲のみソート
r1.EntireRow.Sort Key1:=r1.Item(1), _
Order1:=xlAscending, _
Header:=xlNo, _
OrderCustom:=1, _
Orientation:=xlTopToBottom
'重複データの先頭を検索
Set r = r1.Find(What:="TRUE", _
LookIn:=xlValues, _
LookAt:=xlWhole)
If Not r Is Nothing Then
'重複データあれば行全体削除
Range(r, r1(r1.Count)).EntireRow.Delete
End If
'作業列削除
r1.EntireColumn.Delete
Set dic = Nothing
Set r1 = Nothing
Set r2 = Nothing
Set r = Nothing
End Sub
最速ではないです。速度より理解し易さ重視..(多分。
理解した上でなら、メンテナンスもそんなに大変じゃないと思います。
ありがとうございました。
コンパイルエラー
ユーザー定義型は定義されていません
Dim dic As Dictionaryでとまります。
'VBE[ツール]-[参照設定]で"Microsoft Scripting Runtime"参照
↓
参照可能なライブラリファイル
で
Microsoft Scripting Runtime
というのは無かったのですが.....
初めて開くウィンドーですし
ユーザー定義型?
全然分かりません。
>理解した上でなら
理解は私では難しそうです。
申し訳ありません。
No.7
- 回答日時:
こんな感じでいかがでしょう。
Sub Sample()
Dim LastNum As Long
Dim Data() As String, aData As String
Dim rNum1 As Long, rNum2 As Long
Application.ScreenUpdating = False
Worksheets("最初").Activate
LastNum = Cells(Rows.Count, 1).End(xlUp).Row
ReDim Data(2 To LastNum)
For rNum1 = 2 To LastNum
Data(rNum1) = Cells(rNum1, 1).Value & Cells(rNum1, 2).Value & Cells(rNum1, 3).Value
Next rNum1
Worksheets("残").Activate
For rNum2 = Cells(Rows.Count, 1).End(xlUp).Row To 2 Step -1
aData = Cells(rNum2, 1).Value & Cells(rNum2, 2).Value & Cells(rNum2, 3).Value
For rNum1 = 2 To LastNum
If Data(rNum1) = aData Then
Rows(rNum2).Delete
Data(rNum1) = Data(LastNum)
LastNum = LastNum - 1
Exit For
End If
Next rNum1
Next rNum2
Application.ScreenUpdating = True
End Sub
この回答への補足
シート最初 10,046行
シート残 11,425行
とデータが増えたら
約20秒と処理時間が長くなりました。
でも素晴らしいです。
どうもありがとうございました。
ただ記述にコメントを入れたいのですが
どの分が何をしているのか分からず
入れれないです。すいません。
私のVLOOKUPと同じ処理結果でかつ
1秒かかりませんでした。
20,000行でも挑戦してみます。
どうもありがとうございました。
No.6
- 回答日時:
照合するキーがあるならエクセルに決めてかかる必要性はありません。
アクセスでもCSVファイルでも照合はできます。1つのシートにて、合わせた14000行近くで最初と残の区別がつけばそれでも照合可能です。
決められた時間内にしなければいけないのか?、処理時間に不安げなのはよくわかりませんけど。
すいません。
エクセルがまだよく使えません。
アクセスは無理です。
処理時間についてですが自分で作成した
VLOOKUPは5分です。
よって20,000行だと15分かなと。
その間CPU使用率が100%で他の操作は出来ませんし
また以前ここでVLOOKUPを1秒以内にしてもらった事が
あるので出来るのかなと質問しました。
(ただしその時は値を返して転記で行削除ではなかったです。)
どうもありがとうございました。
No.5
- 回答日時:
条件により行を削除するのを、実際に削除するのではなく一旦配列に入れて早くする方法は
http://oshiete.goo.ne.jp/qa/6404265.html
でも、その前にもお見せしたと思いますが・・・・・・・・。
これでいかがですか?
実際に行を削除しているわけではないので、行により書式が違ったりすると変な感じになってしまいますが。
Sub test01()
Dim myS, myZ, myX
Dim i As Long, j As Long, n As Long, m As Long
Dim buf As Boolean
Dim zz As String, ss As String
With Sheets("最初")
myS = .Range("A2:C" & .Cells(Rows.Count, "A").End(xlUp).Row).Value
End With
With Sheets("残")
myZ = .Range("A2:C" & .Cells(Rows.Count, "A").End(xlUp).Row).Value
End With
ReDim myX(1 To UBound(myZ, 1), 1 To UBound(myZ, 2))
For i = 1 To UBound(myZ, 1)
buf = False
zz = ""
For j = 1 To UBound(myZ, 2)
zz = zz & myZ(i, j)
Next j
For n = 1 To UBound(myS, 1)
ss = ""
For j = 1 To UBound(myS, 2)
ss = ss & myS(n, j)
Next j
If zz = ss Then
buf = True
Exit For
End If
Next n
If Not buf Then
m = m + 1
For j = 1 To UBound(myZ, 2)
myX(m, j) = myZ(i, j)
Next j
End If
Next i
With Sheets("残")
.Range("A2:C" & .Cells(Rows.Count, "A").End(xlUp).Row).ClearContents
.Range("A2").Resize(m, UBound(myZ, 2)).Value = myX
End With
End Sub
この回答への補足
>削除されるべき行が残ったり、
>削除されてはいけない行が残ったり。
↓
削除されるべき行が残ったり、
削除されてはいけない行が削除されたりです。
またお礼に誤解を招く内容がありました。
私が別スレで教えていただいた物を改造した場合と
今回教えていただいた物の処理結果が
同じように読取れてしまいます。
そうではありませんでした。m(__)m
私の改造版の方が程度が悪いです。
merlionXXさんに今回教えていただいた方が
内容がはっきりしています。
まずシート(残)は1行も削除されておらず7,561行
そのまま残っています。
(1,379行だけ残る予定です。
項目行を入れると1,380行目。)
A~E列までデータがありますが
1380行目まではA~E列まで全部データがありますが
1381行目から7,561行までは
A,B,C列の値がなくなりD,E列の値だけになっています。
処理時間は約1分です。
申し訳ありませんでした。
>その前にもお見せしたと思いますが・・・・・・・・。
はい。それを改造すれば出来るとたかをくくっていましたが
駄目でした。
削除されるべき行が残ったり、
削除されてはいけない行が残ったり。
また両シートとも
A~E列のデータなのですが
残った行において
途中までは正常ですが途中から
列のとこどころのデータが消失しました。
よってギブアップで質問しました。
その動かない私が改造した記述では
回答者様に解析の時間をとらせてしまうので
自分で出来た思ったとうりに動く
VLOOKUPの記述を載せました。
merlionXXさんに教えていただいた記述で試したのですが
すでにお断りがありますが
>実際に行を削除しているわけではないので、
>行により書式が違ったりすると変な感じになってしまいますが。
のとうり、
削除されるべき行が残ったり、
削除されてはいけない行が残ったり。
また両シートとも
A~E列のデータなのですが
残った行において途中までは正常ですが
途中から列のとこどころのデータが消失しました。
よく分かりません。m(__)m
どうもありがとうございました。
No.4
- 回答日時:
>記述そのものを教えてください。
よろしくお願いします。まずは記述そのものではなくて考え方から。
なのでニーズがない場合はスルーしてください。
・連結値用に固定の未使用列を使う。
(例えば最右のIV列)
・1件ずつ重複チェックをするのではなく別作業列に数式を入れてまとめてチェックする。
(例えばIU列に=ISNUMBER(MATCH(IV2,Sheet2!$IV$2:$IV$20000,0))などの数式
Formulaプロパティを使えばダイレクトに指定できるので解かりやすい)
・1行ずつ削除するのではなく並べ替えてまとめて削除する。
(IU列基準にソートして下のほうにTRUEがまとまるのでこれを削除)
ワークシート上での作業ですから、複数範囲にまとめて数式を入れたりソートを活用したり。
シート上のソートは速くて便利です。
まずはVBAのA。Applicationの長所を活かして実務を行えば良いのではないでしょうか。
前述の処理は基本的に「マクロの記録」でベースが録れます。
自分で理解した上でコーディングできるので応用も利きやすく、
今後の役にも立つのではないでしょうか。
計算式を入れたのですが
処理が終わらずフリーズ状態になりました。
多分式の入れ方が悪いのだと思いますが
ちょっと手に負えませんでした。
どうもありがとうございました。
No.3
- 回答日時:
A.SelectとSelection.Bを使わず、直接A.Bと書くことを意識するだけでもそこそこ速くなります。
これは、例えば以下のコードを
--
Sheets("残").Select
Columns("F:F").Select
Selection.Delete Shift:=xlToLeft
--
こう書きなおす、という事です。
--
Sheets("残").Columns("F:F").Delete Shift:=xlToLeft
--
Application.ScreenUpdating = falseは画面更新が完全に止まってしまいフリーズと見分けがつかなくなるので、最後の最後まではなるべく使わない方がいいと思います。確かにこれはよく効きますが。
あと、長時間かかる処理は適宜DoEventsを入れておくといいです。これは何らかのバグで無限ループに陥った時などにExcelを強制終了する必要がなくなるため。
No.2
- 回答日時:
どんなことが遅い要因か、意識したらいいでしょう。
セルを選択するのがあちこち行く。
シートを跨ぐ。
行削除等で表示内容が変わる。
等が遅くさせると思えば良いです。
マウスカーソルが転々と動けば動くほど遅い。
最近は性能のおかげで早いのでしょうが、ロジックや記載変えるだけで無駄が無くなりさらに早くなることもあります。
行削除はしないで、削除する行にマーキング。マーキングした行を並び替えかフィルタでまとめた後で複数行をクリア。これだけでも早くなりますし、NO1さんの対処も早くする手段ですから両方やる。
>削除する行にマーキング
この時にVLOOKUPを使いました。
マーキングしている処理の時に
時間がかかってあまり速くはなりませんでした。
どうもありがとうございました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) まとめシートから集計シートへA列のコードが一致したら1行コピーするマクロをネット上で見つけました。こ 1 2022/08/30 14:11
- Visual Basic(VBA) 複数csvを横に追加していくマクロについて 2 2023/04/25 09:19
- Visual Basic(VBA) コード名シートA列と集計シートA列のコードが一致したら、コード名シートA5からk12の範囲をコピーし 1 2022/08/29 23:46
- Visual Basic(VBA) エクセルVBAで教えて頂きたいのですが? 2 2022/12/31 20:28
- Excel(エクセル) マクロで最終行から上に検索を逆にしたい 1 2022/05/17 18:27
- Visual Basic(VBA) フォルダの場所を可変にしたいです(マクロ) 4 2023/05/11 10:00
- Visual Basic(VBA) VBAで、シート間の転記するコードをFOR~NEXTで教えてください。 9 2023/04/30 20:04
- Excel(エクセル) VBAについて 3 2022/06/19 18:19
- Visual Basic(VBA) 【VBA】特定のワードが入っている行全体を塗りつぶしたい 4 2022/04/20 15:22
- Visual Basic(VBA) VBA Userformで一部別シートに転記がしたいのですが 2 2023/05/24 13:08
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
エクセルで 自動的に◯や数字を...
-
エクセルでファイルの最終更新...
-
シフト表をエクセルで作るとき...
-
Excel 2019 [オプション]の[リボンのユ...
-
Excelに詳しい方! B列が「日...
-
Excelファイルが開けません
-
excel2013 MonthDays 関数が使...
-
スプレッドシートの関数につい...
-
【マクロ】2回実行したら、エ...
-
特定の文字列を含む、住所を抽...
-
EXCELの散布図で日付が1900年に...
-
エクセルのツールバーから数値...
-
Excelで表を作ったところに文字...
-
祝日と土曜、日曜の合計をカウ...
-
Excelについて
-
【マクロ】名前を保存する際に...
-
Excel分数の表示について
-
エクセルでCtrl+Tでテーブルの...
-
マイクロソフトのPADを使ってい...
-
【EXCEL】画像の黄色部分の抽出...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
半角カタカナをヘボン式ローマ...
-
(マクロ)vlookupの元データを同...
-
エクセルで上位バイトのセルと...
-
exselの質問です
-
Excel 大小比較演算子による「...
-
Excel VBについての質問です。
-
エクセルの問題です。絶対値の...
-
非表示列の再表示に失敗
-
職場の人から聞かれており、こ...
-
Excel関数-文字列で自動作成さ...
-
Excelデータをコピペして、ペー...
-
ユーザー定義関数をアドイン登...
-
【マクロ】for next構文について
-
エクセルの日付を編集する
-
【マクロ】VLOOKUPにて参照元に...
-
exselで最小数で並び替える関数
-
libre 表計算ソフトの計算がう...
-
エクセルで表
-
エクセルの表で1年間の曜日を...
-
西暦和暦
おすすめ情報