27 votes

L'infini et au-delà en VBA

Cet article traite des valeurs NaN et Inifinies de .NET qui sont transmises à Excel 2010 VBA.

J'utilise une méthode C# sur laquelle je n'ai aucun contrôle et qui peut (apparemment) renvoyer des NaN .NET ou des Neg,Pos Infinity. Les résultats dans VBA sont bizarres (c'est-à-dire plus bizarres que d'habitude), et la seule façon que j'ai trouvée pour gérer la situation en toute sécurité est une comparaison inélégante à trois chaînes "-1.#IND" ou "-1.#INF" ou "1.#INF".

Y a-t-il un meilleur moyen ?

J'ai documenté la partie bizarre ici si vous êtes curieux. (Les exemples sont pour NaN, mais c'est la même histoire pour l'infini pos ou neg).

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

Si la méthode C# renvoie un double.NaN, alors nous avons (dans la fenêtre immed) :

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

La variante (encadrée) contenant les tests NaN positifs pour le numérique, type = double

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

Les comparaisons sur la variante (encadrée) NaN fonctionnent, mais avec les résultats opposés auxquels on pourrait s'attendre. Les comparaisons sur les doubles (non encadrés) provoquent des exceptions de débordement.

?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)

Les opérations sur la variante (encadrée) provoquent des exceptions de débordement. Les opérations sur les doubles (non encadrés) fonctionnent (et renvoient -1.#IND, comme prévu).

?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 ne sont pas utiles :

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

On peut toujours utiliser la comparaison de chaînes de caractères pour tester :

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

2voto

David Healy Points 88

Étant donné qu'un champ Double.NAN représente une valeur qui n'est pas un nombre, vous êtes très probablement sur la bonne voie en utilisant une comparaison de chaînes.

Si vous allez dans l'autre sens (c'est-à-dire passer des valeurs hors de VB), ByRef et ByVal sont les suspects habituels.

La fonction IsNumeric() de VB n'est pas toujours intuitive. Par exemple, elle retournera True si un code alphanumérique se trouve être, par hasard, un nombre en notation scientifique.

1voto

Je suis d'accord avec David pour dire que votre solution de contournement actuelle est acceptable. N'oubliez pas de faire des tests sur les installations en langues étrangères !

L'exemple que vous donnez pourrait faire partie de la solution : une valeur qui est égale à 1 et à 0 en même temps, n'est pas un nombre normal. Ce test permet de distinguer les NaN des nombres normaux. Il est possible de trouver des règles similaires pour trouver +/-infini.

0voto

apan Points 1

Assurez-vous de tenir compte de la situation locale actuelle. NaN peut être "-1.#IND" o "-1,#IND" en fonction des paramètres du séparateur décimal.

Une façon d'éviter cela peut être la comparaison InStr :

InStr(CStr(dVal), "#IND") <> 0

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X