How to handle special characters in DataTable.Select("")? - c#

I'm retrieving data from excel and one of the column in excel has '#' like "POLICY #" is the name of the column in excel.
Here is my code
string _policyNoColumn = dtFile.Columns[1].ToString();
string _policyNoRow = string.Empty;
foreach (DataRow _rows in dtFile.Rows)
{
_policyNoRow = _rows[1].ToString();
DataRow[] _rowInFile = dtFile.Select(_policyNoColumn + " = '" + _policyNoRow + "'"); //Check on Excel
if (_rowInFile.Count() == 2)
{
_lstInValid.Add(_policyNoRow); //Invalid
}
}
The value of the _policyNoColumn is "POLICY #". and this what i'm getting.
The expression contains invalid date constant '# = 'V0263680''.
And Here is the source error
Line 501: {
Line 502: _policyNoRow = _rows[1].ToString();
Line 503: DataRow[] _rowInFile = dtFile.Select(_policyNoColumn + " = '" + _policyNoRow + "'"); //Check on Excel
Line 504: if (_rowInFile.Count() == 2)
Line 505: {
Highlighted part is Line 503.

I got the answer
Here what i Did
string _policyNoColumn = "[" + dtFile.Columns[1].ToString() + "]";

Related

Error: System.Data.OleDb.OleDbException (0x80040E14): Syntax error (missing operator) in query expression

I'm trying to export the results of a stored procedure to Excel and receiving the following error when running: System.Data.OleDb.OleDbException (0x80040E14): Syntax error (missing operator) in query expression. Below is the code I am using. The excel file gets created but there is no data populating the file.
string TableColumns = "";
// Get the Column List from Data Table so can create Excel Sheet with Header
foreach (DataTable table in ds.Tables)
{
foreach (DataColumn column in table.Columns)
{
TableColumns += column + "],[";
}
}
// Replace most right comma from Columnlist
TableColumns = ("[" + TableColumns.Replace(",", " Text,").TrimEnd(','));
TableColumns = TableColumns.Remove(TableColumns.Length - 2);
//Use OLE DB Connection and Create Excel Sheet
Excel_OLE_Con.ConnectionString = connstring;
Excel_OLE_Con.Open();
Excel_OLE_Cmd.Connection = Excel_OLE_Con;
Excel_OLE_Cmd.CommandText = "Create table " + SheetName + " (" + TableColumns + ")";
Excel_OLE_Cmd.ExecuteNonQuery();
//Write Data to Excel Sheet from DataTable dynamically
foreach (DataTable table in ds.Tables)
{
String sqlCommandInsert = "";
String sqlCommandValue = "";
foreach (DataColumn dataColumn in table.Columns)
{
sqlCommandValue += dataColumn + "],[";
}
sqlCommandValue = "[" + sqlCommandValue.TrimEnd(',');
sqlCommandValue = sqlCommandValue.Remove(sqlCommandValue.Length - 2);
sqlCommandInsert = "INSERT into " + SheetName + "(" + sqlCommandValue + ") VALUES(";
int columnCount = table.Columns.Count;
foreach (DataRow row in table.Rows)
{
string columnvalues = "";
for (int i = 0; i < columnCount; i++)
{
int index = table.Rows.IndexOf(row);
columnvalues += "'" + table.Rows[index].ItemArray[i] + "',";
}
columnvalues = columnvalues.TrimEnd(',');
var command = sqlCommandInsert + columnvalues + ")";
Excel_OLE_Cmd.CommandText = command;
Excel_OLE_Cmd.ExecuteNonQuery();
}
}
Excel_OLE_Con.Close();
Dts.TaskResult = (int)ScriptResults.Success;
So the issue is related to you have an unescaped single quote in your data. Two options for dealing with that are to escape the single quote (turn it into two single quotes):
string myData = "This string won't work";
string myDataEscaped = myData.Replace("'", "''");
or the other option (and more robust) is to use a parameterized query. I will use just the lower part of your code where you are doing this query build up and insertion and show you how that can be done (along with some cleanup and making use of StringBuilder). Note I did not compile and test this as I don't have any test data to use.
var tableColumns = string.Join(",", columns.Cast<DataColumn>().Select(x => "[" + x.ColumnName + "]"));
var insertBase = $"INSERT into {SheetName} ({tableColumns}) VALUES(";
int columnCount = table.Columns.Count;
foreach (DataRow row in table.Rows)
{
Excel_OLE_Cmd.Parameters.Clear(); // Since you are reusing the command you have to clear the parameters
var command = new StringBuilder(insertBase);
var index = table.Rows.IndexOf(row);
// I will assume you always have at least one column, otherwise these lines would fail
// Add the first row before the loop that way we don't have to delete the end comma
var param = $"#param_{index}_0";
command.Append(param);
Excel_OLE_Cmd.Parameters.AddWithValue(param, table.Rows[index].ItemArray[0]);
for (int i = 1; i < columnCount; ++i)
{
param = $"#param_{index}_{i}"
command.Append("," + param);
Excel_OLE_Cmd.Parameters.AddWithValue(param, table.Rows[index].ItemArray[i]);
}
command.Append(")");
Excel_OLE_Cmd.CommandText = command.ToString();
Excel_OLE_Cmd.ExecuteNonQuery();
}

Writing data to SQL and dumping it into Excel

My C# application is significantly slower than I would like. The program accesses an Excel sheet and loops through each row on a sheet / does the following:
Collects variables from that row
Creates an SQL query based off those variables
Executes that query
then a reader goes out and puts it in its proper column on that same row.
*Note, each row has 6 different SQL queries/ final numbers that are calculated and input into the sheet, the code below is just showing the first 2 for brevity's sake. The sheet has around 300 rows, so the program is executing 300 * 6= 1,800 SQL queries each time its run. For each one of those 1,800 numbers, the program is accessing the sheet and inputting it into the sheet.
Instead of doing the excelWorksheet.get_Range and inputting the number into the Excel sheet for each number, one at a time, would it be faster to store each number into an array and then go back later and mass dump all of the numbers into the sheet, once all of the queries have been executed and the array is full?
using (SqlConnection conn = new SqlConnection())
{
conn.ConnectionString = "Data Source=WRDXPVSEPIRPT00;DATABASE=Epicor905;Workstation ID=SMEBPPL204TN;Trusted_Connection=true";
try
{
//initiate the connection
conn.Open();
}
catch(SqlException ex)
{
throw new ApplicationException(string.Format("You're not connected to the database, please close the program, re-connect to the network, and try again."), ex);
}
progressBar1.Value = 60;
statusLabel.Text = "Retrieving account balances from database...";
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//iterate through each row and pull information
for (int i = 2; i < lastUsedRow + 1; i++)
{
//string iString = Convert.ToString(i);
statusLabel.Text = "Retrieving balances for " + i + " of " + lastUsedRow + " accounts...";
//declare excel sheet range variables
var CompanyVar = excelWorksheet.get_Range("A" + i, "A" + i).Text;
var FiscalYear = excelWorksheet.get_Range("B" + i, "B" + i).Text;
var FiscalPeriod = excelWorksheet.get_Range("C" + i, "C" + i).Text;
var segValue1 = excelWorksheet.get_Range("F" + i, "F" + i).Text;
var segValue2 = excelWorksheet.get_Range("G" + i, "G" + i).Text;
var segValue3 = excelWorksheet.get_Range("H" + i, "H" + i).Text;
int FiscalYearHelper = Convert.ToInt32(FiscalYear);
var FiscalYearPYY = FiscalYearHelper - 1;
//begin filling in CY YTD column
string SQLCode = "SELECT SUM(DebitAmount-CreditAmount) as BalanceAmt FROM GLJrnDtl WITH (NOLOCK) WHERE" +
" FiscalPeriod between 1 AND " + FiscalPeriod + "AND Company =" + "'" + CompanyVar + "'" +
"AND FiscalYear =" + "'" + FiscalYear + "'" + "AND SegValue1 LIKE " + "'" + segValue1 + "'" +
"AND SegValue2 LIKE " + "'" + segValue2 + "'" + "AND SegValue3 LIKE " + "'" + segValue3 + "'";
SqlCommand command = new SqlCommand(SQLCode, conn);
// Create new SqlDataReader object and read data from the command.
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
string cyAct = reader["BalanceAmt"].ToString();
if (cyAct == "")
{
goto CYM;
//cyAct = "0.00";
}
var cyAct1 = (float)Convert.ToDouble(cyAct);
int one = Convert.ToInt32(excelWorksheet.get_Range("E" + i, "E" + i).Text);
double cyAct2 = (cyAct1 * one);
string cyAct3 = cyAct2.ToString("0.##");
excelWorksheet.get_Range("I" + i, "I" + i).Value = cyAct3;
}
}
//end filling in column
//begin filling in CY Month column
CYM:
string SQLCodeMonth = "SELECT SUM(DebitAmount-CreditAmount) as BalanceAmt FROM GLJrnDtl WITH (NOLOCK) WHERE" +
" FiscalPeriod = " + FiscalPeriod + "AND Company =" + "'" + CompanyVar + "'" +
"AND FiscalYear =" + "'" + FiscalYear + "'" + "AND SegValue1 LIKE " + "'" + segValue1 + "'" +
"AND SegValue2 LIKE " + "'" + segValue2 + "'" + "AND SegValue3 LIKE " + "'" + segValue3 + "'";
SqlCommand commandMonth = new SqlCommand(SQLCodeMonth, conn);
// Create new SqlDataReader object and read data from the command.
using (SqlDataReader reader = commandMonth.ExecuteReader())
{
while (reader.Read())
{
string cyAct = reader["BalanceAmt"].ToString();
if (cyAct == "")
{
goto APY;
//cyAct = "0.00";
}
var cyAct1 = (float)Convert.ToDouble(cyAct);
int one = Convert.ToInt32(excelWorksheet.get_Range("E" + i, "E" + i).Text);
double cyAct2 = (cyAct1 * one);
string cyAct3 = cyAct2.ToString("0.##");
excelWorksheet.get_Range("J" + i, "J" + i).Value = cyAct3;
}
}
//end filling in column
//begin filling in Act PY month column
THIS IS NOT A FULL ANSWER, there is not enough space to write this as a comment, do not mark this as an answer its a comment.
Please try to use objects (instances of classes or structs) it will make your programming more efficient and easy to maintain.
for example:
private void UseObjects()
{
List<ExcelObjects> ListOfvarsForQuery = new List<ExcelObjects>();
for (int i = 2; i < lastUsedRow + 1; i++)
{
ExcelObjects obj = new ExcelObjects();
obj.CompanyVar = ws.Cells[i, 1];
obj.FiscalYear = ws.Cells[i, 2];
obj.FiscalPeriod = ws.Cells[i, 3];
obj.segValue1 = ws.Cells[i, 4];
obj.segValue2 = ws.Cells[i, 5];
obj.segValue3 = ws.Cells[i, 6];
ListOfvarsForQuery.Add(obj);
}
string SQLCode = // use the list of ExcelObjects and write a better query.
}
}
struct ExcelObjects
{
public string CompanyVar;
public string FiscalYear;
public string FiscalPeriod;
public string segValue1;
public string segValue2;
public string segValue3;
}
Instead of looping through each row and running a SQL query for each row, I found that it is faster to outer join the table I speak of in my question with another SQL table that has the account balances on it. I'm doing all of it within memory because I've been coding for 3 weeks and I don't have time to learn how to create a temp table in SQL server yet.

make line break in string array output in c#

how to make line break between words in this following code ? i want to show each output have line break like this so that it can be seen properly. this is my code and output that i want :
try
{
//DataTable dtTemp = (DataTable)ViewState["Information"];
DataTable dtDistinctRecords = dtTemp.DefaultView.ToTable(true, "prod_line");
DataTable dtStudentName = dtTemp.DefaultView.ToTable(true, "request_date");
DataTable a = new DataTable();
DataTable dtStudent = new DataTable();
dtStudent.Columns.Add("request_date");
foreach (DataRow rows in dtDistinctRecords.Rows)
{
dtStudent.Columns.Add(rows["prod_line"].ToString());
}
foreach (DataRow row in dtStudentName.Rows)
{
DataRow dr = dtStudent.NewRow();
dr["request_date"] = row["request_date"];
DataView dv = new DataView(dtTemp);
dv.RowFilter = "request_date='" + row["request_date"] + "'";
DataTable dtStudentdtl = dv.ToTable();
for (int i = 0; i < dtStudentdtl.Rows.Count; i++)
{
string colValue = dtStudentdtl.Rows[i]["jo_no"].ToString();
string colValue2 = dtStudentdtl.Rows[i]["qty"].ToString();
string colValue3 = dtStudentdtl.Rows[i]["need_by_date"].ToString();
string colValue4 = dtStudentdtl.Rows[i]["process_id"].ToString();
dr[dtStudentdtl.Rows[i]["prod_line"].ToString()] = "Job Order: " + colValue + " Quantity: " + colValue2 + " Need by Date: " + colValue3 + " Status: " + colValue4;
var joinedWords = string.Join(" ", dtStudent);
}
dtStudent.Rows.InsertAt(dr, dtStudent.Rows.Count);
}
GridView1.CellPadding = 10;
GridView1.DataSource = dtStudent;
GridView1.DataBind();
GridView_Row_Merger(GridView1);
con.Close();
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
link output that i want
Here's the first result from google for you, adding line break,
or for short \r\n
I made some changes in your for loop to make a sample code snippet:
string colValue = "job order: 124"+System.Environment.NewLine+System.Environment.NewLine;
string colValue2 = "Quantity: 100" + System.Environment.NewLine + System.Environment.NewLine;
string colValue3 = "Need by Date:2/5/2017" + System.Environment.NewLine + System.Environment.NewLine;
string colValue4 = "Status: Pending"+System.Environment.NewLine;
string finalString = colValue + colValue2 + colValue3 + colValue4;
and in front end i am getting following output:
Hope it will work for you.

Datareader Exception Thrown Database - DateTime

In my Access database I have an AutditLog table which Looks like this
I simply want to access this table and display each bit of information when Created*(which is the date of the logs) is equal to today's date.
this is my code
private void ITemail()
{
string FinEmail;
clsDBConnector dbConnector = new clsDBConnector();
OleDbDataReader dr;
dbConnector.Connect();
var sqlStr = " SELECT Created, [Action], ConnectionLoc, ConnectionSystem, Resource, [Text], RecordId, ToVal, ClientName"
+ "FROM tblAudit WHERE (ClientName = '" + Client + "') AND 'Created' = '" + ToDate() + "'";
dr = dbConnector.DoSQL(sqlStr);
while (dr.Read())
{
txtIT.Text = dr[0].ToString() + dr[1].ToString() + dr[2].ToString() + dr[3].ToString() + dr[4].ToString() + dr[5].ToString() + dr[6].ToString()
+ dr[7].ToString() + dr[8].ToString();
}
}
private string ToDate()
{
return DateTime.Today.ToString("dd/MM/yyyy");
}
the problem is that nothing is returned even when i try in server explorer with the correct date as a string nothing is returned. When it reaches the While loop this exception is thrown:
Any help would be very much appreciated
Your date format and the date delimiter is incorrect and spaces are missing:
private void ITemail()
{
string FinEmail;
clsDBConnector dbConnector = new clsDBConnector();
OleDbDataReader dr;
dbConnector.Connect();
var sqlStr = "SELECT Created, [Action], ConnectionLoc, ConnectionSystem, Resource, [Text], RecordId, ToVal, ClientName "
+ "FROM tblAudit WHERE (ClientName = '" + Client + "') AND Created = #" + ToDate() + "#";
dr = dbConnector.DoSQL(sqlStr);
while (dr.Read())
{
txtIT.Text = dr[0].ToString() + dr[1].ToString() + dr[2].ToString() + dr[3].ToString() + dr[4].ToString() + dr[5].ToString() + dr[6].ToString()
+ dr[7].ToString() + dr[8].ToString();
}
}
private string ToDate()
{
return DateTime.Today.ToString("yyyy'/'MM'/'dd");
}

Update Statement Updates 0 Rows via the C# Winform Application?

First of all, please help me out! I can not take this anymore. I could not find where the error is located. Here is my problem:
I'm trying to update a row via c# winform application. The update query generated from the application is formatted correctly. I tested it in the sql server environment, it worked well. When i run it from the application i get 0 rows updated.
Here is the snippet that generates the update statement using reflection - don't try to figure it out. Carry on reading after the code portion:
public void Update(int cusID)
{
SqlCommand objSqlCommand = new SqlCommand();
Customer cust = new Customer();
string SQL = null;
try
{
if ((cusID != 0))
{
foreach (PropertyInfo PropertyItem in this.GetType().GetProperties())
{
if (!(PropertyItem.Name.ToString() == cust.PKName))
{
if (PropertyItem.Name.ToString() != "TableName")
{
if (SQL == null)
{
SQL = PropertyItem.Name.ToString() + " = #" + PropertyItem.Name.ToString();
}
else
{
SQL = SQL + ", " + PropertyItem.Name.ToString() + " = #" + PropertyItem.Name.ToString();
}
}
else
{
break;
}
}
}
objSqlCommand.CommandText = "UPDATE " + this.TableName + " SET " + SQL + " WHERE " + cust.PKName + " = #cusID AND PhoneNumber = " + "'" + "#phNum" + "'";
foreach (PropertyInfo PropertyItem in this.GetType().GetProperties())
{
if (!(PropertyItem.Name.ToString() == cust.PKName))
{
if (PropertyItem.Name.ToString() != "TableName")
{
objSqlCommand.Parameters.AddWithValue("#" + PropertyItem.Name.ToString(), PropertyItem.GetValue(this, null));
}
else
{
break;
}
}
}
objSqlCommand.Parameters.AddWithValue("#cusID", cusID);
objSqlCommand.Parameters.AddWithValue("#phNum", this.PhoneNumber);
DAL.ExecuteSQL(objSqlCommand);
}
else
{
//AppEventLog.AddWarning("Primary Key is not provided for Update.")
}
}
catch (Exception ex)
{
//AppEventLog.AddError(ex.Message.ToString)
}
}
This part below:
objSqlCommand.CommandText = "UPDATE " + this.TableName + " SET " + SQL + " WHERE " + cust.PKName + " = #cusID AND PhoneNumber = " + "'" + "#phNum" + "'";
generates dml:
UPDATE CustomerPhone SET PhoneTypeID = #PhoneTypeID, PhoneNumber = #PhoneNumber WHERE CustomerID = #cusID AND PhoneNumber = '#phNum'
#PhoneTypeID and #PhoneNumber are gotten from two properties. We assigned the value to these properties in the presentation layer from the user input text box. The portion below where fetches the values:
objSqlCommand.Parameters.AddWithValue("#" + PropertyItem.Name.ToString(), PropertyItem.GetValue(this, null));
The code below fills the values of WHERE:
objSqlCommand.Parameters.AddWithValue("#cusID", cusID);
objSqlCommand.Parameters.AddWithValue("#phNum", this.PhoneNumber);
The final code should look as:
UPDATE CustomerPhone
SET PhoneTypeID = 7, PhoneNumber = 999444
WHERE CustomerID = 500 AND PhoneNumber = '911';
Phone type id is 7 - user value that is taken from text box
Phone number is 999444 - user value that is taken from text box
The above final update statement works on the sql environment, but when running
via the application, the execute non query runs ok and gets 0 rows updated! I wonder why?
This is the problem:
AND PhoneNumber = '#phNum'
That's looking for a phone number which is exactly the text '#phNum' - it's not using a parameter called phNum. You want
AND PhoneNumber = #phNum
You're also breaking up your string literals for no obvious reason. This statement:
objSqlCommand.CommandText = "UPDATE " + this.TableName + " SET " + SQL +
" WHERE " + cust.PKName + " = #cusID AND PhoneNumber = " +
"'" + "#phNum" + "'";
would be more easily readable as:
objSqlCommand.CommandText = "UPDATE " + this.TableName + " SET " + SQL +
" WHERE " cust.PKName + " = #cusID AND PhoneNumber = '#phNum'";
Obviously you want to drop the single quotes from it, to make it just:
objSqlCommand.CommandText = "UPDATE " + this.TableName + " SET " + SQL +
" WHERE " cust.PKName + " = #cusID AND PhoneNumber = #phNum";
A little refactoring wouldn't go amiss, either. This loop:
foreach (PropertyInfo PropertyItem in this.GetType().GetProperties())
{
if (!(PropertyItem.Name.ToString() == cust.PKName))
{
if (PropertyItem.Name.ToString() != "TableName")
{
if (SQL == null)
{
SQL = PropertyItem.Name.ToString() + " = #" + PropertyItem.Name.ToString();
}
else
{
SQL = SQL + ", " + PropertyItem.Name.ToString() + " = #" + PropertyItem.Name.ToString();
}
}
else
{
break;
}
}
}
would be more simpler and more readable like this:
StringBuilder sqlBuilder = new StringBuilder();
foreach (PropertyInfo property in this.GetType().GetProperties())
{
string name = property.Name;
// I believe you had a bug before - the properties being updated
// would depend on the ordering of the properties - if it
// ran into "TableName" first, it would exit early!
// I *suspect* this is what you want
if (name != cust.PKName && name != "TableName")
{
sqlBuilder.AppendFormat("{0} = #{0}, ", name);
}
}
// Remove the trailing ", "
if (sqlBuilder.Length > 0)
{
sqlBuilder.Length -= 2;
}
You can do something similar with the final loop too.
Is PhoneNumber a string, or an integer?
I see you're SETting as a integer, but checking in the WHERE as a literal. Could this not be the problem?
If it's an integer, try:
UPDATE CustomerPhone
SET PhoneTypeID = 7, PhoneNumber = 999444
WHERE CustomerID = 500 AND PhoneNumber = 911;
If it's a string, try:
UPDATE CustomerPhone
SET PhoneTypeID = 7, PhoneNumber = '999444'
WHERE CustomerID = 500 AND PhoneNumber = '911';

Categories

Resources