Закрытие книги Excel

У меня есть немного кода, который открывает книгу xls;

Excel.Workbooks workBooks;
workBooks = excelApp.Workbooks;
workbook = workBooks.Open(sourceFilePath + sourceFileName + ".xls");

Затем я получаю рабочий лист;

worksheets = workbook.Worksheets;
worksheet = worksheets.get_Item("Standard");

Затем я сохраняю файл как csv;

worksheet.SaveAs(sourceFilePath + sourceFileName + ".csv", Excel.XlFileFormat.xlCSVWindows, Type.Missing, Type.Missing, false, false, Excel.XlSaveAsAccessMode.xlNoChange, Type.Missing, Type.Missing, Type.Missing);

Затем я пытаюсь закрыть книгу;

Marshal.FinalReleaseComObject(worksheet);
Marshal.FinalReleaseComObject(worksheets);
workbook.Close();
Marshal.FinalReleaseComObject(workbook);

Однако каждый раз, когда я добираюсь до строки workbook.Close(), система останавливается.

Если я не делаю SaveAs, книга закрывается просто отлично.

Как закрыть книгу?

изменить

Глядя на диспетчер задач, я вижу, что Excel.exe все еще работает. Закрытие его приведет к ошибке в моем коде.

изменить 2

Я уже видел упомянутый пост SO, и он не решил проблему.


person griegs    schedule 03.07.2013    source источник
comment
Вы пытались закрыть книгу перед выпуском листов? На них ссылается рабочая книга, поэтому, возможно, они отсутствуют при закрытии.   -  person Chris    schedule 03.07.2013
comment
@ Крис, да, и тот же результат   -  person griegs    schedule 03.07.2013
comment
возможный дубликат Как правильно очистить объекты взаимодействия Excel - Это досадная проблема, вы также должны использовать VSTO Contrib, но даже в этом случае иногда Excel все еще зависает, и многие люди, похоже, прибегают к уничтожению процесса, что я не поддерживаю   -  person Jeremy Thompson    schedule 03.07.2013
comment
Я уже видел этот пост SO, и это не помогло. это не дубликат   -  person griegs    schedule 03.07.2013


Ответы (5)


Вот решение

первый: using EXCEL = Microsoft.Office.Interop.Excel;

а затем path находится там, где находится ваш Excel.

        EXCEL.Application excel = new EXCEL.Application();
        try
        {
            EXCEL.Workbook book = excel.Application.Workbooks.Open(path);
            EXCEL.Worksheet sheet = book.Worksheets[1];
            // yout operation

        }
        catch (Exception ex) { MessageBox.Show("readExcel:" + ex.Message); }
        finally
        {
            KillExcel(excel);
            System.Threading.Thread.Sleep(100);
        }



    [DllImport("User32.dll")]
    public static extern int GetWindowThreadProcessId(IntPtr hWnd, out int ProcessId);
    private static void KillExcel(EXCEL.Application theApp)
    {
        int id = 0;
        IntPtr intptr = new IntPtr(theApp.Hwnd);
        System.Diagnostics.Process p = null;
        try
        {
            GetWindowThreadProcessId(intptr, out id);
            p = System.Diagnostics.Process.GetProcessById(id);
            if (p != null)
            {
                p.Kill();
                p.Dispose();
            }
        }
        catch (Exception ex)
        {
            System.Windows.Forms.MessageBox.Show("KillExcel:" + ex.Message);
        }
    }
person Hercules    schedule 03.07.2013
comment
ВАУ, скорее грубый подход к чему-то, что должно быть обработано с помощью .Close(), но, эй, это работает, и работает хорошо. Так что +1 и спасибо - person griegs; 03.07.2013
comment
@griegs Я связал вас с тем же решением - я не думаю, что вы прочитали все ответы. Это дубликат и способствует плохой практике. - person Jeremy Thompson; 03.07.2013
comment
Спасибо, Джереми, возьму это на заметку. - person griegs; 03.07.2013
comment
Идеальное решение - person Aravindhan R; 12.03.2021

Почему бы не объединить 2. Это решит любые проблемы с закрытием до завершения сохранения. В методе Close есть возможность сохранить файл.

workbook.Close(true, fileName, Missing.Value);

Кроме того, если файл сохраняется правильно, и ваша проблема связана исключительно с тем, что процесс excel.exe все еще работает, это может быть связано с тем, что вы не закрыли и не выпустили ВСЕ необходимое. У меня было это раньше, и я разработал более полную процедуру закрытия. Мой код для закрытия файла excel:

        book.Close(true, fileName, Missing.Value); //close and save individual book
        allBooks.Close(); //close all books
        excel.Quit();
        Marshal.ReleaseComObject(allCells); //any used range objects
        Marshal.ReleaseComObject(sheet);
        Marshal.ReleaseComObject(sheets);
        Marshal.ReleaseComObject(book);
        Marshal.ReleaseComObject(allBooks);
        Marshal.ReleaseComObject(excel);

Это работает в 100% случаев для меня.

person SeeMoreGain    schedule 03.07.2013
comment
Попробовал это, и это не сработало. Excel не ответил ни на одно событие закрытия - person griegs; 03.07.2013
comment
Я расширил свой ответ более полным кодом для закрытия (примечание: переменная allBooks равна workBooks в вашем коде. - person SeeMoreGain; 05.07.2013

Учитывали ли вы тот факт, что система может все еще сохранять файл, когда вы пытаетесь его закрыть? Я просто говорю, что нужно добавить задержку (например, Thread.Sleep(1000) в C#) перед закрытием, чтобы увидеть, не в этом ли проблема.

person Tenescu Andrei    schedule 03.07.2013
comment
Я проверил созданный файл, и он завершен. Всего 200 строк с 41 столбцом. Жду 10 минут и ничего не меняется. - person griegs; 03.07.2013

Этот вопрос продолжает появляться см.:

Как правильно очистить объекты взаимодействия Excel в C#

Вам нужно вызвать System.Runtime.InteropServices.Marshal.ReleaseComObject() для каждого используемого вами объекта excel, даже невидимого, например:

var worksheet = excelApp.Worksheets.Open()

Здесь есть два объекта: 1. Очевидный «Рабочий лист», открытый с помощью Open() 2. «Невидимая» коллекция «Рабочие листы».

Оба они должны быть выпущены (так что вам лучше сохранить ссылку на рабочие листы):

var wkCol = excelApp.Worksheets;
var worksheet = wkCol.Open();
person Eli Algranti    schedule 05.07.2013

    EXCEL.Application excel = new EXCEL.Application();
    try
    {
        EXCEL.Workbook book = excel.Application.Workbooks.Open(path);
        EXCEL.Worksheet sheet = book.Worksheets[1];
        // yout operation

    }
    catch (Exception ex) { MessageBox.Show("readExcel:" + ex.Message); }
    finally
    {
        KillExcel(excel);
        System.Threading.Thread.Sleep(100);
    }


[DllImport("User32.dll")]
public static extern int GetWindowThreadProcessId(IntPtr hWnd, out int ProcessId);
private static void KillExcel(EXCEL.Application theApp)
{
    int id = 0;
    IntPtr intptr = new IntPtr(theApp.Hwnd);
    System.Diagnostics.Process p = null;
    try
    {
        GetWindowThreadProcessId(intptr, out id);
        p = System.Diagnostics.Process.GetProcessById(id);
        if (p != null)
        {
            p.Kill();
            p.Dispose();
        }
    }
    catch (Exception ex)
    {
        System.Windows.Forms.MessageBox.Show("KillExcel:" + ex.Message);
    }
}

Спасибо!!!!

person user2853852    schedule 27.01.2014