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で質問しましょう!
似たような質問が見つかりました
- 電子レンジ・オーブン・トースター 電子レンジの非科学的(カルト的)動作の原因について考えられる理由を知りたい 8 2022/11/29 14:47
- Excel(エクセル) エクセルのVBAについて とあるサイトのコードを参考に、CSVの文字化けを直すVBAを作成しているの 7 2022/11/04 14:15
- Windows 10 数年前からWindows10 の Update ができないです。なぜですか? 7 2022/11/09 06:03
- Visual Basic(VBA) Excel VBA で End Subのところで「型が一致しません」のエラーとなります。 6 2022/07/27 19:58
- Visual Basic(VBA) VBA シート間の転記で、条件の追加コードの書き方について教えて下さい。 13 2023/02/26 09:31
- SEO googleサーチコンソールで、重複URLが多数発生、その修正方法について 2 2023/06/23 16:15
- Visual Basic(VBA) エクセルVBA 4 2022/05/14 00:51
- PHP PostgreSQLからCSV形式でエクスポートする際にカラム内の改行をとる方法 1 2023/02/22 10:05
- C言語・C++・C# C#のSystem.Windows.Media.Colorに関する質問です。 3 2022/05/18 11:51
- プリンタ・スキャナー キャノンmp490プリンター【エラー番号5400】で【プリンタートラブルが発生しました。電源を入れ直 2 2023/07/24 17:45
このQ&Aを見た人はこんなQ&Aも見ています
-
外出時に「待たせる妻」vs イライラする「待つ夫」は日本だけ?見習いたい海外事情
夫の家事参加に積極的なイメージのある海外でも、同様の事例はあるのか。結婚カウンセラーの佐竹悦子さんに伺ってみた。
-
VBAよりCSVファイルの任意の行を取得
その他(データベース)
-
エクセルVBA 大容量CSVファイルの読み込みが遅い
Visual Basic(VBA)
-
VBAでエクセルシートを更新(リフレッシュ)する方法を教えて下さい。
Excel(エクセル)
-
-
4
VBAでの100万行以上のデータの取り込み
その他(プログラミング・Web制作)
-
5
エクセルVBA 2千万行のCSVファイルを開きたい
Visual Basic(VBA)
-
6
Excelのメモリ(配列)の上限は2Gではないのか
Excel(エクセル)
-
7
メモリが不足しています(VBA)
Visual Basic(VBA)
-
8
Microsoft VBAで2GBを超えるファイルサイズのバイナリデータを読み込みたい。
Visual Basic(VBA)
-
9
VBAでブックを非表示で開いて処理して閉じる方法
Excel(エクセル)
-
10
vba メモリーリーク
Visual Basic(VBA)
-
11
ODBCの接続に失敗しました(3146)について
その他(Microsoft Office)
-
12
エクセルでエラーが出て困っています。
Excel(エクセル)
-
13
ExcelVBA:パブリック オブジェクト モジュール…というエラーの対処法
Visual Basic(VBA)
-
14
ExcelVBAを使って、値がある場合は作業を繰り返し実行するプログラムを作成したい。
Visual Basic(VBA)
-
15
CloseとDisposeの違い
Visual Basic(VBA)
-
16
エクセルVBAで実行時エラー7、メモリー不足が出ます。
その他(Microsoft Office)
-
17
エクセルVBAでシートモジュールでのパブリック変数
Excel(エクセル)
-
18
SQLPLUSで結果を画面に表示しない
Oracle
-
19
Cellsのかっこの中はどっちが行と列なの?
Visual Basic(VBA)
-
20
画面ロック中にプログラム実行できないでしょうか
Windows Vista・XP
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
VBAのコマンドボタンの文字列の...
-
Excel VBAからBeckyを起動して...
-
C#の改行について
-
JavaMail,本文中の改行について
-
ToolTipTextの改行はできないの...
-
ソースコードの1行が長いとき...
-
delphi でのコード上でTab を入...
-
delphiにて●文字列置換で勝手に...
-
VBAのINPUTBOX内で、改行する方法
-
awkで改行を除いて文字列を抜き...
-
【PHP】変数内の文字列の改行を...
-
改行コード(CR/LF)の設...
-
エスケープ文字の復帰(¥r)と...
-
xmlファイル(UTF-8)への書き...
-
JAVA System.out.println の ...
-
texのchapterが改行される
-
○個ずつ改行
-
エクセル セルの中の改行を消...
-
C++で空Enterの入力を判...
-
ファイルから読み取った改行文...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
VBAのコマンドボタンの文字列の...
-
ソースコードの1行が長いとき...
-
エスケープ文字の復帰(¥r)と...
-
COBOLの改行
-
改行について
-
最終行の改行について
-
C++で空Enterの入力を判...
-
【VBA】エクセルで最後の不要な...
-
jsp 改行コードで改行させて表...
-
C++でのCRLFについて
-
ファイルから読み取った改行文...
-
テキストファイルから改行コー...
-
ExcelVBAでメールを作成してメ...
-
awkで改行を除いて文字列を抜き...
-
エクセルVBA 文字列領域が不足...
-
VBAでCSVをExcelに取り込む時に...
-
コンボボックスの項目中に改行を
-
JavaDoc コメントの改行について
-
Excel VBAからBeckyを起動して...
-
改行を読み飛ばす
おすすめ情報