previously Asp.Net MVC had this third party library which easily allowed uploading and reading from an excel file called Excel Data Reader. We didn’t need to have the file on the local disk, which was great because my application needs to run on Azure.
However we are now porting this functionality to asp.net core 2, and it seems from searching that this is not possible. Does anybody know any libraries that would allow me to do this? Please note, I am not looking for solutions that read from a disk. I want to upload an excel file and read data from the stream directly.
asked Apr 4, 2018 at 19:25
2
I Could Read Excel File In ‘Asp .Net Core’ By This Code.
Import And Export Data Using EPPlus.Core.
[HttpPost]
public IActionResult ReadExcelFileAsync(IFormFile file)
{
if (file == null || file.Length == 0)
return Content("File Not Selected");
string fileExtension = Path.GetExtension(file.FileName);
if (fileExtension != ".xls" && fileExtension != ".xlsx")
return Content("File Not Selected");
var rootFolder = @"D:Files";
var fileName = file.FileName;
var filePath = Path.Combine(rootFolder, fileName);
var fileLocation = new FileInfo(filePath);
using (var fileStream = new FileStream(filePath, FileMode.Create))
{
await file.CopyToAsync(fileStream);
}
if (file.Length <= 0)
return BadRequest(GlobalValidationMessage.FileNotFound);
using (ExcelPackage package = new ExcelPackage(fileLocation))
{
ExcelWorksheet workSheet = package.Workbook.Worksheets["Table1"];
//var workSheet = package.Workbook.Worksheets.First();
int totalRows = workSheet.Dimension.Rows;
var DataList = new List<Customers>();
for (int i = 2; i <= totalRows; i++)
{
DataList.Add(new Customers
{
CustomerName = workSheet.Cells[i, 1].Value.ToString(),
CustomerEmail = workSheet.Cells[i, 2].Value.ToString(),
CustomerCountry = workSheet.Cells[i, 3].Value.ToString()
});
}
_db.Customers.AddRange(customerList);
_db.SaveChanges();
}
return Ok();
}
answered May 18, 2019 at 8:01
Amin GolmahalleAmin Golmahalle
3,3892 gold badges23 silver badges35 bronze badges
4
I tried this code below (without using libs) for ASP.NET Core and it worked:
public ActionResult OnPostUpload(List<IFormFile> files)
{
try
{
var file = files.FirstOrDefault();
var inputstream = file.OpenReadStream();
XSSFWorkbook workbook = new XSSFWorkbook(stream);
var FIRST_ROW_NUMBER = {{firstRowWithValue}};
ISheet sheet = workbook.GetSheetAt(0);
// Example: var firstCellRow = (int)sheet.GetRow(0).GetCell(0).NumericCellValue;
for (int rowIdx = 2; rowIdx <= sheet.LastRowNum; rowIdx++)
{
IRow currentRow = sheet.GetRow(rowIdx);
if (currentRow == null || currentRow.Cells == null || currentRow.Cells.Count() < FIRST_ROW_NUMBER) break;
var df = new DataFormatter();
for (int cellNumber = {{firstCellWithValue}}; cellNumber < {{lastCellWithValue}}; cellNumber++)
{
//business logic & saving data to DB
}
}
}
catch(Exception ex)
{
throw new FileFormatException($"Error on file processing - {ex.Message}");
}
}
answered May 3, 2020 at 3:23
Pedro CoelhoPedro Coelho
1,3703 gold badges17 silver badges31 bronze badges
if we are talking about Razor Pages, here’s a simple sample that I tested today..
Environ: .NET Core 3.1, VS 2019
A simple class
public class UserModel
{
public string Name { get; set; }
public string City { get; set; }
}
Index.cshtml.cs
usings..
using ExcelDataReader;
public void OnPost(IFormFile file)
{
List<UserModel> users = new List<UserModel>();
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
using (var stream = new MemoryStream())
{
file.CopyTo(stream);
stream.Position = 0;
using (var reader = ExcelReaderFactory.CreateReader(stream))
{
while (reader.Read()) //Each row of the file
{
users.Add(new UserModel { Name = reader.GetValue(0).ToString(), City = reader.GetValue(1).ToString()});
}
}
}
//users // you got the values here
}
Mark up in View
<form id="form1" method="post" enctype="multipart/form-data">
<div class="text-center">
<input type="file" id="file1" name="file" />
</div>
<script>
document.getElementById('file1').onchange = function () {
document.getElementById('form1').submit();
};
</script>
You would require ExcelDataReader nuget package, I used 3.6.0
version
github working code
answered Jul 8, 2020 at 20:53
IrfIrf
4,1652 gold badges35 silver badges48 bronze badges
1
Latest versions of ExcelDataReader support netstandard2.0, thus work with ASP.NET Core 2. It also targets netstandard1.3, so works with ASP.NET Core 1.x as well.
(not sure what you searched that said it is not possible, but that is clearly wrong)
answered Apr 5, 2018 at 15:16
user8728340user8728340
5214 silver badges7 bronze badges
First upload your excel file and read the excel file record using asp.net core 3.1.
using System;
using Microsoft.AspNetCore.Mvc;
using ExcelFileRead.Models;
using Microsoft.AspNetCore.Hosting;
using System.IO;
using OfficeOpenXml;
using System.Linq;
namespace ExcelFileRead.Controllers
{
public class HomeController : Controller
{
private readonly IHostingEnvironment _hostingEnvironment;
public HomeController(IHostingEnvironment hostingEnvironment)
{
_hostingEnvironment = hostingEnvironment;
}
public ActionResult File()
{
FileUploadViewModel model = new FileUploadViewModel();
return View(model);
}
[HttpPost]
public ActionResult File(FileUploadViewModel model)
{
string rootFolder = _hostingEnvironment.WebRootPath;
string fileName = Guid.NewGuid().ToString() + model.XlsFile.FileName;
FileInfo file = new FileInfo(Path.Combine(rootFolder, fileName));
using (var stream = new MemoryStream())
{
model.XlsFile.CopyToAsync(stream);
using (var package = new ExcelPackage(stream))
{
package.SaveAs(file);
}
}
using (ExcelPackage package = new ExcelPackage(file))
{
ExcelWorksheet worksheet = package.Workbook.Worksheets.FirstOrDefault();
if (worksheet == null)
{
//return or alert message here
}
else
{
var rowCount = worksheet.Dimension.Rows;
for (int row = 2; row <= rowCount; row++)
{
model.StaffInfoViewModel.StaffList.Add(new StaffInfoViewModel
{
FirstName = (worksheet.Cells[row, 1].Value ?? string.Empty).ToString().Trim(),
LastName = (worksheet.Cells[row, 2].Value ?? string.Empty).ToString().Trim(),
Email = (worksheet.Cells[row, 3].Value ?? string.Empty).ToString().Trim(),
});
}
}
}
return View(model);
}
}
}
For more details(step by step)
https://findandsolve.com/articles/how-to-read-column-value-from-excel-in-aspnet-core-or-best-way-to-read-write-excel-file-in-dotnet-core
answered Oct 8, 2020 at 16:30
SundarSundar
1421 silver badge15 bronze badges
In this tutorial, we will be Importing Data Using Excel File In ASP NET MVC. In my previous article, I created an article to show how to perform exporting data into an excel file. You may check it using this link. Now, let’s start a simple project that will read the data from an excel file and import it using ASP.NET MVC Application.
Before you proceed with the steps below, please ensure that you have the latest version of the following installer.
- Visual Studio
Output preview
The image shown below would be the final output for this project. If you are interested on this project you can copy the source from the steps below.
I. Setup ASP.NET Web Application Project
- Let’s start by creating a new ASP.NET Web Application. Open your Visual Studio IDE and proceed with the steps below.
- Select File » New » Project.
- Choose ASP.NET Web Application(.NET Framework). Name the project ImportExcel to have the same namespace as my project. Click OK.
- Select MVC template and then check Configure for HTTPS.
- Lastly, Click on Create.
If this is your first time creating MVC project please refer to this article How to start with ASP.Net MVC.
2. Now we need to install required packages for this project. I have listed it all below.
- ExcelDataReader.Dataset
Use NuGet Package Manager to install this package. If this is your first time using this you can visit this article. Or follow the steps below.
- To add right-click on your project name, from your solution explorer. As shown below.
- Then select Manage NuGet Packages and search for ExcelDataReader.
- Install ExcelDataReader and ExcelDataReader.Dataset. When a green check is shown as the image below it means that the package is already installed.
II. Crete Index Action Result View
For this tutorial, we will be using the default HomeController and the index action result. We will be creating the view for the index method that will allow us to upload and display the record from an excel file. I have attached a screenshot below of the final view that the source code below will generate.
To create an index view, navigate to your default view. If you are using default template of MVC your default controller name is HomeController that makes Home » index.cshtml as your default view. Navigate to this file and replace all code inside this file with the code below.
View
@{
ViewBag.Title = "Home Page";
}
@model System.Data.DataTable
@using System.Data;
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script>
function bs_input_file() {
$(".input-file").before(
function () {
if (!$(this).prev().hasClass('input-ghost')) {
var element = $("<input type='file' id='dataFile' name='upload' class='input-ghost' style='visibility:hidden; height:0'>");
element.attr("name", $(this).attr("name"));
element.change(function () {
element.next(element).find('input').val((element.val()).split('\').pop());
});
$(this).find("button.btn-choose").click(function () {
element.click();
});
$(this).find("button.btn-reset").click(function () {
element.val(null);
$(this).parents(".input-file").find('input').val('');
});
$(this).find('input').css("cursor", "pointer");
$(this).find('input').mousedown(function () {
$(this).parents('.input-file').prev().click();
return false;
});
return element;
}
}
);
}
function clear() {
var input = $("#dataFile").val('');
};
$(function () {
clear();
bs_input_file();
});
</script>
@using (Html.BeginForm("Index", "Home", null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="info2">
<h2>Browse File for uploading</h2>
@Html.AntiForgeryToken()
<div class="form-group" name="Fichier1">
<!-- COMPONENT START -->
<div class="form-group">
<div class="input-group input-file">
<span class="input-group-btn">
<button class="btn btn-default btn-choose" type="button">Choose</button>
</span>
<input type="text" class="form-control" placeholder='Choose a file...' />
</div>
</div>
@*<input type="file" id="dataFile" name="upload" />*@
</div>
<div class="form-group">
<input type="submit" value="Upload" class="btn btn-default" />
</div>
<div class="alert alert-danger">
@Html.ValidationSummary()
@*<strong></strong> asdasd*@
</div>
</div>
if (Model != null)
{
<table id="table1" class="table table-bordered table-hover">
<thead>
<tr>
@foreach (DataColumn col in Model.Columns)
{
<th>@col.ColumnName</th>
}
</tr>
</thead>
<tbody>
@foreach (DataRow row in Model.Rows)
{
<tr>
@foreach (DataColumn col in Model.Columns)
{
<td>@row[col.ColumnName]</td>
}
</tr>
}
</tbody>
</table>
}
}
<script>
$(document).ready(function () {
$("table1").DataTable();
});
</script>
III. Create Index POST Action method
By default index method found in HomeController is access using a GET method. Now, we need a POST index method to process the data from the uploaded excel file.
Note : We have created two index action result in our HomeController . First index handle HttpGet request and the other one handle HttpPost request.
HttpGet index:
- This loads default view.
public ActionResult Index()
{
DataTable dt = new DataTable();
try
{
dt = (DataTable)Session["tmpdata"];
}
catch (Exception ex)
{
}
return View(dt);
}
HttpPost index:
- This received post request from the view.Which is the excel data.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(HttpPostedFileBase upload)
{
if (ModelState.IsValid)
{
if (upload != null && upload.ContentLength > 0)
{
// ExcelDataReader works with the binary Excel file, so it needs a FileStream
// to get started. This is how we avoid dependencies on ACE or Interop:
Stream stream = upload.InputStream;
IExcelDataReader reader = null;
if (upload.FileName.EndsWith(".xls"))
{
reader = ExcelReaderFactory.CreateBinaryReader(stream);
}
else if (upload.FileName.EndsWith(".xlsx"))
{
reader = ExcelReaderFactory.CreateOpenXmlReader(stream);
}
else
{
ModelState.AddModelError("File", "This file format is not supported");
return View();
}
int fieldcount = reader.FieldCount;
int rowcount = reader.RowCount;
DataTable dt = new DataTable();
DataRow row;
DataTable dt_ = new DataTable();
try
{
dt_ = reader.AsDataSet().Tables[0];
for (int i = 0; i < dt_.Columns.Count; i++)
{
dt.Columns.Add(dt_.Rows[0][i].ToString());
}
int rowcounter = 0;
for (int row_ = 1; row_ < dt_.Rows.Count; row_++)
{
row = dt.NewRow();
for (int col = 0; col < dt_.Columns.Count; col++)
{
row[col] = dt_.Rows[row_][col].ToString();
rowcounter++;
}
dt.Rows.Add(row);
}
}
catch (Exception ex)
{
ModelState.AddModelError("File", "Unable to Upload file!");
return View();
}
DataSet result = new DataSet();
result.Tables.Add(dt);
reader.Close();
reader.Dispose();
DataTable tmp = result.Tables[0];
Session["tmpdata"] = tmp; //store datatable into session
return RedirectToAction("Index");
}
else
{
ModelState.AddModelError("File", "Please Upload Your file");
}
}
return View();
}
}
}
IV. Test the Application
Now, run your project by pressing F5 from your keyboard and try importing a sample excel file. Excel file should be in table format.
Sample Excel file:
- Click on choose button in importing excel and select your excel file.
2. Then click upload. Your final view should look like this.
V. Full Source Code
Home Controller
using ExcelDataReader;
using Microsoft.AspNet.Identity;
using Microsoft.Owin.Security;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
namespace ImportExcel.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
DataTable dt = new DataTable();
//if ((String)Session["tmpdata"] != null)
//{
try
{
dt = (DataTable)Session["tmpdata"];
}
catch (Exception ex)
{
}
//}
return View(dt);
}
private IAuthenticationManager AuthenticationManager //Sign out method
{
get { return HttpContext.GetOwinContext().Authentication; }
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(HttpPostedFileBase upload)
{
if (ModelState.IsValid)
{
if (upload != null && upload.ContentLength > 0)
{
// ExcelDataReader works with the binary Excel file, so it needs a FileStream
// to get started. This is how we avoid dependencies on ACE or Interop:
Stream stream = upload.InputStream;
// We return the interface, so that
IExcelDataReader reader = null;
if (upload.FileName.EndsWith(".xls"))
{
reader = ExcelReaderFactory.CreateBinaryReader(stream);
}
else if (upload.FileName.EndsWith(".xlsx"))
{
reader = ExcelReaderFactory.CreateOpenXmlReader(stream);
}
else
{
ModelState.AddModelError("File", "This file format is not supported");
return View();
}
int fieldcount = reader.FieldCount;
int rowcount = reader.RowCount;
DataTable dt = new DataTable();
//dt.Columns.Add("UserName");
//dt.Columns.Add("Adddress");
DataRow row;
DataTable dt_ = new DataTable();
try
{
dt_ = reader.AsDataSet().Tables[0];
string ret = "";
for (int i = 0; i < dt_.Columns.Count; i++)
{
dt.Columns.Add(dt_.Rows[0][i].ToString());
}
int rowcounter = 0;
for (int row_ = 1; row_ < dt_.Rows.Count; row_++)
{
row = dt.NewRow();
for (int col = 0; col < dt_.Columns.Count; col++)
{
row[col] = dt_.Rows[row_][col].ToString();
rowcounter++;
}
dt.Rows.Add(row);
}
}
catch (Exception ex)
{
ModelState.AddModelError("File", "Unable to Upload file!");
return View();
}
DataSet result = new DataSet();//reader.AsDataSet();
result.Tables.Add(dt);
string minutes_ID = "";
reader.Close();
reader.Dispose();
// return View();
// return View(result.Tables[0]);
DataTable ddd = result.Tables[0];
Session["tmpdata"] = ddd;
return RedirectToAction("Index");
}
else
{
ModelState.AddModelError("File", "Please Upload Your file");
}
}
return View();
}
}
}
View > Index.cshtml
@{
ViewBag.Title = "Home Page";
}
@model System.Data.DataTable
@using System.Data;
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script>
function bs_input_file() {
$(".input-file").before(
function () {
if (!$(this).prev().hasClass('input-ghost')) {
var element = $("<input type='file' id='dataFile' name='upload' class='input-ghost' style='visibility:hidden; height:0'>");
element.attr("name", $(this).attr("name"));
element.change(function () {
element.next(element).find('input').val((element.val()).split('\').pop());
});
$(this).find("button.btn-choose").click(function () {
element.click();
});
$(this).find("button.btn-reset").click(function () {
element.val(null);
$(this).parents(".input-file").find('input').val('');
});
$(this).find('input').css("cursor", "pointer");
$(this).find('input').mousedown(function () {
$(this).parents('.input-file').prev().click();
return false;
});
return element;
}
}
);
}
function clear() {
var input = $("#dataFile").val('');
};
$(function () {
clear();
bs_input_file();
});
</script>
@using (Html.BeginForm("Index", "Home", null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="info2">
<h2>Browse File for uploading</h2>
@Html.AntiForgeryToken()
<div class="form-group" name="Fichier1">
<!-- COMPONENT START -->
<div class="form-group">
<div class="input-group input-file">
<span class="input-group-btn">
<button class="btn btn-default btn-choose" type="button">Choose</button>
</span>
<input type="text" class="form-control" placeholder='Choose a file...' />
</div>
</div>
@*<input type="file" id="dataFile" name="upload" />*@
</div>
<div class="form-group">
<input type="submit" value="Upload" class="btn btn-default" />
</div>
<div class="alert alert-danger">
@Html.ValidationSummary()
@*<strong></strong> asdasd*@
</div>
</div>
if (Model != null)
{
<table id="table1" class="table table-bordered table-hover">
<thead>
<tr>
@foreach (DataColumn col in Model.Columns)
{
<th>@col.ColumnName</th>
}
</tr>
</thead>
<tbody>
@foreach (DataRow row in Model.Rows)
{
<tr>
@foreach (DataColumn col in Model.Columns)
{
<td>@row[col.ColumnName]</td>
}
</tr>
}
</tbody>
</table>
}
}
<script>
$(document).ready(function () {
$("table1").DataTable();
});
</script>
Summary
This is one of the many ways to Importing Data Using Excel File In ASP NET MVC. This is also a very common functionality in an application that required reports. If you are a beginner in this area you may find it difficult that is why I am sharing this. Hopefully, you may find it useful and may be able to solve your future or current projects.
KEEP Coding!!
Работа с типом файлов Microsoft Excel на сайте – это довольно частая задача. Импорт/экспорт прайса или номенклатуры товаров в интернет-магазине, выгрузка отчета из базы данных в виде таблицы, да все что угодно. В этом уроке посмотрим, как можно обрабатывать файлы такого типа.
На сегодняшний день существует достаточно много готовых решений (библиотек) для взаимодействия с файлами Excel, чтобы не работать напрямую с системными GridView и DataTable. Не будем изобретать велосипед и рассмотрим одну из популярных и удобных библиотек, которой я пользуюсь чаще других.
Данная библиотека называется ClosedXML. По этой ссылке находится официальный адрес проекта на GitHub. Библиотека позволяет легко манипулировать файлами MS Excel в удобной объектно-ориентированной манере. Она может быть использована на любом .NET языке программирования (C#, VisualBasic.NET), а также в проектах не только типа WebApplication.
Представим ситуацию, что у нас есть под рукой вот такой Excel-файл с ценами на ремонт телефонов, в котором на листах расположены отдельные бренды, колонки на листе представляют конкретные модели для этого бренда, а строки представляют конкретные неисправности и сколько будет стоить ремонт для той или иной модели.
Прайс-лист на услуги в виде Excel-файла
Давайте создадим веб-приложение, которое сможет распарсить этот файл так, чтобы мы могли работать с записями в объектно-ориентированной манере, например, сохранять/обновлять бренды, модели и позиции в прайсе в базу данных. Или, например, представлять этот прайс в виде обычной html-таблицы в браузере пользователя.
Создаем в Visual Studio проект типа MVC, открываем Nuget Manager и скачиваем нужный нам пакет.
Добавляем пакет ClosedXML в проект
Создадим все доменные классы-модели, которые описывают предметную область.
Кстати, внизу страницы есть ссылка на архив с исходным кодом проекта.
namespace WebApplication2.Models
{
public class PricePosition
{
//Неисправность
public string Problem { get; set; }
//Стоимость ремонта
public string Price { get; set; }
}
public class PhoneModel
{
public PhoneModel()
{
PricePositions = new List<PricePosition>();
}
//Название модели телефона
public string Title { get; set; }
public List<PricePosition> PricePositions { get; set; }
}
public class PhoneBrand
{
public PhoneBrand()
{
PhoneModels = new List<PhoneModel>();
}
//Название бренда
public string Title { get; set; }
public List<PhoneModel> PhoneModels { get; set; }
}
}
Описанные модели максимально простые, чтобы не усложнять пример. В них нет и не отслеживается уникальных идентификаторов, все свойства типа String и т.д.
Также определим т.н. ViewModel, то есть модель для представления. В нее заключим все объекты доменной модели, которые мы хотим показать пользователю в браузере:
public class PriceViewModel
{
public PriceViewModel()
{
PhoneBrands = new List<PhoneBrand>();
}
public List<PhoneBrand> PhoneBrands { get; set; }
//кол-во ошибок при импорте
public int ErrorsTotal { get; set; }
}
Далее в вашем проекте определите какое-нибудь действие в нужном контроллере, которое будет отвечать за загрузку Excel-файла из браузера на сервер. Пример кода с html-формой в соответствующем представлении:
<div>
@using (Html.BeginForm("Import", "Home", FormMethod.Post, new { enctype = "multipart/form-data", id = "frm-excel" }))
{
<div>
Загрузите Excel-файл:
<input type="file" name="fileExcel" id="fileExcel" />
<div>
<input type="submit" value="Загрузить" />
</div>
</div>
}
</div>
Из примера видно, что в форме мы обращаемся к методу Import в контроллере Home. Создадим подобный метод:
[HttpPost]
public ActionResult Import(HttpPostedFileBase fileExcel)
{
if (ModelState.IsValid)
{
PriceViewModel viewModel = new PriceViewModel();
using (XLWorkbook workBook = new XLWorkbook(fileExcel.InputStream, XLEventTracking.Disabled))
{
foreach (IXLWorksheet worksheet in workBook.Worksheets)
{
PhoneBrand phoneBrand = new PhoneBrand();
phoneBrand.Title = worksheet.Name;
foreach (IXLColumn column in worksheet.ColumnsUsed().Skip(1))
{
PhoneModel phoneModel = new PhoneModel();
phoneModel.Title = column.Cell(1).Value.ToString();
foreach (IXLRow row in worksheet.RowsUsed().Skip(1))
{
try
{
PricePosition pricePosition = new PricePosition();
pricePosition.Problem = row.Cell(1).Value.ToString();
pricePosition.Price = row.Cell(column.ColumnNumber()).Value.ToString();
phoneModel.PricePositions.Add(pricePosition);
}
catch (Exception e)
{
//logging
viewModel.ErrorsTotal++;
}
}
phoneBrand.PhoneModels.Add(phoneModel);
}
viewModel.PhoneBrands.Add(phoneBrand);
}
}
//например, здесь сохраняем все позиции из прайса в БД
return View(viewModel);
}
return RedirectToAction("Index");
}
В этом методе мы парсим Excel-файл и манипулируем записями в объектно-ориентированной манере. Код в методе довольно простой. Более подробно он объясняется в видео-версии этой статьи. Здесь отмечу основные моменты:
- в нескольких циклах foreach{ } мы пробегаемся по всем записям в файле, параллельно создавая объекты классов наших доменных моделей;
- получается сформированная коллекция брендов телефонов, в каждом из которых содержится коллекция конкретных моделей, в каждой из которых содержится коллекция позиций прайса с ценами на ремонт;
- также создается ViewModel, где мы считаем количество ошибок при импорте и в которую вкладываем заполненную коллекцию брендов;
- в итоге мы можем либо сохранить полученные объекты в базу данных, либо отправить ViewModel в представление.
В качестве интерактива Вы можете в соответствующем представлении создать HTML-таблицу с прайсом и отправить ее в браузер пользователя.
Также возможна другая ситуация, когда у нас нет исходного Excel-файла, вместо этого веб-приложение должно сформировать его динамически, и пользователь сайта сможет его скачать. Например, тот же список брендов и моделей телефонов.
Создадим соответствующее действие в контроллере:
public ActionResult Export()
{
List<PhoneBrand> phoneBrands = new List<PhoneBrand>();
phoneBrands.Add(new PhoneBrand()
{
Title = "Apple",
PhoneModels = new List<PhoneModel>()
{
new PhoneModel() { Title = "iPhone 7"},
new PhoneModel() { Title = "iPhone 7 Plus"}
}});
phoneBrands.Add(new PhoneBrand()
{
Title = "Samsung",
PhoneModels = new List<PhoneModel>()
{
new PhoneModel() { Title = "A3"},
new PhoneModel() { Title = "A3 2016"},
new PhoneModel() { Title = "A3 2017"}
}});
using (XLWorkbook workbook = new XLWorkbook(XLEventTracking.Disabled))
{
var worksheet = workbook.Worksheets.Add("Brands");
worksheet.Cell("A1").Value = "Бренд";
worksheet.Cell("B1").Value = "Модели";
worksheet.Row(1).Style.Font.Bold = true;
//нумерация строк/столбцов начинается с индекса 1 (не 0)
for (int i = 0; i < phoneBrands.Count; i++)
{
worksheet.Cell(i + 2, 1).Value = phoneBrands[i].Title;
worksheet.Cell(i + 2, 2).Value = string.Join(", ", phoneBrands[i].PhoneModels.Select(x => x.Title));
}
using (var stream = new MemoryStream())
{
workbook.SaveAs(stream);
stream.Flush();
return new FileContentResult(stream.ToArray(),
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
{
FileDownloadName = $"brands_{DateTime.UtcNow.ToShortDateString()}.xlsx"
};
}
}
}
Отмечу ключевые моменты из листинга выше:
- в нашем простом примере список брендов и моделей мы жестко закодировали, но его также можно получить и из БД;
- к ячейкам на рабочем листе можно обращаться как по литеральному значению, так и по индексу. Нумерация строк/столбцов начинается с индекса 1 (не 0);
- в качестве MIME-type для файлов Excel следует указывать application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;
Вывод: В этой статье мы рассмотрели основные возможности библиотеки ClosedXML. Ее функционала вполне хватает для обработки большинства сценариев, когда данные представлены в формате MS Excel файлов.
Are you using traditional way to read .xls and .xlsx files in ASP.NET/C#? If yes, you might be using following providers:
Microsoft.Jet.OLEDB.4.0 provider for Excel 97-2003 format (.xls)
Microsoft.ACE.OLEDB.12.0 provider for Excel 2007+ format (.xlsx)
and you may get the following common errors:
The ‘Microsoft.Jet.OLEDB.4.0’ provider is not registered on the local machine.
The ‘Microsoft.ACE.OLEDB.12.0’ provider is not registered on the local machine.
and probably, you would go for following approach to fix them
1. Installation of Office 2007 Data Connectivity Components or Office 2010 Database Engine on the Server.
2. The application pool that the site is running set “Enable 32-bit applications” to “True”
3. In project, Change Platform target from: Any CPU to x86 and Rebuild it.
What would happen if you have shared hosting or Azure Website hosting and You are not allowed to install ACE Database engine on the server?
In this post, we will see how to upload and read both .xls and .xlsx excel files without any server dependencies in ASP.NET MVC. We will use ExcelDataReader, an Open Source project to read excel files.
Steps:
1. Create ASP.NET MVC 5 Empty Project
2. To install ExcelDataReader, run the following command in the Package Manager Console:
Install-Package ExcelDataReader
3. Add New Controller say HomeController and add following action:
public ActionResult Upload() { return View(); }
4. Add View of Upload action and use following code:
@model System.Data.DataTable @using System.Data; <h2>Upload File</h2> @using (Html.BeginForm("Upload", "Home", null, FormMethod.Post, new { enctype = "multipart/form-data" })) { @Html.AntiForgeryToken() @Html.ValidationSummary() <div class="form-group"> <input type="file" id="dataFile" name="upload" /> </div> <div class="form-group"> <input type="submit" value="Upload" class="btn btn-default" /> </div> if (Model != null) { <table> <thead> <tr> @foreach (DataColumn col in Model.Columns) { <th>@col.ColumnName</th> } </tr> </thead> <tbody> @foreach (DataRow row in Model.Rows) { <tr> @foreach (DataColumn col in Model.Columns) { <td>@row[col.ColumnName]</td> } </tr> } </tbody> </table> } }
We will read excel, get data in DataTable and show DataTable in View.
5. To read the submitted file:
[HttpPost] [ValidateAntiForgeryToken] public ActionResult Upload(HttpPostedFileBase upload) { if (ModelState.IsValid) { if (upload != null && upload.ContentLength > 0) { // ExcelDataReader works with the binary Excel file, so it needs a FileStream // to get started. This is how we avoid dependencies on ACE or Interop: Stream stream = upload.InputStream; // We return the interface, so that IExcelDataReader reader = null; if (upload.FileName.EndsWith(".xls")) { reader = ExcelReaderFactory.CreateBinaryReader(stream); } else if (upload.FileName.EndsWith(".xlsx")) { reader = ExcelReaderFactory.CreateOpenXmlReader(stream); } else { ModelState.AddModelError("File", "This file format is not supported"); return View(); } reader.IsFirstRowAsColumnNames = true; DataSet result = reader.AsDataSet(); reader.Close(); return View(result.Tables[0]); } else { ModelState.AddModelError("File", "Please Upload Your file"); } } return View(); }
It is assumed the file will have column names in first row.
Output:
Conclusion:
ExcelDataReader has no dependencies on external database engines which may not be available on a remote server. It is helpful to deploy application to Windows Azure Websites, Shared hosting or any other machine where the ACE Database engine is not available. We have seen how easy to read excel sheets in ASP.NET MVC with ExcelDataReader.
Hope It helps. Feel free to share your opinion in comment box.
Background
When a beginner joins a company or if there is a final round of interviews, known as a machine round, then most of the time the team leader gives the Candidate the first assignment to create an application which allows the end user to upload only Excel files and display it in a grid view and download it. When I joined a company the same task was given to me by my team leader; instead I was expecting him to give me the task of inserting, updating and deleting in a grid view.
So by considering the above requirement I decided to write this article specially focusing on beginners and those who want to learn how to upload Excel files and display in a grid view and download files in a gridview selected event which is displayed in the grid view.
Now before creating the application, let us create a table named Excelfiledemo in a database to store the downloaded Excel files in a database table having the following fields (shown in the following image),
In the above table I have created four columns, they are id for the unique identity, Name for the Excel file name, type for file type and data to store the actual content of the files with binary datatype because the content of the files stored in bytes.
I hope you have created the same type of table.
Now let us start to create an application to upload and download Excel files step-by-step.
Create a web site as,
- Start-All Programs-Microsoft Visual Studio 2010
- File-New Website-C#-Empty website (to avoid adding master page)
- Give the web site name as ExcelFileUploadDownload and specify the location
- Then right-click on Solution Explorer — Add New Item-Default.aspx page
- Open source view and simply drag one File upload control, two Buttons, one label and a grid view
- The source code <body> tag should be as follows,
- <body bgcolor=«Silver»>
- <form id=«form1» runat=«server»>
- <div>
- <table>
- <tr>
- <td>
- Select File
- </td>
- <td>
- <asp:FileUpload ID=«FileUpload1» runat=«server» ToolTip=«Select Only Excel File» />
- </td>
- <td>
- <asp:Button ID=«Button1» runat=«server» Text=«Upload» onclick=«Button1_Click» />
- </td>
- <td>
- <asp:Button ID=«Button2» runat=«server» Text=«View Files»
- onclick=«Button2_Click» />
- </td>
- </tr>
- </table>
- <table>
- <tr>
- <td>
- <p>
- <asp:Label ID=«Label2» runat=«server» Text=«label»></asp:Label>
- </p>
- </td>
- </tr>
- </table>
- <asp:GridView ID=«GridView1» runat=«server» Caption=«Excel Files «
- CaptionAlign=«Top» HorizontalAlign=«Justify»
- DataKeyNames=«id» onselectedindexchanged=«GridView1_SelectedIndexChanged»
- ToolTip=«Excel FIle DownLoad Tool» CellPadding=«4» ForeColor=«#333333»
- GridLines=«None»>
- <RowStyle BackColor=«#E3EAEB» />
- <Columns>
- <asp:CommandField ShowSelectButton=«True» SelectText=«Download» ControlStyle-ForeColor=«Blue»/>
- </Columns>
- <FooterStyle BackColor=«#1C5E55» Font-Bold=«True» ForeColor=«White» />
- <PagerStyle BackColor=«#666666» ForeColor=«White» HorizontalAlign=«Center» />
- <SelectedRowStyle BackColor=«#C5BBAF» Font-Bold=«True» ForeColor=«#333333» />
- <HeaderStyle BackColor=«Gray» Font-Bold=«True» ForeColor=«White» />
- <EditRowStyle BackColor=«#7C6F57» />
- <AlternatingRowStyle BackColor=«White» />
- </asp:GridView>
- </div>
- </form>
- </body>
Then run the page which will look as in the following,
From the above view I am using two buttons to do the upload; one to upload the selected files to the database and view files which shows the files in a grid view which is stored in database table.
Now switch to design mode and double click on upload button and put the following code to validate the Only Excel files to be allowed to upload.
- protected void Button1_Click(object sender, EventArgs e) {
- Label2.Visible = true;
- string filePath = FileUpload1.PostedFile.FileName;
- string filename1 = Path.GetFileName(filePath);
- string ext = Path.GetExtension(filename1);
- string type = String.Empty;
- if (!FileUpload1.HasFile) {
- Label2.Text = «Please Select File»;
- } else
- if (FileUpload1.HasFile) {
- try {
- switch (ext)
- {
- case «.xls»:
- type = «application/vnd.ms-excel»;
- break;
- case «.xlsx»:
- type = «application/vnd.ms-excel»;
- break;
- }
- if (type != String.Empty) {
- connection();
- Stream fs = FileUpload1.PostedFile.InputStream;
- BinaryReader br = new BinaryReader(fs);
- Byte[] bytes = br.ReadBytes((Int32) fs.Length);
- query = «insert into Excelfiledemo(Name,type,data)» + » values (@Name, @type, @Data)»;
- com = new SqlCommand(query, con);
- com.Parameters.Add(«@Name», SqlDbType.VarChar).Value = filename1;
- com.Parameters.Add(«@type», SqlDbType.VarChar).Value = type;
- com.Parameters.Add(«@Data», SqlDbType.Binary).Value = bytes;
- com.ExecuteNonQuery();
- Label2.ForeColor = System.Drawing.Color.Green;
- Label2.Text = «File Uploaded Successfully»;
- } else {
- Label2.ForeColor = System.Drawing.Color.Red;
- Label2.Text = «Select Only Excel File having extension .xlsx or .xls «;
- }
- } catch (Exception ex) {
- Label2.Text = «Error: « + ex.Message.ToString();
- }
- }
- }
Add the following code in the view file button click,
- protected void Button2_Click(object sender, EventArgs e)
- {
- GridView1.Visible =true;
- connection();
- query = «Select *from Excelfiledemo»;
- SqlDataAdapter da = new SqlDataAdapter(query, con);
- DataSet ds = new DataSet();
- da.Fill(ds, «Excelfiledemo»);
- GridView1.DataSource = ds.Tables[0];
- GridView1.DataBind();
- con.Close();
- }
Add the following code to the Gridview selected index changed event to download the files,
- protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
- {
- using(SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings[«excelconn»].ToString()))
- {
- con.Open();
- SqlCommand cmd = new SqlCommand(«select Name,type,data from Excelfiledemo where id=@id», con);
- cmd.Parameters.AddWithValue(«id», GridView1.SelectedRow.Cells[1].Text);
- SqlDataReader dr = cmd.ExecuteReader();
- if (dr.Read())
- {
- Response.Clear();
- Response.Buffer = true;
- Response.ContentType = dr[«type»].ToString();
- Response.AddHeader(«content-disposition», «attachment;filename=» + dr[«Name»].ToString());
- Response.Charset = «»;
- Response.Cache.SetCacheability(HttpCacheability.NoCache);
- Response.BinaryWrite((byte[]) dr[«data»]);
- Response.End();
- }
- }
- }
For more code please download the zip file attachment of this article.
After downloading the zip file, extract the files and open it into the Visual Studio and make whatever changes in the connection string to your web.config file as per your server location.
Now run the application and select the file other than Excel which shows the following error as shown in the following,
Now select the Excel file, which shows the following message after Suceessfully Uploaded,
Now click on view files details. The gridview is shows uploaded files with details as shown below.
then Click on the download button of gridview, the following prompt message is displayed as shown in below image,
Then choose browse with Excel and click on the ok button. The file will be opened in Excel as follows,
Summary
I hope this article is useful for all readers, if you have any suggestion then please contact me including beginners also.
Download the zip file from the attachment for the full source code of an application.