• ベストアンサー

VBAでの100万行以上のデータの取り込み

どなたかご教示お願いいたします。 VBAで100万行以上のCSVデータの取り込みは可能でしょうか? 初心者なのでファイルを開いてセルに入れてから範囲を指定し配列に 取り込み処理しておりましたが100万行以上だとデータがシートから出てしまいます。 なのでエクセルに展開せずに配列に取り込むなどということはできるのでしょうか? もし可能であればあつかましいのですが、A列の120万行データを配列に取り込むサンプルをご教示いただけるとありがたいのですが・・・ よろしくお願いいたします。

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

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

6割程度出来たかも? データ数180万、項目数8個、最大・最少を求めるのは1項目、 100データ区切りで試した結果。 5分。 200データ区切りだと 4分。 最初の30秒ほど応答なし状態ですがその後にシート転記が始まりました。 700万だとExcelが落ちる可能性有りです。 ただ、まだ確認したいことがありますのでコードは差し控えます。 時間軸の項目名と書式(例 15:30:25 のようなもの)。 時間軸のデータは重複があり得ますか。 何の最大値・最小値なのでしょう?もしかして時間軸を除く16項目。 もしかして、200区切りでその範囲内なら時間軸の値は同じ? (でないと16項目の最大・最少を求めても意味ないですよね) 200区切りで、もし一部分でも200に満たないものがあった場合に 考慮しないで常に200区切りとして処理しても構わない。 呑み込みが悪くてすみません。 出来ればデータを1行目から数行提示してもらえると助かります。 例えば3データ区切とした場合 時間軸|項目1|項目2|・|項目16 1:01:01  10   20    30 1:01:01  20   50    40 1:01:01  15   80    10 1:01:02  90   60    10 1:01:02  20   50    40 1:01:02  15   80    50 ↓ 1:01:01  20   80    40 1:01:01  10   20    10 1:01:02  90   80    50 1:01:02  15   50    10 ということでしょうか? 横の方が良いのか 1:01:01 20/10  80/20  40/10 1:01:02 90/15  80/50  50/10 つまり、 時間軸が大体200区切りで値が同じ その中でそれぞれの項目の最大・最少なら単純なのですけど。 冒頭のデータ量で2分程度でした。 (3年前の中堅スペックのPCです) 700万行だとやってみないことには…。 ヘッダー(タイトル行)は120も700のモノも同じ でデータ部分が異なるだけ? bin-chan さんにお任せして敵前逃亡しようかな。。。

tomomaki168
質問者

お礼

大変お世話になっております。 ご回答感謝いたします。 データの並びは,時間,ch1,ch2,ch3,ch4,・・・・・ 欲しい情報としては200行毎の最大値と最小値とその行番号です 具体的にいうと 1列目に通し番号 2列目にch1の最大値行番号 3列目にch1の最大値 4列目にch1の最小値行番号 3列目にch1の最小値 5列目にch2の最大値行番号 6列目にch2の最大値 7列目にch2の最小値行番号 8列目にch2の最小値・・・・・というかんじです 下記が見やすいように4列以降を消した生データです。 "ID番号","DCS-100A" "タイトル","中幹線J線残存強度試験H25年度" "試験日時","2014/02/05","15:26:43" "測定チャンネル数",16 "ディジタル入力","OFF" "サンプリング周期(Hz)",100 "データ/ch",7163735 "測定時間(sec)",71637.4 "チャンネル名称","素線01","素線02","素線03","素線04" "チャンネル No","CH01","CH02","CH03","CH04" "レンジ",50000,50000,50000,50000 "校正係数",1.0000,1.0000,1.0000,1.0000 "オフセット",0.0000,0.0000,0.0000,0.0000 "単位","με","με","με","με" 459,-1002,-1125,-1063,-981 460,-803,-878,-825,-700 461,305,186,303,206 462,-1220,-975,-1061,-709 463,-1130,-894,-989,-572 464,-2366,-1813,-2030,-1305 465,-1952,-1413,-1583,-958 466,-1238,-1263,-1009,-875 467,-1341,-1008,-1095,-641 468,-1056,-788,-861,-514 469,-1308,-994,-1042,-645 470,-311,-242,-238,-109 471,-673,-592,-539,-369 472,-633,-492,-534,-289 473,-683,-569,-567,-327 474,-1141,-892,-916,-572 こんな感じで800万行(1GBくらい)続きます

その他の回答 (6)

  • bin-chan
  • ベストアンサー率33% (1403/4213)
回答No.6

またまたすみません。 レコード件数をカウントアップする場所の前にEndSelectが必要でした。 大小比較を文字列で行ってます。数値であれば、比較のIF文を工夫してください。 最小値と最大値、それぞれ時間が必要でしたか? sub CSV読み込み()  '--Sheet1を用います。  '--セルA1に、パスを含むファイル名を入力 ex: C:\20140224\LogData.csv  '--セルA2に、見出し行数を入力 ex: 5  '--セルA3から右へ、ブロックNo.(200件毎), 時間軸、列1の最小値、列1の最大値、・・・、列20の最小値、列20の最大値  '--セルA4から下をデータ行とします。  '--対象ファイルのレコード数が、セルA2の見出し行数以下だとエラーです  dim nレコード件数 as long  dim n行 as long  dim n添え字 as long  dim str行バッファ as string  dim str配列() as string  dim n配列件数 as long  dim nFileNo as long  dim strファイル as string  'これが無いと、とても遅い  application.screenupdating = false  nFileNo = freefile()  strファイル = Worksheets("Sheet1").Range(A1)  open strファイル for input as #nFileNo  for n添え字 = 1 to Worksheets("Sheet1").Range(A2)   line input #nFileNo, str行バッファ  next n添え字  nレコード件数 = 0  n行=3  while not(eof(nFileNo))   line input #nFileNo, str行バッファ   str配列() = split(str行バッファ, ",")   n配列件数 = ubound(str配列())      select case (nレコード件数 mod 200)   case 0    ’200件中の1レコード目の値を最小値・最大値に設定する    n行 = n行 + 1    Worksheets("Sheet1").Range(A1).offset(n行, 0) = (nレコード件数 \ 200) + 1    Worksheets("Sheet1").Range(A1).offset(n行, 1) = str配列(0)    for n添え字 = 1 to n配列件数     Worksheets("Sheet1").Range(A1).offset(n行, n添え字 * 2 ) = str配列(n添え字)     Worksheets("Sheet1").Range(A1).offset(n行, n添え字 * 2 + 1) = str配列(n添え字)    next n添え字   case else    ’200件中の2レコード目以降の値を最小値・最大値と比較する    for n添え字 = 1 to n配列件数     if Worksheets("Sheet1").Range(A1).offset(n行, n添え字 * 2 ) > str配列(n添え字) then      ’最小値を更新      Worksheets("Sheet1").Range(A1).offset(n行, n添え字 * 2 ) = str配列(n添え字)     end if     if Worksheets("Sheet1").Range(A1).offset(n行, n添え字 * 2 + 1) < str配列(n添え字) then      ’最大値を更新      Worksheets("Sheet1").Range(A1).offset(n行, n添え字 * 2 + 1) = str配列(n添え字)     end if    next n添え字   End select   nレコード件数 = nレコード件数 + 1  wend  close  application.screenupdating = true end sub

tomomaki168
質問者

お礼

お世話になります。 とりあえず動く状態まで移植できました。 ダミーデータは動きました。 当事者化は帰ってしまったので、明日データをもらって動かしてみます。 なにはともあれ本当にありがとうございました!!

  • bin-chan
  • ベストアンサー率33% (1403/4213)
回答No.5

さっそくですみません。 レコード件数をカウントアップする場所がおかしいので訂正。 sub CSV読み込み()  '--Sheet1を用います。  '--セルA1に、パスを含むファイル名を入力 ex: C:\20140224\LogData.csv  '--セルA2に、見出し行数を入力 ex: 5  '--セルA3から右へ、ブロックNo.(200件毎), 時間軸、列1の最小値、列1の最大値、・・・、列20の最小値、列20の最大値  '--セルA4から下をデータ行とします。  '--対象ファイルのレコード数が、セルA2の見出し行数以下だとエラーです  dim nレコード件数 as long  dim n行 as long  dim n添え字 as long  dim str行バッファ as string  dim str配列() as string  dim n配列件数 as long  dim nFileNo as long  dim strファイル as string  'これが無いと、とても遅い  application.screenupdating = false  nFileNo = freefile()  strファイル = Worksheets("Sheet1").Range(A1)  open strファイル for input as #nFileNo  for n添え字 = 1 to Worksheets("Sheet1").Range(A2)   line input #nFileNo, str行バッファ  next n添え字  nレコード件数 = 0  n行=3  while not(eof(nFileNo))   line input #nFileNo, str行バッファ   str配列() = split(str行バッファ, ",")   n配列件数 = ubound(str配列())      select case (nレコード件数 mod 200)   case 0    n行 = n行 + 1    Worksheets("Sheet1").Range(A1).offset(n行, 0) = (nレコード件数 \ 200) + 1    Worksheets("Sheet1").Range(A1).offset(n行, 1) = str配列(0)    for n添え字 = 1 to n配列件数     Worksheets("Sheet1").Range(A1).offset(n行, n添え字 * 2 ) = str配列(n添え字)     Worksheets("Sheet1").Range(A1).offset(n行, n添え字 * 2 + 1) = str配列(n添え字)    next n添え字   case else    for n添え字 = 1 to n配列件数     if Worksheets("Sheet1").Range(A1).offset(n行, n添え字 * 2 ) > str配列(n添え字) then      Worksheets("Sheet1").Range(A1).offset(n行, n添え字 * 2 ) = str配列(n添え字)     end if     if Worksheets("Sheet1").Range(A1).offset(n行, n添え字 * 2 + 1) < str配列(n添え字) then      Worksheets("Sheet1").Range(A1).offset(n行, n添え字 * 2 + 1) = str配列(n添え字)     end if    next n添え字    nレコード件数 = nレコード件数 + 1  wend  close  application.screenupdating = true end sub

  • bin-chan
  • ベストアンサー率33% (1403/4213)
回答No.4

#2です。EXCEL環境が無いので未テスト。おかしい場合はすぐ教えてください。 以下を適当なマクロ付きブック(xlsm)に貼り付けてください。 sub CSV読み込み()  '--Sheet1を用います。  '--セルA1に、パスを含むファイル名を入力 ex: C:\20140224\LogData.csv  '--セルA2に、見出し行数を入力 ex: 5  '--セルA3から右へ、ブロックNo.(200件毎), 時間軸、列1の最小値、列1の最大値、・・・、列20の最小値、列20の最大値  '--セルA4から下をデータ行とします。  '--対象ファイルのレコード数が、セルA2の見出し行数以下だとエラーです  dim nレコード件数 as long  dim n行 as long  dim n列 as long  dim n添え字 as long  dim str行バッファ as string  dim str配列() as string  dim n配列件数 as long  dim nFileNo as long  dim strファイル as string  dim n見出し件数 as long  'これが無いと、とても遅い  application.screenupdating = false  nFileNo = freefile()  strファイル = Worksheets("Sheet1").Range(A1)  open strファイル for input as #nFileNo  for n添え字 = 1 to Worksheets("Sheet1").Range(A2)   line input #nFileNo, str行バッファ  next n添え字  nレコード件数 = 0  n行=3  while not(eof(nFileNo))   line input #nFileNo, str行バッファ   str配列() = split(str行バッファ, ",")   n配列件数 = ubound(str配列())      select case (nレコード件数 mod 200)   case 0    n行 = n行 + 1    Worksheets("Sheet1").Range(A1).offset(n行, 0) = (nレコード件数 \ 200) + 1    Worksheets("Sheet1").Range(A1).offset(n行, 1) = str配列(0)    for n添え字 = 1 to n配列件数     Worksheets("Sheet1").Range(A1).offset(n行, n添え字 * 2 ) = str配列(n添え字)     Worksheets("Sheet1").Range(A1).offset(n行, n添え字 * 2 + 1) = str配列(n添え字)    next n添え字   case else    for n添え字 = 1 to n配列件数     if Worksheets("Sheet1").Range(A1).offset(n行, n添え字 * 2 ) > str配列(n添え字) then      Worksheets("Sheet1").Range(A1).offset(n行, n添え字 * 2 ) = str配列(n添え字)     end if     if Worksheets("Sheet1").Range(A1).offset(n行, n添え字 * 2 + 1) < str配列(n添え字) then      Worksheets("Sheet1").Range(A1).offset(n行, n添え字 * 2 + 1) = str配列(n添え字)     end if     nレコード件数 = nレコード件数 + 1    next n添え字  wend  close  application.screenupdating = true end sub

tomomaki168
質問者

お礼

ご回答ありがとうございます。 サンプルコードまで頂き本当にありがとうございます。 当方、よちよち歩きなので、手持ちのマクロのVBAエディターに貼り付けさせていただき、 デバックしながら、仕上げ用と思います。 本当にありがとうございました。

回答No.3

以下の確認をしたいのですが・・・。 1・Excel のバージョン? 2・CSVファイルは、1項目だけ? 3・CSVファイルの1行目はタイトル行か   それとも データで始まっているのか? 4・120万件の内、抽出条件はあるのか? 5・取り込んだ後にどのように使いたいのか?

tomomaki168
質問者

お礼

ご回答ありがとうございます。 1・Excel のバージョン? エクセル2010です。 2・CSVファイルは、1項目だけ? 時間軸+16項目です。 3・CSVファイルの1行目はタイトル行か   それとも データで始まっているのか?ヘッダーと呼ばれる計測装置の測定条件テキストがあります。 4・120万件の内、抽出条件はあるのか? 下部に書きます。 5・取り込んだ後にどのように使いたいのか? 恐らくグラフを書いてトレンド管理をしたいのだと思います 120万行がミニマムで700万行くらいあるデータもあります。 列は16列あります。 120万行のデータを前から200行づつ最大値と最小値を集めていかなければなりません。(6000回) 1列当たり6000行(120万÷200)の最大値と最小値を取得しないといけないのです。 データは200行で1サイクルする機械の時系列データを垂れ流しで取っています。

  • bin-chan
  • ベストアンサー率33% (1403/4213)
回答No.2

120万行全てに用事があるんですか? 行Noカウントしながら読んで、条件に合う必要な行のカウントのみをセルに書き出すとか。

tomomaki168
質問者

お礼

ご回答ありがとうございます。 120万行がミニマムで700万行くらいあるデータもあります。 列は16列あります。 120万行のデータを前から200行づつ最大値と最小値を集めていかなければなりません。(6000回) 1列当たり6000行(120万÷200)の最大値と最小値を取得しないといけないのです。 データは200行で1サイクルする機械の時系列データを垂れ流しで取っています。

  • kmetu
  • ベストアンサー率41% (562/1346)
回答No.1

以下のページを参考にして挑戦してみてください。 一行ごとに読み込んでSplitを使ってカンマ(CSVがカンマ区切りとして)で分割し、(ページではセルに代入してますが)配列に代入する感じでいけるのではないでしょうか。 Office TANAKA - Excel VBA講座 テキストファイルを操作する http://officetanaka.net/excel/vba/file/file08b.htm

tomomaki168
質問者

お礼

大変お世話になります。 参考にさせていただきます。 お忙しいところ本当にありがとうございました。