使用ReportViewer内置function导出到Excel

我想知道是否有可能将Excel输出设置为“locking”,即当我们尝试更改单元格的值时,将会有一个警告,指示我们不能更改它,除非我们删除工作表的保护。

我知道我们可以开发一个自定义的Excel自动化代码,并在我们保存之前设置一个密码来保护表单。 但是,有没有简单的方法来完成这个使用ReportViewer的内置function?

在做了一些研究后,我find了解决方法:)这个想法是拦截ReportViewer的导出报告function,然后运行我们自己的过程。 这个过程将得到输出,这是生成的Excel文件,然后读取它并应用所需的任何更改,并在作为“下载到用户”发送之前再次保存。 但是,应该指出,根据我们使用的报告types,拦截方法会有所不同。 在我的情况下,我的ReportViewer使用的是WebForm而不是WinForm,大多数解释是关于ReportExport事件的解释,它只在WinForm中可用。

对于那些使用WinForm,你可以像这样覆盖ReportExport事件:

void reportViewer_ReportExport(object sender, Microsoft.Reporting.WinForms.ReportExportEventArgs e) { e.Cancel = true; // insert your own code to export excel } 

在WebForm中,没有ReportExport的事件处理程序。 我能想到的选项是在.aspx中创build一个自定义button,它将执行我们的自定义代码,或者直接渲染excel而不需要预览报表。 我决定直接渲染excel文件。 我将使用数据集并从“存储过程”中获取数据。 然后,我将数据集分配到RDLC中,并调用Render方法来获取输出。 输出格式是byte [],我用FileStream来写它。 完成后,我使用Interop打开Excel文件并应用保护。 这里是代码:

 // Setup DataSet (Adapter and Table) YourTableAdapters.ATableAdapter ds = new YourTableAdapters.ATableAdapter(); YourDataSet.ADataTable dt = new YourDataSet.ADataTable (); ds.Fill(dt, outlet, period); // Create Report DataSource ReportDataSource rds = new ReportDataSource("DataSet1", (System.Data.DataTable)dt); // Variables needed for ReportViewer Render method Warning[] warnings; string[] streamIds; string mimeType = string.Empty; string encoding = string.Empty; string extension = string.Empty; // Setup the report viewer object and get the array of bytes ReportViewer viewer = new ReportViewer(); viewer.ProcessingMode = ProcessingMode.Local; viewer.LocalReport.ReportPath = "YourReport.rdlc"; viewer.LocalReport.DataSources.Add(rds); // Add datasource here byte[] bytes = viewer.LocalReport.Render("Excel", null, out mimeType, out encoding, out extension, out streamIds, out warnings); // Prepare filename and save_path, and then write the Excel using FileStream. String temp_path = Path.Combine(Server.MapPath(Config.ReportPath), "FileName.xls"); FileStream fs = new FileStream(temp_path, FileMode.Create); fs.Write(bytes, 0, bytes.Length); fs.Close(); // Open the Excel file created, and add password protection. PIDExcel pidexcel = new PIDExcel(); pidexcel.CollectExcelPID(); Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application(); Microsoft.Office.Interop.Excel.Range lock_range = null; int excelid = pidexcel.GetNewExcelID(); Microsoft.Office.Interop.Excel.Workbook xlWorkBook = null; try { //xlApp.Visible = true; xlWorkBook = (Microsoft.Office.Interop.Excel.Workbook)xlApp.Workbooks.Open(temp_path, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing); foreach(Microsoft.Office.Interop.Excel.Worksheet displayWorksheet in xlApp.ActiveWorkbook.Worksheets) { lock_range = xlApp.Cells; lock_range.Select(); lock_range.EntireColumn.Locked = true; displayWorksheet.Protect("<your password here>"); } } catch (Exception ex) { throw new Exception(ex.Message.Replace("'", "")); ; } finally { // Set First Sheet Active xlWorkBook.Sheets[1].Select(); xlApp.DisplayAlerts = false; xlWorkBook.Save(); xlWorkBook.Close(Type.Missing, Type.Missing, Type.Missing); xlApp.Quit(); System.Runtime.InteropServices.Marshal.FinalReleaseComObject(xlWorkBook); System.Runtime.InteropServices.Marshal.FinalReleaseComObject(xlApp); GC.WaitForPendingFinalizers(); GC.Collect(); pidexcel.KillExcel(excelid); } 

通过使用这个概念,我可以轻松地devise报表输出,因为我使用RDLC作为模板来填充由SP提供的数据,然后进行渲染。 想象一下,如果我们使用Excel手动编写报告(设置边界,合并单元格,分组),麻烦就大了。