VBAマクロによる条件削除処理

このQ&Aのポイント
  • Excel VBAを使用して、指定条件に基づいて行を削除するマクロを作成する方法を教えてください。
  • 削除条件は、列Fの値が0の場合、および列Eの先頭が7B以外の場合です。
  • 削除処理は、指定条件に基づいて行を削除することで行います。
回答を見る
  • ベストアンサー

セルの値が指定条件なら対象行を削除するマクロ

ボタンクリックでプロシージャーが起動します。 そのマクロの中で以下の2つの処理を追加させたいです。 マクロの記述を教えてください。 A~F列までデータが有ります。 1行目は項目で2行目からデータがあります。 行数は都度相違しますが10,000行はあります。 (1) F列の値は標準で、ここが0の場合その行全体を削除します。 入っている値の例 -1234→削除しない 345→削除しない 12346→削除しない 0→削除する セルの空白はぜったいありません。 (2)-1 E列の値は標準で英数字3ケタです。ところどころ空白があります。 E列の値が先頭7B以外は行全体を削除します。 7B1→削除しない 7B2→削除しない 7BW→削除しない 77C→削除 47B→削除 空白→削除 F列を優先なのでE列が7Bで始まっている行でも F列が0なら削除となります。 (2)-2 (2)-1と同じでE列の値は標準で英数字3ケタです。 ところどころ空白があります。 E列の値が 先頭 7Bと72以外 又は CとDと7B以外は 行全体を削除します。 のように(2)-1のように1条件ではなく2~複数になる。 それが1文字の場合、2文字の場合、3文字全部の場合がある F列を優先なのは(2)-1と同じです。 条件例 ・Cと73以外 ・CとFと72以外 ・Gと7Vと8D以外 ・Gと88と8D5以外 以下の記述ですが、(1)は思ったとうり動作しましたが ●の部分が分かりません。 現在の記述では7BB以外は全部行削除されてしまいます。 (2)-1と(2)-2の対応のために 記述内で(2)-1と(2)-2を 書き換える事が出来るような記述にしたいです。 あと凄く処理が遅いので高速化もしたいです。 よろしくお願いします。 Sub test01() 'A~K列のデータにて 'E,F,H,I,K列を列削除する Columns("E:F").Select Selection.Delete Shift:=xlToLeft Columns("F:G").Select Selection.Delete Shift:=xlToLeft Columns("G:G").Select Selection.Delete Shift:=xlToLeft 'データがA~F列になりました。 With ActiveSheet 'アクティブなシートについて x = .UsedRange.Cells(.UsedRange.Count).Row 'xに最終行を取得 For i = x To 2 Step -1 '最終行から2行目まで下から順に 'F列が"0"だったらその行を削除 If .Cells(i, 6) = 0 Then .Rows(i).Delete Next '繰り返し End With With ActiveSheet 'アクティブなシートについて x = .UsedRange.Cells(.UsedRange.Count).Row 'xに最終行を取得 For i = x To 2 Step -1 '最終行から2行目まで下から順に 'E列の値の先頭文字が"7B"でなかったら削除(空白の場合も削除) ●If .Cells(i, 5) <> "7BB" Then .Rows(i).Delete Next '繰り返し End With End Sub

  • gx9wx
  • お礼率95% (440/460)

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

  • ベストアンサー
  • merlionXX
  • ベストアンサー率48% (1930/4007)
回答No.7

おはよう。 二日酔いのmerlionXXです。 見直してみました。 わたしのケアレスミスでした。 下から5行目の .Range("A2:F" & j).Value = myW で変数を間違えてます。 Layyさんがご指摘のとおり、j ではなく n にしなければいけません。 .Range("A2:F" & n).Value = myW に訂正します。

gx9wx
質問者

お礼

ありがとうございます。 .Range("A2:F" & n).Value = myW で思ったとうり動いて今日はたくさん処理できて 助かりました。 もう22:24。 あとひとふんばりです。

gx9wx
質問者

補足

あけましておめでとうございます。 今年もよろしくお願いします。 今日は仕事です。10日も仕事です。(T_T) test02は If .Cells(i, 6) = 0 Then .Rows(i).Delete 'F列が"0"だったらその行を削除 Else 'F列が"0"でなかったら If Left(.Cells(i, 5), 2) <> "7B" Then 'E列の値の先頭文字が"7B"でなかったら .Rows(i).Delete '削除(空白の場合も削除) test03は If .Cells(i, 6) = 0 Then .Rows(i).Delete 'F列が"0"だったらその行を削除 Else 'F列が"0"でなかったら 'E列の値先頭がKとE、先頭2文字が72以外は行削除する If Left(.Cells(i, 5), 1) <> "K" And Left(.Cells(i, 5), 1) <> "E" And Left(.Cells(i, 5), 2) <> 72 Then 'E列判定(下記参照) .Rows(i).Delete '削除(空白の場合も削除) と条件の指定の部分は双方<>です。 test04はtest03の高速型で 'F列が"0"だったらその行を削除 If myV(i, 6) <> 0 Then '●E列の値先頭がKとE、先頭2文字が72以外は行削除する If Left(myV(i, 5), 1) = "K" Or Left(myV(i, 5), 1) = "E" Or Left(myV(i, 5), 2) = 72 Then と条件の指定の部分は=です。 02と03は <>ですが 04は = です。 02の高速型を作成する場合は 'F列が"0"だったらその行を削除 If myV(i, 6) <> 0 Then '●E列の値の先頭文字が"7B"でなかったら If Left(myV(i, 5), 1) = "7B" Or Left(myV(i, 5), 2) それとも If Left(myV(i, 5), 1) = 7B Then でいいのでしょうか? あと高速型test04の方で 02,03に有る 「E列が空白の場合も行削除」は どの部分になるのでしょうか? (コメントを入れたいのですがよく分かりません。) 申し訳ありませんよろしくお願いします。

その他の回答 (9)

  • merlionXX
  • ベストアンサー率48% (1930/4007)
回答No.10

今日の補足みました。 これ、わたしが教えたの? > その状態のまま > Sub エクセル6ファイル取込()を再度走らせます。 この段階で、Sheets("現在在庫")のセルがクリアされますよ。 > MsgBox "抽出した6ファイル用意されていますか?" これでは「はい」しか選択できませんね? だから、自動的に Sub エクセル6ファイル選択 がCallされますね。 ところが、Static を使ってるから、変数myCntはこのプロシージャーが終了しても保持されたままです。(6になってるはず) したがって、 If myCnt >= 6 Then で MsgBox "6個のBOOKの転記が終了してます。" となり Exit Sub でマクロが終了します。 エクセル6ファイル取込()を再度走らせるとは、そのBOOKを終了せずに、同じようなことをまた続けたいってこと? それなら Sub エクセル6ファイル選択02() 'エクセルファイルを選択します。6回行います。 '1番目のプロシージャーでCallされます。2回目に走ります。 Dim ans As Boolean Static myCnt As Integer If myCnt >= 6 Then MsgBox "6個のBOOKの転記が終了してます。" myCnt = 0 '*ここでカウントを初期化 Exit Sub End If ans = Application.Dialogs(xlDialogOpen).Show If ans Then myCnt = myCnt + 1 Call 在庫データ6ファイル転記(ActiveWorkbook, myCnt) End If End Sub としたらどうなるかな? 試してないから責任もてませんが。(こんなことやったことないよ)

gx9wx
質問者

お礼

教えていただいたとうりにしてみました。 やはり 自動的に Sub エクセル6ファイル選択 がCallされ MsgBox "6個のBOOKの転記が終了してます。" となり Exit Sub でマクロが終了 でマクロ終了後に再度同じマクロでの処理はできませんでした。 このスレと違う質問ですのでもう閉じます。 もともと別スレで教えていただいた時に 最初から継続したいという要求はしていませんし 1回閉じて、再立ち上げすれば機能上問題は ないです。 理屈的に継続処理が出来ないのがわかったので いいです。 (私の改造ミスならして指摘していただきたかった。) お手数をかけてすいませんでした。 どうもありがとうございました。

gx9wx
質問者

補足

はいすいません。 http://okwave.jp/qa/q6327202.html QNo.6327202 2010-11-18 09:44:57 ANo.1 2010-11-18 11:37:32 で教えていただきました。 でそれを Sub GetBook() ↓ Sub エクセル6ファイル選択() Sub GetData(ByRef wb As Object, ByVal myCnt As Integer) ↓ Sub 在庫データ6ファイル転記(ByRef wb As Object, ByVal myCnt As Integer) にして5回を6回に改造しました。 また冒頭に 別スレで教えていただいた物を改造した Sub エクセル6ファイル取込() としてくっつけました。 最初は改造が間違っていると思いましたが 最初に教えていただいた↓の記述だけで行っても、 同じく2回目は取り込みが出来ませんでしたので 質問してみました。m(__)m 実際はそういう運用はしないのですが 暮れにたまたまそういう事をした時に疑問に 思ったままでしたので。m(__)m 改造前↓ Sub GetBook() Dim ans As Boolean Static myCnt As Integer If myCnt >= 5 Then MsgBox "5個のBOOKの転記が終了してます。" Exit Sub End If ans = Application.Dialogs(xlDialogOpen).Show If ans Then myCnt = myCnt + 1 Call GetData(ActiveWorkbook, myCnt) End If End Sub ---- Sub GetData(ByRef wb As Object, ByVal myCnt As Integer) Dim x As Long MsgBox wb.Name & "からデータを取得します。", vbInformation, myCnt & "回目ですね。" With wb.ActiveSheet x = .Cells(Rows.Count, "A").End(xlUp).Row If myCnt = 1 Then .Rows("1:" & x).Copy ThisWorkbook.Sheets("Sheet1").Range("A1") Else .Rows("2:" & x).Copy ThisWorkbook.Sheets("Sheet1").Cells(Rows.Count, "A").End(xlUp).Offset(1) End If End With wb.Close (False) MsgBox myCnt & "回目の転記が完了" If myCnt < 5 Then Call GetBook Else MsgBox "5個のBOOKの転記が終了しました。" Call 編集 End If End Sub

  • merlionXX
  • ベストアンサー率48% (1930/4007)
回答No.9

まだ松の内だから、明けましておめでとうございます。 1月は5日から仕事です。今日はお休みですが。 ANo7の補足を見ました。 > 02と03は <>ですが > 04は = です。 はい、その通り。 理由は分かりますね? 前にも説明したように高速化させるため、ワークシート上で不要行を削除するのはやめて、残す行のデータだけを2次元配列に取り込むようにしたからです。 trst02を同じように高速化させるなら、 「E列の値の先頭文字が"7B"でなかったら、E列が空白の場合も含め、その行を削除する」ということは、逆にE列の先頭2文字が"7B"だけを2次元配列に取り込めばいいってことだよね。 つまり、 If Left(myV(i, 5), 2) = “7B” Then で、OKです。 > If Left(myV(i, 5), 1) = 7B Then  ではだめです。 よく見比べてください。 > あと高速型test04の方で02,03に有る「E列が空白の場合も行削除」はどの部分になるのでしょうか? もう説明の必要もないと思いますが、データを残す条件だけを指定すれば、わざわざ「空白の場合も行削除」を指示しなくても削除されるってわけです。 以上、今年最初のこども電話相談室でした。(笑)

gx9wx
質問者

お礼

お礼が遅れました。 いつもありがとうございます。 >あと高速型test04の方で >02,03に有る 「E列が空白の場合も行削除」は >どの部分になるのでしょうか? >(コメントを入れたいのですがよく分かりません。) 要求事項を処理している部分に 無理にコメントをいれようとして 馬鹿言ってました。m(__)m すいません。 教えていただいたとうりでした。

gx9wx
質問者

補足

すいません。閉じる前に。もう1回。 merlionXXさんにしか聞けない事なのでm(__)m 最初の質問にて >ボタンクリックでプロシージャーが起動します。 >そのマクロの中で以下の2つの処理を追加 このマクロというのはmerlionXXさんに教えていただいた物を 改造したものです。 Sub エクセル6ファイル取込() 'これが一番最初に走ります。 Sheets("現在在庫").Select Cells.Select Selection.Delete Shift:=xlUp Range("A1").Select MsgBox "抽出した6ファイル用意されていますか?" Call エクセル6ファイル選択 End Sub ------- Sub エクセル6ファイル選択() 'エクセルファイルを選択します。6回行います。 '1番目のプロシージャーでCallされます。2回目に走ります。 Dim ans As Boolean Static myCnt As Integer If myCnt >= 6 Then MsgBox "6個のBOOKの転記が終了してます。" Exit Sub End If ans = Application.Dialogs(xlDialogOpen).Show If ans Then myCnt = myCnt + 1 Call 在庫データ6ファイル転記(ActiveWorkbook, myCnt) End If End Sub ---- Sub 在庫データ6ファイル転記(ByRef wb As Object, ByVal myCnt As Integer) '選択したファイルをシート「現在在庫」に転記します。 '1回目は1行目から、2~6回目は2行目からです。 '2番目のプロシージャーでCallされます。3回目に走ります。 Dim x As Long MsgBox wb.Name & "からデータを取得します。", vbInformation, myCnt & "回目ですね。" With wb.ActiveSheet x = .Cells(Rows.Count, "A").End(xlUp).Row If myCnt = 1 Then .Rows("1:" & x).Copy ThisWorkbook.Sheets("現在在庫").Range("A1") Else .Rows("2:" & x).Copy ThisWorkbook.Sheets("現在在庫").Cells(Rows.Count, "A").End(xlUp).Offset(1) End If End With wb.Close (False) MsgBox myCnt & "回目の転記が完了" If myCnt < 6 Then '次のファイルを選択する為2番目に走ったプロシージャーをCallします。 Call エクセル6ファイル選択 Else MsgBox "6個のBOOKの転記が終了しました。" Call ●このスレで教えていただいたマクロ(test04) End If End Sub これでシート「現在在庫」に取り込んだデータが このスレで教えていただいたマクロ(test04)で編集された状態で 完了しています。 その状態のまま Sub エクセル6ファイル取込()を再度走らせます。 ↓ MsgBox "抽出した6ファイル用意されていますか?" ↓ 「はい」 ↓ MsgBox "6個のBOOKの転記が終了してます。" となり先ほど編集されたシート「現在在庫」のデータが 全て削除されて終わってしまい取込ファイル選択画面になりません。 一度このエクセルを閉じて再度開いて Sub エクセル6ファイル取込()を起動されば大丈夫です。 実用上問題ないのですがこの原因が分かりません。 通常マクロの処理後、また同じマクロを起動できます。 (処理内容によってはそれをやるとデータは目茶苦茶になりますが) 今回は処理後のシートを別のBOOKにコピペして、 引き続き別データを同じように処理しようとしてマクロを起動したら 出来なかったので疑問が。 暮れからこの件が頭に合ってそのうち次の依頼が大量に来て。 説明が難しいので意味が通じなかったらスルーしてください。 いろいろありがとうございました。

  • layy
  • ベストアンサー率23% (292/1222)
回答No.8

Application.ScreenUpdating = False Application.ScreenUpdating = TRUE この機能は覚えておくこと。 表示→カーソル移動→判定→物理的に消す→(消えた状態を)表示→カーソル移動 これを繰り返すだけで結構時間かかります。 (チカチカします。) 何でもかんでもこれ使うかというわけでなくて、 処理中に何が起きているか見なくてもいいレベルになったらこれを記載することでしょう。 あと、 右の列のどっかに「削除対象行は=消の文字」としてあげたら、 あとはDELETEのコマンド発行しなくても、 並べ替えなりフィルタで不要行削除された状態と同じものは実現できるので、 実際にはそちらのが処理がもっと早かったかもしれません。 ゆっくり休んでください。

gx9wx
質問者

お礼

いろいろとありがとうございました。 年末は助かりました。

  • layy
  • ベストアンサー率23% (292/1222)
回答No.6

.Range("A2:F" & j).Value = myW のjの値が6になっているからでは?。 "A2:F6"分しか貼り付けていない。 貼り付け用に残っているのはn行もあるから、 .Range("A2:F" & n).Value = myW かな?。 あとは本人の確認待ちで。

gx9wx
質問者

お礼

ありがとうございます。 ご指摘のしゅうせいで思ったとおり 動きました。 おかげで助かりました。 まだ、仕事終われませんが.....

  • merlionXX
  • ベストアンサー率48% (1930/4007)
回答No.5

> 03は300行残りました。 > 04は4行しか残りません。 それは困った! これからXmasEveのパーティなんです。もういかなくっちゃ。ごめん。 とりあえずTEST03でしのいでいてください。 あと気づいたことがとがあったら教えてください。

gx9wx
質問者

お礼

お礼が遅れました。 ありがとうございました。

gx9wx
質問者

補足

謝らないでください。 お願いしているのは私ですので。 全国的にクリスマスイヴですから。 明日も仕事なので(26日~1月5日まで11連休) 今日もがんばります。 楽しいパーティを。 すいません。4行ではなく6行でした。 残るべき対象データとなる300行の上から6行目だけが 残るようです。 .Range("A2:F" & x).ClearContents これでデーターが全部消えて .Range("A2:F" & j).Value = myW これで条件に該当して配列に取り込まれた のが貼り付くのですよね。 という事は配列に取り込む時に 6行と制限しているのか 配列には300行分取り込んだけど 貼り付ける時に6行までと なっているのかな? そもそももっと違うのかな?

  • merlionXX
  • ベストアンサー率48% (1930/4007)
回答No.4

> はい。そのとうりです。 > 私のPCを見られているみたいです。 そうじゃなくて、普通は英数のデータってたいてい半角でしょ? かわいい、かわいいgx9wxちゃんは普通じゃないと言われるとそれまでなんだけど、コードを書くに当たって、半角か全角か、あるいは混在するのか、それによって書き方は変わるんじゃないかぐらいは想像できるよね? だから質問の時には手を抜かず、ちゃんと書いてほしいのです。 > ですが、やはり2~3分は待たないといけません。 以前のはどれくらいかかってました? 無駄に二回ループしてたからもっとかかったんじゃないかな。 でもこんな二回ループ、2007年にわたしが書いてたんだ・・・・。 では高速化した(つもりの)コードです。 高速化の秘訣は、 一番時間のかかる大量の行削除はしない。 セルとデータのやりとりは極力減らす。 だから対象範囲を一旦、二次元配列に取り込んじゃう。 データ処理は配列内で完結させる。(行が削除されたような形のデータにしてしまう。) シートをクリアして一度に貼り付ける。 な~んて知ったかぶりして、ぜんぜん早くなってなかったらお笑いですね。 以下のコードでどれくらいかかるか教えてください。 複数条件の判定方法が逆になってますから注意してください。 あそうだ、gx9wxちゃん、Merry Xmas ! Sub test04() 'Test03の高速化   Dim myV, myW   Dim x As Long, i As Long, n As Long, j As Long   Application.ScreenUpdating = False   With ActiveSheet     .Range("E:F,H:I,K:K").Delete Shift:=xlToLeft     x = .UsedRange.Cells(.UsedRange.Count).Row     myV = .Range("A2:F" & x).Value     ReDim myW(1 To x - 1, 1 To 6)     For i = 1 To x - 1       If myV(i, 6) <> 0 Then         If Left(myV(i, 5), 1) = "C" Or Left(myV(i, 5), 1) = "F" Or Left(myV(i, 5), 2) = 72 Then           n = n + 1           For j = 1 To 6             myW(n, j) = myV(i, j)           Next j         End If       End If     Next i     Application.Calculation = xlCalculationManual     .Range("A2:F" & x).ClearContents     .Range("A2:F" & j).Value = myW   End With   Application.Calculation = xlCalculationAutomatic   Application.ScreenUpdating = True End Sub

gx9wx
質問者

お礼

ありがとうございます。 1秒かかりませんでした。 ですが 同じデータで行った場合 10,000行のうち300行が残るはずで 03は300行残りました。 04は4行しか残りません。 今見ていますが????です。

gx9wx
質問者

補足

>以前のはどれくらいかかってました? >無駄に二回ループしてたからもっとかかったんじゃないかな。 それがあまり変わりません。 私の記述では7BB以外は全部削除ですから その辺も関係しているかも? >でもこんな二回ループ、2007年にわたしが書いてたんだ・・・・。 すいません。2回ループにしたのは私です。 merlionXXさんが他に方に回答なさったのは (1)の方だけでそれを今回用に書き換えて、 さらに同じ処理だから、 もう1回同じ記述を貼り付けたのです。 2回だと遅くなるのはわかっていましたが VLOOKUPの時に、 式を貼付し出た値を値貼付する方法より 自作の2回ループの方が速かった事もあり 場合によってはLoopでも速かった時もあったので 挑戦したのですが、駄目でした。 (VLOOKUPはその後 例のdictionaryオブジェクトで秒速以下になりましたが) >だから質問の時には手を抜かず、 >ちゃんと書いてほしいのです。 手は抜いてないのですが、そこまで気がつかないのです。 すいません。別スレッドでは半角と書いてました。 今回はなぜ抜けたのかな? はい。Merry Xmas ! イブは会社で過ごし、クリスマスを会社で向かえたらどうしよう.....

  • layy
  • ベストアンサー率23% (292/1222)
回答No.3

単純に考えると、 10000行あるデータを条件1で検証し、条件2でまた検証するとなると20000行のデータを操作していることになっているので遅い。2条件から4条件に増やすと倍遅くなるでしょう。 1行分操作するときに、条件1に合えばL列に〇、合わなければL列に×、条件2に合えばM列に〇、合わなければM列に×、こんな感じでL列が〇でM列が〇なら削除だ、ということで10000行まで行えば操作した行は少なくなり、処理早くなると考えられます。

gx9wx
質問者

お礼

ありがとうございます。 条件1は常に同じ条件です。 条件2は今回はE列の3文字にて 先頭から7B以外だったらその行は削除です。 ただ条件2に関してはユーザー要求によって相違します。 例えば 今回は ・先頭から2文字が7Bだけ残してあとは削除 次回は ・先頭がC と 先頭が D と先頭から2文字が76  を残してあとは削除 その次は ・先頭がWと先頭から2文字が8Sと7G6  を残してあとは削除 という感じです。 よって条件2の所は要求に応じて 簡単に書き換えが可能な記述 にしたいです。 アドバイスしていただいた内容を 完全に理解できないのですが こんな感じでいいのでしょうか? L,M列に判定結果を転記し その値から行削除を命令する?。 (イメージなのでこのままでは思ったとうりに処理は  されないのは承知してます。  これ以上は作れなかったです。(泣))   Sub 行削除() 行 = 2 Do If Cells(行, 1).Value = "" Then Exit Do If Cells(行, 6).Value = 0 Then Cells(行, 12).Value = "消" If Cells(行, 5).Value <> "7BB" Then Cells(行, 13).Value = "消" End If End If 行 = 行 + 1 Loop With ActiveSheet x = .UsedRange.Cells(.UsedRange.Count).Row For i = x To 2 Step -1 If .Cells(i, 12) = "消" Then .Rows(i).Delete Next End With End Sub

  • merlionXX
  • ベストアンサー率48% (1930/4007)
回答No.2

> A~F列までデータが有ります。 とお書きですが、提示されたコードを見ると、'E,F,H,I,K列を列削除した結果、A~F列のデータになったようです。 そういう理解でいいのですね? 普通はそう言葉で書きますよ。 また、アルファベットや数字を全角でお書きですが、実際のデータは半角なんじゃないですか? その前提で書かれたコードを修正すると以下のようになります。 Sub test02() '(2)-1です。   Application.ScreenUpdating = False   With ActiveSheet 'アクティブなシートについて     .Range("E:F,H:I,K:K").Delete Shift:=xlToLeft 'E,F,H,I,K列を列削除する     x = .UsedRange.Cells(.UsedRange.Count).Row 'xに最終行を取得     For i = x To 2 Step -1 '最終行から2行目まで下から順に       If .Cells(i, 6) = 0 Then         .Rows(i).Delete 'F列が"0"だったらその行を削除       Else 'F列が"0"でなかったら         If Left(.Cells(i, 5), 2) <> "7B" Then 'E列の値の先頭文字が"7B"でなかったら           .Rows(i).Delete '削除(空白の場合も削除)         End If       End If     Next '繰り返し   End With   Application.ScreenUpdating = True End Sub Sub test03() '(2)-2です。   Application.ScreenUpdating = False   With ActiveSheet 'アクティブなシートについて     .Range("E:F,H:I,K:K").Delete Shift:=xlToLeft 'E,F,H,I,K列を列削除する     x = .UsedRange.Cells(.UsedRange.Count).Row 'xに最終行を取得     For i = x To 2 Step -1 '最終行から2行目まで下から順に       If .Cells(i, 6) = 0 Then         .Rows(i).Delete 'F列が"0"だったらその行を削除       Else 'F列が"0"でなかったら         If Left(.Cells(i, 5), 1) <> "C" And Left(.Cells(i, 5), 1) <> "F" And Left(.Cells(i, 5), 2) <> 72 Then 'E列判定(下記参照)           .Rows(i).Delete '削除(空白の場合も削除)         End If       End If     Next '繰り返し   End With   Application.ScreenUpdating = True End Sub 'E列判定の条件例 '・Cと73以外 左の先頭1文字がCでなく、かつ先頭2文字が73でないという意味ですか? ならば If Left(.Cells(i, 5), 1) <> "C" And Left(.Cells(i, 5), 2) <> 73 Then '・CとFと72以外 If Left(.Cells(i, 5), 1) <> "C" And Left(.Cells(i, 5), 1) <> "F" And Left(.Cells(i, 5), 2) <> 72 Then あとはご自分でもわかりますね。 データ量が多いから時間はかかるでしょうね。 配列に取り込めは高速化出来ますが、まずは上記の理解でいいかどうかを確認します。

gx9wx
質問者

お礼

こんにちは。 merlionXXさんに過去に教えていただいた 数々のマクロを書き換えて合体して 最後までやり遂げようと思いましたが ギブアップです。 今回提示しました記述はmerlionXXさんが 2007年ぐらいに他の方に回答した物を 持ち出して書き換えたのですが、 これ以上は無理でした。 >> A~F列までデータが有ります。 >とお書きですが、提示されたコードを見ると、 >'E,F,H,I,K列を列削除した結果、A~F列のデータになったようです。 >そういう理解でいいのですね? >普通はそう言葉で書きますよ。 はい。そのとうりです。 やはり私は普通ではないのかな。 >また、アルファベットや数字を全角でお書きですが、 >実際のデータは半角なんじゃないですか? はい。そのとうりです。 私のPCを見られているみたいです。 >あとはご自分でもわかりますね。 はっきり「はい」といえないが辛いです。(泣) 一応、例であげた以外のパターン用に 教えていただいた物を書き換えて行いましたら思ったとおりに 結果が変化しましたので条件変更時の変更部分については 理解できていると思います。 >データ量が多いから時間はかかるでしょうね。 はい。02も03も思ったように動きました。 また03は前述のとうり書き換えても思ったように 動きました。 ですが、やはり2~3分は待たないといけません。 どうもありがとうございました。

gx9wx
質問者

補足

ちょっと不安です。 >'・CとFと72以外 >If Left(.Cells(i, 5), 1) <> "C" And Left(.Cells(i, 5), 1) <> "F" And Left(.Cells(i, 5), 2) <> 72 Then ・CとFと72と8D5以外 If Left(.Cells(i, 5), 1) <> "C" And Left(.Cells(i, 5), 1) <> "F" And Left(.Cells(i, 5), 2) <> 72 Then And Left(.Cells(i, 5), 3) <> 8D5 Then でいいのでしょうか? E列は3ケタか空白なので 8D5という条件はピンポイントで指定なので = "8D5" Then の方がいいのでしょうか? その場合はLeftはいれず If Left(.Cells(i, 5), 1) <> "C" And Left(.Cells(i, 5), 1) <> "F" And Left(.Cells(i, 5), 2) <> 72 Then And (.Cells(i, 5) = "8D5" Then でいいのでしょうか?

  • layy
  • ベストアンサー率23% (292/1222)
回答No.1

最初に列削除してますが 条件1の判定結果をL列に 条件2-1の判定結果をM列に 条件2-2の判定結果をN列に 最終的に削除するかの判定結果をO列に まずはここまでやって判定の妥当性を確認します。 すべての行に判定でき、問題なかったらO列をみて削除 随時削除、再描画していることが遅くしていると思います。 処理経過を表示させないコマンドあり、参考。 先頭1文字、2文字の文字列判定はLEFT関数使います。

gx9wx
質問者

お礼

ありがとうございました。 >まずはここまでやって判定の妥当性を確認 難しいです。すいません。 >処理経過を表示させないコマンドあり、参考。 よく皆さんにアドバイスされてます。 過去の例だとそれでは早くなりませんでした。 今回ははやくなるのでしょうか。 >先頭1文字、2文字の文字列判定はLEFT関数使います。 その関数での条件付けがよく分かりません。 お手数をおかけいたしました。

関連するQ&A

  • 条件にて行削除をするをマクロで高速化したい

    シート(最初)の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

  • セルの値が同じ行を条件に従って行削除するマクロ

    A~E列までデータがあり 行数は約30,000行あります。 A列は半角英数字と-で桁数は11桁又は14桁です。 数字のみもあれば数字と英字の組み合わせもあります。 (英字はどこの桁にあるか何個あるかは不規則です) 例 ABCD123456789X 124345678901234 55555-55555 ABC12345DEF678 E列には半角の 1 か 2 しかありません。 A列が同じ値の行を検出して重複している行は1行だけ残して 後は行削除をしたいです。 行削除はE列の値によって判定したいです。 重複行は1つの値に対して何行あるか不明です。 30,000行のうち、重複行を削除すると10,000行くらいになる予定です。 (1)重複行にてE列の値が1だけの場合    どれでもいいので1行残して残りは行削除 (2)重複行にてE列の値が2だけの場合   どれでもいいので1行残して残りは行削除 (3)重複行にてE列の値が1も2もある場合   E列の値が2の行をどれでもいいので1行残して残りは削除 例 (1) 1234567890XXXX-1 1234567890XXXX-1 1234567890XXXX-1 ↓ 1234567890XXXX-1 (2) 123ABCDE901234-2 123ABCDE901234-2 ↓ 123ABCDE901234-2 (3) 12345678901234-1 12345678901234-2 ↓ 12345678901234-2 ABC45678901234-1 ABC45678901234-2 ABC45678901234-1 ABC45678901234-2 ↓ ABC45678901234-2 手作業では5時間かかりましたがミスだらけです。 まだ数ファイル残っており手作業では厳しいのでマクロを 作成したいのですが、どう記述していのかまったく検討が付きません。 どうかよろしくお願いします。

  • 空白のセルを行削除する。EXCELマクロなのですが・・

    VBA初心者です。 データーをHPから、単純にコピーしてきて、 EXCELに貼り付けています。 フィルターをかけても、画像かなにかがセルに張り付いているのか、 空白行をすべて削除できません。 いろいろ試して(HPから、空白セルの行削除について書かれてあるマクロを貼り付けて)動いたのが、このVBAです。 しかし、遅いので、早いVBAに簡略できればいいのですが。。 大体、1000行ぐらいの文字を貼り付けて、3/1ぐらいが空白行です。A行のセルの空白のみを、削除したいのですが。  まったくの素人なので、わかりません。 どうかよろしくお願いいたします。 Sub 空白の削除() x% = Worksheets("sheet1").Range("A65536").End(xlUp).Row For i = x% To 1 Step -1 If Worksheets("sheet1").Cells(i, 1).Value = "" Then Worksheets("sheet1").Rows(i).Delete Next End Sub

  • 重複行を完全削除するエクセルのマクロ

    Sub sakujyo() Dim i, ii As Long For i = 1 To Range("a65336").End(xlUp).Row For ii = Range("a65336").End(xlUp).Row To i + 1 Step -1 If Cells(i, 2).Value = Cells(ii, 2).Value _ And Cells(i, 4).Value = Cells(ii, 4).Value _ And Cells(i, 5).Value = Cells(ii, 5).Value Then Dim iii As Byte iii = 1 Rows(ii).Delete Shift:=xlUp End If Next ii If iii = 1 Then Rows(i).Delete Shift:=xlUp iii = 0 Next i End Sub データーが下の表のように入っております。     A    B    C    E    F 1  1/26  a1234  fdsa  5000  C1 2  1/27  a4567  sdfa  4000  T2 3  1/28  a1234  dfsa  5000  C1 4  1/30  b4567  asdf  6600  A2 5  2/10  b4567  fsda  6600  A2 6  2/10  a1234  afds  5000  C1 B列、E列、F列が完全一致(重複1行目と3行目と6行目・4行目と5行目)で削除し結果的に2行目だけ残る方法がしたいのですが、このマクロですと少ないデータですとうまく動くのですが、『大量のデータを一気に削除出来ない』、『同じ重複が3つ以上のデータが多数ある場合データが削除されずに残ってしまう』エラーが出てしまいます。どうかお教えください。

  • エクセル 空の行を削除するマクロについて

    エクセルで、特定の列(ここではFの列としてください)が空欄だった場合に、その行ごと削除するマクロを記述したのですが、不完全で困っています。 不完全な部分としては、 ・Fが空であるはずなのに、行が削除されない ・Fが空でもその隣のセル(E)に文字列などが入っていた場合、削除されない 以下が問題のマクロです Dim i As Integer For i = 1 To 300 If Sheets("Sheet1").Cells(i, "F") = "" Then Sheets("Sheet1").Rows(i).Select Selection.Delete Shift:=xlUp End If Next i End Sub 例) A B C D E F 1 あ い う え お か 2 き く け こ さ し 3 す せ そ た ち 4 つ て と な に ぬ 3列目を削除したいです。 問題箇所がお分かりの方、教えていただけませんでしょうか。 宜しくお願いいたします。

  • エクセルマクロ行削除

    エクセル2013です。 以下の行削除マクロを作りました。 取得した 最終行が20行目として 最終列がZ列として セル Z20 の値が 1以上なら問題なく動作するのですが セル Z20 の値が 0 だとループして終了しません。 どこを修正しても、思うように動作しません。 どこを修正すれば、いいのでしょうか? よろしくお願いします。 Sub 行削除() Dim 最終行 Dim 最終列 Dim 対象行 最終列 = Cells(8, Columns.Count).End(xlToLeft).Column '8行目の最終列を取得 最終行 = Cells(Rows.Count, 1).End(xlUp).Row 'A列の最終行を取得 Application.ScreenUpdating = False '画面切替停止 For 対象行 = 10 To 最終行 If Cells(対象行, 最終列) = 0 Then Rows(対象行).Delete 最終行 = 最終行 - 1 '削除により最終行が1行減ったので最終行の値を1行減らす 対象行 = 対象行 - 1 '削除により対象行が1行繰り上がったので対象行の値を1行減らす Else End If Next 対象行 Application.ScreenUpdating = True '画面切替停止解除 End Sub

  • excel 空白のセルがある行を削除するマクロ

    A列に、みかん りんご バナナ 肉 などと入力されており、 B1に=if(countif(A1,"*みかん*")+countif(A1,"*りんご*")+countif(A1,"*バナナ*"),"fruit","") という感じで、fruit か 空白 を返す関数が入力されており、オートフィルでB列に数式をコピーするマクロを実行します。 その次に、B列で空白のセルがある場合、その行を削除するというマクロを下記のように入力しましたが、削除されません。 Dim lastRow As Long Dim i As Long lastRow =Range("B"&Rows.count).End(xlup).Row For i =lastRow To 5 Step -1 If Cells(i,"B").Value="" Then Rows(i).Delete XlShiftUp End If Next i 間違いをどなたか教えてください。 ちなみに、B列が関数では無く、ただの文字列の場合("fruit")ではマクロが実行できました。 関数の値からマクロを実行することは不可能なのでしょうか? 解答、宜しくお願い致します。

  • エクセルマクロで特定の条件を満たすセルの関数を消す

    A1~D10000の範囲で値が入力されています。 F1~F10000に、それぞれの行の値が必要なのかの判定を関数で表示させています。 F列に「×」と表示されている行のA~D列の値をクリアさせるマクロを 作成したいです。 ネットで調べた所、「行を削除」というテンプレはあったのですが、 それだとF列の関数も消してしまうので、それは避けたいです。 最悪、行の削除をした後に関数をF列にコピペするマクロを 追加すれば良いと思いますが、下記マクロまで作ったのですが、 うまく動いてくれません。 分かる方がいましたら、返信頂きたいです。 Dim i As Long For i = Range("A1").End(xlDown).Row To 2 Step -1 With Cells(i, "F") If _ .Value Like "×" Then .EntireRow.Delete End If End With Next i End Sub

  • 選択した行のみマクロを使いたい

    以前、こちらのサイトで表を展開するマクロを教えていただきました。 そのマクロをシート全体ではなく、任意の行や任意のセルにだけに使えるようにしたいです。 Sub 展開() Dim nLast As Long Dim vAdata, i, j Dim vData nLast = Cells(Rows.Count, 1).End(xlUp).Row '行を追加削除する時は下から上が基本 For i = nLast To 1 Step -1 vAdata = Cells(i, 1) 'A列が空白ではなく、B列が空白の場合、B列以降を上と同じにする If (vAdata <> "") And (Cells(i, 2) = "") And (i > 1) Then Rows(i) = Rows(Cells(i, 2).End(xlUp).Row).Value Cells(i, 1) = vAdata End If If vAdata = "" Then 'A列の値が空白なら削除 Rows(i).Delete Shift:=xlUp Else 'A列の最後に「,」が有る場合は取り除く If Right(vAdata, 1) = "," Then vAdata = Left(vAdata, Len(vAdata) - 1) End If vData = Split(vAdata, ",") 'A列の値がカンマで区切られていた場合 If UBound(vData) > 0 Then '対象行をコピーして区切られていた数-1だけ下に挿入 Rows(i).Copy Rows(i & ":" & i + UBound(vData) - 1).Insert Shift:=xlDown 'A列の値を区切られていた値に書き換える For j = 0 To UBound(vData) Cells(i + j, 1) = vData(j) Next j End If End If Next i End Sub というマクロを教えて頂きました。 これをどのようにすればいいでしょうか? ご教授お願いします。

  • 条件付で20行目おきにComboBoxの値を入れる

    ユーザーフォームのComboBox1の値をシートのR列31行目から20行毎に入れる 但し、選んだ20行毎の6行上が空白なら値を入れない と、したいのですが、下の構文で実行すると一瞬表示されて消えてしまいます。 結果は空白になります。 これでも必死の思いでしましたので笑わないで下さいね。 宜しくご指導をお願いします。 Dim t Dim i For t = 25 To 994 Step 20 For i = 31 To 1000 Step 20 If Cells(t, 18) <> "" Then Cells(i, 18) = ComboBox1.Value ElseIf Cells(t, 18) = "" Then Cells(i, 18) = "" End If Next i Next t

専門家に質問してみよう