2

これ機能していました。そして、破棄コードをfinallyブロックに移動しましたが、今では毎回失敗します。

4レコード、6列の長さのテストスプレッドシートがあります。これが私がそれを持ち込むために使用しているコードです。これはIIS5(私のPC)とIIS 6(Webサーバー)上のASP.Net3.5です。

キャッチの直前の行で爆発します: "values =(object [、])range.Value2;" 次のエラーが発生します。

11/2/2009 8:47:43 AM :: Not enough storage is available to complete this operation. (Exception from HRESULT: 0x8007000E (E_OUTOFMEMORY))

何か案は?提案?私はこのコードのほとんどをcodeprojectから取得したので、これがExcelを操作する正しい方法であるかどうかはわかりません。あなたが提供できるどんな助けにも感謝します。

これが私のコードです:

Excel.ApplicationClass app = null;
Excel.Workbook book = null;
Excel.Worksheet sheet = null;
Excel.Range range = null;

object [、]値= null;

試す
{{
    //Excelを構成します
    app = new Excel.ApplicationClass();
    app.Visible = false;
    app.ScreenUpdating = false;
    app.DisplayAlerts = false;

    //アップロードされたファイルでExcelの新しいインスタンスを開きます
    book = app.Workbooks.Open(path);

    //本の最初のワークシートを取得します
    sheet =(Excel.Worksheet)book.Worksheets [1];

    //2行目の最初のセルから開始
    range = sheet.get_Range( "A2"、Missing.Value);

    //すべてのセルを右側に配置します
    range = range.get_End(Excel.XlDirection.xlToRight);

    //すべてのセルを下向きにします
    range = range.get_End(Excel.XlDirection.xlDown);

    //右下のセルのアドレスを取得します
    string downAddress = range.get_Address(false、false、Excel.XlReferenceStyle.xlA1、Type.Missing、Type.Missing);

    //完全な範囲のデータを取得します
    range = sheet.get_Range( "A2"、downAddress);

    //すべてのデータの2D配列を取得します
    値=(object [、])range.Value2;
}
キャッチ(例外e)
{{
    LoggingService.log(e.Message);
}
ついに
{{
    // 掃除
    範囲=null;
    シート=null;

    if(book!= null)
        book.Close(false、Missing.Value、Missing.Value);

    本=null;

    if(app!= null)
        app.Quit();

    app = null;
}

戻り値;
4

4 に答える 4

5

これがあなたの問題かどうかはわかりませんが、問題はあるかもしれません。Excelオブジェクトを適切にクリーンアップしていません。これらは管理されていないコードであり、クリーンアップするのが難しい場合があります。最後に、次のようになります。コメントにあるように、asp.netのExcelを使用することはお勧めできません。このクリーンアップコードは、winformアプリからのものです。

 GC.Collect();
 GC.WaitForPendingFinalizers();


 System.Runtime.InteropServices.Marshal.FinalReleaseComObject(range);
 System.Runtime.InteropServices.Marshal.FinalReleaseComObject(sheet);
 System.Runtime.InteropServices.Marshal.FinalReleaseComObject(book);

 WB.Close(false, Type.Missing, Type.Missing);

 Excel.Quit();
 System.Runtime.InteropServices.Marshal.FinalReleaseComObject(Excel);

編集

別の方法は、ado.netを使用してブックを開くことです。

            DataTable dt = new DataTable();

            string connectionString;
            System.Data.OleDb.OleDbConnection excelConnection;
            System.Data.OleDb.OleDbDataAdapter da;
            DataTable dbSchema;
            string firstSheetName;
            string strSQL;

            connectionString = @"provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + filename + @";Extended Properties=""Excel 12.0;HDR=YES;IMEX=1""";
            excelConnection = new System.Data.OleDb.OleDbConnection(connectionString);
            excelConnection.Open();
            dbSchema = excelConnection.GetOleDbSchemaTable(System.Data.OleDb.OleDbSchemaGuid.Tables, null);
            firstSheetName = dbSchema.Rows[0]["TABLE_NAME"].ToString();
            strSQL = "SELECT * FROM [" + firstSheetName + "]";
            da = new OleDbDataAdapter(strSQL, excelConnection);
            da.Fill(dt);

            da.Dispose();
            excelConnection.Close();
            excelConnection.Dispose();
于 2009-11-02T19:02:13.260 に答える
1

すべての要求でExcelを作成/破棄すると、何をするかに関係なく、絶対にひどいパフォーマンスになります。一般に、自動化を使用してOfficeアプリを実行することは、多くの理由で厄介なビジネスです(ここを参照)。私がそれを機能させる唯一の方法は、アプリの単一のインスタンス(私の場合はWord)を一度初期化してから、リクエストをこのインスタンスにキューに入れて処理することです。

アプリから離れて自分でファイルを解析できる場合(MSライブラリを使用して、XMLのみ)

于 2009-11-02T19:07:34.950 に答える
1

ASP.NETの相互運用機能を使用すると、多くの問題が発生します。これが社内アプリケーションの小さなものを対象としているのでない限り、それを進めないことをお勧めします。

Office Interopは、従来の意味でのプログラミングAPIではありません。Officeマクロシステムを最大限に活用し、プロセス間で動作する機能を備えています。たとえば、ExcelマクロはOutlookと対話できます。

相互運用機能を使用した場合の影響は次のとおりです。

  • 実際には、Officeアプリケーションの完全なコピーを開いています。
  • アクションは、ユーザーがアクションを開始したかのようにアプリケーションによって実行されます。つまり、エラーメッセージがコードで返される代わりに、GUIに表示されます。
  • アプリケーションのコピーは、明示的にコマンドを実行した場合にのみ閉じます。それでも、エラーによって実際に発生するのを防ぐことができます(変更が不要であることをプログラムでExcelに通知しなかった場合、アプリケーションは「保存しますか」ダイアログを表示する場合があります)保存する)。これにより、通常、Excelの非表示のコピーがシステム上で実行されたままになります。タスクマネージャーを開いて、実行されているExcel.exeプロセスの数を確認してください。

これらすべてにより、相互運用は通常のデスクトップアプリケーションでは回避でき、サーバーアプリケーションの最後の手段としてのみ使用する必要があります。これは、プロセスをリークするアクションまたはスクリプトを必要とするGUIポップアップがサーバー環境で殺害されるためです。

いくつかの選択肢が含まれます:

  • Microsoft Office 2007 XMLベースの形式を使用して、XMLファイルを自分で作成できるようにします。
  • .NETバイナリExcelファイルリーダー/ライターであるSpreadsheetGear.Netを使用します(完全にスタンドアロンであるため、Excelをインストールする必要はありません)。SpreadsheetGearは、古いコードの変換を容易にするために、Intertopインターフェースをモデルにしています。
于 2009-11-02T19:12:08.977 に答える
0

エラーはおそらくまさにそれが言っていることです、あなたはメモリ不足エラーを取得しています。Range全体を一度に取得するのではなく、values配列のロードをいくつかの小さなチャンクに分割してみてください。コードをC#で試しましたが、問題はありませんでしたが、読み込んでいたスプレッドシートはほとんど空でした。

ただし、範囲がスプレッドシート全体(A2からIV65536など)であることに気付きました。それが意図されているかどうかはわかりません。

使用してみることができるのはsheet.UsedRangeです。これにより、ロードするセルの数が削減されます。

私が学んだいくつかの追加の小さなことは、あなたが役に立つと思うかもしれません:

  • ApplicationClassの代わりにApplicationを使用する
  • Marshal.FinalReleaseComObject(range)(およびシート、ブック、アプリ)を使用してください。そうしないと、EXCEL.EXEプロセスが停止します。
于 2009-11-02T19:09:51.680 に答える