简体   繁体   English

使用C#ReportViewer的文件流创建新的Excel工作表

[英]Create new excel worksheet with filestream from c# reportviewer

I have this code to render a reportviewer : 我有这段代码来呈现一个reportviewer

Warning[] warnings;
string[] streamids;
string mimeType;
string encoding;
string extension;

FileStream fs = new FileStream(@"c:\output.xls", FileMode.Create);

foreach (ReportViewer report in this.reports)
{    
    byte[] bytes = report.LocalReport.Render("Excel", null, out mimeType, out encoding, out extension, out streamids, out warnings);

    fs.Write(bytes, 0, bytes.Length);
}

fs.Close();

My problem is that only the first report is viewable in the excel file with the name of the report as the worksheet name. 我的问题是在excel文件中只有第一个报告是可见的,报告的名称为工作表名称。 It appears as though the rest are there (the file size increases) but just not formatted correctly. 看起来好像其余的都在那里 (文件大小增加了),但是格式不正确。

How do I make each report go into a different worksheet? 如何使每个报告进入不同的工作表?

Notes: 笔记:

I tried adding a device info string to for startpage = 0 but that didnt help either. 我尝试将设备信息字符串添加到起始页= 0,但这也没有帮助。

I am trying to avoid using an extra library to accomplish this, it is part of a very lightweight program. 我试图避免使用额外的库来完成此操作,它是一个非常轻量级程序的一部分。

Similar unanswered question: https://stackoverflow.com/questions/20763129/how-to-export-data-to-excel-via-reportviewer-with-multiple-named-worksheets 相似的未解决问题: https : //stackoverflow.com/questions/20763129/how-to-export-data-to-excel-via-reportviewer-with-multiple-named-worksheets

So I figured it out.. 所以我想通了..

  • Create an excel object with an empty workbook 用空的工作簿创建一个Excel对象
  • Render each report to the output file 将每个报告渲染到输出文件
  • After rendered, load the file into the excel object as another workbook 呈现后,将该文件作为另一个工作簿加载到excel对象中
  • Repeat steps 2 and 3 for each report (overwriting the excel file) 对每个报告重复步骤2和3(覆盖Excel文件)
  • Copy each workbook into the first 将每个工作簿复制到第一个
  • Save the workbook over the desired file 将工作簿保存在所需文件上

Kinda crazy, but it works and only uses the file specified by a savefiledialog so its all safe and good to go: Kinda很疯狂,但是它可以正常工作,并且只使用savefiledialog指定的文件,因此一切安全无虞:

FileStream fs = null;
Microsoft.Office.Interop.Excel.Application app = null;
try
{
    app = new Microsoft.Office.Interop.Excel.Application();
    app.Workbooks.Add("");

    Warning[] warnings;
    string[] streamids;
    string mimeType;
    string encoding;
    string extension;

    // Uses a string of comma separated ints to determine which reports to print
    foreach (string indexChecked in Properties.Settings.Default.PrintAllReports.Split(','))
    {
        // Create temp file
        fs = new FileStream(saveFileDialog1.FileName, FileMode.Create);
        byte[] bytes = this.reports[Convert.ToInt32(indexChecked)].LocalReport.Render("EXCELOPENXML", null, out mimeType, out encoding, out extension, out streamids, out warnings);
        fs.Write(bytes, 0, bytes.Length);
        fs.Close();
        fs = null;
        // Add copy of workbook
        app.Workbooks.Add(saveFileDialog1.FileName);
    }

    // Process each workbook and combine
    // http://stackoverflow.com/questions/7376964/how-to-merge-two-excel-workbook-into-one-workbook-in-c
    for (int i = app.Workbooks.Count; i >= 2; i--)
    {
        int count = app.Workbooks[i].Worksheets.Count;
        app.Workbooks[i].Activate();

        for (int j = 1; j <= count; j++)
        {
            Microsoft.Office.Interop.Excel._Worksheet ws = (Microsoft.Office.Interop.Excel._Worksheet)app.Workbooks[i].Worksheets[j];
            ws.Select(Type.Missing);
            ws.Cells.Select();

            Microsoft.Office.Interop.Excel.Range sel = (Microsoft.Office.Interop.Excel.Range)app.Selection;
            sel.Copy(Type.Missing);

            Microsoft.Office.Interop.Excel._Worksheet sheet = (Microsoft.Office.Interop.Excel._Worksheet)app.Workbooks[1].Worksheets.Add(
                Type.Missing, Type.Missing, Type.Missing, Type.Missing
            );

            sheet.Paste(Type.Missing, Type.Missing);
            sheet.Name = ws.Name;
            Clipboard.Clear();
            app.Workbooks[i].Close();
        }
    }

    // Remove it if it exists, we already asked once
    if (System.IO.File.Exists(saveFileDialog1.FileName))
    {
        try
        {
            System.IO.File.Delete(saveFileDialog1.FileName);
        }
        catch (System.IO.IOException)
        {
            // It will ask and then overwrite in the next step if the delete failed
        }
    }
    app.Workbooks[1].SaveAs(saveFileDialog1.FileName, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, XlSaveAsAccessMode.xlNoChange, XlSaveConflictResolution.xlLocalSessionChanges);
    app.Workbooks[1].Close();
    app = null;
}
catch (IOException)
{
    // uses a wrapper method
    this.showErrorDialog("Report Generator cannot access the file '" + saveFileDialog1.FileName + "'. There are several possible reasons:\n\n\u2022 The file name or path does not exist.\n\u2022 The file is being used by another program.");
}
finally
{
    if (fs != null)
    {
        fs.Close();
    }
    if (app != null)
    {
        app.Workbooks.Close();
    }
}

Any input/feedback is welcome. 欢迎任何输入/反馈。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM