Загрузите файл EXCEL со страницы ASP.NET без создания физического файла на сервере (на лету)

Я пытаюсь экспортировать C # DataTable в файл EXCEL на лету (без создания физического файла) с помощью Microsoft Office EXCEL INTEROP и загрузить его через веб-страницу asp.net через объект Response. Я могу генерировать поток памяти с помощью библиотеки, но почему-то файл не сохраняется через поток памяти. Код ссылки приведен ниже. Вам потребуется взять ссылку на DocumentFormat.OpenXml.dll и WindowsBase.DLL (которые вы можете скачать с сайта Microsoft).

Любая идея, как решить проблему? ? ?

Private void DownloadFile()
{
                DataSet objTable = ReadTableFromViewstate();
            if (objTable != null && objTable.Rows.Count > 0)
            {

                string strDownloadableFilename = "TestExcelFileName.xls";
                MemoryStream fs1 = new MemoryStream();
                if (CreateExcelFile.CreateExcelDocument(objTable, fs1))
                {
                    Response.Clear();
                        byte[] data1 = new byte[fs1.Length];
                        fs1.Read(data1, 0, data1.Length);
                        fs1.Close();

                    Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
                    Response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}", strDownloadableFilename));
                    Response.BinaryWrite(data1); ;
                   Response.End();

                }
                else
                {
                    LblErrorMessage.Text = "Error Exporting File.";
                }
            }

        }

..

public static bool CreateExcelDocument(DataSet ds, System.IO.Stream excelFileStream)
    {
        try
        {
            using (SpreadsheetDocument document = SpreadsheetDocument.Create(excelFileStream, SpreadsheetDocumentType.Workbook))
            {
                CreateParts(ds, document);
            }

            Trace.WriteLine("Successfully created: " + excelFileStream);
            return true;
        }
        catch (Exception ex)
        {
            Trace.WriteLine("Failed, exception thrown: " + ex.Message);
            return false;
        }
    }
..




private static void CreateParts(DataSet ds, SpreadsheetDocument document)
        {
            WorkbookPart workbookPart = document.AddWorkbookPart();
            Workbook workbook = new Workbook();
            workbookPart.Workbook = workbook;

            //  If we don't add a "WorkbookStylesPart", OLEDB will refuse to connect to this .xlsx file !

                WorkbookStylesPart workbookStylesPart = workbookPart.AddNewPart<WorkbookStylesPart>("rIdStyles");
            Stylesheet stylesheet = new Stylesheet();

            workbookStylesPart.Stylesheet = stylesheet;

            Sheets sheets = new Sheets();

            //  Loop through each of the DataTables in our DataSet, and create a new Excel Worksheet for each.
        uint worksheetNumber = 1;
        foreach (DataTable dt in ds.Tables)
        {
            //  For each worksheet you want to create
            string workSheetID = "rId" + worksheetNumber.ToString();
            string worksheetName = dt.TableName;

            WorksheetPart worksheetPart = workbookPart.AddNewPart<WorksheetPart>(workSheetID);
            WriteDataTableToExcelWorksheet(dt, worksheetPart);

            Sheet sheet = new Sheet() { Name = worksheetName, SheetId = (UInt32Value)worksheetNumber, Id = workSheetID };
            sheets.Append(sheet);

            worksheetNumber++;
        }

        workbook.Append(sheets);
    }

person Sankalp    schedule 16.05.2012    source источник
comment
Почему бы не сделать это с разделителями табуляции, а затем просто отправить это пользователю? Он откроется в Excel.   -  person James Black    schedule 17.05.2012
comment
Не совсем ответ, но я могу порекомендовать EPPLus для создания файлов Excel на лету. stackoverflow.com/a/10547727/284240 Тогда все, что вам нужно, это Response.BinaryWrite(pck.GetAsByteArray());   -  person Tim Schmelter    schedule 17.05.2012
comment
@James: Спасибо за предложение. Но я не хочу идти по этому пути, иначе я мог бы сгенерировать файл .csv. Я хочу использовать INTEROP, потому что в будущем я хочу добавлять изображения/графики на лист Excel (тоже на лету).   -  person Sankalp    schedule 17.05.2012
comment
@Tim: Спасибо за ссылку, библиотека кажется многообещающей. :-) Но я пытаюсь разработать такую ​​же библиотеку. Код, который я использую, почти такой же, как и в библиотеке. Мне нужна реализация метода ExcelDocument.GetAsByteArray(). (т.е. как он преобразуется из объекта Stream, возвращаемого INTEROP, в ByteArray)   -  person Sankalp    schedule 17.05.2012
comment
@Sankalp: вы можете использовать ILSpy для отражения кода. Но имейте в виду, что это LGPL. Так почему бы не использовать его в первую очередь?   -  person Tim Schmelter    schedule 17.05.2012


Ответы (2)


Спасибо всем, наконец-то я получил решение своей проблемы. Я просто заменил следующую строку кода:

                    byte[] data1 = new byte[fs1.Length];
                    fs1.Read(data1, 0, data1.Length);
                    fs1.Close();

с этой строкой

                    byte[] data1 = fs1.ToArray();

и моя проблема решилась.

person Sankalp    schedule 17.05.2012

После завершения записи в поток памяти вам необходимо установить указатель на его источник, прежде чем читать его.

fs1.Seek(0, SeekOrigin.Begin);   
person Tommy    schedule 17.05.2012