We will connect to a Microsoft Excel workbook using the OLEDB.NET data provider, extract data, and then display the data in a View.
Firstly, we will create an ImportExcel in Home Controller which returns a View. This method will return a View for Get Request. Now we will create another method ImportExcel1 and decorate it with [HttpPost] Attribute. Since in MVC 2 Methods cannot have the same method name, we can call 2 actions using the Action Name attribute. So we will decorate ImportExcel1 with [ActionName("Importexcel")]. Now if we make a get request then ImportExcel will be called and for post request, ImportExcel1 will be called. The following is the code to read Excel files.
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.OleDb;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ExcelUpload.Models;
namespace ExcelUpload.Controllers
{
public class HomeController : Controller
{
public ActionResult ImportExcel()
{
return View();
}
[ActionName("Importexcel")]
[HttpPost]
public ActionResult Importexcel1()
{
if (Request.Files["FileUpload1"].ContentLength > 0)
{
string extension = Path.GetExtension(Request.Files["FileUpload1"].FileName).ToLower();
string query = null;
string connString = "";
string[] validFileTypes = { ".xls", ".xlsx", ".csv" };
string path1 = Path.Combine(Server.MapPath("~/Content/Uploads"), Request.Files["FileUpload1"].FileName);
if (!Directory.Exists(Server.MapPath("~/Content/Uploads")))
{
Directory.CreateDirectory(Server.MapPath("~/Content/Uploads"));
}
if (validFileTypes.Contains(extension))
{
if (System.IO.File.Exists(path1))
{
System.IO.File.Delete(path1);
}
Request.Files["FileUpload1"].SaveAs(path1);
if (extension == ".csv")
{
DataTable dt = Utility.ConvertCSVtoDataTable(path1);
ViewBag.Data = dt;
}
else if (extension.Trim() == ".xls")
{
connString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + path1 + ";Extended Properties=\"Excel 8.0;HDR=Yes;IMEX=2\"";
DataTable dt = Utility.ConvertXSLXtoDataTable(path1, connString);
ViewBag.Data = dt;
}
else if (extension.Trim() == ".xlsx")
{
connString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + path1 + ";Extended Properties=\"Excel 12.0;HDR=Yes;IMEX=2\"";
DataTable dt = Utility.ConvertXSLXtoDataTable(path1, connString);
ViewBag.Data = dt;
}
}
else
{
ViewBag.Error = "Please Upload Files in .xls, .xlsx or .csv format";
}
}
return View();
}
}
}
Here we have created a static class Utility that contains 2 methods ConvertCSVtoDataTable and ConvertXSLXtoDataTable. The following is the code for the Utility class.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Web;
using System.Data.OleDb;
namespace ExcelUpload.Models
{
public static class Utility
{
public static DataTable ConvertCSVtoDataTable(string strFilePath)
{
DataTable dt = new DataTable();
using (StreamReader sr = new StreamReader(strFilePath))
{
string[] headers = sr.ReadLine().Split(',');
foreach (string header in headers)
{
dt.Columns.Add(header);
}
while (!sr.EndOfStream)
{
string[] rows = sr.ReadLine().Split(',');
if (rows.Length > 1)
{
DataRow dr = dt.NewRow();
for (int i = 0; i < headers.Length; i++)
{
dr[i] = rows[i].Trim();
}
dt.Rows.Add(dr);
}
}
}
return dt;
}
public static DataTable ConvertXSLXtoDataTable(string strFilePath, string connString)
{
OleDbConnection oledbConn = new OleDbConnection(connString);
DataTable dt = new DataTable();
try
{
oledbConn.Open();
using (OleDbCommand cmd = new OleDbCommand("SELECT * FROM [Sheet1$]", oledbConn))
{
OleDbDataAdapter oleda = new OleDbDataAdapter();
oleda.SelectCommand = cmd;
DataSet ds = new DataSet();
oleda.Fill(ds);
dt = ds.Tables[0];
}
}
catch
{
// Handle exceptions
}
finally
{
oledbConn.Close();
}
return dt;
}
}
}
Now we will create a view that contains a file upload control and a button. When a request for ImportExcel of Home Controller is made, we will show file upload control with button control. When we select a file and press the button it will make a post request to the Home Controller and the ImportExcel1 method will be called. The following is the Razor View for both requests.
@using System.Data;
@{
ViewBag.Title = "ImportExcel";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>ImportExcel</h2>
<!--[if !IE]><!-->
<style type="text/css">
/* Generic Styling, for Desktops/Laptops */
table {
width: 100%;
border-collapse: collapse;
}
/* Zebra striping */
tr:nth-of-type(odd) {
background: #eee;
}
th {
background: #333;
color: white;
font-weight: bold;
}
td, th {
padding: 6px;
border: 1px solid #ccc;
text-align: left;
}
/*
Max width before this PARTICULAR table gets nasty
This query will take effect for any screen smaller than 760px
and also iPads specifically.
*/
@media only screen and (max-width: 760px),
(min-device-width: 768px) and (max-device-width: 1024px) {
/* Force table to not be like tables anymore */
table, thead, tbody, th, td, tr {
display: block;
}
/* Hide table headers (but not display: none;, for accessibility) */
thead tr {
position: absolute;
top: -9999px;
left: -9999px;
}
tr {
border: 1px solid #ccc;
}
td {
/* Behave like a "row" */
border: none;
border-bottom: 1px solid #eee;
position: relative;
padding-left: 50%;
}
td:before {
/* Now like a table header */
position: absolute;
/* Top/left values mimic padding */
top: 6px;
left: 6px;
width: 45%;
padding-right: 10px;
white-space: nowrap;
}
/*
Label the data
*/
td:before {
content: attr(data-title);
}
}
</style>
<!--<![endif]-->
@using (Html.BeginForm("ImportExcel", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<table>
<tr>
<td>Excel file</td>
<td><input type="file" id="FileUpload1" name="FileUpload1" /></td>
</tr>
<tr>
<td></td>
<td><input type="submit" id="Submit" name="Submit" value="Submit" /></td>
</tr>
</table>
}
<div>
<table id="">
@if (ViewBag.Data != null)
{
<thead>
@foreach (DataColumn column in (ViewBag.Data as DataTable).Columns)
{
<th>@column.ColumnName.ToUpper()</th>
}
</thead>
if ((ViewBag.Data as DataTable).Rows.Count > 0)
{
foreach (DataRow dr in (ViewBag.Data as DataTable).Rows)
{
<tr>
@foreach (DataColumn column in (ViewBag.Data as DataTable).Columns)
{
<td data-title='@column.ColumnName'>
@dr[column].ToString()
</td>
}
</tr>
}
}
else
{
int count = (ViewBag.Data as DataTable).Columns.Count;
<tr>
<td colspan='@count' style="color:red;">
No Data Found.
</td>
</tr>
}
}
else
{
if (ViewBag.Error != null)
{
<tr>
<td style="color:red;">
@(ViewBag.Error != null ? ViewBag.Error.ToString() : "")
</td>
</tr>
}
}
</table>
</div>
Truong NgoPosted Oct 1, 2021, 3:21 AM
I appreciate you for the project! Thanks so much!
Samar RizviPosted Apr 6, 2021, 5:16 AM
I am able to read data in debug mode but after publishing its not working, could you please suggest what might be the problem ? Can you please suggest
Samar RizviPosted Mar 31, 2021, 9:11 AM
Hii I have to edit it and want to select only selected columns instead of *
عدنان محمودPosted Sep 9, 2019, 11:12 PM
I get the IndexOutOfRangeException after deployment
Kapil AgrawalPosted Aug 6, 2019, 2:18 AM
Hello Rajeev, I am able to read data in debug mode but after publishing its not working, could you please suggest what might be the problem ?
Anu RadhaPosted Apr 1, 2019, 10:09 PM
Rajeev Punhani Please do reply
Anu RadhaPosted Apr 1, 2019, 5:52 AM
Hey can u get excel file data without uploading it manually by specifying excel file path
prashant solankiPosted Nov 21, 2018, 8:56 AM
Hi I could not see data on view side can you please help
Ayush PatilPosted Jun 30, 2018, 5:25 AM
Hi, can you do the same thing in mvc with get all the excel sheet data and get it into dataset as per sheet name and display data as per query apply.
Nithish ReddyPosted Mar 13, 2018, 5:41 AM
How to do for csv file import
Nithish ReddyPosted Mar 7, 2018, 4:44 AM
Nice article very helpful
Yasir NazirPosted May 31, 2017, 5:18 PM
What if I am using excel 2016 then what microsoft.ace.oledb I need to use because I am getting exception
subhash raoPosted Mar 3, 2017, 4:32 AM
Thanks for the article
Santhakumar MunuswamyPosted Jan 5, 2016, 11:12 PM
Thanks for nice article. can you upload source code it will helpful for the beginner
Gowtham RajamanickamPosted Jan 5, 2016, 7:26 AM
Good article
Debasis SahaPosted Jan 5, 2016, 4:59 AM
Good one..
Humayun Kabir MamunPosted Jan 5, 2016, 3:49 AM
Nice...
Arul RPosted Jan 5, 2016, 2:35 AM
Nice share
Ankit BansalPosted Jan 5, 2016, 1:44 AM
nice..
Shridhar SharmaPosted Jan 5, 2016, 12:19 AM
nice share Rajeev.