I am trying to import a .csv file into my database. I am able to import an excel worksheet into my database, however due to different file format as .csv as from .xls, I need to make an import function specially for .csv.
Below is my code:
protected void Button1_Click(object sender, EventArgs e)
{
if (FileUpload1.HasFile)
{
// Get the name of the Excel spreadsheet to upload.
string strFileName = Server.HtmlEncode(FileUpload1.FileName);
// Get the extension of the Excel spreadsheet.
string strExtension = Path.GetExtension(strFileName);
// Validate the file extension.
if (strExtension != ".xls" && strExtension != ".xlsx" && strExtension != ".csv" && strExtension != ".csv")
{
Response.Write("<script>alert('Failed to import DEM Conflicting Role Datasheet. Cause: Invalid Excel file.');</script>");
return;
}
// Generate the file name to save.
string strUploadFileName = #"C:\Documents and Settings\rhlim\My Documents\Visual Studio 2005\WebSites\SoD\UploadFiles\" + DateTime.Now.ToString("yyyyMMddHHmmss") + strExtension;
// Save the Excel spreadsheet on server.
FileUpload1.SaveAs(strUploadFileName);
// Create Connection to Excel Workbook
string connStr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + strUploadFileName + ";Extended Properties=Text;";
using (OleDbConnection ExcelConnection = new OleDbConnection(connStr)){
OleDbCommand ExcelCommand = new OleDbCommand("SELECT [columns] FROM +userrolelist", ExcelConnection);
OleDbDataAdapter ExcelAdapter = new OleDbDataAdapter(ExcelCommand);
ExcelConnection.Open();
using (DbDataReader dr = ExcelCommand.ExecuteReader())
{
// SQL Server Connection String
string sqlConnectionString = "Data Source=<IP>;Initial Catalog=<DB>;User ID=<userid>;Password=<password>";
// Bulk Copy to SQL Server
using (SqlBulkCopy bulkCopy =
new SqlBulkCopy(sqlConnectionString))
{
bulkCopy.DestinationTableName = "DEMUserRoles";
bulkCopy.WriteToServer(dr);
Response.Write("<script>alert('DEM User Data imported');</script>");
}
}
}
}
else Response.Write("<script>alert('Failed to import DEM User Roles Data. Cause: No file found.');</script>");
}
The file has been successfully saved, but the error says that the path for the file is not valid, even though the file has been successfully saved as .csv, therefore I am not able to continue with the process of importing the data into my database.
Below are the screenshots of my error:
In conclusion I am having the error that the file path which the csv file is saved is not valid, although the csv file is successfully saved. Need some help from experienced. Thank You
If you're reading a CSV file, your connection string should specify the directory containing your CSV file.
string connStr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" +
Path.GetDirectoryName(strUploadFileName);
You then use the filename in your SELECT statement:
"SELECT * FROM [" + Path.GetFileName(strUploadFileName) + "]"
I think you have this problem because you use "/" instead of "\"
Try to modify the path C:\.....
You need to use the backward slashes(\) on the file path.
string strUploadFileName = #"C:\Documents and Settings\rhlim\My Documents\Visual Studio 2005\WebSites\SoD\UploadFiles\" + DateTime.Now.ToString("yyyyMMddHHmmss") + strExtension;
EDIT 1: I believe FileUpload1.SaveAs converts the / to \ internally to identify the correct location.
EDIT 2: Its the problem with your connectionstring, even though you are using .csv format, you need to set Excel 8.0 or Excel 12.0 Xml as the Extended Properties
Here is the sample:
string connStr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + strUploadFileName + ";Extended Properties=Excel 12.0 Xml;";
For other types, check the code of OLEDB section of my article.
To avoid the connection open you can use like
// Read the CSV file name & file path
// I am usisg here Kendo UI Uploader
string path = "";
string filenamee = "";
if (files != null)
{
foreach (var file in files)
{
var fileName = Path.GetFileName(file.FileName);
path = Path.GetFullPath(file.FileName);
filenamee = fileName;
}
// Read the CSV file data
StreamReader sr = new StreamReader(path);
string line = sr.ReadLine();
string[] value = line.Split(',');
DataTable dt = new DataTable();
DataRow row;
foreach (string dc in value)
{
dt.Columns.Add(new DataColumn(dc));
}
while (!sr.EndOfStream)
{
value = sr.ReadLine().Split(',');
if (value.Length == dt.Columns.Count)
{
row = dt.NewRow();
row.ItemArray = value;
dt.Rows.Add(row);
}
}
For more help you can also See This Link
Related
The program i got is able to load CSV and Excel files in to a datagridview.
This works perfectly fine except the CSV files retain old data.
For example, the CSV file has 30 values. i load the data in to the datagridview and it works fine.
I close the application and i then edit the CSV file removing 26 of the rows. The next time i open the application and load the file it still get's the version with 30 values even tho that file no longer exists.
To be clear, i open and edit the file in Notepad and it works as intended, but even after editing it in notepad my Winform application seems to load the previous version. Even if i rename the file it still takes the data that should no longer exist. Even after completely restarting the PC the file still retains data that should not exist.
BUT! If i move the file to a different folder (add new folder and just throw it in there) it does load the new data...
EDIT:
It seems that it is actually loading all CSV files in the folder. (including older versions)
what could cause this problem? Seeing the Excel files are not experiencing this problem.
The code used:
private void OpenExcel()
{
OpenFileDialog openFileDialog1 = new OpenFileDialog
{
InitialDirectory = #"C:\",
Title = "Browse Text Files",
CheckFileExists = true,
CheckPathExists = true,
DefaultExt = "txt",
FilterIndex = 2,
RestoreDirectory = true,
ReadOnlyChecked = true,
ShowReadOnly = true,
Filter = "Excel Worksheets|*.csv"
};
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
FileLocation = openFileDialog1.FileName;
GetExcelSheetNames(openFileDialog1.FileName);
MyConnection = new OleDbConnection(connString);
MyCommand = new OleDbDataAdapter("select * from [" + SheetName + "]", MyConnection);
MyCommand.TableMappings.Add("Table", "TestTable");
Datatable_Temp = new DataTable();
MyCommand.Fill(Datatable_Temp);
MyConnection.Close();
}
else
{
Canceled = true;
}
}
private string GetExcelSheetNames(string excelFile)
{
OleDbConnection objConn = null;
DataTable dt = null;
string CSVOrNot = excelFile.Substring(excelFile.Length - 3);
try
{
// Connection String.
if (CSVOrNot == "csv")
{
connString = string.Format(#"Provider=Microsoft.Jet.OleDb.4.0; Data Source={0};Extended Properties=""Text;HDR=YES;FMT=Delimited""", Path.GetDirectoryName(excelFile));
}
else
{
connString = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source=" + excelFile + ";Extended Properties=Excel 12.0;";
}
// Create connection object by using the preceding connection string.
objConn = new OleDbConnection(connString);
// Open connection with the database.
objConn.Open();
// Get the data table containg the schema guid.
dt = objConn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
if (dt == null)
{
MessageBox.Show("No Data Found");
return null;
}
SheetName = dt.Rows[0]["TABLE_NAME"].ToString();
return SheetName;
}
catch
{
return null;
}
finally
{
// Clean up.
if (objConn != null)
{
objConn.Close();
objConn.Dispose();
}
if (dt != null)
{
dt.Dispose();
}
}
}
i Found the issue, it was different then i thought.
Seeing older versions of the file were also in the folder i didn't notice that it wasn't taking an older version of itself but it was simply merging all CSV files in to the output.
I searched for this instead and found the following post:
c# reading csv file gives not a valid path
i added an if clause to see if the file is a csv file and then use the following:
Because the difference between opening an Excel or a CSV file is is that the Excel file asked for path and file name while CSV only wants the path and later on a query to select the file...a bit odd but ok.
MyCommand = new OleDbDataAdapter("SELECT * FROM [" + Path.GetFileName(openFileDialog1.FileName) + "]", MyConnection);
While uploading Excel there are values in columns in alphabets, so taking into datatable the values are getting blank.
below is the code which is making it blank.
string filename = Path.GetFileName(fluploadData.FileName);
// FileUpload.SaveAs(Server.MapPath("~/") + filename);
string filenamewithoutrext = string.Empty;
FileExt = Path.GetExtension(fluploadData.FileName).ToLower();
if (Path.GetExtension(fluploadData.FileName).ToLower() != ".xls" &&
Path.GetExtension(fluploadData.FileName).ToLower() != ".xlsx"
)
{
Response.Write("Only .xls,.xlsx are allowed.!");
return;
}
filenamewithoutrext = Path.GetFileNameWithoutExtension(fluploadData.FileName).ToLower();
string path = Server.MapPath("UploadData\\");
string filename_ = filenamewithoutrext;
// DeleteDirectory(path);
if (!Directory.Exists(path)) // CHECK IF THE FOLDER EXISTS. IF NOT, CREATE A NEW FOLDER.
{
Directory.CreateDirectory(path);
}
else
{
foreach (string file in Directory.GetFiles(path))
{
File.Delete(file);
}
}
string fname;
fname = path + filename_ + ".xls";
fluploadData.SaveAs(fname);
HttpContext.Current.Session["ExcelFilePath"] = fname;
string conStr = "";
System.Data.DataTable dtExcelRows = new System.Data.DataTable();
switch (FileExt)
{
case ".xls": //Excel 97-03
conStr = System.Configuration.ConfigurationManager.ConnectionStrings["Excel03ConString"].ConnectionString;
break;
case ".xlsx": //Excel 07
conStr = System.Configuration.ConfigurationManager.ConnectionStrings["Excel07ConString"].ConnectionString;
break;
}
conStr = String.Format(conStr, fname, "YES");
System.Data.OleDb.OleDbConnection connExcel = new System.Data.OleDb.OleDbConnection(conStr);
System.Data.OleDb.OleDbCommand cmdExcel = new System.Data.OleDb.OleDbCommand();
System.Data.OleDb.OleDbDataAdapter oda = new System.Data.OleDb.OleDbDataAdapter();
cmdExcel.Connection = connExcel;
connExcel.Open();
System.Data.DataTable dtExcelSchema = connExcel.GetOleDbSchemaTable(System.Data.OleDb.OleDbSchemaGuid.Tables, null);
System.Data.DataTable dtExcelColumnsTable = connExcel.GetSchema("Columns");
//string SheetName = dtExcelSchema.Rows[0]["TABLE_NAME"].ToString().Replace('\'', ' ').Trim();
string SheetName = dtExcelSchema.Rows[0]["TABLE_NAME"].ToString().Trim();
cmdExcel.CommandText = "SELECT * From [" + SheetName + "]";
oda.SelectCommand = cmdExcel;
oda.Fill(dtExcelRows);
connExcel.Close();
The problem is likely caused by mixed datatypes in a column. For example the first few rows have a number value so it is then presumed to be a column with a numeric type. When a non numeric value is encountered it can't be parsed and is ignored.
See this answer for some ways around this. They may include setting a value of IMEX=1 in the connection string or treating the header row as data (HDR=0) - assuming your column names are non numeric.
You might also want to look into specific libraries which are designed for reading/writing Excel Documents, I have had good experiences with EPPlus but it only works for .xlsx files not .xls, NPOI which I haven't used can do both.
As others have mentioned if you are just using the Excel document as a datasource for the applications it may be better to look into an alternative solution such as SQL. If you have a requirement to process spreadsheets from third parties obviously that would not be an option.
I need this code C# working for files excel 2003 and 2007 version.
I can't get this C# code working to convert excel file (xls) on csv file.
If try with excel file extension xlsx it's all ok but if try with extension xls I have error in this line:
result.Tables[0].TableName.ToString();
My code below, what's wrong?
code-behind
FileUploadControl.SaveAs(Server.MapPath("/public/") + filename);
System.IO.FileStream stream = File.Open(filePath, FileMode.Open, FileAccess.Read);
Excel.IExcelDataReader excelReader = Excel.ExcelReaderFactory.CreateOpenXmlReader(stream);
DataSet result = excelReader.AsDataSet();
excelReader.Close();
result.Tables[0].TableName.ToString();
string csvData = "";
int row_no = 0;
int ind = 0;
while (row_no < result.Tables[ind].Rows.Count)
{
for (int i = 0; i < result.Tables[ind].Columns.Count; i++)
{
csvData += result.Tables[ind].Rows[row_no][i].ToString() + ",";
}
row_no++;
csvData += "\n";
}
keys = GetUniqueKey(8).ToUpper();
output = System.Web.HttpContext.Current.Server.MapPath("/public/target_" + keys.ToString() + ".csv");
StreamWriter csv = new StreamWriter(#output, false);
csv.Write(csvData);
csv.Close();
Excel can be of two types:
Binary - Excel 2003 and older - xls
Zip - based on Open Office XML standards - Excel 2007 onwards - xlsx
You should try to use following for older excel format files:
ExcelReaderFactory.CreateBinaryReader(stream);
Use any Xls to Xslx conversation tool. You can try Aspose libraries. I think it's licensed but you can try trail version.
You can do all other conversions as well using these libraries.
Here's how I do it - OLEDB - get the first sheet name, and remove all empty rows. Replace //whatever you need to do with your logic.
//Your Method signature
{
//create connection string
var connStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + path +
";Extended Properties='Excel 12.0;HDR=Yes;IMEX=1'";
//process
using (var conn = new OleDbConnection(connStr))
{
conn.Open();
//programatically get the first sheet, whatever it is named.
var sheetName = GetSheetNames(conn)[0].SheetNameOf;
var adapter = new OleDbDataAdapter(String.Format("SELECT * FROM [{0}]", sheetName), connStr);
var ds = new DataSet();
adapter.Fill(ds, "anyNameHere");
var data = ds.Tables["anyNameHere"];
//copy and remove blank lines
var resData = data.Clone();
var filteredData = data.Rows.Cast<DataRow>().Where(
row => !row.ItemArray.All(
field => field is DBNull ||
field == null ||
(String.IsNullOrEmpty(field.ToString().Trim())))
);
filteredData.CopyToDataTable(resData, LoadOption.OverwriteChanges);
var newData = resData.AsEnumerable();
//whatever you need to do
}
public List<SheetName> GetSheetNames(OleDbConnection conn)
{
if (conn.State != ConnectionState.Open)
{
conn.Open();
}
DataTable excelSchema = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
var sheetNames = (from DataRow row in excelSchema.Rows
where !row["TABLE_NAME"].ToString().Contains("FilterDatabase")
select new SheetName { SheetNameOf = row["TABLE_NAME"].ToString() }
).ToList();
conn.Close();
return sheetNames;
}
You can use Aspose.Cells to convert excel file like xls or xlsx into csv format with the following simple code.
string filePath = #"F:\Downloads\source.xlsx";
Workbook workbook = new Workbook(filePath);
workbook.Save("output.csv", SaveFormat.CSV);
Note: I am working as developer evangelist at Aspose.
I'm trying to copy data from excel to sql server but facing the following error.
The Microsoft Office Access database engine could not find the object 'sheet1$'. Make sure the object exists and that you spell its name and the path name correctly.
My code is:
protected void importdatafromexcel(string filepath)
{
string sqltable = "PFDummyExcel";
string exceldataquery = "select EmployeeId,EmployeeName,Amount from [Sheet1$]";
string excelconnectionstring = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + filepath + ";Extended Properties=Excel 12.0;Persist Security Info=False";
string sqlconnectionstring = System.Configuration.ConfigurationManager.ConnectionStrings["HRGold"].ConnectionString;
SqlConnection con = new SqlConnection(sqlconnectionstring);
OleDbConnection oledb = new OleDbConnection(excelconnectionstring);
OleDbCommand oledbcmd = new OleDbCommand(exceldataquery, oledb);
oledb.Open();
OleDbDataReader dr = oledbcmd.ExecuteReader();
SqlBulkCopy bulkcopy = new SqlBulkCopy(sqlconnectionstring);
bulkcopy.DestinationTableName = sqltable;
while (dr.Read())
{
bulkcopy.WriteToServer(dr);
}
oledb.Close();
}
Please tell me how i solve this..
This error is raised because of you are trying to access sheet (which name is sheet1) in excel file. By default first sheet name is "sheet1" but user have either rename this name or delete this sheet.
To resolved this issue first of all you have to get all sheet name from excel file, then you have to pass this sheet name in your above code to import data.
string filePath = "your file path";
string excelconnectionstring = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + filepath + ";Extended Properties=Excel 12.0;Persist Security Info=False";
OleDbConnection Connection = new OleDbConnection(excelconnectionstring);
DataTable activityDataTable = Connection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
if(activityDataTable != null)
{
//validate worksheet name.
var itemsOfWorksheet = new List<SelectListItem>();
string worksheetName;
for (int cnt = 0; cnt < activityDataTable.Rows.Count; cnt++)
{
worksheetName = activityDataTable.Rows[cnt]["TABLE_NAME"].ToString();
if (worksheetName.Contains('\''))
{
worksheetName = worksheetName.Replace('\'', ' ').Trim();
}
if (worksheetName.Trim().EndsWith("$"))
itemsOfWorksheet.Add(new SelectListItem { Text = worksheetName.TrimEnd('$'), Value = worksheetName });
}
}
// itemsOfWorksheet : all worksheet name is added in this
so you can use itemsOfWorksheet[0] as sheet name in-place of "sheet1"
I had similar issue, I sorted it out by
Saving the excel file from fileuploader to a temporary folder inside website folder.
Using path to that file in my connection string
Rest all was same and now the error: The Microsoft Office Access database engine could not find the object 'sheet1$' was gone.
Here's my situation. I'm designing a program that takes Excel files (which may be in csv, xls, or xlsx format) from a remote network drive, processes the data, then outputs and stores the results of that process. The program provides a listbox of filenames that are obtained from the remote network drive folder using the method detailed in the accepted answer here. Once the user selects a filename from the listbox, I want the program to find the file and obtain the information from it to do the data processing. I have tried using this method to read the data from the Excel file while in a threaded security context, but that method just fails without giving any kind of error. It seems to not terminate. Am I going about this the wrong way?
Edit - (Final Notes: I have taken out the OleDbDataAdapter and replaced it with EPPlus handling.)
I was able to scrub sensitive data from the code, so here it is:
protected void GetFile(object principalObj)
{
if (principalObj == null)
{
throw new ArgumentNullException("principalObj");
}
IPrincipal principal = (IPrincipal)principalObj;
Thread.CurrentPrincipal = principal;
WindowsIdentity identity = principal.Identity as WindowsIdentity;
WindowsImpersonationContext impersonationContext = null;
if (identity != null)
{
impersonationContext = identity.Impersonate();
}
try
{
string fileName = string.Format("{0}\\" + Files.SelectedValue, #"RemoteDirectoryHere");
string connectionString = string.Format("Provider=Microsoft.ACE.OLEDB.14.0; data source={0}; Extended Properties=Excel 14.0;", fileName);
OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * FROM Sheet1", connectionString);
DataSet ds = new DataSet();
adapter.Fill(ds, "Sheet1");
dataTable = ds.Tables["Sheet1"];
}
finally
{
if (impersonationContext != null)
{
impersonationContext.Undo();
}
}
}
Additional Edit
Now xlsx files have been added to the mix.
Third Party
Third party solutions are not acceptable in this case (unless they allow unrestricted commercial use).
Attempts - (Final Notes: Ultimately I had to abandon OleDb connections.)
I have tried all of the different connection strings offered, and I have tried them with just one file type at a time. None of the connection strings worked with any of the file types.
Permissions
The User does have access to the file and its directory.
Your connection string might be the issue here. As far as I know, there isn't 1 that can read all xls, csv, and xlsx. I think you're using the XLSX connection string.
When I read xls, i use the following connection string:
#"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + sFilePath + ";Extended Properties='Excel 8.0;HDR=YES;IMEX=1;'"
Having said that, I recommend using a 3rd party file reader/parser to read XLS and CSV since, from my experience, OleDbDataAdapter is wonky depending on the types of data that's being read (and how mixed they are within each column).
For XLS, try NPOI https://code.google.com/p/npoi/
For CSV, try http://www.codeproject.com/Articles/9258/A-Fast-CSV-Reader
For XLSX, try EPPlus http://epplus.codeplex.com/
I've had great success with the above libraries.
Is it really important that you use an OleDb interface for this? I've always done it with Microsoft.Office.Excel.Interop, to wit:
using System;
using Microsoft.Office.Interop.Excel;
namespace StackOverflowExample
{
class Program
{
static void Main(string[] args)
{
var app = new Application();
var wkbk = app.Workbooks.Open(#"c:\data\foo.xls") as Workbook;
var wksht = wkbk.Sheets[1] as Worksheet; // not zero-based!
for (int row = 1; row <= 100; row++) // not zero-based!
{
Console.WriteLine("This is row #" + row.ToString());
for (int col = 1; col <= 100; col++)
{
Console.WriteLine("This is col #" + col.ToString());
var cell = wksht.Cells[row][col] as Range;
if (cell != null)
{
object val = cell.Value;
if (val != null)
{
Console.WriteLine("The value of the cell is " + val.ToString());
}
}
}
}
}
}
}
As you will be dealing with xlsx extension, you should rather opt for the new connection string.
public static string getConnectionString(string fileName, bool HDRValue, bool WriteExcel)
{
string hdrValue = HDRValue ? "YES" : "NO";
string writeExcel = WriteExcel ? string.Empty : "IMEX=1";
return "Provider=Microsoft.ACE.OLEDB.12.0;" + "Data Source=" + fileName + ";" + "Extended Properties=\"Excel 12.0 xml;HDR=" + hdrValue + ";" + writeExcel + "\"";
}
Above is the code for getting the connection string. First argument expects the actual path for file location. Second argument will decide whether to consider first row values as column headers or not. Third argument helps decide whether you want to open the connection to create and write the data or simply read the data. To read the data set it to "FALSE"
public static ReadData(string filePath, string sheetName, List<string> fieldsToRead, int startPoint, int endPoint)
{
DataTable dt = new DataTable();
try
{
string ConnectionString = ProcessFile.getConnectionString(filePath, false, false);
using (OleDbConnection cn = new OleDbConnection(ConnectionString))
{
cn.Open();
DataTable dbSchema = cn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
if (dbSchema == null || dbSchema.Rows.Count < 1)
{
throw new Exception("Error: Could not determine the name of the first worksheet.");
}
StringBuilder sb = new StringBuilder();
sb.Append("SELECT *");
sb.Append(" FROM [" + sheetName + fieldsToRead[0].ToUpper() + startPoint + ":" + fieldsToRead[1].ToUpper() + endPoint + "] ");
OleDbDataAdapter da = new OleDbDataAdapter(sb.ToString(), cn);
dt = new DataTable(sheetName);
da.Fill(dt);
if (dt.Rows.Count > 0)
{
foreach (DataRow row in dt.Rows)
{
string i = row[0].ToString();
}
}
cn.Dispose();
return fileDatas;
}
}
catch (Exception)
{
}
}
This is for reading 2007 Excel into dataset
DataSet ds = new DataSet();
try
{
string myConnStr = "";
myConnStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=MyDataSource;Extended Properties=\"Excel 12.0;HDR=YES\"";
OleDbConnection myConn = new OleDbConnection(myConnStr);
OleDbCommand cmd = new OleDbCommand("select * from [Sheet1$] ", myConn);
OleDbDataAdapter adapter = new OleDbDataAdapter();
adapter.SelectCommand = cmd;
myConn.Open();
adapter.Fill(ds);
myConn.Close();
}
catch
{ }
return ds;