旅行好きのおしりトラブル対策グッズ3選

txtファイルをOpenステートメントで開き、Line Inputで文字列を入れた変数Xがあります。
それよりも新しいtxtファイルを同じように取り込んだ変数Yがあります。
例えばXの中身は500行でYは503行などに増えています。
この3行を抽出するにはどうすれば良いのでしょうか。

このQ&Aに関連する最新のQ&A

A 回答 (6件)

追加分の場合を少し変更


Sub test()
Dim fso As New FileSystemObject
Dim file1 As String
Dim file2 As String
Dim size1 As Long
Dim buf As String

file1 = "C:\file1.txt" '旧ファイル
file2 = "C:\file2.txt" '新ファイル

'旧ファイルのサイズ(文字数、バイト数ではない)を取得
With fso.GetFile(file1).OpenAsTextStream
size1 = Len(.ReadAll)
.Close
End With

'新ファイル読み込み
With fso.GetFile(file2).OpenAsTextStream
.Skip size1 '読み込みスキップ
buf = .ReadAll '追加分読み込み
.Close
End With
Set fso = Nothing

MsgBox buf
'配列にするなら、
'Dim d() As String
'd = Split(buf, vbCrLf)
End Sub


ADODB.Streamを使って、file1を読まない場合
Sub test()
Dim strm As New ADODB.Stream
Dim fso As New FileSystemObject
Dim file1 As String
Dim file2 As String
Dim size1 As Long
Dim buf() As Byte
Dim s As String

file1 = "C:\file1.txt"
file2 = "C:\file2.txt" '新ファイル

'旧ファイルのサイズ(バイト数)を取得
size1 = fso.GetFile(file1).Size
Set fso = Nothing

'新ファイル読み込み
With strm
'バイナリで増えた分を読み込み
.Open
.Type = adTypeBinary
.LoadFromFile file2
.Position = size1
buf = .Read(adReadAll)
.Close

'文字列に変換
.Open
.Type = adTypeBinary
.Write buf
.Position = 0
.Type = adTypeText
.Charset = "shift_jis"
s = .ReadText(adReadAll)
.Close
End With
set strm = Nothing

MsgBox s
'配列にするなら、
'Dim d() As String
'd = Split(s, vbCrLf)
End Sub
    • good
    • 0
この回答へのお礼

fumufumuさん、たびたびすみません。
現在の方法でも遅れた時に手動で流れを一時ストップすれば動くことは動くんです。
ただ、それでは不完全なのでお聞きしました。
教えていただいたコードを自分でチェックしながらやってみます。

新回答が次々増えると困るので、一度これで締め切ります。
有り難うございました。

お礼日時:2008/01/04 22:46

追加という条件なら


Sub test()
Dim fso As New FileSystemObject
Dim file1 As String
Dim file2 As String
Dim buf As String

file1 = "C:\file1.txt"
file2 = "C:\file2.txt" '新ファイル

With fso.GetFile(file1).OpenAsTextStream
buf = .ReadAll
.Close
End With
With fso.GetFile(file2).OpenAsTextStream
buf = .Read(Len(buf))
buf = .ReadAll
.Close
End With
MsgBox buf
Set fso = Nothing
End Sub
file1は、.sizeでサイズだけ読んで、その分offsetする方がいいので、本当はADODB.Stream使った方がいいかもしれない。


途中をチェックするなら、追加部分に重複がない条件だけれどinstrでvbに任せた方が早いかも。
Sub TestDiffShowing()
Dim fso As New FileSystemObject
Dim file1 As String
Dim file2 As String
Dim buf1 As String
Dim buf2() As String
Dim i As Integer

file1 = "C:\file1.txt"
file2 = "C:\file2.txt" '新ファイル

With fso.GetFile(file1).OpenAsTextStream
buf1 = .ReadAll
.Close
End With
With fso.GetFile(file2).OpenAsTextStream
buf2 = Split(.ReadAll, vbCrLf)
.Close
End With
buf1 = vbCrLf & buf1 & vbCrLf
For i = 0 To UBound(buf2)
If InStr(buf1, vbCrLf & buf2(i) & vbCrLf) = 0 Then
MsgBox buf2(i)
End If
Next
Set fso = Nothing
End Sub

p.s.
とりあえず、ファイルは読まないか、読むなら一発で読んだ方が早いと思う
    • good
    • 0

こんばんは。



>コンマ秒単位の各ファイル処理をしなければならない

たぶん、BDiff のようなツールのことをおっしゃっていると思いますが、VBA では、オーバーヘッドが大きすぎて、どの方法を取っても、そういう話は、かなり厳しいと思いますね。たとえば、CommandLine のFC コマンドでも、一旦、VBAを抜け出てしまうので、行き帰りではコンマ秒単位は無理かもしれません。

ためしに考えてみましたが、無理かもしれませんね。

'一括で取るなら、こういう方法は考えられます。出力は、今は、MsgBox にしていますが、適当に、Debug.Print や、セルなどに出力してください。

'--------------------------------------------------------------
Sub TestDiffShowing()
'オーバーヘッドが気になるようなら、参照設定要
'Microsoft Scripting Runtime
  Dim objFS As Object 'FileSystemObject
  Dim objText As Object 'TextStream
  Dim fnA As String
  Dim fnB As String
  Dim mText As String
  Dim mDiff As String
  Dim LastLine As Long
  Dim i As Long
  
  fnA = "C:\Test1.txt"
  fnB = "C:\Test1N.txt" 新ファイル
  
  Set objFS = CreateObject("Scripting.FileSystemObject")
  Set objText = objFS.OpenTextFile(fnA)
  mText = objText.ReadAll
  LastLine = objText.Line
  objText.Close
  Set objText = objFS.OpenTextFile(fnB)
  For i = 1 To LastLine - 1
    objText.SkipLine
  Next i
  Do While objText.AtEndOfLine <> True
    mDiff = mDiff & objText.ReadLine & vbCrLf
  Loop
  
  MsgBox mDiff
  'Debug.Print mDiff
  
  objText.Close
  Set objText = Nothing
  Set objFS = Nothing

End Sub
    • good
    • 0
この回答へのお礼

Wendyさん、こんばんは。 m(_ _)m

ごく基本的なステートメントでやったんですが(それしか知らないもので・・)、早く動かすとなるとやはり高度な処理が必要なんですね。
インスタンスとか使ってるんでしょうか。教えていただいたマクロ、調べながらやってみます。
ありがとうございます。

お礼日時:2008/01/04 22:45

> リアルタイムでコンマ秒単位の各ファイル処理をしなければならない



かなりシビアな要求ですね...VBA では厳しい(無理?)と思います。

> Line Inputで文字列を入れた変数Xがあります

少しでも高速でテキストファイルを読み込みたいなら、Binary モードで
まず全体をバッファ用変数に読み込み、Split (区切り文字:改行コード)
で配列にばらすのはどうですか?
その配列内を WorksheetFunction の Match とか Vlookup で比較します。

下記に一例を書いてみます。ただし、実際にテストしたわけではありま
せんが、先述のとおりコンマ秒という要求に追従できるかは疑問です^^;
少なくとも Line Input で行単位で読み込む、行単位で逐次比較していく
よりは高速なはずですが...

 # 1つのテキストファイル内に全く同一の行が無いことが前提です

ご参考までに。

Sub SampleProc()
  
  Dim n    As Integer
  Dim sBuffer As String
  Dim X    As Variant
  Dim Y    As Variant
  Dim i    As Long
  
  ' // ※ 注意
  ' // 変数 sInFile1, sInFile2 にはテキストファイルの
  ' // フルパスを代入しておいて下さい
  
  ' // テキスト1 をバイナリモードで読み込み、変数 X に
  ' // 改行コードで行単位にばらした配列を作成
  n = FreeFile()
  Open sInFile1 For Binary Lock Read Write As #n
    sBuffer = Space$(LOF(n))
    Get #n, , sBuffer
  Close #n
  X = Split(sBuffer, vbCrLf)

  ' // テキスト2 も同様の処理
  n = FreeFile()
  Open sInFile2 For Binary Lock Read Write As #n
    sBuffer = Space$(LOF(n))
    Get #n, , sBuffer
  Close #n
  Y = Split(sBuffer, vbCrLf)
  
  ' // イミディエイトウインドウに差分抽出の結果を表示
  For i = 0 To UBound(Y)
    ' // Match 関数の結果でエラー値が返るようなら
    ' // テキスト2(Y) にあって、テキスト1(X) には無い
    If IsError(Application.Match(Y(i), X, 0)) Then
      ' // Split は 0 オリジンの配列を返すので
      ' // 行番号は+1になる
      Debug.Print Format$(i + 1, "0000") & ": ";
      Debug.Print Y(i)
    End If
  Next i

End Sub
    • good
    • 0
この回答へのお礼

お礼が遅れすみません。
作業の対象はかなりレベルが高いんですが、自分の持ってる知識は極わずかなのでギャップが大きいです。
Matchなど使ってみます。

ただ、たまに同一行が出てきます。それとバイナリだと他からアクセスされるとエラーが出るんではなかったでしたっけ? たぶんLock出来ないです。
あいまいな知識なんですが・・
回答有り難うございます。

お礼日時:2008/01/04 22:42

根本的に違いはないのですが、Vlookupではなく、Match関数を使ってVBAで比較します。



Dim dmy As String
Dim er As Integer
Dim i As Integer
For i = 0 To UBound(y)
On Local Error Resume Next
dmy = Application.WorksheetFunction.Match(y(i), x, 0)
er = Err
On Local Error GoTo 0
If er <> 0 Then MsgBox y(i)
Next
    • good
    • 0

Excelなら、A列にX、B列にYを書き込んで、C列にVLOOKUP関数書き込んで、エラーの行(見つからない行)が追加された行、と

かでは?
    • good
    • 0
この回答へのお礼

回答有り難うございます。
ソフトはExcel2003です。
一枚一枚全文字列を表に出せば関数やマクロで差分取得は出来るんですが、リアルタイムでコンマ秒単位の各ファイル処理をしなければならないのと、他ソフトを同時進行で使うため、出来るだけ変数段階で処理し数行だけを表に書き込んでPCの負担を減らしたいという考えなんです。

お礼日時:2008/01/04 00:44

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


人気Q&Aランキング