I'm trying to insert multiple records with excel file to database. Scenerio is, the user selects the excel file from his hard drive then the code reads first row and shows it as the title columns. These columns are not ordered. So user matches right columns with drop down.
Everything is okay until now. But after matching I have to read the file again from another action. But i am not saving file to server. Is there any way to read or hold the file in variable or session?
My code similiar like this
public JsonResult ExcelUpload(FormCollection formCollection)
{
if (Request != null)
{
HttpPostedFileBase file = Request.Files["ExcelFile"];
}
}
If you mean by "another action", you mean a different HTTP request, then you can't do that without it persisting somewhere.
Better read file in data table by using library given here
FileStream stream = File.Open(filePath, FileMode.Open, FileAccess.Read);
//1. Reading from a binary Excel file ('97-2003 format; *.xls)
IExcelDataReader excelReader = ExcelReaderFactory.CreateBinaryReader(stream);
//...
//2. Reading from a OpenXml Excel file (2007 format; *.xlsx)
IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
//...
//3. DataSet - The result of each spreadsheet will be created in the result.Tables
DataSet result = 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();
and store DataSet into session for further processing.
Related
I have a page on my site where a user can upload a XLSX spreadsheet. This is a .NET Core web application using the DocumentFormat.OpenXml (2.15.0) NuGet package.
I'm trying to read through each row in the spreadsheet they upload and do something with that data. I'm trying to do this without saving a physical file by copying the file to a MemoryStream, then reading the file from that stream, but not sure if that's possible.
The problem is that when reading the doc from the stream, it's like there's no data in the spreadsheet
Here's what I have:
using (var memoryStream = new MemoryStream())
{
await viewModel.SpreadsheetFile.CopyToAsync(memoryStream).ConfigureAwait(false);
// confirm that copying to memory stream worked correctly
var fileBytes = memoryStream.ToArray();
string s = Convert.ToBase64String(fileBytes);
using (SpreadsheetDocument document = SpreadsheetDocument.Open(memoryStream, true))
{
WorkbookPart workbook = document.WorkbookPart;
WorksheetPart worksheet = workbook.WorksheetParts.First();
SheetData sheetData = worksheet.Worksheet.Elements<SheetData>().First();
string text;
// no rows, doesn't enumerate here
foreach (Row r in sheetData.Elements<Row>())
{
foreach (Cell c in r.Elements<Cell>())
{
text = c.CellValue.Text;
// do stuff
}
}
}
}
I added a couple lines to read bytes from the memory stream just to confirm that it's working, which it is.
But when I try to create a SpreadsheetDocument from the memory stream and read the sheet data, it's just empty, it doesn't enumerate through the rows.
The code to read the sheet data I got from here: https://learn.microsoft.com/en-us/office/open-xml/how-to-parse-and-read-a-large-spreadsheet
Is this possible, or am I just doing this wrong?
You need to set memory stream to zero after reading to it. Change code to this:
await viewModel.SpreadsheetFile.CopyToAsync(memoryStream).ConfigureAwait(false);
memoryStream.Position = 0;
I have two sheets in CSV excel file which I upload using the following code. But from this code it reads only the first sheet. Even httpRequest.Files.Count returns only 1. How to read both sheet of the file
var httpRequest = HttpContext.Current.Request;
if (httpRequest.Files.Count > 0)
{
foreach (string file in httpRequest.Files)
{
long dataSourceId = 1;
var postedFile = httpRequest.Files[file];
var filePath = HttpContext.Current.Server.MapPath("~/" + postedFile.FileName);
//postedFile.SaveAs(filePath);
Stream stream = postedFile.InputStream;
byte[] fileData = null;
using (var binaryReader = new BinaryReader(postedFile.InputStream))
{
fileData = binaryReader.ReadBytes(postedFile.ContentLength);
}
Stream strrr = new MemoryStream(fileData);
}
}
From what I can tell CSV files aren't workbooks like Excel files, so you won't be about to read CSV file with two sheets as two entities on a single file. This is why I came to that conclusion:
http://network.ubotstudio.com/forum/index.php/topic/3236-save-in-multiple-sheets-in-a-csv-file/
You have two options: 1) Create multiple CSV files with the needed data and read from them individually OR 2) Use an Excel file that is formatted to handle these multiple sheet features.
I'm using ExcelDataReader v.2.1. library to read both xls and xlsx files in my C# project. This way:
FileStream stream = File.Open(filePath, FileMode.Open, FileAccess.Read);
IExcelDataReader excelReader;
string extension = Path.GetExtension(filePath);
if (extension == ".xls")
{
excelReader = ExcelReaderFactory.CreateBinaryReader(stream);
}
else if (extension == ".xlsx")
{
excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
}
else
{
throw new NotSupportedException("Wrong file extension");
}
return excelReader;
Then, I use "AsDataSet" method to get a filled DataSet:
_dataSet = GetDataReader(_options.Filepath).AsDataSet();
It works fine most of the times, but, with some XLSX files, it only reads the first column.
I've been looking at excelReader instance with a Watch and I saw that it actually gets all the values of the Excel, but then, when using the AsDataSet method, it only reads the first column.
Do you know what can be going wrong here? Do you think it could be a "AsDataSet" method bug?
install ExcelDataReader.DataSet via nugget
Install-Package ExcelDataReader.DataSet -Version 3.6.0
Install DataSet to work with AsDataSet
I have a WebApi wich will receive an excel file uploaded by the user as multipart/form-data.
I need to read the content of that file in order to update the database. I was thinking on using EPPlus but I can't access the file.
Here is the code
public class MyController : APIController
{
[Route("import")]
[HttpPost]
public async Task<HttpResponseMessage> importFile()
{
if (!Request.Content.IsMimeMultipartContent())
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, "ERROR");
Stream stream = await Request.Content.ReadAsStreamAsync();
var excel = new ExcelPackage(stream);
var workbook = excel.Workbook;
var sheet = excel.Workbook.Worksheets.First();
...
}
The error is on the var sheet = excel.Workbook.Worksheets.First() because the Workbook doesn't have any Worksheet (but the physical file has 2).
What am I doing wrong? Is it the Stream?
I'm trying to have separate library for each type of Excel file (.xls or .xlsx) but I'm not able to make this work with the .xls files.
I'm using ExcelDataReader and the code is now like this:
public async Task<HttpResponseMessage> importFile()
{
if (!Request.Content.IsMimeMultipartContent())
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, "NOT MULTIPART");
Stream stream = await Request.Content.ReadAsStreamAsync();
//open xlsx file
var excel = new ExcelPackage(stream);
var workbook = excel.Workbook;
try
{
var sheet = excel.Workbook.Worksheets.First();
//working fine with EPPlus for .xlsx files
return Request.CreateResponse(HttpStatusCode.OK, errors);
}catch(Exception)//open xls file
{
//if its a .xls file it will throw an Exception
}
//using ExcelDataReader to open .xls file
IExcelDataReader excelReader = ExcelReaderFactory.CreateBinaryReader(stream);
DataSet result = excelReader.AsDataSet();
// the DataSet is null, stream is setted as ReadOnlyStream and stream.length is throwing an ObjectDisposedException
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "erro");
}
You can use Microsoft.Interop.Excel to read xls files, but even Microsoft disaproved this technique, because it is slow and it is not designed to run on servers. Furthermore, their support just ended.
As alternative you can use EasyXLS library. You can use it to read XLS files.
Take a look on this code sample that explains how to import an Excel file into a SQL table:
http://www.easyxls.com/manual/FAQ/import-excel-to-sql.html
I am trying to load a large excel file (~30MB) with 11 columns and 485k rows using the following code:
OpenFileDialog ofd = new OpenFileDialog();NameOfFile = ofd.SafeFileName;
if (NameOfFile.Contains("xlsx"))
{
NameOfFile = NameOfFile.Substring(0, NameOfFile.Length - 5);
}
else
{
NameOfFile = NameOfFile.Substring(0, NameOfFile.Length - 4);
}
string dbConn = "Provider=Microsoft.ACE.OLEDB.12.0;" + "Data Source=" + ofd.FileName + ";Extended Properties=" + "Excel 12.0;";
OleDbConnection con = new OleDbConnection(dbConn);
OleDbDataAdapter da = new OleDbDataAdapter("select * from [Contacts$]", con); //Contacts$ -> onoma filou sto excel
da.Fill(dataBase1);
dataGridView1.DataSource = dataBase1.Tables[0];
dataGridView1.Columns[0].Width = 35;
dataGridView1.Columns[1].Width = 35;
dataGridView1.Columns[2].Width = 35;
dataGridView1.Columns[3].Width = 35;
dataGridView1.Columns[4].Width = 35;
dataGridView1.Columns[5].Width = 40;
dataGridView1.Columns[9].Width = 55;
dataGridView1.Columns[10].Width = 60;
The problem is whenever I run my program and try to load the file the program freezes and has to be shut down. The program has been tested with smaller excel file (11 columns and 100 rows) and runs perfectlly.
Any ideas?
With 485K rows, hard to say if the problem is OLEDB or the DataGridView. I suggest you dump OLEDB and use a native excel library and then use Virtual Mode with the DataGridView.
The EPPlus library open source Excel library that can read the xlsx format (Office 2007 and later) and the ExcelLibrary project that can read the older xls binary format (prior to Office 2007).
Check this tutorial for implementing virtual mode in the DataGridView so that the Grid doesn't have to manage all 485K rows on the screen and in memory at once.
Using OLEDB to load large Excel files can be a problem. Take a look on this code sample that loads the Excel file and fill the DataGridView:
http://www.easyxls.com/manual/FAQ/import-excel-to-datagridview.html
It uses EasyXLS Excel library. If your DataGridView cannot display so big volume of data, you can adjust the code to load ranges from the Excel file and display data page by page or only the data that shows interest.
I have faced the same problem with big excel files and solved it by using Excel Data Reader library:
https://exceldatareader.codeplex.com/
It is lightweight, fast and free library written in C#.
Usage:
FileStream stream = File.Open( file, FileMode.Open, FileAccess.Read );
IExcelDataReader excelReader = null;
if (file.ToLower().EndsWith("xls"))
//1. Reading from a binary Excel file ('97-2003 format; *.xls)
excelReader = ExcelReaderFactory.CreateBinaryReader( stream );
else
//2. Reading from a OpenXml Excel file (2007 format; *.xlsx)
excelReader = ExcelReaderFactory.CreateOpenXmlReader( stream );
DataSet result = excelReader.AsDataSet();
and then you can do anything you want with the DataSet.