par , 16/10/2019 à 08h00 (18348 Affichages)
Salut.
On lit de ces horreurs, parfois, sur nos forums.
A propos des dates, par exemple, j'ai lu dans une discussion que "l'anglophonisme de VBA a de grande chance de transformer le 3 février en 2 mars et réciproquement" (sic)... Wouah, voilà que transformer du texte en date est une question "de chance"...
Dans une autre, je lis que "les dates et les TextBox [...], ça ne fait pas bon ménage. A moins de prendre de grandes précautions, c'est la cata garantie." Houlà, mais ça va faire fuir les gens, ce genre de trucs... Au secours, on ne sait pas gérer les dates saisies dans des textbox...
Allons allons, un peu de sérieux s'il vous plait. Qu'est-ce qu'il ne faut pas lire. La programmation, ce n'est pas une question de chance, et il est légitime de douter qu'il soit si compliqué de transformer du texte en date, pour autant bien sûr que la saisie n'ait pas été ésotérique. Je ne parle pas ici de tentatives, évidemment infructueuses, de pouvoir transformer n'importe quoi en date comme je l'ai vu sur le forum Excel/Contribuez, mais bien d'une approche rigoureuse de la transformation d'une saisie textuelle supposée correcte en date.
Préambule
Avant d'approcher les deux fonctions qui vont nous aider à réaliser ce transtypage sans problèmes, il est utile de s'intéresser aux paramètres régionaux et à la façon dont VBA les comprend et les gère.
Il y a plusieurs formats de saisie selon que l'on souhaite 1 ou 2 chiffres pour les valeurs inférieures à 10 relatives aux jours et aux mois, et il faut compter sur la possibilité de saisir l'année sur 2 ou 4 chiffres. Mais il y a aussi, plus important pour nous, la séquence de saisie. VBA (et les paramètres régionaux) reconnaissent 3 séquences possibles:
- m/d/y, mois - jour - année;
- y/m/d, année - mois - jour;
- d/m/y, jour - mois - année.
En se positionnant sur la séquence définie par les paramètres régionaux, VBA va tester les trois séquences dans l'ordre ci-dessus. Cela signifie que, pour "notre" paramètre régional continental d-m-y, VBA va tester les séquences dans l'ordre d-m-y => m-d-y => y-m-d. Si les paramètres régionaux utilisent la séquence m-d-y, VBA va tester m-d-y => y-m-d => d-m-y.
Un petit exemple?
Avec la séquence d-m-y dans les paramètres régionaux, "13/12/30" est considéré comme le 13 décembre 1930. Avec m-d-y comme paramètres régionaux, "13/12/30" est considéré comme le 30 décembre 2013, car m-d-y ne fonctionnant pas (pas de mois n° 13), VBA utilise la séquence suivante dans sa liste, soit y-m-d.
Test de date et conversion
Note: Ce qui suit s'appuie sur des paramètres régionaux utilisant la séquence d-m-y.
Convertir une date s'effectue en utilisant la fonction CDate(Value) qui renvoie... une date
. Encore faut-il que la saisie puisse être interprétée comme telle, car dans le cas contraire, la fonction lèvera une exception 13 - incompatibilité de type.
Pour tester, nous avons la fonction IsDate(Value) qui va tester que Value est une date ou est susceptible d'être transformée en date.
Test |
Valeur |
Commentaire |
isdate("Pierre") |
Faux |
Pierre ne peut évidemment pas être converti en date |
isdate("02/03/19") |
Vrai |
VBA considère la séquence d-m-y, celle des paramètres régionaux => 02 mars 2019 |
isdate("12/30/19") |
Vrai |
la séquence d-m-y n'est pas bonne, Excel essaie avec la séquence m-d-y => 30 décembre 2019 |
isdate("80/12/30") |
Vrai |
d-m-y et m-d-y ne fonctionnent pas, VBA essaie avec la séquence y-m-d => 30 décembre 1980 |
isdate("80/30/12") |
Faux |
Aucune séquence ne fonctionne, la saisie n'est pas une date |
La conversion avec CDate fonctionne de la même façon, en interprétant les dates selon le schéma des séquences vu plus haut. En tenant compte que la saisie est effectuée selon les paramètres régionaux, ce qui me semble cohérent, on peut donc convertir du texte en date grâce au test avec IsDate puis, s'il valide la saisie, à la conversion avec CDate. On réalisera bien entendu cela dans une fonction perso que l'on sauvegardera dans son module Tools:
1 2 3
| Function StringToDate(Value As String) As Date
If IsDate(Value) Then StringToDate = CDate(Value)
End Function |
Il ne faut pas utiliser CDate sans avoir testé avant avec IsDate, car comme nous l'avons vu, cela pourrait lever une exception, déroutant le process du processeur vers le gestionnaire d'exception. La tentation serait grande alors de contourner cela avec un On Error... (une sorte de Try Catch Finally à la VBA), mais c'est pour moi une mauvaise approche: On ne programme pas par la gestion des exceptions. Cette possibilité de gérer l'exception est uniquement là pour tout ce que l'on ne peut gérer autrement. Or, on peut prévoir l'exception éventuellement levée par CDate, et la contourner, en utilisant IsDate.