2012-05-16 17 views
7

Sto tentando di esportare C# DataTable nel file EXCEL al volo (senza creare file fisico) utilizzando Microsoft Office EXCEL INTEROP e scaricarlo tramite asp.net pagina web tramite oggetto di risposta. Sono in grado di generare memorystream usando la libreria Ma in qualche modo il file non viene salvato attraverso il flusso di memoria. Il codice di riferimento è riportato di seguito. Ti verrà richiesto di prendere visione di DocumentFormat.OpenXml.dll & WindowsBase.DLL (che puoi scaricare dal sito microsoft).Scaricare il file EXCEL dalla pagina ASP.NET senza Generare file fisico sul server (On The Fly)

Qualche idea su come risolvere il problema? ? ?

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

Perché non farlo come delimitato da tabulazioni e quindi inviarlo all'utente? Si aprirà in Excel. –

+1

Non proprio una risposta, ma posso raccomandare [EPPLus] (http://epplus.codeplex.com/releases/view/42439) per creare file Excel al volo. http://stackoverflow.com/a/10547727/284240 Quindi tutto ciò di cui hai bisogno è 'Response.BinaryWrite (pck.GetAsByteArray());' –

+0

@James: Grazie per il suggerimento. Ma non voglio andare in quel modo, altrimenti avrei potuto generare un file .csv. Voglio usare INTEROP perché in futuro, voglio aggiungere immagini/grafici al foglio excel (che anche al volo). – Sankalp

risposta

3

grazie a tutti, Finalmente ho avuto la soluzione del mio problema. Ho appena sostituito seguente riga di codice:

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

con questa linea

    byte[] data1 = fs1.ToArray(); 

e il mio problema ho risolto.

1

Dopo aver terminato la scrittura sul flusso di memoria, è necessario riportare il puntatore all'origine prima di leggerlo.

fs1.Seek(0, SeekOrigin.Begin); 
Problemi correlati