- ベストアンサー
VBA初心者の悩み:基本的な手法 | テキストファイルの特定パターン間のダミー文字挿入
- VBA初心者がテキストファイルの特定パターンの間にダミー文字列を挿入する方法についてアドバイスを求めています。
- 課題としては、テキストファイル内の指定した文字列の間に何もない場合にダミー文字列を挿入する処理を行うことです。
- さらに、指定した文字列が含まれる複数のテキストファイルに対して処理を実行する方法も教えてほしいとのことです。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
3要素しかないのだから、億劫がらずに理論展開しましょうよ。 (1) 最初の有効数の値は-1なので、If 有効数 > 1 にはかからず、 Else節が実行されます。有効数は1が加えられ0になります。 次のLine Input #1, バッファ(有効数)はバッファ(0)ですね。 (2) 2回目は有効数が0なので、やはりIf文のElse節に入り、 有効数は1になります。次の読み込みはバッファ(1)に読み込まれ ます。 (3) 3回目は有効数が1なので、やはりIf文のElse節に入り、 有効数は2になります。次の読み込みはバッファ(2)に読み込まれ ます。 (4) つまり有効数>1とは3行読み込んでいるという状態を示すのです。 よって、Line Input 後のIfで、3行を比較し、各行の条件を 調べているのです。 (5) ループの4回目は最初のIf文では初めてThen節に入ります。 そこで、一番古いバッファ(0)を出力し、バッファの要素を 前方に移動します。つまり、(0)←(1)、(1)←(2)という具合です。 Then節では有効数が+1されないので、有効数は2のままです。 (6) ということで、3行目以降は常にバッファ(2)に読み込まれます。 勿論、ループ1回に1行ずつしか読み込んでいません。 初心のうちから横着すると、論理的思考能力が鍛錬されませんよ。 もし、怪しいなら、デバッグ実行で、1ステップずつ実行して動作を 確認するぐらいのことはやらないといけません。 尚、掲題のコードは実際に実行させていますので、実行時エラーが 出るとすると、コピーミス(&の前の空白をぬいてしまうとか)では ないかと思います。
その他の回答 (2)
- nda23
- ベストアンサー率54% (777/1416)
スミマセン 間違いが2箇所あります。 Const 元パス As String = "C:\VBA\" Const 新パス As String = "C:\TMP\" Const 固定語 As String = ":SAMPLE_TEXT_ID_" '☆追加 Dim ファイル名 As String Dim 位置 As Long Dim 有効数 As Long Dim シェル, 旧フォルダ, 新フォルダ ファイル名 = Dir(元パス & "*.txt") Do Until ファイル名 = "" Open 元パス & ファイル名 For Input As #1 Open 新パス & ファイル名 For Output As #2 有効数 = -1 ReDim バッファ(2) As String Do Until EOF(1) If 有効数 > 1 Then Print #2, バッファ(0) バッファ(0) = バッファ(1) バッファ(1) = バッファ(2) Else 有効数 = 有効数 + 1 End If Line Input #1, バッファ(有効数) If 有効数 > 1 Then If Left(バッファ(0), 16) = 固定語 And _ バッファ(1) = "" And _ Left(バッファ(2), 16) = 固定語 Then バッファ(1) = "Dummy" End If End If Loop Close #1 For 位置 = 0 To 有効数 Print #2, バッファ(位置) Next Close #2 ファイル名 = Dir '★1 Loop Set シェル = CreateObject("Shell.Application") set 旧フォルダ = シェル.NameSpace(元パス) set 新フォルダ = シェル.NameSpace(新パス) 旧フォルダ.MoveHere 新フォルダ.Items, &H10 '★2 【解説】 (1) ファイル名 = Dir(元パス & "*.txt") Do Until ファイル名 = "" Dir関数は指定パターンに一致するファイル名を返します。 なければ空文字列が返るので、次のDo文と合わせて、 フォルダ内の指定パターンのファイルを全て処理します。 ★1の「次のファイル名を受け取る」というステートメントを 忘れたため、無限ループになってしまいました。 (2) 有効数 = -1 ReDim バッファ(2) As String 指定パターンであることを認識するには3行読み込んで 調べる必要があるため、3要素の配列を定義しています。 インデックスの底は0なので、有効数が-1とは全ての要素が 無効であるという意味です。 (3) If 有効数 > 1 Then Print #2, バッファ(0) バッファ(0) = バッファ(1) バッファ(1) = バッファ(2) Else 有効数 = 有効数 + 1 End If Line Input #1, バッファ(有効数) 有効数が2(つまり配列が一杯)なら、最初の行を書き込み、 配列を詰め替えます。そうでなければ読み込み先となる インデックスを更新しています。 (4) If 有効数 > 1 Then If Left(バッファ(0), 16) = 固定語 And _ バッファ(1) = "" And _ Left(バッファ(2), 16) = 固定語 Then バッファ(1) = "Dummy" End If End If 3行読み込まれていたら、パターンに一致するかを調べて、 一致すれば中間行に"Dummy"を入れています。 (5) For 位置 = 0 To 有効数 Print #2, バッファ(位置) Next 配列の残りを出力しています。 (6) Set シェル = CreateObject("Shell.Application") == 中略 == 旧フォルダ.MoveHere 新フォルダ.Items, &H10 新フォルダ内のファイルを全て元フォルダに上書き移動 します。&H10は何も聞かないという意味です。
お礼
懇切丁寧にご説明いただき、本当にありがとうございます。 実行すると「定数式が必要です。」となってしまいますが、だいたい処理の内容が理解できました。 でも、バッファの概念がイマイチ理解できないのですが、 Line Input #1, バッファ(有効数) とすると、有効数が2の場合、配列に3行分格納してくれるということでしょうか。 私のような初心者だと、ここは「Do Until EOF(1)」の中なので、1行ずつしか読み込まれないのではないか(バッファ(0)しか格納されないのではないか)と思ってしまいます。 やっぱり、理解できていないのでしょうね。 今後、勉強していくうちにわかるようになったらいいなと思います。
- nda23
- ベストアンサー率54% (777/1416)
先ず、テキストファイルは入力/出力/追加のいずれかの モードでしか開けませんので、この問題を解決するには 旧ファイルを読み込み、新ファイルにコピーしながら、 問題の部分だけ、特別な書き込みを行うようにします。 新しいファイルを作る場所を"D\TMP"と仮定します。 Const 元パス As String = "C:\VBA\" Const 新パス As String = "C:\TMP\" Dim ファイル名 As String Dim 位置 As Long Dim 有効数 As Long Dim シェル, 旧フォルダ, 新フォルダ ファイル名 = Dir(元パス & "*.txt") Do Until ファイル名 = "" Open 元パス & ファイル名 For Input As #1 Open 新パス & ファイル名 For Output As #2 有効数 = -1 ReDim バッファ(2) As String Do Until EOF(1) If 有効数 > 1 Then Print #2, バッファ(0) バッファ(0) = バッファ(1) バッファ(1) = バッファ(2) Else 有効数 = 有効数 + 1 End If Line Input #1, バッファ(有効数) If 有効数 > 1 Then If Left(バッファ(0), 16) = ":SAMPLE_TEXT_ID_" And _ バッファ(1) = "" And _ Left(バッファ(2), 16) = ":SAMPLE_TEXT_ID_" Then バッファ(1) = "Dummy" End If End If Loop Close #1 For 位置 = 0 To 有効数 Print #2, バッファ(位置) Next Close #2 Loop Set シェル = CreateObject("Shell.Application") set 旧フォルダ = シェル.NameSpace(元パス) set 新フォルダ = シェル.NameSpace(新パス) 旧フォルダ.MoveHere 旧フォルダ.Items, &H10 尚、作業用の新パスをMkDir、RmDir を使って、作成/削除する ことも可能です。
お礼
ご回答ありがとうございます。 とりあえず「C:\VBA\」にファイルを1つだけ入れて実行してみたところ、ずっと実行中のままになってしまいました。(中断時の「位置」の値は「3」、「有効数」は「2」でした) ところで、提示していただいたサンプルコードですが、「バッファ」や「有効数」の部分がいまいち理解できません。 「Do Until EOF(1)」のループのところで、普通は1行ずつ処理するところを、配列を導入することによって複数行の処理ができるようにしているのだろうということは何となくわかりますが、1つ1つの処理を追っていくと「???」状態です。 あつかましいお願いですが、今後の勉強のためにも少し解説していただけないでしょうか。 もちろん、お時間があればで結構です。
お礼
お礼が遅くなり大変申し訳ありません。 プログラミングにもだいぶ慣れてきて、ご提案の手法もかなり理解できるようになっていきました。 まだまだ初歩的な質問をせざるを得ないレベルですが、このようなサイトなどを利用しながら勉強していきたいと思っています。 今後また質問した時にはよろしくお願いいたします。