Đóng Quy trình Ứng dụng Excel trong C # sau khi Truy cập Dữ liệu


86

Tôi đang viết một ứng dụng bằng C # để mở tệp mẫu Excel cho các thao tác đọc / ghi. Tôi muốn khi người dùng đóng ứng dụng, quy trình ứng dụng excel đã được đóng lại mà không cần lưu tệp excel. Xem Trình quản lý tác vụ của tôi sau nhiều lần chạy ứng dụng.

nhập mô tả hình ảnh ở đây

Tôi sử dụng mã này để mở tệp excel:

public Excel.Application excelApp = new Excel.Application();
public Excel.Workbook excelBook;
excelBook = excelApp.Workbooks.Add(@"C:/pape.xltx");

và để truy cập dữ liệu, tôi sử dụng mã này:

Excel.Worksheet excelSheet = (Worksheet)(excelBook.Worksheets[1]);
excelSheet.DisplayRightToLeft = true;
Range rng;
rng = excelSheet.get_Range("C2");
rng.Value2 = txtName.Text;

Tôi thấy câu hỏi tương tự trong stackoverflow như câu hỏi nàynày , và kiểm tra câu trả lời, nhưng nó không hoạt động.


Excel và Word rất chậm và đi kèm với vô số lỗi như bạn đã vấp phải. Các tệp là tệp nén với một số XML và nội dung khác trong đó. Ngoài ra còn có Open XML SDK (hoặc có thể mới hơn) có thể mở các tài liệu. Mã như vậy cũng hoạt động mà không cần cài đặt cục bộ Office. Cân nhắc không sử dụng Excel
Sten Petrov

Câu trả lời:


94

Thử đi:

excelBook.Close(0); 
excelApp.Quit();

Khi đóng sổ làm việc, bạn có ba tham số tùy chọn:

Workbook.close SaveChanges, filename, routeworkbook 

Workbook.Close(false)hoặc nếu bạn đang thực hiện ràng buộc muộn, đôi khi sử dụng số 0 sẽ dễ dàng hơn Workbook.Close(0) Đó là cách tôi đã thực hiện khi tự động đóng sổ làm việc.

Ngoài ra, tôi đã tìm kiếm tài liệu cho nó và tìm thấy nó ở đây: Excel Workbook Close

Cảm ơn,


Nhờ thân mến Michael, Đó là công trình đúng: excelBook.Close (0)
Javad Yousefi

Xin chào các bạn, tính năng này không hoạt động khi bạn đang mở tệp excel để đọc. Sau đây là mã var excelApp = new Application (); var workBooks = excelApp.Workbooks.Open @ "c: \ temp \ myexcel.xlsx"); workBooks.Close (0); excelApp.Quit ();
user1131926

Tôi đã sử dụng applicationClass ... và tôi đã sử dụng mã trên để loại bỏ các đối tượng nhưng nó sẽ không hoạt động ...
Singaravelan

3
Sau nhiều lần thử không thành công với tất cả các câu trả lời này, tôi đã sử dụng giải pháp này để lấy ID quy trình mà tôi đã mở và giết nó trực tiếp.
UndeadBob

@Singaravelan: Bạn đã kiểm tra câu trả lời của David Clarke chưa?
Thế Anh Nguyễn

22
xlBook.Save();
xlBook.Close(true);
xlApp.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp);

thử cái này .. nó hoạt động với tôi ... bạn nên giải phóng đối tượng ứng dụng xl đó để dừng quá trình.


14

Tham khảo: https://stackoverflow.com/a/17367570/132599

Tránh sử dụng các biểu thức gọi hai dấu chấm, chẳng hạn như sau:

var workbook = excel.Workbooks.Open(/*params*/)

... bởi vì theo cách này, bạn tạo các đối tượng RCW không chỉ cho sổ làm việc mà còn cho Sổ làm việc, và bạn cũng nên giải phóng nó (không thể thực hiện được nếu tham chiếu đến đối tượng không được duy trì).

Điều này đã giải quyết vấn đề cho tôi. Mã của bạn trở thành:

public Excel.Application excelApp = new Excel.Application();
public Excel.Workbooks workbooks;
public Excel.Workbook excelBook;
workbooks = excelApp.Workbooks;
excelBook = workbooks.Add(@"C:/pape.xltx");

...

Excel.Sheets sheets = excelBook.Worksheets;
Excel.Worksheet excelSheet = (Worksheet)(sheets[1]);
excelSheet.DisplayRightToLeft = true;
Range rng;
rng = excelSheet.get_Range("C2");
rng.Value2 = txtName.Text;

Và sau đó giải phóng tất cả các đối tượng đó:

System.Runtime.InteropServices.Marshal.ReleaseComObject(rng);
System.Runtime.InteropServices.Marshal.ReleaseComObject(excelSheet);
System.Runtime.InteropServices.Marshal.ReleaseComObject(sheets);
excelBook .Save();
excelBook .Close(true);
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlBook);
System.Runtime.InteropServices.Marshal.ReleaseComObject(workbooks);
excelApp.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp);

Tôi bọc điều này trong một try {} finally {}để đảm bảo mọi thứ được giải phóng ngay cả khi có sự cố xảy ra (điều gì có thể xảy ra?)

public Excel.Application excelApp = null;
public Excel.Workbooks workbooks = null;
...
try
{
    excelApp = new Excel.Application();
    workbooks = excelApp.Workbooks;
    ...
}
finally
{
    ...
    if (workbooks != null) System.Runtime.InteropServices.Marshal.ReleaseComObject(workbooks);
    excelApp.Quit();
    System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp);
}

2
Điều này đã làm việc cho tôi, gán sổ làm việc cho một biến để nó có thể bị xóa. Cũng có một quan sát, tôi có cùng một đoạn mã để xóa ứng dụng excel trong ứng dụng Web và ứng dụng bảng điều khiển. Mã trước khi cập nhật loại bỏ dấu chấm đôi hoạt động tốt trong ứng dụng bảng điều khiển nhưng khi chạy trong ứng dụng web, nó không xóa EXCEL.EXE. Tôi không chắc tại sao chúng hoạt động khác nhau nhưng việc loại bỏ tham chiếu dấu chấm kép đã khắc phục nó trong ứng dụng web.
IronHide

làm việc cho tôi. Tôi nghĩ rằng để chuyển đổi đối tượng, chúng ta phải giải phóng tất cả các đối tượng liên quan. Tôi đã gặp vấn đề tương tự về chương trình solidworks.
Gs.

1
Đóng sổ làm việc, thoát khỏi ứng dụng Excel, tránh gọi hai chấm và giải phóng mọi đối tượng COM đơn lẻ đã tạo. Điều đó đã làm việc cho tôi. Câu trả lời cứu sống. Cảm ơn.
Sinan ILYAS

13

Hãy nghĩ về điều này, nó giết chết quá trình:

System.Diagnostics.Process[] process=System.Diagnostics.Process.GetProcessesByName("Excel");
foreach (System.Diagnostics.Process p in process)
{
    if (!string.IsNullOrEmpty(p.ProcessName))
    {
        try
        {
            p.Kill();
        }
        catch { }
    }
}

Ngoài ra, bạn có thử đóng nó lại bình thường không?

myWorkbook.SaveAs(@"C:/pape.xltx", missing, missing, missing, missing, missing, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange, missing, missing, missing, missing, missing);
excelBook.Close(null, null, null);                 // close your workbook
excelApp.Quit();                                   // exit excel application
excel = null;                                      // set to NULL

Cảm ơn cho giải pháp đầu tiên answer.Your bạn đóng tất cả mở Excel files.when tôi sử dụng 'excelBook.Close', excel tiết kiệm xuất hiện hộp thoại, và tôi không muốn nó :(
Javad Yousefi

1
Tôi sửa nó và thêm vào nó với một dòng để làm SaveAs trong mã này sẽ thay thế hộp thoại bằng mã, hy vọng nó sẽ giúp :).
Morris Miao

1
Tôi chỉ sử dụng điều này với kiểm tra ban đầu cho các quy trình Excel đang mở và lưu các ID trong danh sách. Sau đó, thực hiện một quy trình Excel mới, tôi đã chỉnh sửa và đóng bất kỳ quy trình Excel nào không có trong danh sách ID.
182764125216

Đó không phải là cách chính xác để giải phóng excel từ trình quản lý tác vụ. Bạn nên giải phóng tất cả các đối tượng đã được tạo bao gồm cả những đối tượng đã được tạo ra phía sau hiện trường, chẳng hạn như WorkBOoks.
ehh

Bằng cách này, bạn sẽ giết mọi quy trình Excel đang chạy. Vấn đề là, có thể có người dùng hoặc ứng dụng khác sử dụng Excel cùng lúc. Chỉ cần ghi nhớ nếu bạn sẵn sàng làm điều này.
Sinan ILYAS

5

Việc giết Excel không phải lúc nào cũng dễ dàng; xem bài viết này: 50 cách để giết Excel

Bài viết này lấy lời khuyên tốt nhất từ ​​Microsoft ( MS Knowlege Base Article ) về cách thoát khỏi Excel một cách dễ dàng, nhưng sau đó cũng đảm bảo về điều đó bằng cách hủy bỏ quy trình nếu cần. Tôi thích có một chiếc dù thứ hai.

Đảm bảo Đóng mọi sổ làm việc đang mở, Thoát ứng dụng và Giải phóng đối tượng xlApp. Cuối cùng kiểm tra xem quá trình có còn tồn tại hay không và nếu có thì hãy giết nó.

Bài viết này cũng đảm bảo rằng chúng tôi không giết tất cả các quy trình Excel mà chỉ giết quy trình chính xác đã được bắt đầu.

Xem thêm Nhận quy trình từ Window Handle

Đây là mã tôi sử dụng: (hoạt động mọi lúc)

Sub UsingExcel()

    'declare process; will be used later to attach the Excel process
    Dim XLProc As Process

    'call the sub that will do some work with Excel
    'calling Excel in a separate routine will ensure that it is 
    'out of scope when calling GC.Collect
    'this works better especially in debug mode
    DoOfficeWork(XLProc)

    'Do garbage collection to release the COM pointers
    'http://support.microsoft.com/kb/317109
    GC.Collect()
    GC.WaitForPendingFinalizers()

    'I prefer to have two parachutes when dealing with the Excel process
    'this is the last answer if garbage collection were to fail
    If Not XLProc Is Nothing AndAlso Not XLProc.HasExited Then
        XLProc.Kill()
    End If

End Sub

'http://msdn.microsoft.com/en-us/library/ms633522%28v=vs.85%29.aspx
<System.Runtime.InteropServices.DllImport("user32.dll", SetLastError:=True)> _
    Private Shared Function GetWindowThreadProcessId(ByVal hWnd As IntPtr, _
    ByRef lpdwProcessId As Integer) As Integer
End Function

Private Sub ExcelWork(ByRef XLProc As Process)

    'start the application using late binding
    Dim xlApp As Object = CreateObject("Excel.Application")

    'or use early binding
    'Dim xlApp As Microsoft.Office.Interop.Excel

    'get the window handle
    Dim xlHWND As Integer = xlApp.hwnd

    'this will have the process ID after call to GetWindowThreadProcessId
    Dim ProcIdXL As Integer = 0

    'get the process ID
    GetWindowThreadProcessId(xlHWND, ProcIdXL)

    'get the process
    XLProc = Process.GetProcessById(ProcIdXL)


    'do some work with Excel here using xlApp

    'be sure to save and close all workbooks when done

    'release all objects used (except xlApp) using NAR(x)


    'Quit Excel 
    xlApp.quit()

    'Release
    NAR(xlApp)

End Sub

Private Sub NAR(ByVal o As Object)
    'http://support.microsoft.com/kb/317109
    Try
        While (System.Runtime.InteropServices.Marshal.ReleaseComObject(o) > 0)
        End While
    Catch
    Finally
        o = Nothing
    End Try
End Sub

Đây là giải pháp duy nhất phù hợp với tôi. Cảm ơn.
Jon Vote

2

Tôi đã gặp những vấn đề tương tự và đã thử nhiều phương pháp để giải quyết nó nhưng không hiệu quả. Cuối cùng, tôi đã tìm thấy bằng cách của tôi. Một số tham khảo nhập mô tả liên kết tại đây

Hy vọng mã của tôi có thể giúp ai đó trong tương lai. Tôi đã mất hơn hai ngày để giải quyết nó. Dưới đây là Mã của tôi:

//get current in useing excel
            Process[] excelProcsOld = Process.GetProcessesByName("EXCEL");
            Excel.Application myExcelApp = null;
            Excel.Workbooks excelWorkbookTemplate = null;
            Excel.Workbook excelWorkbook = null;
try{
    //DO sth using myExcelApp , excelWorkbookTemplate, excelWorkbook
}
catch (Exception ex ){
}
finally
            {
                //Compare the EXCEL ID and Kill it 
                Process[] excelProcsNew = Process.GetProcessesByName("EXCEL");
                foreach (Process procNew in excelProcsNew)
                {
                    int exist = 0;
                    foreach (Process procOld in excelProcsOld)
                    {
                        if (procNew.Id == procOld.Id)
                        {
                            exist++;
                        }
                    }
                    if (exist == 0)
                    {
                        procNew.Kill();
                    }        
                }
            }

1

excelBook.Close (); excelApp.Quit (); thêm vào cuối mã, nó có thể là đủ. nó đang hoạt động trên mã của tôi


Có, nhưng khi tôi sử dụng nó, tiết kiệm sẽ xuất hiện hộp thoại, và tôi không muốn nó xuất hiện :(
Javad Yousefi

1

Bạn có thể kết thúc quá trình với COMđối tượng excel pid của riêng bạn

thêm vào đâu đó bên dưới mã nhập dll

[DllImport("user32.dll", SetLastError = true)]
private static extern int GetWindowThreadProcessId(IntPtr hwnd, ref int lpdwProcessId);

Và sử dụng

 if (excelApp != null)
            {
                int excelProcessId = -1;
                GetWindowThreadProcessId(new IntPtr(excelApp.Hwnd), ref excelProcessId);

                Process ExcelProc = Process.GetProcessById(excelProcessId);
                if (ExcelProc != null)
                {
                    ExcelProc.Kill();
                }
            }

1

Tôi nhận thấy rằng điều quan trọng là phải có Marshal.ReleaseComObjecttrong Whilevòng lặp VÀ kết thúc với Bộ sưu tập rác .

static void Main(string[] args)
{
    Excel.Application xApp = new Excel.Application();
    Excel.Workbooks xWbs = xApp.Workbooks;
    Excel.Workbook xWb = xWbs.Open("file.xlsx");

    Console.WriteLine(xWb.Sheets.Count);

    xWb.Close();
    xApp.Quit();

    while (Marshal.ReleaseComObject(xWb) != 0);
    while (Marshal.ReleaseComObject(xWbs) != 0);
    while (Marshal.ReleaseComObject(xApp) != 0);

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

0
         wb.Close();
         app.Quit();

         System.Diagnostics.Process[] process = System.Diagnostics.Process.GetProcessesByName("Excel");
         foreach (System.Diagnostics.Process p in process)
         {
             if (!string.IsNullOrEmpty(p.ProcessName) && p.StartTime.AddSeconds(+10) > DateTime.Now)
             {
                 try
                 {
                     p.Kill();
                 }
                 catch { }
             }
         }

Nó đóng quá trình 10 giây cuối cùng với tên "Excel"


0

Cách phù hợp để đóng tất cả quy trình excel

var _excel = new Application();
foreach (Workbook _workbook in _excel.Workbooks) {
    _workbook.Close(0);
}

_excel.Quit();
_excel = null;
var process = System.Diagnostics.Process.GetProcessesByName("Excel");
foreach (var p in process) {
    if (!string.IsNullOrEmpty(p.ProcessName)) {
        try {
            p.Kill();
        } catch { }
    }
}

0

Dựa trên các giải pháp khác. Tôi đã sử dụng cái này:

IntPtr xAsIntPtr = new IntPtr(excelObj.Application.Hwnd);
excelObj.ActiveWorkbook.Close();

System.Diagnostics.Process[] process = System.Diagnostics.Process.GetProcessesByName("Excel");
                foreach (System.Diagnostics.Process p in process)
                {
                    if (p.MainWindowHandle == xAsIntPtr)
                    {
                        try
                        {
                            p.Kill();
                        }
                        catch { }
                    }
                }

Sử dụng "MainWindowHandle" để xác định quy trình và đóng lại.

excelObj: Đây là đối tượng excel Interop ứng dụng của tôi


0

Sử dụng một biến cho mỗi đối tượng Excel và phải lặp lại Marshal.ReleaseComObject >0. Không có vòng lặp, quy trình Excel vẫn hoạt động.

public class test{
        private dynamic ExcelObject;
        protected dynamic ExcelBook;
        protected dynamic ExcelBooks;
        protected dynamic ExcelSheet;

public void LoadExcel(string FileName)
        {
            Type t = Type.GetTypeFromProgID("Excel.Application");
            if (t == null) throw new Exception("Excel non installato");
            ExcelObject = System.Activator.CreateInstance(t);
            ExcelObject.Visible = false;
            ExcelObject.DisplayAlerts = false;
            ExcelObject.AskToUpdateLinks = false;
            ExcelBooks = ExcelObject.Workbooks;
            ExcelBook = ExcelBooks.Open(FileName,0,true);
            System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application");
            ExcelSheet = ExcelBook.Sheets[1];
        }
 private void ReleaseObj(object obj)
        {
            try
            {
                int i = 0;
             while(   System.Runtime.InteropServices.Marshal.ReleaseComObject(obj) > 0)
                {
                    i++;
                    if (i > 1000) break;
                }
                obj = null;
            }
            catch 
            {
                obj = null;
            }
            finally
            {
                GC.Collect();
            }
        }
        public void ChiudiExcel() {
            System.Threading.Thread.CurrentThread.CurrentCulture = ci;

            ReleaseObj(ExcelSheet);
            try { ExcelBook.Close(); } catch { }
            try { ExcelBooks.Close(); } catch { }
            ReleaseObj(ExcelBooks);
            try { ExcelObject.Quit(); } catch { }
            ReleaseObj(ExcelObject);
        }
}

0

Chúng tôi có thể đóng Ứng dụng Excel trong khi chuyển đổi xls sang xlsx bằng cách sử dụng mã sau. Khi chúng ta thực hiện loại tác vụ này thì ứng dụng Excel đang chạy trong trình quản lý tác vụ, chúng ta nên đóng excel này đang chạy ở chế độ nền. Interop là một thành phần Com, để phát hành thành phần com, chúng tôi đã sử dụng Marshal.FinalReleaseComObject.

 private void button1_Click(object sender, EventArgs e)
    {

        Excel03to07("D:\\TestExls\\TestExcelApp.XLS");

    }
    private void Excel03to07(string fileName)
    {
        string svfileName = Path.ChangeExtension(fileName, ".xlsx");
        object oMissing = Type.Missing;
        var app = new Microsoft.Office.Interop.Excel.Application();
        var wb = app.Workbooks.Open(fileName, oMissing, oMissing,
                        oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing);
        wb.SaveAs(svfileName, XlFileFormat.xlOpenXMLWorkbook, Type.Missing, Type.Missing, Type.Missing, Type.Missing, XlSaveAsAccessMode.xlNoChange, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);

        wb.Close(false, Type.Missing, Type.Missing);
        app.Quit();
        GC.Collect();
        Marshal.FinalReleaseComObject(wb);
        Marshal.FinalReleaseComObject(app);
   }

0

Hầu hết các phương pháp đều hoạt động, nhưng quy trình excel luôn tồn tại cho đến khi đóng ứng dụng.

Khi kill excel process một lần nó không thể được thực thi lại trong cùng một luồng - không biết tại sao.


-1
        GetWindowThreadProcessId((IntPtr)app.Hwnd, out iProcessId);
        wb.Close(true,Missing.Value,Missing.Value);
        app.Quit();
        System.Diagnostics.Process[] process = System.Diagnostics.Process.GetProcessesByName("Excel");
        foreach (System.Diagnostics.Process p in process)
        {
            if (p.Id == iProcessId)
            {
                try
                {
                    p.Kill();
                }
                catch { }
            }
        }
}
[DllImport("user32.dll")]

private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

uint iProcessId = 0;

GetWindowThreadProcessId này tìm đúng Process Id o excell .... Sau khi giết nó .... Hãy tận hưởng nó !!!


-1
private void releaseObject(object obj)
{
    try
    {
        System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
        obj = null;
    }
    catch (Exception ex)
    {
        obj = null;
        MessageBox.Show("Unable to release the Object " + ex.ToString());
    }
    finally
    {
        GC.Collect();
    }
}

Mặc dù mã này có thể giải quyết câu hỏi, bao gồm giải thích về cách thức và lý do tại sao điều này giải quyết vấn đề sẽ thực sự giúp cải thiện chất lượng bài đăng của bạn và có thể dẫn đến nhiều phiếu bầu hơn. Hãy nhớ rằng bạn đang trả lời câu hỏi cho độc giả trong tương lai, không chỉ người hỏi bây giờ. Vui lòng chỉnh sửa câu trả lời của bạn để thêm giải thích và đưa ra dấu hiệu về những giới hạn và giả định nào được áp dụng.
Dave
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.