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

このQ&Aのポイント
  • EXCELのVBAにて巨大なファイルのデータを途中から読み込む方法がありますか?具体的には300万行ほどのCSVデータがありまして、50万行目のデータをスマートに取得したいと思っています。
  • 現在の方法では、50万行目までSKIPするのに数秒の時間がかかってしまいます。いきなり50万行目からのデータを取得するような効率的な方法はあるのでしょうか?
  • VBAで巨大なファイルの途中からの読み込みに関する効率的な手法やアプローチがあれば教えてください。
回答を見る
  • ベストアンサー

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

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

  • ベストアンサー
回答No.3

項目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万件データを扱うことはできます シートを使わずデータ処理を行うブックもあります 質問者は シートの行数を問題にしていません シーケンシャルであることも条件にしていません  できる できない は知識によって違います 最短 最適 は別の条件もあります

from2001
質問者

補足

大変的確な回答ありがとうございます! まさに求めていた手法でした。 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

その他の回答 (2)

回答No.2

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

  • imogasi
  • ベストアンサー率27% (4737/17068)
回答No.1

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

from2001
質問者

お礼

ご回答ありがとうございます。 imogasi様のご回答では「絶対無理」とのことでしたが、他の方が的確な回答をしてくださいました。 後学のためご参考にされることをお勧めします。 ありがとうございました。

関連するQ&A

  • VBScriptのOpenTextFileメソッドのようなことをJavaScriptで行いたい

    VBScriptの指定されたファイルを開き、ファイルを読み込んだりするOpenTextFileメソッドのようなことを JavaScriptを用いて行いたいんですがどのようにすればいいんでしょうか? できれば、以下ソースと対比したソースを張っていただけるとありがたいです。よろしくお願いします。 Sub OpenTextFileTest Const ForReading = 1, ForWriting = 2, ForAppending = 3 Dim fs, f Set fs = CreateObject("Scripting.FileSystemObject") Set f = fs.OpenTextFile("c:\testfile.txt", ForAppending,TristateFalse) f.Write "Hello world!" f.Close End Sub

  • VB6.0にて、CSVファイルを読み込もうとしているのですが、1行ずつ

    VB6.0にて、CSVファイルを読み込もうとしているのですが、1行ずつ読み込めません。 以下のコードで、Lineのメッセージボックスが表示されないのです。 どなたか教えていただけないでしょうか。よろしくお願いします。 'CSVファイル読み込み Sub Stream() Dim Line, Temp As Variant Dim objFSO As Object Dim objStream As Object Const ForReading = 1, ForWriting = 2, ForAppending = 3 Set objFSO = CreateObject("Scripting.FileSystemObject") Set objStream = objFSO.OpenTextFile(strDFpath & strDFname(1), ForReading, False) Temp = objStream.ReadAll MsgBox Temp '最後の行までループ Do Until objStream.AtEndOfLine - 1 <> True '1行読む Line = objStream.ReadLine MsgBox Line Loop objStream.Close Set objStream = Nothing Set objFSO = Nothing End Sub

  • CSVファイルの読み込み

    ASPの勉強をしています。 CSVファイルを読み込んでDBに登録していきたいのですが、 111,222,"aaa[改行]bbb","1,000",444,555 のようなデータがあったとすると、 「1,000」の桁区切りのカンマのせいで、 「1」 と 「000」に別れてしまいます。 これを防ぐプログラムを作りたいのですが、 わかる方よろしくお願いします。 現在はReadLineで1行ずつ読み込んでいます。 set ObjFS = CreateObject("Scripting.FileSystemObject") set Stream = ObjFS.OpenTextFile(Server.MapPath(FILENAME,1,false,0) ReadBuf = Stream.ReadLine

  • Csvから1行ずつ変数に格納するには;

    いつもお世話になっています。 次のようなcsvファイルがあります。 会員番号,パスワード,データ1,データ2,データ3 1234567,1111,1970/1/1,1990/4/1,A 1111111,1,1960/1/1,1985/4/1,AB ・ ・ ・ このcsvファイルをExcelのVBAで次のようなコードで読みとろうとしています。 Set fs = CreateObject("Scripting.FileSystemObject") Set f = fs.GetFile("csvファイル名") Set ts = f.OpenAsTextStream(1, -2) ssk = ts.readline readlineは1行だけ読み込むと覚えているのですが、なぜか変数sskにはすべての行が連結された状態で格納されてしまいます。 2回目以降のreadlineでは「ファイルにこれ以上データがありません。」と出ます。何か根本的に間違っているのでしょうか;; このようなcsvファイルを、正しく1行ずつ変数に格納する方法にはどのようなものがありますでしょうか。 よろしくお願いします。

  • CSVファイル

    CSVファイルを1行ずつ比較して読み込み、一致した行を別ファイルに記述していこうと思っています。 現在、csvファイルを読み込む所まで出来ています。 比較して別ファイルに記述する方法を教えて下さい。 もしくはアドバイスください。 【ファイルの中身】 "09/09/2005 0:00:00,aaa,bbb,ccc" 【比較条件】 当日の日付を取得し、年月日だけで比較する Dim objFSO ' FileSystemObject Dim objFile ' ファイル読み込み用 Set objFSO = WScript.CreateObject("Scripting.FileSystemObject") Set objFile = objFSO.OpenTextFile("c:\test.csv") Do while objFile.ReadLine <> ""         'IF文を記述(条件:日付)        '別ファイルに記述する Loop objFile.close Set objFileSystem = Nothing Set objFile = Nothing

  • csvファイルを読み込む方法について

    aspにてscvファイルを読み込む際、直接ファイル名を指定するとうまくいくのですが、ファイル名を変数で指定しようとすると、「ファイルが見つかりません」というエラーになってしまいます。どのように記述すれば良いでしょうか。お教えください。よろしくお願いいたします。 (例) 'OK Set objFS = CreateObject("Scripting.FileSystemObject") Set objText = objFS.OpenTextFile(Server.MapPath("aaa.csv"),1) 'NG fname = "aaa.csv" Set objFS = CreateObject("Scripting.FileSystemObject") Set objText = objFS.OpenTextFile(Server.MapPath(fname),1) また、 Set objText = objFS.OpenTextFile(Server.MapPath("""" & fname & """"),1) としてもダメでした。以上です。

  • ファイル書き込み

    out.csvファイルに追記していくにはどのように記述すればいいのでしょうか? アドバイス下さい。 Set objFSO = WScript.CreateObject("Scripting.FileSystemObject") Set objFile = objFSO.OpenTextFile("c:\test.csv") 'objFile.ReadLine Do While Not objFile.AtEndOfStream StrLine = objFile.ReadLine MyString = split(StrLine,",") ' msgbox Mid(MyString(0),2,10) ' MyString = split(objFile.ReadLine,",") if Mid(MyString(0),2,10) = "(PDH-CSV 4" then Set objWFile=objFSO.OpenTextFile("c:\out.csv",2,true) objWFile.write(StrLine) msgbox "!!!" end if ' if Mid(MyString(0),2,10) = DateString then Set objWFile=objFSO.OpenTextFile("c:\out.csv",2,true) objWFile.write(StrLine) ' 'msgbox Mid(MyString(0),2,10) msgbox "???" end if loop objFile.close Set objFSO = Nothing Set objFile = Nothing

  • VB6でCSVの取込をする

    VB6.0 でCSVの取り込みをしています。 Dim objFso As FileSystemObject Dim objTso As TextStream Dim データ As Variant Dim stArrayData() As String Set objFso = New FileSystemObject Set objTso = objFso.OpenTextFile(取込パス, ForReading) データ = objTso.ReadLine '配列に格納 stArrayData = Split(データ, ",") 'データの取得 データの取得 = stArrayData(0) stArrayData(0)で、データが取得できますが、 ダブルコーテーションが付加された状態で取得がしたいのですが、できません。。 今は、「000」で取得しているのを、 「"000"」で取得したいのです。 なお、取込むCSVをテキストで開くと、 ダブルコーテーションはついていません。 また、そもそも、取込む際に、ダブルコーテーションを付加する方法があるのでしょうか? それとも、取込んだ後に、ダブルコーテションを付加するのでしょうか? ご教授宜しくお願いします。

  • VBS 改行無しのファイル抽出方法

    いつもお世話になっております。 WindowsXP環境にある下記のようなVBSがあります。 コード------------------------------------------------------------------ path = "a.txt" Set FSO = WScript.CreateObject( "Scripting.FileSystemObject" ) '全行読み込み処理 (改行を1行単位として) Set f = FSO.OpenTextFile( path ) Do Until f.AtEndOfStream line = f.ReadLine() i_line = f.Line - 1 Loop WScript.Echo "全件数= " & i_line '最終行-5読み込み処理 Set f = FSO.OpenTextFile( path ) For i=1 To i_line - 6 f.SkipLine Next LAST5 = f.ReadLine() MOJI = Mid(LAST5,20,5) WScript.Echo "文字 = " & MOJI コード------------------------------------------------------------------ 上記VBSの簡単な流れは・・・ (1)改行で1行とみなす a.txt を全行取得。 (2)全件数を表示 (3)最終行から5行前の行まで移動。 (4)(3)の行から20文字からの5文字を取得。 (5)5文字を表示。 とこんな感じです。 しかし、これだと改行有のファイルにのみ有効で 改行無には対応出来ません。 例えば120文字で1行とみなすファイルでも同様の 取得がしたいのです。 ご存知の方がいれば、ご教授願いませんでしょうか? 何卒、宜しくお願い致します。

  • CSVファイルの読込

    Dim strTxt Set Obj = CreateObject("Scripting.FileSystemObject") Set ObjF = Obj.OpenTextFile(フルパス) strTxt = ObjF ObjF.Close 変数strTxtに、ファイルの内容を格納したいのですが、 どうも上手くいかないんです。 基本的に、どう記述すれば良いのでしょうか?

専門家に質問してみよう