質問
2018年6月10日日曜日 17:42
次のVBAでUTF8形式テキストファイルを1行ずつ読み込めません。
(A)の個所で、2行目以降は、行の先頭が1列目からではなく、行の途中から読み込んでいるようです。
このため、(B)の行の先頭にある日付の比較で合致せず、必要なログの抽出ができません。
なぜでしょうか。ご教示いただきたく宜しくお願い致します。
Sub chk_Log()
Dim i As Long
Dim rBk As Workbook
Dim Path, Target As String
Dim toDay As Date
toDay = Date
Path = ThisWorkbook.Path & "\aaaadata.log"
Target = Path
Set rBk = Workbooks.Add
i = 0
With CreateObject("ADODB.Stream")
.Charset = "UTF-8"
.Open
.LoadFromFile Target
Do Until .EOS
Logrec = .ReadText(-2) <--(A)
If toDay <= Left(Logrec, 10) Then <--(B)
i = i ; 1
rBk.Sheets(1).Cells(i, 1) = Logrec
End If
Loop
.Close
End With
End Sub
すべての返信 (7)
2018年6月11日月曜日 1:17 ✅回答済み | 1 票
Windows 7 SP1, ADODB.Stream.6.0, Excel 2007で確認しましたが、BOM付き・BOM無し共に問題なく行単位で読めました。
とりあえず、以下の点を確認されてみては。
- 読み取った各行を全て各セルに出力するなどして、ReadTextがどのような文字列を返してきているか
- テキストファイルの改行がCRLFになっているか(バイナリエディタで開いて、0D 0Aを確認する)※ADODB.StreamではCRのみまたはLFのみは改行として認識されないようです。
2018年6月12日火曜日 0:31 ✅回答済み | 1 票
その UTF-8 ファイルの改行コードを確認してみてください。
ADODB.Stream 側での改行の切り替えは、LineSeparator プロパティで行えます。
このプロパティの既定値は adCRLF (=-1) で、VBA でいうところの vbCrLf (0D,0A) に相当します。
adCR (=&H0D) にすると、vbCr 改行(0D) 扱いで
adLF (=&H0A) にすると、vbLf 改行(0A) 扱いです。
この 3 種類以外の改行については、行単位であるとは認識されません。
また、複数の改行コードが混在しているようなファイルにも対応していません。
もしも改行コードの混在がありえる場合には、
.ReadText( adReadLine ) で行単位に読み取るのではなく、
.ReadText( adReadAll ) でファイル全体を読み取った上で
自前で改行コードの統一化や切り出しを行うようにします。
Dim allText As String
'ファイル全体を読み取り
allText = stm.Read(adReadAll)
'Replace 呼び出しを 3 回行うことで、
'Cr / CrLf / Lf が混在しているテキストを CrLf 改行に揃える
allText = Replace(allText, vbCrLf, vbLf, , , vbBinaryCompare)
allText = Replace(allText, vbCr, vbLf, , , vbBinaryCompare)
allText = Replace(allText, vbLf, vbCrLf, , , vbBinaryCompare)
'CrLf で区切って、一次元配列に変換
Dim lines() As String
lines = Split(allText, vbCrLf, , vbBinaryCompare)
2018年6月12日火曜日 4:03 ✅回答済み | 1 票
改行のチェックが済んでからの話ですが、
If toDay <= Left(Logrec, 10) Then
これはおかしいです。
(セルには自動で日付型に変換して入れてくれますが)
(文字列の段階での比較はうまくいかない思いますけど、、)
Dim var As Variant '追加
var = Left(Logrec, 10)
If IsDate(var)
If toDay <= CDate(var)
など。
2018年6月12日火曜日 5:28 ✅回答済み | 2 票
If toDay <= Left(Logrec, 10) Then
これはおかしいです。
(セルには自動で日付型に変換して入れてくれますが)
(文字列の段階での比較はうまくいかない思いますけど、、)
「書式がyyyy/mm/ddで、1桁の数値には前ゼロが必ず付いている」を前提とできるなら、文字列の比較で問題ないです。
2018年6月12日火曜日 6:04 ✅回答済み | 2 票
さらに言うと、Logrec 側と toDay 側の双方の書式が問題となりえますね。
今回の場合、変数 toDay は Date 型ですが、対する Left 関数は「内部処理形式 String のバリアント型」を返すため、日付型としての比較ではなく、文字列型としての比較処理が行われます。
暗黙の型変換によって、日付型が文字列型に変換される場合、その書式はコントロールパネルの地域設定に依存したものとなります。そのため、たとえば和暦モードに設定されている環境で実行した場合などは、予期していた物とは異なる結果になる可能性があります。
しかし UTF-8 なファイルの方は、コントロールパネル依存なわけではなく、固定フォーマットなはずです。できれば toDay 変数は String 型に変更しておき、Format 関数で明示的な書式指定を行うことをお奨めします。
2018年6月12日火曜日 7:43
一旦、すべて読込んで処理することにしました。
また、日付の比較についても、月と日は2桁の固定であることから、正常に処理することができました。
皆さんありがとうございます。
2018年6月12日火曜日 9:45 | 1 票
いまから書いてもいいのかなあ、、
そうなんですか、ガックリガックリ。
たしかにtoDay以前のものははじいてますね(ビックリ)。
(toDay以後と日付なしの行は通してますけれど。)
(2018-9-21とか、2019/11/9の日付でも大丈夫でした。)
("2005-5-7 発送方法" のように2個以上スペースを入れておく必要がありますが)