こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

VBAで巨大なファイルの途中からの読み込み

こんにちは。
EXCELのVBAにて巨大なファイルのデータを途中から読み込む方法がございましたらご教授いただきたいと思っています。

具体的には300万行ほどのCSVデータがありまして
たとえば、50万行目のデータを読み込みたい場合下記のようにすることにより、データの取得は可能なのですが、50万行目までSKIPするのに数秒の時間がかかってしまいます。いきなり50万行目からのデータを取得するようなスマートな方法は存在するのでしょうか。

よろしくお願いいたします。

Const ForReading = 1, ForWriting = 2, ForAppending = 3
Dim fs, f
Set fs = CreateObject("Scripting.FileSystemObject")
Set f = fs.OpenTextFile("C:\tmp.csv", ForReading, 0)

For w = 0 To 500000
f.skipline
Next

Debug.Print f.readline

f.Close

投稿日時 - 2007-10-07 00:21:27

QNo.3407338

困ってます

質問者が選んだベストアンサー

項目1 連番
項目2 名前
項目3 住所
3列の300万行データなら




'=========================
myDIR = "c:\happy"
myCSV = "ADO_EXCEL.csv"
mySQL = "SELECT * FROM " & myCSV & " WHERE 連番='500000'"
'=========================

Set myDB = CreateObject("ADODB.Connection")
myDB.Open "Driver={Microsoft Text Driver (*.txt; *.csv)};" & _
"DBQ=" & myDIR & ";" & "ReadOnly=1"
Set myRS = myDB.Execute(mySQL)
Do Until myRS.Eof = True
Msgbox "項目1 連番 :" & myRS(0)
Msgbox "項目2 名前 :" & myRS(1)
Msgbox "項目3 住所 :" & myRS(2)
myRS.MoveNext
Loop
myRS.Close : myDB.Close : Set myRS = Nothing : Set myDB = Nothing


http://www.jtw.zaq.ne.jp/kayakaya/new/kihon/text/db_sql_kihon.htm
http://itpro.nikkeibp.co.jp/article/COLUMN/20070529/272836/
http://itpro.nikkeibp.co.jp/article/lecture/20061211/256500/
Excelで扱うことができる限界は 
シートの行数が決めるのではありません
使う人の知識がExcelでできることを決定します
Excel2000でも100万件データを扱うことはできます
シートを使わずデータ処理を行うブックもあります
質問者は シートの行数を問題にしていません
シーケンシャルであることも条件にしていません 
できる できない は知識によって違います
最短 最適 は別の条件もあります

投稿日時 - 2007-10-08 09:09:40

補足

大変的確な回答ありがとうございます!
まさに求めていた手法でした。
CSVにもSQLを使うことができるんですね。知りませんでした。
これは大変便利です。しかもかなり高速に動作しました。

私の利用したいCSVにはヘッダーが存在しませんでしたので、少し調べてみました。
HDR=No と指定することにより、フィールドをF1、F2などとして利用できると書いてあったのですが
Microsoft Text Driver では正常に動作しませんでした。
Microsoft.Jet.OLEDB.4.0 を利用することにより動作しました。

参考まで正常に動作したコードを書いておきます。

'=========================
myDIR = "C:\temp"
myCSV = "test.csv"
mySQL = "SELECT TOP 2 * FROM " & myCSV & " WHERE F2 = '4034';"
'=========================

Set rs = CreateObject("ADODB.Recordset")
Con = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & myDIR & ";" & _
"Extended Properties=""text;HDR=No;FMT=Delimited;"";"

rs.Open mySQL, Con, 0

Do Until rs.EOF = True
MsgBox "項目1 :" & rs(0)
MsgBox "項目2 :" & rs(1)
rs.MoveNext
Loop

rs.Close: Set myRS = Nothing

投稿日時 - 2007-10-09 00:15:37

このQ&Aは役に立ちましたか?

1人が「このQ&Aが役に立った」と投票しています

回答(3)

ANo.2

http://www.happy2-island.com/vbs/cafe02/capter00803.shtml
SQLを使うことで 目的のレコードを抽出することができます
できれば レコードにそれぞれ最初から連番を付けて
その連番で50万行目を呼び出せば 1件だけ表示できます
この方法なら他の条件での検索もできるので便利です
分からなければ サンプルを用意します 補足してください

投稿日時 - 2007-10-08 08:36:29

ANo.1

エクセルと言っているが、エクセルやエクセルVBAと関係を持たせるのは無理です。たとえ2007でも。制限行数をオーバーしてます。
エクセルだから早くできるかも知れないと想像するとことは、ディスクの読み書きの早さで、MS社のエキスパートだから特別のテクニックを弄していると思うのかもしれないが、不明です。
ですからプログラムはVBでの方法ということになるが、CSVファイルはレコード(各行に当たる)長が一定している保証はないので、順次読むしかなく、50万件目から、あるいは番号500001から処理をいきなり始めるなど絶対無理です。
前もって固定長でランダム読み出しのファイル形式の場合は、可能です。
後尾にスペースを無理に持たせて一定長のレコードを作る手はあるかもしれないが、まあそうはしませんね。
ーー
アクセスでも、「量的に」可能かどうかわかりませんが、エクセル
VBAより可能性はありそう。
ーー
シーケンシャル読み出し
ランダム読み出し
ファイル構造
各種データベース
などを勉強して考えてください。
ーー
時代につれ、ディスクの読み取りスピードアップがなされ、それが寄与するが、今日明日のことにならない。
ーー
50万行を即時に処理し無ければならない業務とはどんなものかな。
>数秒の時間がかかってしまいます
数秒ですむというのも信じがたいが、それが辛抱できないのでしょうか。
何か初心者が思いついた一本線のロジックでつっ走っているような
印象なんだが。
ディスクからメモリに読み込まないと50万件目はわからないし、
CSVファイルは、順読み出ししか方法がないし、VBなど言語やデータ処理ソフトの中でも、質問の方法は単純で早い方法とおもう。
ーー
この処理はどういう場面で出てくるのか、問い合わせの都度か、分析などして数回限りで終るのか書いてないのも、前もって別ファイルを処理できる機械が与えられるのか書いてないのも片手落ちです。
ただし
繰り返し問い合わせなどがあるので、前もって検索などに適したファイル構造にCSVを変換しておき
 (1)前もって時間を使いー>問い合わせ時に回答が早い
その回はデータは全体の1単位しか使わない。
 (2)1回・数回限り
 (3)定例バッチ処理(応答・完了処理に時間を取れる)
データは通常全部を対象にする。
 (4)毎回CSVファイルから処理する
などあるが、(1)はデータベースソフトを使って、プロの領分です。

投稿日時 - 2007-10-07 09:20:21

お礼

ご回答ありがとうございます。
imogasi様のご回答では「絶対無理」とのことでしたが、他の方が的確な回答をしてくださいました。

後学のためご参考にされることをお勧めします。

ありがとうございました。

投稿日時 - 2007-10-09 00:27:14

あなたにオススメの質問