2012-12-18 43 views
12

如何讀取剛發佈到我的服務器的Excel電子表格? 我搜索了一些東西,但我只找到了如何閱讀Excel電子表格的文件名路徑,這不是我的情況。在內存中讀取Excel電子表格

我需要類似的東西:

public ActionResult Import(HttpPostedFileBase file) 
{ 
    var excel = new ExcelQueryFactory(file); //using linq to excel 
} 
+1

這個問題的可能重複:

在代碼文件的頂部導入的命名空間[讀取Excel從流文件](HTTP://計算器.COM /問題/ 560435 /讀取Excel的文件從-A-流)? –

+0

您必須考慮如下問題:如果桌子不在第一張桌子上,該怎麼辦?如果它不在您指定的範圍內,該怎麼辦? Excel具有OleDb功能,但您必須使用像GetOleDbSchema()這樣的方法來獲取選項卡,然後知道要查詢的範圍。這是可能的,但它不只是3行代碼。 –

+0

@DominicZukiewicz在我的情況下,這不是一個真正的問題,因爲每個上傳文件將具有相同的架構。 – MuriloKunze

回答

13

不幸的是,使用LinqToExcel從流中讀取電子表格是不可能的。

這是因爲它使用OLEDB從電子表格中讀取並且無法從流中讀取。

19

我遇到了同樣的問題,但我不想切換到付費服務,所以這就是我所做的。

public class DataImportHelper : IDisposable 
{ 
    private readonly string _fileName; 
    private readonly string _tempFilePath; 

    public DataImportHelper(HttpPostedFileBase file, string tempFilePath) 
    { 
     _fileName = file.FileName; 
     _tempFilePath = Path.Combine(tempFilePath, _fileName); 
     (new FileInfo(_tempFilePath)).Directory.Create(); 
     file.SaveAs(_tempFilePath); 
    } 

    public IQueryable<T> All<T>(string sheetName = "") 
    { 
     if (string.IsNullOrEmpty(sheetName)) 
     { 
      sheetName = (typeof (T)).Name; 
     } 

     var excelSheet = new ExcelQueryFactory(_tempFilePath); 

     return from t in excelSheet.Worksheet<T>(sheetName) 
       select t; 
    } 

    public void Dispose() 
    { 
     File.Delete(_tempFilePath); 
    } 

} 

下面是測試

[Fact] 
    public void AcceptsAMemoryStream() 
    { 
     MemoryFile file; 

     using (var f = File.OpenRead("SampleData.xlsx")) 
     { 
      file = new MemoryFile(f, "multipart/form-data", "SampleData.xlsx"); 

      using (var importer = new DataImportHelper(file, "Temp/")) 
      { 
       var products = importer.All<Product>(); 

       Assert.NotEmpty(products); 

      } 
     } 
    } 

這裏是MemoryFile.cs。該文件僅用於測試。它只是HttpPostedFileBase的一個實現,所以你可以測試你的控制器和我的小幫手。這是從另一個帖子借來的。

public class MemoryFile : HttpPostedFileBase 
    { 
     Stream stream; 
     string contentType; 
     string fileName; 

     public MemoryFile(Stream stream, string contentType, string fileName) 
     { 
      this.stream = stream; 
      this.contentType = contentType; 
      this.fileName = fileName; 
     } 

     public override int ContentLength 
     { 
      get { return (int)stream.Length; } 
     } 

     public override string ContentType 
     { 
      get { return contentType; } 
     } 

     public override string FileName 
     { 
      get { return fileName; } 
     } 

     public override Stream InputStream 
     { 
      get { return stream; } 
     } 

     public override void SaveAs(string filename) 
     { 
      using (var file = File.Open(filename, FileMode.Create)) 
       stream.CopyTo(file); 
     } 
    } 
+0

這個問題不錯,我做了這樣的事來解決我的問題。 – MuriloKunze

+0

感謝Brett Allred,這有幫助! – escist

0

您可以使用HttpPostedFileBaseInputStream屬性來讀取內存中的Excel電子表格。

我用ClosedXML nuget包來讀取您的案例中可用的流中的excel內容。它有一個簡單的重載,它將流指向流的Excel文件(又名工作簿)。

using ClosedXML.Excel; 

源代碼:

public ActionResult Import(HttpPostedFileBase file) 
{ 
    //HttpPostedFileBase directly is of no use so commented your code 
    //var excel = new ExcelQueryFactory(file); //using linq to excel 
    var stream = file.InputStream; 
    if (stream.Length != 0) 
    { 
     //handle the stream here 
     using (XLWorkbook excelWorkbook = new XLWorkbook(stream)) 
     { 
      var name = excelWorkbook.Worksheet(1).Name; 
      //do more things whatever you like as you now have a handle to the entire workbook. 
      var firstRow = excelWorkbook.Worksheet(1).Row(1); 
     } 
    } 
}