

http://oshiete.goo.ne.jp/qa/8769403.html
上記参照URLと同じ現象が発生しています。エラー発生場所もLine, 大容量CSVを開く際に発生します。
①改行コードがLFの場合に発生するとありますが、確認方法はどうすればいいのでしょうか?
②対策はあるのでしょうか?

No.4ベストアンサー
- 回答日時:
#3です。
前回処理時間がかかりすぎるので無理と回答しましたが、約10Kバイト単位で一気に読込、処理するように変えました。
1000万行が約5分以内で処理できましたので、それでよければ試してみてください。
前提として、以下のサイトを参考にしています。
https://support.microsoft.com/ja-jp/kb/189981
標準モジュールとクラスモジュールがありますが、
クラスモジュール(Random)は、サイトの内容をそのままコピー&ペーストして作成します。
ただし、読込のメソッドは、以下のメソッド(ReadBytes2)を追加し、それを使います。
-------------------------------
Public Function ReadBytes2(ByVal ByteCount As Long, ByRef ReadBuff() As Byte) As Long
Dim BytesRead As Long
If hFile = INVALID_HANDLE_VALUE Then
RaiseError W32F_FILE_ALREADY_CLOSED
End If
ReadFile hFile, ReadBuff(LBound(ReadBuff)), ByteCount, BytesRead, 0
ReadBytes2 = BytesRead
End Function
--------------------------------
標準モジュールは、以下のようになります。
--------------------------------------------
Option Explicit
Dim F As Random
Dim buff(10240) As Byte
Dim restLen As Long
Dim getLen As Long
Sub Macro2()
Dim readcount As Long
Dim st As Single
Dim et As Single
Dim lastline As Boolean
Dim line As String
Set F = New Random
F.OpenFile "c:\\goo\\File1000man.txt"
restLen = 0
st = Timer
readcount = 0
Do While True
line = MyReadLine(lastline)
If lastline = True Then Exit Do
readcount = readcount + 1
'Debug.Print line
Loop
F.CloseFile
Set F = Nothing
et = Timer
Debug.Print "時間(秒)=" + CStr(et - st)
Debug.Print "読込件数=" + CStr(readcount)
End Sub
Public Function MyReadLine(ByRef lastline As Boolean) As String
Dim rec As Byte
Dim recs() As Byte
Dim cnt As Long
Dim line As String
cnt = 0
line = ""
Do While True
rec = MyGetByte()
If rec = 0 Then
lastline = True
MyReadLine = ""
Exit Function
End If
' LF(0x0A)の場合、1行の区切りとし、ループ終了
If rec = &HA Then Exit Do
' CR(0x0D))以外は、バッファに保存
If rec <> &HD Then
ReDim Preserve recs(cnt)
recs(cnt) = rec
cnt = cnt + 1
End If
Loop
line = StrConv(recs, vbUnicode)
MyReadLine = line
End Function
Public Function MyGetByte() As Byte
If restLen = 0 Then
getLen = 0
restLen = F.ReadBytes2(10240, buff())
If restLen < 1 Then
'0x00のデータは無いことが前提
MyGetByte = 0
Exit Function
End If
End If
MyGetByte = buff(getLen)
getLen = getLen + 1
restLen = restLen - 1
End Function
---------------------------------------------
実行結果
時間(秒)=276.3906
読込件数=10000000
不明点があれば、補足してください。
ありがとうございます。
クラスの使用は初めてです。Hello Worldだけ試しに作ってみて、実使用をどうしようか迷っていたところです。参考にさせて下さい。こちらの方法でも4~5分で終わるようですね。DOSプロンプトを使わないので終了監視せずに使えるのが便利そうです。
No.5
- 回答日時:
こんばんは。
#2の回答者です。
>ストリーム系のツールか、コマンド・プロンプトで考えなくてはなりません。
#2のこの自分の言葉に引っかかっていていたのですが、最初、sed (ストリームエディタ)やPerl が浮かびましたが、探していれるのも面倒ですから、nkf.exe のことを思い出しました。会社で、これを使えるのかどうかは別として、変換には、1,000万行でも、せいぜい十秒程度です。
nkf -Lw myLF.csv > myCrLf.csv
とすればよいです。これは、VBAでも、Shell で取り込めます。nkf が使えればですが。
command prompt というよりも、DOSでは、more を通せば、LF は、CRLF になるそうですが、あくまでも、s_jis のファイルに限るそうです。
http://www.atmarkit.co.jp/ait/articles/1301/25/n …
http://osksn2.hep.sci.osaka-u.ac.jp/~taku/osx/cr …
ちなみに、 "ADODB.Stream" で、やってみましたが、20分経っても終わらないです。それに、一度全部読んでいますから、これではダメでしょうね。
http://winofsql.jp/VA003334/infoboard_page.php?m …
ありがとうございます。
moreを使ってみましたが、1時間で1%程度しか終わらず中断しました。
nkd, sedはどちらも無いため、使用可否を調べてます。正直言って10秒は魅力です。

No.3
- 回答日時:
#1です。
>VBAとしての対処は無理でしょうか。①はともかく、②は作成中のVBAに組み込むことになります。サイズは5列×1000万行程度です。
VBAで行うことは、難しいでしょう。
要望としては、改行=CR+LF の場合と 改行=LF の場合のどちらでも、処理できるようにしたい。
ということかと思います。
処理の方法としては、1行単位での読み込みを既存の関数(Line)に任せるのではなく、自前でこれを出来るように
改造することになります。
つまり、バイナリーモードで読込、1バイトずつ処理し、LF検知時に、1行として扱うことになります。(CRは読み捨てる)
原理的には可能ですが、1000万行の場合、時間がかかりすぎます。
以下のソースは、上記の実装例です。(MyReadLineで1行読込)
1行約60バイトで10万行のデータ読み込むと私の環境で約27秒かかりました。
1000万行だと約45分になります。
----------------------------------------------
Option Explicit
Sub MacroRead()
Dim st As Single
Dim et As Single
Dim n As Integer
Dim line As String
Dim lastline As Boolean
Dim readcount As Long
st = Timer
n = FreeFile
Open "C:\\goo\\file1000.txt" For Binary As #n
readcount = 0
Do While True
line = MyReadLine(n, lastline)
If lastline = True Then Exit Do
readcount = readcount + 1
'Debug.Print line
Loop
Close #n
et = Timer
Debug.Print "時間(秒)=" + CStr(et - st)
Debug.Print "読込件数=" + CStr(readcount)
End Sub
Public Function MyReadLine(ByVal n As Integer, ByRef lastline As Boolean) As String
Dim rec As Byte
Dim recs() As Byte
Dim cnt As Long
Dim line As String
cnt = 0
line = ""
Do While True
Get #n, , rec
'読み込み完了の場合はループ終了
If EOF(n) Then
lastline = True
Exit Do
End If
' LF(0x0A)の場合、1行の区切りとし、ループ終了
If rec = &HA Then Exit Do
' CR(0x0D))以外は、バッファに保存
If rec <> &HD Then
ReDim Preserve recs(cnt)
recs(cnt) = rec
cnt = cnt + 1
End If
Loop
line = StrConv(recs, vbUnicode)
MyReadLine = line
End Function
--------------------------------------------------------
実行結果
時間(秒)=27.48828
読込件数=100000
従って、(45分以上かかっても問題ないなら別ですが)他のツールでLFをCR+LFに変換し、そのデータを
現行のVBA処理で行うほうが、現実的かと思います。
No.2
- 回答日時:
こんにちは。
今回、少し甘く考えていましたが、
http://www.moug.net/tech/exvba/0060089.html
LFコードで改行したファイルを読み込む
ここを読んで気が付きました。(別に開かなくて話だけでも良いです)
Sample2, Sample3 をやってみて、両方共ほとんど一括で読み込んでいます。Variant 型やString型は、限界が、2GB ですが、それを越えているのかもしれません。
http://d.hatena.ne.jp/tobiaki/20061107/p1
■[コンピュータ][VBA]「Line Input # ステートメント」の仕様
》ファイルが巨大だった場合、メモリに収まらずにエラーとなってしまうのです。*1
》こうなるとVBAだけで対応するのは難しく、事前にファイルの改行コードを変換しておくしかありません。
ここらは、純粋にVBAでは無理かもしれません。
VBAでというお望みは、常時、それが発生するからではないでしょうか。書き込みの中では、Unix/Linux 系のデータは、全部そういう方式ですから、本来は出力側から直してもらう、というのも一案かもしれません。
もしくは、ストリーム系のツールか、コマンド・プロンプトで考えなくてはなりません。
>5列×1000万行程度です。
ということは、まず、Excelでは、オーバーしてしまうようですが、処理だけにしますし、行の認識があれば、切り取りもできます(LFは行の認識がWin側ではできません)。
http://58391.diarynote.jp/200805101826280000/
ここを参考にして作ってみました。
'//
Sub ReplaceLfTest()
Dim objFS As Object
Dim oFile As Object
Dim tmpFile As Object
Dim buf As Variant
Dim fileName As String
Dim tmpF As String
Const ForReading As Long = 1
Const ForWriting As Long = 2
fileName = xFILENAME
tmpF = "$Tmp.csv" '臨時ファイル名
Set objFS = CreateObject("Scripting.FileSystemObject")
Set oFile = objFS.OpenTextFile(fileName, ForReading)
Set tmpFile = objFS.OpenTextFile(tmpF, ForWriting, True)
Do While Not oFile.AtEndOfStream
buf = oFile.ReadLine
buf = Replace(buf, vbLf, "", , , vbBinaryCompare)
buf = buf & vbCrLf
tmpFile.Write buf
Loop
oFile.Close
tmpFile.Close
MsgBox "終了"
End Sub
'///
しかし、場合によっては、タイトルのように文字領域が不足するという結果になるかもしれません。
念の為に、添付画像は、今回のバイナリエディタで確認した結果です。

後追いですが、動作確認しました。
このマクロとNo4がほぼ同等の速さで3~4分でした。No5が最速ですが、マクロ全体の所要時間が長いため今回はnkfは見送りました。

No.1
- 回答日時:
>①改行コードがLFの場合に発生するとありますが、確認方法はどうすればいいのでしょうか?
方法1:秀丸(テキストエディタ)で、そのファイルを開き、
ファイルー>エンコードの種類
をクリックします。
改行=CR+LFと表示されるか、
改行=LFと表示されるかのどちらかかと思います。
改行=LFと表示されれば、改行コードがLFです。
秀丸がない場合は下記からダウンロードしてください。(お試し版が使用可能)
http://hide.maruo.co.jp/software/hidemaru.html
方法2:バイナリエディタでCSVファイルを開き
改行位置に0D0A(16進数)があれば改行コードはCR+LF
改行位置に0A(16進数)があれば改行コードはLF
となる。
バイナリエディタの1例としてstirlingがあります。下記からダウンロード可能
http://www.vector.co.jp/download/file/win95/util …
>②対策はあるのでしょうか?
改行コードがLFのであれば、改行コードをCR+LFに変える。
変える方法としては、
方法1:秀丸で、ファイルー>エンコードの種類をクリックして
改行コードが表示されますが、そこで改行コード=CR+LF
を選択し、保存すると、改行コードがCR+LFに変換されます。
方法2:改行コード 変換 で検索を行ってください。
改行コードを変換するツールがいくつか表示されますので、
それを使って下さい。(以下は参考です)
http://www.vector.co.jp/soft/winnt/util/se406512 …
ありがとうございます。
VBAとしての対処は無理でしょうか。①はともかく、②は作成中のVBAに組み込むことになります。サイズは5列×1000万行程度です。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
-
VBAよりCSVファイルの任意の行を取得
その他(データベース)
-
ACCESSのVBAで[Split]について
その他(プログラミング・Web制作)
-
Microsoft VBAで2GBを超えるファイルサイズのバイナリデータを読み込みたい。
Visual Basic(VBA)
-
-
4
Access VBAから使用したExcelプロセスを閉じる方法について
Visual Basic(VBA)
-
5
VBAで文字を反映させると255文字の制限になってしまいます。
Visual Basic(VBA)
-
6
VBA 大きなtxtテキストファイルを開く方法
Excel(エクセル)
-
7
アクセスのクエリでSplit関数は使えないのですか
Access(アクセス)
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
VBAのコマンドボタンの文字列の...
-
VBAでCSVをExcelに取り込む時に...
-
ラベル(スタティックテキスト)...
-
マクロでセル内の改行を削除す...
-
バーコード入力と手入力の判断...
-
C++で空Enterの入力を判...
-
CSVファイルの改行コード判別
-
1行ごとに取得して、その改行...
-
FORTRANで作成したテキストファ...
-
C#における改行を含む文字の探索
-
Excel VBS、ADODB.Streamで改行
-
COBOLの改行
-
文字列型変数に1024を超えた文...
-
ButtonコントロールのT...
-
ダイアログにおける改行
-
【VBA】エクセルで最後の不要な...
-
Objective-c 改行コードによる...
-
改行コード2種類を混在させたい
-
文の改行
-
FTP受信する際、改行コードをは...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
VBAのコマンドボタンの文字列の...
-
エスケープ文字の復帰(¥r)と...
-
ソースコードの1行が長いとき...
-
COBOLの改行
-
C++で空Enterの入力を判...
-
Excel VBAからBeckyを起動して...
-
【VBA】エクセルで最後の不要な...
-
エクセルVBA 文字列領域が不足...
-
テキストボックス行の桁数を制...
-
秀丸の正規表現で複数行にわた...
-
C言語の標準入力で改行しない方法
-
VBAでCSVをExcelに取り込む時に...
-
改行コード(CR/LF)の設...
-
グレープシティのSPREAD...
-
改行について
-
1行ごとに取得して、その改行...
-
ラベル(スタティックテキスト)...
-
コンボボックスの項目中に改行を
-
ファイルから読み取った改行文...
-
C# DataGridViewのセルを改行禁...
おすすめ情報