Прочитайте файл Excel, загруженный с помощью FileUpload Control без сохранения его на сервере
Необходимо уметь читать файл Excel, загруженный с помощью FileUploadControl в ASP.NET. Решение будет размещено на сервере. Я не хочу хранить файл Excel на сервере. Я хотел бы напрямую преобразовать содержимое excel в набор данных или данные и использовать.
Ниже представлены два решения, которые я уже нашел, но не работаю для меня.
-
LINQTOEXCEL - этот метод работает, когда у вас есть файл excel на вашем локальном компьютере, и вы запускаете свой код на локальном компьютере. В моем случае пользователь пытается загрузить файл excel с его локальной машины, используя веб-страницу, размещенную на сервере.
-
ExcelDataReader - я в настоящее время использую этот, но это сторонний инструмент. Я не могу переместить это нашему клиенту. Кроме того, если пересечение строк/столбцов содержит формулу, то данные пересечения строк/столбцов не считываются в набор данных.
Большинство предложений, которые я нашел в google и StackOverflow, работают, когда оба решения excel и .NET находятся на одной машине. Но в моем случае мне нужно, чтобы он работал, когда решение размещено на сервере, и пользователи пытаются загрузить excel с помощью размещенной веб-страницы на своей локальной машине.
Если у вас есть другие предложения, не могли бы вы сообщить мне?
Ответы
Ответ 1
Вы можете использовать InputStream
свойство HttpPostedFile
для чтения файла в памяти.
Вот пример, который показывает, как создать DataTable
из IO.Stream
для HttpPostedFile
, используя EPPlus
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>
Ответ 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();
}
Ответ 3
Возможно, вы можете взглянуть на Koogra, это читатель с открытым исходным кодом (только для чтения). Я думаю, вы получите поток обратно от клиента. Затем вы можете делать все, что делаете сейчас. Читайте из memystream и пишите в базу данных.
Надеюсь, это поможет.
Ответ 4
Вот как это сделать в MVC с помощью ClosedXML.Excel. Я знаю, что этот ответ слишком поздно. Я просто хотел ответить на этот вопрос всем тем, кто приземлился на эту страницу после проблемы с поиском. В Visual Studio нажмите на меню инструментов и разверните диспетчер пакетов NuGet, а затем запустите консоль диспетчера пакетов. Введите следующую команду:
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>
}