2012-05-16 16 views
7

Próbuję wyeksportować plik C# DataTable do pliku EXCEL w locie (bez tworzenia fizycznego pliku) przy użyciu Microsoft Office EXCEL INTEROP i pobrać go przez Strona asp.net poprzez obiekt Response. Jestem w stanie wygenerować memorystream przy użyciu biblioteki, ale jakoś plik nie jest zapisywany przez strumień pamięci. Kod referencyjny podano poniżej. Będziesz musiał pobrać referencję dla DocumentFormat.OpenXml.dll & WindowsBase.DLL (można pobrać z witryny Microsoft).Pobierz plik EXCEL ze strony ASP.NET bez generowania pliku fizycznego na serwerze (w locie)

Każdy pomysł, jak rozwiązać 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); 
    } 
+0

Dlaczego nie zrobić tego jako rozdzielanego tabulatorami, a następnie po prostu wysłać to do użytkownika? Otworzy się w Excelu. –

+1

Naprawdę nie jest to odpowiedź, ale mogę polecić [EPPLus] (http://epplus.codeplex.com/releases/view/42439) do szybkiego tworzenia plików Excel. http://stackoverflow.com/a/10547727/284240 Następnie wszystko, czego potrzebujesz, to 'Response.BinaryWrite (pck.GetAsByteArray());' –

+0

@ James: Dzięki za sugestię. Ale nie chcę iść w ten sposób, w przeciwnym razie mógłbym wygenerować plik .csv. Chcę użyć INTEROP, ponieważ w przyszłości chcę dodać Grafiki/Grafiki do arkusza Excela (który też w locie). – Sankalp

Odpowiedz

3

Dzięki wszystkim, koniec I Got rozwiązanie mojego problemu. Ja po prostu zastąpić następującą linię kodu:

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

z tej linii

    byte[] data1 = fs1.ToArray(); 

i mój problem został rozwiązany.

1

Po zakończeniu zapisywania w strumieniu pamięci, musisz przywrócić wskaźnik do jego źródła przed jego odczytaniem.

Powiązane problemy