PC SOFT

FORUMS PROFESSIONNELS
WINDEVWEBDEV et WINDEV Mobile

Accueil → WINDEV 2025 → WinDev et Null
WinDev et Null
Débuté par hibernatus34, 25 aoû. 2014 11:34 - 16 réponses
Posté le 25 août 2014 - 11:34
Bonjour,

Est-ce que quelqu'un peut m'expliquer le comportement du W-Langage avec les Variants et Null ?

Par exemple :
vVar1est Variant= Null
vVar2est Variant= 0

SI vVar1 <> vVar2 ALORS
Trace("SI vVar1 <> vVar2 : Oui") // On passera là
SINON
Trace("SI vVar1 <> vVar2 : Non")
FIN
SI vVar1 = vVar2 ALORS
Trace("SI vVar1 = vVar2 : Oui") // On passera là !
SINON
Trace("SI vVar1 = vVar2 : Non")
FIN
SI (vVar1 <> vVar2) ALORS
Trace("SI (vVar1 <> vVar2) : Oui")
SINON
Trace("SI (vVar1 <> vVar2) : Non") // On passera là
FIN
SI (vVar1 = vVar2) ALORS
Trace("SI (vVar1 = vVar2) : Oui") // On passera là
SINON
Trace("SI (vVar1 = vVar2) : Non")
FIN

Quelle est la logique suivie par WinDev ?

J'aimerais aussi savoir pourquoi, lorsqu'on affecte Null à colonne de table numérique avec l'option "Null si vide" elle affiche zéro au lieu de "vide". Et pourquoi si on lui affecte une chaîne vide, sa valeur devient zéro, alors que ça affiche bien "vide" !

TableAjouteLigne(TABLE_Test, Null)
COL_Test[1] = Null
Trace("Valeur affichée : """ + COL_Test[1]..ValeurAffichée + """") // 0
Trace("Valeur : " + pNullableVersChaîne(COL_Test[1]..Valeur)) // NULL
COL_Test[1] = ""
Trace("Valeur affichée : """ + COL_Test[1]..ValeurAffichée + """") // vide
Trace("Valeur : " + pNullableVersChaîne(COL_Test[1]..Valeur)) // 0


Enfin, il y a aussi le test d'un variant quand il est retourné par une fonction ou une expression :
vVarest Variant= 0

Trace("vVar est Variant = 0")
SI vVar = Null ALORS
Trace("vVar = Null")
SINON
Trace("vVar <> Null") // On passera là, OK
FIN
SI (vVar) = Null ALORS
Trace("BUG : (vVar) = Null") // On passera là (pourquoi ?)
SINON
Trace("OK : (vVar) <> Null")
FIN
SI pRenvoieVariant(0) = Null ALORS // Cette fonction renvoie un variant valant zéro (entier)
Trace("pRenvoieVariant(0) = Null") // On passera là (pourquoi ?)
SINON
Trace("pRenvoieVariant(0) <> Null")
FIN

Où est la logique ?

Merci d'avance.
Posté le 01 septembre 2014 - 08:09
Bonjour,

Je rajoute le code des fonctions :
Procedure pRenvoieVariant(vValeur)
vVariant est Variant = vValeur
RENVOYER vVariant


Procedure pNullableVersChaîne(LOCAL vValeur est Variant)
SI vValeur..Type = 0 ALORS
RENVOYER "<NULL>"
FIN
RENVOYER "" + vValeur


Le comportement du WLangage dans ces cas est incompréhensible.
Est-ce un bug qui sera corrigé bientôt ?
Posté le 01 septembre 2014 - 13:08
Bonjour

je ne suis pas vraiment sur de ce que tu essaye de faire, mais il me
semble que tu n'as pas bien lu l'aide en ligne concernant null...

Null n'est pas une valeur numérique ou chaine, et est donc traité
différement en wlanguage ou NULL est une PROPRIETE des champs et
variables...

Ca se teste donc avec MonChamp..NUll=VRAI

Cordialement


--
Fabrice Harari
Consultant WinDev, WebDev et WinDev Mobile International

NOUVEAU: WXShowroom.com est disponible : Montrez vos projets !
Plus d'information sur http://fabriceharari.com


On 9/1/2014 12:09 AM, Hibernatus34 wrote:
Bonjour,

Je rajoute le code des fonctions :
PROCEDURE pRenvoieVariant(vValeur)
vVariant est Variant = vValeur
RENVOYER vVariant


PROCEDURE pNullableVersChaîne(LOCAL vValeur est Variant)
SI vValeur..Type = 0 ALORS
RENVOYER "<NULL>"
FIN
RENVOYER "" + vValeur


Le comportement du WLangage dans ces cas est incompréhensible.
Est-ce un bug qui sera corrigé bientôt ?
Posté le 01 septembre 2014 - 17:14
Bonjour,

Je parle des Variants, qui n'ont pas une propriété ..Null mais une valeur Null (= pas de valeur ni de type).
Merci de tester le code que je fournis.

Vous parlez de tout autre chose : les rubriques de l'analyse.
Mais ma question ne porte pas là-dessus.
Membre enregistré
6 messages
Posté le 01 septembre 2014 - 19:55
Bonjour,

On parle ici de variants qui peuvent valoir "Null". (ou ne rien valoir si vous préférez)
Rien à voir avec la propriété ..Null des rubriques d'analyse.
Posté le 01 septembre 2014 - 20:48
Je ne parle pas seulement des rubriques d'analyse, je parle de TOUTES
les variables wlanguage... A ma connaissance, NULL est TOUJOURS géré par
la propriété ..NULL en wlanguage...

Cordialement


--
Fabrice Harari
Consultant WinDev, WebDev et WinDev Mobile International

NOUVEAU: WXShowroom.com est disponible : Montrez vos projets !
Plus d'information sur http://fabriceharari.com


On 9/1/2014 11:55 AM, TC-TrioTech wrote:
Bonjour,

On parle ici de variants qui peuvent valoir "Null". (ou ne rien valoir
si vous préférez)
Rien à voir avec la propriété ..Null des rubriques d'analyse.
Membre enregistré
6 messages
Posté le 01 septembre 2014 - 22:04
Et bien non.
Essayez le code ci-dessus, et essayez surtout ..Null sur un Variant, avant de prétendre rectifier ce qui est dit ici. Vous obtiendrez une erreur de compilation.


Ensuite, lisez la page d'aide suivante :
http://doc.pcsoft.fr/?1511015&name=null_mot_reserve

Bonne lecture...
Membre enregistré
240 messages
Posté le 01 septembre 2014 - 22:31
Encore une fois le mieux est de tester le code.
Ce serait bien que quelqu'un nous éclaire à propos de cette variable Null (qui n'a pas de rapport avec l'analyse) qui entraine des résultats plutôt surprenants.

--
Vincent
Membre enregistré
27 messages
Posté le 02 septembre 2014 - 11:20
Bonjour,

Attention à ne pas confondre les variables de type Variant et les rubriques fichier qui peuvent être nulles.

Un variant non affecté est null mais a la valeur zéro !!
Testez le code suivant qui le démontre :
Procedure TestNull()

vVar est un Variant


Trace("Var=" + vVar)

SI vVar=Null ALORS Trace("Var est NULL")

vVar=0

Trace("Var=" + vVar)

SI vVar<>Null ALORS Trace("Var n'est pas NULL")

vVar=Null

SI vVar=Null ALORS Trace("Var est NULL")



Les rubriques de fichier ont un fonctionnement un peu différent :

C'est par la propriété ..Null que l'on peut savoir si une rubrique est nulle ou pas.
Si ..Null est vrai alors la valeur présente dans la rubrique correspond à la valeur par défaut du type de donnée, 0 pour les numériques, etc...
Si ..Null est faux alors la valeur de la rubrique est celle qui lui a été affectée dans un traitement précédent.

Exemple : Dans un fichier Clients, on mémorise une valeur de CA antérieur. Ce chiffre peut être connu, ou pas.
Si on connait le chiffre, c'est bon on l'affecte, si on ne le connait pas on met la rubrique à null.

Sans cela on ne pourrai faire la différence entre un CA égale à zéro et un CA inconnu.

En code ça donne :

// 1 - Ecriture
//CA inconnu
Clients.CA..Null=Vrai
HModifie(Clients)

//CA Connu
Clients.CA = 50000 //La propriété ..Null passe à faux automatiquement
HModifie(Clients)

//2 - Lecture

SI Clients.CA..Null = Vrai ALORS
Info("Le CA est inconnu")
SINON
Info("CA =" + Clients.CA)
FIN


En espérant avoir été clair..
Bon Dev !
Membre enregistré
6 messages
Posté le 02 septembre 2014 - 12:04
Bonjour Didier,

Non, un variant valant Null ne vaut pas zéro, il ne vaut rien.
Dans votre code, vous pouvez remplacer 0 par 42 et le comportement sera le même.
C'est le sujet de ce fil de discussion ! L'exemple donné dans le premier message montre exactement ce cas.

Ensuite, pour les rubriques d'analyse, il y a aussi une critique à émettre :
Puisqu'on peut écrire le code suivant :
vValeur est Variant
vValeur = MonFichier.MaRubrique

Pourquoi WinDev ne met-il pas Null dans vValeur au lieu de mettre une valeur qui ne signifie rien ?

De même, la copie dans une variable de type défini pourrait au moins donner la valeur nulle/initiale du type en question ("" pour une chaîne, 0 pour un numérique...), au lieu de créer un comportement aléatoire sans aucun avertissement.
Au pire, il faudrait une exception si on lit la valeur d'une rubrique alors qu'elle est nulle, mais ça serait lourd et ferait planter les applications existantes.

Bref, puisque MonFichier.MaRubrique est manipulée comme une variable, elle devrait en avoir le comportement...
Membre enregistré
6 messages
Posté le 02 septembre 2014 - 12:08
Je corrige un point : en réalité WinDev met déjà une valeur "nulle" quand on faire MonFichier.MaRubrique..Null = Vrai.
Mais il ne met pas Null dans un Variant qui récupère la valeur.

Ce comportement peut se défendre, mais me paraît peu intuitif et plus lourd à l'usage.
Membre enregistré
512 messages
Posté le 02 septembre 2014 - 12:09
Bonjour à tous,

Didier FOURNIER a écrit :

Un variant non affecté est null mais a la valeur zéro !!


Désolé Didier, je trouve que ton affirmation manque de rigueur.

Une variable variant à Null n'a pas de valeur.
Mais l'évaluation de cette variable donne la valeur 0.
Pour moi, c'est l'évaluation qui pose problème.

Pour résumer : l'évaluation d'un Variant à Null donne 0.

Je vous propose de tester le code ci-dessous:

vVar est un Variant = Null

SI vVar=Null ALORS Trace("Var est NULL")
SI vVar<>Null ALORS Trace("Var n'est pas NULL")

SI vVar=0 ALORS Trace("Var est 0")
SI vVar<>0 ALORS Trace("Var n'est pas 0")

SI vVar = "" ALORS Trace("Var est chaîne vide")
SI vVar <> "" ALORS Trace("Var est différent de chaîne vide")


La trace donne ceci:

Var est NULL
Var est 0
Var n'est pas 0
Var est chaîne vide
Var est différent de chaîne vide

:(

Pour tester rigoureusement si un variant est à Null, je préfère utiliser la propriété ..Type.
La propriété ..Type d'un variant vaut 0 (ou wlVide pour WinDev 19) si le variant est à Null.

:)

--
Pour me contacter par courrier électronique, cliquez sur le lien ci-dessous (protection antispam): http://cerbermail.com/…
Membre enregistré
27 messages
Posté le 02 septembre 2014 - 12:29
Je continue car je n'ai pas répondu à la question d'Hibernatus en fait...

Les tests de comparaisons renvoient des résultats surprenants car en fait tu compare des choux et des carottes !
Si un variant peut être null dans ton code, il faut que tu teste si il l'est ou pas avant de le comparer à une autre variable.
Dans ton exemple vVar1 est null et vVar2 vaux 0.

Si tu vérifie les types de tes variants avec :
Trace(vVar1..Type)
Trace(vVar2..Type)


Tu verra qu'ils sont différents car vVar2 de type wlEntier_4 (8) et vVar1 de type wlVide (0)

D'autre part le code suivant montre que null ou PAS Null est interprété comme vrai. (En toute logique, le compilateur devrait au moins mettre un warning sur ce code)
On ne peut donc pas tester une expression pouvant être nulle !

SI Null ALORS
Trace("Null") //passe ici
SINON
Trace("Pas Null !")
FIN

SI PAS Null ALORS
Trace("Null") //passe ici aussi !
SINON
Trace("Pas Null !")
FIN


De plus si tu vérifie la valeur prise par les expressions nVar1=nVar2 ou nVar1<>nVar2, tu verra que c'est Null !
Du coup le test est incohérent.

En conclusion, avant de tester la Valeur d'une variable de type variant, il faut vérifier qu'elle ne soit pas nulle.

Précision :
Dans ton exemple tu teste :

SI (vVar) = Null ALORS
Trace("BUG : (vVar) = Null") // On passera là (pourquoi ?)
SINON
Trace("OK : (vVar) <> Null")
FIN


Le fait d'avoir mis des parenthèses autour de vVar en fait une expression de valeur 0 , le test ne vérifie plus si la variable est nulle, mais compare la valeur d'un entier ( 0 ) à null.
Dans ce cas null vaux 0 donc (vVar)=Null est vrai.
(Voir la doc sur Null)

C'est le même principe avec la fonction pRenvoieVariant.

On ne peut comparer à Null qu'une variable de type Variant.

Bon Dev
Membre enregistré
27 messages
Posté le 02 septembre 2014 - 12:35
Effectivement, tu as raison, je n'ai pas été assez rigoureux.
C'est bien l'évaluation qui donne 0.
:merci:
Membre enregistré
6 messages
Posté le 02 septembre 2014 - 14:35
Didier :

1. L'aide de WinDev précise bien qu'on teste la nullité d'un variant en écrivant "SI vVar = Null ..."
cf. http://doc.pcsoft.fr/?1511015&name=null_mot_reserve#null_les_variants_ELTPARAGRAPHE000216

2. La comparaison de choux et de carottes, comme vous dites, est évaluée positivement par WinDev (chou = carotte), et c'est justement ce qui pose problème !

3. Un variant entre parenthèses reste un variant :
vVar1 est Variant = Null
vVar2 est Variant = 42
vVar2 = (vVar1)
Trace(vVar2..Type) // 0


4. Allez donc expliquer la différence entre "SI vVar1 <> vVar2" et "SI (vVar1 <> vVar2)"...

En fait, le bug a été enregistré par le Support Technique, et j'espère une correction d'ici WD20.
Membre enregistré
6 messages
Posté le 02 septembre 2014 - 14:47
Ceci étant dit, on peut effectivement comprendre d'où vient le problème :
WinDev, comme le SQL, propage le Null dans toutes les expressions.
Mais SQL ne valide pas une condition quand on a Null à la place d'un booléen et dispose d'une syntaxe spécifique pour savoir si une expression est Null.

Dans le cas de WinDev, il suffirait que les tests <> Null et = Null soient équivalent à IS NULL et IS NOT NULL même quand l'expression évaluée n'est pas le seul nom d'un variant et que Null invalide une condition au lieu de la valider.
Membre enregistré
240 messages
Posté le 02 septembre 2014 - 21:27
Selon le support technique il risque de ne pas y avoir de mise à jour de la v19... Dommage, car j'ai également soumis deux autres bugs qui reviennent constamment...
Ce topic est une lecture intéressante en tout cas !

--
Vincent