• 締切済み

書き出し処理速度について

バイナリデータを読み込み、数値データに変換、テキストファイルにタブ区切りで書き出すプログラムをvba/excelにて作成中ですが、書き出し処理速度の遅さに困惑しております。数値データに変換した配列はDATA(256,120000)としており、書き出しデータ数は約3,000,000個あります。その書き出しプログラムを下記のように記述したのですが、とんでもなく処理速度がおそいのです。   Open "c:\test.txt" For Output As #2 For i = 1 To 120000 For j = 1 To 256 Print #2, DATA(j, i); Chr(9);     Next j  Print #2, Chr(10); Next i Close #2 対処方法をご存知でしたら、ご教授願います。

みんなの回答

  • noocyte
  • ベストアンサー率58% (171/291)
回答No.3

> 書き出しデータ数は約3,000,000個 3百万じゃなくて3千万ですね. データ型がわかりませんが,1個4バイトだとすると約117MBです. それだけ巨大なメモリを使っていると, ページングが多発して非常に遅くなると思います. 変換を行うのに全データを調べる必要があるのなら仕方ありませんが, 単にバイナリファイルの中の一つ一つのデータを個別に変換するだけでよいのなら, #2 さんも書いておられるように次のようにする方が速くなると思います. (1) 巨大な配列ではなく,小さなバッファを用意する.例えば DATA(256). (2) バイナリファイルを先頭から順にバッファに読み込み,   一杯になったらテキストファイルに書き出す. (3) (2) を必要回数繰り返す. VB は知らないのでサンプルを示せません.あしからず.

  • KenKen_SP
  • ベストアンサー率62% (785/1258)
回答No.2

バイナリは配列に読み込んで、配列上で加工してるんですよね? んー > DATA(256,120000) 0 オリジンだと縦横の要素数が 行257×列120001 となって Excel VBA では非常に違和感があるんですけども。。。 256 バイトずつ 120000 回バッファしたなら、1 オリジンで考えると   Data(1 To 120000, 1 TO 256) となりそうな気がします。。。まあ、いずれにせよ、   Range("A1:IV12000").Value = Data といったコードで一度データをセルに一括転記し、   ActiveWorkbook.SaveAs Filename:="C:\test.txt", _              FileFormat:=xlText として、Excel のタブ区切りテキスト形式で保存します。データ の加工が既に完了しているなら、書き出し処理を自前でするより、 Excel の機能を利用した方が高速処理できますよ。 でも、このような処理は、本来データを一括オンメモリにしないで、 メモリを圧迫しない程度の最大バッファサイズを決めておき、   読み込み-->データ加工-->出力 を小刻みに繰り返すのが定石だと思いますが。

  • tkrn
  • ベストアンサー率53% (33/62)
回答No.1

回答ではありませんが、アドバイスさせて頂きます。 このポイントで処理速度を上げるのは難しいかもしれません。 ファイルの書き出しの負荷以前に、ループ処理とキャストの負荷が高そうです。 取り込む時に、事前に数値データとして扱わずに文字列として取り込む操作はできませんか? また、2次元配列を使わずに1次元配列で操作できませんか? 1次元配列かつ文字列として操作可能あれば、ループ処理を極力減らしてコーディングすることが可能かもしれません。 ヒントコードとしては、下記のような感じで文字列操作として処理が事前(読込み時とかに)できれば改善できそうですが… Dim VALUE(256) As String '値の配列(1行) Dim ROW(120000) As String '行の配列 : '値と値の間にChr(9)をセットし結合 ROW(i)= Join(VALUE, Chr(9)) : '行と行の間にChr(10)をセットし結合 strAll = Join(ROW, Chr(10))

関連するQ&A

  • マクロの処理速度が遅くなってしまいました

     今までエクセル2000を使用していたのですが、エクセル2003にバージョンアップして、以下の処理速度を検証したところ、処理が遅くなってしまいました。内容はsheet2にあるデータを変数に格納して簡単な計算をした後にsheet1に入力するということを5回繰り返し、それぞれの処理にかかる時間をsheet3に表示するというものです。 Sub タイム計測()   Dim myStart As Single, myGoal As Single   Dim j As Integer   Application.ScreenUpdating = False   Sheets(1).Select   Cells.Clear     For j = 1 To 5       myStart = Timer         Call サンプル       myGoal = Timer - myStart       Sheets(3).Select       Cells(j, 1) = myGoal       Sheets(1).Select     Next     Sheets(3).Select   Application.ScreenUpdating = True End Sub Sub サンプル()   Dim i As Integer, j As Integer   Dim Data As Variant, KeKKa(1 To 2000, 1 To 199) As Variant   Data = Range(Sheets(2).Cells(1, 1), Sheets(2).Cells(2000, 199))   For i = 1 To 2000     For j = 1 To 199       KeKKa(i, j) = Data(i, j) + Data(i, j)     Next   Next   Range(Cells(1, 1), Cells(2000, 199)) = KeKKa End Sub エクセル2000のときは1回当り平均して概ね0.7秒位で処理していたのですが、エクセル2003にすると1.4秒位かかってしまいます。処理速度が遅くなってしまうとバージョンアップした意味がないのですが、原因や改善策があればどなたか教えていただけないでしょうか?よろしくお願いします。

  • ExcelVBAでの配列処理について

    処理速度向上を目的に配列を利用したいのですが、結果の書きだし処理で悩んでいます。 Dim aa(10000,2) as Double for i = 1 to 10000 for j = 1 to 2 aa(i,j)=Rnd() next j next i 上記の処理で、10000行と2列の乱数表データが配列として出来、そのデータをシートに書き出しするときに、列を2つほど飛ばして書き出したいのですが、どうすればよいのでしょうか? range("A1:B10000") = aa  という連続した列ではなく、A列に1万行、D列に1万行書き出したいと思っています。 処理速度を向上させたいので、またFor分処理するのではなく、一気に書き出したいと思っています。 ご教授のほどよろしくお願い申し上げます。

  • 処理を早くできませんか?

    お世話になります。 職場で日報をエクセルで作成していて運用してから1年になります。 先日1年となったので、さらに Sub ERS() Dim Msg, Style, Title, Help, Ctxt, Response, MyString Msg = ("入力の全てが消去されます。") & Chr(13) & ("よろしいですか?") & Chr(13) & ("処理には相当時間必要です。") Style = vbYesNo + vbExclamation + vbDefaultButton2 Title = "消去の確認" Help = "DEMO.HLP" Ctxt = 1000 Response = MsgBox(Msg, Style, Title, Help, Ctxt) If Response = vbYes Then GoSub kesu Else Exit Sub End If kesu: For i = 2 To 5200 Step 14 For j = 3 To 12 ActiveSheet.Range("F" & i + j) = "" ActiveSheet.Range("G" & i + j) = "" ActiveSheet.Range("H" & i + j) = "" ActiveSheet.Range("I" & i + j) = "" ActiveSheet.Range("J" & i + j) = "" ActiveSheet.Range("k" & i + j) = "" Next j Next i End Sub というものを作成して、フォーマットの初期化(入力を全て消す)をするようにしました。 しかし、このモジュールでは、処理速度がかなり遅く、数日分の消去にかかった時間から計算すると1年分に130分かかってしまいます。 PCのスペックによるものとはおもいますが、上記のモジュールを書き換えて早く処理できるものなら。。と思い、書き込みさせていただきました。 よろしくご教示願います。 ちなみにOSはWIN2000、EXCEL2002、PCはクロック800MHZです。

  • chr関数の戻り値について質問です。

    chr関数を使用して、バイナリレベルで自由なデータを、ファイルに出力したいと思っていますが、一部のデータがうまくいきません。 たとえば以下のようなコードを実行して、バイナリエディタで中身を見てみると、0x81~0x9Fと0xE0~0xFCまでが全て、0x00に変換されて出力されています。 Dim i As Long Dim binHex As String Open fileName For Binary As #1 For i = 0 To 255   binHex = Chr(i)   Put #1, , binHex Next 0x81等をファイルに書き込む良い方法は無いでしょうか? 詳しい方、アドバイスをお願いいたします。

  • VB.NETにおける二値化処理の高速化

    いつも参考にさせて頂いております。 現在、VB.NET(VS2003/.NET Framework1.1)を使用して画像の二値化処理のプログラムを作成しております。 処理する事は簡単で、ビットマップファイルのRED要素を取り出し、閾値内なら白に変換して二値化するプログラムです。 以下がそのプログラムです。 ----- '変換する前の画像をファイルから読み込む Dim img1 As System.Drawing.Bitmap = New System.Drawing.Bitmap(filepath) '変換後のビットマップ Dim img2 As System.Drawing.Bitmap = New System.Drawing.Bitmap(img1.Width, img2.Height) '二値化処理 Dim b As Byte For i = 0 To img1.Width - 1 For j = 0 To img1.Height - 1 b = img1.GetPixel(i, j).R If b >= 閾値下限 And b <= 閾値上限 Then img2.SetPixel(i, j, Color.White) Else img2.SetPixel(i, j, Color.Black) End If Next Next PictureBox1.Image = img ----- これで処理は出来るのですが、ファイルが大きい場合は、非常に時間が掛かってしまいます。処理速度はCPUの速度にもよると思うのですが、できるだけ高速化したのですが、何かよい知恵があればご教授頂けると助かります。よろしくお願いいたします。 XP Pro SP2/VS2003/VB.NET/.NET Framework1.1

  • Tiny Basic。。。。

    今、やってるプログラムで躓いてしまっているのでどうか助けてください>< 今、ファイルの書き込みのプログラムでフロッピーディスクに書き込みをするプログラムをつくってて。。 前につくったのはフロッピーにjyoho01.txtのファイルを書き込むっていうのを作って 'Example-F2. 'データファイルの書き込み Cls Print "フロッピディスクにデータを書き込みます。" Print "FDを挿入して下さい。" Print "準備ができたら、";chr$(&h22);"y";chr$(&h22);"と入力してください。" ans$="" While not (ans$="y" or ans$="Y") ans$=inkey$ Wend Open "A:\jyoho01.txt" for output as #1 For i=1 to 10 Print #1,i Next i Close print "書き込みが終了しました。" End っていうのを作ったんです。これはちゃんとできたんです。 つまづいてるのが フロッピーディスク内にあるX線回折結果のデータファイル(xrd01.csv)のデータ数を1/5に縮減して、新しいファイル(xrd02.csv)を作成するプログラムを作成せよ。 っていうのなんです。 とりあえず、このX線回折結果っていうのがエクセルで 15  133.333 15.02  170 15.04  170 15.06  143.333 15.08  146.667 15.1  170 15.12  173.333 15.14  200 15.16  156.667 15.18  190 15.2  180 っていうデータがあって80までの値があるんです。 先生から聞いたところ5分の一にしろというのは15と15.1の間の数値を飛ばして15 15.1といったふうにファイルの書き込みを指示すれば14行くらいで出来るって言われて自分でやってみたんですが。。 'Example-F2. 'データファイルの書き込み Cls Print "フロッピディスクにデータを書き込みます。" Print "FDを挿入して下さい。" Print "準備ができたら、";chr$(&h22);"y";chr$(&h22);"と入力してください。" ans$="" While not (ans$="y" or ans$="Y") ans$=inkey$ Wend Open "A:\xrd02.csv" for output as #1 For i=15 to 80 step 0.1 Print #1,i Next i Close print "書き込みが終了しました。" End で実行したところ左の15 15.1っていうのはできるんですが右の値を出すことができません。 どうやったらいいんでしょう。。 長くてすみません(泣

  • VBへの変換の仕方 RS232C送信データとチェックサム

    以下のプログラムをVBに変換する仕方を教えてください。 サンプルプログラム 1110 CHKSUM=0 1120 FOR i=1 to LEN(A$)      'A$は送信データ 1130 CHKSUM=CHKSUM+ASC(MID$(A$,i,1) 1140 NEXT i 1150 C$=CHR$((CHKSUM+13) MOD 256) 1160 PRINT #1,A$;CHR$(13);C$; 私のVBプログラムは1110行から1150行まではそのままで CHKSUM=0 FOR i=1 TO LEN(A$) CHKSUM=CHKSUM+ASC(MID$(A$,i,1) NEXT i C$=CHR$((CHKSUM+13) MOD 256) としました。 送信部分を MSComm1.Output =A$ & CHR$(&H13) & C$ としてみましたが 1160行にあるセミコロン ";" はCHR$(&h3B) として送る必要があるのでしょうか? MSComm1.Output =A$ & CHR$(&h3B) & CHR$(&h13) ・・・・・・ また、データとしてA$="I 02"のチェックサムは "リ" となりますが正しいのでしょうか? 以上ご教示ください。

  • バイナリデータの取り方

    VB6を使用して、バイナリファイルをバイナリデータとして文字列にとりたいのですが、全角文字が絡んだ時の処理がうまくいきません。 バイナリファイルをString型の変数に丸ごと読み込んで、後は何バイトから何バイト目を抜き取り数値に変換…という処理をしようとしています。 本来は、バイナリでファイルをオープンして、Getコマンドで取得するのが手っ取り早いのですが、ファイルアクセス回数を減らすため、このような面倒な方法をとっております。 そこで仮に、 dim test as string dim i as integer test = "aあ" & chr(1) & "0 " For i = 1 to 6 Debug.Print Asc(Strconv( _ MidB(Strconv(test,vbFromUnicode),i,1), _ vbUnicode)) Next のようなソースを作ってみました。(本来は文字列は数100KByte…) しかしながら、この方法ですと上の例では2Byte目、つまり「あ」の文字の1Byte目が「&H00」になってしまいます。その次は「&HA0」、他の箇所も問題ないのですが… おそらくは根本的に違う方法で解決すべきではないかと思うのですがその方法がわかりません。 なお、この格納データはバイナリデータなので、意図的に全角文字にしていくてもその値によって(偶然)全角文字になったり制御文字になったりしますので前もって全角文字に対する処理は難しいと考えてます。 質問の仕方が良くなく、質問の内容がなかなかご理解いただけないとは思いますが、ご存知の方、ご経験者の方、ご教授お願いいたします。

  • マクロの処理速度を上げたい

    例えば"A1"から"Z100"までランダムに数字が入っている場合に、 次の処置をしたいのです。  処理A:10以下の数値を0に置き換える。 "A1"から始まるのはほぼ決まっているのですが、 最後のセルが決まっていません。 いろいろなときに使えるように下記マクロを作りましたが、 データ量が多いのか、処理に時間がかかってしまいます。 (本番データは200×3000件くらいあり、処理も例より複雑です) 処理は行えているみたいなので、速度を上げるのにいい方法はないか 相談させてください。 プログラムの知識は基本情報処理試験のC言語を勉強していた くらいです。マクロは本を見ながら作っているので、調べきれて いない部分もあるかもしれませんが、よろしくお願いいたします。 参考にしている本は、C&R研究所のEXCEL VBAハンドブックです。 ====ここから==== sub テスト() '使用する変数  dim LastColNum as integer  dim i as integer  'A1をアクティブにします  range("A1").select  '最後の列の行番号を調べます  LastColNum=range("A1").end(xlToRight).column  'アクティブなセルが空白になるまで処理を続けます  Do Until activecell.value=""   '行数分処理を続けます   for i=0 to LastColNum-1    '10未満だったら処理をします    if activecell.offset(0,i).value<10 then     '10未満のセルに0を入力します。     activecell.offset(0.i).value=0    end if   next   '次の行をアクティブにします   activecell.offset(1,0).activate  Loop end

  • C言語のfwrite関数について

    現在,バイナリのデータを処理するプログラムを作成しています。 おおまかに言えば,ファイルA(バイナリモードでオープン)からバイナリでデータを読み込んできて,そのデータを処理してファイルB(バイナリモードでオープン)に書出す,のようなプログラムです。 その処理したデータを入れるデータ型にunsigned long long int型(64bit)を使用しています。 その処理データをファイルBに書出す時に,fwrite関数を用いています(例参照)。 (例) for(i=0; i<N; i++){ fwrite(&c[i], sizeof(c[i]), 1, fp); } //配列cが「unsigned long long int型」です。 //配列cは最初に"0"で初期化しています。 //fpはファイルポインタです。 しかし,本システムでunsigned long long int型が実際に使用しているのは下位32bitです。 上の例で書出した場合,上位32bitの"0"も書出されていることになるのでしょうか。 書出されたファイルのサイズを見れば,64bit全て書出されているようですが,計算間違いで32bitを超えたところまで何かデータが入っている可能性もあります。 どなたはfwrite関数に詳しい方,ご回答をよろしくお願いします。