1

Excel Interop Comオブジェクトのリリースに問題があり、Excel Interopを介して作成されたExcelブックを保存して閉じようとすると、c#アプリケーションがクラッシュします。問題は、私が読んだものから許可されていない優れた相互運用COMオブジェクトで「2ドット」を使用している場合があることだと感じています。ほとんどのコード行から2つのドットを削除しましたが、次のコード行を1つのドットのみを使用するように再作成する方法を考え出すのに苦労しています。誰か提案があれば、私はそれを大いに感謝します。

workbook = (Excel.Workbook)app.Workbooks.Open(startForm.excelFileLocation,);

workbook = (Excel.Workbook)app.Workbooks.Add(1);

workSheet_range.Font.Color = System.Drawing.Color.FloralWhite.ToArgb();

workSheet_range.Font.Bold = font;

workSheet_range.Interior.Color = System.Drawing.Color.Red.ToArgb();
4

3 に答える 3

3

各命令の戻りタイプを確認し、それらを個別に分類します。

最初の行は、Workbooksタイプのオブジェクトを返す「app.Workbooks」で始まります。次に、Open命令はワークブックを返します。

workbooks = app.Workbooks;
workbook = workbooks.Open(startForm.excelFileLocation);

次に、次のように2番目を分割できます。

workbook = workbooks.add(1);

実際のInterOpオブジェクトを「ドット」しない場合は、複数のドットを使用してもかまいません。

完全なサンプルは次のとおりです。

Using Excel = Microsoft.Office.Interop.Excel;
public void Read()
{
    Excel.Application xlApp = new Excel.Application();
    Excel.Workbooks xlWorkBooks = xlApp.Workbooks;
    Excel.Workbook xlWorkBook = xlWorkBooks.Open(sourceFile);
    Excel.Worksheet xlWorkSheet = xlWorkBook.Worksheets[ 1 ];

    Excel.Range range = xlWorkSheet.UsedRange;
    range = range.Cells;
    Array myValues = ( Array )range.Value;    //now holds all the data in the sheet

    //The following is to ensure the EXCEL.EXE instance is released...
    //If you edit this code, know that using 2 dots (ex: range.Cells.Value) can create weird stuff!
    xlWorkBook.Close(false);
    xlWorkBooks.Close();
    xlApp.Quit();

    releaseObject(xlWorkSheet);
    releaseObject(xlWorkBook);
    releaseObject(xlWorkBooks);
    releaseObject(xlApp);

    xlWorkSheet = null;
    xlWorkBooks = null;
    xlWorkBook = null;
    xlApp = null;
}

private static void releaseObject( object obj )
{
try
{
    System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
    obj = null;
}
catch (Exception ex)
{
    obj = null;
    Console.WriteLine("Unable to release the Object " + ex.ToString());
}
}
于 2012-10-25T13:10:53.447 に答える
1

ここにすべての情報を要約します。

  1. 割り当てるときに2つのドットを使用しないでください。
  2. AutoReleaseComObjectクラスを使用します。
  3. Microsoft KBで説明されているReleaseObjectメソッド(whileループを使用)を使用します。Officeアプリケーションは、.NETクライアントからの自動化後に終了しません
  4. GC.CollectとGC.WaitForPendingFinalizersを使用します。
  5. デバッグ時にExcelプロセスが有効に保たれていても驚かないでください。アプリケーションを実行するだけで、プロセスが有効に保たれているかどうかを常にテストしてください。

例えば:

using Microsoft.Office.Interop.Excel;
...
var missing = Type.Missing;
using (AutoReleaseComObject<Microsoft.Office.Interop.Excel.Application> excelApplicationWrapper = new AutoReleaseComObject<Microsoft.Office.Interop.Excel.Application>(new Microsoft.Office.Interop.Excel.Application()))
{
    var excelApplicationWrapperComObject = excelApplicationWrapper.ComObject;
    excelApplicationWrapperComObject.Visible = true;

    var excelApplicationWrapperComObjectWkBooks = excelApplicationWrapperComObject.Workbooks;
    try
    {
        using (AutoReleaseComObject<Workbook> workbookWrapper = new AutoReleaseComObject<Workbook>(excelApplicationWrapperComObjectWkBooks.Open(@"C:\Temp\ExcelMoveChart.xlsx", false, false, missing, missing, missing, true, missing, missing, true, missing, missing, missing, missing, missing)))
        {
            var workbookComObject = workbookWrapper.ComObject;
            Worksheet sheetSource = workbookComObject.Sheets["Sheet1"];
            ChartObject chartObj = (ChartObject)sheetSource.ChartObjects("Chart 3");
            Chart chart = chartObj.Chart;
            chart.Location(XlChartLocation.xlLocationAsObject, "Sheet2");

            ReleaseObject(chart);
            ReleaseObject(chartObj);
            ReleaseObject(sheetSource);

            workbookComObject.Close(false);
        }
    }
    finally
    {
        excelApplicationWrapperComObjectWkBooks.Close();
        ReleaseObject(excelApplicationWrapperComObjectWkBooks);

        excelApplicationWrapper.ComObject.Application.Quit();
        excelApplicationWrapper.ComObject.Quit();
        ReleaseObject(excelApplicationWrapper.ComObject.Application);
        ReleaseObject(excelApplicationWrapper.ComObject);

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

private static void ReleaseObject(object obj)
{
    try
    {
        while (System.Runtime.InteropServices.Marshal.ReleaseComObject(obj) > 0);
        obj = null;
    }
    catch (Exception ex)
    {
        obj = null;
        Console.WriteLine("Unable to release the Object " + ex.ToString());
    }
}

すべてのオブジェクトを解放し、GC.Collectを使用し、割り当てるときに2つのドットを使用しないことは上にあるように見えます、少なくともExcelのインスタンスを終了すると、プロセスが解放され、プログラムでExcelプロセスを強制終了する必要はありません!!

于 2015-12-03T01:56:02.480 に答える
-1

2つのドットを使用することは「禁止」されていませんが、特にタイトなループで実行している場合は、パフォーマンスに影響を与える可能性があります。

各「ドット」はExcelライブラリへのCOM呼び出しであり、通常のCLRオブジェクトアクセスよりも大幅に遅くなる可能性があります。一般に、COM呼び出しの数をできるだけ少なくする必要があります。

同じ変数を再利用しない限り、2つの線に分割して2つのドットを1つに減らしても、影響はありません。たとえば、変更します

workSheet_range.Interior.Color = System.Drawing.Color.Red.ToArgb();

var interior = workSheet_range.Interior;
interior.Color = System.Drawing.Color.Red.ToArgb();

パフォーマンスへの影響はゼロinteriorであり、変数を再利用しない場合は、元のシングルライナーに「最適化」されて戻る可能性があります。

ただし、変更する

var font = workSheet_range.Font;
font.Color = System.Drawing.Color.FloralWhite.ToArgb();
font.Bold = font;

呼び出しが1つ少なくなるworkSheet_range.Fontため、メリットが増えます。

ボトムライン

2ドットの呼び出しごとに変更することについてはあまり心配しませんが、代わりに優れたプロファイリングツールを使用して、コードが最も時間を費やしている場所を特定し、最初にその領域に取り組みます。

于 2012-10-25T13:31:43.507 に答える