I have a DataTable from which I would like to loop through each row and column and then select a value from a specific column depending on the other values in the columns/each row.
My code currently looks like this:
foreach (DataRow drow in dt.Rows)
{
foreach (DataColumn dcol in dt.Columns)
{
foreach (var Item in ImportData)
{
if (Item.Value.Equals(true))
{
if (Item.Key.Equals("" + dcol))
{
string value = drow[dcol].ToString();
if (value.Equals("X"))
{
outDraws += drow["Drawing"].ToString();
outDraws += "\n";
}
}
}
}
}
}
ImportData is a Dictionary<string, bool>, which holds the data that I want to compare with my DataTable.
string outDraws is just a string which should hold the content of the drawings I want to print out.
My problem now is that I only want to print out the content in the column 'Drawing' of the row where all columns with the same name as the Keys in ImportData have 'X' as value. At the moment I'm getting all the rows where any of the columns have 'X' as value and has the same name as any Key in ImportData.
I understand that it will be quite hard for you to get what I want to do but please ask if you need any more information and I will try to provide.
Many thanks in advance.
Edit:
ImportData contains the name of different products as keys. These products have either been selected or not by the customer through another program, if they have been selected they have the value true and if not selected they have the value false.
With the method presented above I would like to compare ALL the keys that have the value true with the column names in the DataTable. If the column name corresponds to the key in ImportData (which is the name of a product) then I want to check if that column in a specific row has 'X' as value.
This goes on for ALL the keys in ImportData and in the end I should know which row in the DataTable that has an 'X' in all the columns with the same name as the keys in ImportData. For this row I would like to get the content of the column called 'Drawing'.
So for an example say that ImportData contains:
[Motor, true][Product6, true][Product7, true]
Then I would like to print out the column Drawing at row 6.
Unfortunately I can't post pictures..
As with any problem: divide and conquer. Break down your problem in smaller pieces and go from there.
From what I understand, you want to do something with certain rows from the datatable. Something like:
foreach (var drow in dt.Rows.OfType<DataRow>())
{
if (SomeConditionIsMet(dt, drow, ImportData))
{
outDraws += drow["Drawing"].ToString();
outDraws += "\n";
}
}
The function SomeConditionIsMetcould looks like this:
private static bool SomeConditionIsMet(
DataTable dt, DataRow drow,
IDictionary<string, bool> importData)
{
// TODO if the condition is met, return true
// otherwise, return false
}
Now your problem is simplified to thinking about what it means that 'Some condition is met'. Once you can clearly express that in words, rename the function to reflect that (e.g. to 'AllColumnsAreChecked')
Here's a sample with solution as I understand it:
internal class Program
{
private static void Main(string[] args)
{
var importData = new Dictionary<string, bool>()
{
{"Product1", true},
{"Product2", false},
{"Product3", true},
};
var dt = new DataTable();
dt.Columns.Add("Product1");
dt.Columns.Add("Product2");
dt.Columns.Add("Product3");
dt.Columns.Add("Product4");
dt.Columns.Add("Drawing");
// row1 should be added
var row1 = dt.NewRow();
row1["Product1"] = "X";
row1["Product3"] = "X";
row1["Drawing"] = "Drawing1";
dt.Rows.Add(row1);
// row2 should not be added
var row2 = dt.NewRow();
row2["Product1"] = "X";
row2["Drawing"] = "Drawing2";
dt.Rows.Add(row2);
string outDraws = string.Empty;
foreach (DataRow drow in dt.Rows.OfType<DataRow>())
{
if (AllColumnsAreChecked(drow, importData))
{
outDraws += drow["Drawing"].ToString();
outDraws += "\n";
}
}
Console.WriteLine(outDraws);
}
private static bool AllColumnsAreChecked(DataRow drow, Dictionary<string, bool> importData)
{
foreach (var key in importData.Keys)
{
if (!importData[key])
continue;
var value = drow[key] as string;
if (value != "X")
return false;
}
}
}
Bonus: here's a LINQ based implementation of the check:
private static bool AllColumnsAreChecked(DataRow drow, Dictionary<string, bool> importData)
{
return importData.Keys
.Where(k => importData.ContainsKey(k) && importData[k]) // the field must be enabled in importData
.All(k => (drow[k] as string) == "X"); // the corresponding value in the row must be 'X'
}
Try this
DataTable tbl = new DataTable();
foreach (DataRow row in tbl.Rows)
{
object cellData = row["colName"];
}
Related
I want to compare two list of row data. Right now I want to see if the two list contain the same title in their respective cell values.
What methods with using Smartsheet API C# could I use to sort through the list and compare each select element in each row?
I already have a column name table to search for the column name and reference the actual column id. But I can not seem to fathom how?
Any input would be helpful and I'm sorry if I sound plain dumb but I usually do not ask for help.
I have two sheets in Smartsheet. One sheet contains all the data that is given and as it goes through a process of acceptance or rejection. If completely accepted it is given a status of "Moved to Project". When the code runs it will place all rows with that status to a List that will then be used to move and compare against other list.
The Moved to Project List will be compared to our Project Management Active List.
I am stuck at trying to compare cell values through the API and maybe I'm just looking at it wrong. I've tried Enum Except to compare list but it is not working and I'm thinking I will need to create a nested loop to sort through and compare each element.
foreach (Row row in rowsToCompare)
{
Cell PMOPName = getPMOCellByColumnName(row, "Project Name");
foreach (Row innerrow in rowsToMove)
{
Cell MainTitle = getCellByColumnName(innerrow, "Title");
if (PMOPName.DisplayValue == MainTitle.DisplayValue)
{
Console.WriteLine("Yes");
}
else
Console.WriteLine("No");
}
}
static Cell getCellByColumnName(Row row, string columnName)
{
return row.Cells.FirstOrDefault(cell => cell.ColumnId ==
columnMap[columnName]);
}
static Cell getPMOCellByColumnName(Row row, string columnName)
{
return row.Cells.FirstOrDefault(cell => cell.ColumnId ==
columnMapPMO[columnName]);
}
}
Whenever there is a match of title and project name it should output yes and if not a no.
But instead I get a Unhandled Exception: System.ArgumentNullException: Value cannot be null.
I've pinpointed it to the nested loop. I'm sure I just did something stupid.
EDIT:
So this is the definition of the map and how it get it's data.
static Dictionary<string, long> columnMap = new Dictionary<string, long>();
static Dictionary<string, long> columnMapPMO = new Dictionary<string,
long();
// Build column map for later reference
foreach (Column column in sheet.Columns)
columnMap.Add(column.Title, (long)column.Id);
foreach (Column column in pmosheet.Columns)
columnMapPMO.Add(column.Title, (long)column.Id);
EDIT 2: Confirming with Tim the code works but in my instance it is still coming up with an error so I will place the code that I currently have as a whole to see if possible the other functions could be causing issues.
static void Main(string[] args)
{
SmartsheetClient ss = new SmartsheetBuilder()
// TODO: Set your API access in environment variable
SMARTSHEET_ACCESS_TOKEN or else here
.SetAccessToken(token.AccessToken)
.Build();
var sheet = ss.SheetResources.GetSheet(
sheetId, // long sheetId
null, // IEnumerable<SheetLevelInclusion>
includes
null, // IEnumerable<SheetLevelExclusion>
excludes
null, // IEnumerable<long> rowIds
null, // IEnumerable<int> rowNumbers
null, // IEnumerable<long> columnIds
null, // Nullable<long> pageSize
null // Nullable<long> page
);
var pmosheet = ss.SheetResources.GetSheet(
copyId,
null,
null,
null,
null,
null,
null,
null
);
// Build column map for later reference
foreach (Column column in sheet.Columns)
columnMap.Add(column.Title, (long)column.Id);
foreach (Column column in pmosheet.Columns)
columnMapPMO.Add(column.Title, (long)column.Id);
// Accumulate rows needing update and archive here
List<Row> rowsToMove = new List<Row>();
List<Row> rowsToArchive = new List<Row>();
List<Row> rowsToCompare = new List<Row>();
//Loops through the Ideation Sheet and execute function to evaluate
//each row and add those row to the move list.
foreach (Row row in sheet.Rows)
{
Row rowToMove = evaluateRowAndBuildUpdates(row);
if (rowToMove != null)
{
rowsToMove.Add(rowToMove);
}
}
Console.WriteLine("\n");
foreach (Row row in pmosheet.Rows)
{
Row rowtoCompare = compareRowandCopy(row);
if (rowtoCompare != null)
rowsToCompare.Add(rowtoCompare);
}
Console.WriteLine("\n");
foreach (Row innerrow in rowsToMove)
{
Cell MainTitle = getCellByColumnName(innerrow, "Title");
foreach (Row row in rowsToCompare)
{
Cell PMOPName = getPMOCellByColumnName(row, "Project Name");
if (PMOPName.DisplayValue == MainTitle.DisplayValue)
{
Console.WriteLine("Yes");
break;
}
else
Console.WriteLine("No");
}
}
System.Environment.Exit(1); //End of Program
}
static Row evaluateRowAndBuildUpdates(Row sourceRow)
{
Row rowToUpdate = null;
// Find cell we want to examine
Cell statusCell = getCellByColumnName(sourceRow, "Status");
if (statusCell.DisplayValue == "Moved to Project")
{
Cell remainingCell = getCellByColumnName(sourceRow, "Status");
Cell titleCell = getCellByColumnName(sourceRow, "Title");
if (remainingCell.DisplayValue == "Moved to Project")
{
rowToUpdate = new Row
{
Id = sourceRow.Id,
};
Console.WriteLine("Ideation");
}
Console.WriteLine(titleCell.DisplayValue + " ID: " +
sourceRow.Id.ToString());
}
return rowToUpdate;
}
static Row compareRowandCopy(Row sourceRow)
{
Row rowToCopy = null;
Cell pmoStatusCell = getPMOCellByColumnName(sourceRow, "Project
Name");
if (pmoStatusCell.DisplayValue != null)
{
rowToCopy = new Row
{
Id = sourceRow.Id,
};
}
Console.WriteLine("PMO");
Console.WriteLine(pmoStatusCell.DisplayValue + " ID: " +
sourceRow.Id.ToString());
return rowToCopy;
}
static Cell getCellByColumnName(Row row, string columnName)
{
return row.Cells.FirstOrDefault(cell => cell.ColumnId ==
columnMap[columnName]);
}
static Cell getPMOCellByColumnName(Row row, string columnName)
{
return row.Cells.FirstOrDefault(cell => cell.ColumnId ==
columnMapPMO[columnName]);
}
Ok, I have two sheets, the project sheet looks like this:
And the job sheet containing the rows to be inserted looks like this:
Here is the code:
using System;
using System.Collections.Generic;
// Add nuget reference to smartsheet-csharp-sdk (https://www.nuget.org/packages/smartsheet-csharp-sdk/)
using Smartsheet.Api;
using Smartsheet.Api.Models;
using System.Linq;
namespace sdk_csharp_sample
{
class Program
{
static Dictionary<string, long> columnMap = new Dictionary<string, long>();
static Dictionary<string, long> columnMapPMO = new Dictionary<string, long>();
static void Main(string[] args)
{
// Initialize client
SmartsheetClient ss = new SmartsheetBuilder()
.SetHttpClient(new RetryHttpClient())
.Build();
heet insert = ss.SheetResources.GetSheet(...148L, null, null, null, null, null, null, null);
Sheet pmosheet = ss.SheetResources.GetSheet(...556L, null, null, null, null, null, null, null);
// Build column map for later reference
foreach (Column column in insert.Columns)
columnMap.Add(column.Title, (long)column.Id);
foreach (Column column in pmosheet.Columns)
columnMapPMO.Add(column.Title, (long)column.Id);
IList<Row> rowsToCompare = pmosheet.Rows;
IList<Row> rowsToMove = insert.Rows;
foreach (Row innerrow in rowsToMove)
{
Cell MainTitle = getCellByColumnName(innerrow, "Title");
foreach (Row row in rowsToCompare)
{
Cell PMOPName = getPMOCellByColumnName(row, "Project Name");
if (PMOPName.DisplayValue == MainTitle.DisplayValue)
{
Console.WriteLine("Yes");
break;
}
else
Console.WriteLine("No");
}
}
}
static Cell getCellByColumnName(Row row, string columnName)
{
return row.Cells.FirstOrDefault(cell => cell.ColumnId ==
columnMap[columnName]);
}
static Cell getPMOCellByColumnName(Row row, string columnName)
{
return row.Cells.FirstOrDefault(cell => cell.ColumnId ==
columnMapPMO[columnName]);
}
}
}
As just a nit I modified the order of the loops so that the rows to be added forms the outer loop (assuming there are projects that may not have corresponding line items to insert that don't need to be looked at), and when I find my match for projects I exit the inner loop.
The output looks like this:
I do get all the way through the test, so it seems like your code does the trick. Maybe simplify your sample inputs so that you can verify that you get what you want. That might also tell us if it is a data driven issue.
I'm trying to link data from my db (sqlite) to my textboxes, but I don't know exactly how...
Here's what i'm trying:
private void btnUpdate_Click(object sender, EventArgs e)
{
con.Open();
adapter = new SQLiteDataAdapter("SELECT PRECO_PRODUTO FROM INGREDIENTES WHERE NOME_PRODUTO='"+listProdutos.SelectedIndex+"'", con);
adapter.Fill(populate);
List<DataTable> precoIng = new List<DataTable>();
precoIng.Add(populate.Tables[0]);
con.Close();
tbPrecoProduto.Text = precoIng[0]; //error here
}
I think I need a way to convert the SQLiteDataTable to a string? I'm new on db stuffs. This is my table and this is my form design, if helps...
It seems as if you're trying to set the text of the TextBox to a DataTable. This doesn't quite make sense, as the type DataTable isn't the same as a string. You'd first have to extract the data out of your table like that:
var builder = new StringBuilder ();
foreach (var rowObject in precoIng [0].Rows)
{
var row = (DataRow) rowObject;
var id = row ["ID_PRODUTO"].ToString ();
var name = row ["NOME_PRODUTO"].ToString ();
var price = row ["PRECO_PRODUTO"].ToString ();
var count = row ["QNT_PRODUTO"].ToString ();
builder.AppendLine ($"Id: {id}; Name: {name}; Price: {price}; Count: {count}");
}
tbPrecoProduto.Text = builder.ToString ();
You can of course shorten this if you only want for example the price:
var builder = new StringBuilder ();
foreach (var rowObject in precoIng [0].Rows)
{
var row = (DataRow) rowObject;
var price = row ["PRECO_PRODUTO"].ToString ();
builder.AppendLine (price);
}
tbPrecoProduto.Text = builder.ToString ();
And, btw, precoIng[0] will always be the same as populate.Tables[0].
Alternatively you could write an extension method like that:
public static string GetData (this DataTable table)
{
var builder = new StringBuilder ();
foreach (DataRow row in table.Rows)
foreach (DataColumn column in table.Columns)
builder.Append (column.ColumnName).Append (": ").Append (row [column]).Append ("; ");
return builder.ToString ();
}
And then call precoIng[0].GetData() to get the data as a string.
If you want to be able to filter the data to get printed, you could do something like this:
public static string GetData (this DataTable table, List <string> columns = null)
{
var builder = new StringBuilder ();
foreach (DataRow row in table.Rows)
if (columns == null)
foreach (DataColumn column in table.Columns)
builder.Append (column.ColumnName).Append (": ").Append (row [column]).Append ("; ");
else
foreach (var column in columns)
builder.Append (column).Append (": ").Append (row [column]).Append ("; ");
return builder.ToString ();
}
I do however feel as if you don't want the data of your whole table as a string, but rather want the data to certain ids or something. To help you with this, however, I'd need more precise information.
Ok, so it seems as if what you actually want is something like this:
var preco = precoIng.FirstOrDefault ()?.Rows.Cast <DataRow> ().FirstOrDefault ()? ["PRECO_PRODUTO"]?.ToString () ?? "";
I am here today trying to work out how I can do this. I have the code below to look through each column in a DataRow, but how can I access the key AND value? I want to assign it to a dictionary in the class but I can't seem to get both of them, the only way I can get anything is by calling:
var columnValue = playerDataRow[column];
Here is the full thing:
using (var mysqlConnection = Sirius.GetServer().GetDatabaseManager().GetConnection())
{
mysqlConnection.SetQuery("SELECT * FROM `users` WHERE `auth_ticket` = #authTicket LIMIT 1");
mysqlConnection.AddParameter("authTicket", authTicket);
var playerDataTable = mysqlConnection.GetTable();
foreach (DataRow playerDataRow in playerDataTable.Rows)
{
foreach (DataColumn column in playerDataTable.Columns)
{
var columnValue = playerDataRow[column];
}
}
}
foreach (DataRow playerDataRow in playerDataTable.Rows)
{
var myDic = new Dictionary<string, object>();
foreach (DataColumn column in playerDataTable.Columns)
{
myDic.Add(column.ColumnName, playerDataRow[column]);
}
}
the variable column will be the key and the value will be columnValue
looks that you only want one row of output - perhaps for this specific user based on auth_ticket
here is an example of how to get all values for this row into a Dictionary of strings (I'm converting all data to strings by the way just for this example)
var htRowValues = new Dictionary<string,string>();
using (var mysqlConnection = Sirius.GetServer().GetDatabaseManager().GetConnection())
{
mysqlConnection.SetQuery("SELECT * FROM `users` WHERE `auth_ticket` = #authTicket LIMIT 1");
mysqlConnection.AddParameter("authTicket", authTicket);
var playerDataTable = mysqlConnection.GetTable();
foreach (DataRow playerDataRow in playerDataTable.Rows)
{
foreach (DataColumn column in playerDataTable.Columns)
{
var columnValue = playerDataRow[column];
htRowValues[column.ColumnName]=System.Convert.ToString(columnValue);
}
}
}
now you have all column values in the dictionary for this one row of data.
I have the code below. To explain there will always be values for the 'tl' variable.
At the moment its hard coded to always assume 4 columns in the row, but I want to make it work based on the count of the columns and make it build the levels based on how many columns there are, but there also needs to be a value in the column.
So at the moment if there is a value in column 2, it will build the 'ltwo' variable, and then if there is a value in column 3 it does the 'lthree'.
I want to make it build as many levels as it needs to so im not repeating code and having the same code over and over.
public static List<AdditionalPropertyType> SQLAddPropsStructured(DataTable dataTable, List<AdditionalPropertyType> currentadditionalproperties)
{
foreach (DataRow row in dataTable.Rows)
{
var tl = new AdditionalPropertyType
{
Name = row[0].ToString(),
Value = row[1].ToString()
};
if (!String.IsNullOrEmpty(row[2].ToString()))
{
var ltwo = new AdditionalPropertyType
{
Name = row[2].ToString()
};
var ltwolist = new List<AdditionalPropertyType>();
ltwolist.Add(tl);
ltwo.AdditionalProperties = ltwolist;
if (!String.IsNullOrEmpty(row[3].ToString()))
{
var lthree = new AdditionalPropertyType
{
Name = row[3].ToString()
};
var lthreelist = new List<AdditionalPropertyType>();
lthreelist.Add(ltwo);
lthree.AdditionalProperties = lthreelist;
currentadditionalproperties.Insert(0, lthree);
}
else
currentadditionalproperties.Insert(0, ltwo);
}
else
currentadditionalproperties.Insert(0, tl);
}
return currentadditionalproperties;
}
You can get the columns using the Columns property of the DataTable:
foreach (DataRow row in dataTable.Rows)
{
foreach(DataColumn column in dataTable.Columns)
{
Trace.WriteLine(column.ColumnName + " = " + row[column]);
}
}
You probably want to do something like this: (written on the websites, some minor typos can be present)
You need to iterate the additional columns and check if there is a value present. When there is a value, create a backup reference and renew your property.
public static List<AdditionalPropertyType> SQLAddPropsStructured(DataTable dataTable, List<AdditionalPropertyType> currentadditionalproperties)
{
// check if there are atleast 2 columns defined
if(dataTable.Columns.Count < 2)
throw new Exception("At least two columns are required");
// The result
var currentadditionalproperties = new List<AdditionalPropertyType>();
// iterate the rows
foreach (DataRow row in dataTable.Rows)
{
// create the base property
var tl = new AdditionalPropertyType
{
Name = row[0].ToString(),
Value = row[1].ToString()
};
// check the rest of the columns for additional names
foreach(int index=2;index<dataTable.Columns.Count;index++)
{
var columnValue = row[index].ToString();
// if the column is empty, discontinue the iteration
if(String.IsNullOrEmpty(columnValue))
break;
// create a backup reference.
var previous = tl;
// create a new AdditionalPropertyType
var tl = new AdditionalPropertyType { Name = columnValue };
// Create the list
tl.AdditionalProperties = new List<AdditionalPropertyType>();
// add the previous (backup reference)
tl.AdditionalProperties.Add(previous);
}
// insert the 'chain' of additional properties on the list at possition 0
currentadditionalproperties.Insert(0, tl);
}
// return the list
return currentadditionalproperties;
}
The first step is to reverse your condition and make use of the keyword continue
public static List<AdditionalPropertyType> SQLAddPropsStructured(DataTable dataTable, List<AdditionalPropertyType> currentadditionalproperties)
{
foreach (DataRow row in dataTable.Rows)
{
var tl = new AdditionalPropertyType
{
Name = row[0].ToString(),
Value = row[1].ToString()
};
if (String.IsNullOrEmpty(row[2].ToString())){
currentadditionalproperties.Insert(0, tl);
continue;
}
var ltwo = new AdditionalPropertyType
{
Name = row[2].ToString()
};
var ltwolist = new List<AdditionalPropertyType>();
ltwolist.Add(tl);
ltwo.AdditionalProperties = ltwolist;
if (String.IsNullOrEmpty(row[3].ToString())) {
currentadditionalproperties.Insert(0, ltwo);
continue;
}
var lthree = new AdditionalPropertyType
{
Name = row[3].ToString()
};
var lthreelist = new List<AdditionalPropertyType>();
lthreelist.Add(ltwo);
lthree.AdditionalProperties = lthreelist;
currentadditionalproperties.Insert(0, lthree);
}
return currentadditionalproperties;
}
Now, the code is clearer. The next step is to collect the repeating cases. Note the second case onward is repeating. Thus, do further simplification:
public static List<AdditionalPropertyType> SQLAddPropsStructured(DataTable dataTable, List<AdditionalPropertyType> currentadditionalproperties)
{
foreach (DataRow row in dataTable.Rows)
{
var tlprev = new AdditionalPropertyType
{
Name = row[0].ToString(),
Value = row[1].ToString()
};
bool isTlUpdated = true;
for (int i = 2; i <= 3; ++i) { //change this according to your need
if (String.IsNullOrEmpty(row[i].ToString()) && isTlUpdated){
currentadditionalproperties.Insert(0, tlprev);
isTlUpdated = false;
break; //note that this will now change to break to break from the current for-loop
}
var lnext = new AdditionalPropertyType
{
Name = row[i].ToString()
};
var lnextlist = new List<AdditionalPropertyType>();
lnextlist.Add(tlprev);
lnext.AdditionalProperties = lnextlist;
tlprev = lnext; //need to record this for the next loop or end of the case
isTlUpdated = true;
}
if (isTlUpdated) //correction by Jeroen
currentadditionalproperties.Insert(0, tlprev);
}
return currentadditionalproperties;
}
The key is to simplify the code step-by-step
You haven't posted all your code, so I had to guess in a couple of places (such as what the "currentAdditionalProperties" does).
I think that the below code illustrates what you want to do by making the logic extendable depending on how many columns the data table has.
The trick is to just store the "last thing" in a variable, so it can be used for the "current thing". At the end, whatever was the "last thing" is what you want to store in your "currentAdditionalProperties" object. I have commented so you can see the logic.
private List<AdditionalPropertyType> SQLAddPropsStructured(DataTable dataTable)
{
AdditionalPropertyType lastNewType; // to remember the previous new instance
// for all rows...
foreach (DataRow row in dataTable.Rows)
{
// the first type takes name and value from the first two fields
AdditionalPropertyType newType = new AdditionalPropertyType();
newType.Name = row[0].ToString();
newType.Value = row[1].ToString();
// remember this type: it is used as the AdditionalProperties for the NEXT type
lastNewType = newType;
// additional types start from field 2
int field = 2;
// iterate until we find a NULL field.
// If you want to check for the end of the fields rather than a NULL value, then instead use:
// while(field < dataTable.Columns.Count)
while(!String.IsNullOrEmpty(row[field].ToString()))
{
// create new type
var newSubType = new AdditionalPropertyType();
// get name
Name = row[field].ToString();
// new type takes the PREVIOUS type as its additional parameters
List<AdditionalPropertyType> propertyData = new List<AdditionalPropertyType>();
propertyData.Add(lastNewType);
newSubType.AdditionalProperties = propertyData;
// remember THIS type for the NEXT type
lastNewType = newSubType;
// process next field (if valid)
field++;
}
// put the last set of properties found into the current properties
currentAdditionalProperties.Insert(0, lastNewType);
return currentAdditionalProperties;
}
}
I am importing data from csv file, sometimes there are column headers and some times not the customer chooses custom columns(from multiple drop downs)
my problem is I am able to change the columns type and name but when I want to import data row into cloned table it just adds rows but no data with in those rows. If I rename the column to old values it works, let's say column 0 name is 0 if I change that to something else which I need to it won't fill the row below with data but If I change zero to zero again it will any idea:
here is my coding:
#region Manipulate headers
DataTable tblCloned = new DataTable();
tblCloned = tblDataTable.Clone();
int i = 0;
foreach (string item in lstRecord)
{
if (item != "Date")
{
var m = tblDataTable.Columns[i].DataType;
tblCloned.Columns[i].DataType = typeof(System.String);
tblCloned.Columns[i].ColumnName = item;
}
else if(item == "Date")
{
//get the proper date format
//FillDateFormatToColumn(tblCloned);
tblCloned.Columns[i].DataType = typeof(DateTime);
tblCloned.Columns[i].ColumnName = item;
}
i++;
}
tblCloned.AcceptChanges();
foreach (DataRow row in tblDataTable.Rows)
{
tblCloned.ImportRow(row);
}
tblCloned.AcceptChanges();
#endregion
in the second foreach loop when it calls to import data to cloned table it adds empty rows.
After couple of tries I came up with this solution which is working:
foreach (DataRow row in tblDataTable.Rows)
{
int x = 0;
DataRow dr = tblCloned.NewRow();
foreach (DataColumn dt in tblCloned.Columns)
{
dr[x] = row[x];
x++;
}
tblCloned.Rows.Add(dr);
//tblCloned.ImportRow(row);
}
but I will accept Scottie's answer because it is less code after all.
Instead of
foreach (DataRow row in tblDataTable.Rows)
{
tblCloned.ImportRow(row);
}
try
foreach (DataRow row in tblDataTable.Rows)
{
tblCloned.LoadDataRow(row.ItemArray, true);
}