2016-08-02 113 views
0

在C#,asp.net 4.0的項目,我創建使用的Microsoft.Office.Interop.Excel的Excel文件。該文件被正確創建並被放置在服務器上的文件夾中。但是,我一直無法想出將文件顯示給客戶端的方法。有人能幫我嗎?如何將Excel文件下載到用戶的下載文件夾?

一些背景:我試圖解決的是從攔截了Excel文件的微軟改變。我們的Web應用程序使用Telerik網格,並使用ExportToExcel函數將該網格導出到Excel文件。文件下載(轉到用戶的下載文件),但是當用戶試圖打開它時,他們會得到一個空白的Excel應用程序。有解決方法,例如卸載創建此問題的修補程序,關閉Excel安全選項,並單擊文件屬性中的解除阻止;但是,我們的客戶不想做任何這些。所以我重寫了40多個網格的出口。

我得到了來自radgrid控件的數據到DataTable,並使用此代碼的工作就寫入Excel中:

  Microsoft.Office.Interop.Excel.Application m_objExcel = null; 
      Microsoft.Office.Interop.Excel.Workbooks m_objBooks = null; 
      Microsoft.Office.Interop.Excel._Workbook m_objBook = null; 
      Microsoft.Office.Interop.Excel.Sheets m_objSheets = null; 
      Microsoft.Office.Interop.Excel._Worksheet m_objSheet = null; 
      object m_objOpt = System.Reflection.Missing.Value; 

      m_objExcel = new Microsoft.Office.Interop.Excel.Application(); 
      m_objBooks = (Microsoft.Office.Interop.Excel.Workbooks)m_objExcel.Workbooks; 
      m_objBook = (Microsoft.Office.Interop.Excel._Workbook)(m_objBooks.Add(m_objOpt)); 

      m_objSheets = (Microsoft.Office.Interop.Excel.Sheets)m_objBook.Worksheets; 
      m_objSheet = (Microsoft.Office.Interop.Excel._Worksheet)(m_objSheets.get_Item(1)); 

      int colcount = 1; 
      foreach (DataColumn col in dt.Columns) 
      { 
       m_objSheet.Cells[1, colcount] = col.ColumnName; 
       colcount++; 
      } 

      int rowcount = 2; 
      foreach (DataRow row in dt.Rows) 
      { 
       for (int i = 1; i < dt.Columns.Count; i++) 
       { 
        m_objSheet.Cells[rowcount, i] = row[i - 1].ToString(); 
       } 
       rowcount++; 
      } 

      string currentDateTime = DateTime.Now.ToString("yyyyMMddHHmmss"); 

      m_objBook.SaveAs("C:\\Temp\\MD" + currentDateTime + ".xlsx"); 
      m_objBook.Close(); 

      m_objExcel.DisplayAlerts = false; 
      m_objExcel.Quit(); 

我的問題是當我試圖讓用戶下載該文件。我嘗試了下面的代碼,但是我得到一個錯誤,說「進程無法訪問文件'C:\ Temp \ MD20160802161458.xlsx',因爲它正在被另一個進程使用。」任何人都可以解釋如何在通過Excel創建文件後取消阻止該文件,或者向我展示另一種將文件下載到用戶的方式?

string fileName = "C:\\Temp\\MD" + currentDateTime + ".xlsx", myStringWebResource = null; 
WebClient myWebClient = new WebClient(); 
myStringWebResource = fileName; 
myWebClient.DownloadFile(myStringWebResource, fileName); 

我也試過下面的代碼打開Excel文件。該文件在服務器上創建,但從不打開。當我嘗試打開服務器上的文件時,Excel崩潰。我懷疑這是因爲我在開發計算機上安裝了Excel 2013,而Excel 2007在服務器上。這引發了另一個問題,因爲我無法保證最終生產服務器上的Excel版本是什麼。任何建議,將不勝感激。

  var excelApp = new Microsoft.Office.Interop.Excel.Application(); 
      excelApp.Visible = true; 
      excelApp.Workbooks.Open("C:\\Temp\\MD" + currentDateTime + ".xlsx"); 
      m_objExcel.Quit(); 
+0

嘗試使用不受MS修補程序影響的不同導出格式。我認爲BIFF選項應該可行。 – rdmptn

回答

0

首先要檢查的是Excel進程是否仍在服務器上運行。 Microsoft強烈建議不要在生產服務器環境中使用Microsoft Interop組件,原因很多。他們從來沒有爲此目的。這是最近的文章中,我可以(快速)發現:

https://support.microsoft.com/en-us/kb/257757

微軟目前並不提倡,不支持,Microsoft Office應用程序自動化從任何無人蔘與的非交互式客戶端應用程序或組件(包括ASP,ASP.NET,DCOM和NT服務),因爲Office在此環境中運行時可能會出現不穩定的行爲和/或死鎖。

我試過這條路線(由於客戶的要求)在很多場合都出現了問題。其中最大的問題是Excel互操作組件有一個非常討厭的習慣,即不會終止Excel進程,這意味着當您嘗試打開並將其發送給客戶端時,Excel可能仍會打開文件。解決方法是(字面上)編寫枚舉計算機上正在運行的進程並關閉任何Excel實例的代碼,但當然,您正在冒着關閉正在執行實際工作的實例的風險。

有很多實惠的組件,在那裏,工作更加可靠(如ComponentPro - 他們沒有隸屬關係,但我已經用他們的成分在許多場合),可以用很少的努力來實現。

編輯 - 如果你必須使用互操作和強制Excel關閉

This StackOverflow article有很多這樣做的不同的機制。根據你在做什麼,你可能不得不嘗試多個路線。釋放COM對象似乎對我來說最清潔。

+0

感謝您的回覆。如何檢查Excel進程是否在服務器上運行?我們通常不這樣做Excel文件,但由於我們的舊方法由於Microsoft做出的更改而不起作用,我被告知儘快找到解決方案。恐怕我的老闆不會去購買任何軟件,但是謝謝你的推薦。 – boilers222

+0

@ boilers222添加了一些鏈接,以確保Excel已關閉。 – DVK