2012-09-14 37 views
20

需要能夠讀取Excel文件上上傳。該解決方案將託管在服務器上。我不想將Excel文件存儲在服務器上。 我想直接在Excel中的內容轉換爲數據集或數據表和利用。在ASP.NET中使用FileUploadControl閱讀使用FileUpload控件上載的Excel文件,但不保存在服務器

下面是兩種解決方案我已經找到,但不會爲我工作。

  1. LINQTOEXCEL - 當你有你的本地計算機上的Excel文件,你是在本地計算機上運行代碼,此方法有效。就我而言,用戶正嘗試使用服務器上託管的網頁從本地機器上傳Excel文件。

  2. ExcelDataReader - 我目前使用的這一個,但是這是一個第三方工具。我無法將此轉移給我們的客戶。另外,如果行/列交叉點攜帶公式,則該行/列交叉點的數據不會被讀入數據集。

當我在google和StackOverflow上發現的大部分建議都可以在Excel和.NET解決方案都在同一臺機器上時使用。但是在我的情況下,當解決方案託管在服務器上時,我需要它工作,並且用戶正嘗試使用本地計算機上的託管網頁上載Excel。 如果您有任何其他建議,請讓我知道嗎?

回答

32

您可以使用HttpPostedFileInputStream屬性文件讀入到內存中。

這裏是它展示瞭如何從一個HttpPostedFileIO.Stream使用EPPlus創建DataTable一個例子:

protected void UploadButton_Click(Object sender, EventArgs e) 
{ 
    if (FileUpload1.HasFile && Path.GetExtension(FileUpload1.FileName) == ".xlsx") 
    { 
     using (var excel = new ExcelPackage(FileUpload1.PostedFile.InputStream)) 
     { 
      var tbl = new DataTable(); 
      var ws = excel.Workbook.Worksheets.First(); 
      var hasHeader = true; // adjust accordingly 
      // add DataColumns to DataTable 
      foreach (var firstRowCell in ws.Cells[1, 1, 1, ws.Dimension.End.Column]) 
       tbl.Columns.Add(hasHeader ? firstRowCell.Text 
        : String.Format("Column {0}", firstRowCell.Start.Column)); 

      // add DataRows to DataTable 
      int startRow = hasHeader ? 2 : 1; 
      for (int rowNum = startRow; rowNum <= ws.Dimension.End.Row; rowNum++) 
      { 
       var wsRow = ws.Cells[rowNum, 1, rowNum, ws.Dimension.End.Column]; 
       DataRow row = tbl.NewRow(); 
       foreach (var cell in wsRow) 
        row[cell.Start.Column - 1] = cell.Text; 
       tbl.Rows.Add(row); 
      } 
      var msg = String.Format("DataTable successfully created from excel-file. Colum-count:{0} Row-count:{1}", 
            tbl.Columns.Count, tbl.Rows.Count); 
      UploadStatusLabel.Text = msg; 
     } 
    } 
    else 
    { 
     UploadStatusLabel.Text = "You did not specify a file to upload."; 
    } 
} 

這裏的VB.NET版本

Sub UploadButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) 
    If (FileUpload1.HasFile AndAlso IO.Path.GetExtension(FileUpload1.FileName) = ".xlsx") Then 
     Using excel = New ExcelPackage(FileUpload1.PostedFile.InputStream) 
      Dim tbl = New DataTable() 
      Dim ws = excel.Workbook.Worksheets.First() 
      Dim hasHeader = True ' change it if required ' 
      ' create DataColumns ' 
      For Each firstRowCell In ws.Cells(1, 1, 1, ws.Dimension.End.Column) 
       tbl.Columns.Add(If(hasHeader, 
            firstRowCell.Text, 
            String.Format("Column {0}", firstRowCell.Start.Column))) 
      Next 
      ' add rows to DataTable ' 
      Dim startRow = If(hasHeader, 2, 1) 
      For rowNum = startRow To ws.Dimension.End.Row 
       Dim wsRow = ws.Cells(rowNum, 1, rowNum, ws.Dimension.End.Column) 
       Dim row = tbl.NewRow() 
       For Each cell In wsRow 
        row(cell.Start.Column - 1) = cell.Text 
       Next 
       tbl.Rows.Add(row) 
      Next 
      Dim msg = String.Format("DataTable successfully created from excel-file Colum-count:{0} Row-count:{1}", 
            tbl.Columns.Count, tbl.Rows.Count) 
      UploadStatusLabel.Text = msg 
     End Using 
    Else 
     UploadStatusLabel.Text = "You did not specify an excel-file to upload." 
    End If 
End Sub 

對於完整的緣故,這裏的ASPX:

<div> 
    <h4>Select a file to upload:</h4> 

    <asp:FileUpload id="FileUpload1"     
     runat="server"> 
    </asp:FileUpload> 

    <br /><br /> 

    <asp:Button id="UploadButton" 
     Text="Upload file" 
     OnClick="UploadButton_Click" 
     runat="server"> 
    </asp:Button>  

    <hr /> 

    <asp:Label id="UploadStatusLabel" 
     runat="server"> 
    </asp:Label>   
</div> 
+0

嘿添,感謝您的快速反應。我相信這將需要Microsoft Office安裝在託管服務器上。如果是,請問我是否還有其他解決方法?如果沒有,那麼沒問題。我會測試這個並讓你知道。 – Chandra

+0

@Chandra:正如我在[LGPL許可證](http://epplus.codeplex.com/license)下使用['EPPLus'](http://epplus.codeplex.com/)所述。我可以熱烈地推薦它,我不是唯一的。 http://stackoverflow.com/a/2603625/284240(在接受的答案Jan本身旁邊) –

+0

感謝您的快速響應!我看到這是開源代碼,這又難以將其推向我們的高知名度客戶。是否有可能使用純.NET代碼實現這一點? – Chandra

0

也許你可以看看Koogra這是一個開源Excel的讀者(只讀作者)我認爲你會從客戶端得到一個流。然後,您可以像現在這樣做所有事情從內存流中讀取數據並寫入數據庫。

我希望這會有所幫助。

2
//Best Way To read file direct from stream 
IExcelDataReader excelReader = null; 
//file.InputStream is the file stream stored in memeory by any ways like by upload file control or from database 
int excelFlag = 1; //this flag us used for execl file format .xls or .xlsx 
if (excelFlag == 1) 
{ 
    //1. Reading from a binary Excel file ('97-2003 format; *.xls) 
    excelReader = ExcelReaderFactory.CreateBinaryReader(file.InputStream); 
} 
else if(excelFlag == 2)         
{ 
    //2. Reading from a OpenXml Excel file (2007 format; *.xlsx) 
    excelReader = ExcelReaderFactory.CreateOpenXmlReader(file.InputStream); 
} 

if (excelReader != null) 
{ 
    //... 
    //3. DataSet - The result of each spreadsheet will be created in the result.Tables 
    ds = excelReader.AsDataSet(); 
    //... 
    ////4. DataSet - Create column names from first row 
    //excelReader.IsFirstRowAsColumnNames = true; 
    //DataSet result = excelReader.AsDataSet(); 

    ////5. Data Reader methods 
    //while (excelReader.Read()) 
    //{ 
    // //excelReader.GetInt32(0); 
    //} 

    //6. Free resources (IExcelDataReader is IDisposable) 
    excelReader.Close(); 
} 
0

這是如何在MVC中使用ClosedXML.Excel來做到這一點。我知道這個答案爲時已晚。我只是想爲Google搜索問題後出現在這個頁面上的所有人提供這個答案。在Visual Studio中,單擊工具菜單並展開NuGet Package Manager,然後運行包管理器控制檯。鍵入以下命令:

Install-Package ClosedXML 

的型號:

namespace ExcelUploadFileDemo.Models 
    { 
     public class UploadFile 
     { 
      [Required] 
      public HttpPostedFileBase ExcelFile { get; set; } 
     } 
    } 

控制器:

namespace ExcelUploadFileDemo.Controllers 
    { 
     public class HomeController : Controller 
     { 
      public ActionResult Index() 
      { 
       UploadFile UploadFile = new UploadFile(); 
       return View(UploadFile); 
      } 

      [HttpPost] 
      public ActionResult Index(UploadFile UploadFile) 
      { 
       if (ModelState.IsValid) 
       { 

        if (UploadFile.ExcelFile.ContentLength > 0) 
        { 
         if (UploadFile.ExcelFile.FileName.EndsWith(".xlsx") || UploadFile.ExcelFile.FileName.EndsWith(".xls")) 
         { 
          XLWorkbook Workbook; 
          Try//incase if the file is corrupt 
          { 
           Workbook = new XLWorkbook(UploadFile.ExcelFile.InputStream); 
          } 
          catch (Exception ex) 
          { 
           ModelState.AddModelError(String.Empty, $"Check your file. {ex.Message}"); 
           return View(); 
          } 
          IXLWorksheet WorkSheet = null; 
          Try//incase if the sheet you are looking for is not found 
          { 
           WorkSheet = Workbook.Worksheet("sheet1"); 

          } 
          catch 
          { 
           ModelState.AddModelError(String.Empty, "sheet1 not found!"); 
           return View(); 
          } 
          WorkSheet.FirstRow().Delete();//if you want to remove ist row 

          foreach (var row in WorkSheet.RowsUsed()) 
          { 
           //do something here 
           row.Cell(1).Value.ToString();//Get ist cell. 1 represent column number 

          } 
         } 
         else 
         { 
          ModelState.AddModelError(String.Empty, "Only .xlsx and .xls files are allowed"); 
          return View(); 
         } 
        } 
        else 
        { 
         ModelState.AddModelError(String.Empty, "Not a valid file"); 
         return View(); 
        } 
       } 
       return View(); 
      } 
     } 
    } 

該鏈接有很多例子來說明處理Excel中的不同的東西不同的方式。

https://github.com/ClosedXML/ClosedXML/tree/9ac4d868a313f308b82e94617b9cc2d28baeb1c3/ClosedXML

@model ExcelUploadFileDemo.Models.UploadFile 


@{ 
    ViewBag.Title = "Upload Excel File"; 
} 
<h2>Upload an Excel File</h2> 

@using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" })) 
{ 



    <div class="form-horizontal"> 
     @Html.ValidationSummary("", new { @class = "text-danger" }); 
     <div class="form-group"> 
      @Html.LabelFor(model => model.ExcelFile, htmlAttributes: new { @class = "control-label col-md-2" }) 
      <div class="col-md-10"> 
       @Html.TextBoxFor(model => model.ExcelFile, new { type = "file", @class = "form-control" }) 
       @Html.ValidationMessageFor(model => model.ExcelFile, "", new { @class = "text-danger" }) 
      </div> 
     </div> 
     <div class="form-group"> 
      <div class="col-md-offset-2 col-md-10"> 
       <input type = "submit" value="Submit" class="btn btn-default" /> 
      </div> 
     </div> 
    </div> 
} 
相關問題