1.) ***Ok, so I have my DataTable that is imported from an Excel SpreadSheet and it is filled.I would like to sift through the DataTable and sum each row. I have to skip the first column & the first rows because they are labels. I am trying to reach each row in the table and total it and output to a "Row Total" column .. I am getting a "invalid cast specified" when I am trying to assign the 'number' variable to try and sum each cells value.
Example:
Row(0) --------------------ItemA......ItemB.......ItemC..............RowTotal
Column(1) CompanyA .....12 ..........12.............10....................34
2.) Also, I haven't reached it yet -- there is a potential issue with my trying to output it to the last column in the DataTable.
noted by: dr[dt.Columns.Count - 1] = Convert.ToInt32(sum);
Any thoughts or suggestions?
DataRow dr = dt.NewRow();
int sum = 0;
dt.Columns.Add("Row Totals", typeof(int));
for (int i = 0; i < dt.Columns.Count; i++)
{
if (dt.Columns[i].ColumnName == "Client")
{
dt.Columns.Cast<DataColumn>().Skip(1);
}
else
{
for (int j = 0; j < dt.Rows.Count - 1; j++)
{
dt.Rows.Cast<DataRow>().Skip(1);
int number =0;
number = (dt.Rows[j].Field<int>(i));
sum += number;
dr[dt.Columns.Count - 1] = Convert.ToInt32(sum);
Console.WriteLine("Row : {0} , Column : {1} , Value : {2}", i,j, dt.Rows[i][j].ToString());
Console.WriteLine(sum);
}
Console.ReadLine();
}
}
UPDATE: 12/27/12 ************
So, a solution I'm trying is to just skip the rows and column I know are text. I am still getting the "specified cast not valid" when it tries to filter through each cell and sum it. Any more suggestions?
Thank you in advance.
DataRow dr = dt.NewRow();
int sum = 0;
int number = 0;
for (int i = 0; i < dt.Columns.Count-1; i++)
{
if (dt.Columns[i].ColumnName == "column1")
{
dt.Columns.Cast<DataColumn>().Skip(0);
}
if (dt.Columns[i].ColumnName == "column2")
{
dt.Columns.Cast<DataColumn>().Skip(1);
}
else
{
for (int j = 0; j < dt.Rows.Count; j++)
{
dt.Rows.Cast<DataRow>().Skip(0);
dt.Rows.Cast<DataRow>().Skip(1);
//if (number != -1 && number != 0)
//{
number = (dt.Rows[j].Field<int>(i));
sum += number;
dr[dt.Rows.Count] = Convert.ToInt32(sum);
//}
//else
//{
// number = 0;
//}
Console.WriteLine("Row : {0} , Column : {1} , Value : {2}", i, j, dt.Rows[i][j].ToString());
Console.WriteLine(sum);
}
Console.ReadLine();
dataGridView1.DataSource = dt;
}
**UPDATE 12/27 1:30pm
I have scratched all that previous code and am attempting a test sheet and output. It seems to be working except now I can't seem to get the items to total when I am adding them to the last row. I'm stuck in the "else"" section of the code.
for (int i = 0; i < dt.Columns.Count - 2; i++)
{
for (int j = 0; j < dt.Rows.Count - 1; j++)
{
string value = dt.Rows[i][j].ToString();
int num = 0;
bool res = int.TryParse(value, out num);
if (res == false)
{
num = 0;
}
else
{
int sum = 0;
sum += num;
DataRow dr;
dr["Totals"] = sum;
dt.Rows.Add(dr);
}
}
dataGridView1.DataSource = dt;
}
}
One possibility is that there is a blank value in your data table - you can't cast a null object to an integer, so the Field extension method may be failing.
Related
How can I possibly count only the specific whole column I want in a multidimensional array
I do the counting of my whole column and row like this
//COLUMN
for(int col = 0; col < table.GetLength(0); col++)
{
int sum = 0;
//ROW
for (int row = 0; row < table.GetLength(1); row++)
{
if (table[col,row] != null)
{
sum++;
}
}
Debug.Log("table column: " + col + " has " + sum + " data");
}
What I want is just to get the specific whole Column then move to another Column just like that. I need to do this because i need to compare it with the last column value to the next one.
For example : I want to check how many data are there in the 2nd column then compare it with the 1st column.
You´re almost there. All you have to do is store the sum of the current column into a list:
var List<int> sums = new List<int>();
//COLUMN
for(int col = 0; col < table.GetLength(0); col++)
{
int sum = 0;
//ROW
for (int row = 0; row < table.GetLength(1); row++)
{
if (table[col,row] != null)
{
sum++;
}
}
Debug.Log("table column: " + col + " has " + sum + " data");
sums.Add(sum);
}
Now you can easily compare the number of rows in colum 1 and that of column 2:
bool areEqual = sums[0] == sums[1];
Got a solution :)
//generic function
public static int CountRow<T>(T[,] table, int col)
{
if (table == null || col < 0 || col >= table.GetLength(1))
{
//handle error
return -1;
}
//this is the same as the block of the outer for loop
int sum = 0;
for (int row = 0; row < table.GetLength(1); row++)
{
if(table[col,row] != null)
{
sum++;
}
}
return sum;
}
then used it like this
int prevSum = -1;
for (int col = 0; col < table.GetLength(0); ++col)
{
int sum = CountRow(table, col);
Debug.Log("table column :" + col + " has " + sum + " data");
if (sum == prevSum)
{
//comparison happens
}
}
I have a multidimensional array which is declared like this
string[,] table = new string[104,15];
Now it has all the data that I need and I got the data to put it on the table by doing this
int xIndex = 0;
int yIndex = 0;
string newPreviousValue = "placeholder";
for (int i = 0; i < list.Count; i++)
{
newString[0] += list[i].r;
newString[0] += ",";
}
string[] newChars = newString[0].Split(',');
foreach (string previousValue in newChars)
{
table[xIndex, yIndex] = result;
}
Now what I am trying to do is from this Data A
All these value of Data B is depending on what value of Data A has
RED means "The same in length"
BLUE means "Not the same in length"
So here how it works .
PSEUDO CODE
//I am talking about Data A
if table[1,1] is equal to null or T then
{
if table[1,0] and table[0,0] has the same length
//Display blue circle on Data B
display a blue circle
}
//I am talking about Data A
else if table[1,1] is not equal to null then
{
compare table[0,1] and table[0,0] if they have the same length as table[1,1] and table[1,0]
//Display a red circle
display a red circle }
}
If I am not clear here's the rule . What I am talking about is the Big Eye Road Rules.
What I have tried so far is this
//lets check for the 2nd row and 2nd column of the big road table
if (table[1,1] == null && table[2,0] != null)
{
Move = true;
if (Move)
{
//lets move to the 3rd row and compare if they have the same in length (1st row and 1st column)
if (table[0, 0] != null && table[1, 0] != null)
{
//red circle
}
else
{
//blue circle
}
}
}
What I want to achieve here is to count every row and column in DATA A if how many data's that are stored there for example
table[0,0] to table[0,6] has 1 data
table[1,0] to table[1,6] has 1 data
table[2,0] to table[2,6] has 2 data
Just like that . Could someone help with it please. Thank you.
EDIT
On the last part of my question I will share what I did
//COLUMN
for(int col = 0; col < table.GetLength(0); col++)
{
int sum = 0;
//ROW
for (int row = 0; row < table.GetLength(1); row++)
{
if (table[col,row] != null)
{
sum++;
}
}
Debug.Log("table column: " + col + " has " + sum + " data");
}
I can now get this
table[0,0] to table[0,6] has 1 data
table[1,0] to table[1,6] has 1 data
table[2,0] to table[2,6] has 2 data
for(int col = 0; col < table.GetLength(0); col++)
{
int sum = 0;
//ROW
for (int row = 0; row < table.GetLength(1); row++)
{
if (table[col,row] != null)
{
sum++;
}
}
Debug.Log("table column: " + col + " has " + sum + " data");
}
I want to get the cell number of the column "Hersteller".
I don't know how to do that and thought anyth
int columnIndex = dataGridView1.CurrentCell.ColumnIndex;
tring columnName = dataGridView1.Columns[columnIndex].Name;
for(columnName.Equals("Hersteller") columnIndex++;) { }
any ideas?
You could iterate over the columns and get the index:
int colIndex = -1;
for (int i = 0; i < dataGridView1.Columns.Count; i++)
{
if (dataGridView1.Columns[i].Name.Equals("Hersteller"))
{
colIndex = i;
break;
}
}
if (colIndex > -1)
// Found the column, do something
I have a horrible method that extracts data from a DataTable and converts it to a desirable formatted DataTable. I'm sure there is a much nicer way to do this in LinQ but I'm not really experienced with it. I would appreciate if somebody could show me a nicer solution.
Heres the code
private static void ExtractImportLayoutFromExcelDt(DataTable importDt, DataTable dtExtracted, int languages)
{
// The number of Locale colums included in the excel file.
for (int x = 0; x < languages; x++)
{
// The total number of friendlynames-keys / language included in the excel.
for (int j = 0; j < dtExtracted.Rows.Count; j++)
{
var row = dtExtracted.Rows[j];
DataRow tempRow = importDt.NewRow();
// Filling in the 3 columns. (FriendlyName - LocaleID - Text)
for (int i = 0; i <= 2; i++)
{
if (i == 0)
{
tempRow[i] = row[i]; // Friendly names: This is always going to be column 1 [0].
}
else if (i == 1)
{
tempRow[i] = Regex.Match(dtExtracted.Columns[x + 1].ToString(), #"\d+").Value; // LocaleIDs: Getting rid of non numeric characters from this column.
}
else
{
tempRow[i] = row[x + 1];
}
}
importDt.Rows.Add(tempRow);
}
}
}
i would rewrite inner for loops
for (int x = 0; x < languages; x++)
foreach (DataRow row in dtExtracted.Rows)
importDt.Rows.Add
(
row[0],
Regex.Match(dtExtracted.Columns[x + 1].ToString(), #"\d+").Value; // LocaleIDs: Getting rid of non numeric characters from this column.
row[x + 1]
);
DataTable.Rows collection has overload of Add method, which accept an array of objects: Add
I am not quite sure if LINQ could be of any help here, but apart from rewriting the entire mapping logic I would at least split this method into two:
private static void ExtractImportLayoutFromExcelDt(DataTable importDt, DataTable dtExtracted, int languages)
{
// The number of Locale colums included in the excel file.
for (int x = 0; x < languages; x++)
{
// The total number of friendlynames-keys / language included in the excel.
for (int j = 0; j < dtExtracted.Rows.Count; j++)
{
AddRow(importDt, dtExtracted, dtExtracted.Rows[j], x+1);
}
}
}
private static void AddRow(DataTable table, DataTable dtExtracted, DataRow originalRow, int language)
{
var row = table.NewRow();
row[0] = originalRow[0];
row[1] = Regex.Match(dtExtracted.Columns[language].ToString(), #"\d+").Value;
row[2] = originalRow[language];
table.Rows.Add(row);
}
You can write something like this but in this case is more like abuse of Linq but if you do it for educational purposes ..The main power of LINQ is when you want to enumerate or filter for example collections not in cases like this.
public static void ExtractImportLayoutFromExcelDt(DataTable importDt, DataTable dtExtracted, int languages)
{
Enumerable.Range(0, languages)
.ToList().ForEach(x =>
{
Enumerable.Range(0, dtExtracted.Rows.Count)
.ToList().ForEach(j =>
{
var row = dtExtracted.Rows[j];
DataRow tempRow = importDt.NewRow();
AddRow(importDt, dtExtracted, x, row, tempRow);
});
});
}
private static void AddRow(DataTable importDt, DataTable dtExtracted, int x, DataRow row, DataRow tempRow)
{
for (int i = 0; i <= 2; i++)
{
if (i == 0)
{
tempRow[i] = row[i]; // Friendly names: This is always going to be column 1 [0].
}
else if (i == 1)
{
tempRow[i] = Regex.Match(dtExtracted.Columns[x + 1].ToString(), #"\d+").Value; // LocaleIDs: Getting rid of non numeric characters from this column.
}
else
{
tempRow[i] = row[x + 1];
}
}
importDt.Rows.Add(tempRow);
}
I have the ability to total each column and add the row -- using this block of code :
DataRow totalRow = t.NewRow();
int colCount = 1;
for (int j = 1; j < t.Columns.Count; j++)
{
if (t.Columns[j].ColumnName == "Client")
{
t.Columns.Cast<DataColumn>().Skip(1);
}
else
{
int colTotal = 0;
for (int i = 1; i < t.Rows.Count; i++)
{
colTotal += Convert.ToInt32(t.Rows[i][j]);
totalRow[t.Columns[j].ColumnName] = colTotal;
}
}
++colCount;
}
t.Rows.Add(totalRow); <br>
**WHY O WHY Can't I just alter this OR use this block (below) to total the rows and insert a new column with the totals of each row??? I don't know why I'm having such a block on this--I'm sure it's relatively simple I just am not seeing it! It is driving me nuts -- I've been at this for 3 days --its sad.
int sum = 0;
foreach (DataRow rows in dt.Rows)
{
for (int i = 0; i < dt.Columns.Count; i++)
{
for (int j = 0; j < dt.Rows.Count; j++)
{
int number = Convert.ToInt32(dt.Rows[j].Field<int>(i));
sum += number;
}
}
rows["testrow"] = sum;
}
dataGridView1.DataSource = dt;
}
The error is still "Specified cast in not valid" -- The datatable is coming from an excel sheet. I can use it on a self-made DataTable just fine. I don't understand.
This block of code works just fine and gives me the sum of the rows in a new column
System.Data.DataTable dt = new System.Data.DataTable();
dt.Columns.Add("amount1", typeof(int));
dt.Columns.Add("amount2", typeof(int));
dt.Columns.Add("amount3", typeof(int));
dt.Columns.Add("amount4", typeof(int));
dt.Columns.Add("Row Totals", typeof(int));
DataRow dr = dt.NewRow();
dr[0] = 100;
dr[1] = 200;
dr[2] = 300;
dr[3] = 400;
dr[4] = 0;
dt.Rows.Add(dr);
int sum = 0;
for (int i = 0; i < dt.Columns.Count; i++)
{
for (int j = 0; j < dt.Rows.Count; j++)
{
// int sum = 0;
int number = dt.Rows[j].Field<int>(i);
sum += number;
}
}
It seems likely that it's not an int but a long (or byte) you can cast a long to int but you can't unbox a long to an int which the code in question tries to do.
if that's the case you can do something like
var sum = (from column in dt.Columns.AsEnumerable<DataColum>().Skip(1)
from row in dt.Rows.AsEnumerable<DataRow>().Skip(1)
where column.ColumnName != "Client"
select (long)row[column]).Sum();
Drum roll please ---
Thank you guys for comments and suggestions they did help me get to this point understanding what exactly was going on behind the scenes.
System.Data.DataTable dt = ds.Tables[0];
dt.Columns.Add("testrow", typeof(int));
DataRow dr = dt.NewRow();
int sum = 0;
for (int i = 1; i < dt.Columns.Count; i++)
{
for (int j = 1; j < dt.Rows.Count; j++)
{
if (j == dt.Rows.Count - 1)
{
dt.Rows[i][j] = Convert.ToInt32(sum);
sum = 0;
}
else
{
object number = dt.Rows[i][j];
sum += Convert.ToInt32(number);
}
}
dataGridView1.DataSource = dt;
}