Adding array into datatable with limited columns - c#

I already know how to add array into datatable.
string[] months = {"Jan" , "Feb" , "Mar" , "Apr" , "Jun"};
DataTable dt = new DataTable();
dt.Columns.Add("M1");
dt.Columns.Add("M2");
dt.Columns.Add("M3");
dt.Columns.Add("M4");
dt.Columns.Add("M5");
DataRow row = dt.NewRow();
for (int i = 0; i < months.Length; i++)
{
row[i] = months[i];
}
dt.Rows.Add(row);
The above code perfectly works. But I have a different question. Lets assume I have an array of 8 values.
string[] arr = {"1","2","3","4","5","6","7","8"};
Now I have created a new datatable with 4 columns.
DataTable dt = new DataTable();
dt.Columns.Add("v1");
dt.Columns.Add("v2");
dt.Columns.Add("v3");
dt.Columns.Add("v4");
DataRow row = dt.NewRow();
Now I want to add the values of array in to columns like
arr[0] = v1
arr[1] = v2
arr[2] = v3
arr[3] = v4
arr[4] = v1
arr[5] = v2
arr[6] = v3
arr[7] = v4
Update 1
I have a function in which I want to perform all these actions
public string LoadAMIReadings(string startTS, string endTS, string batch, string divCode, string cc_code)
{
totalRec = 0;
processedRec = 0;
this.BATCH = batch;
this.DIVCODE = divCode;
this.CCCODE = cc_code;
this.FROMDATE = startTS;
this.TODATE = endTS;
HESservicesDoCommandRequest obj = new HESservicesDoCommandRequest();
DataTable dt = new DataTable();
dt.Columns.Add("Application_No", typeof(string));
dt.Columns.Add("REF_NO", typeof(string));
dt.Columns.Add("METER_SERIAL_NO", typeof(string));
dt.Columns.Add("XMETER_NO", typeof(string));
// here I want to call the modified solution
int rowCount = bill.Length / dt.Columns.Count; // array bill is declared globally with 7780 values in it
for (int rowIndex = 0; rowIndex < rowCount; rowIndex++)
{
DataRow row = dt.NewRow();
for (int columnIndex = 0; columnIndex < dt.Columns.Count; columnIndex++)
{
// In case of 2 rows:
// row 1: (0 * 4) + 0 = 0
// row 1: (0 * 4) + 1 = 1
// row 1: (0 * 4) + 2 = 2
// row 1: (0 * 4) + 3 = 3
// row 2: (1 * 4) + 0 = 4
// row 2: (1 * 4) + 1 = 5
// row 2: (1 * 4) + 2 = 6
// row 2: (1 * 4) + 3 = 7
row[columnIndex] = bill[(rowIndex * dt.Columns.Count) + columnIndex];
}
dt.Rows.Add(row);
}
if (dt != null && dt.Rows.Count > 0)
{
totalRec = dt.Rows.Count;
string ReqEnvPath = System.Configuration.ConfigurationManager.AppSettings["ReadEnvPath"].ToString();
XElement SoapReqEnv = XElement.Load(ReqEnvPath);
foreach (DataRow dr in dt.Rows)
{
string uniqueID = dr["APPLICATION_NO"].ToString();
string meterNo = dr["METER_SERIAL_NO"].ToString();
string timestamp = DateTime.UtcNow.ToString("o");
StringBuilder sbArg0 = new StringBuilder();
try
{
sbArg0.AppendFormat(#"<?xml version=""1.0"" encoding=""UTF-8"" ?> " + SoapReqEnv.ToString(), uniqueID, startTS, endTS, timestamp, this.HEXURL, this.HEXUID, this.HEXPWD);
Guid currentGuid = Guid.NewGuid();
obj.getResponseAsync(sbArg0.ToString(), currentGuid + "$" + uniqueID);
obj.getResponseCompleted += this.myHandler;
string delayMS = System.Configuration.ConfigurationManager.AppSettings["DelayMS"].ToString();
ushort delay = 1000;
ushort.TryParse(delayMS, out delay);
System.Threading.Thread.Sleep(delay);
}
catch (Exception ex)
{
error += "Error for UniqID:" + uniqueID + "Desc:" + ex.Message + "\n";
}
finally
{
//System.Threading.Thread.CurrentThread.Join();
}
}
}
return error;
}
How can I add them?

Solution 1
Code example; this is not the best or shortest implemention, but it is a clear and understandable one for novice programmers.
string[] arr = { "1", "2", "3", "4", "5", "6", "7" };
int rowCount = arr.Length / dt.Columns.Count;
for (int rowIndex = 0; rowIndex < rowCount; rowIndex++)
{
DataRow row = dt.NewRow();
for (int columnIndex = 0; columnIndex < dt.Columns.Count; columnIndex++)
{
// In case of 2 rows:
// row 1: (0 * 4) + 0 = 0
// row 1: (0 * 4) + 1 = 1
// row 1: (0 * 4) + 2 = 2
// row 1: (0 * 4) + 3 = 3
// row 2: (1 * 4) + 0 = 4
// row 2: (1 * 4) + 1 = 5
// row 2: (1 * 4) + 2 = 6
// row 2: (1 * 4) + 3 = 7
row[columnIndex] = arr[(rowIndex * dt.Columns.Count) + columnIndex];
}
dt.Rows.Add(row);
}
Solution 2
A more advanced and edge-case-safe solution which uses extension methods to split the original array to multiple sub-arrays and fill a datatable.
public static class Extensions
{
public static IEnumerable<IEnumerable<T>> Split<T>(this T[] array, int size)
{
for (var i = 0; i < (float)array.Length / size; i++)
{
yield return array.Skip(i * size).Take(size);
}
}
public static void FillDataTable<T>(this DataTable dataTable, T[] input)
{
IEnumerable<IEnumerable<T>> rowValues = input.Split(dataTable.Columns.Count);
foreach (IEnumerable<T> rowValue in rowValues)
{
DataRow row = dataTable.NewRow();
T[] cellValues = rowValue.ToArray();
for (int columnIndex = 0; columnIndex < cellValues.Length; columnIndex++)
{
// 'Safe'-check in case the original array didn't contain enough values. The cell value will remain 'null'
if (columnIndex < dataTable.Columns.Count)
{
row[columnIndex] = cellValues[columnIndex];
}
}
dataTable.Rows.Add(row);
}
}
}
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
int[] input = { 1, 2, 3, 4, 5, 6, 7, 8 };
DataTable dataTable = new DataTable();
dataTable.Columns.Add("v1");
dataTable.Columns.Add("v2");
dataTable.Columns.Add("v3");
dataTable.Columns.Add("v4");
dataTable.FillDataTable(input);
}
}

What I mean is that you can do something like this:
DataRow row = null;
for (int i = 0; i < arr.Length; i++) {
if (i % 4 == 0)
{
row = dt.NewRow();
dt.Rows.Add(row);
}
row[i % 4] = arr[i];
}
EDIT: Take this as an example:
var arr = Enumerable.Range(1, 40).ToArray();
for (int i = 0; i < arr.Length; i++)
{
if (i % 4 == 0) { Console.WriteLine("new row"); }
Console.WriteLine($"row[{i % 4}] = arr[{i}];");
}
The output would be:
new row
row[0] = arr[0];
row[1] = arr[1];
row[2] = arr[2];
row[3] = arr[3];
new row
row[0] = arr[4];
row[1] = arr[5];
row[2] = arr[6];
row[3] = arr[7];
new row
row[0] = arr[8];
row[1] = arr[9];
row[2] = arr[10];
row[3] = arr[11];
new row
row[0] = arr[12];
row[1] = arr[13];
row[2] = arr[14];
row[3] = arr[15];
...
Which is what you want, right?

This worked for me, need to add hooks for the edge cases but the concept is simple enough.
string[] arr = { "1", "2", "3", "4", "5", "6", "7", "8" };
DataTable dt = new DataTable();
dt.Columns.Add("v1");
dt.Columns.Add("v2");
dt.Columns.Add("v3");
dt.Columns.Add("v4");
DataRow row = dt.NewRow();
int col = 0;
foreach (var val in arr)
{
if (col > 3)
{
col = 0;
dt.Rows.Add(row);
row = dt.NewRow();
row[col] = val;
}
else
{
row[col] = val;
col++;
}
}
dt.Rows.Add(row);

Related

Number looping get row number(01,02,03)

string[] SName = Request.Form.GetValues("Description");
string[] Email = Request.Form.GetValues("Email");
DataTable dtable = dt();
for (int i = 0; i <= SName.Length - 1; i++)
{
DataRow row1 = dtable.NewRow();
row1["Description"] = SName[i];
row1["Email"] = Email[i];
DAL.DMSS insertdata = new DMSS();
insertdata.INSERT_DATA(loggeduser.SUBSIDIARY_CD, input, SName[i], Email[i]);
}
above are my code to get the data from dynamic row add.
if i have 2 rows,data i get is :
now i want to add 1 more data ,sequence number
tried this code but not working..
for (int i = 0; i <= SName.Length - 1; i++)
{
if (i.length <2 )
{
string strvalue = i.PadLeft(2, '0');
}
else
{
string strvalue = i;
}
DataRow row1 = dtable.NewRow();
row1["Description"] = SName[i];
row1["Email"] = Email[i];
DAL.DMSS insertdata = new DMSS();
insertdata.INSERT_DATA(loggeduser.SUBSIDIARY_CD, input, SName[i], Email[i], strvalue);
}
for (int i = 0; i <= SName.Length - 1; i++)
{
var rowNumber = (i + 1).ToString("0#");
}

How to change a DataTable structure so columns values are in multiple columns?

If i have a datatable with structure like that :
emp_num name status session_id
22 john 0 4
22 john 0 5
34 moh 1 3
35 Ran 0 3
35 Ran 0 4
How to convert it to datatable like that :
emp_num name status session_id1 session_id2 session_id3 session_id4 session_id5
22 john 0 0 0 0 1 1
34 moh 1 0 0 1 0 0
35 Ran 0 0 0 1 1 0
I try to create custom data table with looping but it's not generic ,I want something so generic so if i add more columns or the number of sessions increased i get no out of range exceptions ..
using System.Data;
public static class DataTableExtensionMethods
{
public static DataTable TransposeIntegerColumnIntoColumns(this DataTable dt, int indexColumnToEstablishDuplicateRows, int integerColumnIdToTranspose, string transposedColumnName)
{
//Protection if the column to transpose is not an integer or doesn't exist
if (integerColumnIdToTranspose >= dt.Columns.Count) return null;
var columnDataType = dt.Columns[integerColumnIdToTranspose].DataType;
if (columnDataType != typeof(int)) return null;
//Get max sessions number
int maxColumnNumber = 0;
foreach (DataRow dr in dt.Rows)
{
int? number = dr.Field<int?>(integerColumnIdToTranspose);
if (number != null)
{
maxColumnNumber = Math.Max(maxColumnNumber, (int)number);
}
}
//Protection if there are zero rows or the maxColumnNumber is 0
if (dt.Rows.Count == 0 || maxColumnNumber == 0) return null;
//Make a copy of the table so we can remove duplicate rows and add the transposed columns
DataTable result = dt.Copy();
//Add columns to store the session_ids
for (int i = 1; i <= maxColumnNumber; i++)
{
DataColumn dc = new DataColumn(transposedColumnName + i.ToString(), typeof(int));
dc.DefaultValue = 0;
//Possibly make an overloaded method that supports inserting columns
result.Columns.Add(dc);
}
//Remove rows with duplicated employees
for (int i = 0; i < result.Rows.Count; i++)
{
int duplicateRow = GetRowIndexById(result, indexColumnToEstablishDuplicateRows, result.Rows[i][indexColumnToEstablishDuplicateRows].ToString(), i + 1);
if (duplicateRow > -1)
{
result.Rows.RemoveAt(duplicateRow);
}
}
//Populate the transposed columns with values in the integer Column To Transpose
foreach (DataRow dr in dt.Rows)
{
int? sessionNumber = dr.Field<int?>(integerColumnIdToTranspose);
if (sessionNumber == null) continue;
int rowIndex = GetRowIndexById(result, indexColumnToEstablishDuplicateRows, dr[indexColumnToEstablishDuplicateRows].ToString(), 0);
result.Rows[rowIndex][transposedColumnName + sessionNumber.ToString()] = 1; //or +=1 if you want to increment the number
}
//Remove the integerColumnIdToTranspose (again overload this method if you want to keep this column)
result.Columns.RemoveAt(integerColumnIdToTranspose);
return result;
}
//Net 4 implementation with optional parameter
//private static int GetRowIndexById(DataTable dt, int indexColumnToEstablishDuplicateRows, string id, int startLookAtRow = 0)
private static int GetRowIndexById(DataTable dt, int indexColumnToEstablishDuplicateRows, string id, int startLookAtRow)
{
for (int i = startLookAtRow; i < dt.Rows.Count; i++)
{
if (dt.Rows[i][indexColumnToEstablishDuplicateRows].ToString() == id) return i;
}
return -1;
}
}
Calling code:
private void button1_Click(object sender, EventArgs e)
{
DataTable dt = GetData();
DataTable result = dt.TransposeIntegerColumnIntoColumns(0, 3, "session_id");
}
private DataTable GetData()
{
DataTable dt = new DataTable();
dt.Columns.Add("emp_num", typeof(int));
dt.Columns.Add("name");
dt.Columns.Add("status", typeof(int));
dt.Columns.Add("session_id", typeof(int));
DataRow dr = dt.NewRow();
dr["emp_num"] = 22;
dr["name"] = "John";
dr["status"] = 0;
dr["session_id"] = 4;
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["emp_num"] = 22;
dr["name"] = "John";
dr["status"] = 0;
dr["session_id"] = 5;
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["emp_num"] = 34;
dr["name"] = "Moh";
dr["status"] = 1;
//dr["session_id"] = null;
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["emp_num"] = 35;
dr["name"] = "Ran";
dr["status"] = 0;
dr["session_id"] = 3;
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["emp_num"] = 35;
dr["name"] = "Ran";
dr["status"] = 0;
dr["session_id"] = 4;
dt.Rows.Add(dr);
return dt;
}
The result is:

First column in Excel should continuously repeated in datagrid

I have an Excel file with 2 columns [file in my pc]? Now iam getting 2 columns with 8 rows with below code.but continuously i should get 5*2=10 more of same columns with 8 rows in datagridview.
I have written the code which gives result only 2 columns but I should get 10 more columns with 8 rows.below is my code
for (int Cnum = 1; Cnum <= ShtRange.Columns.Count; Cnum++)
{
dt.Columns.Add((ShtRange.Cells[1, Cnum] as Excel.Range).Value2.ToString());
}
for (int Rnum = 2; Rnum <= 9; Rnum++)
{
dt.Rows.Add((ShtRange.Cells[Rnum, 1] as Excel.Range).Value2.ToString(),
(ShtRange.Cells[Rnum, 1] as Excel.Range).Value2.ToString());
}
}
for (int i = 0; i < 13; i++)
{
DataGridViewTextBoxCell txtbx = new DataGridViewTextBoxCell();
DataGridViewColumn txcol = new DataGridViewColumn();
txcol.CellTemplate = txtbx;
txcol.HeaderText = "column" + i.ToString();
dg1.Columns.Add(txcol);
}
dg1.Rows.Add(8);
int dgRw, dgCol;
dgRw = dgCol = 0;
foreach (DataRow dr in dt.Rows)
{
dg1[dgCol, dgRw].Value = dr[0].ToString();
dgRw++;
if (dgRw == 8)
{
dgCol++;
dgRw = 0;
}

How to compare the rows in a datatable and manipulate itto show in a particular format in C#/asp.net

I have a data in data table with say 4 columns.Out of those 10 columns first column contains the date.The data in the table is in the form :
I/p
"15/12/2010",username,24,No
"16/12/2010",username,24,No
"17/12/2010",username,24,No
"18/12/2010",username,24,No
"19/12/2010",username,24,No
"20/12/2010",username,25,No
"21/12/2010",username,24,yes
"22/12/2010",username,24,No
"23/12/2010",username,24,No
"24/12/2010",username,24,No
"25/12/2010",username,24,No
"26/12/2010",Prakhar,24,No
"27/12/2010",username,24,No
"28/12/2010",username,24,No
We have to bind the o/p with the repeater.
For aforemenioned i/p the output should be :
O/P
"15/12/2010 - 20/12/2010",username,24,No
"21/12/2010 - 21/12/2010",username,24,Yes
"22/12/2010 - 25/12/2010",username,24,no
"26/12/2010 - 26/12/2010",username,24,no
"27/12/2010 - 28/12/2010",username,24,no
I.e. we are clubbing all the dates whose corresponsing column values are matching.
We have to write a c# code for it.
First I have created a new Datatable for our final result:
DataTable dtInventoryTable = new dtInventoryTable();
dtInventoryTable.Columns.Add("RateDate", typeof(string));
dtInventoryTable.Columns.Add("RatePlanId", typeof(string));
dtInventoryTable.Columns.Add("RoomTypeId", typeof(string));
private DataTable DisplayInventoryDetails(DataTable dtInventoryDetail)
{
for (int i = 0; i < dtInventoryDetail.Rows.Count; i++)
{
String[] row = new String[dtInventoryDetail.Columns.Count];
String[] row1 = new String[dtInventoryDetail.Columns.Count];
string str=string.Empty;
int h=0;
str = dtInventoryDetail.Rows[i][0].ToString() + " - " +dtInventoryDetail.Rows[i]0].ToString();
for (int j = i+1;j< dtInventoryDetail.Rows.Count; j++)
{
for (int x = 1; x < dtInventoryDetail.Columns.Count; x++)
{
row[x] = dtInventoryDetail.Rows[i][x].ToString();
}
for (int y = 1; y < dtInventoryDetail.Columns.Count; y++)
{
row1[y] = dtInventoryDetail.Rows[j][y].ToString();
}
bool result = ArraysEqual(row, row1);
if (!result)
{
dtInventoryTable = GetRoomRateTable(row, str);
i = j-1;
h = j;
break;
}
else
str= dtInventoryDetail.Rows[i][0].ToString() + " - " + dtInventoryDetail.Rows[j][0].ToString();
h = j;
}
}
if (h >= dtInventoryDetail.Rows.Count-1)
{
dtInventoryTable = GetRoomRateTable(row, str);
break;
}
}
return dtInventoryTable;
}
private DataTable GetRoomRateTable(String[] row,string str)
{
row[0] = str;
dtInventoryTable.LoadDataRow(row, true);
return dtInventoryTable;
}

How to partitioning or splitting DataTable in C#?

I want to split DataTable so that I can upload its chunks from one place to other.
For example
pick first 100 rows.
pick next 100 rows.
pick next 100 rows and so on ...
Is there any way to do it just like cursor in Database? I do not like to use loops etc. for counting rows.
YourDataTable.Select() gives you an array of Data
What about linq?
Fro example YourDataTable.Select (x => x).Take (100).ToEnumerable() gives you the first 100 DataRows and YourDataTable.Select (x => x).Skip(100).Take (100).ToEnumerable() for the next 100.
Try this:
public static class DataExtensions
{
public static IEnumerable<IEnumerable<DataRow>> Partition(this DataTable dataTable, int partitionSize)
{
var numRows = Math.Ceiling((double)dataTable.Rows.Count);
for(var i = 0; i < numRows / partitionSize; i++)
{
yield return Partition(dataTable, i * partitionSize, i * partitionSize + partitionSize);
}
}
private static IEnumerable<DataRow> Partition(DataTable dataTable, int index, int endIndex)
{
for(var i = index; i < endIndex && i < dataTable.Rows.Count; i++)
{
yield return dataTable.Rows[i];
}
}
}
var partitions = dataTable.Partition(100);
Doing:
dataTable.Skip(0).Take(100);
dataTable.Skip(100).Take(100);
dataTable.Skip(200).Take(100);
dataTable.Skip(300).Take(100);
Will iterate 0 times, and take 100 on the first execution. Then iterate through 100 rows, take 100, then iterate 200 rows, then take 100, etc.
The above will do a lazy fetch and only hit each row once
This is a simply way to do that:
public DataSet test(DataSet ds, int max)
{
int i = 0;
int j = 1;
DataSet newDs = new DataSet();
DataTable newDt = ds.Tables[0].Clone();
newDt.TableName = "Table_" + j;
newDt.Clear();
foreach (DataRow row in ds.Tables[0].Rows)
{
DataRow newRow = newDt.NewRow();
newRow.ItemArray = row.ItemArray;
newDt.Rows.Add(newRow);
i++;
if (i == max)
{
newDs.Tables.Add(newDt);
j++;
newDt = ds.Tables[0].Clone();
newDt.TableName = "Table_" + j;
newDt.Clear();
i = 0;
}
}
return newDs;
}
Can you try?
Use linq select part of record
this link in stack overflow can be helpful
Split a collection into n parts with LINQ?
Check: splitting a large datatable into smaller batches from c-sharpcorner.com
internal static List<datatable> SplitTable(DataTable originalTable, int batchSize)
{
List<datatable> tables = new List<datatable>();
DataTable new_table = new DataTable();
new_table = originalTable.Clone();
int j = 0;
int k = 0;
if (originalTable.Rows.Count <= batchSize)
{
new_table.TableName = "Table_" + k;
new_table = originalTable.Copy();
tables.Add(new_table.Copy());
}
else
{
for (int i = 0; i < originalTable.Rows.Count; i++)
{
new_table.NewRow();
new_table.ImportRow(originalTable.Rows[i]);
if ((i + 1) == originalTable.Rows.Count)
{
new_table.TableName = "Table_" + k;
tables.Add(new_table.Copy());
new_table.Rows.Clear();
k++;
}
else if (++j == batchSize)
{
new_table.TableName = "Table_" + k;
tables.Add(new_table.Copy());
new_table.Rows.Clear();
k++;
j = 0;
}
}
}
return tables;
}
Improving on #vanessa
public DataSet SplitDataTable(DataTable tableData, int max)
{
int i = 0;
int j = 1;
int countOfRows = tableData.Rows.Count;
DataSet newDs = new DataSet();
DataTable newDt = tableData.Clone();
newDt.TableName = tableData.TableName+"_" + j;
newDt.Clear();
foreach (DataRow row in tableData.Rows)
{
DataRow newRow = newDt.NewRow();
newRow.ItemArray = row.ItemArray;
newDt.Rows.Add(newRow);
i++;
countOfRows--;
if (i == max )
{
newDs.Tables.Add(newDt);
j++;
newDt = tableData.Clone();
newDt.TableName = tableData.TableName + "_" + j;
newDt.Clear();
i = 0;
}
if (countOfRows == 0 && i < max)
{
newDs.Tables.Add(newDt);
j++;
newDt = tableData.Clone();
newDt.TableName = tableData.TableName + "_" + j;
newDt.Clear();
i = 0;
}
}
return newDs;
}

Categories

Resources