色の知識で人生の可能性が広がる!みんなに役立つ色彩検定 >>

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

教えて!goo グレード

A 回答 (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 さんにお任せして敵前逃亡しようかな。。。
    • good
    • 1
この回答へのお礼

大変お世話になっております。
ご回答感謝いたします。
データの並びは,時間,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くらい)続きます

お礼日時:2014/02/25 20:07

またまたすみません。


レコード件数をカウントアップする場所の前に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
    • good
    • 0
この回答へのお礼

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

お礼日時:2014/02/25 22:01

さっそくですみません。


レコード件数をカウントアップする場所がおかしいので訂正。

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
    • good
    • 0

#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
    • good
    • 0
この回答へのお礼

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

お礼日時:2014/02/25 12:21

以下の確認をしたいのですが・・・。



1・Excel のバージョン?
2・CSVファイルは、1項目だけ?
3・CSVファイルの1行目はタイトル行か
  それとも データで始まっているのか?
4・120万件の内、抽出条件はあるのか?
5・取り込んだ後にどのように使いたいのか?
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
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サイクルする機械の時系列データを垂れ流しで取っています。

お礼日時:2014/02/24 13:00

120万行全てに用事があるんですか?


行Noカウントしながら読んで、条件に合う必要な行のカウントのみをセルに書き出すとか。
    • good
    • 0
この回答へのお礼

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

お礼日時:2014/02/24 12:50

以下のページを参考にして挑戦してみてください。


一行ごとに読み込んでSplitを使ってカンマ(CSVがカンマ区切りとして)で分割し、(ページではセルに代入してますが)配列に代入する感じでいけるのではないでしょうか。

Office TANAKA - Excel VBA講座
テキストファイルを操作する
http://officetanaka.net/excel/vba/file/file08b.htm
    • good
    • 1
この回答へのお礼

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

お礼日時:2014/02/24 08:22

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

教えて!goo グレード

人気Q&Aランキング