I have a C# program that I want to import an Excel file into Microsoft SQL Server 2008 R2.
Can someone give me a link or tutorial where I can fully understand on how to this?
I've been doing this for a long time and I really don't have an idea on how to implement this.
Please help. Thanks.
string excelConnectionString = #"Provider=Microsoft
.Jet.OLEDB.4.0;Data Source=Book1.xls;Extended
Properties=""Excel 8.0;HDR=YES;""";
// Create Connection to Excel Workbook
We can Import excel to sql server like this
using (OleDbConnection connection =
new OleDbConnection(excelConnectionString)){
OleDbCommand command = new OleDbCommand
("Select ID,Data FROM [Data$]", connection);
connection.Open();
`// Create DbDataReader to Data Worksheet `
using (DbDataReader dr = command.ExecuteReader())
{
// SQL Server Connection String
string sqlConnectionString = "Data Source=.;
Initial Catalog=Test;Integrated Security=True";
// Bulk Copy to SQL Server
using (SqlBulkCopy bulkCopy =
new SqlBulkCopy(sqlConnectionString))
{
bulkCopy.DestinationTableName = "ExcelData";
bulkCopy.WriteToServer(dr);
}
This code may also help you.
private void processExcel(string filename)
{
filename = Server.MapPath("~/Files/WM-0b23-productsBook.xlsx");
Microsoft.Office.Interop.Excel.Application xlApp;
Microsoft.Office.Interop.Excel.Workbook xlWorkBook;
Microsoft.Office.Interop.Excel.Worksheet xlWorkSheet;
var missing = System.Reflection.Missing.Value;
xlApp = new Microsoft.Office.Interop.Excel.Application();
xlWorkBook = xlApp.Workbooks.Open(filename, false, true, missing, missing, missing, true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, '\t', false, false, 0, false, true, 0);
xlWorkSheet = (Microsoft.Office.Interop.Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
Microsoft.Office.Interop.Excel.Range xlRange = xlWorkSheet.UsedRange;
Array myValues = (Array)xlRange.Cells.Value2;
int vertical = myValues.GetLength(0);
int horizontal = myValues.GetLength(1);
System.Data.DataTable dt = new System.Data.DataTable();
// must start with index = 1
// get header information
for (int i = 1; i <= horizontal; i++)
{
dt.Columns.Add(new DataColumn(myValues.GetValue(1, i).ToString()));
}
// Get the row information
for (int a = 2; a <= vertical; a++)
{
object[] poop = new object[horizontal];
for (int b = 1; b <= horizontal; b++)
{
poop[b - 1] = myValues.GetValue(a, b);
}
DataRow row = dt.NewRow();
row.ItemArray = poop;
dt.Rows.Add(row);
}
// assign table to default data grid view
GridView1.DataSource = dt;
GridView1.DataBind();
xlWorkBook.Close(true, missing, missing);
xlApp.Quit();
releaseObject(xlWorkSheet);
releaseObject(xlWorkBook);
releaseObject(xlApp);
}
private void releaseObject(object obj)
{
try
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
obj = null;
}
catch (Exception ex)
{
obj = null;
MessageBox.Show("Unable to release the Object " + ex.ToString());
}
finally
{
GC.Collect();
}
}
Check out this post :
Bulk Insertion of Data Using C# DataTable and SQL server OpenXML function
Import Data from Excel to SQL Server
I think that most useful answers already have been given.
I am not going to describe the C# way, but rathher give you an easy way of doing it without C#:
Open your MS Access, link your MS SQL database via ODBC, open your table in Access and paste your Excel records there via copy-paste (preformatted to match the table schema.)
This way is very fast and useful when you do some one-time data import.
Related
I want to read an excel file. This excel file have multiple sheets. The user have the choice to select which sheet is loaded in c# to work with it. I want to copy data into access database.
I have written the code for loading excel workbook and for copying data into access database table. But in this code only user select the Excel file not the worksheet, i have hard coded the worksheet name Seven in code.
How to give functionality for user to select his own choice sheet in
workbook excel. Also i want to retrieve all worksheets in excel file.
Code is under
private void btnImport_Click(object sender, EventArgs e)
{
var openFileExcel = new OpenFileDialog()
{
Filter = "Excel Files | *.xlsx; *.xls; *.xlsm",
Title = "Select an Excel File",
CheckFileExists = true
};
if (openFileExcel.ShowDialog() == DialogResult.Cancel)
return;
DatabaseObjects.FileName = openFileExcel.FileName;
using(OleDbConnection conn = new OleDbConnection(DatabaseObjects.ConnectionString),
connExcel = new OleDbConnection(DatabaseObjects.ConnectionStringExcel))
{
string query = "INSERT INTO Students (RollNo, SName, FName, ClassID) VALUES(#RollNo, #SName, #FName, #ClassID)";
string queryExcel = "SELECT * FROM [Seven$]";
using (OleDbCommand command = new OleDbCommand(query, conn), commandExcel = new OleDbCommand(queryExcel,connExcel))
{
OleDbParameter param1 = new OleDbParameter("RollNo", OleDbType.Numeric);
command.Parameters.Add(param1);
OleDbParameter param2 = new OleDbParameter("SName", OleDbType.VarChar);
command.Parameters.Add(param2);
OleDbParameter param3 = new OleDbParameter("FName", OleDbType.VarChar);
command.Parameters.Add(param3);
OleDbParameter param4 = new OleDbParameter("ClassID", OleDbType.Numeric);
command.Parameters.Add(param4);
conn.Open();
connExcel.Open();
OleDbDataReader drExcel = commandExcel.ExecuteReader();
while(drExcel.Read())
{
param1.Value = Convert.ToInt32(drExcel[0]);
param2.Value = drExcel[1].ToString();
param3.Value = drExcel[2].ToString();
param4.Value = Convert.ToInt32(drExcel[4]);
command.ExecuteNonQuery();
}
}
}
}
I'm using the office interop classes to retrieve sheets names in excel file
Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel.Workbook excelBook = xlApp.Workbooks.Open("D:\\Book1.xlsx");
String[] excelSheets = new String[excelBook.Worksheets.Count];
int i = 0;
foreach(Microsoft.Office.Interop.Excel.Worksheet wSheet in excelBook.Worksheets)
{
excelSheets[i] = wSheet.Name;
i++;
}
You can put the list of sheets into a DataTable quite easily.
DataTable dtSheets = conn.GetSchema("Tables")
Pardon me, I went all the way to VBA, since I read the word EXCEL... LOL
Now, to get the list of the existing table in c# you can use
DataTable schemaTable = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
You need conn to be an active connection.
To get the sheets name:
foreach (DataRow dr in schemaTable.Rows)
{
ExcelSheets.Add(dr["TABLE_NAME"].ToString());
}
or, using LINQ
ExcelSheets = schemaTable.AsEnumerable()
.Select(r => r.Field<string>("TABLE_NAME"))
.ToList();
UPDATED 3/12/20. I am struggling with a problem where the Excel application is not releasing following my function call below. I'm not sure what references I'm screwing up but I assume I'm somehow leaving a reference to the application because I see multiple Excel processes in my task manager as the program runs, not to mention large amounts of memory use that don't improve with GC. Thoughts?
static void ParseExcel(string file, SqlConnection conn)
{
Excel.Application xlApp = new Excel.Application();
Excel.Workbook xlWorkbook = xlApp.Workbooks.Open(file);
Excel._Worksheet xlWorksheet = xlWorkbook.Sheets[1];
Excel.Range rng = xlWorksheet.UsedRange;
SqlCommand cmd = conn.CreateCommand();
double colCount = rng.Columns.Count;
double rowCount = rng.Rows.Count;
//iterate over the rows and columns
//start on row 2 since row 1 is column headers
for (int i = 2; i <= rowCount; i++)
{
string companyName = "";
for (int j = 1; j <= colCount; j++)
{
//write the value to the console
if (rng.Cells[i, j] != null && rng.Cells[i, j].Value2 != null)
{
string tst = rng.Cells[i, j].Value2.ToString();
switch (j)
{
case 2:
companyName = tst;
break;
}
} //end of column
}//end of row
//write to database
string sql = "insert into dbo.company( ";
sql += DBI(companyName) + ")";
Console.WriteLine("sql = " + sql);
try
{
cmd.CommandText = sql;
cmd.ExecuteNonQuery();
}catch(Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
xlApp.Quit();
Marshal.ReleaseComObject(rng);
Marshal.ReleaseComObject(xlWorksheet);
Marshal.ReleaseComObject(xlWorkbook);
Marshal.ReleaseComObject(xlApp);
System.Threading.Thread.Sleep(3000);
}
and outside call looks like this:
ParseExcel(#"c:\testfile.xls", conn);
//cleanup
GC.Collect();
GC.WaitForPendingFinalizers();
I should not have made my parse method static. That was the cause of the memory leak.
I've written some code that copies the data from an Azure database into an Excel file. This can be found at the end of this question.
The problem is it takes forever to populate an excel sheet when I have 10k rows for one of the tables. Obviously, this is not ideal for Excel but at this point it has to be done this way. I'm wondering if there is a faster way to code this.
Certainly, creating excel sheet is the bottleneck, because C# grabs the dataset in seconds. If I go into Excel and view the data and then right click and copy with headers and paste that into and excel sheet it also does this in seconds.
So can I programmatically do this?
private void createExcelFile()
{
string fileName = "FvGReport.xlsx";
string filePath = HttpContext.Current.Request.MapPath("~/App_Data/" + fileName); //check www.dotnetperls.com/mappath
string sqlQuery = "";
List<string> sheetNames = new List<string>();
foreach (ListItem item in ddlSummary_Supplier.Items)
{
string sqlSummary = "SELECT * FROM FvGSummaryAll WHERE Supplier_Code = '" + item.Text + "'; ";
sqlQuery = sqlQuery + sqlSummary;
sheetNames.Add("Summary " + item.Text);
string sqlPaymentsSummary = "SELECT * FROM FvGSummaryPayment WHERE Supplier_Code = '" + item.Text + "'; ";
sqlQuery = sqlQuery + sqlPaymentsSummary;
sheetNames.Add("PaymentSummary " + item.Text);
}
DataSet dataSet = new DataSet();
//string sqlQuery = #"SELECT * FROM FvGData WHERE Supplier_Code = 'SFF Pacific'; SELECT * FROM FvGSummaryPayment";
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
SqlDataAdapter adapter = new SqlDataAdapter();
adapter.SelectCommand = new SqlCommand(sqlQuery, connection);
adapter.Fill(dataSet);
}
//this reference conflicts with System.Data as both have DataTable. So defining it here.
Microsoft.Office.Interop.Excel.Application ExcelApp = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel.Workbook excelWorkBook = null;
Microsoft.Office.Interop.Excel.Worksheet excelWorkSheet = null;
ExcelApp.Visible = true;
excelWorkBook = ExcelApp.Workbooks.Add(Microsoft.Office.Interop.Excel.XlWBATemplate.xlWBATWorksheet);
//excel rows start at 1 not 0
try
{
for (int i = 1; i < dataSet.Tables.Count; i++)
{
excelWorkBook.Worksheets.Add(); //Adds new sheet in Excel WorkBook
}
for (int i = 0; i < dataSet.Tables.Count; i++)
{
int dsRow = 1;
excelWorkSheet = excelWorkBook.Worksheets[i + 1];
//Writing Columns Name in Excel Sheet
for (int col = 1; col < dataSet.Tables[i].Columns.Count; col++)
{
excelWorkSheet.Cells[dsRow, col] = dataSet.Tables[i].Columns[col - 1].ColumnName;
}
dsRow++;
for (int xlRow = 0; xlRow < dataSet.Tables[i].Rows.Count; xlRow++)
{
//Excel row and col positions for writing row = 1, col = 1
for (int col = 1; col < dataSet.Tables[i].Columns.Count; col++)
{
excelWorkSheet.Cells[dsRow, col] = dataSet.Tables[i].Rows[xlRow][col - 1].ToString();
}
dsRow++;
}
excelWorkSheet.Name = sheetNames[i]; //Renaming ExcelSheets
}
excelWorkBook.SaveAs(filePath);
excelWorkBook.Close();
ExcelApp.Quit();
Marshal.ReleaseComObject(excelWorkSheet);
Marshal.ReleaseComObject(excelWorkBook);
Marshal.ReleaseComObject(ExcelApp);
}
catch (Exception ex)
{
lblNoData.Text = ex.ToString();
}
finally
{
foreach (Process process in Process.GetProcessesByName("Excel"))
{
process.Kill();
}
}
downloadExcel(filePath, fileName);
}
It looks like you're using Office Automation, which is usually slow on things like this, in my experience. I would suggest saving the output as a delimited file (.csv) and using automation to open that file (or files) with Excel and then save it as a spreadsheet.
I would suggest you to try using some ETL tool, Esspecially if you will do this from time to time again. If you take Talend, for instance, .... you connect to the DB and the schema will be pulled on its own. Take a SQL input component and connect it to a Excel component and you are done. Take about 5 minutes, without a single line of code
I'm not sure what you mean by 'forever', but for comparison I have a process that writes an OpenXML Spreadsheet of 46,124 row with ~500 characters per row in less than 17-seconds. This is generated on by a C# process that is on a separate server at the same hosting facility as the database server.
If writing to a CSV is an option, then that is going to be the solution with the best performance. OpenXML will give you the next best performance, I found the following article to be the most helpful when I was trying to put together my process:
Read-and-Write-Microsoft-Excel-with-Open-XML-SDK
Regarding memory -- You have two things you need to put in memory, your incoming data and your outgoing file. Regardless of what type of file you write, you'll want to use a SqlDataReader instead of your dataSet. This means your incoming data will only have one row at a time in memory (instead of all 10K). When writing your file (CSV or OpenXML) if you write directly to disk (FileStream) instead of memory (MemoryStream) you'll only have that little bit in memory.
Especially if you are running code that is running within your website, you don't want to use up a bunch of memory at once because .NET/IIS doesn't handle that very well.
I have excel file with several excel tables. I want to read all the data in excel tables for a given excel sheet and copy those to a different excel table.
One excel sheet may have several tables
I have done that through VBA. I want to find a C# code to achieve it.
This is the VBA code I used.
Dim tableObject As ListObject
Dim oLastRow As ListRow
Dim srcRow As Range
Set sheet = ThisWorkbook.Worksheets("Sheet1")
For Each tableObject In sheet.ListObjects
Set srcRow = tableObject.DataBodyRange
Set oLastRow = Worksheets("Sheet2").ListObjects("table1").ListRows.Add
srcRow.Copy
oLastRow.Range.PasteSpecial xlPasteValues
Next
Try to follow this:
public static DataTable exceldata(string filePath)
{
DataTable dtexcel = new DataTable();
bool hasHeaders = false;
string HDR = hasHeaders ? "Yes" : "No";
string strConn;
if (filePath.Substring(filePath.LastIndexOf('.')).ToLower() == ".xlsx")
strConn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + filePath + ";Extended Properties=\"Excel 12.0;HDR=" + HDR + ";IMEX=0\"";
else
strConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + filePath + ";Extended Properties=\"Excel 8.0;HDR=" + HDR + ";IMEX=0\"";
OleDbConnection conn = new OleDbConnection(strConn);
conn.Open();
DataTable schemaTable = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });
//Looping Total Sheet of Xl File
/*foreach (DataRow schemaRow in schemaTable.Rows)
{
}*/
//Looping a first Sheet of Xl File
DataRow schemaRow = schemaTable.Rows[0];
string sheet = schemaRow["TABLE_NAME"].ToString();
if (!sheet.EndsWith("_"))
{
string query = "SELECT * FROM [" + sheet3 + "]";
OleDbDataAdapter daexcel = new OleDbDataAdapter(query, conn);
dtexcel.Locale = CultureInfo.CurrentCulture;
daexcel.Fill(dtexcel);
}
conn.Close();
return dtexcel;
}
You can also use the following part of code to import data from tables inside your excel sheet
static void Main(string[] args)
{
try
{
ReadInData readInData = new ReadInData(#"C:\SC.xlsx", "sc_2014");
IEnumerable<Recipient> recipients = readInData.GetData();
}
catch (Exception ex)
{
if(!(ex is FileNotFoundException || ex is ArgumentException || ex is FileToBeProcessedIsNotInTheCorrectFormatException))
throw;
Console.WriteLine(ex.Message);
}
Console.Write(Press any key to continue...);
Console.ReadKey(true);
}
public static class ReadInData
{
public static IEnumerable<Recipient> GetData(string path, string worksheetName, bool isFirstRowAsColumnNames = true)
{
return new ExcelData(path).GetData(worksheetName, isFirstRowAsColumnNames)
.Select(dataRow => new Recipient()
{
Municipality = dataRow["Municipality"].ToString(),
Sexe = dataRow["Sexe"].ToString(),
LivingArea = dataRow["LivingArea"].ToString()
});
}
}
private static IExcelDataReader GetExcelDataReader(string path, bool isFirstRowAsColumnNames)
{
using (FileStream fileStream = File.Open(path, FileMode.Open, FileAccess.Read))
{
IExcelDataReader dataReader;
if (path.EndsWith(".xls"))
dataReader = ExcelReaderFactory.CreateBinaryReader(fileStream);
else if (path.EndsWith(".xlsx"))
dataReader = ExcelReaderFactory.CreateOpenXmlReader(fileStream);
else
throw new FileToBeProcessedIsNotInTheCorrectFormatException("The file to be processed is not an Excel file");
dataReader.IsFirstRowAsColumnNames = isFirstRowAsColumnNames;
return dataReader;
}
}
private static DataSet GetExcelDataAsDataSet(string path, bool isFirstRowAsColumnNames)
{
return GetExcelDataReader(path, isFirstRowAsColumnNames).AsDataSet();
}
private static DataTable GetExcelWorkSheet(string path, string workSheetName, bool isFirstRowAsColumnNames)
{
DataTable workSheet = GetExcelDataAsDataSet(path, isFirstRowAsColumnNames).Tables[workSheetName];
if (workSheet == null)
throw new WorksheetDoesNotExistException(string.Format("The worksheet {0} does not exist, has an incorrect name, or does not have any data in the worksheet", workSheetName));
return workSheet;
}
private static IEnumerable<DataRow> GetData(string path, string workSheetName, bool isFirstRowAsColumnNames = true)
{
return from DataRow row in GetExcelWorkSheet(path, workSheetName, isFirstRowAsColumnNames).Rows select row;
}
I think you'll find that Excel's COM interface is very similar to VBA in that the class libraries are all identical. The only challenge is in grabbing the Excel instance and then managing the syntactical differences (ie VBA uses parentheses for indexers, and C# uses square brackets).
Assuming your VBA works, this should be the identical code in C# to grab an open instance of Excel and do what you have done. If you want to open a new instance of Excel, that's actually even easier (and very easy to Google):
Excel.Application excel;
Excel.Workbook wb;
try
{
excel = (Excel.Application)Marshal.GetActiveObject("Excel.Application");
excel.Visible = true;
wb = (Excel.Workbook)excel.ActiveWorkbook;
}
catch (Exception ex)
{
ErrorMessage = "Trouble Locating Open Excel Instance";
return;
}
Excel.Worksheet sheet = wb.Worksheets["Sheet1"];
foreach (Excel.ListObject lo in sheet.ListObjects)
{
Excel.Range srcRow = lo.DataBodyRange;
Excel.ListRow oLastRow = wb.Worksheets["Sheet2"].ListObjects["table1"].ListRows.Add();
srcRow.Copy();
oLastRow.Range.PasteSpecial(Excel.XlPasteType.xlPasteValues);
}
This all presupposes you have referenced Excel COM and set your using:
using Excel = Microsoft.Office.Interop.Excel;
I am using Asp.net with C#. I need to import data from an Excel sheet to a DataTable. The sheet has 100,000 records with four columns: Firstname, LastName, Email,Phone no.
How can I do this?
Use the following code:
public static DataTable exceldata(string filePath)
{
DataTable dtexcel = new DataTable();
bool hasHeaders = false;
string HDR = hasHeaders ? "Yes" : "No";
string strConn;
if (filePath.Substring(filePath.LastIndexOf('.')).ToLower() == ".xlsx")
strConn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + filePath + ";Extended Properties=\"Excel 12.0;HDR=" + HDR + ";IMEX=0\"";
else
strConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + filePath + ";Extended Properties=\"Excel 8.0;HDR=" + HDR + ";IMEX=0\"";
OleDbConnection conn = new OleDbConnection(strConn);
conn.Open();
DataTable schemaTable = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });
//Looping Total Sheet of Xl File
/*foreach (DataRow schemaRow in schemaTable.Rows)
{
}*/
//Looping a first Sheet of Xl File
DataRow schemaRow = schemaTable.Rows[0];
string sheet = schemaRow["TABLE_NAME"].ToString();
if (!sheet.EndsWith("_"))
{
string query = "SELECT * FROM [" + sheet3 + "]";
OleDbDataAdapter daexcel = new OleDbDataAdapter(query, conn);
dtexcel.Locale = CultureInfo.CurrentCulture;
daexcel.Fill(dtexcel);
}
conn.Close();
return dtexcel;
}
Source: http://www.codeproject.com/Questions/445400/Read-Excel-Sheet-Data-into-DataTable
You may also refer the following question: Importing Excel into a DataTable Quickly if you wish to import faster.
I'm not sure if this will work in ASP.NET but it works in WPF so maybe there's something you can take from it?
Anyway, at the global scope:
Microsoft.Office.Interop.Excel.Application xls;
Then to select and read a spreadsheet:
private void readSheet()
{
// Initialise and open file picker
OpenFileDialog openfile = new OpenFileDialog();
openfile.DefaultExt = ".xlsx";
openfile.Filter = "Office Files | *xls;.xlsx";
var browsefile = openfile.ShowDialog();
if (browsefile == true)
{
string path = openfile.FileName;
xls = new Microsoft.Office.Interop.Excel.Application();
// Dynamic File Using Uploader... Note the readOnly flag is true
Workbook excelBook = xls.Workbooks.Open(path, 0, true, 5, "", "", true, XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
Worksheet excelSheet = (Worksheet)excelBook.Worksheets.get_Item(1); ;
Range excelRange = excelSheet.UsedRange;
// Make default cell contents
string strCellData = String.Empty;
double douCellData;
// Initialise row and column
int rowCnt, colCnt = 0;
// Initialise DataTable
System.Data.DataTable dt = new System.Data.DataTable();
// Loop through first row of columns to make header
for (colCnt = 1; colCnt <= excelRange.Columns.Count; colCnt++)
{
string strColumn = "";
strColumn = Convert.ToString((excelRange.Cells[1, colCnt] as Range).Value2);
var Column = dt.Columns.Add();
Column.DataType = Type.GetType("System.String");
// Check & rename for duplicate entries
if (dt.Columns.Contains(strColumn))
Column.ColumnName = (strColumn + ", " + colCnt);
else
Column.ColumnName = strColumn;
}
dt.AcceptChanges();
// Fill in the rest of the cells
for (rowCnt = 2; rowCnt <= excelRange.Rows.Count; rowCnt++)
{
string strData = "";
for (colCnt = 1; colCnt <= excelRange.Columns.Count; colCnt++)
{
try
{
strCellData = Convert.ToString((excelRange.Cells[rowCnt, colCnt] as Range).Value2);
strData += strCellData + "|";
}
catch (Exception ex)
{
douCellData = (excelRange.Cells[rowCnt, colCnt] as Range).Value2;
strData += douCellData.ToString() + "|";
Console.Write(ex.ToString());
}
}
strData = strData.Remove(strData.Length - 1, 1);
dt.Rows.Add(strData.Split('|'));
}
dtGrid.ItemsSource = dt.DefaultView;
try
{
excelBook.Close(true, null, null);
}
catch (System.Runtime.InteropServices.COMException comEX)
{
Console.Write("COM Exception: " + comEX.ToString());
}
xls.Quit();
}
}
Speed Problems?
I'll note several ways to do this:
ODBC (answered here)
Interop (answered here)
These have drawbacks, they might not be fast; Interop requires excel, runs it, and can cause lots of problems with re-running it or the web server trying to run it.
please try #milan_m solution first. If it has problems come back here.
So some faster, potentially better solutions are as such.
NPOI
Save-As CSV
NPOI is available as a NuGet for C# and will read excel files very well. Yes this is a product recommendation, but you didn't ask for one. It is a well-maintained project and will be relevant for readers into the 2030s.
https://github.com/nissl-lab/npoi
You'll want to use NPOI if ODBC is too slow, and your users are uploading a different XLSX file as part of the use case. Unless there are only 2 or 3 internal power users you are in contact with, then you can require them to upload it as CSV.
What if the use case is: You just use one .XLSX file that's the same for all users, you deploy it with the app?
You didn't mention if this is the case or not and it makes a HUGE difference. you definitely will be miles ahead if you save as csv and consume that from the startup of the program. Or, if you need it in a datatable, import it to the data table at dev time and save it to XML file using a method on the dataset object (you have to put the tbl into a set to save as XML I believe ... many examples abound).
If you need to do super flexible lookups, a datatable (or object collection and linq-to-objects) is good.
However if you have to look up items at extreme speed, and not via ranges but just by exact match, load it to a dictionary or dictionaries at startup time, from a CSV or similar.
I did this for a power user who was searching a spreadsheet of about 2-3lakh / records with interop+excel ... operation went from 90 minutes to 30 seconds. Literally. Dictionary is about the fastest way to look stuff up in .Net, if you can fit that stuff in memory, that is, and don't have to reload different data all the time (so keep your RDBMS).
Oops.
Just now saw this question is 7 years old. ##$^##!!!