• 締切済み

エクセルVBAにて、特定文字の前に行を追加したい

こんにちは。 エクセルVBAにて、特定文字が含まれる行の前に空白の行を挿入するマクロはどのように書けばいいでしょうか。 そして、特定文字が連続して入力されている場合、連続した文字の個数と同じ行数を、連続した最初の文字の前に挿入したいと思っています。 特定文字=ラーメン 1行目 うどん 2行目 ラーメン(この上に3行挿入) 3行目 ラーメン 4行目 ラーメン 5行目 うどん 6行目 うどん 7行目 ラーメン(この上に1行挿入) 8行目 うどん 9行目 ラーメン(この上に2行挿入) 10行目 ラーメン 11行目 うどん 下記のようなコードを検索結果を参考に作成しましたが、これだとラーメンの上にすぐ空白の行が挿入されてしまい、連続した最初の特定文字の上にまとめて挿入する事ができません。 Sub Test() Dim a As Range Dim j As Long, k As Long j = WorksheetFunction.CountIf(Columns(3), "ラーメン") Set a = Range("C1") Do Set a = Columns(3).Find(What:="ラーメン" _ , After:=a _ , LookIn:=xlValues _ , LookAt:=xlWhole _ , SearchDirection:=xlPrevious) If Not a Is Nothing Then k = k + 1 a.EntireRow.Insert End If Loop While k < j End Sub どうすればいいかご教授お願いいたします。

みんなの回答

回答No.7

回答No.1です。 なんか盛り上がってますね。色んな意味で。 この課題、やり方は無数にあるということはご覧の通りな訳ですが、 混乱を避ける意味で、一応、 どんな意図で解答をしているのか、という説明 をこちらから加えながら、その他の簡単な方法も紹介してみます。 回答No.1では、ご質問で例示された、 range.Find メソッド の扱い方に重点をおいたものを紹介しています。 range.Find メソッド は良く使う基本技ですので、 扱い方をキチンと理解しておいた方が好い、という意図で書いています。 VBAのヘルプで range.Find メソッド を読んでみると解ると思いますが、 > 同じ検索を繰り返すときは、FindNext メソッドおよび FindPrevious メソッドを使用します。 推奨された方法、を、まず理解しておいた方が宜しいかと。 非VBAの場合で考えると、 ●Ctrl+F で[検索と置換]ダイアログを表示して、   [次を検索]ボタンを最初に押した時にあたるのが    range.Find メソッド   続けて[次を検索]ボタンを2回目以降に押した時は    range.FindNext メソッド ●Ctrl+F で[検索と置換]ダイアログを表示して、   Shiftキー+[次を検索]ボタンを最初に押した時にあたるのが    range.Find メソッドの SearchDirection:=xlPrevious 指定   続けてShiftキー+[次を検索]ボタンを2回目以降に押した時は    range.FindPrevious メソッド ということになります。 range.FindNext メソッド、range.FindPrevious メソッド、には、 終着点がないので、下手な書き方をすると無限ループを招く、 といった恐怖心?がもとで、食わず嫌いの方が結構多いようなのですが、 2~3通りも形で覚えておけば、困ることはまずないです。 、、、以下、range.Find メソッドを離れて、、、。 回答No.1でも触れた、AutoFilterを使った例を紹介します。 意図としては、項目タイトル行がある、という前提ひとつで、Excelは ただの<表>をひとつの<テーブル>として看做しますから、 用意された多彩な機能の中から、選ぶ機会が増える、 という例を示すことにあります。 既述の通り、状況が許すなら、ですが、 項目タイトル行は有った方が、 多くの場合、処理を簡素化する選択肢が増えることにはなります。 例では、ご提示のサンプルについて、 一旦、項目タイトル行を挿入して、 [フィルター]機能を使って一括で行挿入をして、 後に、項目タイトル行を削除しています。 ★でマークした行は、本来不要な記述です。 Sub ReW9197009c()   Rows(1).Insert ' ★ 最初から項目タイトル行があるなら、この行の処理不要   Range("A1:C1").Value = Split("a b c") ' ★ 〃   Cells.AutoFilter Field:=3, Criteria1:="ラーメン", Operator:=xlOr   Range("2:" & Cells(Rows.Count, "C").End(xlUp).Row).SpecialCells(xlCellTypeVisible).EntireRow.Select   Cells.AutoFilter   Selection.Insert   Rows(1).Delete ' ★ 〃 End Sub 最後に、作業セルを活用する例を挙げます。 Excelの数式などでもそうですが、一息に処理を纏めるよりも、 段階的に分けて処理する方が、無駄なく簡潔に纏められる場合が結構多いです。 予め作業用の列を固定的に用意しておくこと等出来れば尚更、 これもExcelに用意された一般機能を活用し易くする例として 紹介するものです。 また、簡素に短時間で書ける、というのは、それはそれで価値のあるものです。 例では、1列めに(作業用の)列を挿入しておいて、そこに Excel数式による判定(挿入したい行は数値、それ以外はエラー)を書いておいて、 [ジャンプ]機能(range.SpecialCells)で篩に掛けて、一括で行挿入をして、 後に、作業列を削除しています。 Sub ReW9197009a()   Columns(1).Insert ' ★ 最初から作業列を特定出来るなら、この行の処理不要   With Range("A1:A" & Cells(Rows.Count, "D").End(xlUp).Row) ' ▼ ★の場合、"D" は "C"     .FormulaLocal = "=1/(D1=""ラーメン"")" ' ▼ ★の場合、D1 は C1     .SpecialCells(xlCellTypeFormulas, xlNumbers).EntireRow.Insert   End With   Columns(1).Delete ' ★ 〃 End Sub 以上、なにか疑問が残るようでしたら、補足欄ででも、おたずねください。 追伸、 "ご教授..." って、Web上でも超メジャーな誤用ですけれど、 正しくは "ご教示..." です。 印象悪く受け止める方も少なくないようなので、一応、情報として。

全文を見る
すると、全ての回答が全文表示されます。
  • imogasi
  • ベストアンサー率27% (4737/17068)
回答No.6

#3です。さらに考え直して、下記の方がわかりやすい(また他シートを使わないのでよい)と思ったので上げます。 同じロジックで回答がすでに出ているかもしれない。その場合は後免。 ーー 「行挿入問題には最下の行から上方向に処理」という、一応のセオリーがありそれに従って、 (下記の例データのb は「ラーメン」のつもり) Sub test01() 連続 = 0 lr = Range("A10000").End(xlUp).Row For i = lr To 2 Step -1 If Cells(i, "A") = Cells(i - 1, "A") And Cells(i, "A") = "b" Then 連続 = 連続 + 1 Else If 連続 <> 0 Then Cells(i, "A").Resize(連続 + 1).EntireRow.Insert 連続 = 0 End If End If Next i End Sub 例データ a b b b v c c f g b b b j j j h b b 処理結果 a b b b v c c f g b b b j j j h b b

全文を見る
すると、全ての回答が全文表示されます。
  • ushi2015
  • ベストアンサー率51% (241/468)
回答No.5

こんにちは、No4です 良くみたら元データC列でしたね。 他の列のデータも関連するかもしれないので、同じSheet1で処理するとして、 Sub test1()   Dim sh1 As Worksheet   Dim i As Long   Dim a As Long   Dim r As Range      Set sh1 = Worksheets("Sheet1")      With sh1.UsedRange     With .Offset(, .Columns.Count)       .Formula = "=IFERROR(FIND(""ラーメン"",$C1,1),"""")"       .Value = .Value       On Error GoTo err_Line       Set r = .SpecialCells(xlCellTypeConstants)       a = r.Areas.Count       For i = a To 1 Step -1         r.Areas(i).EntireRow.Insert xlShiftDown       Next       .ClearContents     End With   End With   Exit Sub    err_Line:   MsgBox Err.Description End Sub ファイルのバックアップしておいてから試して下さい。

全文を見る
すると、全ての回答が全文表示されます。
  • ushi2015
  • ベストアンサー率51% (241/468)
回答No.4

こんにちは Sheet2にデータをコピーして処理しています。 Sub test()   Dim sh1 As Worksheet   Dim sh2 As Worksheet   Dim i As Long   Dim a As Long   Dim r As Range      Set sh1 = Worksheets("Sheet1")   Set sh2 = Worksheets("Sheet2")      sh2.UsedRange.ClearContents   sh1.Range("A1").CurrentRegion.Copy sh2.Range("A1")      With sh2.Range("A1").CurrentRegion     With .Offset(, .Columns.Count)       .Formula = "=IFERROR(FIND(""ラーメン"",$A1,1),"""")"       .Value = .Value       On Error GoTo err_Line       Set r = .SpecialCells(xlCellTypeConstants)       a = r.Areas.Count       For i = a To 1 Step -1         r.Areas(i).EntireRow.Insert xlShiftDown       Next       .ClearContents     End With   End With   Exit Sub err_Line:   MsgBox Err.Description End Sub

全文を見る
すると、全ての回答が全文表示されます。
  • imogasi
  • ベストアンサー率27% (4737/17068)
回答No.3

VBAコードなど書いて質問する前に、処理ロジックを「文章に」(またはフローチャートにして)書いてみて、じっくり考えるべきことだ。 初心者は、文章に書いてみて、じっくり考えて、漏れるケースや異例のケースがないか考える癖を付けることだ大切。そのプロセスをどれだけやったのか、すっ飛ばしてないか。 ーー ポイント Sheet1に行挿入をすると、現在の処理行が動くので、別シート(Sheet2)に、望むものを作る方式をお勧め。 ーー A。横1行に「ラーメン」がないか検索する。 1つのセルにでもあれば「あり」と判定し、その行の検索は打ち切り  ・見つからない行の場合  それまでの「後仕舞」    後仕舞  見つかった件数分データだけ別シートにコピー。(スペース行は見つかっ        た都度に挿入済み)         見つかった件数を0にリセット         見つかった最初の行番号記憶変数を空白にする    現在行データ  現在行を別シートにコピーする         別シートでの貼り付け位置をしっかりとらえておく  ・見つかった行の場合 別シートSheet2(次行)に空白行1行挿入          見つかった最初の行番号記憶変数が空白なら、今の行番号をセット         空白でなければそのままにする         見つかった最初の行番号を記憶        (見つかった最初の行と今回の「連」で見つかった行数をカウント保持する)        見つかった件数に+1        次行処理へ ===== A列だけ「ラーメン」があるかないかの例に簡略化した。 標準モジュールに Sub test01() '初期化 pos = 0 kensu = 0 k = 1 'Sheet2の行ポインター '--Sheet1各行処理 For i = 1 To 11 If Cells(i, "A") = "ラーメン" Then Worksheets("sheet2").Cells(k, "A") = "" '空白行の挿入 k = k + 1 If pos = 0 Then pos = i End If kensu = kensu + 1 Else '--- If kensu = 0 Then Worksheets("sheet2").Cells(k, "A") = Worksheets("Sheet1").Cells(i, "A") k = k + 1 Else '--保留した行をコピー貼り付け For m = pos To pos + kensu Worksheets("sheet2").Cells(k, "A") = Worksheets("Sheet1").Cells(m, "A") k = k + 1 Next m pos = 0 kensu = 0 End If '--ラーメンなしの現在行をコピー Worksheets("Sheet2").Cells(k, "A") = Worksheets("Sheet1").Cells(i, "A") End If Next i End Sub ==== 例データ Sheet1 A列 うどん ラーメン ラーメン ラーメン うどん うどん ラーメン うどん ラーメン ラーメン うどん ===== 結果 Sheet2 A列 うどん ラーメン ラーメン ラーメン うどん うどん ラーメン うどん ラーメン ラーメン うどん うどん ーー ややロジックが複雑で、もっと良い(すっきりした)回答が出れば勉強します。 しかし、こういう類似パターンは経験があるので、出ない予想だが。

全文を見る
すると、全ての回答が全文表示されます。
  • kkkkkm
  • ベストアンサー率65% (1636/2481)
回答No.2

もとのコードのイメージを残して変更してみましたがいかがでしょう。 Sub Test() Dim a As Range Dim MyRow As Long, k As Long, i As Long, AddRowsCount As Long MyRow = Cells(Rows.Count, 3).End(xlUp).Row Do Set a = Range(Cells(1, 3), Cells(MyRow, 3)).Find(What:="ラーメン" _ , LookIn:=xlValues _ , LookAt:=xlWhole _ , SearchDirection:=xlPrevious) AddRowsCount = 0 If a.Row > 1 Then For i = 1 To a.Row If a.Offset(-i, 0).Value = "ラーメン" Then AddRowsCount = AddRowsCount + 1 Else Exit For End If Next i End If If Not a Is Nothing Then Range(a, a.Offset(-AddRowsCount, 0)).EntireRow.Insert MyRow = a.Offset(-AddRowsCount, 0).Row - 1 End If Loop While MyRow > 1 End Sub

全文を見る
すると、全ての回答が全文表示されます。
回答No.1

こんにちは。 とりあえず、こんな感じ。 Sub ReW9197009() Dim c As Range Dim nRowB As Long, nRowT As Long   With Columns("C")     Set c = .Find( _       What:="ラーメン", _       LookIn:=xlValues, _       LookAt:=xlWhole, _       SearchDirection:=xlPrevious)     If c Is Nothing Then Exit Sub     nRowT = c.Row     nRowB = nRowT     Do       Set c = .FindPrevious(c)       If c.Row <> nRowT - 1 Then         Rows(nRowT & ":" & nRowB).Insert         If c.Row > nRowB Then Exit Do         nRowB = c.Row       End If       nRowT = c.Row     Loop   End With   Set c = Nothing End Sub もしも、1行めに項目行があるなら、 AutoFilterで抽出して、より簡単にできますね。 状況が許すなら、検討してみて下さい。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • VBA 特定の文字列を含む行を削除する方法

    特定の文字列を含む行を削除する方法が知りたいです。 行を削除する方法はWebで見つけたのですが↓ ---------------------------------------------------- Sub 特定の文字列を含む行を削除() Dim c As Range Dim myRow As Long With Range("A:A") Set c = .Find("特定の文字列") Do While Not c Is Nothing Rows(c.Row).Delete shift:=xlUp Set c = .Find("特定の文字列") Loop End With End Sub ---------------------------------------------------- ↑行を指定している箇所のRowsを Columns  RowをColomn に変更して以下の様にしてみました、   Columns(Colomn,c).Delete shift:=xlUp だめでした、、、。 VBAの知識が乏しく、組み立て方について理解が無いため、どうすればよいかさっぱりわからず、、 こちらで質問させて頂きました。。。 何卒宜しくお願い致します。

  • EXCEL VBA4行毎に枠で囲みたい

    お世話になります。 添付の様な表1があります。 これを表2のようにA1から順に4行毎に枠で囲みたいのです。 下記のようなコードを見よう見まねで書いてみましたがうまく動きません。 ごなたかご教授いただけませんでしょうか? よろしくお願い致します。 Dim i As Long Dim j As Long Dim lngYCnt As Long Dim intXCnt As Long Dim LastRow As Long ingYCnt = Worksheets("Sheet1").UsedRange.Rows.Count intXCnt = Worksheets("Sheet1").UsedRange.Columns.Count LastRow = Cells(Rows.Count, 1).End(xlUp).Row With Selection For i = 5 To LastRow Range("A" & i & ":F" & j).Select Selection.BorderAround Weight:=xlMedium j = j + 5 i = i + 5 Next End With どなたかご教授いただけませんでしょうか? よろしくお願い致します。 環境 EXCEL2003 WINDOWS XP SP3

  • エクセルのVBAで行選択

    エクセルVBAで、連続してない2行(たとえば10行目と13行目)を選択する場合 Sub test02() Dim x As Long, y As Long x = 10 y = 13 Range(x & ":" & x & "," & y & ":" & y).Select End Sub でできましたが、もっと簡単に書く方法はないでしょうか?

  • VBA 複数の行を挿入後、挿入以外を削除

    知恵をお借りください。 A10に5行分挿入、A13に2行分挿入、A14に1行分挿入、A16に2行分挿入 以下がコードです。 Dim n As Long n = Worksheets("Sheet1").Range("A1").Value With Worksheets("Sheet2") .Range("A10").Resize(n).EntireRow.Insert .Range("A10").Resize(n).EntireRow.Interior.Color = vbYellow .Activate End With Dim k As Long k = Worksheets("Sheet1").Range("A2").Value With Worksheets("Sheet2") .Range("A13").Resize(n).EntireRow.Insert .Range("A13").Resize(n).EntireRow.Interior.Color = vbRed .Activate End With Dim m As Long m = Worksheets("Sheet1").Range("A5").Value With Worksheets("Sheet2") .Range("A14").Resize(n).EntireRow.Insert .Range("A14").Resize(n).EntireRow.Interior.Color = vbGreen .Activate End With Dim ka As Long ka = Worksheets("Sheet1").Range("A10").Value With Worksheets("Sheet2") .Range("A16").Resize(n).EntireRow.Insert .Range("A16").Resize(n).EntireRow.Interior.Color = vbBlue .Activate End With マクロ実行後、行の並び方がバラバラになっています。 ↓イメージ図 https://mega.nz/#!yUwXHTLK!TSZvMJ1CaiTi-OoX-1j9IeNleuXesrzU5O7o2vG-svI 理想図に整えるにはどうすれば良いのでしょうか? また、マクロで行を挿入したら、不要な行を削除するコードも教えてくださればありがたいです。 ↓イメージ図 https://mega.nz/#!fMRDAKAJ!GHMpiagpn-O_0aaMhrHOozFd8WHHkSQzOS-fSCInw-g 宜しくお願いします。

  • エクセルVBA抽出がうまく出来ません

    エクセル2013VBA初心者です。 入力シートからDBシートへ、DBシートから印刷シートへのデータ転記と印刷、入力内容のクリアまでは出来るようになりました。 DBシートの検索を行い、記録内容を入力シートに転記する抽出を行いたいのですが、下記構文を書いたところで問題が発生しました。 If Sh2.Range("A & i").Value = j And Sh2.Range("B & i").Value = k Then  でとまります。メッセージは ‘Range’メソッドは失敗しました:‘Workshieet’オブジェクトというものです。 やろうとしていることは、入力シートに設けた“E12”と”G12”の二つの検索項目をキーにDBシートの行を特定し、この行の内容を入力シートに反映しようということです。 入力シートの検索項目“E12”、 ”G12”はそれぞれDBシートのA列、B列に格納されている項目で、年度と連番です。サンプルとして入力シート"C5"に抽出しようとしているDBシートD列は申請者名です。 恐れ入りますがよろしくご教示頂きたく、お願い申し上げます。 Sub DBシートから力情報を抽出する () Dim Sh1 As Worksheet Dim Sh2 As Worksheet Dim i As Long Dim j As Long Dim k As Long Set Sh1 = Worksheets("入力") Set Sh2 = Worksheets("DB") j = Sh1.Range("E12").Value k = Sh1.Range("G12").Value With Sh2 For i = 2 To .Range("A" & Rows.Count).End(xlUp).Row If Sh2.Range("A & i").Value = j And Sh2.Range("B & i").Value = k Then Sh1.Range("C5").Value = Sh2.Range("D & i").Value End If Next  End With End Sub

  • エクセルVBA カウンタ2つを入れ子にしたくない時

    皆さんこんにちは。 エクセル2013を使用しております。 エクセルVBAの繰り返し処理について質問させていただきます。 下記のコードですと入れ子があるので A1にi、A3にi・・・・を一通り記載したあと またA1にi+2、A3にi+2・・・を繰り返し 最終的にA列には全て同じ値が入ってしまいます。 (Step 2にしたのはA1:A2のように2行毎の結合セルだからです) -----------------------------------------------------------------    Dim i As Long Dim j As long Dim n As long Dim k As long     i =Userform.textbox1.value     j =Userform.textbox2.value    For k =i To j Step 2 For n = 1 to j Step 2 Range("A" & n) = k    Range(”B”&n)=k+1        Next    Next ---------------------------------------------------------- もしiが1、jが10だとしたら A1に1、B1に2、A3に3、B3に4、・・・A9に9、B9に10 が入るようにするにはどうしたら良いでしょうか。 iが必ず1から始まるのであればまだ分かるのですが そうとも限らないので カウンタはやはり2つ必要だと思うのですが カウンタが2つあるのに入れ子にしないコードの書き方って あるのでしょうか。 いくら本やネットを見ても分かりません。 ご教授いただけると幸いです。

  • エクセル 最終行からの連続コピー

    エクセルで最終行から上に連続する10行(最終行含む)をコピーしたいです。 途中、空白行が含まれている場合でも、最終行を特定し、コピーできるようにするには、下記のコードにどう手を加えたらよいでしょうか? どなたかアドバイスをお願いします。 Sub Test()   Dim i As Long   Dim j As Integer   Dim rng As Range   With ActiveSheet     'フィルタ     .Range("A1").CurrentRegion.AutoFilter Field:=1          '行選択     With .AutoFilter.Range       For i = .Cells(.Cells.Count).Row To 2 Step -1         If .Rows(i).Hidden = False Then           If rng Is Nothing Then             Set rng = .Rows(i)           Else             Set rng = Union(rng, .Rows(i))           End If           j = j + 1         End If         If j >= 10 Then Exit For       Next i       'コピー       If Not rng Is Nothing Then         rng.Copy Worksheets("Sheet2").Range("A1")         Beep       Else         MsgBox "該当行は存在しません。", 48       End If     End With   End With   Set rng = Nothing なお、コードはこちらを参考にさせていただきました。 http://okwave.jp/qa3552420.html?ans_count_asc=1

  • エクセルVBA FindNextについて

    エクセル2002使用です。 VBAのFindNextメソッドについて教えていただけますでようか?不定期の行ごとに存在する○から△までの表を抽出するために次のようなコードをつくりました。   A  B  C  D 1 ○ × × 2 × × × 3 △ × × 4 5 ○ × × 6 × × × 7 △ × × Sub 表の抜き出し() Dim myr1 as range Dim myr2 as range Dim firstmyr1 as String Set myr1 = Columns("A").Find(What:="○") firstmyr1 =myr1.adress Set myr2 = Columns("A").Find(What:="△") Do  処理・・・・ Set myr1 = Columns("A").FindNext(after:=myr1) Set myr2 = Columns("A").FindNext(after:=myr2) Loop until myr1.adress = firstmyr1 End Sub 上記のようなコードで、処理の後のSetステートメントでFindNextを使うと、A5の○とA7の△を見つけてほしいのに、1回目の処理・・・の後の読み込みでウオッチで見るとmyr1値が△になってしまって2回目の読み込みにいけません。Setステートメントが2つ以上あるときのFindNextメソッドの使い方で何か注意点があるのでしょうか? よろしくお願いします。

  • エクセルVBAで列幅設定

    A列の幅を、C~F列の幅(同一ではありません)に設定しようと思いました。 ところが Columns("A").ColumnWidth = Range("C1:F1").Width とすると、ColumnWidthとWidthの単位がまったく違うのでエラーになります。 同じ単位で設定するには Columns("A").ColumnWidth = Columns("C").ColumnWidth + Columns("D").ColumnWidth + Columns("E").ColumnWidth + Columns("F").ColumnWidth とするか、 Sub test02() Dim c As Range Dim x As Single For Each c In Range("C1:F1") x = x + c.ColumnWidth Next Columns("A").ColumnWidth = x End Sub などのように手の込んだことをするしか思いつきません。 もっと簡単な方法はないでしょうか?

  • EXCEL(VBA)で1行おきに行を選択する方法

    こんにちは。VBAは苦手なので教えてください。 EXCELのsheet1にあるリストに、下記マクロで1行おきに 空白行を挿入しました。 Sub test1() '隔行で空白行を挿入 Dim rw As Long 'セル For rw = Range("A1").End(xlDown).Row To 2 Step -1 Rows(rw).Insert Next End Sub 同じファイルのSheet2の1行目<Rows("1:1")>に、計算式が入力されています。 マクロで挿入した空白行全てを選択し、そこへSheet2の1行目のコピーを 貼り付けたいです。 ぜひ、良い方法を教えてください。