2016-08-02 111 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