C# datatable computing - c#

I am computing in the large datatable. The table name is templetable.
I am trying to calculate the sum from the 4th column to the last column and save the results to another datatable. But I am getting errors as it says could not find the column "colPnow"
Any ideas?
DataView dv2 = new DataView(SP_dt);
for (int i = 0; i < LoadIDcount; i++)
{
string IDnow = LoadID[i, 0];
dv2.RowFilter = String.Format("Load_ID = '{0}'", IDnow);
DataTable temptable = dv2.ToTable();
for (int j = 0; j < 8760; j++)
{
string colPnow = SP_dt.Columns[j*2 + 4].ColumnName.ToString();
double ColP_sum= (double)temptable.Compute("Sum(colPnow)", String.Format("Load_ID = '{0}'", IDnow));
string colQnow = SP_dt.Columns[j*2 + 5].ColumnName.ToString();
double ColQ_sum = (double)temptable.Compute("Sum(colQnow)", String.Format("Load_ID = '{0}'", IDnow));
Load_dt.Rows[i][j * 2 + 2] = ColP_sum;
Load_dt.Rows[i][j * 2 + 3] = ColQ_sum;
}
}

You are not formatting your expression string correctly in the Compute method. Use another String.Format and it will work. Your Compute expression is currently literally equal to "Sum(colPnow)". You want the actual column name string that is stored in your colPnow variable.
Change this part of your code to this:
string colPnow = SP_dt.Columns[j*2 + 4].ColumnName.ToString();
double ColP_sum= (double)temptable.Compute(String.Format("Sum([{0}])", colPnow),
String.Format("Load_ID = '{0}'", IDnow));
The same should be done for your colQnow variable. I would also suggest you read how String.Format works so that you can grasp the string formatting concept.

Related

Format error when trying to run the program [duplicate]

This question already has answers here:
int.Parse, Input string was not in a correct format
(7 answers)
Closed last year.
So, today I was trying to make an app in which the user enters the coordinates of their car and the app calculates the easiest way to reach a gas station before the fuel tank runs out. But when I wanted to test if the app displays the data which is stored in a .txt file, I get a System.FormatException error which I cannot solve. I have used this method many many times before and I am not sure what is the problem here.
The error occurs at the line:
int xcoor = int.Parse(s.Substring(k + 1));
Code:
int n = 10;
string[] cities = new string[n];
int[] x = new int[n];
int[] y = new int[n];
System.IO.StreamReader sr = new System.IO.StreamReader(
#"..\..\CitiesGPS.txt", Encoding.GetEncoding(1250));
for (int i = 0; i < n; i++)
{
string s = sr.ReadLine();
int k = s.IndexOf(";");
string city = s.Substring(0, k);
cities[i] = city;
int xcoor = int.Parse(s.Substring(k + 1));
x[i] = xcoor;
int k2 = s.IndexOf(";");
int ycoor = int.Parse(s.Substring(k2 + 1));
y[i] = ycoor;
}
sr.Close();
Console.WriteLine("Data in the file:");
for (int i = 0; i < n; i++)
{
Console.WriteLine(cities[i] + ";" + x[i] + ";" + y[i]);
}
Data:
Nagyváros;150;30
Kisváros;250;300
TanyaBenzunkúttal;290;310
Szépváros;500;10
Alsóváros;250;0
Felsőváros;560;560
Középváros;300;300
FolyópartiVáros;380;400
HáromBenzinkutasváros;10;400
Nagyvárosbvezetőútja;380;230
Thanks in advance,
Blaise
You don't have any length on the middle Substring call, so it takes the rest of the line.
int xcoor = int.Parse(s.Substring(k + 1, /* missing length*/));
But, please use a CSV-parser. There is no reason to re-invent the wheel every time you need it.
EDIT
I just noticed you're getting the same index of ";" into both k and k2, so it won't work at all.
Again, use a CSV-parser.
EDIT 2
If you won't use a CSV-parser, here is a solution with Split as #ADyson suggests:
for (int i = 0; i < n; i++)
{
var parts = sr.ReadLine().Split(";");
string city = parts[0];
cities[i] = city;
int xcoor = int.Parse(parts[1]);
x[i] = xcoor;
int k2 = s.IndexOf(";");
int ycoor = int.Parse(parts[2]);
y[i] = ycoor;
}
Apart from the general advice to use a ready-made CSV / delmimited-file parser for this task, your own code is massively over-complicating the problem, and suffers from various logical flaws when trying to detect the location of the delimiters and calculate the correct lengths of the strings in between them.
It's much simpler to just use the String.Split method.
Also your onward data structure (consisting of separate arrays for cities, x coords and y coords) doesn't make much sense if you're intending to then match the co-ordinates to the location names - if you want to do that, keep the data together. A simple object structure would make it easier to work with later on. And lists are generally easier to work with than arrays, too.
Also for simplicity you should just read to the end of the file, not a specific number of lines.
Lastly, best practice with a disposable item like a StreamReader is to initialise it in conjunction with a using block to ensure it's properly disposed afterwards (see StreamReader documentation examples.
e.g.
public class LocationData
{
public string Name {get; set;}
public int X {get; set;}
public int Y {get; set;}
}
and then
using (System.IO.StreamReader sr = new new System.IO.StreamReader(#"..\..\CitiesGPS.txt", Encoding.GetEncoding(1250)))
{
List<LocationData> locationList = new List<LocationData>();
while ((s = sr.ReadLine()) != null)
{
string[] data = s.Split(';');
LocationData loc = new LocationData()
{
Name = data[0],
X = int.Parse(data[1]),
Y = int.Parse(data[2])
};
locationList.Add(loc);
}
}
foreach (LocationData loc in locationList)
{
Console.WriteLine(loc.Name + ";" + loc.X + ";" + loc.Y);
}
P.S. Super-simple demo of processing a single row using string.split: https://dotnetfiddle.net/vGXu2O
The fail is with the substring in the line
int xcoor = int.Parse(s.Substring(k + 1));
You are trying to parse to int the value 150;30. And obviously it can't be parsed as a number.
I recommend split every line by ; to get the values for each position.
You can do this inside for loop:
string[] line = s.Split(";");
var city = line[0];
var xcoor = int.Parse(line[1]);
var ycoor = int.Parse(line[2]);
cities[i] = city;
x[i] = xcoor;
y[i] = ycoor;
Edit to add how it works using substring().
Substring method takes two arguments:
1st: Is the position where start.
2nd: Is how many positions more do you want to get.
So, the solution is get the ondex of all ; (I've used a lambda expression) and then use substring in a correct way.
That is: Saying the program to start where a semicolon has been found and end as many position as there exists until the next semicolon.
var indexes = Regex.Matches(s, ";").Cast<Match>().Select(m => m.Index).ToList();
var city = s.Substring(0,indexes[0]);
var xcoor = s.Substring(indexes[0]+1,(indexes[1]-indexes[0])-1);
var ycoor = s.Substring(indexes[1]+1, (s.Length-indexes[1])-1);
cities[i] = city;
x[i] = int.Parse(xcoor);
y[i] = int.Parse(ycoor);
With this code, you can see the position where to start and 'cut' the substring.

C# How can I convert an excel cells address in the following notation: "LetterNumber" to "Number, Number" and vice-versa?

How can I convert an excel cells address in the following notation: "LetterNumber" to "Number, Number" and vice-versa?
Well, even if the question wasn't clear, here is an answer for:
How can I convert an excel cells address in the following notation: "LetterNumber" to "Number, Number" and vice-versa?
private const string ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static string ToExcelCoordinates(string coordinates)
{
string first = coordinates.Substring(0, coordinates.IndexOf(','));
int i = int.Parse(first);
string second = coordinates.Substring(first.Length + 1);
string str = string.Empty;
while (i > 0)
{
str = ALPHABET[(i - 1) % 26] + str;
i /= 26;
}
return str + second;
}
public static string ToNumericCoordinates(string coordinates)
{
string first = string.Empty;
string second = string.Empty;
CharEnumerator ce = coordinates.GetEnumerator();
while (ce.MoveNext())
if (char.IsLetter(ce.Current))
first += ce.Current;
else
second += ce.Current;
int i = 0;
ce = first.GetEnumerator();
while (ce.MoveNext())
i = (26 * i) + ALPHABET.IndexOf(ce.Current) + 1;
string str = i.ToString();
return str + "," + second;
}
The results are:
"1,1" -> "A1"
"A1" -> "1,1"
"42,231" -> "AP231"
"AP231" -> "42,231"
I'm trying to set the value of Worksheet.Cells[] but it does not except the "B3" kinds of values
Worksheet.Range does:
Worksheet.Range("A4").Value = "Foo";
I would also advise you not to set one cell at a time if you can help it. Every call to Cells or Range in a slow interop call, so you'll get much better performance if you put your values in an array and set the value of an entire range in one shot:
int[,] values;
// fill values with integers
Worksheet.Range("A1","D4") = values;

EPPLUS multiple columns configuration and conditional formatting in Excel C#

In my tool, user can choose one configuration (through combobox->multiple datatable) and the respective table will reflect in the excel sheet as per below.Columns (data in rows will differ) that will remain the same for all configuration are Product Name, Serial Name and Length 1 and Total Length. Different configuration will have added columns such as Length 2, Length 3,Length 4 (user will add the data in these rows)etc.
I want to add conditional formatting formula in Total Length column where background cell will turn green if it is in range (minval to maxval) and red when it is out of range. I am stuck with my code without solution.It did not change any color when the user add the data in the excel. Help. Thanks!
Table
private void ManualFormatExcelandAddRules(ExcelWorksheet WS, DataTable DTtoFormat, int ColStartAddOfDT, int RowStartAddOfDT)
{
int colCountofDT = DTtoFormat.Columns.Count;
int rowCountofDT = DTtoFormat.Rows.Count;
double minval = 0;
double maxval = 0;
int flag = 0;
for (int Colno = ColStartAddOfDT; Colno < ColStartAddOfDT + colCountofDT; Colno++)
{
WS.Cells[RowStartAddOfDT, Colno].Style.Border.BorderAround(ExcelBorderStyle.Thin);
for (int RowNo = RowStartAddOfDT + 1; RowNo <= RowStartAddOfDT + rowCountofDT; RowNo++)
{ if (WS.Cells[RowNo, Colno].Text.Contains("to") && WS.Cells[RowNo, ColStartAddOfDT].Text.Contains("DRAM"))
{
string[] GuidelineVal = WS.Cells[RowNo, Colno].Text.Split("to".ToArray(), StringSplitOptions.RemoveEmptyEntries).ToArray();
if (GuidelineVal[0].Trim() != "NA" && GuidelineVal[1].Trim() != "NA")
{
minval = Convert.ToDouble(GuidelineVal[0].Trim());
maxval = Convert.ToDouble(GuidelineVal[1].Trim());
flag = 0;
}
else
flag = 1;
}
else if (WS.Cells[RowNo, Colno].Text == "" && WS.Cells[RowStartAddOfDT + 1, Colno].Text.Contains("to"))
{
if (flag == 0)
{
string _statement = "AND(Convert.ToDouble(WS.Cells[RowNo, Colno].Text) >= minval,Convert.ToDouble(WS.Cells[RowNo, Colno].Text) <= maxval)";
var _cond = WS.ConditionalFormatting.AddExpression(WS.Cells[RowNo, Colno]);
_cond.Formula = _statement;
_cond.Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid;
_cond.Style.Fill.BackgroundColor.Color = Color.Green;
}
else
WS.Cells[RowNo, Colno].Style.Fill.BackgroundColor.SetColor(Color.Red);
WS.Cells[RowNo, Colno].Style.Border.BorderAround(ExcelBorderStyle.Thin);
}
}
}
The conditional formatting expression you use is wrong/contains syntax errors/uses functions that don't exist and that makes that Excel will ignore it as it doesn't understand what it needs to do.
Looking at your code you have 4 variables that make up that expression:
RowNo and ColNo to indicate the cell to apply the conditional formattig to
minval and maxval to be the lower and upper bound of the condition
The following code uses those variables to build up the correct expression:
string _statement = string.Format(
CultureInfo.InvariantCulture,
"AND({0}>={1},{0}<={2})",
new OfficeOpenXml.ExcelCellAddress(RowNo, ColNo).Address,
minval,
maxval );
var _cond = WS.ConditionalFormatting.AddExpression(WS.Cells[RowNo, ColNo]);
_cond.Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid;
_cond.Style.Fill.BackgroundColor.Color = Color.Green;
_cond.Formula = _statement;
Notice that the expression uses only valid Excel functions. You can't mixin .Net statements like Convert.ToDouble. It is also important to use the InvariantCulture for the number conversion, otherwise the separators might get interpreted as an extra parameter in your function.
When you debug this _statement will contain this: AND(A2>=40.2,A2<=44.5) and when applied to the A2 cell, that works as advertised.

Input string was not in a correct format.Couldn't store <> in Column. Expected Int64

here i am trying to get the comma separated values. In the following code "tbl"
is the table which contains the comma separated values..
private static DataTable PivotFieldData(DataTable tbl)
{
var tblPivot = new DataTable();
if (tbl.Columns.Count > 0)
{
tblPivot.Columns.Add(tbl.Columns[0].ColumnName, typeof(int));
for (int i = 0; i < tbl.Rows.Count; i++)
{
tblPivot.Columns.Add(Convert.ToString(tbl.Rows[i][1]), typeof(long));
}
var r = tblPivot.NewRow();
r[0] = tbl.Rows[0][0].ToString();
for (int col = 0; col < tbl.Rows.Count; col++)
{
r[col + 1] = tbl.Rows[col][2].ToString();
}
tblPivot.Rows.Add(r);
}
return tblPivot;
}
but i am getting an error as follow.
i have tried like
r[col + 1] = tbl.Rows[col][2].ToString().Trim() == "" ? 0 : Convert.ToInt64(tbl.Rows[col][2].ToString());
but i am getting an error that input string was not in correct format ....
please check it and help me... thank you..
The error message is pretty clear. You have a string value (i.e. -2312,77,845.00) and you're trying to store that into a column that is typeof(long). If that string value represents a number then strip out the commas and remove the ToString call inside your loop. If it represents a string (which it seems it does because the columns are in the wrong place for it to be a number) then change the column type.

Special characters in string.Replace

I want to replace special characters in string.
For example this is input text
http\u00253A\u00252F\u00252Fvideo.l3.fbcdn.net\u00252Fcfs-l3-ash4\u00252F351111\u00252F203\u00252F260478023976707_55781.mp4\u00253Foh\u00253D064626d4996116bdcde2d52f9b70e1f0\u002526oe\u00253D4E566C00\u002526l3s\u00253D20110823082632\u002526l3e\u00253D20110825083632\u002526lh\u00253D0dbcb2d22cd4dd5eb10bf
and then I expect this result :
http://video.l3.fbcdn.net/cfs-l3-ash4/351111...
But string is not replacing as expected
string[] BadCharacters = { "\\u00253A", "\\u00252F", "\\u00253F" };
string[] GoodCharacters = { ":", "/", "?" };
int i;
for (i = 0; i <= 2; i++)
{
textBox2.Text = textBox1.Text.Replace(BadCharacters[i], GoodCharacters[i]);
}
Your problem is your string gets stomped every iteration through the loop by going back to TextBox1.Text, you need to keep it in a local and keep using the changed value for the next substitution:
var changedText = textBox1.Text;
// always modify and assign to temp, that way we modify previous
for (i = 0; i <= 2; i++)
{
changedText = changedText.Replace(BadCharacters[i], GoodCharacters[i]);
}
textBox2.Text = changedText;
Try this:
var tmp = textBox1.Text;
for (i = 0; i <= 2; i++)
{
tmp = tmp.Replace(BadCharacters[i], GoodCharacters[i]);
}
textBox2.Text = tmp;
textBox2.Text will only ever contain one of the substitutions for each loop, so you likely see only the last iteration.
for (i = 0; i <= 2; i++)
{
textBox1.Text = textBox1.Text.Replace(BadCharacters[i], GoodCharacters[i]);
}
would likely provide the full substituted string desired.
You need to save the updated value of string each time you replace a substring. So save initial value of textBox1 to textBox2 and use it during iteration. In this way, you won't lose your updated string value.
textBox2.Text = textBox1.Text;
for(i = 0; i <= 2; i++)
{
textBox2.Text = textBox2.Text.Replace(BadCharacters[i], GoodCharacters[i]);
}
Also, by asssigning initial textBox1 value to textBox2 and using it inside your for loop, you save one assigmant statement.

Categories

Resources