1

基本的に、大量のデータを Excel ファイルに挿入する必要があります。OleDB 接続を作成するのが最速の方法のようですが、メモリの問題が発生したことがわかりました。INSERT クエリを実行すると、プロセスで使用されるメモリが増加し続けるようです。Excelファイルに出力するときにのみ発生するように絞り込みました(Excelへの出力がなくてもメモリは安定しています)。各ワークシート間の接続を閉じて再度開きますが、これはメモリ使用量に影響を与えないようです (Dispose() と同様)。比較的小さなデータセットで確認できるように、データは正常に書き込まれています。誰かが洞察力を持っているなら、それはありがたいです。

initializeADOConn()はコンストラクターで呼び出されます

initADOConnInsertComm()は、挿入パラメータ化された挿入クエリを作成します

writeRecord()は、新しいレコードが書き込まれるたびに呼び出されます。必要に応じて新しいワークシートが作成されます。

public bool initializeADOConn()
        {
            /* Set up the connection string and connect.*/
            string connectionString = @"Provider=Microsoft.Jet.OLEDB.4.0;" +
                "Data Source=" + this.destination + ";Extended Properties=\"Excel 8.0;HDR=YES;\"";
            //DbProviderFactory factory =
                //DbProviderFactories.GetFactory("System.Data.OleDb");
            conn = new OleDbConnection(connectionString);
            conn.ConnectionString = connectionString;
            conn.Open();

            /* Intialize the insert command. */
            initADOConnInsertComm();
            return true;
        }
    public override bool writeRecord(FileListerFileInfo file)
            {
                /* If all available sheets are full, make a new one. */
                if (numWritten % EXCEL_MAX_ROWS == 0)
                {
                    conn.Close();
                    conn.Open();
                    createNextSheet();
                }
                /* Count this record as written. */
                numWritten++;
                /* Get all of the properties of the FileListerFileInfo record and add
                 * them to the parameters of the insert query. */
                PropertyInfo[] properties = typeof(FileListerFileInfo).GetProperties();
                for (int i = 0; i < insertComm.Parameters.Count; i++)
                    insertComm.Parameters[i].Value = properties[i].GetValue(file, null);
                /* Add the record. */
                insertComm.ExecuteNonQuery();

                return true;
            }

編集:

いいえ、エクセルは全く使いません。私は意図的に Interop.Excel を避けています。パフォーマンスが悪いためです (少なくとも、私が手を出していたからです)。

4

3 に答える 3

2

答えははいです。あなたが説明する式悪い時間に等しいです。

手元にデータベースがある場合 (SQL Server または Access がこれに適しています)、すべての挿入をデータベース テーブルに実行してから、テーブルを一度にすべて Excel スプレッドシートにエクスポートできます。

一般的に言えば、データベースは大量の挿入を処理するのに適していますが、スプレッドシートはそうではありません。

于 2008-11-11T06:07:26.127 に答える
1

ここにいくつかのアイデアがあります:

対象のブックは開いていますか? 上記の記事では確認されていませんが、IIRC が Jet の OLE DB プロバイダー (使用している) に実際にあるバグ ( ActiveX Data Objects を使用して開いている Excel ワークシートを照会すると、メモリ リークが発生する) があります。

とにかく、一括挿入が適しているようです。

同じ Jet OLE DB プロバイダーを使用してこれを行うことができます。必要なのは 1 行のテーブルだけです。その場で作成することもできます。新しい Excel ワークブックを作成するCREATE TABLEには、接続文字列で存在しない xls ファイルを使用して DDL を実行します。プロバイダーは、テーブルを表すワークシートを使用してワークブックを作成します。Excel ワークブックへの接続があるので、これを実行できます。

CREATE TABLE [EXCEL 8.0;DATABASE=C:\MyFabricatedWorkbook;HDR=YES].OneRowTable 
(
   x FLOAT
);

(さらに良い IMO は、Jet データベース、つまり .mdb ファイルを作成することです)。

INSERTダミー行を作成するために使用します。

INSERT INTO [EXCEL 8.0;DATABASE=C:\MyFabricatedWorkbook;HDR=YES].OneRowTable (x) 
   VALUES (0);

次に、引き続きターゲット ワークブックへの接続を使用して、次のようなものを使用して、値の派生テーブル (DT1) をINSERT1 回のヒットで作成できます。

INSERT INTO MyExcelTable (key_col, data_col)
SELECT DT1.key_col, DT1.data_col
FROM (
   SELECT 22 AS key_col, 'abc' AS data_col
   FROM [EXCEL 8.0;DATABASE=C:\MyFabricatedWorkbook;HDR=YES].OneRowTable
   UNION ALL
   SELECT 55 AS key_col, 'xyz' AS data_col
   FROM [EXCEL 8.0;DATABASE=C:\MyFabricatedWorkbook;HDR=YES].OneRowTable
   UNION ALL
   SELECT 99 AS key_col, 'efg' AS data_col
   FROM [EXCEL 8.0;DATABASE=C:\MyFabricatedWorkbook;HDR=YES].OneRowTable
) AS DT1;
于 2008-11-11T08:39:59.033 に答える
0

一度に1つのレコードを書き込む代わりに、バルク容量に挿入する方法を見つけることができますか?私はクレイジーなDataSetのものを使用しないようにしていますが、最初にすべての挿入をローカルで実行してから、一気に上昇させる方法はありませんか?このプロセスはバックグラウンドでExcelを開きますか?これらのプロセスは後で死にますか?

于 2008-11-11T05:16:05.513 に答える