web-dev-qa-db-fra.com

Excel VBA Compile génère une erreur "Type défini par l'utilisateur non défini" mais n'entend pas la ligne de code incriminée

Symptômes

Ceci est un symptôme spécifique lors de la compilation d'un projet VBA Excel. L'erreur suivante se produit:

User-defined type not defined

Cependant, le code qui génère cette erreur n'est pas mis en évidence par le compilateur et je ne peux donc pas identifier le problème.

Ce que je sais déjà et que j'ai essayé

Il s'agit d'une erreur "Type défini par l'utilisateur non défini" que j'ai déjà vue avec des problèmes simples tels que nommer quelque chose As Strig au lieu de As String. Toutefois, cette erreur particulière ne s'affiche que pendant l'option de menu Debug > Compile VBAProject et, lorsque la boîte de message d'erreur s'affiche, elle ne met pas en évidence la ligne de code dans laquelle l'erreur se produit.

Après de nombreuses recherches, j'ai découvert que ce bogue pouvait être lié à des références manquantes et je l'ai écarté car j'ai inclus toutes les références nécessaires et les objets Toolbox.

Pour être sûr de ne pas manquer toutes les instructions Dim manquantes évidentes, j'ai ajouté Option Explicit à toutes les pages de code (formulaires inclus) pour m'assurer que rien ne manquait. L'erreur persiste lors de l'exécution d'une compilation.

Il existe également ce bogue connu qui indique que le problème est connu du fait des projets VB6 utilisant la compatibilité binaire:

Désactivez la compatibilité binaire et compilez le projet. Visual Basic mettra en surbrillance la ligne de code contenant le type défini par l'utilisateur ce n'est pas défini. Après avoir résolu le problème, Compatibilité binaire peut être rallumé.

J'ai trouvé cet article via ceci Question and Answer , cependant, je ne trouve pas cette option dans l'éditeur Excel VBA standard.

Aidez à sauver la santé mentale des miens et des autres!

Grâce aux recherches Google et à d’autres questions, je sais que je ne suis pas le seul à avoir eu ce problème.

J'ai essayé de parcourir le code manuellement, mais il y a tout simplement trop de lignes pour le faire.

Existe-t-il un moyen de désactiver la compatibilité binaire dans les projets VBA Excel? Comment les gens trouvent-ils cette ligne de code choquante s’ils ne peuvent pas déboguer ce qu’ils doivent changer? Toute aide serait ravissante!

Merci d'avance.

Modifier: J'ai trouvé la ligne de code incriminée et mon problème particulier est résolu Le problème persiste après la suppression de cette ligne. Il s'agissait d'un nom de contrôle mal exprimé sur un formulaire référencé dans son code. Cela ne résout toujours pas le problème particulier de savoir comment trouver le code incriminé. Sommes-nous en mesure de trouver un bon moyen de trouver le code incriminé lorsque ce bogue survient afin que d'autres, à l'avenir, puissent éviter cette agonie?

18
Tom 'Blue' Piddock

Ma solution n'est pas une bonne nouvelle, mais au moins cela devrait marcher.

Mon cas est le suivant: j'ai un fichier .xlsm d'un collègue. 1) Je l’ouvre et clique sur le bouton: cela fonctionne bien. 2) Je sauvegarde le fichier, ferme Excel, ouvre à nouveau le fichier: cela ne fonctionne plus. La conclusion est la suivante: le code est correct mais Excel ne peut pas gérer les références correctement. (J'ai essayé de supprimer la ré-ajout des références sans aucun succès)

La solution consiste donc à déclarer chaque objet référencé en tant que Variant et à utiliser CreateObject("Foo.Bar") au lieu de New Foo.Bar.

Par exemple:

Dim objXML As MSXML2.DOMDocument
Set objXML = New MSXML2.DOMDocument

Remplacé par:

Dim objXML As Variant
Set objXML = CreateObject("MSXML2.DOMDocument")
5
jng

Comme il semble que vous ayez essayé de nombreuses solutions potentielles différentes, vous devrez probablement le faire de manière méthodique maintenant.

Créez un nouveau classeur vide. Ensuite, copiez morceau par morceau votre ancien cahier. Ajoutez une référence, écrivez un peu de code pour le tester. Assurez-vous qu'il compile, assurez-vous qu'il fonctionne. Ajoutez un sous ou une fonction, encore une fois, écrivez un petit sous-test pour l'exécuter, assurez-vous également qu'il compile. Répétez ce processus en ajoutant et en testant lentement tout.

Vous pouvez accélérer un peu ce processus en essayant d’abord de gros morceaux, puis lorsque vous en trouvez un qui provoque le problème, supprimez-le et divisez-le en plusieurs parties plus petites pour les tester.

Soit vous trouvez le délinquant, soit vous avez un nouveau classeur qui, comme par magie, n’a pas de problème. Ce dernier serait dû à une sorte de corruption cachée dans le fichier de classeur, probablement dans la partie binary vbproject.

Bienvenue dans le monde du débogage sans les débogueurs ou autres outils utiles pour faire le gros du travail pour vous!

4
AndASM

J'ai eu une expérience similaire, mais c'est parce que j'avais renommé un enum dans l'un de mes cours. J'ai exporté et réimporté les classes qui avaient fait référence à l'ancien enum et le message d'erreur a disparu. Cela suggère qu'il s'agit d'un problème de mise en cache dans l'environnement VBA.

2
Rob Bishop

J'ai eu exactement le même problème (semble toujours se produire lorsque je tente d'implémenter une interface sur un utilisateur. Téléchargez et installez Code Cleaner à partir de ici . Il s'agit d'un utilitaire gratuit qui m'a sauvé à de nombreuses occasions. Avec votre VBA projet ouvert, exécutez l'option "Clean Code...". Assurez-vous de bien cocher "projet de sauvegarde" et/ou "exporter tous les modules de code" vers des emplacements sûrs avant d'exécuter le nettoyage. Pour autant que je sache, cet utilitaire exporte puis réimporte tous modules et classes, ce qui élimine les erreurs de compilateur qui se sont glissées dans le code, a fonctionné comme un charme pour moi! Bonne chance.

2
user3803315

Tout en vous faisant savoir que j’avais ce problème aussi. Plutôt que le code, le problème était de savoir quelle macro un bouton appelait. (Elle appelait la macro 'createroutes.createroutes', mais j'avais renommé le module 'createroutes' en 'routes'.) Par conséquent, le problème a été résolu en pointant le bouton sur l'emplacement correct.

2
Cameron Bradley

J'ai pu réparer l'erreur en 

  1. Fermeture complète de l'accès 
  2. Renommer le fichier de base de données
  3. Ouverture du fichier de base de données renommé dans Access.
  4. Accepté divers avertissements de sécurité et invites .
    • Non seulement j'ai choisi d'activer les macros, mais j'ai également accepté de transformer la base de données renommée en document de confiance.
    • Le fichier précédent avait également été marqué comme document de confiance.
  5. Compiler avec succès le projet VBA sans erreur, aucune modification de code.
  6. Après la compilation réussie, j'ai pu refermer Access, le renommer en tant que nom de fichier d'origine. J'ai dû répondre aux mêmes instructions de sécurité, mais une fois que j'ai ouvert le projet VBA, il a toujours été compilé sans erreur.

Un petit historique de ce cas et des observations:

  • Je poste cette réponse parce que mes symptômes observés étaient un peu différents des autres et/ou que ma solution semble unique.
  • Au moins pendant une partie du temps où j'ai vécu l'erreur, ma fenêtre VBA montrait deux projets "mystérieux" supplémentaires. Malheureusement, je n'ai pas enregistré les noms avant d'avoir résolu l'erreur. L'une ressemblait à ACXTOOLS. Les modules à l'intérieur ne pouvaient pas être ouverts.
  • Je pense que le problème initial était en effet dû à un code incorrect, car j'avais apporté des modifications majeures à un formulaire avant de tenter de mettre à jour son code de module. Mais même après avoir corrigé le code, l'erreur a persisté. Je savais que le code fonctionnait, car le formulaire serait chargé et aucune erreur. Comme l'indique la publication d'origine, l'erreur «Type défini par l'utilisateur non défini» apparaît, mais ne concerne aucune ligne de code incriminée.
  • Avant de trouver cette erreur, je me suis assuré que toutes les références nécessaires ont été ajoutées. J'ai compacté et réparé la base de données plus d'une fois. J'ai fermé Access et rouvert le fichier plusieurs fois entre différentes tentatives de réparation. J'ai enlevé le formulaire incriminé, mais j'ai quand même eu l'erreur. J'ai essayé d'autres étapes suggérées ici et sur d'autres forums, mais rien ne résout le problème.
  • Je suis tombé sur ce correctif lorsque j'ai fait une copie de sauvegarde pour tenter des mesures drastiques, comme la suppression d'un formulaire/module à la fois. Mais lors de l'ouverture de la copie de sauvegarde, le problème ne s'est pas reproduit.
1
C Perkins

Solution possible, vous essayez de travailler avec PowerPoint via Excel VBA et vous n’avez pas d’abord activé la bibliothèque d’objets PowerPoint.

Pour ce faire, dans le menu supérieur de l'éditeur VBA, sélectionnez Outils, Références, puis faites défiler la liste pour cliquer sur la bibliothèque appelée Bibliothèque d'objets Microsoft PowerPoint xx.x. Office 2007 est la bibliothèque 12, chaque version d'Office a une bibliothèque différente. Pour votre information, j’ai rencontré des erreurs étranges et des fichiers corrompus lorsque j’ai activé la bibliothèque 2007, mais un utilisateur tente d’ouvrir et d’exécuter cette macro avec Excel 2003. L’ancienne version d’Excel ne reconnaît pas la nouvelle bibliothèque, ce qui semble poser problème.

1
Nathalii.

J'ai eu ce problème avec un programme ordinaire VB6. Il s'est avéré que j'avais omis une définition de classe, pas un type défini par l'utilisateur. Apparemment, VB a vu quelque chose comme "Thing.name" et a supposé que Thing était un UDT. Oui, il s’agit d’un grave problème lié à VB6, mais vous ne pouvez pas vous attendre à ce que Microsoft prenne en charge un produit vendu par ceux-ci il ya seize ans. Alors, quelles versions des différents produits impliqués utilisez-vous? Ceci n’est intéressant que si cela se produit avec un produit pris en charge par MS. 

1
user3818635

Je sais que c'est vieux, mais j'ai eu un problème similaire et j'ai trouvé une solution:

Je rencontrais le même problème avec un module que j'avais transféré d'Excel dans Access. Dans un fichier UDF indépendant, l'atténuation était définie sur 'As Range', mais aucune plage n'existait dans Access. Vous utilisez peut-être un type de variable sans avoir activé la bibliothèque de références appropriée.

Si vous avez des dims non standard, recherchez-les dans Google et voyez si la référence à cette bibliothèque est manquante dans Outils.

-E

1
Schalton

Pour référence future -

J'ai eu ce problème avec ce morceau de code dans Microsoft Access avec le débogueur soulignant la ligne avec le commentaire:

Option Compare Database
Option Explicit

Dim strSQL As String
Dim rstrSQL As String
Dim strTempPass As String


Private Sub btnForgotPassword_Click()
On Error GoTo ErrorHandler

Dim oApp As Outlook.Application '<---------------------------------Offending line
Dim oMail As MailItem
Set oApp = CreateObject("Outlook.application") 'this is the "instance" of Outlook
Set oMail = oApp.CreateItem(olMailItem) 'this is the actual "email"

Je devais sélectionner des références précédemment désélectionnées. Ils étaient

Bibliothèque d'objets Microsoft Outlook 15.0
Contrôle de la vue Microsoft Outlook

1
Mark

Pour le type Scripting.Dictionary, vous pouvez utiliser une liaison tardive (comme indiqué précédemment) avec:

Dim Dict as Object
Set Dict = CreateObject("Scripting.Dictionary")

Ce qui fonctionne, mais vous n'obtenez pas l'achèvement automatique du code. Vous pouvez également utiliser la liaison anticipée, mais vous devez vous assurer que VBA peut trouver le type Scripting.Dictionary en ajoutant la référence à la bibliothèque de scripts Microsoft via VBA -> Outils -> Références -> "Microsoft Scripting Runtime". Ensuite, vous pouvez utiliser:

Dim Dict as Scripting.Dictionary
Set Dict = New Scripting.Dictionary

... et l'auto complétion fonctionnera.

1
RexBarker

J'ai eu le même problème, si vous activez Microsoft Scripting Runtime, vous devriez être bon. Vous pouvez le faire sous outils> références>, puis cochez la case pour Microsoft Scripting Runtime . Cela devrait résoudre votre problème.

0
Vincent

Un problème différent avec le même symptôme: j'ai eu une classe implémentée qui n'était pas définie. Il était entouré d'un #si je pensais que cela n'aurait pas dû permettre au compilateur de le voir, mais pas autant. Supprimez le commentaire de la déclaration Implements et tout va bien. Je suppose que l'importation de la définition fonctionnerait également ...

0
Ed Hoeffner

J'ai eu la même erreur hier: mon projet comportait deux classes, cProgress et cProgressEx, dont l'une n'était plus utilisée, et lorsque j'ai supprimé la classe cProgress, la même erreur de compilation s'est produite.

J'ai réussi à corriger l'erreur comme suit:

  • Exporté tous les modules, formulaires et classes sur le disque dur
  • Tout supprimé du projet
  • Sauvé le projet
  • Réimporté tous les modules, formulaires et classes, supprimé la classe cProgress et compilé. 
  • L'erreur a disparu.
0
Stanislav Okhvat

Après des années, j'ai découvert une, sinon la, réponse au bogue Microsoft du type d'erreur «Type défini par l'utilisateur non défini» dans Excel. J'utilise Excel 2010 pour Windows.

Si vous avez une UDF nommée par exemple 'xyz()', alors si vous appelez une entité inexistante commençant par ce nom suivi d'un point suivi d'autres caractères -, par exemple si vous essayez d'appeler une plage inexistante nom 'xyz.abc', la stupide application jette ce message erroné, après quoi elle vous ramène à votre feuille.

Dans mon cas, c’était particulièrement déroutant, car j’ai nommé les FDU avec une seule lettre, par exemple. x(), y(), etc., et j'ai également des noms de plage qui incluent des points - 'x.a', 'c.d', etc. Chaque fois que j'ai mal orthographié un nom de plage - par exemple , 'x.h', l'erreur 'Défini par l'utilisateur…' a été générée simplement parce qu'une UDF nommée 'x()' existait quelque part dans mon projet.

Cela a pris plusieurs heures. diagnostiquer. Les suggestions ci-dessus visant à supprimer progressivement le code de votre projet, ou inversement à supprimer tout le code et à l'ajouter progressivement, étaient sur la bonne voie, mais elles n'ont pas suivi. Cela n'a rien à voir avec le code en soi; cela concerne uniquement le nom de la première ligne de code de chaque proc, à savoir la ligne Sub MyProc ou Function MyProc nommant le proc. C'est lorsque j'ai commenté l'un de mes fichiers UDF nommés à une lettre dans une partie du projet totalement indépendante que le message d'erreur bugé. est parti, et de là, après une autre heure. ou alors, j'ai pu généraliser la règle comme indiqué.

Peut-être que le bogue survient également avec caractères de ponctuation autres que points ('.'). Cependant, il n'y a pas beaucoup de caractères non alpha autorisés dans un nom de plage; le soulignement ('_') est autorisé, mais son utilisation de la manière décrite ne semble pas jeter le bogue.

Jim Luedke

0
Jim Luedke

Reliure tardive 

Cette erreur peut survenir en raison d'une référence manquante. Par exemple, en supprimant la référence, il est possible que certains codes référant à des types de données spécifiques à la référence supprimée soient remplacés par une liaison anticipée par une liaison tardive.

Essayez d'inclure la référence pour voir si le problème disparaît.

Peut-être que l'erreur n'est pas une erreur du compilateur mais une erreur de l'éditeur de liens, de sorte que la ligne spécifique est inconnue. Honte à Microsoft!

0
jas0501

Un peu en retard, et pas une solution complète non plus, mais pour tout le monde qui est frappé par cette erreur sans aucune raison évidente (ayant toutes les références définies, etc.) Ce fil m'a mis sur la bonne piste cependant. Le problème semble provenir d’un bogue lié à la mise en cache dans l’éditeur VBA de MS Office.

Après avoir apporté des modifications à un projet comprenant environ 40 formulaires avec des modules de code plus 40 classes et des modules globaux dans MS Access 2016, la compilation a échoué. 

Commenter le code n'était évidemment pas une option, et exporter et réimporter plus de 80 fichiers ne semblaient pas raisonnables… .. Concentrée sur ce qui avait été récemment changé, mes soupçons se concentraient sur la suppression d'un module de classe. 

N'ayant pas de meilleures idées, j'ai recréé un module de classe vide portant le même nom que celui précédemment supprimé. Et voliá l’erreur avait disparu! Il était même possible de supprimer à nouveau le module de classe inutilisé sans que l'erreur ne réapparaisse, jusqu'à ce que toutes les modifications soient enregistrées dans un module de formulaire contenant auparavant une déclaration WithEvents impliquant la classe maintenant supprimée.

Pas tout à fait sûr si la déclaration WithEvents est vraiment ce qui déclenche l'erreur même après que la déclaration a été supprimée. Et aucun indice sur la manière de savoir réellement (sans avoir des informations sur l'historique du développement) quelle forme pourrait être le coupable ...

Mais ce qui a finalement résolu le problème était:

  1. En VBE - Copier tout le code du module de code de formulaire
  2. Dans Access, ouvrez le formulaire en mode Création et définissezHas Moduleproperty à No
  3. Enregistrez le projet (cela supprime tout code associé au formulaire)
  4. (Je ne sais pas s'il faut fermer et rouvrir Access, mais je l'ai fait)
  5. Ouvrez le formulaire en mode Création et définissezA Modulepropriété Retour à Oui
  6. Dans VBE, recopiez le code du module copié
  7. Sauvegarder
0
Kristian L