6

WindowsエクスプローラーでExcelブックをダブルクリックして開いていますが、コードでアクセスできません

Excel.Application xlApp = (Application)Marshal.GetActiveObject("Excel.Application");
Excel.Workbooks xlBooks = xlApp.Workbooks;

xlBooks.Countは0ですが、開いているブックを参照していないのはなぜですか?

編集

さまざまなシナリオと何が起こっているかを次に示します。

シナリオ1:ファイルがまだ開いていない場合

  • コードはワークブックを開きます、私は幸せです。

シナリオ2:ファイルが最初にコードから開かれ、アプリを閉じて再度開いた場合

  • コード参照ファイルxlBooks.Countは1に等しいだけで、満足しています。

シナリオ3:ファイルがコードからではなく、エクスプローラーでダブルクリックして最初に開かれた場合

  • xlBooks.Countコードは0に等しいファイルの別のインスタンスを開きます、私は激怒しています!

これが現在のコード全体です

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using Microsoft.Office.Interop.Excel;

public class ExcelService : IExcelService
{
    const string _filePath = @"C:\Somewhere";
    const string _fileName = @"TestFile.xlsb";
    string _fileNameAndPath = Path.Combine(_filePath, _fileName);

    Application xlApp;
    Workbooks xlBooks;
    Workbook xlBook;
    Worksheet xlSheet;

    public ExcelService()
    {
        try
        {
            xlApp = (Application)Marshal.GetActiveObject("Excel.Application");
            xlBooks = xlApp.Workbooks;

            var numBooks = xlBooks.Count;
            Log.Info("Number of workbooks: {0}".FormatWith(numBooks));
            if (numBooks > 0)
            {
                xlBook = xlBooks[1];
                Log.Info("Using already opened workbook");
            }
            else
            {
                xlBook = xlBooks.Open(_fileNameAndPath);
                Log.Info("Opening workbook: {0}".FormatWith(_fileNameAndPath));
            }

            xlSheet = (Worksheet)xlBook.Worksheets[1];

            // test reading a named range
            string value = xlSheet.Range["TEST"].Value.ToString();
            Log.Info(@"TEST: {0}".FormatWith(value));

            xlApp.Visible = true;
        }
        catch (Exception e)
        {
            Log.Error(e.Message);
        }
    }

    ~ExcelService()
    {
        GC.Collect();
        GC.WaitForPendingFinalizers();

        try
        {
            Marshal.FinalReleaseComObject(xlSheet);
        }
        catch { }

        try
        {
            Marshal.FinalReleaseComObject(xlBook);
        }
        catch { }

        try
        {
            Marshal.FinalReleaseComObject(xlBooks);
        }
        catch { }

        try
        {
            Marshal.FinalReleaseComObject(xlApp);
        }
        catch { }
    }
}
4

2 に答える 2

10

このスレッドは少し古いことは知っていますが、これを行う別の方法を見つけました。新しいExcel.Applicationオブジェクトを作成するときは、WorkBooksオブジェクトを作成する必要があります。すでに開いているExcelファイルにアクセスすると、WorkBooksオブジェクトは既に作成されているため、既存のワークブックに新しいワークブックを追加するだけで済みます。@Tipxのソリューションは、WorkBook名にアクセスできる場合にうまく機能しますが、私の場合、現在のWorkBook名は常にランダムです。これを回避するために私が思いついた解決策は次のとおりです。

Excel.Application excelApp = null;
Excel.Workbooks wkbks = null;
Excel.Workbook wkbk = null;

bool wasFoundRunning = false;

Excel.Application tApp = null;
//Checks to see if excel is opened
try
{
    tApp = (Excel.Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application");
    wasFoundRunning = true;
}
catch (Exception)//Excel not open
{
    wasFoundRunning = false;
}
finally
{
    if (true == wasFoundRunning)
    {
        excelApp = tApp;
        wkbk = excelApp.Workbooks.Add(Type.Missing);                    
    }
    else
    {
        excelApp = new Excel.Application();
        wkbks = excelApp.Workbooks;
        wkbk = wkbks.Add(Type.Missing);
    }
    //Release the temp if in use
    if (null != tApp) { Marshal.FinalReleaseComObject(tApp); }
    tApp = null;
}
//Initialize the sheets in the new workbook

最善の解決策ではないかもしれませんが、それは私のニーズには役立ちました。これが誰かを助けることを願っています。:)

于 2013-12-03T07:46:00.870 に答える
4

すべてのブックが同じExcelインスタンスで開かれている場合(Alt-tabを使用して一方から他方に切り替えることができるかどうかを確認することでこれを確認できます)。を使用して他を参照するだけですWorkbooks("[FileName]")。したがって、たとえば:

Dim wb as Workbook //for C#, type Excel.Workbook wb = null;
Set wb = Workbooks("MyDuperWorkbook.xlsx") //for C#, type wb = Excel.Workbooks["MyDuperWorkbook.xlsx"];
wb.Sheets(1).Cells(1,1).Value = "Wahou!"
于 2011-07-13T23:38:52.783 に答える