My excel has millions of records (approx 1.1M) and when I am trying to read cell by cell using WorkSheet.Cells[row,cloumn] it is very slow.
Rather if I use, WorkSheet.Cells.CheckCell(row, column) performance is very good.
Can you please let me know the difference between these two API's
Worksheet.Cells.CheckCell() is the most right way to check if the cell exists or not.
CheckCell method will not instantiate the cell if it does not exist. On the other hand, Cells[r, c] will instantiate the cell if it does not exist.
It means,
CheckCell can return null or cell object.
But Cells[r, c] will never return null and will always return cell object.
Since Cells[r, c] will always return cell object and if it does not already exist, it will create it, this is why, it affects the performance. If you want to iterate all the existing cells in your worksheet without creating new cells, please use Worksheet.Cells.GetEnumerator() method.
Please see the following sample code, its comments and console output for a reference.
C#
//Create a workbook
Workbook wb = new Workbook();
//Access first worksheet
Worksheet ws = wb.Worksheets[0];
//At the moment, Cell B4 does not exist
//Therefore check cell will return null
Cell cell = ws.Cells.CheckCell(3, 1);
Console.WriteLine(cell == null); //<<<<<<<<<< It will print - True
//After this statement, cell B4 will be instantiated and it will exist
var o = ws.Cells[3, 1];
//Now check cell will not return null, but it will return cell B4
cell = ws.Cells.CheckCell(3, 1);
Console.WriteLine(cell == null);//<<<<<<<<<< It will print - False
Console Output
True
False
Update - 1
Please see the following sample code, its comments and console output. It illustrates that GetEnumerator() method returns non-empty and empty cells as well.
C#
//Create a workbook
Workbook wb = new Workbook();
//Access first worksheet
Worksheet ws = wb.Worksheets[0];
//Create empty cells
//Cell A4, B6, C8 and D10 all are empty
var o = ws.Cells["A4"];
o = ws.Cells["B6"];
o = ws.Cells["C8"];
o = ws.Cells["D10"];
//Get cells enumerator
var i = ws.Cells.GetEnumerator();
//Iterate all cells
while(i.MoveNext())
{
Cell cell = i.Current as Cell;
//Print cell name
Debug.WriteLine(cell.Name);
}
Console Output
A4
B6
C8
D10
Note: I am working as Developer Evangelist at Aspose
Related
I am trying to generate an Excel sheet using Exceljs on NodeJS.
I need to get a particular cell (E4) for which I have this code written.
var row = worksheet.getRow(4);
var compInfra = row.getCell(5);
The cell ('E4') contains a value as the result of a formula ('E4 = C4+D4'), which I have defined previously. C4 and D4 contain non zero numbers.
I need to use this resultant value of the formula in a subsequent statement as below:
row = worksheet.getRow(20);
row.getCell(5).value = compInfra * worksheet.getCell('A20');
I get no output on my Excel sheet at 'E20', since the value in 'E4' is a result of the formula.
If I choose any other cell with some value instead of a formula, I get the result correctly.
How do I address this issue.
Thanks in advance
worksheet.getCell('E4').value = { formula: 'C4+D4' };
worksheet.getCell('C4').value = 7;
worksheet.getCell('D4').value = 5;
https://github.com/exceljs/exceljs#formula-value
I have a workbook with a number of cells that have data validation specified as a dropdown list of allowed values. Using EPPlus, I want to be able to get for each such cell, the list of allowed values.
So far I've got:
ExcelWorkSheet.DataValidations gives me an ExcelDataValidationCollection, which is a collection of IExcelDataValidation items for the worksheet.
Each IExcelDataValidation has an Address property of type ExcelAddress which presumably references all cells that have that validation rule.
The step I'm stuck on is finding if a given cell is one of the cells included in the ExcelAddress
Any takers?
I'm currently using EPPlus 3.1.1.0, but can upgrade to a more recent version if necessary.
UPDATE
I didn't explain this clearly enough. Here's my situation in more detail.
Assume column C has some cells with list data validation. Some cells allow, say, "A, B, C"; other cells allow "D, E, F" etc. The range of cells for each data validation list is not contiguous, so, for example:
C2, C4, C7-C10, C20 may allow "A,B,C"
C3, C5-C6", C15 may allow "D,E,F"
I'm trying to determine which cells allow "A,B,C" and which allow "D,E,F" etc.
ExcelWorksheet.DataValidations contains ExcelDataValidationList items, one with values "A,B,C", one with values "D,E,F", etc.
ExcelDataValidationList.Address for the list "A,B,C" contains an ExcelAddress whose Address property looks something like: "C4 C7:C10 C2 C20 ...".
I want to determine if a given cell (say C6) is included in the range specified by this address "C4 C7:C10 C2 C20 ...".
Of course, I can String.Split on whitespace, and parse each item in the resulting list. But I was hoping there would be some more direct way of doing this, e.g.
ExcelAddress.Contains("C6")
or
ExcelAddress.Contains(6, 2) // row 6 col 2 = C6
Almost there, just check the IExcelDataValidation's specific type. Tested with EPPlus 4.1.0.0:
using (var package = new ExcelPackage(new FileInfo(path)))
{
var sheet = package.Workbook.Worksheets[1];
var validations = sheet.DataValidations;
foreach (var validation in validations)
{
var list = validation as ExcelDataValidationList;
if (list != null)
{
var range = sheet.Cells[list.Formula.ExcelFormula];
var rowStart = range.Start.Row;
var rowEnd = range.End.Row;
// allowed values probably only in one column....
var colStart = range.Start.Column;
var colEnd = range.End.Column;
for (int row = rowStart; row <= rowEnd; ++row)
{
for (int col = colStart; col <= colEnd; col++)
{
Console.WriteLine(sheet.Cells[row, col].Value);
}
}
}
}
}
Test worksheet:
Output:
one
two
three
I have this cell that has a formula which constantly updates its value. If the value gets to a specified number (For example: 10), I want to record its value on a different cell (For example: B2).
I'm guessing something like this would work:
If (Cell A2 = 10) {
change cell B2 into 10
}
I tried it inputting this formula on B2:
=if(A2=10,"10","")
The problem is, once A2 changes again, B2 changes as well. Is there any way to prevent this?
See if this works for you.
=if(A2=10,"10",if (A2<> 10,"10"))
Sorry if I misunderstood the problem. Try pasting this in the script editor.
function onEdit(){
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet()
var target = ss.getRange("A1").getValue()//Sets the Target value i.e. 10
var r = ss.getRange(2,1) //gets A2 range
var val = r.getValue()// gets A2 value (in my test A2 is =F1 which is a calculated value(=D1*E1).
if(val==target){ //If the value = the target value
ss.getRange(2,2).setValue(val) //write the value to B2
}
}
I want to get content of a cell in Excel whose value is calculated using a Formula (=D6*0.1236) and i am using HssfWorkbook and using getCell() method to get content. But i am getting D6*0.1236. I want to get the value calculated using this formula and not the formula. Please suggest some solution for this.
Below is the code to get the contents
HSSFSheet sheet = workbook.getSheetAt(1);
Row r = sheet.getRow(13);
//get the cell [a particular cell of the row obtained above]
Cell c = r.getCell(2);
You are not suppose to use getCell() to fetch a value. Try the following ,
Cell c = r.getCell(2);
System.out.println("The Cell value is " + c.getNumericCellValue());
I use poi-ooxml 3.9 to generate invoice report from an excel template I store in db. I have formulas at the end of the sheet that will do sum and other tax calculations.
cell D30 =SUM(D22:D28)
cell D31 =D30*0.12
cell D32 =D31*0.02
cell D33 =D31*0.01
cell D35 =SUM(D30:D33)
Before I write the sheet to a new file I evaluate the formulas, but nothing works. The code below is used to evaluate the formulas. Do I need to evaluate the formulas whenever I write the values into the cells or only at the end of the operation?
String formulaCells[] = { "D30", "D31", "D32", "D33", "D35" };
FormulaEvaluator formulaEvaluator = workBook.getCreationHelper()
.createFormulaEvaluator();
Sheet sheet = workBook.getSheetAt(0);
for (String cellRef : formulaCells) {
CellReference ref = new CellReference(cellRef);
Row actualRow = sheet.getRow(ref.getRow());
Cell cell = actualRow.getCell(ref.getCol());
if (cell != null) {
// here I evaluate the formula
formulaEvaluator.evaluateFormulaCell(cell);
anything I have missed?
Note: Only after I open the generated sheet and press enter in every cells the formulas are evaluated!
Are you sure that your cell are added as number?
if not, try to do something like this:
if(type.equals("String")) {
cell.setCellValue (value.toString());
} else if (type.equals("int")) {
cell.setCellValue(Integer.parseInt(value.toString()));
} else if (type.equals("double")) {
cell.setCellValue(Double.parseDouble(value.toString()));
}