When I tried to select all data from excel using OLEDB.I get an error of
Syntax error (missing operator) in query expression 'Created By'
Is this because of that space in the column name?
The query is:
SELECT Code,Name,Created By,Date FROM [Template$]
public DataTable GetExcelDataToTable(string filename, string dataExchangeSelectedColum)
{
//List<DataExchangeDefinition> dataExchange = new List<DataExchangeDefinition>();
string extension = Path.GetExtension(filename);
string connstring = string.Empty;
DataTable ExcelData = null;
try
{
switch (extension)
{
case ".xls":
connstring = string.Format(ConfigurationManager.ConnectionStrings["Excel03ConString"].ConnectionString, filename);
break;
case ".xlsx":
connstring = string.Format(ConfigurationManager.ConnectionStrings["Excel07+ConString"].ConnectionString, filename);
break;
}
using (OleDbConnection connExcel = new OleDbConnection(connstring))
{
using (OleDbCommand cmd = new OleDbCommand())
{
cmd.Connection = connExcel;
connExcel.Open();
var dtExcelSchema = connExcel.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
connExcel.Close();
var firstSheet = dtExcelSchema.Rows[0]["TABLE_NAME"].ToString();
cmd.CommandText = "SELECT " + dataExchangeSelectedColum + " FROM [" + firstSheet + "]";
ExcelData = new DataTable();
OleDbDataAdapter oda = new OleDbDataAdapter();
oda.SelectCommand = cmd;
oda.Fill(ExcelData);
}
}
}
catch (Exception ex)
{
throw ex;
}
return ExcelData;
}
This is the code I tried, here dataExchangeSelectedColum contains the columns they are "Code, Name, Created By, Date"
You need to add square brackets around the column name if it contains spaces:
cmd.CommandText = $"SELECT [{dataExchangeSelectedColum}] FROM [{firstSheet}]";
EDIT after your comment:
If you want to select several columns which name may contain spaces:
public DataTable GetExcelDataToTable(string filename, IEnumerable<string> columns)
{
...
string formattedColumns = string.Join("," columns.Select(column => $"[{column}]"));
cmd.CommandText = $"SELECT {formattedColumns} FROM [{firstSheet}]";
...
}
which can be invoked the following way:
DataTable table = GetExcelDataToTable(fileName,
new string[] { "Code", "Name", "Created By", "Date" });
I have done it like this
List<string> selecttedColsList = dataExchangeSelectedColum.Split(',').ToList();
string formattedColumns = "";
//string comma = "";
for (int i = 0; i < selecttedColsList.Count; i++)
{
//formattedColumns = string.Join(",", selecttedColsList.Select(col => $"[" + selecttedColsList[i] + "]"));
formattedColumns+= ""+$"[" + selecttedColsList[i] + "]";
if (i != selecttedColsList.Count - 1)
{
formattedColumns += ",";
}
}
Related
I have a page where the user the can upload a csv file, this will then be saved in the database and displayed in in a gridview. This all works fine when developing the site, but when I publish the site to IIS and access it externally it gives and error of "500 internal server error" When trying to uplaod the file
This is the code I am using to upload the files:
private string GetConnectionString()
{
return ConfigurationManager.ConnectionStrings["OfficeConnection"].ConnectionString;
}
private void CreateDatabaseTable(DataTable dt, string tableName)
{
string sqlQuery = string.Empty;
string sqlDBType = string.Empty;
string dataType = string.Empty;
StringBuilder sb = new StringBuilder();
sb.AppendFormat(string.Format("CREATE TABLE {0} (", tableName));
for (int i = 0; i < dt.Columns.Count; i++)
{
int maxLength = 0;
dataType = dt.Columns[i].DataType.ToString();
if (dataType == "System.Int32")
{
sqlDBType = "INT";
}
else if (dataType == "System.String")
{
sqlDBType = "NVARCHAR";
maxLength = dt.Columns[i].MaxLength;
}
else
{
//do something else
}
if (maxLength > 0)
sb.AppendFormat(string.Format("{0} {1} ({2}), ", dt.Columns[i].ColumnName, sqlDBType, maxLength));
else
sb.AppendFormat(string.Format("{0} {1},", dt.Columns[i].ColumnName, sqlDBType));
}
sqlQuery = sb.ToString();
sqlQuery = sqlQuery.Trim().TrimEnd(',');
sqlQuery = sqlQuery + " )";
using (SqlConnection sqlConn = new SqlConnection(GetConnectionString()))
{
sqlConn.Open();
using (SqlCommand sqlCmd = new SqlCommand(sqlQuery, sqlConn))
{
sqlCmd.ExecuteNonQuery();
sqlConn.Close();
}
}
}
private void LoadDataToDatabase(string tableName, string fileFullPath, string delimeter)
{
string sqlQuery = string.Empty;
StringBuilder sb = new StringBuilder();
sb.AppendFormat(string.Format("BULK INSERT {0} ", tableName));
sb.AppendFormat(string.Format(" FROM '{0}'", fileFullPath));
sb.AppendFormat(string.Format(" WITH ( FIELDTERMINATOR = '{0}' , ROWTERMINATOR = '\n' )", delimeter));
sqlQuery = sb.ToString();
using (SqlConnection sqlConn = new SqlConnection(GetConnectionString()))
{
sqlConn.Open();
using (SqlCommand sqlCmd = new SqlCommand(sqlQuery, sqlConn))
{
sqlCmd.ExecuteNonQuery();
sqlConn.Close();
}
}
}
private void UploadAndProcessFile()
{
if (FileUpload1.HasFile)
{
FileInfo fileInfo = new FileInfo(FileUpload1.PostedFile.FileName);
if (fileInfo.Name.Contains(".csv"))
{
string fileName = fileInfo.Name.Replace(".csv", "").ToString();
string csvFilePath = Server.MapPath("UploadedCSVFiles") + "\\" + fileInfo.Name;
//Save the CSV file in the Server inside 'UploadedCSVFiles'
FileUpload1.SaveAs(csvFilePath);
//Fetch the location of CSV file
string filePath = Server.MapPath("UploadedCSVFiles") + "\\";
string strSql = string.Format("SELECT * FROM [{0}]", fileInfo.Name);
string strCSVConnString = string.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties='text;HDR=YES;'", filePath);
// load the data from CSV to DataTable
DataTable dtCSV = new DataTable();
DataTable dtSchema = new DataTable();
using (OleDbDataAdapter adapter = new OleDbDataAdapter(strSql, strCSVConnString))
{
adapter.FillSchema(dtCSV, SchemaType.Mapped);
adapter.Fill(dtCSV);
}
if (dtCSV.Rows.Count > 0)
{
CreateDatabaseTable(dtCSV, fileName);
Label2.Text = string.Format("The table ({0}) has been successfully created to the database.", fileName);
string fileFullPath = filePath + fileInfo.Name;
LoadDataToDatabase(fileName, fileFullPath, ",");
Label1.Text = string.Format("({0}) records has been loaded to the table {1}.", dtCSV.Rows.Count, fileName);
}
else
{
lblError.Text = "File is empty.";
}
}
else
{
lblError.Text = "Unable to recognize file.";
}
}
}
protected void btnImport_Click(object sender, EventArgs e)
{
UploadAndProcessFile();
}
Is this a setting in IIS I need to change? I have checked the permission on the site and all is fine.
Thanks
I made a program to open Excel file.
There are exist data page and blank page.
Can I add only the pages where the data exists in the combo box?
Can I use ButtonEvent to view only pages that contain data?
string filePath = openFileDialog1.FileName;//파일 경로 가져오기
string filename = openFileDialog1.SafeFileName;//파일 이름만 가져오기
string fileExtension = Path.GetExtension(filePath);
//string connectionString = string.Empty;
string sheetName = string.Empty;
using (OleDbConnection con = new OleDbConnection(ConnectStr()))
{
using (OleDbCommand cmd = new OleDbCommand())
{
using (OleDbDataAdapter oda = new OleDbDataAdapter())
{
DataTable dt = new DataTable();
cmd.CommandText = "SELECT * From [" + sheetName + "]";
cmd.Connection = con;
con.Open();
oda.SelectCommand = cmd;
oda.Fill(dt);
con.Close();
dataGridView1.DataSource = dt;
}
}
}
public string ConnectStr()
{
string filePath = openFileDialog1.FileName;
string filename = openFileDialog1.SafeFileName;//파일 이름만 가져오기
string fileExtension = Path.GetExtension(filePath);
string connectionString = string.Empty;
string sheetName = string.Empty;
switch (fileExtension)
{
case ".xls": //Excel 97-03버전
connectionString = string.Format(Excel03ConString, filePath);
break;
case ".xlsx": //Excel 07이상 버전
connectionString = string.Format(Excel16ConString, filePath);
break;
}
return connectionString;
}
I don't really get what is this. But I beg you need to show only specific sheet from spreadsheet correct me if i'm wrong.
There is a SQL commend that we can query from the specific sheet.
try
{
this.txtImportFilePath.Text = opd.FileName;
OleDbConnection con = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;data source=" + this.txtImportFilePath.Text + ";Extended Properties=Excel 8.0;");
StringBuilder stbQuery = new StringBuilder();
stbQuery.Append("Select * From [Sheet1$]");
OleDbDataAdapter adp = new OleDbDataAdapter(stbQuery.ToString(), con);
DataSet dsXLS = new DataSet();
adp.Fill(dsXLS);
DataView dvEmp = new DataView(dsXLS.Tables[0]);
trnxlistDataview.DataSource = dvEmp;
}
catch (Exception ex)
{
MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
}
I'm converting .csv file to datatable like below.
string header = isFirstRowHeader ? "Yes" : "No";
string itinerarycsvfilePath = Path.GetDirectoryName(#"D:\projects\MSC cruise\MSCCruiseProjects\MsccruiseWithLogin\MsccruiseWithLogin\UnzippedFiles\itinff_gbr_eng.csv");
string filename = Path.GetFileName(#"D:\projects\MSC cruise\MSCCruiseProjects\MsccruiseWithLogin\MsccruiseWithLogin\UnzippedFiles\itinff_gbr_eng.csv");
string sql = #"SELECT * FROM [" + filename + "]";
using (OleDbConnection connection = new OleDbConnection(#"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + itinerarycsvfilePath +
";Extended Properties=\"Text;HDR=" + header + "\""))
using (OleDbCommand command = new OleDbCommand(sql, connection))
using (OleDbDataAdapter adapter = new OleDbDataAdapter(command))
{
DataTable dataTable = new DataTable("ItineraryDetails");
dataTable.Locale = CultureInfo.CurrentCulture;
adapter.Fill(dataTable);
return dataTable;
}
then the result when I look with quick watch
Am I doing something wrong.I feel like that because table does not show like columns.
what can I do for that.
hope your help.
See code below
public class CSVReader
{
public DataSet ReadCSVFile(string fullPath, bool headerRow)
{
string path = fullPath.Substring(0, fullPath.LastIndexOf("\\") + 1);
string filename = fullPath.Substring(fullPath.LastIndexOf("\\") + 1);
DataSet ds = new DataSet();
try
{
if (File.Exists(fullPath))
{
string ConStr = string.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0}" + ";Extended Properties=\"Text;HDR={1};FMT=Delimited\\\"", path, headerRow ? "Yes" : "No");
string SQL = string.Format("SELECT * FROM {0}", filename);
OleDbDataAdapter adapter = new OleDbDataAdapter(SQL, ConStr);
adapter.Fill(ds, "TextFile");
ds.Tables[0].TableName = "Table1";
}
foreach (DataColumn col in ds.Tables["Table1"].Columns)
{
col.ColumnName = col.ColumnName.Replace(" ", "_");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return ds;
}
}
Am trying to read a csv file using oledb command. Following is am using.
This code execute smoothly. But i need to remove first row from csv file and set second row as column header of the datatable. Is it possible?
static DataTable ImportCsvFileToDataTable(string filename, string fullPath)
{
FileInfo file = new FileInfo(fullPath);
using (OleDbConnection con =
new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=\"" +
file.DirectoryName + "\";Extended Properties='text;HDR=Yes;FMT=Delimited(,)';"))
{
using (OleDbCommand cmd = new OleDbCommand(string.Format
("SELECT * FROM [{0}]", file.Name), con))
{
con.Open();
// Using a DataTable to process the data
using (OleDbDataAdapter adp = new OleDbDataAdapter(cmd))
{
DataTable tbl = new DataTable(filename);
adp.Fill(tbl);
return tbl;
}
}
}
}
I shed much blood trying to develop the perfect method to import CSV's into DataTable. Here's the result. It parses first row as column headers. This method works with Ace OleDB 12, but should with no problem work with Jet OleDB 4 as well.
public static DataTable FromCSV(string FilePath, char Delimiter = ',')
{
DataTable dt = new DataTable();
Dictionary<string, string> props = new Dictionary<string, string>();
if (!File.Exists(FilePath))
return null;
if (FilePath.EndsWith(".csv", StringComparison.OrdinalIgnoreCase))
{
props["Provider"] = "Microsoft.Ace.OLEDB.12.0";
props["Extended Properties"] = "\"Text;FMT=Delimited\"";
props["Data Source"] = Path.GetDirectoryName(FilePath);
}
else
return null;
StringBuilder sb = new StringBuilder();
foreach (KeyValuePair<string, string> prop in props)
{
sb.Append(prop.Key);
sb.Append('=');
sb.Append(prop.Value);
sb.Append(';');
}
string connectionString = sb.ToString();
File.Delete(Path.GetDirectoryName(FilePath) + "/schema.ini");
using (StreamWriter sw = new StreamWriter(Path.GetDirectoryName(FilePath) + "/schema.ini", false))
{
sw.WriteLine("[" + Path.GetFileName(FilePath) + "]");
sw.WriteLine("Format=Delimited(" + Delimiter + ")");
sw.WriteLine("DecimalSymbol=.");
sw.WriteLine("ColNameHeader=True");
sw.WriteLine("MaxScanRows=1");
sw.Close();
sw.Dispose();
}
using (OleDbConnection conn = new OleDbConnection(connectionString))
{
conn.Open();
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = conn;
cmd.CommandText = "SELECT * FROM [" + Path.GetFileName(FilePath) + "] WHERE 1=0";
OleDbDataAdapter da = new OleDbDataAdapter(cmd);
da.Fill(dt);
using (StreamWriter sw = new StreamWriter(Path.GetDirectoryName(FilePath) + "/schema.ini", true))
{
for (int i = 0; i < dt.Columns.Count; i++)
{
string NewColumnName = dt.Columns[i].ColumnName.Replace(#"""", #"""""");
int ColumnNamePosition = NewColumnName.LastIndexOf("#csv.", StringComparison.OrdinalIgnoreCase);
if (ColumnNamePosition != -1)
NewColumnName = NewColumnName.Substring(ColumnNamePosition + "#csv.".Length);
if (NewColumnName.StartsWith("NoName"))
NewColumnName = "F" + (i + 1).ToString();
sw.WriteLine("col" + (i + 1).ToString() + "=" + NewColumnName + " Text");
}
sw.Close();
sw.Dispose();
}
dt.Columns.Clear();
cmd.CommandText = "SELECT * FROM [" + Path.GetFileName(FilePath) + "]";
da = new OleDbDataAdapter(cmd);
da.Fill(dt);
cmd = null;
conn.Close();
}
File.Delete(Path.GetDirectoryName(FilePath) + "/schema.ini");
return dt;
}
Perhaps something like this:
tbl.Rows[0].Delete();
DataRow r = tbl.Rows[0];
foreach(DataColumn c in tbl.Columns)
{
tbl.Columns[c.ColumnName].ColumnName = r[c.ColumnName].ToString();
}
tbl.Rows[0].Delete();
There is no built-in way to tell OLEDB to use the second row for the headers instead of the first row.
You will have to open the CSV file, remote the first row, and save it again. Fortunately, this is fairly easy to do:
var lines = File.ReadAllLines(oldFileName);
File.WriteAllLines(newFileName, lines.Skip(1));
(Add .ToArray() after Skip(1) if you are using a .NET version < 4.)
I want to import an Excel file to a Access table.
I have a code that works well the first time. It is making a loop through all the sheets of the excel file, and it inserts the records.
At the second time, I get an exception:
"The table already exists"
I know that the table already exists in the Access file! I want to insert more records on it! I don't want to drop it!
Anyone knows how to solve this?
Here it is the code:
class Program
{
static void Main(string[] args)
{
string ExcelFiles = System.Configuration.ConfigurationSettings.AppSettings["FilesLocation"];
string AccessFile = System.Configuration.ConfigurationSettings.AppSettings["AccessFileLocation"];
string[] files = Directory.GetFiles(ExcelFiles, "*.xlsx");
foreach (string excelFile in files)
{
string[] sheets = ListSheetInExcel(excelFile).ToArray();
foreach (string sheetName in sheets)
{
ImportSpreadsheet(
excelFile,
sheetName.Replace("'", ""),
"MyTable",
AccessFile);
}
}
}
public static void ImportSpreadsheet(string ExcelfileName, string ExcelsheetName, string AccesstableName, string AccessDatabase)
{
OleDbConnectionStringBuilder sbConnection = new OleDbConnectionStringBuilder();
String strExtendedProperties = String.Empty;
sbConnection.DataSource = ExcelfileName;
if (Path.GetExtension(ExcelfileName).Equals(".xls"))//for 97-03 Excel file
{
sbConnection.Provider = "Microsoft.Jet.OLEDB.4.0";
strExtendedProperties = "Excel 8.0;HDR=Yes;IMEX=1";//HDR=ColumnHeader,IMEX=InterMixed
}
else if (Path.GetExtension(ExcelfileName).Equals(".xlsx")) //for 2007 Excel file
{
sbConnection.Provider = "Microsoft.ACE.OLEDB.12.0";
strExtendedProperties = "Excel 12.0;HDR=Yes;IMEX=1";
}
sbConnection.Add("Extended Properties", strExtendedProperties);
using (OleDbConnection conn = new OleDbConnection(sbConnection.ToString()))
{
try
{
conn.Open();
using (OleDbCommand cmd = new OleDbCommand())
{
cmd.CommandText = #"SELECT * INTO [MS Access;Database="
+ AccessDatabase + "].["
+ AccesstableName + "] FROM ["
+ ExcelsheetName + "]";
cmd.CommandType = CommandType.Text;
cmd.Connection = conn;
cmd.ExecuteNonQuery(); //THE ERROR OCCURS HERE !!!!!!!!
}
}
catch (DbException ex)
{
Console.WriteLine("Exception: {0}\r\n Stack Trace: {1}", ex.Message, ex.StackTrace);
}
finally
{
conn.Close();
}
}
}
public static List<string> ListSheetInExcel(string filePath)
{
OleDbConnectionStringBuilder sbConnection = new OleDbConnectionStringBuilder();
String strExtendedProperties = String.Empty;
sbConnection.DataSource = filePath;
if (Path.GetExtension(filePath).Equals(".xls"))//for 97-03 Excel file
{
sbConnection.Provider = "Microsoft.Jet.OLEDB.4.0";
strExtendedProperties = "Excel 8.0;HDR=Yes;IMEX=1";//HDR=ColumnHeader,IMEX=InterMixed
}
else if (Path.GetExtension(filePath).Equals(".xlsx")) //for 2007 Excel file
{
sbConnection.Provider = "Microsoft.ACE.OLEDB.12.0";
strExtendedProperties = "Excel 12.0;HDR=Yes;IMEX=1";
}
sbConnection.Add("Extended Properties", strExtendedProperties);
List<string> listSheet = new List<string>();
using (OleDbConnection conn = new OleDbConnection(sbConnection.ToString()))
{
conn.Open();
DataTable dtSheet = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
foreach (DataRow drSheet in dtSheet.Rows)
{
if (drSheet["TABLE_NAME"].ToString().Contains("$"))//checks whether row contains '_xlnm#_FilterDatabase' or sheet name(i.e. sheet name always ends with $ sign)
{
listSheet.Add(drSheet["TABLE_NAME"].ToString());
}
}
}
return listSheet;
}
}
I have found the solution.
The command "INSERT INTO" needs to create a new table.
The solution is to build a command without that need:
cmd.CommandText = #"INSERT INTO [MS Access;Database="
+ AccessDatabase + "].["
+ AccesstableName + "] SELECT * FROM ["
+ ExcelsheetName + "]";