Reputation: 10995
In my last question: ExcelDNA throwing exception accessing Range.Value2
I blamed ExcelDNA for the reason why Value2 was throwing a COMException. But I'm not sure this is the case any longer.
I disables the IsMacroType flag which completely stops the COMException from happening and noticed that sometimes Range.Value2 doesn't throw an exception at all.
So sometimes it works, and sometimes it doesn't. My question is, what would cause range.Value2 to throw intermittent COMExceptions?
It's annoying because the stacktrace gives me no useful information, and IsMacroType fixes the problem entirely.
My suspicion is if a cell is constantly changing, by the time Value2 is accessed the cell might get invalidated, but it's a guess and I'm not sure how excel works.
But also, it doesn't make sense as there aren't multiple threads in the code.
Have you encountered this problem?
This is the code:
var valueCell = (Range)row.Cells[1, 30];
if (valueCell .Value2 != null)
{
//do something
}
Seriously, Value2 fails to evaluate on the if statement
Upvotes: 0
Views: 166
Reputation: 16907
I'm a bit surprised it ever works without IsMacroType=true
. It might depend on whether the cell has been calculated or not.
Excel normally prevents a UDF from reading other parts of the sheet, unless the UDF is registered as a "macro sheet equivalent" (with a # in the registration string).
Functions that are registered as "macro sheet equivalents" have the following behaviour (see towards the bottom of the documentation from xlfRegister):
Placing a # character after the last parameter code in pxTypeText gives the function the same calling permissions as functions on a macro sheet. These are as follows:
The function can retrieve the values of cells that have not yet been calculated in this recalculation cycle.
The function can call any of the XLM information (Class 2) functions, for example, xlfGetCell.
If the number sign (#) is not present: evaluating an uncalculated cell results in an xlretUncalced error, and the current function is called again once the cell has been calculated; calling any XLM information function other than xlfCaller results in an xlretInvXlfn error.
Your error in the case without IsMacroType=true
might be the last one of these - you're reading an uncalculated cell hence getting an error.
The side-effects of setting IsMacroType=true
for a UDF is not entirely clear. One effect is that functions registered as IsMacroType=true
and having a parameter that is marked as AllowReference=true
will automatically be considered volatile (even if registered with IsVolatile=false
). Another side effect is that the recalculation sequence is affected - particularly if you are reading uncalculated cells from inside your UDF.
You also have to be really careful in reading other cells from a UDF, regarding your expectation of what should recalculate when, since you are kind of undermining the calculation dependency tree. In your example your UDF is reading cell A30
, but will changes to cell A30 automatically cause your function to recalculate? Certainly you can't use the Excel dependency tracking tools to understand that your cell depends on A30
. Really you rather want to have a function that takes the explicit parameter, and is called as =DoSomething(A30)
making everything clear and avoiding all these problems.
One reason you might be trying to read Value2
is to determine the formatting of the cell instead of the underlying value that Excel stores, but that's really dangerous since it is not part of the recalculation and dependency tree.
So I would say the fact that you are seeing some unexpected behaviour is a sign that you are going in a direction that Excel does not like.
Upvotes: 1