До бесконечности и дальше в VBA - PullRequest
28 голосов
/ 09 февраля 2012

Этот пост о возвращении значений .NET NaN и Inifinite обратно в Excel 2010 VBA.

Я использую метод C # не под моим контролем, который (по-видимому) может возвращать .NET NaN или Neg, Pos Infinity. Результаты в VBA странные (т. Е. Более странные, чем обычно), и единственный способ, которым я смог придумать, чтобы справиться с ситуацией, - это сложное сравнение трех строк «-1. # IND» или «-1. # INF». или "1. # INF".

Есть ли лучший способ?

Я задокументировал странную часть здесь, если вам любопытно. (Примеры для NaN, но это же история для pos или neg infinity.)

double  dVal  =  CSharpMethodReturningDouble()  ' via .NET assembly / COM interop
variant vVal  =  CSharpMethodReturningDouble()  ' via .NET assembly / COM interop

Если метод C # возвращает double.NaN, то имеем (в окне immed):

?dVal               
 -1.#IND            
?vVal                
 -1.#IND             

(в штучной упаковке) вариант, содержащий NaN-тесты, положительные для числовых, тип = double

?IsNumeric(vVal) 
 True
?TypeName(vVal)
 Double

Сравнение работы (в штучной упаковке) варианта NaN, но с противоположными результатами, которые вы ожидаете. Сравнения по (без коробки) двойным числам вызывают исключения переполнения

?vVal=1          '<== NaN comparisons should always return false
 True               
?vVal=0          '<== that's not what you get with -1.#IND
 True               
?dVal=0          '<== strangely, the same comparison on the unboxed double fails
 (OverFlow Exc)

Операции над вариантом (в штучной упаковке) вызывают исключения переполнения Операции над (без коробки) удваивают работу (и возвращают -1. # IND, как и ожидалось)

?vVal * 1.1      '<== even stranger, for arith ops its the boxed value that fails
 (Overflow Exc)
?dVal * 1.1      '<== but the operation on the unboxed double goes through
-1.#IND 

IsError, IsNumeric не помогает:

?IsError(vVal)
 False            
?IsError(dVal)
 False            
?IsNumeric(vVal)
 True       
?IsNumeric(dVal)
 True            

Всегда можно использовать сравнение строк для проверки:

?vVal = "-1.#IND"
True
?dVal = "-1.#IND"
True

Ответы [ 3 ]

2 голосов
/ 15 февраля 2012

Поскольку поле Double.NAN представляет значение, которое не является числом, вы, скорее всего, на правильном пути, используя сравнение строк.

Если вы шли другим путем (то есть, передавая значения из VB), ByRef и ByVal являются обычными подозреваемыми.

Функция VB IsNumeric () не всегда интуитивно понятна. Например, он вернет True, если буквенно-цифровой код случайно окажется номером в научной нотации.

1 голос
/ 07 марта 2012

Я согласен с Дэвидом, что ваш текущий обходной путь приемлем.Обязательно протестируйте установку на иностранном языке!

Этот пример может быть частью решения: значение, равное 1 и 0 одновременно, не является нормальным числом.Этот тест может отличить NaN от нормальных чисел.Возможно, вы можете найти похожие правила, как это, чтобы найти +/- бесконечность.

0 голосов
/ 11 февраля 2015

Убедитесь, что вы принимаете во внимание текущую локаль. NaN может быть "-1.#IND" или "-1,#IND" в зависимости от настроек десятичного разделителя.

Одним из способов избежать этого может быть сравнение InStr:

InStr(CStr(dVal), "#IND") <> 0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...