• ベストアンサー

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
質問者

お礼

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

関連するQ&A

  • VBAでエクセルのいくつかの表を同じ配列に格納する

    VBA初心者です。 調べてみましたがどうにも情報に行きあたらなく、ご質問をさせていただきます。 添付のようなエクセル上の同一シート上にある3つの表をコピーし、VBAで同じ配列の各列として取り込みをしたいと考えております。 大分類、中分類、小分類のそれぞれの行は同じもののそれぞれの内容を記載しており、 できればこれらを同じ配列の1列目、2列目、3列目に格納をしたいと思っております。 これらの表が1つの表にまとまっていれば、 Dim 配列(1,10) as Variant 配列 =range("A1:C10") で事足りると思うのですが、別々のためこの方法がとれません。 セル指定で行うことも考えましたが、データが10万行を超える場合もあるため、できれば避けたいと思っています。 各表を指定し、配列の1列目、2列目、3列目に一括して代入をご存じでしたらら、どうぞ教えていただきたいと思います。 どうぞよろしくお願いします。

  • アクセスの外部データ(エクセル)の取り込み。VBA

    アクセスの外部データ(エクセル)の取り込み。VBAの質問です。 アクセス2003 エクセル2003 不要な行・列がある場合の外部データ取り込みVBAを教えて下さい。 今は、エクセルで削除して取り込んでいます。 アクセスに「得意先リスト」というテーブルを作っています。 コード(テキスト型)主キー 名称(テキスト型) フリガナ(テキスト型) 郵便番号(テキスト型) 住所1(テキスト型) 住所2(テキスト型) TEL(テキスト型) FAX(テキスト型) エクセルブック[得意先リスト.xls] シートは「リスト形式」のみです。 1~4行は不要。 5行目が見出しです。 A~AZ列までデータがあります。 必要な列は、B・C・D・F・G・H・M・N列です。 セルの書式設定は「文字列」です。 [アクセス エクセル インポート 行 列 削除]などでサンプルVBAを探しましたが見つからなかったので質問させて頂きました。 申し訳ありませんが、教えて下さい。

  • EXCEL2003でテキストデータ取込開始行32768行以後の取り込み

    EXCEL2003の使用方法の質問です。OSはWindowsXP sp2です。 EXCEL2003で データ->外部データの取り込み->データの取り込み->ファイル名の指定 上記でテキストデータの13万行4列のデータのうち一部を取り込みます。 EXCELで取り扱い可能な行数は65535行までなのは承知していますので 「取り込み開始行」の指定で5万行あたりから3万行取り込もうとしたのですが「取り込み開始行」の数値が32767までしかできず、32768以上は指定できません。 32768以上に指定するにはどうしたらよいでしょうか。 常にOS、OFFICE2003ともに随時Microsoft Updateで最新にしています。 よろしくお願いします。

  • 〔EXCEL VBA〕で「第1のシート」のデータを「第2のシート」に転

    〔EXCEL VBA〕で「第1のシート」のデータを「第2のシート」に転記する方法 EXCEL2003でデータが480行/65列ある第1のシート(データベース的)があります。 第1のシートの列にデータが入力されている場合のみ、第2シートの指定されたセルに検索した列の 表題と検索したデータを結合して転記したいのですが良い方法が分りません。 その際、各行毎に検索し空白列は第2のシ-トに転記せず左詰めにして転記したいのですが・・・・ 初心者に合せたご教示をお願いします。 また、Excel VBAの短期マスター法が御座いましたら合せて教示願います。 以上、宜しくお願い致します。

  • CSVファイルの取り込みについて

    CSV取り込み方法について 教えていただきたくお願いいたします。 エクセルのマクロ・VBAの組み方について デスクトップ上の000という名前のCSVファイルを、作業しているエクセルファイルのLoadという名前のシートに貼り付けたいと思っています。 CSVファイルはエクセルで開くと1行に11列の項目が展開されています。 貼り付ける項目はこのようになります。 (CSV) →(エクセルのLoadシート) 1列目(A行)→B行へ 2列目   →C行へ 3列目   →D行へ 4列目   →E行へ 5列目   →F行へ 9列目   →G行へ 10列目  →H行へ 11列目  →I行へ (6.7.8列目は使いません) 最後にLoadのシートのA行に”=B&E”とい式を入力したいと思っています。 まだ初心者なので勉強中なのですが、仕事上急遽必要になりましたのでお願いいたします。

  • 【Excel】csvファイル取込み VBA処理

      VBAの初心者です。 csvファイル(カンマ区切り)の取込みをVBAで処理したいのですが、知識がないので 何方か詳しい方ご教授下さい。 動作的には以下のように処理したいと思ってます。 1. sheet1のボタンからテキストのインポート   任意のフォルダ(c:\data\i_data)からカンマ区切りで保存されたcsvファイル群から   選んで読込み。   読込むファイルに間違いがないか対話型で確認のメッセージを表示し、キャンセ   ルした場合は中断させる。 2. csvファイル内の200列分のデータ(指数)をsheet3の任意のセル(指定可能)に取込   み。セルの指定が出来なければ固定でも可ですが、行違いで他のファイルも取込   み出来るようにしたいのです。 色んなサイトからヒントを貰って自分なりに試してますが上手くいかず、行き詰って質 問させて頂いた次第です。 また別のQ&Aに記載されてましたFileSystemObjectが使えません。 お手数ですが、各行毎にコメント(解説)があると有難いです。 Excelのバージョンは"2007"ですが"2000"でも使えるようにしたいのですが・・ よろしくお願いします。

  • VBAでのセル範囲指定について

    お世話になります。 私が分からないのは、VBAでのセル範囲指定なのですが、 例えば、シートにデータが有、そのデータの1行目は見出しなので 2行目からデータが入っているセルまでの範囲を指定、コピーして 隣のシートに貼付したいのですが、そのデータの入力される範囲が 毎回違います。「CurrentRegion.Select」としてしまうと、1行目 の見出しまでも範囲指定されてしますので、どうやったら良いのか どなたかお教え頂きたく宜しくお願い申し上げます。

  • エクセルVBA 不要行の削除について

    皆さんこんにちは。 お忙しいところ恐れ入ります。 以下の内容をVBAで実行したく色々やってみたのですが、思うように動きません。 もしお分かりになる方がおられましたらご教示の程ねがえませんでしょうか? 1.A列に”無作為な数値(例えば1から100)”と”空セル”がランダムに並んでいる。 2.このA列に、指定した数値(例えば3,7,15,23,50,88など色々)があった場合、  その指定した数値が書かれている行のみを行ごと削除したい。 以上です。 お忙しいところ恐れ入りますが、どうぞよろしくお願いいたします。

  • VBAでEXCELから固定長のテキストデータにしたい

    VBAにてEXCELに展開されたデータを固定長のテキストデータに落としたい。 EXCEL側の用件 (1)シート1にボタンを用意して、ボタンをクリックしたらテキストファイルを作成する処理にしたい。 (2)シート2にデータが展開されている。 列は10個程度、行は場合によりけり(MAX65536?) 固定長にする箇所とかはわかるのですが、ボタンクリックしたらシート2を見て、セル(もしくはrange)をどのように取得すればいいのかVBAがよくわからないのです。

  • Excel VBA 外部データ(CSV)の自動読込について 

    VBAに関して昨日基本書を読み始めたばかりの初心者です。 業務の効率化が急務であるという手前勝手な都合により、 さっそくの他力本願で失礼とは思いますが 以下のケーススタディについてアウトラインだけでも助言をいただけないでしょうか。 帳票[yyyymmdd].csv ←末尾に年月日 日毎にCSVファイルが存在する A1:A10 B1:B10 C1:C10 の範囲の値を 期間集計.xlsx のそれぞれシート別のyyyymmdd列1行~10行にコピーする sheet1の[yyyymmdd]列1行:10行 ←A1:A10の値 sheet2の[yyyymmdd]列1行:10行 ←B1:B10の値 sheet3の[yyyymmdd]列1行:10行 ←C1:C10の値 過去数年分の日毎帳票を一括で自動処理したいと思い、 マクロの記録機能を使用したのですがどうしてもうまくいきませんでした。 特にわからないポイントが ・CSVファイルを開かずに参照する処理  (Excelで開かずにどうしてセルの範囲を指定できるのかという矛盾が生じてる気はするのですが・・・) ・自動的に帳票[yyyymmdd].csvを昇順に参照する処理 ・それをyyyymmddに対応した列にコピーする処理  以上のVBA処理についての助言をいただけますようよろしくお願いします。 Excelのバージョンは2007です。

専門家に質問してみよう