大きなExcelファイルで作業する

大きなファイルとは何ですか? まあ、本当に大きい? 私がいた頃は、50〜60千行のレコードがあるファイルだと思いました。 そして、私はこれまでこの無知のままでしたが、私は60万から80万行のファイルを扱う必要がある1つのプロジェクトを実行しなければなりませんでした。 のどを通り抜ける-カットの下:







最初に何を





そして最初に、私の友人たち、あなたが考えることができる最も単純なものに急いだ。 Interop.Excell、およびすべてのもの。 そうだった。 うん、シャズ。 テストテストが示したように、このオープン方法により、1時間で20万行のExcelが読み取られ、アプリケーションがRAMを積極的に消費し、マシン上の残りのプロセスを分散させました。 すべてが期待どおりに終了しましたが、調査実験を完了する必要がありました-26万件で、アプリケーションは4 GBのマシンでOutOfMemoryに落ちました。 問題は額では解決できないことが明らかになりました



Google it





なんとすばらしい発見があったのか...奇妙なことに、Googleがmsdnにもたらしたのは、非常に大きなファイルを開く2つの方法、DOMとSAXです。 昔のことは覚えていませんが、その時点でOutOfMemoryはすでにうんざりしていて、2つ目はデータへのアクセスの点で完全に壊れていなかったため、それらのいくつかは落ちました。 なぜ-以下をお読みください。



何から、何から





私たちのエクセルは作られています。 バイナリxlsとは異なり、xlsxは本質的にzipデータアーカイブです。このフォーマットをもう少し詳しく調べることを決めた人にとっては、秘密ではありません。 拡張機能をハンドルで変更し、アーカイブをフォルダーに解凍するだけで十分です。ドキュメントの内部構造全体を取得します。これは、XMLファイルと関連情報のセットにすぎません。 判明したように、ルートxmlにはテキストデータはありません。 代わりに、キー/値のペアが提示される補助ファイルを参照するインデックスのセットがあります。上記の方法のいずれかを使用してファイルを開くことができますが、同時に付随するファイルを掘り下げて、そこからテキスト値を抽出する必要があります。 暗闇。



そして闇は後退した





多くの痛みと嘆きの後、以下が生まれました。



一部の個人が示すことを忘れている私たちのお気に入りの使用法:

using System;

using System.Collections. Generic ;

using System.Data;

using System.Data.OleDb;

using System.IO;

using System.Linq;

using DocumentFormat.OpenXml;

using DocumentFormat.OpenXml.Packaging;

using DocumentFormat.OpenXml.Spreadsheet;




* This source code was highlighted with Source Code Highlighter .









using System;

using System.Collections. Generic ;

using System.Data;

using System.Data.OleDb;

using System.IO;

using System.Linq;

using DocumentFormat.OpenXml;

using DocumentFormat.OpenXml.Packaging;

using DocumentFormat.OpenXml.Spreadsheet;




* This source code was highlighted with Source Code Highlighter .









using System;

using System.Collections. Generic ;

using System.Data;

using System.Data.OleDb;

using System.IO;

using System.Linq;

using DocumentFormat.OpenXml;

using DocumentFormat.OpenXml.Packaging;

using DocumentFormat.OpenXml.Spreadsheet;




* This source code was highlighted with Source Code Highlighter .














実際、コード自体:

public delegate void MessageHave( string message);



public delegate void _DataLoaded( List < string > data);



public delegate void _NewProcent( int col);



public static _DataLoaded DataLoaded;



public static _NewProcent NewProcent;



public static MessageHave MessageHave_Event;



public static void ReadData( object data)

{

// " "-" "

var keyValuePair = (KeyValuePair< string , string >)data;

using ( var cnn = new OleDbConnection( @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" +

keyValuePair.Key + @";Extended Properties=" "Excel 12.0;HDR=No;IMEX=1" "" )

)

{

int calc = 1000;

MessageHave_Event( " " );

cnn.Open();

try

{

var cmd = new OleDbCommand( String .Format( "select * from [{0}]" , keyValuePair.Value), cnn);

using (OleDbDataReader dr = cmd.ExecuteReader())

{

var lines = new List < string >();

int id = 0;

if (dr != null )

while (dr.Read())

{

string text = "" ;

for ( int i = 0; i < dr.FieldCount; ++i)

{

if (dr[i] != null )

text += dr[i] + "^" ; //

else

text += "^" ;

}

lines.Add(text);



id++;

if (id == calc)

{

NewProcent(id);

calc += 1000;

}

}

DataLoaded(lines);

}

cnn.Close();

}

catch (Exception ex)

{

MessageHave_Event( "Exception: " + ex.Message);

cnn.Close();

}

}

}




* This source code was highlighted with Source Code Highlighter .









public delegate void MessageHave( string message);



public delegate void _DataLoaded( List < string > data);



public delegate void _NewProcent( int col);



public static _DataLoaded DataLoaded;



public static _NewProcent NewProcent;



public static MessageHave MessageHave_Event;



public static void ReadData( object data)

{

// " "-" "

var keyValuePair = (KeyValuePair< string , string >)data;

using ( var cnn = new OleDbConnection( @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" +

keyValuePair.Key + @";Extended Properties=" "Excel 12.0;HDR=No;IMEX=1" "" )

)

{

int calc = 1000;

MessageHave_Event( " " );

cnn.Open();

try

{

var cmd = new OleDbCommand( String .Format( "select * from [{0}]" , keyValuePair.Value), cnn);

using (OleDbDataReader dr = cmd.ExecuteReader())

{

var lines = new List < string >();

int id = 0;

if (dr != null )

while (dr.Read())

{

string text = "" ;

for ( int i = 0; i < dr.FieldCount; ++i)

{

if (dr[i] != null )

text += dr[i] + "^" ; //

else

text += "^" ;

}

lines.Add(text);



id++;

if (id == calc)

{

NewProcent(id);

calc += 1000;

}

}

DataLoaded(lines);

}

cnn.Close();

}

catch (Exception ex)

{

MessageHave_Event( "Exception: " + ex.Message);

cnn.Close();

}

}

}




* This source code was highlighted with Source Code Highlighter .









public delegate void MessageHave( string message);



public delegate void _DataLoaded( List < string > data);



public delegate void _NewProcent( int col);



public static _DataLoaded DataLoaded;



public static _NewProcent NewProcent;



public static MessageHave MessageHave_Event;



public static void ReadData( object data)

{

// " "-" "

var keyValuePair = (KeyValuePair< string , string >)data;

using ( var cnn = new OleDbConnection( @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" +

keyValuePair.Key + @";Extended Properties=" "Excel 12.0;HDR=No;IMEX=1" "" )

)

{

int calc = 1000;

MessageHave_Event( " " );

cnn.Open();

try

{

var cmd = new OleDbCommand( String .Format( "select * from [{0}]" , keyValuePair.Value), cnn);

using (OleDbDataReader dr = cmd.ExecuteReader())

{

var lines = new List < string >();

int id = 0;

if (dr != null )

while (dr.Read())

{

string text = "" ;

for ( int i = 0; i < dr.FieldCount; ++i)

{

if (dr[i] != null )

text += dr[i] + "^" ; //

else

text += "^" ;

}

lines.Add(text);



id++;

if (id == calc)

{

NewProcent(id);

calc += 1000;

}

}

DataLoaded(lines);

}

cnn.Close();

}

catch (Exception ex)

{

MessageHave_Event( "Exception: " + ex.Message);

cnn.Close();

}

}

}




* This source code was highlighted with Source Code Highlighter .














このコードは、60〜80万行のレコードのファイルで約15〜20分のパフォーマンスを示しました。



実装が曲線のような誰かに見える場合-あまり蹴らないでください:)私はすべてのコメントを聞きます






All Articles