I get the Excel sheet with data uploaded from UI, I need to access that sheet through WCF service and insert the data contained in it into a SQL table.
Kindly guide how this can be done.
I am facing challenge in reading that Excel sheet through WCF service.
I have used below code to read a Excel sheet from a local drive. Change Source property to your FTP location of your excel sheet.
string con = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=D:\MyData.xlsx;" +
#"Extended Properties='Excel 8.0;HDR=Yes;'";
using (OleDbConnection connection = new OleDbConnection(con))
{
connection.Open();
OleDbCommand command = new OleDbCommand("select * from [Sheet1$]", connection);
using (OleDbDataReader dr = command.ExecuteReader())
{
while (dr.Read())
{
// Do your things here
}
}
}
Note: .xls has data limitations whereas .xlsx supports more data rows in a sheet. You need to install Microsoft Office Access database engine 2007 if you are going to read .xlsx files
string UploadedFilePath = FullPathOfExcelOnTheServer;
string ExcelConn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + UploadedFilePath + ";Extended Properties=\"Excel 12.0;HDR=Yes;IMEX=1;FMT=Delimited\"";
using (OleDbConnection oledbConnExcel = new OleDbConnection(ExcelConn))
{
oledbConnExcel.Open();
using (OleDbDataAdapter oledbAdapterExcel = new OleDbDataAdapter("SELECT * from [" + SheetName + "$]", oledbConnExcel))
{
using (DataTable dtblSheetData = new DataTable())
{
try
{
oledbAdapterExcel.Fill(dtblSheetData);
}
catch (Exception lexQuery)
{
}
}
}
oledbConnExcel.Close();
}
Fact is the is no way to read the excel data through WCF Service. But You can cosider this approaches
You may:
Read all excel data on client side and call WCF service and include all data from excel in parameter as (array of strings)?
You can create macro(VB) in Excel sheet and what call WCF Service and send data through parameter. When You have all logic in one place.
If client side is .NET side You can use atribbute [KnowsTypeAtribbute].Then You can call WCF service with param type as Excel type (Sheet or other). May by use some type form OpenXml dll may by usefull (But I don't know is sheet or other types is serializable. A serializable is require)
You can send to WFC service path to file and read excel file from that path through WCF service.
Related
I am trying to upload an excel(.xlsx) file in my application which has been created by the same application via open xml sdk. I am facing the exception 'External table not in expected format'. However if i manually open the file and save it and try again, it is uploaded without any errors.
Is there any way to programatically perform the task of opening the excel file and save ? I cannot ask my user/client to follow this workaround. Any leads would be helpful. Below is the code snippet which is throwing the exception. The line 'con.open()' is throwing the mentioned exception. Please find the connection string used
private readonly string connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"Excel 12.0 Xml;HDR=Yes;MAXSCANROWS=0;IMEX=1\";";
public DataTable GetSheetData(string sheetName)
{
System.IO.FileInfo fileInfo = new System.IO.FileInfo(this.filePath);
DataTable excelData = new DataTable();
excelData.Locale = CultureInfo.InvariantCulture;
using (OleDbConnection con = new OleDbConnection(string.Format(CultureInfo.CurrentCulture, this.connectionString, this.filePath)))
{
con.Open();
if (!string.IsNullOrEmpty(sheetName))
{
using (OleDbDataAdapter dataAdapter = new OleDbDataAdapter(string.Format(CultureInfo.CurrentCulture, "select * from [{0}$]", sheetName), con))
{
dataAdapter.Fill(excelData);
}
}
}
return excelData;
}
I figured out a workaround by programatically opening the excel file and saving it by Interop. Now I am able to upload the excel file without any errors.
var ExcelApp = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel.Workbook workbook = ExcelApp.Workbooks.Open(filePath);
workbook.Save();
workbook.Close();
ExcelApp.Quit();
I have a large excel file(530K Rows with a lot of columns). Ends up being 247MB in .xlsb format. I am attempting to import to SQL Server using BulkCopy in C#, however I am having issues where the datareader ends up running out of memory before it even starts reading the file once I run the ExecuteReader() command.
string exlConnString = $"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={_filepath};Extended Properties=\"Excel 12.0;HDR=YES;\"";
string sqlQuery = $"SELECT * FROM [{SheetName}]";
using OleDbConnection conn = new OleDbConnection(_connstring)) {
OleDbCommand exlCmd = new OleDbCommand(sqlQuery, conn)
conn.Open();
OleDbDataReader dr = exlcmd.ExecuteReader(); <---NEVER GETS PAST THIS LINE BEFORE RUNNING OUT OF MEMORY.
SqlBulkCopy bulkCopy = new SqlBulkCopy(sqlConnString);
bulkCopy.DestinationTable = TableName;
while(dr.Read()) {
bulkcopy.WriteToServer(dr);
}
dr.Close();
}
I am running in x86 mode because I was geting an error that the ACE Database was not installed on my local machine and corporate policy restrictions prevent me from downloading and installing the needed file to run it in x64 mode.
The code works perfectly fine when I test it on smaller files, but not when I test it on this bigger file, so it definitely is the filesize causing the issue. Any suggestions or help would be appreciated. Doesn't make much sense that a bulk copy runs out of memory when it is meant for handling large sets of data, which also means that the filesize is going to be large as well...
And yes, I know I SHOULD be able to import this using OPENROWSET or OPENDATASOURCE in SQL Server but THAT is ALSO Turned off and they will not enable it, so this is not an option.
So your problem is next.
When you try to ExecuteReader DataReader attempt to read all data from your excel file to memory. You could think about this, like a speciality working with excel through a OleDbProvider.
So my suggestion is to work with csv files instead of excel, because with csv file you have an ability to read and parse them line by line. For this aim i would recommend you to use CSV helper
Refer this code..
Here dtExcelData is datatable variable & da is OleDbDataAdapter variable.
string excelConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source={_filepath};Extended Properties='Excel 12.0;HDR=YES';";
// Create Connection to Excel Workbook
using (OleDbConnection connection = new OleDbConnection(excelConnectionString))
{
connection.Open();
da = new OleDbDataAdapter("Select * FROM [Sheet1$]", connection);
da.Fill(dtExcelData);
//store data in sql server database table
// below connection string "conString" is I mention in app.config file.(sql server connection string to store data in sql server database)
string str = ConfigurationManager.ConnectionStrings["conString"].ConnectionString;
using (SqlConnection con = new SqlConnection(str))
{
// Bulk Copy to SQL Server
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(con))
{
bulkCopy.DestinationTableName = "TableName";
con.Open();
bulkCopy.WriteToServer(dtExcelData);
con.Close();
}
}
connection.Close();
}
Mark it as a answer if it is useful to you. :)
I have created a SSIS import task, where in For Each Loop container I have Data Flow Task, in which I have Script Component where I try to import xlsx files from external drive folder to upload to database.
My excel connection method is:
private DataTable QueryData(string FileName, string Header, string QueryString)
{
string connectionString;
OleDbConnection excelConnection;
OleDbDataAdapter dataAdapter;
DataSet excelDataSet;
connectionString = "Provider = Microsoft.ACE.OLEDB.16.0; Data Source ="
+ FileName + ";Extended Properties=\"Excel 12.0 XML;HDR= "
+ Header + ";IMEX=1;\"";
excelConnection = new OleDbConnection(connectionString);
dataAdapter = new OleDbDataAdapter(QueryString, excelConnection);
excelDataSet = new DataSet();
dataAdapter.Fill(excelDataSet, "Sheet1");
excelConnection.Close();
return excelDataSet.Tables["Sheet1"];
}
The Script component works fine with files saved by me.
When the component tries to get information from Excel files that are saved by others, the method returns only one row with empty object[].
I have tried unsuccessfully to Run the SSIS as Administrator and also in the server as I suspect there might be problems with file permissions.
I have been trying to find a way to convert data type string to nvarchar while I am importing data from an excel spreadsheet. So far I have this piece of code to import the data through C#.
// Connection String to Excel Workbook,Replace DataSource value to point to your excel file location
string excelConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\Folder\\Folder\\Excel_File.xls ;Extended Properties=Excel 8.0";
// Create Connection to Excel Workbook
using (OleDbConnection connection =
new OleDbConnection(excelConnectionString))
{
OleDbCommand command = new OleDbCommand
("Select * FROM [Sheet1$]", connection);
connection.Open();
// Create DbDataReader to Data Worksheet
using (DbDataReader dr = command.ExecuteReader())
{
// SQL Server Connection String
string sqlConnectionString = "Data Source=localhost;Initial Catalog=DatabaseName;Integrated Security=True";
// Bulk Copy to SQL Server
using (SqlBulkCopy bulkCopy =
new SqlBulkCopy(sqlConnectionString))
{
bulkCopy.DestinationTableName = "Table_Name";
bulkCopy.WriteToServer(dr);
MessageBox.Show("Data Exported To Sql Server Successfully");
}
}
I have looked for ways to convert from string to nvarchar but the only examples that I have found are only for converting string collected from textboxes or through consoles. I do have one column though in date type but I have compensated for it in MSSQL.
If anyone could give me a sample code of what I should be doing it would be greatly appreciated.
My suspicion is that you are 'tripping' over some hidden characters that Excel is inserting in your text strings. Try logging the imported data to ensure that it's clean.
I wrote this method (almost similar in other post)
public void update(string fileName, string sheetName)
{
string connString = connString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + Server.MapPath(fileName) + ";Extended Properties='Excel 12.0;HDR=NO'";
try
{
OleDbConnection oledbConn = new OleDbConnection(connString);
oledbConn.Open();
OleDbCommand cmd = new OleDbCommand("UPDATE ["+sheetName+"$B5:B5] SET F1=17", oledbConn);
cmd.ExecuteNonQuery();
oledbConn.Close();
}
catch(Exception ex)
{
Debug.Write("Error: " + ex.Message);
}
}
and calling that method:
update("test.xls", "test");
So far, it works fine because when I open the test.xls file, B5 gets updated to 17. However, if there is a cell: B1 is dependent on B5: B1=B5*5, then B1 will not get updated automatically. I have to manually open the Excel file and save it with warning in order to get B1 updated. How can I do it programmatically?
I don't think that you can depend on Excel updating calculated columns when you use the ACE driver to interact with the Excel worksheet. When you are using OLEDB to operate on the workbook's worksheet, it is treating the worksheet as a database table like structure.
I think you may want to use OpenXML to read/write to the file. There are several threads on StackOverflow with more info on using OpenXML that are worth checking out.
This post shows your exactly how to force a cell re-calc using OpenXML.