ClosedXml Excel Add multiple values to Rows - c#

Trying to add values from an array string[] to a row in Excel.
When I'm trying to use dt.Rows.Add(string[i]) it is added to the Excel sheet. The problem is it is added vertically, which is quite obvious because I'm only adding one item to the row and then insert a new row. My question now is how to add every item from the string[] to one row so that my data is displayed horizontally.
For example string[] values = {"a","b","c","d"};
The output I have at the moment:
a
b
c
d
The output I want:
a b c d (each in a different cell).
A1 = a
B1 = b
...
I've already been able to add columns to the worksheet, I only need my data to be right.
This is my code for now.
//Add columns
dt.Columns.AddRange(columns.Select(c => new DataColumn(c.ToString())).ToArray());
List<string> temp;
string[] values;
for (int i = 0; i < 7; i++)
{
temp = new List<string>();
temp.Add(timeStamps[i].ToString());
foreach (var item in tagCollection)
{
if (timeStamps[i].Date == item.time)
{
temp.Add(item.min);
temp.Add(item.max);
temp.Add(item.avg);
}
}
int index = 0;
values = new string[temp.Count];
foreach (var item in temp)
{
values[index] = item;
dt.Rows.Add(values[index]);
index++;
}
}
//Convert datatable to dataset and add it to the workbook as worksheet
ds.Tables.Add(dt);
workbook.Worksheets.Add(ds);

The solution may go through the following:
string[] cars = { "Volvo", "BMW", "Mazda" };
table.Rows.Add(cars[0].ToString(), cars[1].ToString(), cars[2].ToString());
Output:
Just need to adapt to your own code.
You've to guarantee that your Datasheet has the columns needed to display all data in the same row. If you didn't do that, for sure it will generate a matrix error.

This works for me. I Changed the foreach loop and discoverd that there was a NewRow() method.
int index = 0;
values = new string[temp.Count];
DataRow newRow;
newRow = dt.NewRow();
foreach (var item in temp) {
values[index] = item;
newRow.ItemArray = temp.Cast<object>().ToArray();
index++;
}
dt.Rows.Add(newRow);

Related

How to Autofill values dynamically from a list to a range of cells in an Excel using C#?

Hi I have a list mentioned below. I want the values in the list to be filled in excel row wise which starts from the cell "A12".
List<string> fmlist = new List<string>();
fmlist = gateways.Keys.Select(x => x.FirmwareVersion).Distinct().ToList();
Please find the Snapshot for the output reference.
Below is what I have tried, but it fills in the last value to the row 12 to the excel.
foreach (var item in fmlist)
{
for (int index = 12; fmlist.Contains(item);)
{
sheet.Cells[index, 1].Value = item;
index++;
break;
}
}
Please help me.
int index = 12;
foreach (var item in fmlist)
{
if (fmlist.Contains(item))
{
sheet.Cells[index, 1].Value = item;
index++;
}
}
This worked for me!

Filter specific rows of worksheet C#

I'm currently trying to get specific rows of an Excel file in my code.
I get the data of my Excel file with this code:
FileInfo existingFile = new FileInfo(local_in_file_path);
using (ExcelPackage package = new ExcelPackage(existingFile))
{
ExcelWorksheet worksheet = package.Workbook.Worksheets[1];
int colCount = worksheet.Dimension.End.Column; //get Column Count
int rowCount = worksheet.Dimension.End.Row; //get row count
List<string> testlist = new List<string>();
List<string> articlelist = new List<string>();
for (int row = 1; row <= rowCount; row++)
{
for (int col = 1; col <= colCount; col++)
{
testlist.Add(worksheet.Cells[row, col].Value?.ToString().Trim());
foreach (var i in testlist)
{
if (articlelist.Contains(i))
{
continue;
}
else
{
articlelist.Add(i);
}
}
}
}
foreach (var article in articlelist)
{
var rows = worksheet.Row().Where(n => n = article); //doesnt work
}
In the foreach loop I want all rows, in which the specific article occurs. How can I do this?
Be careful because when you add something to testlist you are picking only 1 cell everytime (so if your excel file is structured like "1 row has 'article name' , 'description' ecc you are running through every col in every row so it's pretty inefficient, if you could only provide an example of your excel file we can try to help, and does that foreach create an exception or something else?

How can I convert a List<T> to DataTable with only selected parameters

I have a List<Indicators> where Indicators has several properties.
I have a ListView which holds selected properties of that class as a list of strings.
I want to create a DataTable from the List using only the selected properties in the listview.
So far I can create the columns for the DataTable with the selected parameters in listview. I'm stuck on how to fill each row with data from selected columns only.
the for block is where I'm stuck, I know what I have there isn't right. Any help is appreciated, thanks.
internal DataTable ConvertToDataTableAll(List<Indicators> data)
{
DataTable table = new DataTable();
foreach (ListViewItem item in listviewFeatures.Items)
{
table.Columns.Add(item.Text);
//this for block should fill the current column with data.
for (int i = 0; i < data.Count; i++)
{
var row = table.NewRow();
table.Rows.InsertAt(row, i);
table.Rows[i][item.Text] = data.Select(x => item.Text);
}
}
}
Solution with some changes to CodingYoshis suggestion.
This is after adding all columns from code above and removing the for block.
foreach(Indicators ind in data)
{
var row = table.NewRow();
foreach(PropertyInfo prop in ind.GetType().GetProperties())
{
if (table.Columns.Contains(prop.Name))
{
row[prop.Name] = prop.GetValue(ind);
}
}
table.Rows.Add(row);
}
You need to add the columns once for the entire table, not for every row as you are doing. So it should be done like this:
var firstItem = listviewFeatures.Items.FirstOrDefault();
if (firstItem == null)
{
// Nothing to convert to datatable so return
return;
}
// We have items so lets initialize the table
DataTable table = new DataTable();
foreach (ColumnHeader header in listviewFeatures.Columns)
{
table.Columns.Add(header);
}
// Now lets add the rows
foreach (ListViewItem item in listviewFeatures.Items)
{
// Create one row per row in listview
var row = table.NewRow();
// Traverse the listview by each column and fill the row
foreach (ColumnHeader header in listviewFeatures.Columns)
{
row[header] = item.Text;
}
// Add row to table. It will add it to the end.
table.Rows.Add(row);
}

How to increment multiple loops properly in C#

I am running into a problem where I am not comparing the correct data points because only part of my test is iterating.
//for each row from csv
foreach (DataRow dataRow in csvDataTable.Rows)
{
//for each cell from csv row
foreach (var csvItem in dataRow.ItemArray)
{
//for each audiogram
for (int i = 0; i < audioGramData.Count(); i++)
{
//for each stimulus frequency
for (int e = 0; e < audioGramData.Count(); e++)
{
string stimLevel = audioGramData[i].ToList()[e]["StimulusLevel"].ToString();
if (csvItem.ToString() != stimLevel)
{
return false;
}
}
}
}
}
return true;
The first pass of the test properly compares the first cell from a csv file to a the proper field from a JSON object. However, on the second pass, only the stimLevel variable is incremented.
If there were 3 rows in the CSV file, 3 columns in the CSV file, and 3 stimLevels in the JSON object, the flow of the test should be like this:
((Compare first csvItem to first stimLevel
csvItem++
stimLevel++)x3
DataRow++
audiogram++)x3
The audioGramData 2D array is created by first converting a dataTable containing JSON into a JSON object like this:
sqlAdapter.Fill(sqlDataTable);
Conn.Close();
JObject someObject = JObject.Parse(sqlDataTable.Rows[0].ItemArray[0].ToString());
var audioGramData = (JArray)someObject["HIMSAAudiometricStandard"]["ToneThresholdAudiogram"];
This was resolved by getting rid of the two extra 4 loops and iterating i and e outside of each of the for each loops.
int i =0;
int e =0;
//for each row from csv
foreach (DataRow dataRow in csvDataTable.Rows)
{
//for each cell from csv row
foreach (var item in dataRow.ItemArray)
{
string stimlevel = audioGramData[i].ToList()[1].ToList()[0].ToList()[e]["StimulusLevel"].ToString();
stimlevel = stimlevel.Remove(stimlevel.Length -2);
if (item.ToString() != stimlevel)
{
return false;
}
e++;
}
i++;
}
return true;

Get count of selected column out of DataGridView

What do I have:
Filled datagridview
Selected cells of this grid
What do I want:
Amount of unique columns of the selected cells
Names of these columns
What I found:
int selectedColumnsCount = dataGridView3.SelectedColumns.Count;
Somehow this piece of code isn't working in my case.
My question: How can I get the columns name and the amount of columns selected out of a DataGridView?
This is what I created now:
int selectedCellCount = dataGridView3.GetCellCount(DataGridViewElementStates.Selected);
int selectedcolumncount = dataGridView3.SelectedColumns.Count;
ArrayList arr = new ArrayList();
int j = 0;
if (selectedCellCount > 0)
{
for (int i = 0; i < selectedCellCount; i++)
{
int Xcor2 = int.Parse(dataGridView3.SelectedCells[i].ColumnIndex.ToString());
test = test + dataGridView3.Columns[Xcor2].Name;
arr.Add(dataGridView3.Columns[Xcor2].Name);
}
}
ArrayList arr2 = new ArrayList();
foreach (string str in arr)
{
if (!arr2.Contains(str))
{
arr2.Add(str);
j++;
}
}
This is what I made myself, not that nice but its working to get the count of columns if anyone has a better way of realizing this, feel free to add
You can register for the SelectionChanged event and process the SelectedCells. For example
public Form1()
{
InitializeComponent();
dataGridView1.SelectionChanged += new EventHandler(dataGridView1_SelectionChanged);
}
HashSet<int> column_indicies = new HashSet<int>();
HashSet<string> column_names = new HashSet<string>();
int number_of_columns = 0;
void dataGridView1_SelectionChanged(object sender, EventArgs e)
{
column_indicies.Clear();
column_names.Clear();
foreach (DataGridViewCell cell in dataGridView1.SelectedCells)
{
// Set of column indicies
column_indicies.Add(cell.ColumnIndex);
// Set of column names
column_names.Add(dataGridView1.Columns[cell.ColumnIndex].Name);
}
// Number of columns the selection ranges over
number_of_columns = column_indicies.Count;
}
You cannot select columns. Only one columns can be selected at a time!
Columns are the same as Rows.
Or did you mean to get those columns, which cells are slected?
Ok, this is one of the way of getting column names (you can even use HeaderText property instead of Name):
List<DataGridViewColumn> listOfColumns = new List<DataGridViewColumn>();
foreach (DataGridViewCell cell in dataGridView1.SelectedCells)
{
DataGridViewColumn col = dataGridView1.Columns[cell.ColumnIndex] as DataGridViewColumn;
if (!listOfColumns.Contains(col))
listOfColumns.Add(col);
}
StringBuilder sb =new StringBuilder();
foreach (DataGridViewColumn col in listOfColumns)
sb.AppendLine(col.Name);
MessageBox.Show("Column names of selected cells are:\n" + sb.ToString());

Categories