My aim is to check line per line in the Sheet1 in order to discover how many rows are, so i put a do\while that should stop once it reaches a blank cell
Example:
row1 data row2 data row3 datarow4 datarow5 data
row6 data row7 data
In this case I need only the first 5 rows, so the do\while check is intended to stop once it reaches the blank cell. This doesn't happens, because the check doesn't loop (it stops after completing a circle like it finds a blank cell even if it is filled with data).
string str;
int rCnt = 11; //the data I need is after the 10th row in excel
int cCnt = 1;
int valori = 1;
Excel.Application xlApp = new Excel.Application();
Excel.Workbook xlWorkbook = xlApp.Workbooks.Open(label4.Text, 0, false, 5, "", "",
false, Excel.XlPlatform.xlWindows,
"", true, false, 0, true, false,
false);
Excel.Sheets xlsheet = xlWorkbook.Worksheets;
string sheet1 = "Sheet1";
Excel.Worksheet xlWorksheet = (Excel.Worksheet)xlsheet.get_Item(sheet1);
Excel.Range xlCell;
do
{
rCnt++;
str = "A" + rCnt;
xlCell = (Excel.Range)xlWorksheet.get_Range(str, str);
} while (xlCell.Value2 == null);
I tried changing Value2 to Value or Text and trying to set == "" instead of null.
If you want the loop stop when reach blank cell then .. Try to change
while (xlCell.Value2 == null);
with
while (! IsNull(xlCell.Value2));
Simple way to check a cell is empty:
if (sheet.Cells[4,3] == null || sheet.Cells[4,3].Value2 == null || sheet.Cells[4,3].Value2.ToString() == "")
MessageBox.Show(“cell on row 4 col 3 is empty”);
You can use the Text property of the selected cell. It can be converted to a string type via "as". The result string can already be checked as usual in C#, like not-empty
string TempText = excelWorksheet.Cells[1, 1].Text as string;
if (!string.IsNullOrWhiteSpace(TempText)){
// actions
}
The issue mainly comes from when you don't know what sort of data to expect. When I work with Excel reads I often do something similar to:
var _cell = range.Cells[1, 2].Value2;
if (_cell.GetType() != typeof(Double))
In your instance if you always are getting a string returned then you should be able to assume the cast:
string _str = (string)(range.Cells[str, str] as Excel.Range).Value2;
and then check that is not empty.
This is working for me:
using Excel = Microsoft.Office.Interop.Excel; to read excelsheet:
var excelApp = new Excel.Application();
Excel.Workbook excelWorkbook = excelApp.Workbooks.Open(path, 0, false, 5, "", "", false, XlPlatform.xlWindows, "", true, false, 0, true, false, false);
Excel.Worksheet excelWorksheet = (Excel.Worksheet)excelWorkbook.Sheets[2];
Excel.Range excelRange = excelWorksheet.UsedRange;
int rowCount = excelRange.Rows.Count;
int colCount = excelRange.Columns.Count;
string wwdEmpty = Convert.ToString(excelRange.Cells[5, 14].value2);
// this is working code with NULL Excell cell
do
{
rCnt++;
str = Sheet.Cells[rCnt, 5].Value;
} while (str != null);
Related
I can use XlCellType.xlCellTypeLastCell to find last cell in the used range. How to get first cell in one line ?
Code to get last cell position.
Excel.Range mergeCells = (Excel.Range)mergeSheet.Cells[6,1].EntireRow;
var rowRng = mergeCells.SpecialCells(XlCellType.xlCellTypeLastCell, Type.Missing);
var colPosition = rowRng.Column;
One way is to get mergeCells.value and loop through to increment a counter until I see null/empty value. But I was hoping to get this in one line.
Any ideas ?
Test Cases:
(1)
Expected Result colPosition = 1
(2)
Expected Result colPosition = 5
Here is a solution using the Excel Interop library (as tagged in the question). The below method will return a 1-based column index of the first cell in a given row. It worked for me on your supplied test cases as well as a few of my own. Note that if you wish to simply use the first row in the used range - rather than a supplied row, you can find the first used row number using ActiveSheet.UsedRange.Rows[1].Row.
public static int FindFirstCellInExcelRow(string filePath, int rowNum)
{
Excel.Application xlApp = null;
Excel.Workbook wkBook = null;
Excel.Worksheet wkSheet = null;
Excel.Range range = null;
try
{
xlApp = new Excel.Application();
wkBook = xlApp.Workbooks.Open(filePath);
wkSheet = wkBook.ActiveSheet;
range = wkSheet.Cells[rowNum, 1].EntireRow;
if (range.Cells[1, 1].Value != null)
{
return range.Cells[1, 1].Column;
}
var result = range.Find(What: "*", After: range.Cells[1, 1], LookAt: Excel.XlLookAt.xlPart, LookIn: Excel.XlFindLookIn.xlValues, SearchOrder: Excel.XlSearchOrder.xlByColumns, SearchDirection: Excel.XlSearchDirection.xlNext, MatchByte: false, MatchCase: false);
int colIdx = result?.Column ?? 0; // return 0 if no cell in row contains value
return colIdx;
}
finally
{
wkBook.Close();
Marshal.ReleaseComObject(xlApp);
Marshal.ReleaseComObject(wkBook);
Marshal.ReleaseComObject(wkSheet);
Marshal.ReleaseComObject(range);
xlApp = null;
wkBook = null;
wkSheet = null;
range = null;
}
}
I highly (x10) recommend using ClosedXML over Microsoft's Excel libraries (unless you are using the old xls files). Using ClosedXML you would do the following (this is taken right from their webpage):
Get it right off the NuGet packages. Install-Package ClosedXML -Version 0.93.1
https://github.com/ClosedXML/ClosedXML/wiki/Finding-and-extracting-the-data
var wb = new XLWorkbook(northwinddataXlsx);
var ws = wb.Worksheet("Data");
// Look for the first row used
var firstRowUsed = ws.FirstRowUsed();
// Narrow down the row so that it only includes the used part
var categoryRow = firstRowUsed.RowUsed();
// Move to the next row (it now has the titles)
categoryRow = categoryRow.RowBelow();
// Get all categories
while (!categoryRow.Cell(coCategoryId).IsEmpty())
{
String categoryName = categoryRow.Cell(coCategoryName).GetString();
categories.Add(categoryName);
categoryRow = categoryRow.RowBelow();
}
try the below code snippet, this will give the first row of a excel used range
Excel.Workbook xlWB = Globals.ThisAddIn.Application.ActiveWorkbook;
Excel.Worksheet xlWS = xlWB.ActiveSheet;
int firstRow = xlWS.UsedRange.Row;
I am creating a simple application in C# where I am saving the data in an already created Excel sheet. To do this, first I am reading the data from the rows and if that row is empty that means I have to save my new data in it. I have an excel sheet with following details:
S.No | Name | Email ID | Phone Number
So I first check which is the last S.No. Let's say if it is 4, this means I have to enter data in 6th row with S.No = 5 because one row is taken by the header.
To do this I am first opening the excel file and then scanning the rows. I am able to scan it but when I try to save it, it replace the current file with new one and old data is lost. Here is what I am doing:
Excel.Application xlApp = new Excel.Application();
Excel.Workbook xlWorkbook = xlApp.Workbooks.Open("<filepath>", 0, true, 5, "", "", true, Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
Excel._Worksheet xlWorksheet = (Excel._Worksheet)xlWorkbook.Sheets[1];
Excel.Range xlRange = xlWorksheet.UsedRange;
int rowCount = xlRange.Rows.Count;
int colCount = xlRange.Columns.Count;
for(parse = 2; parse <= 100; parse++)
{
if (xlRange.Cells[parse, 1].Value2 != null)
{
Sno++;
}
else
{
break;
}
}
//Sno contains the recent serial number
After this I am just filling the data and saving the file:
xlWorksheet.Cells[Sno + 2, 1] = Sno + 1;
xlWorksheet.Cells[Sno + 2, 2] = NameTextBox.Text;
xlWorksheet.Cells[Sno + 2, 3] = EmailIdTextBox.Text;
xlWorksheet.Cells[Sno + 2, 4] = PhoneNumberTextBox.Text;
xlWorksheet.SaveAs("<filepath>");
xlWorkbook.Close();
xlApp.Quit();
But at the time of saving it says file already exit because I am doing SaveAs. Is there any way to just save the file or any other alternative.
Please help.
For saving see this
Also consider the workaruond I said in comment.
I have an excel file in which some cell values are generating dynamically using macro.
File is also read-only.
I have to read these dynamically generated values using c# code.
Use following macro code to generate cell values:
**Sub abc()
Range("E5").Value = "string"
Range("E6").Value = 2
End Sub**
Thank You...!
Check if you need to connect to already opened excel file.
If you use excelApp.Workbooks.Open, it is not reflecting sheet data updated by macros.
Instead, try BindToMoniker method as follows:
private void btnGetXLSValue_Click(object sender, EventArgs e)
{
object _row = 5;
object _column = 5;
Excel.Application excelApp = new Excel.Application();
excelApp.Visible = false;
excelApp.ScreenUpdating = false;
excelApp.DisplayAlerts = false;
Microsoft.Office.Interop.Excel.Workbook excelWorkbook ;//= excelApp.Workbooks.Open(#"C:\July.xlsm", 0, false, 5, "", "", false, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "", true, false, 0, true, false, false);
//Get a reference to the Workbook object by using a file moniker.
//The xls was saved earlier with this file name.
excelWorkbook = (Excel.Workbook)System.Runtime.InteropServices.Marshal.BindToMoniker(#"C:\July.xlsm");
Microsoft.Office.Interop.Excel.Sheets excelSheets = excelWorkbook.Worksheets;
string currentSheet = "July 2015";
Microsoft.Office.Interop.Excel.Worksheet excelWorksheet = (Microsoft.Office.Interop.Excel.Worksheet)excelSheets.get_Item(currentSheet);
Microsoft.Office.Interop.Excel.Range range = (Microsoft.Office.Interop.Excel.Range)excelWorksheet.UsedRange;
string sValue = (range.Cells[_row, _column] as Microsoft.Office.Interop.Excel.Range).Value2.ToString();
//string sValue = (range.Cells[_row, _column] as Microsoft.Office.Interop.Excel.Range).get_Value(range).ToString();
MessageBox.Show(sValue);
}
Im reading an Excel document from C# Windows Form.. There are 25 worksheets in Excel Workbook.. i can read 1st worksheet successfully.. But when i change it to worksheet 2.. it won't working at all.. Im not using OLEDB..
I want to read 100 Row in every sheet.. following is my code...
` dt.Columns.Add("Amount", typeof(double));
dt.Columns.Add("ChequeNo", typeof(int));
dt.Columns.Add("month", typeof(int));
int AmountRow = 100;
int ChequeNoRow = 101;
int Column = 3;
xlApp = new Excel.ApplicationClass();
xlWorkBook = xlApp.Workbooks.Open(path, 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Sheets[2];\\This place is the changing worksheets
range = xlWorkSheet.UsedRange;
double chequeAmount;
double chequeNo;
for (int i = Column; i < 15; i++)
{
chequeAmount = (double)(range.Cells[AmountRow, i] as Excel.Range).Value2;
chequeNo = (double)(range.Cells[ChequeNoRow, i] as Excel.Range).Value2;
if (chequeNo != 0.0)
{
dt.Rows.Add(Convert.ToDouble(chequeAmount), Convert.ToInt32(chequeNo), i);
}
}
dataGridView1.DataSource = dt;
xlWorkBook.Close(true, null, null);
xlApp.Quit();
releaseObject(xlWorkSheet);
releaseObject(xlWorkBook);
releaseObject(xlApp);`
releaseObject methods are not here.. those working perfectly...
`xlWorkSheet = (Excel.Worksheet)xlWorkBook.Sheets[1];`
This is how i change my worksheets.. The following line gives an exception..[Null point Exception]
chequeAmount = (double)(range.Cells[AmountRow, i] as Excel.Range).Value2;
Hope you'll know answers..
Try this instead:
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets[2];
The Sheets property can include non-worksheet sheets, which could be the issue in your scenario.
I've written this code to count the number of rows that are populated in an excel worksheet. It works until it gets yo a certain number of rows (not the total). Then comes up with the error message "Exception from HRESULT: 0x800A01A8" Any help much appreciated
namespace ConsoleApplication1
{
class ExcelClass
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
Excel.Application excelApp = new Excel.Application(); // Creates a new Excel Application
excelApp.Visible = true; // Makes Excel visible to the user.
// The following code opens an existing workbook
string workbookPath = "D:\\RSG_D.xls"; // Add your own path here
Excel.Workbook excelWorkbook = excelApp.Workbooks.Open(workbookPath, 0,
false, 5, "", "", false, Excel.XlPlatform.xlWindows, "", true,
false, 0, true, false, false);
// The following gets the Worksheets collection
Excel.Sheets excelSheets = excelWorkbook.Worksheets;
// The following gets Sheet1 for editing
string currentSheet = "Sheet1";
Excel.Worksheet excelWorksheet = (Excel.Worksheet)excelSheets.get_Item(currentSheet);
//declare a variable to hold the CurrentCulture
System.Globalization.CultureInfo oldCI;
//get the old CurrenCulture and set the new, en-US
//void SetNewCurrentCulture()
//{
oldCI = System.Threading.Thread.CurrentThread.CurrentCulture;
System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
//}
int rowCounter = 1;
while ( rowCounter != null)
{
Excel.Range countRows = (Excel.Range)excelWorksheet.Cells[rowCounter, 1] as Excel.Range;
object CountRows = countRows.Value;
rowCounter++;
Console.WriteLine(CountRows);
}
excelWorkbook.Close(0);
excelApp.Quit();
//reset Current Culture back to the originale
System.Threading.Thread.CurrentThread.CurrentCulture = oldCI;
}
}
}
I had the exact same problem tonight: Here is the code I have used and it's worked properly for me:
Excel.Application oExcel = new Excel.Application();
//oExcel.Visible = true; (this caused me huge problems
Excel.Workbook oBook = oExcel.Workbooks.Open(#"C:\Yoink\Birr Castle Demesne Interactive Map\Birr Castle Demesne Interactive Map\bin\Debug\Red Tree Trail.xlsx");
Excel.Worksheet oSheet1 = oBook.Worksheets["Red Tree Trail"] as Excel.Worksheet; (use your own worksheet title there)
Excel.Range rng = oSheet1.get_Range("A1", "AJ51"); (use your own range there
int rowCount = rng.Rows.Count;
int colCount = rng.Columns.Count;
string[,] tsReqs = new string[rowCount, colCount];
for (int i = 1; i <= rowCount; i++)
{
for (int j = 1; j <= colCount; j++)
{
string str = rng.Cells[i, j].Text;
tsReqs[i - 1, j - 1] = str;
}
}
I think your problem is in this line:
Excel.Workbook excelWorkbook = excelApp.Workbooks.Open(workbookPath, 0,
false, 5, "", "", false, Excel.XlPlatform.xlWindows, "", true,
false, 0, true, false, false);