Reading a matrix from excel and loop through using c# DataTable - c#

I am reading an excel that contains a matrix table like the following:
I need to enter the values into an SQL table with the following syntax:
insert into t values (1,18,1.943)
insert into t values (1,18,1.524)
insert into t values (1,18,1.395)
etc
what I tried to do is:
DataTable dt = new DataTable();
dt = ReadExcelFile(Server.MapPath("/Migration/" + txtExcelName.Text + ".xlsx"), false);
if (dt.Rows.Count > 0)
{
StringBuilder str = new StringBuilder();
DataRow myrow = null;
DataColumn mycol = null;
for (int i = 0; i < dt.Rows.Count; i++)
{
myrow = dt.Rows[i];
if (i == 0)
{
myrow = dt.Rows[i +1];
}
for (int j = 1; j < dt.Columns.Count; j++)
{
mycol = dt.Columns[j];
try
{
str.Append("insert into HousingLoanInsuranceRate values (" + dt.Rows[i][mycol] + "," + myrow[0] + ",'" + dt.Rows[i+1][mycol] + "',0,0)");
str.Append("<br/>");
}
catch (Exception ex)
{
}
}
}
litMessage.Text += str.ToString();
}
But it seems my code is not returning the wished result
Appreciate your help.

for (int i = 1; i < dt.Rows.Count; i++) // start from 1
{
myrow = dt.Rows[i];
//if (i == 0)
//{
// myrow = dt.Rows[i +1];
//}
for (int j = 1; j < dt.Columns.Count; j++)
{
try
{
// CHANGES MADE HERE ---------------------------------------vvvvvvvvvvvvv--------------------------vvvvvvvv
str.Append("insert into HousingLoanInsuranceRate values ("+ dt.Rows[0][j] + "," + myrow[0] + "," + myrow[j] + ",0,0)");
str.Append("<br/>");
}
catch (Exception ex)
{
}
}
}
This should fix your problem.
However, be aware that this code is vulnerable to SQL injection. Consider using parameterized query.

Related

C# EPPlus not evaluating formula SUM(A3:B3)

I have just started working with EPPlus. i have data table which has some numeric data and formula. when i load data table by EPPlus and save to excel then formula not evaluated i found when i open the same excel file. formula lies in excel cell as string like SUM(A3:B3)
To evaluate formulate i have tried many options of EPPLUS and those are listed here
pack.Workbook.Worksheets["Test"].Calculate();
pack.Workbook.Worksheets["Test"].Cells["A3"].Calculate();
pack.Workbook.Worksheets["Test"].Cells["B3"].Calculate();
ws.Calculate();
Here i am referring my full sample code where formula not working. please have a look and tell me what i need to add in my code to evaluate formula.
private void button1_Click(object sender, EventArgs e)
{
DataTable dt = GetDataTable();
string path = #"d:\EPPLUS_DT_Excel.xlsx";
Stream stream = File.Create(path);
using (ExcelPackage pack = new ExcelPackage())
{
ExcelWorksheet ws = pack.Workbook.Worksheets.Add("Test");
ws.Cells["A1"].LoadFromDataTable(dt, false);
//pack.Workbook.Worksheets["Test"].Calculate();
//pack.Workbook.Worksheets["Test"].Cells["A3"].Calculate();
//pack.Workbook.Worksheets["Test"].Cells["B3"].Calculate();
ws.Calculate();
pack.SaveAs(stream);
stream.Close();
MessageBox.Show("Done");
}
}
public DataTable GetDataTable()
{
string strSum = "", strColName, strImmediateOneUp = "", strImmediateTwoUp = "";
int startsum = 0;
int currow = 0;
bool firstTimeSum = true;
int NumRows = 3;
int NumColumns = 2;
DataTable dt = new DataTable();
for (int col = 0; col < NumColumns; col++)
{
strColName = GenerateColumnText(col);
DataColumn datacol = new DataColumn(strColName, typeof(object));
dt.Columns.Add(datacol);
}
for (int row = 0; row < NumRows; row++)
{
dt.Rows.Add();
for (int col = 0; col < NumColumns; col++)
{
if (row < 2)
{
dt.Rows[row][col] = Convert.ToInt32(new Random().Next(1, NumRows));
}
else
{
if (firstTimeSum)
{
if (row - currow == 2)
{
currow = row;
startsum = 0;
firstTimeSum = false;
}
else
{
startsum = 1;
}
}
else
{
if (row - currow == 3)
{
currow = row;
startsum = 0;
}
}
if (startsum == 0)
{
strColName = GenerateColumnText(col);
strImmediateOneUp = strColName + ((row + 1) - 1).ToString();
strImmediateTwoUp = strColName + ((row + 1) - 2).ToString();
strSum = string.Format("+SUM({0}:{1})", strImmediateTwoUp, strImmediateOneUp);
dt.Rows[row][col] = strSum;
}
else
{
dt.Rows[row][col] = Convert.ToInt32(new Random().Next(1, NumRows));
}
}
}
startsum = 1;
}
return dt;
}
private string GenerateColumnText(int num)
{
string str = "";
char achar;
int mod;
while (true)
{
mod = (num % 26) + 65;
num = (int)(num / 26);
achar = (char)mod;
str = achar + str;
if (num > 0) num--;
else if (num == 0) break;
}
return str;
}
When adding a formula to a cell you use the Formula property. When you load a range from a DataTable using LoadFromDataTable it has no way of knowing that some of the values are meant to be interpreted as formulas.
You can use LoadDataTable to populate the cells on which the formulas will operate, but for the formulas you'll need to set the Formula property.

evaluate dynamically created formula on large (in memory) flat table

I am currently using this code:
using System;
using NCalc;
namespace SandboxConsoleApp
{
class Program
{
static void Main(string[] args)
{
double[,] data = new double[100, 10];
Random random = new Random();
var numberOfRows = data.GetLength(0);
var numberOfColumns = data.GetLength(1);
for (int row = 0; row < numberOfRows; row++)
{
for (int col = 0; col < numberOfColumns; col++)
{
data[row, col] = random.Next();
}
}
// in the case of 10 columns the expression looks like: [x0] + [x1] + [x2] + [x3] + [x4] + [x5] + [x6] + [x7] + [x8] + [x9]
var stringExpression = "";
for (int col = 0; col < numberOfColumns - 1; col++)
{
stringExpression += string.Format("[x{0}] + ", col);
}
stringExpression += string.Format("[x{0}]", (numberOfColumns - 1));
var exp = new Expression(stringExpression);
var total = 0.0;
for (int row = 0; row < numberOfRows; row++)
{
for (int col = 0; col < numberOfColumns; col++)
{
exp.Parameters[string.Format("x{0}", col)] = data[row, col];
}
if (row % 100000 == 0)
{
Console.WriteLine(row);
}
if (!exp.HasErrors())
{
total += (double)exp.Evaluate();
}
}
}
}
}
Here the fake 'dynamic' expression/formula:
[x0] + [x1] + [x2] + [x3] + [x4] + [x5] + [x6] + [x7] + [x8] + [x9]
adds 10 columns of a 10000000 row 'flat file'. The execution is not very fast and I hit limits, if I have lets say 100 million rows. Is there anything I can do to execute the above faster or should I use some other technologies to execute dynamically created formulas like this? Not sure how fast MySql would be - here I would generate the formula as SQL to the db via (e.g. Dapper).

CSV Export from DataGrid - Wrong Rows

How can I export my datagrid to CSV correctly? Why are the Rows in different columns?
ExportToCsv function return:
Column Headers:
"SR #;8D Report Requested;Status (ASSIST);In R&D;BTQ NUMBER;Priority;Target Date;Implementation Date;Status (BTQ)"
Rows: WRONG!
"1-3271406718;yes;yes;BTQ00153254;6 - Enhancement;22.02.2014;09.09.2014 ;COMPLETED;Eng. wait"
How it should be:
Column Headers:
"SR #;8D Report Requested;Status (ASSIST);In R&D;BTQ NUMBER;Priority;Target Date;Implementation Date;Status (BTQ)"
Rows:
"1-3271406718;yes;Eng. wait;yes;BTQ00153254;6 - Enhancement;22.02.2014;09.09.2014 ;COMPLETED"
here my code:
string CsvFpath = saveDLG.FileName;
StreamWriter csvFileWriter = new StreamWriter(CsvFpath, false);
string columnHeaderText = "";
int countColumn = dgvView.Columns.Count - 1;
if (countColumn >= 0)
{
columnHeaderText = (dgvView.Columns[0].Header).ToString();
}
//Writing column headers
for (int i = 1; i <= countColumn; i++)
{
columnHeaderText = columnHeaderText + ';' + (dgvView.Columns[i].Header).ToString();
}
csvFileWriter.WriteLine(columnHeaderText);
// Writing values row by row
for (int i = 0; i <= dgvView.Items.Count - 2; i++)
{
string dataFromGrid = "";
for (int j = 0; j <= dgvView.Columns.Count - 1; j++)
{
if (j == 0)
{
dataFromGrid = ((DataRowView)dgvView.Items[i]).Row.ItemArray[j].ToString();
}
else
{
dataFromGrid = dataFromGrid + ';' + ((DataRowView)dgvView.Items[i]).Row.ItemArray[j].ToString();
}
}
csvFileWriter.WriteLine(dataFromGrid);
}
csvFileWriter.Flush();
csvFileWriter.Close();
Try it with Linq. It's simpler and easy to read:
public string DataGridToCSV(string delimiter = ";")
{
var sb = new StringBuilder();
var headers = myDataGridView.Columns.Cast<DataGridViewColumn>();
sb.AppendLine(string.Join(delimiter, headers.Select(column => "\"" + column.HeaderText + "\"").ToArray()));
foreach (DataGridViewRow row in myDataGridView.Rows)
{
var cells = row.Cells.Cast<DataGridViewCell>();
sb.AppendLine(string.Join(delimiter, cells.Select(cell => "\"" + cell.Value + "\"").ToArray()));
}
return sb.ToString();
}
Just save the String as *.csv File and you're done.

How can I remove the values apostrophes of my choice from a line?

I want to remove in each line from specific values the apostrophes.
This is my code for writing into a text file:
for (int a = 0; a < checkedListBox1.CheckedItems.Count; a++)
{
DataTable ExportTable = new DataTable();
//Debug.WriteLine(checkedListBox1.CheckedItems[a].ToString());
string SelectLines =
"SELECT Identifier,
TestID,
Description,
Enabled,
StringLimit,
LowLimit,
HighLimit,
LimitType,
Unit,
Parameters
FROM specifications
where Identifier = '" + checkedListBox1.CheckedItems[a] + "'";
ExportTable = ObjSqlAccess.GetDataTableFromTable(SelectLines);
int rowcount = ExportTable.Rows.Count;
int columncount = ExportTable.Columns.Count;
int rw = 0;
int clm = 0;
writeText.WriteLine("\r\n\r\n[" + checkedListBox1.CheckedItems[a].ToString() + "]" + "\r\nCount = " + (rowcount - 1));
for (rw = 0; rw < rowcount - 1; rw++)
{
string test = "";
for (clm = 0; clm < columncount - 1; clm++)
{
test += ExportTable.Rows[rw][clm].ToString();
test += "','";
}
writeText.WriteLine((rw + 1) + "=(Identifier,TestID,Description,Enabled,StringLimit,LowLimit,HighLimit,LimitType,Unit,Parameters) VALUES ('" + removeThis + "')");
}
writeText.Flush();
writeText.Close();
writeText.Dispose();
And for instance, I want to remove the apostrophes from each line from only these values: 1, 0 , 0 before writing it to a text file. Or to be more specific, only the values that are assigned to Enable, LowLimit and HighLimit column.
Does anyone has an idea of how to proceed? I hope my question is clear enough.
Try this:
for (clm = 0; clm < columncount - 1; clm++)
{
DataColumn col = ExportTable.Columns[clm];
test += ExportTable.Rows[rw][clm].ToString();
if (col.DataType == bool || col.DataType == Int32) //Add other types that dont require single quotes to if statement
{
test += ",";
}
else
{
test += "','";
}
}
First, I would change the way you're writing the string so it doesn't care if there are single quotes, or anything else, in the variable you pass for VALUES.
writeText.WriteLine((rw + 1) + "=(Identifier,TestID,Description,Enabled,StringLimit,LowLimit,HighLimit,LimitType,Unit,Parameters) VALUES (" + test + ")");
Also worth noting is I don't think your loops will work correctly. When you use a count in a for loop, the count is already 1-indexed. So, if you do columnCount = ExportTable.Columns.Count;, your loop should be for (int i = 0; i < columnCount; i++). An easy way to remember is index is 0-based, but count is 1-based.
I would also use a string builder instead. Then in your loop just do a check for those columns:
string test = "";
for (clm = 0; clm < columncount; clm++)
{
StringBuilder sb = new Stringbuilder();
sb.Append(ExportTable.Rows[rw][clm].ToString());
if (clm != 3 && clm != 5 && clm != 6)
{
sb.Insert(0,"'");
sb.Append("'");
}
test += sb;
if (clm != columncount - 1) // add a comma if it's not the last column
{
test += ",";
}
}

Why datatable ignores initial spaces

Datatable does not take initial spaces, so when i insert it into database and retrieve it by select statement and display it on page using stringBuilder, Initial spaces are gone and text does not appear on screen as it is written in textbox
DataTable1.Rows[0][0]=TextBox1.Text;
This is how I insert into database
public static void Insert(DataTable table)
{
StringBuilder Col = new StringBuilder();
StringBuilder Val = new StringBuilder();
string Query, finalVal;
int i, j;
int count = 0;
int ColumnCount = table.Columns.Count;
for (i = 0; i < ColumnCount; i++)
{
if (table.Rows.OfType<DataRow>().Any(r => !r.IsNull(table.Columns[i].ColumnName)))
{
Col.Append(table.Columns[i].ColumnName);
Col.Append(",");
count++;
}
}
Col.Remove(Col.Length - 1, 1);
string[] columnName = Col.ToString().Split(',');
foreach (DataRow r in table.Rows)
{
Val.Append(",(");
for (j = 0; j < count; j++)
{
if (r[columnName[j]] != null)
{
Val.Append("'" + r[columnName[j]] + "'");
Val.Append(",");
}
else
{
Val.Append("null,");
}
}
Val.Append(")");
Val.Remove(Val.Length - 2, 1);
}
finalVal = Val.ToString().Substring(1);
Query = "Insert into " + table.TableName + "(" + Col + ")" + "Values" + finalVal;
EduDB.ExecuteNonQuery(Query);
}
You must be trimming the string befor inserting into database. Please check that out

Categories

Resources