populate datatable with arrays of strings - c#

How do i populate this dataTable with array of strings? Im using this template but i can only add data hardcoded... I have an string[]values which contains my data and that should be added to the datatable. I think its quite easy but i don't see it. i've been trying to loop through it but that doens't seem to work? Think im missing a crucial step.
I've created a my datatable here :
DataTable dt = new DataTable() { TableName = "MBR" };
Adding the columns to it
string[] columns = new string [l];
for (int i = 0; i < l; i++)
{
columns[i] = tags[i];
}
for (int i = 0; i < timeStamps.Count(); i++)
{
foreach (var item in tagCollection)
{
if (timeStamps[i].Date == item.time)
{
Console.WriteLine(item.time + " " + item.name );
}
}
}
dt.Columns.AddRange(columns.Select(c => new DataColumn(c.ToString())).ToArray());
And this i used in the template my collegue is working with and we need to provide the data here
var rows = new string[][]
{
new string[] {"1", "2", "false" },
new string[] { "test", "10000", "19.9" },
};
foreach (var row in rows)
{
dt.Rows.Add(row);
}
//Convert datatable to dataset and add it to the workbook as worksheet
ds.Tables.Add(dt);
workbook.Worksheets.Add(ds);
I've got many columns like 500+. And i need to add to each column a piece of data which i get from my string[]. which can contains 10 or 500+ records it depends. I need to add each record to a row. My columns are already working in this thing. I just need a way to add multiple Arrays to the table

This works for me:
DataTable dt = new DataTable() { TableName = "MBR" };
dt.Columns.Add(new DataColumn("A", typeof(string)));
dt.Columns.Add(new DataColumn("B", typeof(string)));
dt.Columns.Add(new DataColumn("C", typeof(string)));
var rows = new string[][]
{
new string[] {"1", "2", "false" },
new string[] { "test", "10000", "19.9" },
};
foreach (var row in rows)
{
dt.Rows.Add(row);
}
That gives me:

Here's how you might fill a datatable from a file of people:
var people = new DataTable();
people.Columns.Add("Name");//string
people.Columns.Add("Age", typeof(int));
people.Columns.Add("HireDate", typeof(DateTime));
people.Columns.Add("IsManager", typeof(bool));
foreach(var line in File.ReadLines("people.csv")){
var bits = line.Split(',');
dt.Rows.Add(new object[]{
bits[0], //Name
int.Parse(bits[1]), //Age
DateTime.Parse(bits[2]), //HireDate
bool.Parse(bits[3]) //IsManager
});
}
It would, of course, be preferable to use some library like Csvhelper if you're reading from a CSV - it can read into DataTables directly and is a lot more sophisticated than this example. This is just to show the process of "make a datatable, add columns, add rows by providing values for columns"
It would be better to create a strongly typed datatable for this:
Add a new DataSet type of file to your project and goive it a good name
Open it, right click the surface, choose Add DataTable, give it a sensible name
Right click the table, choose Add Column .. add a column and set its name, data type, default value etc...
Repeat until all columns are done
Using this in your code is mostly the same as above, except you make an instance of the table. It is an inner class so you create it using the name of the dataset too:
var dt = new YourDataSetNameHere.YourDataTableNameHere_DataTable();
//the columns are already added, you don't need to add them
foreach(var line in ...){
...
dt.Add_YourDataTableNameHere_Row(
bits[0], //Name
int.Parse(bits[1]), //Age
DateTime.Parse(bits[2]), //HireDate
bool.Parse(bits[3]) //IsManager
);
}
They're a lot nicer to use than regular weakly typed datatables

Related

Remove some coma separated header values from a csv file and create a datatable from that csv in C#

I have a very big csv file like this (more than 12K rows) ;
Comment, DateTime Name, Age, Class, Place, --> these are the header columns
Good, 03/10/2022, John, 12, 3, UK,
Bad, 12/10/2022, Tom, 15, 2, US
This is a generalized example which shows column names. But it will be more than this columns some times.
I am reading it as shown below
List<string> lines = File.ReadAllLines(System.IO.Path.ChangeExtension(FileNameWithPath, ".csv")).ToList();
I need a datatable from the above mentioned csv file but i DO NOT want Comment and Place columns in the datatable.
Can anybody show me how we can achieve this ?
Column datatypes :
DateTime --> typeof(datetime)
Name --> typeof(string)
Age --> typeof(double?)
Class --> typeof(int)
You can remove the columns using DataColumnCollection.Remove() after converting from the list to a datatable.
dt.Remove("Comments")
public static DataTable CSVtoDataTable(string filePath)
{
DataTable dtData = new DataTable();
using (StreamReader sReader = new StreamReader(filePath))
{
string[] columnHeader = sReader.ReadLine().Split(',');
foreach (string header in columnHeader)
{
dtData.Columns.Add(header);
}
while (!sReader.EndOfStream)
{
string[] rows = sReader.ReadLine().Split(',');
DataRow drRow = dtData.NewRow();
for (int i = 0; i < columnHeader.Length; i++)
{
drRow[i] = rows[i];
}
dtData.Rows.Add(drRow);
}
}
dtData.Columns.Remove("Comment");
dtData.Columns.Remove("Place");
return dtData;
}

Remove all columns from datatable except for 25

I have 500 Columns in my DataTable and I want to remove all of them except for 25 columns.
Is there any way to do this faster to save time and lines of code?
This is what I already tried:
private static void DeleteUselessColumns()
{
//This is example data!
List<DataColumn> dataColumnsToDelete = new List<DataColumn>();
DataTable bigData = new DataTable();
bigData.Columns.Add("Harry");
bigData.Columns.Add("Konstantin");
bigData.Columns.Add("George");
bigData.Columns.Add("Gabriel");
bigData.Columns.Add("Oscar");
bigData.Columns.Add("Muhammad");
bigData.Columns.Add("Emily");
bigData.Columns.Add("Olivia");
bigData.Columns.Add("Isla");
List<string> columnsToKeep = new List<string>();
columnsToKeep.Add("Isla");
columnsToKeep.Add("Oscar");
columnsToKeep.Add("Konstantin");
columnsToKeep.Add("Gabriel");
//This is the code i want to optimize------
foreach (DataColumn column in bigData.Columns)
{
bool keepColumn = false;
foreach (string s in columnsToKeep)
{
if (column.ColumnName.Equals(s))
{
keepColumn = true;
}
}
if (!keepColumn)
{
dataColumnsToDelete.Add(column);
}
}
foreach(DataColumn dataColumn in dataColumnsToDelete)
{
bigData.Columns.Remove(dataColumn);
}
//------------------------
}
var columnsToKeep = new List<string>() { "Isla", "Oscar", "Konstantin", "Gabriel"};
var toRemove = new List<DataColumn>();
foreach(DataColumn column in bigData.Columns)
{
if (!columnsToKeep.Any(name => column.ColumnName == name ))
{
toRemove.Add(column);
}
}
toRemove.ForEach(col => bigData.Columns.Remove(col));
Test1...test9 same code could be made a loop. No need to add the columns to delete in a list, just delete them in the first while loop. As for performance, not sure how to improve it.
You could try to use a DataView that selects the desired columns then copy to table. You need to experiment.
if they have different names create an array of string
var columns = new string[] { "Harry", "Konstantin","John"};
var columnsToKeep = new string[] { "John", "Konstantin"};
var columnsToDelete = from item in columns
where !columnsToKeep.Contains(item)
select item;
or using lambda
var columnsToDelete = columns
.Where (i=> !columnsToKeep.Contains(i))
.ToList();
toDelete
Harry

How to melt a DataTable in C# .NET (wide to long format)?

How to melt a DataTable in C# (wide to long format) as Python Pandas.melt does? https://pandas.pydata.org/docs/reference/api/pandas.melt.html
Is there any method already implemented? If not, how the code for melting a DataTable would
For example:
I have one DataTable which is in wide format, that is that has one row per id and has as many columns as variables. I would like to transform this DataTable to long format that has as many rows as combinations of id with each variable column. You can see this example in top image.
Please, if there is not clear enough visit Pandas documentation, there is more clear. (https://pandas.pydata.org/docs/reference/api/pandas.melt.html)
Note: I would like a solution that is DataTable independent, that is, that the solution is able to take parameters as id_vars, value_vars, etc... like Pandas.melt does
Any help is appreciated.
I don't know that Melt method but according to docs it seems to be an unpivot method:
public static DataTable MeltTable(DataTable inputTable, string outputColumn, params string[] unpivotColumns)
{
DataTable resultTable = new DataTable();
DataColumn col = new DataColumn(outputColumn, inputTable.Columns[outputColumn].DataType);
resultTable.Columns.Add(col);
resultTable.Columns.Add("Variable");
resultTable.Columns.Add("Value");
foreach(string unpivotColumn in unpivotColumns)
{
foreach (DataRow row in inputTable.Rows)
{
resultTable.Rows.Add(row[outputColumn], unpivotColumn, row[unpivotColumn]);
}
}
return resultTable;
}
You use it in this way:
DataTable table = new DataTable();
table.Columns.Add("Name");
table.Columns.Add("Course");
table.Columns.Add("Age", typeof(int));
table.Rows.Add("Tim", "Masters", 47);
table.Rows.Add("Bob", "Graduate", 19);
table.Rows.Add("Sheila", "Graduate", 20);
DataTable resultTable = MeltTable(table, "Name", "Course", "Age");
Result:
Name Variable Value
Tim Course Masters
Bob Course Graduate
Sheila Course Graduate
Tim Age 47
Bob Age 19
Sheila Age 20
#TimSchmelter gave me the answer but I modified a little bit to be a more general solution. Here's the code:
public static List<string> GetDifferenceColumns(DataTable dt, List<string> diffCols)
{
string[] columns = GetColumnsList(dt).ToArray();
IEnumerable<string> differenceColumns = from column in columns.Except(diffCols.ToArray()) select column;
return differenceColumns.ToList();
}
public static DataTable Melt(DataTable dt, List<string> idCols = null, List<string> varCols = null)
{
string errorPrefixString = "Error in DataProcessing Melt Method:\n";
bool varsColsIsNull = (varCols == null || varCols.Count == 0);
bool idColsIsNull = (idCols == null || idCols.Count == 0);
string varsName = "Variable";
string valueName = "Value";
if (dt.Rows.Count == 0)
{
throw new Exception(errorPrefixString + "DataTable is empty");
}
if (varsColsIsNull && varsColsIsNull)
{
throw new Exception(errorPrefixString+"You should past at least varCols or idCols");
}
if (varsColsIsNull)
{
varCols = GetDifferenceColumns(dt, idCols);
}
if (idColsIsNull)
{
idCols = GetDifferenceColumns(dt, varCols);
}
DataTable resultTable = new DataTable();
// Creating final columns of resultTable
foreach (string id in idCols)
{
resultTable.Columns.Add(id);
}
resultTable.Columns.Add(varsName);
resultTable.Columns.Add(valueName);
// Populating resultTable with the new rows
// generated by unpivoting varCols
foreach (string varCol in varCols)
{
foreach (DataRow row in dt.Rows)
{
DataRow resultRow = resultTable.NewRow();
foreach(string id in idCols)
{
resultRow[id] = row[id]; // create id cols
}
resultRow[varsName] = varCol;
resultRow[valueName] = row[varCol];
resultTable.Rows.Add(resultRow);
}
}
return resultTable;
}
How to use it:
DataTable dt = new DataTable();
dt.Columns.Add("Name");
dt.Columns.Add("Course");
dt.Columns.Add("Age");
dt.Rows.Add("Tim", "Masters", 47);
dt.Rows.Add("Bob", "Graduate", 19);
dt.Rows.Add("Sheila", "Graduate", 20);
List<string> varCols = new List<string> { "Course", "Age" };
DataTable finalDataTable = Melt(dt, varCols: varCols);

Brackets To each Line of Data in a foreach loop

My problem is that i have a foreach loop that saves every row of data into a List and then creates a TXT from the list, the problem is that my data is saved into the TXT in this form:
["ROW1","DATA1","DATA2","DATA3","ROW2","DATA4","DATA5","DATA6"]
And i want to make my txt to have the data like this:
[["ROW1","DATA1","DATA2","DATA3"],["ROW2","DATA4","DATA5","DATA6"]]
Getting each row into a separate aditional brackets brackets("[]"), how can i do this without using another List?
This is my Foreach Loop:
List<string> listaprocedure = new List<string>();
foreach (DataRow dato in myTable.Rows)
{
foreach (DataColumn datoC in myTable.Columns)
{
listaprocedure.Add(dato[datoC].ToString());
}
}
json4 = JsonConvert.SerializeObject(procedimiento2);
System.IO.File.WriteAllText(#"C:\procedure.txt", json4);
You can manually iterate through rows, writing each one as you have read it, then add , after it (except last row). Plus add [ and ] at the beginning and end.
Quite ugly, but can help if you deal with really big table.
But the best option is to populate List<List<string>> (or string[,]).
Anyway here is working example:
using (var reader = File.CreateText("C:\\procedure.txt"))
{
// Starting outer json array
reader.WriteLine("[");
for (var rowIndex = 0; rowIndex < myTable.Rows.Count; rowIndex++)
{
var row = myTable.Rows[rowIndex];
var rowValues = new List<string>(); // can be reused if needed
foreach (DataColumn column in myTable.Columns)
rowValues.Add(row[column].ToString());
var jsonRow = JsonConvert.SerializeObject(rowValues);
// Write current row
reader.Write(jsonRow);
// Add separating comma
if (rowIndex != myTable.Rows.Count - 1)
reader.WriteLine(",");
}
// End outer json array
reader.WriteLine("]");
}
Given your sample data, this works:
var query =
from dr in myTable.Rows.OfType<DataRow>()
from dc in myTable.Columns.OfType<DataColumn>()
group dr[dc].ToString() by dc.Ordinal / 4;
var json4 = JsonConvert.SerializeObject(query);
This gives me:
[["ROW1","DATA1","DATA2","DATA3"],["ROW2","DATA4","DATA5","DATA6"]]
I used this code to initialize my data:
var myTable = new DataTable();
myTable.Columns.Add("A1", typeof(string));
myTable.Columns.Add("A2", typeof(string));
myTable.Columns.Add("A3", typeof(string));
myTable.Columns.Add("A4", typeof(string));
myTable.Columns.Add("B1", typeof(string));
myTable.Columns.Add("B2", typeof(string));
myTable.Columns.Add("B3", typeof(string));
myTable.Columns.Add("B4", typeof(string));
myTable.Rows.Add("ROW1", "DATA1", "DATA2", "DATA3", "ROW2", "DATA4", "DATA5", "DATA6");

Adding data to datatable using object[] not working?

The Add method for a DataTable contains an overload for adding data to a table using an object array.
I would like to have an array of arrays, which I can loop through and insert into the DataTable. The code below creates an array of size 4000 and puts an array of 4 "columns" into the 0th element of the outer array (ContiguousTradeMem).
However, when I debug the last line below all the data which was in testObject (and in the cache- ContiguousTradeMem[]) does not get copied over to the DataTable()???
//The "array" which we wish to insert into the DataTable
object[] testObject = new object[4];
//Inserts some test data
for (int m = 0; m < 4; m++)
{
testObject[m] = "test";
}
//A test DataTable
DataTable test = new DataTable();
test.Columns.Add("Col1");
test.Columns.Add("Col2");
test.Columns.Add("Col3");
test.Columns.Add("Col4");
//Put the test "array" into the cache
ContiguousTradeMem[0] = testObject; //The data of testObject is fine here
//Write the cache element to the DataTable
test.Rows.Add(ContiguousTradeMem[0]); //The data is not fine in test.Rows
Actually the overload of DatarowCollection.Add takes a param array which is similar to a list of paramaters. You can initialize and add the DataRow from your array in this way:
var row = test.NewRow();
row.ItemArray = (Object[])ContiguousTradeMem[0];
test.Rows.Add(row);
params C#
test.Rows.Add adds existing DataRow object to your table. First you have to create new row, then fill it with your data, and after that - add it to your data table. Here is the code in VB, it is easy, so you will be able to translate it to C# :)
Dim t As New DataTable
Dim r As DataRow
r = t.NewRow()
r.ItemArray = testObject
t.Rows.Add(r)
I think you are trying to add 4 rows(array) to 4 columned table.
It should be logically:
DataRow newRow = test.NewRow();
newRow [0] = testObject[0];
newRow [1] = testObject[1];
newRow [2] = testObject[2];
newRow [4] = testObject[3];
test.Rows.Add(newRow );
You can also pass in an object array as well, like so:
DataTable dt = new DataTable();
dt.Clear();
dt.Columns.Add("Name");
dt.Columns.Add("Marks");
object[] o = { "Ravi", 500 };
dt.Rows.Add(o);
Or even:
dt.Rows.Add(new object[] { "Ravi", 500 });

Categories

Resources