[VBA]指定の範囲から指定の文字列の行を削除する

このQ&Aのポイント
  • VBAを使用して、指定範囲から指定の文字列の行を削除する方法について質問しています。具体的には、A列に入っている値が'FALSE'か'TRUE'の場合、昇順で並び替えて'FALSE'の行を削除したいです。質問者はColumnDifferencesメソッドを使用して試みましたが、'TRUE'か'FALSE'どちらかしか含まれていない場合にエラーが発生するため、別の方法を模索しています。
  • VBAを使用して特定の範囲から特定の文字列を含む行を削除したい場合の質問です。具体的には、A列に入っている値が'FALSE'か'TRUE'の場合、昇順で並び替えて'FALSE'の行を削除したいです。質問者はColumnDifferencesメソッドを使用した方法について調査していますが、'TRUE'か'FALSE'どちらかしか含まれていない場合にエラーが発生します。どのようなコードが適しているかのアドバイスをお願いします。
  • VBAを使用して指定範囲から特定の文字列の行を削除する方法についての質問です。具体的には、A列に入っている値が'FALSE'か'TRUE'の場合、昇順で並び替えて'FALSE'の行を削除したいです。質問者はColumnDifferencesメソッドを使用して試みましたが、'TRUE'か'FALSE'どちらかしか含まれていない場合にエラーが発生するため、別の方法を模索しています。どのような方法が最適か教えてください。
回答を見る
  • ベストアンサー

[VBA]指定の範囲から指定の文字列の行を削除する

こちらの識者の方々にはいつもお世話になっています。 VBAの質問です。 環境は下記になります。 OS=windows7 pro 64bit Office=Excel2010(14.0.7128.5000) ・やりたいこと 指定範囲から、指定の文字列の範囲のrangeオブジェクトを取得する。 ColumnDifferencesが比較的やりたいことに近い(というか今まではこれを使っていた)のですが、 具体的には、A列に"FALSE"か"TRUE"の値が入っている状態で、A列を昇順で並び替え、FALSEの列を削除するというコードで、 Dim rng As Range  rng = Range("A1:A100")  rng.ColumnDifferences(rng(2)).EntireRow.Delete というような感じでやっていました。 しかし、A列に"TRUE"か"FALSE"どちらか一方しかない場合にエラーになってしまうことがわかり、その回避をしたいのです。 Dim rng As Range  rng = Range("A1:A100")  rng.ColumnDifferences(”TRUE”).EntireRow.Delete のような使い方ができればと思うのですが、通りません。 ColumnDifferencesメソッドの引数ComparisonはVariant型のようですが、文字列を指定することはできないのでしょうか? また、この場合どのようなコードが適していますでしょうか。 ColumnDifferencesメソッドを使うことには頓着していませんが、for~next文などで一行ずつ削除する方法を使わずに実現したいです。 質問に不備不足等ございましたらご指摘ください。 ご面倒お掛けしますがよろしくお願いします。

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

  • ベストアンサー
回答No.4

こんにちは。 > ColumnDifferencesメソッドの引数ComparisonはVariant型のようですが、文字列を指定することはできないのでしょうか? 少なくとも、文字列値を基準に列範囲を切り分けることは出来ません。 ComparisonはRange型専用 (改めて訊かれると詳しく調べた訳ではないので自信が揺らぎますが) と考えておいていいと思います。 Range型として受け取ることの出来るオブジェクト、 というような意図でそうした仕様になっているのでしょうが、 古めのVBAのメソッドには、特に理由も見当たらないのに オブジェクト型引数をVariant型にしていることが多々ありますね。 元々はExcelの一般機能をVBAから呼び出せるようにしたものですから、 列範囲を選択して、ショートカット Ctrl+Shift+| キーを押したタイミングの、 アクティブセルにあたるのが、引数Comparisonですので、値を指定する余地は無いような。 例外を挙げるなら、 selection.ColumnDifferences(null).select を実行すると、アクティブセルを無視して、 選択範囲の先頭セルがComparisonになりますから、 もしかしたらNull値を受け取る為のVariant型だったのかなぁ?とか。 それならObject型やRange型ではない、という理由の説明としては十分のような。 該当するオブジェクトが無い場合にエラーを返すメソッド の扱い方として基本通りのやり方として、2通り、 用途に合わせて使い分けてみて下さい。 勿論、単に   On Error Resume Next だけでも用途によっては十分というケースもあると思います。 ' /// Dim rng As Range   Set rng = Range("A1:A100")   On Error Resume Next   Set rng = rng.ColumnDifferences(rng(2))   If Err.Number <> 0 Then     MsgBox "ないよ!"   Else     rng.EntireRow.Delete   End If   On Error GoTo 0 ' /// ' /// Dim rng As Range Dim rng2 As Range   Set rng = Range("A1:A100")   On Error Resume Next   Set rng2 = rng.ColumnDifferences(rng(2))   On Error GoTo 0   If Not rng2 Is Nothing Then     rng2.EntireRow.Delete   Else     MsgBox "ないよ!"   End If ' /// (MsgBoxは仮設) range.ColumnDifferences メソッドは私も良く使いますが、 設計時によく迷う他の方法として、  AutoFilterで抽出後に表示・非表示の差分に対して処理(削除)する方法  セル範囲にフラグを出力しておいて、.SpecialCells()で切り分けて処理(削除)する方法   フラグを2種類のデータ型  [数値or文字列、 数値orエラー値、論理値or数値、、、]   の組合わせで建てておけば、range.SpecialCells(Type, Value)の引数Valueに [xlErrors,xlLogical,xlNumbers,xlTextValues]を指定して判別出来るので、.EntireRow.Delete などがあります。  前者は、抽出の前後で表示行数に変動があるかどうか、  後者は、該当するオブジェクトが無い場合にエラーを返すので、   .ColumnDifferences同様エラートラップで、判別します。   フラグの方でよく使うのは、    =(条件式)/1 みたいなExcel数式をセルに計算させておいて、    数値orエラー値で切り分けるとかですね。    場合によっては、二次元配列に格納したものを出力するとか、    Evaluateメソッドで丸ごと計算させる場合もあります。 いずれの方法でも、XL2010でしたら、ご承知のように、 ソートしてから削除するのが処理速度的にベターです。 2種の値だけを切り分ける目的でしたら、ソートした上で、 下方に位置する値の先頭行をrange.Findメソッドで取得して、 以降の行を削除する手もあります。 range.Findメソッドの場合は、 該当するオブジェクトが無い場合にもエラーにはなりませんから、   If Not Is Nothing Then みたいな判別だけで、 エラートラップ無しでも行けます。 エラートラップというと腰が引けちゃう人結構いるみたいですが、 エラーを放置して実行時エラーで処理が中断するこは問題になりますが、 エラートラップについては、オブジェクトを扱う以上は扱いに熟れた方がいいです。 野菜も食べましょうね!的なニュアンスで、これは閲覧者さん向けのメッセージです。 実例を見れば、もう少し絞り込んだ提案も出来ると思いますが、一般論として、 とりあえず、以上です。 何か不足、不明があれば、遠慮なくお尋ねください。

rihitomo
質問者

お礼

例を2つもあげていただきありがとうございます。 また、Comparisonについても解説も分かりやすくご説明いただきありがとうございます。 仰るようにSpecialCellsで判定できるようにする方法もありますね。 ちょっと目から鱗でした、ありがとうございます。 エラートラップ、Findメソッド、SpecialCellsを使い分けられるよう精進したいと思います。

その他の回答 (4)

回答No.5

No.4です、訂正です。 誤) > =(条件式)/1 正)  =1/(条件式) でした。 条件式がFalseならdiv0エラーを返す、という意味です。 取り急ぎ訂正のみ。失礼しました。

  • kagakusuki
  • ベストアンサー率51% (2610/5101)
回答No.3

Dim rng As Range  rng = Range("A1:A100")  rng.ColumnDifferences(”TRUE”).EntireRow.Delete としたのでは、例えA1:A100の範囲にTRUEが入力されているセルが存在している場合でもエラーになると思います。  一例としては次の様にされては如何でしょうか。 Sub QNo9090068_指定の範囲から指定の文字列の行を削除する() Dim rng As Range, c As Range Set rng = Range("A1:A100") Set c = rng.Find(True, , xlValues, xlWhole) If Not c Is Nothing Then rng.ColumnDifferences(c).EntireRow.Delete End Sub

rihitomo
質問者

お礼

true値が指定範囲にあるかどうかをFindメソッドで調べるということですね。 処理分岐もできるしとても参考になりました。ありがとうございます。

  • dogs_cats
  • ベストアンサー率38% (278/717)
回答No.2

スマートなやり方ではありませんが、ソート後にfalseの最初の行番号をワークシート関数のmatchで取得、終了位置はcountif関数で取得し、行を削除する。 match関数なのでセル範囲がA1から指定しないと行がずれます。 Sub test() Dim StRow, EndRow, cnt As Integer Dim rng As Range Set rng = Range("A1:A100") On Error GoTo myError rng.Sort _ Key1:=Range("A1"), Order1:=xlAscending StRow = Application.Match(False, rng, 0) cnt = Application.CountIf(rng, False) EndRow = StRow + cnt - 1 Rows(StRow & ":" & EndRow).Delete myError: End Sub

rihitomo
質問者

お礼

参考になりました。ありがとうございます。

  • ushi2015
  • ベストアンサー率51% (241/468)
回答No.1

こんにちは Sub test() Dim rng As Range Set rng = Range("A1:A100") On Error Resume Next rng.ColumnDifferences(rng(2)).EntireRow.Delete On Error GoTo 0 End Sub これでいいのかと思います。 後はオートフィルタかけて行削除するとか。

rihitomo
質問者

お礼

参考になりました。ありがとうございます。

関連するQ&A

  • エクセル VBA 表示範囲の簡素化

    よろしくお願いします。 下記構文の簡素化ができないでしょうか。 CommandButtonが30個ほどあります。 ーーーーーーーーーー Private Sub CommandButton1_Click() Dim rng As Range Application.Goto Sheets("基本台紙").Range("A1") Set rng = Range("A1:D7") Rows.Hidden = True rng.EntireRow.Hidden = False Columns.Hidden = True rng.EntireColumn.Hidden = False rng(1).Select Unload Me UserForm1.Show vbModeless End Sub ーーーーーーーーーー Private Sub CommandButton2_Click() Dim rng As Range Application.Goto Sheets("基本台紙").Range("A1") Set rng = Range("A8:B21") Rows.Hidden = True rng.EntireRow.Hidden = False Columns.Hidden = True rng.EntireColumn.Hidden = False rng(1).Select Unload Me UserForm1.Show vbModeless End Sub ーーーーーーーーーー Private Sub CommandButton3_Click() Dim rng As Range Application.Goto Sheets("基本台紙").Range("A1") Set rng = Range("C8:D21") Rows.Hidden = True rng.EntireRow.Hidden = False Columns.Hidden = True rng.EntireColumn.Hidden = False rng(1).Select Unload Me UserForm1.Show vbModeless End Sub

  • 指定した範囲内が空白なら行削除するマクロ

    エクセルで指定した範囲内(A列からC列まで)で何も文字が入っていなければ(空白)、行を削除する、というマクロを教えてください。 いくつか調べて、以下を試しましたが、何も動作しませんでした。 どなたかアドバイスをいただければ助かります。 よろしくお願いします。 Sub DeleteBlankRows2() Application.ScreenUpdating = False On Error Resume Next With Columns("A:C") .SpecialCells(xlCellTypeConstants).EntireRow.Hidden = True .SpecialCells(xlCellTypeFormulas).EntireRow.Hidden = True .SpecialCells(xlCellTypeComments).EntireRow.Hidden = True .SpecialCells(xlCellTypeVisible).EntireRow.Delete .EntireRow.Hidden = False End With Application.ScreenUpdating = True End Sub

  • CountBlankの範囲指定について

    VBA勉強中の者です 変数にて指定した範囲の空白セルをカウントする為に、以下のコードを作成しました。 Sub test() Dim rng As Range Set rng = Range(Cells(1, 1), Cells(1, 10)) Dim CntBnk As Long '-------↓以下が認識されないコード-------------- CntBnk = WorksheetFunction.CountBlank(ActiveSheet.Range(rng)) '--------------------------------------------------- MsgBox (CntBnk) End Sub CountBlankの範囲指定の方法が間違っていると思われます。 簡単に CntBrk = rng.CountBlank と入力するなどしてみましたが、やはりダメでした。 自分なりに調べつつ改善してみたものの解決に至らず、どなたかご助力お願い致します。

  • 特定文字列を含む行を削除するマクロ

    すみませんどなたか教えてください。 エクセルで商品の在庫管理をしておりまして、AP列に製品メーカー名が入っているのですが、 いくつかの(数十個)メーカーを省き削除したく思い、以下のようなマクロをググって作ってみましたが、 上手く動きませんでした。 1つのメーカーだけ記載した場合はうまく動きました。 やりたいことは1つのマクロの中に、数十個のメーカー名を記入しておき、そのメーカーを全件 検索して、AP列に文字列が含まれる場合は、その行を削除したいです。 宜しくお願い致します。 ~~~~~~ Sub DelLines1() Dim R As Range Do Set R = ActiveSheet.Range("AP:AP").Find(What:="softbank", LookAt:=xlPart) If R Is Nothing Then Exit Sub R.EntireRow.Delete Loop Sub DelLines2() Dim R As Range Do Set R = ActiveSheet.Range("AP:AP").Find(What:="docomo", LookAt:=xlPart) If R Is Nothing Then Exit Sub R.EntireRow.Delete Loop Sub DelLines3() Dim R As Range Do Set R = ActiveSheet.Range("AP:AP").Find(What:="au", LookAt:=xlPart) If R Is Nothing Then Exit Sub R.EntireRow.Delete Loop End Sub

  • エクセルVBAで表から行の削除

    添付画像のような表があります。 表はB列の名前でソートされています。 D列の比率をみて、100でないものは、必ず同じ名前で複数行にわかれ合計で100になります。この例では名前CとEとHがそうです。 同じ名前が複数行にわかれている場合、最大の比率の行を残し、他の行(例では、埼玉、栃木、長野、新潟の行)を削除したいのです。 複数行にわかれるのが名前CやEのように2行なら、以下のコードで出来ました。 しかし、めったにはありませんが名前Hのような3行以上に分かれるものには対応できません。 どうすればよいでしょうか? Sub test01()   Dim c As Range   Dim Rng As Range   Set Rng = Range(Cells(2, "D"), Cells(Rows.Count, "D").End(xlUp))   For Each c In Rng '2地区の分担の場合、分担比率高い方を残す。(3地区以上は未対応)2012/08/29     If c.Value <> 100 And c.Offset(1).Value <> 100 Then       If c.Offset(, -2).Value = c.Offset(1, -2).Value Then         If c.Value >= c.Offset(1).Value Then           c.Offset(1).Value = False         Else           c.Value = False         End If       End If     End If   Next   If Application.WorksheetFunction.CountIf(Rng, False) > 0 Then     Rng.SpecialCells(xlCellTypeConstants, xlLogical).EntireRow.Delete   End If End Sub

  • エクセル2010 VBA 行削除

    特定列が空白であれば行削除をしたいのですが、下記コードでうまく削除は出来るのですが、応答なしになったり、とても遅いのですが、もう少し早く処理出来る方法はありますか? E列が空白であれば行削除をしたいのですが・・ With Range("E13", Cells(Rows.Count, 5).End(xlUp)) .AutoFilter Field:=1, Criteria1:="" On Error Resume Next Set rng = .Offset(1).Resize(.Rows.Count - 1).SpecialCells(xlCellTypeVisible) If Err.Number = 0 Then rng.EntireRow.Delete On Error GoTo 0 .AutoFilter End With

  • VBA 範囲選択時エラー

    Private Sub Worksheet_SelectionChangeのVBAでA列B列C列でワンクリックで文字が入力できるように設定致しました。 その後、A列からC列を範囲選択してDeleteするとデバック 「実行時エラー  型が一致しません」と出てしまいます。業務上、そのセルのデータは一気に消したいので困っております。どなたか分かる方よろしくお願い致します。 Private Sub Worksheet_SelectionChange(ByVal Target As Range) Dim rng As Range, rng_1 As Range, rng_2 As Range Application.EnableEvents = False Set rng_1 = Range("H17:H100") Set rng_2 = Range("I17:I100") Set rng_3 = Range("J17:J100") Set rng_4 = Range("K17:K100") Application.EnableEvents = True Set rng = Intersect(Target, rng_1) If Not rng Is Nothing Then Cancel = True If Target.Value = "" Then Target.Value = "(1)" Else Target.Value = "(1)" End If Else Set rng = Intersect(Target, rng_2) If Not rng Is Nothing Then Cancel = True If Target.Value = "(2)" Then Target.Value = Empty Else Target.Value = "(2)" End If Else Set rng = Intersect(Target, rng_3) If Not rng Is Nothing Then Cancel = True If Target.Value = "(3)" Then Target.Value = Empty Else Target.Value = "(3)" End If Else Set rng = Intersect(Target, rng_4) If Not rng Is Nothing Then Cancel = True If Target.Value = "(4)" Then Target.Value = Empty Else Target.Value = "(4)" End If End If End If End If End If End Sub

  • FALSEの行を削除したい

    office365 データベースから抽出したデータでフラグがFALSEの行を削除したい。 行数は2万行くらいある状態。 データの状態は A列に親となる番号のコード B列に順番と品番が結合されたコード C列にフラグのコード で、具体的なデータのイメージは下記状態 A列   B列  C列 A0001 1code1 TRUE A0001 2code1 TRUE A0001 2code1 FALSE A0001 3code1 TRUE A0001 4code1 A0001 5code1 TRUE A0001 6code1 TRUE A0001 7code1 TRUE A0001 8code1 TRUE A0001 9code1 TRUE A0001 10code1 TRUE A0001 11code1 TRUE A0001 12code1 TRUE A0002 1code2 TRUE A0002 2code2 TRUE A0002 3code2 TRUE A0002 4code2 TRUE A0002 5code2 TRUE A0002 6code2 TRUE A0002 7code2 TRUE A0002 8code2 TRUE A0003 1code3 TRUE A0003 2code3 TRUE A0003 3code3 TRUE A0003 3code3 FALSE この状態でC列がFALSEとなっている行を削除したい。 C列がNULLの行はそのまま残す。 これを実現するマクロを下記の様にしました。 C列NULLのセルをいったんTRUEに置換、 sub macro1() Dim LASTROW1 As Long 'シートのmax行数 LASTROW1 = Worksheets("sheet1").Cells(Rows.count, 1).End(xlUp).Row Range("C2: C" & LASTROW1).Select Selection.Replace What:="", Replacement:="TRUE", LookAt:=xlPart, _ SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _ ReplaceFormat:=False, FormulaVersion:=xlReplaceFormula end sub C列で並び替えてTRUEの行を別シート(work)へコピー sub macro2() ThisWorkbook.Worksheets("sheet1").Select Dim t As Long t = 2 Dim LASTROW As Long LASTROW = Worksheets("sheet1").Cells(Rows.count, 1).End(xlUp).Row Range("A:C").Select Selection.AutoFilter ActiveSheet.Range(Cells(1, 1), Cells(LASTROW, 3)).AutoFilter Field:=3, Criteria1:="TRUE" Rows(t & ":" & LASTROW).Select Selection.Copy Sheets("work").Select Range("A1").Select ActiveSheet.Paste end sub 実行結果 A0001 1code1 TRUE A0001 2code1 TRUE A0001 3code1 TRUE A0001 4code1 A0001 5code1 TRUE A0001 6code1 TRUE A0001 7code1 TRUE A0001 8code1 TRUE A0001 9code1 TRUE A0001 10code1 TRUE A0001 11code1 TRUE A0001 12code1 TRUE A0002 1code2 TRUE A0002 2code2 TRUE A0002 3code2 TRUE A0002 4code2 TRUE A0002 5code2 TRUE A0002 6code2 TRUE A0002 7code2 TRUE A0002 8code2 TRUE A0003 1code3 TRUE A0003 2code3 TRUE A0003 3code3 TRUE となる様にしたいのです。 いちおうmacro1とmacro2の内容で目的は達成されているのですが、 もっとすっきりするマクロがあれば教えていただきたく。

  • VBAで空白行を削除する

    VBAでリストの空白行を削除するための適当なコードを探しているのですがどんぴしゃのものが中々見つかりません。ご教授下さい。 ブックBのシートBのリストにはA2~AN●まで値が入っています。 別のブックAからVBAで値を取り出し貼り付けています。 いくつかの方法を試しました。 (1)ブックを開いたときに空白行を削除 Sub Auto_Open() '空白行を削除 Dim lRow As Long Dim i As Long lRow = Cells(Rows.Count, 1).End(xlUp).Row Application.ScreenUpdating = False For i = lRow To 2 Step -1 If Cells(i, 1).Value = "" Then Range(i & ":" & i).Delete End If Next i Application.ScreenUpdating = True End Sub 5分以上砂時計のままで結局終わりません。 強制終了させ再度ブックを開くと空白行は削除されているのですが、こんな動作では使うことができません。 (2)ブックAの値を貼り付けた後、空白行を削除し上書き保存する Sub エクスポート() Application.ScreenUpdating = False Application.Calculation = xlCalculationManual Range(Cells(5, 7), Cells(79, 46)).Select Selection.Copy 'コピー Workbooks.Open Filename:="\\パス\ブックB.xlsm" '貼り付け先ファイルオープン Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _ :=False, Transpose:=False '貼り付け Dim lRow As Long Dim i As Long lRow = Cells(Rows.Count, 1).End(xlUp).Row Application.ScreenUpdating = False For i = lRow To 2 Step -1 If Cells(i, 1).Value = "" Then Range(i & ":" & i).Delete End If Next i Application.ScreenUpdating = True  '空白行を削除 ActiveWorkbook.Save '上書き保存 Application.Calculation = xlCalculationAutomatic Application.ScreenUpdating = True End Sub (3)空白行を削除の部分は以下のコードも試しました Worksheets("SheetB").Range("A1").Select Set currentCell = Worksheets("sheetB").Range("A1") Do While Not IsEmpty(currentCell) Set nextCell = currentCell.Offset(1, 0) If Not IsEmpty(currentCell) Then 'カレントセルが空白でなく、 If IsEmpty(nextCell) Then '次のセルが空白のとき nextCell.EntireRow.Delete End If End If Set currentCell = currentCell.Offset(1, 0) Loop '空白行削除 宜しくお願い致します。

  • EXCEL 2つの特定の文字列がある行を残して削除

    EXCELにて2つの特定の文字列が含まれる行を残して削除したいと思っております。 A列50行にそれぞれ"年賀状""喪中""名刺"がランダムに羅列されていて、その中から"年賀状"と"喪中"の行だけを残して"名刺"の行は削除したいと思ってます。(B列以降は注文番号、枚数、氏名等が入力されています) 以下のコードで1つだけは可能でしたが、色々試しても2つはできませんでした。(コードは拾い物を少しアレンジ) Sub MacroTest1()   Dim keyWord As Variant   Dim FirstAdd As String   Dim UR As Range   Dim c As Range   Const col As Long = 1 '列数   keyWord = "年賀状"   If VarType(keyWord) = vbBoolean Or Len(keyWord) = 0 Then Exit Sub      With ActiveSheet     With .UsedRange       Set c = .Find( _       What:="*" & keyWord & "*", _       LookIn:=xlValues, _       LookAt:=xlPart, _       SearchOrder:=xlByRows)              If Not c Is Nothing Then         FirstAdd = c.Address         Set UR = c         Do           Set c = .FindNext(c)           Set UR = Union(UR, c)           If c.Address = FirstAdd Then Exit Do         Loop Until c Is Nothing       End If     End With     If Not UR Is Nothing Then       UR.EntireRow.Hidden = True       .UsedRange.SpecialCells(xlCellTypeVisible).Delete       .UsedRange.EntireRow.Hidden = False     End If   End With End Sub どうか宜しくお願いします。

専門家に質問してみよう