I am performing search within excel workbook using small c# application
using below method
public void SearchExcelFiles(string FilePath)
{
string ConnStr = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + FilePath + ";Extended Properties=\"Excel 12.0 Xml;HDR=YES\";";
Microsoft.Office.Interop.Excel.Application oXL = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel.Workbook oWB;
Microsoft.Office.Interop.Excel.Range currentFind = null;
Microsoft.Office.Interop.Excel.Range firstFind = null;
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
if (!GB_Search.Controls.OfType<TextBox>().Any(x => !string.IsNullOrEmpty(x.Text)))
{
MessageBox.Show("Enter text for search");
return;
}
oWB = oXL.Workbooks.Open(FilePath, //---Filename OR FilePath
0, //---object UpdateLinks
true, //---object ReadOnly
Type.Missing, //5//---object Format
"", //---object Password
"", //---object WriteResPassword
false, //---object ReadOnlyRecommend
Excel.XlPlatform.xlWindows, //---object Origin
"", //---object Delimiter
true, //---object Editable
false, //---object Notify
0, //---object Converter
true, //---object AddToMru
false, //---object Local
false); //---object CorruptLoad;
//specifying searching range within each excel sheet
//Excel.Range oRng = oXL.get_Range("A1", "XFD1048576");
Excel.Range xlCell =
xlWSheet.UsedRange.SpecialCells(Excel.XlCellType.xlCellTypeLastCell, Type.Missing);
Excel.Range oRng = xlWSheet.get_Range("A1",
xlWSheet.UsedRange.SpecialCells(Excel.XlCellType.xlCellTypeLastCell, Type.Missing));
//loop to search witin all excel sheets (workbook)
foreach (Excel.Worksheet SheetID in oWB.Worksheets)
{ //loop within all textboxs value to search if it is exist
foreach (TextBox cont in GB_Search.Controls.OfType<TextBox>())
{
if (!string.IsNullOrEmpty(cont.Text))
{
currentFind = oRng.Find(cont.Text,
Type.Missing,
Excel.XlFindLookIn.xlValues,
Excel.XlLookAt.xlPart,
Excel.XlSearchOrder.xlByRows,
Excel.XlSearchDirection.xlNext,
false,
Type.Missing,
Type.Missing);
while (currentFind != null)
{
//Keep track of the first range you find.
if (firstFind == null)
{
firstFind = currentFind;
}
//if current address is same as the starting address stop searching
else if (currentFind.get_Address(true, true, Excel.XlReferenceStyle.xlR1C1, Type.Missing, Type.Missing) == firstFind.get_Address(true, true, Excel.XlReferenceStyle.xlR1C1, Type.Missing, Type.Missing))
{
break;
}
//keep searching for next value
currentFind = oRng.FindNext(currentFind);
MessageBox.Show(currentFind.get_Address(true, true, Excel.XlReferenceStyle.xlR1C1, Type.Missing, Type.Missing)); // for test purpose
string CurrentAddress = currentFind.get_Address(true, true, Excel.XlReferenceStyle.xlR1C1, Type.Missing, Type.Missing);
AddToDataGridView(CurrentAddress, SheetID.Name, ConnStr); //when match found get full Row details and populate it to datagridview
}
//empty ranges before looking for the next textbox values
firstFind = null;
currentFind = null;
}
//MessageBox.Show("Done control..." + cont.Name); //~test Purpose
}
//MessageBox.Show("Done...sheet"); //~test Purpoes
}
//MessageBox.Show("Done...wb"); //~test Purpose
oWB.Close(false, Type.Missing, Type.Missing);
oWB = null;
oXL.Quit();
}
now when match found I am calling this method AddToDataGridView() which should do the following:
Get full row details by using where clause (in somehow) the rowid shown at attached image
populate this row and add to datagridview
another way to this are welcomed
public void AddToDataGridView(string CurrentAddress, string SheetName, string ConnStr)
{
string cmdtxt = #"select * from [" + SheetName + "$" + CurrentAddress + "]Where ???? ";
MessageBox.Show(cmdtxt); // test purpose
using (OleDbConnection conn = new OleDbConnection(ConnStr))
{
OleDbDataAdapter DA = new OleDbDataAdapter(cmdtxt, conn);
DA.Fill(dt);
DGV_Data.DataSource = dt;
conn.Close();
}
}
example
----------------------------------------------------------
# | A | B | C | D |
----------------------------------------------------------
1 | A VALUE1 | B VALUE1 | C VALUE1 | D VALUE1 |
----------------------------------------------------------
2 | A VALUE2 | B VALUE2 | C VALUE2 | D VALUE2 |
----------------------------------------------------------
suppose that B VALUE2 is my searching match value... I want to get the rowid which is 2 in that case the query that row select * from [sheet_Name$] where rowid=2 then add it to datagridview how to do that ?
thanks alot
Without fully understanding, what the goal is here. The best I can sum up is to search for a string in an Excel workbook. You want the results of the search to be displayed in a DataGridView. From your comments, you stated that each worksheet may have a different column structure and you want the “complete” row that matched the search string in at least one of the cells in that row. Therefore, each worksheet search result may/will have a different column structure. I hope I understand this correctly.
If this is the case then I am hoping the code below may help. It is a simple form, that has a button to open/select an Excel workbook to search; a text box to allow the user to type the search string into; a combo box to hold the names of the worksheets in the selected workbook; a search button to initiate the search process; a textLog text box for debugging and finally a DataGridView to hold the search results. Throw in a few labels and it may look something like below after a search for “John” in the workbook “new293.xlsx”.
The text box on the right is used as a log output for testing if needed. After the search results come back, the user can use the combo box to select the results from each worksheet.
The code does a simple search for a string in a given workbook. When the user types something into the search text box and clicks the search button, the code opens the given workbook, searches for the target string in each worksheet and creates a DataTable to hold the successfully found rows. A DataSet is created to hold the “different” DataTable’s created by each worksheet since each worksheet may have a different column structure.
Below is a more detail description, however, I must comment about some possible Excel issues that may arise.
Currently the code will search for any substring of the target string. Example, if you searched for “a”, the returned results will contain ANY string with an “a” in it... “cat” “bat” etc. You may want to refine how this is done. Excels “Find” method may not be the best option. (more below)
When using Excels UsedRange property, it should be noted that this may return cells that will “appear” empty. In almost all cases when this happens, there is some formatting in the cell but the cell is empty and contains no data… UsedRange may include that cell in the range because of the formatting. Please be aware of this and do not be too quick to claim UsedRange is flawed when it returns these “apparently” empty cells. I have a solution for this in another answer.
Lastly, about Excel and interop… the current code uses the same Excel Find method as your posted code does. This should be fine if the dataset is not to large, however, if there is a large amount of data (large Excel worksheets with many columns and rows), this may become a performance problem. This is an Excel and interop issue. Calling methods like UsedRange, Find and others is VERY EXPENSIVE when used in a loop (which we are). Point being, if the worksheets are large, you may want to consider a different implementation without using interop. I understand there are better (free) third party Excel libraries.
With that said, below is the code to the form above.
Global variables in the form:
A DataSet ds to hold the DataTables; self-explanatory path DefaultDirectory; an Excel workbook to search and finally the Excel application itself. Upon load, the Excel app is started and waits for the user to select a workbook.
DataSet ds = new DataSet();
string DefaultDirectory = #"D:\Test\";
Workbook workbook;
Excel.Application excelApp;
public Form3() {
InitializeComponent();
}
private void Form3_Load(object sender, EventArgs e) {
excelApp = new Excel.Application();
}
The open/select workbook button click to select a workbook uses an OpenFileDialog to allow the user to select the workbook to search. Once selected, the global variable workbook is open and available to other methods.
private void btnSelectWorkbook_Click(object sender, EventArgs e) {
DGV_Data.DataSource = null;
tbSearch.Text = "";
cbWorksheetNames.Items.Clear();
textLog.Text = "";
lblWorkbookName.Text = "";
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "Excel Files|*.xls;*.xlsx;*.xlsm";
ofd.InitialDirectory = DefaultDirectory;
if (ofd.ShowDialog() == DialogResult.OK) {
string fileToOpen = ofd.FileName;
workbook = excelApp.Workbooks.Open(fileToOpen);
lblWorkbookName.Text = "Workbook: " + fileToOpen;
}
}
After the user selects a workbook to search, and has typed some target text to search for… the user clicks the “Search” button. First, two checks are made to make sure there is some text to search for and also check if there is a workbook open to search in. If there is no text to search for or a workbook is not open, display a message to the user and return without searching.
If there is an open workbook and text to search for, the global DataSet ds is initialized, then ds is filled with each worksheet’s DataTable by calling the GetRowsFromSearchStringFromAllWorksheets. . After the DataSet has been filled (more below) the DataGridView’s DataSource is set to the first DataTable in the DatatSet; the combo box is filled with the worksheet names and finally some labels are updated.
private void btnSearch_Click(object sender, EventArgs e) {
if (string.IsNullOrEmpty(tbSearch.Text)) {
MessageBox.Show("Enter text for search");
return;
}
if (workbook == null) {
MessageBox.Show("Select a workbook");
return;
}
ds = new DataSet();
try {
ds = GetRowsFromSearchStringFromAllWorksheets(workbook, tbSearch.Text);
DGV_Data.DataSource = ds.Tables[0];
FillComboBoxWithSheetNames();
cbWorksheetNames.SelectedIndex = 0;
gbResults.Text = "Search Results for '" + tbSearch.Text + "'";
tbSearch.Text = "";
}
catch (Exception ex) {
MessageBox.Show("Error: " + ex.Message);
}
}
The GetRowsFromSearchStringFromAllWorksheets method (which probably needs a better name) is not doing much. It loops through each worksheet in the workbook, creates a DataTable from the worksheet, fills the data table by calling the FillTableWithSearchResults method (below), then finally adds the DataTable to the DataSet. The GetDTColumnsFromWorksheet method (below) creates a DataTable based on what the header rows are in the worksheet. The first row in the worksheet is assumed to be header rows and uses these as column names for the DataTable. Note: currently, if the search returns with no results, the worksheet DataTable is STILL added to the DataSet. I left the debug code to modify if you only want to add worksheets that contained results.
private DataSet GetRowsFromSearchStringFromAllWorksheets(Workbook wb, string searchString) {
DataSet ds = new DataSet();
foreach (Worksheet currentWorksheet in wb.Worksheets) {
System.Data.DataTable currentDT = GetDTColumnsFromWorksheet(currentWorksheet);
//textLog.Text += "Searching in worksheet " + currentWorksheet.Name + Environment.NewLine;
FillTableWithSearchResults(currentWorksheet.UsedRange, searchString, currentDT);
if (currentDT.Rows.Count > 0) {
textLog.Text += "Matches found in worksheet " + currentWorksheet.Name + Environment.NewLine;
}
else {
textLog.Text += "No matches found in worksheet " + currentWorksheet.Name + Environment.NewLine;
}
ds.Tables.Add(currentDT);
}
return ds;
}
The GetDTColumnsFromWorksheet takes a worksheet and returns a DataTable. The data table returned will have the same number of columns as there are returned from “UsedRange` from the worksheet. An extra column is added to display where in the worksheet the cell is found. It is in an RXXCXX format in the first column. If a cell in a column in the used range has no value, the string “???XX” will be used. This is for cases where there is an empty column.
private System.Data.DataTable GetDTColumnsFromWorksheet(Worksheet ws) {
// this assumes that row 1 of the worksheet contains a row header
// we will use this to name the `DataTable` columns
// this also assumes there are no "lingering" cells with values
// that may not necessarily belong to the data table
int missingColumnNameCount = 1;
Range usedRange = ws.UsedRange;
int numberOFColumns = usedRange.Columns.Count;
System.Data.DataTable dt = new System.Data.DataTable();
dt.TableName = ws.Name;
string currentColumnHeader = "";
Range row1;
// add an extra column in the front
// this column will show where (RXCX) the found item is in the worksheet
dt.Columns.Add("CXRX", typeof(string));
for (int i = 1; i <= numberOFColumns; i++) {
row1 = usedRange[1, i];
if (row1.Value2 != null) {
currentColumnHeader = row1.Value2.ToString();
}
else {
// if the row has no value a default name and indexer to avoid duplicate column names
currentColumnHeader = "???" + missingColumnNameCount;
missingColumnNameCount++;
}
dt.Columns.Add(currentColumnHeader, typeof(string));
}
return dt;
}
The FillTableWithSearchResults method takes a range to search through, a string to search for and finally a data table to add the successful searches to. The DataTable passed in has already been created and the columns have been initialized.
I am not sure if this is the best way to handle Excels Find/FindNext methods. Therefore, I hope I have this correct. When the Find is used on a range for the first time, it returns the first found cell that matches what it is searching for. This retuned range is a cell address of the “first” found item. From my understanding, the FindNext will obviously return the NEXT found item. The issue is that when it finds the LAST item and searches for the next one, it simply starts over at the beginning. Therefore, the stopping condition for the loop would be when the cell address of the NextFind matches the cell address of the “first” Find. This will require that we save the “first” Find’s cell address. Below is one approach to this conundrum.
Create two ranges: one startRange to hold the starting “first” Find, another currentRange to hold the currently “found” range. First, a check is made to make sure there is something to search in. If there is at least one row to search in, the startRange is set from the “first” Find. This is the cell address we need to stop at when using FindNext. If there is at least one item found, then we can search for the next one and enter the FindNext loop. Simply set currentRange to the NextFind add the startRange from the “first” Findto the data table then finally enter the FindNext loop such that it will continue using FindNext and adding new rows to the data table until the currentRange cell address Equals the startingRange cell address. This indicates that FindNext has looped back to the beginning and the search is complete. The AddExcelRowToDataTable adds the found row to the data table (below).
Note: currently this code allows duplicate entries in cases where the searched for string is found in more than one column in the same row. There will be one row entry in the grid for every found search string in the rows columns. Example: if row 5 has the searched for string in columns 4, 6 and 8, there will be a row for R5C4, R5C6 and R5C8. I did not filter this to remove duplicate rows.
private void FillTableWithSearchResults(Range usedRange, string searchString, System.Data.DataTable dt) {
Range currentRange;
if (usedRange.Rows.Count > 0) {
Range startRange = usedRange.Find(searchString);
if (startRange != null) {
currentRange = usedRange.FindNext(startRange);
AddExcelRowToDataTable(usedRange, startRange, dt);
string startAddress = startRange.get_Address(true, true, XlReferenceStyle.xlR1C1);
while (!currentRange.get_Address(true, true, XlReferenceStyle.xlR1C1).Equals(startAddress)) {
AddExcelRowToDataTable(usedRange, currentRange, dt);
currentRange = usedRange.FindNext(currentRange);
}
}
}
}
The AddExcelRowToDataTable method takes a used range to get the data from, a range row to add to the third given parameter DataTable. Again a little hacky, a check is made to make sure that there are not more columns in the used range than there are in the data table. A row Index is obtained to indicate which row in the used range to add to the data table. A DataRow dr is created from the given DataTable dt to make sure the column schemas are the same. The first column is going to be the column we added earlier to display the RXXCXX location column of the found item. Add the extra column data then loop through the rest of the columns adding the worksheet values to the DataRow. After the all the column values have been added, the DataRow is added to the DataTable.
private void AddExcelRowToDataTable(Range usedRange, Range row, System.Data.DataTable dt) {
if (usedRange.Columns.Count >= dt.Columns.Count - 1) {
int rowIndex = GetRowIndexOfFoundItem(row);
if (rowIndex >= 0) {
DataRow dr = dt.NewRow();
// add the CXRX data
dr[0] = row.get_Address(true, true, XlReferenceStyle.xlR1C1);
for (int i = 1; i <= usedRange.Columns.Count; i++) {
dr[i] = usedRange.Cells[rowIndex, i].Value2;
}
dt.Rows.Add(dr);
}
}
}
The GetRowIndexOfFoundItem takes a cell range and returns the (int) row index from the cells string RXXCXX address.
private int GetRowIndexOfFoundItem(Range range) {
// hacky ... the string is a format of RXXCX or RXXcXXX or RXXXXCXX.
// we want the XXX after the R... split the string on 'C'
// to get RXX..X, then remove the 'R' and parse the number
string RCaddress = range.get_Address(true, true, XlReferenceStyle.xlR1C1);
string[] split = RCaddress.Split('C');
RCaddress = split[0].Remove(0, 1);
int rowIndex = 0;
if (int.TryParse(RCaddress, out rowIndex)) {
return rowIndex;
}
else {
// not valid number
return -1;
}
}
Method to fill the combo box with worksheet names after the search has finished.
private void FillComboBoxWithSheetNames() {
cbWorksheetNames.Items.Clear();
foreach (System.Data.DataTable dt in ds.Tables) {
cbWorksheetNames.Items.Add(dt.TableName);
}
}
The combo boxes SelectedIndexChnged event is wired up and uses the combo boxes selected index to determine which DataTable to display in the grid.
private void cbWorksheetNames_SelectedIndexChanged(object sender, EventArgs e) {
DGV_Data.DataSource = ds.Tables[cbWorksheetNames.SelectedIndex];
}
Finally some resource cleanup.
private void Form3_FormClosing(object sender, FormClosingEventArgs e) {
try {
if (workbook != null) {
workbook.Close();
Marshal.ReleaseComObject(workbook);
}
excelApp.Quit();
Marshal.ReleaseComObject(excelApp);
}
catch (Exception ex) {
MessageBox.Show("Error: " + ex.Message);
}
}
Sorry for the long winded answer, I hope it helps.
First, you are only finding the "first" row in each sheet because it is searching for a named range called TB_First_Name.Text in each sheet - there can only be at most one of those in each sheet.
Secondly, there seems to be a typo in your code - I believe DataGridView gdv_data = new DataGridView(); should be DataGridView DGV_data = new DataGridView();
Finally, seems from other answers (e.g. https://stackoverflow.com/a/46044387/3661120) the best way to populate a datagridview row from excel would be this kind of way:
var rowArray = oRng.Cells.Value2.Cast<object>().ToArray();
try { j = d.CurrentRow.Index; } catch { }
DataGridViewRow r = new DataGridViewRow();
r.CreateCells(d, rowArray);
DGV_Data.Rows.Insert(j, r);
I have a worksheet that has 5 rows and 3 columns. I make a copy of this sheet:
activeSheet.Copy(Type.Missing, activeSheet);
var outputSheetIndex = activeSheet.Index + 1;
var outputSheet = (Worksheet)application.Sheets[outputSheetIndex];
The above copies the sheet into another sheet. I now want to insert another range into the outputSheet and shift the outputSheet columns to the right.
I am not sure on which range object to apply the Insert method on.
I tried creating a new range to insert in the beginning, but this doesn't work:
var startCell = outputSheet.Cells[1, 1];
var endCell = outputSheet.Cells[output.Count(),
properties.Length + 1];
var writeRange = outputSheet.Range[startCell, endCell];
writeRange.Insert(XlInsertShiftDirection.xlShiftToRight);
When I insert writeRange, I want the existing range of data to be shifted to the right.
If all you want to do is insert a blank column on your new (copied worksheet), I think this would work:
outputSheet.Range["A:A"].Insert(
Microsoft.Office.Interop.Excel.XlInsertShiftDirection.xlShiftToRight,
Type.Missing);
If you want the column somewhere else, you would change "A:A" to your desired range.
I'm using EPPlus and iterating through all the columns of each worksheet in a workbook. I'm trying to format every column with a header that contains the word "NUMBER" as a number format. It runs and it hits the breakpoint where I set the number format but, when I open the spreadsheet, the columns are still formatted as text. Any help would very much be appreciated.
private void cleanSpreadSheet(string fileName)
{
// set all columns with a header of number to numeric type
FileInfo existingFile = new FileInfo(fileName);
var package = new ExcelPackage(existingFile);
ExcelWorkbook wb = package.Workbook;
foreach (ExcelWorksheet workSheet in wb.Worksheets)
{
var start = workSheet.Dimension.Start;
var end = workSheet.Dimension.End;
for (int col = start.Column; col <= end.Column; col++)
{ // col by col
if (workSheet.Cells[1, col].Text.ToUpper().Contains("NUMBER"))
{
workSheet.Column(col).Style.Numberformat.Format = "0";
}
}
}
package.Save();
package.Dispose();
wb.Dispose();
}
The issue may be that your existing Excel workbook has data formatted as Excel "Text". If this is the case, you won't likely be able to simply convert each cells' format to a number as Excel doesn't know how to convert "Text" to "Numbers".
Instead, you may need to iterate over each column and row in EPPlus and replace each value after casting them. The code below could use some error checking on the casts, but gives you a sense of the concept.
//foreach row ... foreach column...
ExcelRange cell = worksheet.Cells[row, col];
cell.Value = double.Parse((string)cell.Value);
My Excel file is not in tabular data. I am trying to read from an excel file.
I have sections within my excel file that are tabular.
I need to loop through rows 3 to 20 which are tabular and read the data.
Here is party of my code:
string fileName = "C:\\Folder1\\Prev.xlsx";
var workbook = new XLWorkbook(fileName);
var ws1 = workbook.Worksheet(1);
How do I loop through rows 3 to 20 and read columns 3,4, 6, 7, 8?
Also if a row is empty, how do I determine that so I can skip over it without reading that each column has a value for a given row.
To access a row:
var row = ws1.Row(3);
To check if the row is empty:
bool empty = row.IsEmpty();
To access a cell (column) in a row:
var cell = row.Cell(3);
To get the value from a cell:
object value = cell.Value;
// or
string value = cell.GetValue<string>();
For more information see the documentation.
Here's my jam.
var rows = worksheet.RangeUsed().RowsUsed().Skip(1); // Skip header row
foreach (var row in rows)
{
var rowNumber = row.RowNumber();
// Process the row
}
If you just use .RowsUsed(), your range will contain a huge number of columns. Way more than are actually filled in!
So use .RangeUsed() first to limit the range. This will help you process the file faster!
You can also use .Skip(1) to skip over the column header row (if you have one).
I'm not sure if this solution will solve OP's problem but I prefer using RowsUsed method. It can be used to get the list of only those rows which are non-empty or has been edited by the user. This way I can avoid making emptiness check while processing each row.
Below code snippet can process 3rd to 20th row numbers out of all the non-empty rows. I've filtered the empty rows before starting the foreach loop. Please bear in mind that filtering the non-empty rows before starting to process the rows can affect the total count of rows which will get processed. So you need to be careful while applying any logic which is based on the total number of rows processed inside foreach loop.
string fileName = "C:\\Folder1\\Prev.xlsx";
using (var excelWorkbook = new XLWorkbook(fileName))
{
var nonEmptyDataRows = excelWorkbook.Worksheet(1).RowsUsed();
foreach (var dataRow in nonEmptyDataRows)
{
//for row number check
if(dataRow.RowNumber() >=3 && dataRow.RowNumber() <= 20)
{
//to get column # 3's data
var cell = dataRow.Cell(3).Value;
}
}
}
RowsUsed method is helpful in commonly faced problems which require processing the rows of an excel sheet.
It works easily
XLWorkbook workbook = new XLWorkbook(FilePath);
var rowCount = workbook.Worksheet(1).LastRowUsed().RowNumber();
var columnCount = workbook.Worksheet(1).LastColumnUsed().ColumnNumber();
int column = 1;
int row = 1;
List<string> ll = new List<string>();
while (row <= rowCount)
{
while (column <= columnCount)
{
string title = workbook.Worksheets.Worksheet(1).Cell(row, column).GetString();
ll.Add(title);
column++;
}
row++;
column = 1;
}
I am doing an ExcelAddin in VisualStudio 2010 for Excel 2007. In my Excel Workbook I have a named range that I call MyRange. It goes from cells C10 to M25. How can I read only the cells that have value in them within MyRange. Note I don´t want to read anything from the other cells, only within MyRange? I want to read the cells that have values in them into a Word document. I think I have that figured out.
I have tried to use UsedRange but that selects everything from A1-M25 ( I only want to select the cells with value from C10-M25). Here is what I got so far.
string FileName = #"C:\MyFile.xlsx";
Excel.Application xlApp = xlApp = new Excel.Application();
Excel.Workbook xlWorkBook = null;
Excel.Worksheet xlWorkSheet = null;
xlWorkBook = xlApp.Workbooks.Open(FileName);
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
object cell1 = "C10", cell2 ="M25";
//Here are some different versions that I tried. I also tried to use the SpecialCell //method but it didn´t seem to work.
Excel.Range namedRange = (Excel.Range)xlWorkSheet.get_Range("C10", "M25");
Excel.Range last = (Excel.Range)xlWorkSheet.UsedRange;
Excel.Range usedRange = (Excel.Range)xlWorkSheet.get_Range("C10", last);
Any help is highly appreciated. Thank you.
To read each cell value from your 'namedRange' you can loop through the range like this:
foreach (Excel.Range cell in namedRange.Cells)
{
if (String.IsNullOrEmpty(cell.Value.ToString()))
{
string thisCellHasContent = cell.Value.ToString();
string thisCellAddress = cell.Address.ToString();
}
}