Probably simple once i see the correct code but what is the best way to loop through a specific column in a worksheet until the end?
It's pretty simple. Just create a range object that points to the range you want to start at, then loop through each offset from that range until you get to a blank cell.
int i = 0;
while (target_range.Offset(i, 0).Value != "")
{
i++;
}
Related
I'm looking some help with my code for writing data to an Excel worksheet.
I'm currently writing data to a single cell at a time which is taking around three seconds per cell. As you can imagine, this time really starts to add up when you start to get into hundreds of cells.
I'm aware that there is a method of saving to a range of cells but not entirely sure how to do this.
The document I am writing to is a questionnaire style spread sheet with columns: Number, Question, Yes, No, NA.
I loop through a list of user controls which hold the users selected answer from my form and then write it to the cell.
Any help appreciated, thanks.
if (QuestionList.Count > 0)
{
//loop round rows
for (int i = 0; i < QuestionList.Count; i++)
{
//check that index is not null
if (!String.IsNullOrEmpty(QuestionList[i].Index))
{
//if the char in index is a letter
if (Char.IsLetter(QuestionList[i].Index[0]))
{
worksheet2.Cells[i + 1, 4].Value2 = QuestionList[i].Yes;
worksheet2.Cells[i + 1, 5].Value2 = QuestionList[i].No;
worksheet2.Cells[i + 1, 6].Value2 = QuestionList[i].NA;
}
}
}
}
The simple way to read multiple cell values in one go is to create a new Excel range, specifying the range of cells that you want to read.
You can then take the values within the range and put them into a multidimensional object array.
Then simply refer back to the cell position within the array to get values.
This will do one single read to get multiple cell values rather than a single read for each cell.
string name;
string dob;
string address;
//excel range
Excel.Range range = (Excel.Range)xlWorksheet1.Range["A1", "I10"];
//range array
object[,] rangeValueArray = range.Value2;
//cell 1A
if (rangeValueArray[1,1] != null)
{
name = rangeValueArray[1, 1].ToString();
}
//cell 1B
if (rangeValueArray[1, 2] != null)
{
dob = rangeValueArray[1, 2].ToString();
}
//cell 1C
if (rangeValueArray[1, 3] != null)
{
address = rangeValueArray[1, 3].ToString();
}
i tried Trial version of Gembox.SpreadSheet.
when i Get Cells[,].value by for() or Foreach().
so i think after Calculate() & get Cell[].value, but that way just take same time,too.
it take re-Calculate when i Get Cell[].value.
workSheet.Calcuate(); <- after this, values are Calculated, am i right?
for( int i =0; i <worksheet.GetUsedCellRange(true).LastRowIndex+1;++i)
{
~~~~for Iteration~~~
var value = workSheet.Cells[i,j].Value; <- re-Calcuate value(?)
}
so here is a Question.
Can i Get calculated values? or you guys know pre-Calculate function or Get more Speed?
Unfortunate, I'm not sure what exactly you're asking, can you please try reformulating your question a bit so that it's easier to understand it?
Nevertheless, here is some information which I hope you'll find useful.
To iterate through all cells, you should use one of the following:
1.
foreach (ExcelRow row in workSheet.Rows)
{
foreach (ExcelCell cell in row.AllocatedCells)
{
var value = cell.Value;
// ...
}
}
2.
for (CellRangeEnumerator enumerator = workSheet.Cells.GetReadEnumerator(); enumerator.MoveNext(); )
{
ExcelCell cell = enumerator.Current;
var value = cell.Value;
// ...
}
3.
for (int r = 0, rCount = workSheet.Rows.Count; r < rCount; ++r)
{
for (int c = 0, cCount = workSheet.CalculateMaxUsedColumns(); c < cCount; ++c)
{
var value = workSheet.Cells[r, c].Value;
// ...
}
}
I believe all of them will have pretty much the same performances.
However, depending on the spreadsheet's content this last one could end up a bit slower. This is because it does not exclusively iterate only through allocated cells.
So for instance, let say you have a spreadsheet which has 2 rows. The first row is empty, it has no data, and the second row has 3 cells. Now if you use 1. or 2. approach then you will iterate only through those 3 cells in the second row, but if you use 3. approach then you will iterate through 3 cells in the first row (which previously were not allocated and now they are because we accessed them) and then through 3 cells in the second row.
Now regarding the calculation, note that when you save the file with some Excel application it will save the last calculated formula values in it. In this case you don't have to call Calculate method because you already have the required values in cells.
You should call Calculate method when you need to update, re-calculate the formulas in your spreadsheet, for instance after you have added or modified some cell values.
Last, regarding your question again it is hard to understand it, but nevertheless:
Can i Get calculated values?
Yes, that line of code var value = workSheet.Cells[i,j].Value; should give you the calculated value because you used Calculate method before it. However, if you have formulas that are currently not supported by GemBox.Spreadsheet's calculation engine then it will not be able to calculate the value. You can find a list of currently supported Excel formula functions here.
or you guys know pre-Calculate function or Get more Speed?
I don't know what "pre-Calculate function" means and for speed please refer to first part of this answer.
I'm trying to get the row count of rows which don't have any value (any of columns)
Sample image of the Excel file I'm using:
Highlighted rows have some values in some columns rest of rows are blank I need to count those rows.
I already used this method
int blankRows = 0;
double notEmpty = 1;
while (notEmpty > 0)
{
string aCellAddress = "A" + (rowIndex++).ToString();
Excel.Range row = excelApp.get_Range(aCellAddress, aCellAddress).EntireRow;
notEmpty = excelApp.WorksheetFunction.CountA(row);
if (notEmpty <= 0)
{
blankRows++;
}
}
but this is very time consuming process when file is large and minimum number of blank rows is there.
One thing that might help would be to find the last column that has data and last row that has data as to limit your search.
This is VBA code snippet, but could be easily transformed to C#:
'iterate through columns to determine which is longest to determine the highest row number.
For i = 1 To 16384 'number of columns in excel
'get the row
rowcount = ws.Cells(Rows.Count, i).End(xlUp).Row
'check to see if it's larger than what it is now, if it is, set the value of lRow.
If rowcount > lrow Then
lrow = rowcount
End If
Next
then use a similar loop to get the last row based on the last row, stepping through each row until the last one to get the last column with data.
You can use those values to limit the range that you're looking through. I'm not sure if it will be any faster, but it might help.
I want to get a specific column of an excel sheet and then iterate through it's cells. I want it to look something like this:
Excel.Workbook workbook = app.Workbooks.Open(svDropPath);
Excel.Worksheet xlWorkSheet = (Excel.Worksheet)workbook.Sheets["Sheet Name"];
var col = xlWorkSheet.UsedRange.Columns["C:C", Type.Missing]; // I want the 3rd column
foreach(Cell c in col)
....
How do I actually make this foreach loop?
Your loop will looks as follow:
foreach (Excel.Range item in col.Cells)
{
//whatever you want to do with your cells, here- msgbox of cells value
MessageBox.Show(Convert.ToString(item.Value));
}
I believe there is no nice way of doing it other than to loop through the indices in question and use either Cells or Rows:
for (int i = 1; i <= max; i++)
{
Range cell = col.Cells[i, 1];
// or
Range cell = col.Rows[i];
}
However, note that if you are reading and/or writing all the cells, you are much better off reading/writing the whole column to/from an array of object, and then looping through the array items, as outlined in my answer https://stackoverflow.com/a/18058144/1737957 . Not only is this much faster, you can also use nicer language constructs for looping since you are now dealing with a straightforward C# array.
The only reason you would have to loop rather than do this AFAIK is if you were accessing something like conditional formats etc., rather than just cell contents, and you couldn't write a whole range of them in one statement. However there may be ways of doing these too using arrays.
I know how to write single cell into excel but when im trying it on array excel sheet is filling with only last value
this is my range
Excel.Range ServiceName = (Excel.Range)_sheet.get_Range(_sheet.Cells[38, "B"] as Excel.Range, _sheet.Cells[45, "B"] as Excel.Range);
_ServiceName is List which contains 1,2,3,4,5,6
for (int i = 0; i < _ServiceName.Count; i++)
{
ServiceNameArray[0, i] = _ServiceName[i];
}
this i my trying to write into excel but as i said it there is only last item (6) in excel book
for (int i = 0; i < _ServiceName.Count; i++)
{
ServiceName.set_Value(Type.Missing, ServiceNameArray[0,i]);
}
does anyone have an idea?
Davide Piras is right. And you're doing a few other strange things there, I can elaborate by request.
For now I just want to point out that you can directly assign the .Value property of a Range to an array:
ServiceName.Value2 = _ServiceName.toArray();
This is much, much faster for bigger amounts of data.
(Side note: If you want to do the same with Formulas, for some strange reason you have to take an extra step (doubling the time):
range.Formula = array;
range.Formula = range.Formula;
unless there is a better way I don't know about yet.)
I see you looping on the ServiceName array to get all values one after the other but not see you changing the focused cell inside the cellrange at every loop iteration. Of course, I would say, you see only the last value, because you are writing all values one over the other always in the same place.