I have data table like below. Here row 2,3,4,5 are not allowed. how do i validate this scenario using C#. Please help. Here the number of columns is not fixed.
A B C
A B C
A B
A C
B C
A B B
B B C
A C B
C# with LinQ
This function eliminates duplicates and null values from columns. If is not null what you are looking for, then you just need to change "DBNull" for what you want.
public static DataTable FilterDataTable(DataTable table)
{
// Erase duplicates
DataView dv = new DataView(table);
table = dv.ToTable(true, table.Columns.Cast<DataColumn>().Select(x => x.ColumnName).ToArray());
// Get Null values
List<DataRow> toErase = new List<DataRow>();
foreach (DataRow item in table.Rows)
for (int i = 0; i < item.ItemArray.Length; i++)
{
if (item.ItemArray[i].GetType().Name == "DBNull")
{ toErase.Add(item); break; }
}
//Erase Null Values
foreach (DataRow item in toErase)
table.Rows.Remove(item);
return table;
}
Related
I have an Excel VSTO Add-in, and I have to get excel table data into a DataTable class, I've already implemented it by looping through the cells but its a bit slow:
DataTable dataTable = new DataTable(table.Name);
foreach (Excel.ListColumn column in table.ListColumns)
dataTable.Columns.Add(column.Name);
for (int r = 2; r < table.ListRows.Count + 2; r++)
{
DataRow row = dataTable.NewRow();
for (int c = 1; c < table.ListColumns.Count + 1; c++)
row[c - 1] = ((Excel.Range)table.Range[r, c]).Value;
dataTable.Rows.Add(row);
}
So my question is, is there any Method (or fast way) in Excel interop to export table data to a DataTable class?
Thanks
You can read all values in the DataBodyRange of your table (a ListObject I deduce) at once, into a 1-based 2D object array, like so:
var theValues = table.DataBodyRange.Value;
It's then just a matter of scanning this array.
The goal of this piece of code is to get each DataGridViewRow THAT CONTAINS DATA as a separate element in the List. The problem is that empty rows are being recorded as well.
foreach (DataGridViewRow row in dataGridView1.Rows)
{
List<int> rowtemp = new List<int>();
foreach (DataGridViewCell cell in row.Cells)
{
if (cell.Value!=null && cell.Value.ToString().Length > 0)//empty cells are passing this check. Why?
{
if (Int32.TryParse(cell.Value.ToString(), out v) == true)
rowtemp.Add(v);
else
ErrorLog("Value must be single number in each cell. It is: " + cell.Value.ToString());
}
}
xmlParse(rowtemp);
}
I'm using epplus to read an excel file, I want to loop through each rows and each column and look for the column header to check against a collection and read the cell value if it matches. I'm new to epplus and couldn't find any reference to do something like this. I have looked into the similar question in this link, but I don't have something that loops through column headers.
Is there a possibility for doing this? Any help is much appreciated.
Thanks!
If you want to find a column in the Excel file that matches the name you specify you can use this function:
public string FindColumnAddress(ExcelWorksheet sheet, string columnName)
{
int totalRows = sheet.Dimension.End.Row;
int totalCols = sheet.Dimension.End.Column;
var range = sheet.Cells[1, 1, 1, totalCols];
for (int i = 1; i <= totalCols; i++)
{
if (range[1, i].Address != "" && range[1, i].Value != null && range[1, i].Value.ToString() == columnName)
return range[1, i].Address;
}
return null;
}
It will return the address of the column header.
You can change it to return i as the index of the column.
Or if you prefer a solution using Linq:
/// <summary>
/// Get 1 based column number of first column with 'columnName' as column header
/// </summary>
/// <param name="sheet"></param>
/// <param name="columnName">Column name to find</param>
/// <returns>1 based column number if found or null if column not found</returns>
public int? FindColumnAddress(ExcelWorksheet sheet, string columnName)
{
int totalCols = sheet.Dimension.End.Column;
var header = sheet.Cells[1, 1, 1, totalCols].ToList();
var idx = header.IndexOf(header.FirstOrDefault(hdritm => hdritm.Text == columnName));
return idx < 0 ? (int?)null : idx + 1;
}
Note: If you are retrieving many column header locations, you might want to generate the "header" list and then use the Linq query to retrieve each column number w/o having to rebuild the list for every search.
I found suggestion to use IndexOf here:
Get List<> element position in c# using LINQ
I am using TextFielParse to parse through a CSV file with 10 columns and 100 rows.
I am interested in first and 3rd column of each row.
How do I skip once the 3rd column is processed and move to the next row to process?
Currently it is going through all the 10 columns
using (TextFieldParser parser = new TextFieldParser(#"c:\20140513_134709.csv"))
{
parser.TextFieldType = FieldType.Delimited;
parser.SetDelimiters(",");
parser.ReadLine();
int regSeqNo = 0;
bool isNumerical = false;
string mailDate = string.Empty;
while (!parser.EndOfData)
{
//Processing row
string[] fields = parser.ReadFields();
foreach (string field in fields)
{
isNumerical = int.TryParse(fields[0].ToString(), out regSeqNo);
mailDate = fields[2].ToString();
continue;
}
}
}
You can use following code to get the required
while (!parser.EndOfData)
{
//Processing row
string[] fields = parser.ReadFields();
isNumerical = int.TryParse(fields[0].ToString(), out regSeqNo);
mailDate = fields[2].ToString();
}
Inner loop is not required :)
I have a DataTable like this
Col1 Col2 Col3 col4
GRPs 2009 69952.4 a
GRPs 2010 58949.8 a
GRPs 2009 37251.2 b
GRPs 2010 35433.9 b
GRPs 2009 28039.2 c
GRPs 2010 35079.4 c
SOC 2009 69952.4 a
SOC 2010 58949.8 a
SOC 2009 37251.2 b
SOC 2010 35433.9 b
SOC 2009 28039.2 c
SOC 2010 35079.4 c
And I need a to "transform" it to a excel file using OpenXML with this format
A B C D E F G H I
1 2009 2010 2009 2010 2009 2010
2 GRPs 69952.4 58949.8 37251.2 35433.9 28039.2 35079.4
3 SOC 69952.4 58949.8 37251.2 35433.9 28039.2 35079.4
Thanks in advance
It goes a little like this (sorry this isn't the complete code but it should help):
//Column headers
static string[] headerColumns = new string[] { "A", "B", "C" };
//Used for header column counting
static string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
foreach (char c in alphabet.Split(alphabet[dt.Columns.Count])[0])
headerColumns[alphabet.IndexOf(c)] = c.ToString();
//Loops through the data table and appends the data rows onto sheet data
for (int r = 0; r < dt.Rows.Count; r++)
{
//Builds a list of values from the data row
List<string> values = new List<string>();
for (int i = 0; i < dt.Columns.Count; i++)
values.Add(dt.Rows[r][i].ToString());
//Creates a spreadsheet row from the list of values
Spreadsheet.Row contentRow = CreateContentRow(values, r + 2);
//Appends the row to the sheetData
sheetData.AppendChild(contentRow);
}
private static Spreadsheet.Row CreateContentRow(List<string> values, int index)
{
//Create the new row.
Spreadsheet.Row r = new Spreadsheet.Row();
r.RowIndex = (UInt32)index;
//Create the cells that contain the data.
for (int i = 0; i < headerColumns.Length; i++)
{
Spreadsheet.Cell c = new Spreadsheet.Cell();
c.CellReference = headerColumns[i] + index;
Spreadsheet.CellValue v = new Spreadsheet.CellValue();
v.Text = values[i];
c.AppendChild(v);
r.AppendChild(c);
}
return r;
}