Apache POI: Get more detail for formula error - apache-poi

My application puts values into a workbook with Apache POI and then evaluates formulas at that workbook. The formulas in the workbook are large: one contains a lot of references to other cells and those also contain formulas with additional references and so on. So far this works.
But when one of those formulas contains an error, it is hard to identify from which cell/formula the error comes from, because the error could be in the evaluated cell or in one of the referenced or in one of the referenced of the referenced (and so on).
With this code I get the type of the error (e.g. REF, DIV0, NAME, NUM, ...):
evaluator.evaluateFormulaCell(mycell);
if (mycell.getCellType() == CellType.FORMULA) {
switch (mycell.getCachedFormulaResultType()) {
case ERROR:
System.out.println(FormulaError.forInt(mycell.getErrorCellValue()).getString()));
break;
}
}
How can I get more detail about the error?
And more specific: How do I get the information where it comes from?

Related

VLOOKUP results in #N/A with Exact Match

Using Microsoft 365 Excel.
In cell K2, I have:
=VLOOKUP(F2,METERS,2,FALSE)
In cell L2:
=VLOOKUP(G2,KNOTS,2,FALSE)
The result in L2 is what I expect.
No matter what I do to the equation or anywhere in the workbook, I keep getting #N/A in K2.
When I replace the named range in K2, METERS for KNOTS, the function evaluates properly.
Copying the named range works properly, so there's nothing wrong with the named range:
=METERS
returns the complete named range without errors.
Checking the value in F2 evaluates as TRUE, so the value is an exact match:
=(F2=MS!A210)
Oddly enough, if I change the function in K2:
=VLOOKUP(F2,METERS,2,TRUE)
then it sort of works, in that it gives me a value instead of #N/A, but doesn't give me exactly the result I need.
I tried moving the function from K2 to different cell and using a different cell for the lookup value; then no matter what I input, I get 0.
I know the syntax in K2 is correct. The named range is correct. Everything seems to be correct.
Yet no matter what, I get #N/A.
Here/screenshot(s) refer:
Given the info you have provided, the only reasons I can think of why this could occur are:
a) Conflicting named ranges with common names/different scopes
b) Inconsistency between the two named ranges you're using
These aren't mutually exclusive (a different scope could lead to an inconsistency). I'll demonstrate the following in this solution:
No issues arise when using two different names that refer to the exact same range / sheet / scope
How easily issues can arise due to duality of scope (e.g. worksheet vs. workbook) for common names, and how either of these can be referenced anywhere in the workbook
Finally, I'll comment on the 'true/false' indicator in the vlookup function you mentioned, and propose an alternative / improved feature avail. with Office 365.
Context
Conflicts RE: named ranges can arise in several ways - e.g. when multiple sheets contain named ranges that have common names, when copying a function that comprises a named range from one sheet to another, etc. It's possible to produce a conflict from one workbook to another in this fashion too.
When copying such a function from one sheet to another you should see the something like the following UI appear:
Sheet 1 - correct referencing
Comprises two named ranges (range_1, range_2 resp.) which both refer to the exact same range (with identical scopes). Vlookups operate perfectly fine and produce identical results:
Besides their name, range_1 and range_2 are otherwise identical in every way per the following in Name Manager:
Sheet 2 - conflict / error
Copy of Sheet 1, with range_1 amended to only include the 1st column - the same vlookup functions as Sheet 1 now produce an error for range_1:
Note: copying the functions from Sheet 1 have now produced the following in Name Manager:
However, I'm still able to reference range_1 from Sheet 1 per the following tooltip that appears when I start typing '=range_1' in any cell within Sheet 2:
Thus its possible to retrieve what appears to be the 'correct' range for range_1 in any cell in the workbook by referencing the original scope (workbook), despite the vlookup in Sheet 2 producing an error.
It this is not the case (and you do not have 'duality' in scopes for the same named range) then the only other reason I can think of is inconsistency RE: formulation. If they are truly identical in the ranges they reference, then I would suggest adopting a single name (KNOTS, given this appears to function correctly) to simplify the workbook/functions and improve auditability.
Vlookup parameter (0/1)
RE: vookup(range, lookup, True/False) -
True (i.e. '1') parameter will return an 'approximate' match (which distinguishes this function from alternatives such as index/match). However, xlookup is advisable / preferred over vlookup in any case given it also has this feature and can reference to the left or right of the lookup column (vlookup works strictly to the right). Although it is more complex with additional parameters/arguments to consider. See here for details.

Excel Formula with OFFSET Fails When Copied to Different Sheet

I've been struggling with this longer than I care to admit, but I have a fairly simple OFFSET function call which works on one sheet, but if I copy it to a different sheet it gives a #VALUE error.
On a sheet named "Deliverable" I have this formula in a cell:
=OFFSET(Deliverable!$B$72,1,0,,3)
and it works fine.
If I go to any other sheet and use the same exact formula, or use it in the Name Manager, it gives a #VALUE error.
If I leave off the final parameter indicated the number of columns I want, it does work:
=OFFSET(Deliverable!$B$72,1,0)
but of course isn't giving me the range I need.
Any idea what's going on with this?
I'm using Excel 2016 on Windows 7.
-- Updated Info --
In a nutshell, my spreadsheet has two cells which I'm using as dropdown lists, where the 2nd cell's list feeds off the selection in the first. The data they are based on has this format:
OptionA A B C D
OptionB A B
OptionC D E F
So the first dropdown uses a simple Data Validation source pointing to the column with OptionA, OptionB, etc. Once that's chosen, the second dropdown list should contain the appropriate options for the one selected. So if OptionB is selected, then the 2nd dropdown list should show A and B.
When I initially wrote this, the data validation source was just a simple VLOOKUP entry, but the lists often had blanks since the number of options varies for each entry. Wanting to fix it up a bit, I ended up with this formula:
=OFFSET(Deliverable!B72,Deliverable!B87,0,1,COUNTA(OFFSET(Deliverable!B72,Deliverable!B87,0,1,5)))
There won't be any more than 5 options, and there are no empty cells in the middle of the data to filter out.
In one spreadsheet I have I used this as a named range definition, then specified the named range for the cells data validation source and it worked. In this other spreadsheet however, it gave me the error described earlier.
However, it looks like when I enter the statement directly into the data validation source field and not in the name manager, it works as expected.
Am I taking the totally wrong approach?
What is it that you want this formula to do? As written, it is returning a block of three horizontal cells. The #VALUE error is Excel's way of telling you "Hey, you're trying to return three cells, but I can't fit them all in the one cell that you are calling this formula from".
The reason you see a result in some places and not others is because of something called Implicit Intersection. Give it a spin on Google. But basically, it just returns whichever one of those three results corresponds to the column that the formula is entered into. If you copy that exact same formula to say row F you will see that it returns a #VALUE error there, because it doesn't know what cell it should return given the column you're calling it from doesn't match any of the cells it is returning. The fact that you don't know this indicates that the formula you're using doesn't in fact do what you think it does.
--UPDATE --
Okay, following your further clarificaiton it seems that you're talking about Cascading Dropdowns aka Dynamic Dropdowns. Lots of info on Google about how to set these up, but you may be interested in an approach I blogged about sometime back that not only provides this functionality, but also ensures that someone can't later on go and change the 'upstream' dropdown without first clearing the 'downstream' one should they want to make a change.
Note that those links talk about a slightly complicated method compared to others, but the method has it's advantages in that it also handles more levels than two, and your DV lists are easily maintained as they live in an Excel Table.
This sounds like an array equation. Try hitting Ctrl+Shift+Enter in the other sheets to validate it as an array equation.
Whenever you need to reference ranges instead of single cells, Excel needs to know that you are working with arrays.

Excel Vlookup error

I have a spreadsheet that is stored in a shared location on a website that I need to do a Vlookup on in order to gather certain data. In order to test I have a Workbook stored in my documents. I have some VBA in this workbook but this does not affect the data in question.
The Formula that I am attempting is
=VLOOKUP("activated",$A4,4,TRUE)
What I need to do is to pull data from several columns in this sheet but I have not used Vlookup in a long time so I am trying to start small. I have formatted all of the cells to general but this has not helped.
I have also tried
=VLOOKUP("activated",$A2:$A71,4,TRUE)
However I constantly get the #REF error
Putting the following will return Activated so I know that in principal the formula is correct
=VLOOKUP("activated",$A2:$A71,1,TRUE)
I have looked at the answer submitted in Excel VLOOKUP #REF Error but this has not resulted in the correction of my errors
Any help would be greatly appreciated
The third argument is the column that you want to return... As there is only 1 column in the range $A2:$A71 you can't put 4 as the argument...
You probably need =VLOOKUP("activated",$A2:$D71,4,TRUE)
Also you should probably use FALSE for your last argument, as this can return the next closest match, if you use TRUE.
Range_lookup A logical value that specifies whether you want VLOOKUP to find an exact match or an approximate match:
http://office.microsoft.com/en-gb/excel-help/vlookup-HP005209335.aspx

Excel "Don't update links" not working. I specifically tell Excel not to update my links, and it does it anyway, giving me an the #VALUE! error

I have a spreadsheet which uses the OFFSET function in several cells.
It refers to date in another spreadsheet.
When I open the file, I don't want Excel to update the links but instead keep the values. I click "Don't update", but it does it anyway giving me the VALUE! error.
Same thing happens on different computers. How do I stop this?
Thanks!
For some reason, OFFSET requires the workbook to be open. Many OFFSET formulas can be changed to an INDEX function that does not have the same restrictions
=OFFSET('C:\...\[Main Database.xlsx]Technical'!$S481, (ROW(B14) -1)*1,0)
would be re-written as
=INDEX('C:\...\[Main Database.xlsx]Technical'!$S:$S, (ROW(B14) -1)*1+481)
(path removed to avoid scroll bars when looking at solution)
The cell is changed to a column reference: $S481 -> $S:$S
The previous cell row is added to the index: (ROW(B14) -1)*1 -> (ROW(B14) -1)*1 + 481
Column not needed, as you have 0
If you have a 3rd or 4th parameter to the offset function then index will not work, but you could add another sheet that has a simple ='C:\...\[Main Database.xlsx]Technical'!A1 (and all other cells needed to be referenced) and then reference that sheet with the offset, instead of the original workbook

What's wrong with using this named range for List validation?

I have a column of data that will have more values added to it over time. I would like to use this column's values for List validation on another worksheet, such that the drop-down options reflect the current contents of the column. I tried creating a named range ListColumn with the following formula:
=ADDRESS(3,12,1,1,"DataSource")&":"&ADDRESS(COUNTA('DataSource'!$L:$L),12,1,1,"DataSource")
When I try to add validation for a cell, choosing Allow: 'List' and entering =ListColumn in the formula box, I get this error message:
The list source must be a delimited list, or a reference to a single row or column.
I tried wrapping the whole formula in an INDIRECT(), and while that didn't generate an error on the Name Manager screen, when I tried to add the validation, I got this error message:
The Source currently evaluates to an error. Do you want to continue?
I'm not sure what's wrong here. The second parameter of both ADDRESS() calls is the same, so the range address should refer to a single column. How can I set up the dynamic list validation that I'm looking for?
EDIT: Debugging this is producing some odd behavior. I keep getting a run-time error when I try to select ListColumn using Range("ListColumn").Select. Message is "Method 'Range' of object '_Global' failed."
Entering =ListColumn returns: 'DataSource'!$L$3:'DataSource'!$L$65, which is the expected value.
Also, when I enter the formula =COUNTA(ListColumn) it returns "1", but when I enter the formula =COUNTA('DataSource'!$L$3:'DataSource'!$L$65) it returns the correct value of "63". =COUNTA(INDIRECT(ListColumn)) also returns "1".
I believe the issue may be the inclusion DataSource as the text sheet name in the second ADDRESS block. I get the exact same behavior as you do when performing your steps above, but it seems to work with this:
=INDIRECT(ADDRESS(3,12,1,1,"DataSource")&":"&ADDRESS(COUNTA(DataSource!$L:$L),12,1,1))
You can then do exactly what you did above and use it in a drop-down. My best assumption would be that since you are already defining the sheet in the first portion of the address, you do not need to provide it in the second portion (and it will cause an error if you do). If you think about it from a program perspective, it makes sense (I think :) ), since it would be difficult/impossible to refer to ranges over multiple sheets, and therefore the syntax likely doesn't allow for a second sheet to be specified after the colon (even if it is the same). That is just conjecture though (probably wrong), so hopefully the solution works :)

Resources