Pourquoi mon code VB6/VBA ne marche pas en VB.Net ?

Préambule

Cet article n'a pas vocation à relancer une polémique sur le bien-fondé des choix de Microsoft, mais de montrer les principales différences entre ces deux langages.
Il n'a pas vocation non plus à faire un cours complet sur VB.Net, d'autres l'ont déjà très bien fait
-Celui-ci s'adresse aux anciens de VB6 ou VBA https://plasserre.developpez.com/cours/vb-net/.
-Celui-là s'adresse aux débutants en VB https://tahe.developpez.com/dotnet/vbnet/

Pour la suite de l'article, VB désigne VB6 ou antérieur.
Il est souvent fait référence au C#, mais tous les codes présentés sont en VB.Net.

Un peu d'histoire

Au commencement fut le BASIC, à l'époque un langage simple pour les débutants.
Puis avec le succès de Windows, Microsoft a commercialisé en 1991 Visual Basic, un environnement de développement ou l'on pose sur la future fenêtre du programme les différents contrôles à utiliser et l'écriture du code des interactions se définit par rapport aux évènements qu'ils subissent.
La dernière version de VB est sortie en 1998, mais a été mise à jour jusqu'en 2005 pour le grand public et 2008 dans le cadre du support étendu.
En 2001, Microsoft a sorti la Framewok .Net 1.0 et son langage créé pour l'occasion le C#.
Sources et informations supplémentaires Wikipédia.

.Net Qu'est-ce que c'est ?

Le principe de ce Framework est d'installer, sur le PC cible, tout un panel d'outils permettant de faire fonctionner un logiciel sans (trop) se soucier de la configuration de la machine.
Comment ça marche ? Lorsque l'on génère le projet, Visual Studio écrit un fichier exe qui n'est pas directement exécutable. Il s'agit en fait d'une traduction vers un langage intermédiaire (IL).
Sur le PC cible, à la première exécution, la Framework va interpréter ce code intermédiaire et compiler le programme en fonction de la configuration de la machine (OS, périphériques, etc..)
Ce principe a permis à Microsoft d'étendre le concept à d'autres langages que C#, on trouve ainsi C++.Net, ASP.Net, J# (Java. Net), VB.Net, ...
On peut même éventuellement générer un exe dans un langage et le décompiler dans un autre.

VB.Net ce faux ami

  • On dispose donc d'un éditeur avec lequel on peut poser des contrôles sur des Form.
  • Les procédures sont toujours déclarées
     Sub Truc()
    `...
    End Sub

    ou

    Function Bidule()
    `...
    End Function

    selon qu'elles retournent ou non un résultat. Par contre, on les appelle méthodes maintenant.

  • La disposition de l'environnement avec la liste déroulante des objets et celle des événements rappelle celle de VB.
  • On retrouve quelques instructions.

Mais le code que je copie colle ne marche pas !
Parce qu'en dépit de toutes ces ressemblances VB.Net n'est pas du VB.

Les différences

Le typage

Microsoft a fait de C# un langage très fortement typé. Il est impossible de déclarer une variable sans lui donner de type et, le type var (un peu l'équivalent de Variant) n'est apparu qu'avec Linq (une sorte de SQL maison) et la Framework 3.5.

VB est historiquement très souple. En VB.Net, une certaine largesse (mais moindre) existe toujours. Cependant, il est préférable de se contraindre un peu, notamment en configurant

Option Strict On
Option Explicit On

car au final le fichier IL devrait être le même que l'on code en VB ou en C#, et cette tolérance amène un risque de bug.

Lors d'un copier coller d'un code VB/VBA, le « manque » de typage peut aussi être générateur de bug.

Les types « Valeurs » et « Référence »

Le passage de paramètre peut se faire par valeur, par exemple avec une fonction qui calcule la racine carrée d'un nombre, on transmet la valeur de ce nombre à la fonction et pas l'adresse de la case mémoire où ce nombre est rangé. Donc, on crée une seconde case mémoire, qui copie la valeur de la première.

En cas de passage par référence, c'est l'adresse de la case mémoire qui est transmise, si une modification est apportée au contenu de la variable, cette modification sera valable aussi dans la procédure appelante.
Dans notre exemple de racine carrée, si le nombre en entrée est négatif, il est nécessaire de retourner un booléen à vrai pour une racine complexe.

En VB, par défaut, les paramètres sont transmis par référence. Pour passer par valeur, il faut utiliser le modificateur ByVal :

Function Racine(ByVal Nombre As Double, IsComplex As Boolean)'utilisation du modificateur ByVal
    IsComplex = (Nombre < 0)
   Nombre = Abs(Nombre)'modification de la valeur de Nombre pour l'exemple
    Racine = Sqr(Nombre)
End Function

Dans la procédure appelante, la valeur de Nombre ne sera pas modifiée. Par contre IsComplex aura la valeur fixée dans Racine.

En VB.Net, le comportement par défaut dépend du type :

  • les types de base (Integer, Long, Short, Single, Double, Decimal, Boolean, Char, Date), les structures de données et les énumérations sont des types valeurs.
  • String et tous les autres (ils apparaissent en bleu ciel dans Visual Studio) sont des types références.

Si on modifie une variable de type référence sans y penser, ou à l'inverse une variable de type valeur en croyant son effet "global", cela aura forcément un effet indésirable quelque part.

Les codes VB/VBA ne sont pas prévus pour ce comportement différent selon le type, là encore un copier coller sans précautions sera cause de bug.

Plus de détails.

De plus, le type Date a été conservé (alors qu'il n'existe pas en C#) et cohabite avec le type DateTime (lui purement .Net) qui possède plus d'outils que Date. Il est donc préférable d'utiliser ce deuxième, mais lors de l'import d'un code VB cela nécessite là encore beaucoup de modifications.

La programmation Objet

C'est La Principale Différence entre VB et VB.Net.
Sans aller faire un cours complet sur la programmation Objet, il y en a de nombreux sur le net, les objets (avec interface graphique ou pas) interagissent entre eux via des méthodes (Sub et Function), des événements, des constructions (création d'une instance) ou destruction (libération d'une instance).
Même si VB offrait la possibilité d'écrire des classes, et donc des objets, cela était assez peu utilisé et majoritairement pour des contrôles personnalisés.
A minima, on peut voir la classe comme étant une structure de données améliorée. En plus de stocker des informations, elle pourra faire des calculs et générer des évènements.
Pour un objet "voiture", la méthode "AppuiSurAccelarateur" va générer l'évènement "Accélère" et le calcul de "Vitesse" qui va varier avec le temps.

En .Net, écrire une classe par « thème » de traitement est la base de la conception du programme.

C# est un langage Tout objet. Tout est en italique car le terme ne plait pas à tout le monde.
J'entends par là que les instructions sont réduites au minimum vital (déclaration, boucle, clause de requêtes,...).
Il n'existe pas d'instruction qui donne la taille d'un string, ni d'instruction de calcul mathématique, ni d'instruction de conversion de type, etc...
Ces actions et toutes les autres seront réalisées au travers d'objets. Tout est tellement objet que même un simple "a". tapé dans l'IDE ouvre une liste déroulante proposant plusieurs méthodes directement utilisables.

On peut même s'amuser à créer une extension du type String appelée « ConvertirEnEntier », dont la fonction est de convertir le texte en Integer (Attention ça n'est pas pour tout de suite, on trouve le comment du pourquoi vers la fin du cours cité plus haut).
Cette ligne

 Dim chiffre as Integer = "4". ConvertirEnEntier()

déclare chiffre et l'initialise avec la valeur 4.

Pour VB.Net, là encore, Microsoft a laissé une certaine souplesse, quelques instructions VB sont présentes, quelques autres peuvent être importées en tant que référence du projet (Microsoft.VisualBasic). Cette référence est cochée par défaut lors de la création d'un nouveau projet, il est judicieux de la désactiver systématiquement.

On se retrouve donc avec 2 façons de faire, qui, au final, ne feront qu'une dans le fichier en IL.

Par exemple

 Dim nombre as Double = Convert.ToDouble(1)'utilisation de la classe Convert
Dim nombre2 as Double = CDbl(1)'utilisation de l'instruction CDbl

Ces deux lignes font la même chose, mais il convient d'utiliser la première. Pourquoi ? C'est comme mélanger le blanc et la couleur, quand on lave à 30°C ça va si on passe à 90°C, le blanc va ressortir arc en ciel....

Le copier coller d'un code VB/VBA peut contenir des instructions qui n'existent plus. Il faudra, alors, au pire, chercher les objets qui réalisent le travail de ces instructions et les remplacer.
Mais la plupart du temps, il convient de remanier entièrement le code car les interactions entre objets sont souvent moins séquentielles en VB.Net (ou en tout cas pour la majorité des codes VB que l'on trouve sur la toile).

Conclusion

Le copier coller ça ne marche pas ou très rarement, les traductions automatiques non plus.
Il faut donc le plus souvent réécrire le code, et tant qu'à faire, pour qu'il soit plus efficace et maintenable de le faire dans la philosophie objet.
Je vais transmettre le conseil qu'on m'a fait quand j'ai quitté VB pour .Net : faites du C#.

  • On n'est plus face à un faux ami.
  • On n'est pas tenté de faire de copier coller car c'est évident que cela ne marchera pas.
  • On se fait plus naturellement « violence » pour s'adapter à la philosophie tout objet.
  • Quand on code en VB.Net, on ne fait plus de mélange.

Certes c'est un nouveau langage (pour une bonne part VB.Net aussi) mais il ouvre vers Java ou C++, ça peut être un atout.

Quoiqu'il en soit, mettez

Option Strict On
Option Explicit On

et désactivez la référence à Microsoft.VisualBasic (insertion VB6)

C'est le début des bonnes habitudes.

Merci à Buno, cptpingu, Jordane, NHenry et Ucfoutu pour leur relecture et surtout corrections

Ce document intitulé « Pourquoi mon code VB6/VBA ne marche pas en VB.Net ? » issu de CodeS SourceS (codes-sources.commentcamarche.net) est mis à disposition sous les termes de la licence Creative Commons. Vous pouvez copier, modifier des copies de cette page, dans les conditions fixées par la licence, tant que cette note apparaît clairement.
Rejoignez-nous