Read excel file row by row, cell by cell C# - c#

I want (as title states) to programmatically read values from an Excel file. Row by row and then cell by cell, to have the freedom of creating custom collections out of cell's data.
This questions helped me.
But I need more flexible code. Can I for example write (* is just for all columns)
Range range1 = worksheet.get_Range("*1", Missing.Value)
foreach (Range r in range1)
{
string user = r.Text;
string value = r.Value2;
}
And iterate all cells in row 1 as long as there is next.
There must be some elegant way to iterate through rows and cells in C#.

You can rely on the Rows/Columns properties and then iterate through all the contained ranges (Cells). Sample code:
Range range1 = worksheet.Rows[1]; //For all columns in row 1
//Range range1 = worksheet.Columns[1]; //for all rows in column 1
foreach (Range r in range1.Cells) //range1.Cells represents all the columns/rows
{
// r is the range of the corresponding cell
}

Try this:
Excel.Range r = worksheet.get_Range("*1", Missing.Value);
for (int j = 0; j < r.Rows.Count; j++) {
Excel.Range currentCell = r.Rows[j + 1] as Excel.Range;
}

Related

Loop on excel rows in different Excel worksheets C#

I have an excel file myexcel.xlsx which has multiple worksheets. All worksheets has the same columns names in the first row. One column is called ID and another column is called Total. I am going through each row in every worksheet then I wonder how I can then check the columns ID if it exists in any other row in the same or other worksheet. If the ID is not found somewhere else then the total will be only equal to the Total column of this row, but if the same ID exists in another row in the same/other worksheet then I want to add the Total column of the other row as well then ignore all these rows of the same ID in the for loop so that they are not repeated.
Excel.Application myapp = new Excel.Application();
Excel.Workbook myworkbook = myapp(#"myexcel.xlsx");
for (int i = 1; i <= myworkbook.Worksheets.Count; i++)
{
Excel._Worksheet myworksheet = myworkbook.Worksheets[i];
Excel.Range myrange = myworksheet.UsedRange;
int myrowCount = myrange.Rows.Count;
}
I don't know the correct syntax for working with Excel sheets, so I'll give you a basic example for what I think you are asking. You'll have to adjust the code so it works, but if you want to aggregate (get the sum) of the "Total" in all the rows with the same "ID" you should be able to do something like this:
var totalsDictionary = new Dictionary<int, int>();
for (var ws = 0; ws < worksheets.Count; ws++)
{
var worksheet = worksheets[ws];
for (var row = 0; row < worksheet.Rows.Count; row++)
{
var id = worksheet.Rows[row]["ID"];
var total = worksheet.Rows[row]["Total"];
if (totalsDictionary.ContainsKey(id))
{
totalsDictionary[id] += total;
}
else
{
totalsDictionary.Add(id, total);
}
}
}
// totalsDictionary now contains the sum of Totals for each ID

Comparing a formula column with value column in excel

I have two columns in a excel sheet. I am populating the first column with a formula and I have some values in second column. Now I want to compare these two columns and need to display True/false in third column. But when I use 'IF' condition all I am getting is FALSE. Here is my code.
Formulating the column
using (ExcelPackage xlPackage = new ExcelPackage(newFile))
{
ExcelWorksheet worksheet = xlPackage.Workbook.Worksheets[GetConfigValue("Reconsheet")];
int totalRows = worksheet.Dimension.End.Row;
for (int row = startupRow; row <= totalRows; row++)
{
//Formula
string vlookforH = "IF(ISNA(VLOOKUP(C" + row + ",PWA!A:B,2,FALSE)),0,VLOOKUP(C" + row + ",PWA!A:B,2,FALSE))";
worksheet.Cells[row, 8].Formula = vlookforH;
}
xlPackage.Save();
MessageBox.Show("PWA hours received");
}
Comparing Formula column and Normal value column:
for (int row = startupRow; row <= totalRows; row++)
{
if (Convert.ToInt32(worksheet.Cells[row, 18].Value) != 0)
{
decimal hvalue = (worksheet.Cells[row, 8].Value) != null ? Convert.ToDecimal(worksheet.Cells[row, 8].Value.ToString()) : 0;
decimal rvalue = (worksheet.Cells[row, 18].Value) != null ? Convert.ToDecimal(worksheet.Cells[row, 18].Value.ToString()) : 0;
if (hvalue == rvalue)
{
worksheet.Cells[row, 31].Value = "True";
}
else
{
worksheet.Cells[row,31].Value = "False";
Count = Count + 1;
}
}
}
When I am debugging the application, I realized hvalue is always zero because it's a formula column.
I've tried in different ways, but unable to find the solution. Can anyone help me? What am I doing wrong?
You will have to call worksheet.Calculate(); after writing the formulas into the cells to actually calculate the values. Calling it once after your first for-loop is enough.
I verified that on a test-project.
EDIT:
If worksheet.Calculate() does not work you can try xlPackage.Workbook.Calculate();
Here is a link to the documentation: EPPlus Calculate Documentation

How to Check and merge two rows if next value is same or not in excel with epPlus

I am working on dynamic Excel creation with the help of EPPlus library and I have an excel which data looks like:
Name EmpCode Department attendance
Prashant 111 CSE 70% for Sep
Prashant 111 CSE 90% for Oct
XYZ 112 HR 50% for Sep
XYZ 112 HR 90% for Oct
What I want is:
if the current EmpCode is equal to the value of next row then merge this both columns so the expected output will be
I am damn sure that each empCode will be repeated only two times.
The code what I have tried:
for (var rowNum = 1; rowNum <= ws.Dimension.End.Row; rowNum++)
{
var row = ws.Cells[string.Format("{0}:{0}", rowNum)];
}
This code will only work if the empcode is repeated twice but you said you're damn sure it will only be repeated twice so it should be okay, just not very scale-able.
Once you get the data in your spreadsheet you have to loop through all the rows in your dataset. At the beginning of the loop you set the range of your current row and at the end of the loop you set the range of your prior row.
If the previous range is set, you evaluate the columns of each row to determine if you should merge the cells together.
using (var p = new OfficeOpenXml.ExcelPackage(new FileInfo(#"c:\FooFolder\Foo.xlsx")))
{
ExcelWorkbook wb = p.Workbook;
ExcelWorksheet ws = wb.Worksheets[1];
//create variable for previous range that will persist through each loop
ExcelRange previousRange = null;
//set position of first column to merge
int mergecellBegin = 1;
//set position of last column to merge
int mergeCellEnd = 3;
//create variable to check the cells of your rows
bool areCellsEqual;
//iterate through each row in the dataset
for (var rowNum = 2; rowNum <= ws.Dimension.End.Row; rowNum++)
{
ExcelRange currentRange = ws.Cells[rowNum, 1, rowNum, mergeCellEnd];
//will skip if we haven't set previous range yet
if (previousRange != null)
{
//reset your check variable
areCellsEqual = true;
//check if all cells in the ranges are qual to eachother
for (int i = 1; i <= mergeCellEnd; i++)
{
//if the cells from the ranges are not equal then set check variable to false and break the loop
if (!currentRange[rowNum, i].Value.Equals(previousRange[rowNum - 1, i].Value))
{
areCellsEqual = false;
break;
}
}
//if all cells from the two ranges match, merge them together.
if (areCellsEqual)
{
//merge each cell in the ranges
for (int i = 1; i <= mergeCellEnd; i++)
{
ExcelRange mergeRange = ws.Cells[rowNum - 1, i, rowNum, i];
mergeRange.Merge = true;
}
}
}
//sets the previous range to the current range to be used in next iteration
previousRange = currentRange;
}
p.Save();
}

How to Find ColumnPostion by Text in SpreadsheetGear?

How to find Column Position from Header by using text in Spreadsheet Gear?
i.e want to find Remark Text ColumnPosition From SpreadSheet.
Got the result is as below.
SpreadsheetGear.IRange range = workbookView.ActiveWorksheet.Cells.Find("StringtoFind", null, SpreadsheetGear.FindLookIn.Values, SpreadsheetGear.LookAt.Part, SpreadsheetGear.SearchOrder.ByRows, SpreadsheetGear.SearchDirection.Next, true);
Thanks..
You could loop though the columns in the header row until you find your text match.
//Get the cells of a worksheet
SpreadsheetGear.IRange cells = worksheet.Cells;
int iColRemark = 0;
//loop through columns
for (int iCol = 0; iCol < cells.ColumnCount; iCol++)
{
//check header row for colummn that has the text 'Remark'
if (cells[0, iCol].Text.Equals("Remark"))
{
iColRemark = iCol;
break;
}
}

find the last used row in a column in windows c#

I have a excel report and i need to draw charts based on the data in the report. Am able to get the range from a particular column to last filled row like shown below. I have many columns in my report and i need only the data in a particular column like ("c1","
c12"). the column length may vary. it need not be 12. How can i get the range till last filled row of a column.
Excel.Range last1 = xlWorkSheet2.Cells.SpecialCells(Excel.XlCellType.xlCellTypeLastCell, Type.Missing);
oRange = xlWorkSheet2.get_Range("A6", last1);
Try the following code. This works by selecting the top cell in a row, and then searching downwards until the end of the range is found. The range column is simply the range between start and end. Note that this will only find the last contiguous cell in the range, and will not search through blank rows.
Excel.Range start = xlWorkSheet2.Range["A1"];
Excel.Range column;
if (start.Offset[1].Value != null)
column = xlWorkSheet2.Range[start, start.End[Excel.XlDirection.xlDown]];
else
column = start;
The following code will allow you to retrieve the full used range of the column even if there are blank rows. This code works in a similar manner, but searches upwards from the bottom of the used range in the worksheet to find the last cell in the column containing a value.
Excel.Range start = xlWorkSheet2.Range["A1"];
Excel.Range bottom = xlWorkSheet2.Range["A" + (ws.UsedRange.Rows.Count + 1)];
Excel.Range end = bottom.End[Excel.XlDirection.xlUp];
Excel.Range column = xlWorkSheet2.Range[start, end];
Hi found that all the above methods didn't work for what I wanted to do, so here is my solution:
public object GetLastNotEmptyRowOfColumn(string sheet, string column,int startRow,int endRow)
{
try
{
var validColumn = Regex.IsMatch(column, #"^[a-zA-Z]+$");
if(!validColumn)
{
throw new Exception($"column can only a letter. value entered : {column}");
}
xlBook = xlApp.ActiveWorkbook;
xlSheet = xlBook.Sheets[sheet];
xlRange = xlSheet.Range[$"{column}{startRow}", $"{column}{endRow}"];
object[,] returnVal = xlRange.Value;
var rows = returnVal.GetLength(0);
// var cols = returnVal.GetLength(1);
int count = 1;
for (int r = 1; r <= rows; r++)
{
var row = returnVal[r, 1];
if (row == null) break;
count++;
}
//returns an object : {Count:10,Cell:A9}
return= new { Count=count-1, Cell=$"{column}{startRow+count-1}" };
}
catch (Exception ex)
{
......
}
return null;
}
Usage: var response = GetLastNotEmptyRowOfColumn("Sheet1", "A",1,100);
Result:

Categories

Resources