8

I am trying to export C# DataTable to EXCEL file on the fly (without creating physical file) using Microsoft Office EXCEL INTEROP and download it through asp.net webpage through Response object. I am able to generate memorystream using the library But somehow the file is not getting saved through the memory stream. Reference code is given below. You will be required to take reference for DocumentFormat.OpenXml.dll & WindowsBase.DLL (that you can download from microsoft site).

Any Idea how to resolve the problem ? ? ?

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);
    }
Sankalp
  • 929
  • 1
  • 7
  • 16
  • Why not do it as tab-delimited and then just send that to the user? It will open up in Excel. – James Black May 16 '12 at 23:38
  • 1
    Not really an answer, but i can recommend [EPPLus](http://epplus.codeplex.com/releases/view/42439) to create Excel files on the fly. http://stackoverflow.com/a/10547727/284240 Then all you need is `Response.BinaryWrite(pck.GetAsByteArray());` – Tim Schmelter May 17 '12 at 00:27
  • @James: Thanks for the suggestion. But i don't want to go that way, otherwise i could have been generate .csv file. I want to use INTEROP because in future, i want to add Images/Graphs to the excel sheet (that too on the fly). – Sankalp May 17 '12 at 00:45
  • @Tim: Thanks for the link, the library seems promising. :-) But I am trying to develop the same kind of library. The code that I am using is almost the same code that the library has been written. I need the implementation of ExcelDocument.GetAsByteArray() Method. (i.e. how it is converting from Stream object returned by INTEROP to ByteArray) – Sankalp May 17 '12 at 00:47
  • 2
    @Sankalp: You can use [ILSpy](http://wiki.sharpdevelop.net/ILSpy.ashx) to reflect the code. But bear in mind that it's [LGPL](http://epplus.codeplex.com/license). So why not using it in the first place? – Tim Schmelter May 17 '12 at 00:51

2 Answers2

4

Thanks to All, Finally I Got solution of my problem. I just replaced following line of code:

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

with this line

                    byte[] data1 = fs1.ToArray();

and my problem got resolved.

Sankalp
  • 929
  • 1
  • 7
  • 16
1

After finishing writing to the memory stream, you need to set back the pointer to its origin before reading it.

fs1.Seek(0, SeekOrigin.Begin);   
Tommy
  • 131
  • 1