Ceci est une page optimisée pour les mobiles. Cliquez sur ce texte pour afficher la vraie page.

XL 2016 VBA - Comment passer une structure Private en argument d'une fonction ?

Dudu2

XLDnaute Barbatruc
Bonjour,

On peut passer en argument d'une fonction une structure Public ByRef.
Excel refuse de le faire avec une structure Private.



Y a-t-il un moyen détourné de le faire en la mappant sur son adresse ou autre ?
 

Pièces jointes

  • Classeur1.xlsm
    22 KB · Affichages: 8

Nicolas JACQUIN

XLDnaute Impliqué
Supporter XLD
Bonjour l'ami,
si ça peut t'aider

En VBA (Visual Basic for Applications), une structure (ou Type) déclarée comme Private dans un module est accessible uniquement au sein de ce module. Cela signifie que si vous essayez de la passer comme argument à une fonction qui se trouve dans un autre module ou un autre contexte, cela entraînera une erreur.

Pour contourner ce problème, voici quelques options :


1. Déclarer la structure comme Public

Si vous avez besoin que votre structure soit accessible en dehors de son module, déclarez-la comme Public :

vba
Copier le code
' Dans un module standard
Public Type MonType
Valeur1 As String
Valeur2 As Integer
End Type

Avec une structure publique, vous pourrez passer cette structure comme argument d'une fonction, même si celle-ci se trouve dans un autre module :

vba
Copier le code
' Fonction acceptant une structure en argument
Public Function TraitementMonType(ByVal data As MonType) As String
TraitementMonType = data.Valeur1 & " - " & data.Valeur2
End Function

Et dans votre code principal, vous pouvez appeler la fonction :

vba
Copier le code
Sub TestPassageStructure()
Dim info As MonType
info.Valeur1 = "Bonjour"
info.Valeur2 = 42

MsgBox TraitementMonType(info)
End Sub


2. Utiliser une variable globale pour contourner la portée

Si vous ne voulez pas rendre la structure publique mais que vous devez la partager, vous pouvez utiliser une variable globale (dans un module standard) :

vba
Copier le code
' Structure privée et variable globale dans le même module
Private Type MonType
Valeur1 As String
Valeur2 As Integer
End Type

Private GlobalStruct As MonType

Puis, utilisez des fonctions ou des sous-programmes pour modifier ou lire la structure depuis d'autres modules :

vba
Copier le code
' Fonction pour affecter des valeurs
Public Sub SetStruct(v1 As String, v2 As Integer)
GlobalStruct.Valeur1 = v1
GlobalStruct.Valeur2 = v2
End Sub

' Fonction pour lire ou traiter la structure
Public Function GetStruct() As String
GetStruct = GlobalStruct.Valeur1 & " - " & GlobalStruct.Valeur2
End Function

Appel dans un autre module :

vba
Copier le code
Sub TestVariableGlobale()
Call SetStruct("Hello", 100)
MsgBox GetStruct()
End Sub


3. Redéfinir la même structure dans plusieurs modules

Si vous insistez pour garder la structure Private dans chaque module, une autre approche consiste à redéfinir la même structure (avec le même nom et les mêmes membres) dans chaque module où elle est nécessaire. Voici un exemple :

vba
Copier le code
' Dans Module1
Private Type MonType
Valeur1 As String
Valeur2 As Integer
End Type

Public Sub FonctionModule1()
Dim info As MonType
info.Valeur1 = "Test"
info.Valeur2 = 123

Call FonctionModule2(info)
End Sub

vba
Copier le code
' Dans Module2
Private Type MonType
Valeur1 As String
Valeur2 As Integer
End Type

Public Sub FonctionModule2(data As MonType)
MsgBox data.Valeur1 & " - " & data.Valeur2
End Sub

Cette approche fonctionne, mais il est important que les deux structures soient définies exactement de la même manière. Sinon, des erreurs peuvent survenir.


4. Utiliser des paramètres spécifiques au lieu de la structure

Si vous avez une structure privée et que vous ne voulez pas la rendre publique, vous pouvez passer ses membres individuellement à la fonction, plutôt que de passer la structure elle-même :

vba
Copier le code
' Structure privée
Private Type MonType
Valeur1 As String
Valeur2 As Integer
End Type

' Fonction utilisant des arguments séparés
Public Function TraitementValeurs(V1 As String, V2 As Integer) As String
TraitementValeurs = V1 & " - " & V2
End Function

Sub TestPassageParValeur()
Dim info As MonType
info.Valeur1 = "Exemple"
info.Valeur2 = 50

MsgBox TraitementValeurs(info.Valeur1, info.Valeur2)
End Sub


Conclusion​

La meilleure méthode dépend de votre contexte :

  • Utilisez Public Type si vous avez besoin que la structure soit largement accessible.
  • Utilisez des variables globales ou redéfinissez localement la structure pour préserver la portée.
  • Passez des arguments individuels si les membres de la structure sont peu nombreux.
 

patricktoulon

XLDnaute Barbatruc
bonsoir de plus le byref est implicite me semble t il
mais si ta question est de faire

public type truc
machin as long
bidule as long
end type

sub test
truc="toto"
bidule=15
end sub
alors non ce n'est pas possible
les blocs sont des déclarations il faut instancier un exemplaire
 

jurassic pork

XLDnaute Occasionnel
Hello,
Nicolas je crois que l'I.A t'a balançé tout un speech qui ne correspond pas au problème de Dudu2 (as-tu posé la bonne question ?). En tout cas moi j'ai une solution de contournement : utiliser une classe à la place d'une structure.
Exemple :
Créer un module de classe qui s'appelle MonType2 avec dedans :
VB:
Public a As Long
 Public b As String

et alors ce code fonctionne :
Code:
Sub a()
    Dim MT2 As New MonType2
    MT2.a = 10
    MT2.b = "toto"
    Call b(MT2)
End Sub

Ami calmant, J.P
 

patricktoulon

XLDnaute Barbatruc
re a oui mais non en private même si elles portent le même nom ce ne sont pas les mêmes structures
j'en ai enlevé un et l'autre en public et "ok"
pour être clair là je pense qu'il s'agit d'un problème de porté par rapport a un besoin qui ferait que tu es obligé de le mettre en private mais non ce n'est pas possible
 
Dernière édition:

Dudu2

XLDnaute Barbatruc
j'en ai enlevé un et l'autre en public et "ok"
Oui ça, ça fonctionne.
Mais le problème c'est que lorsqu'on a des modules différents utilisant la même structure, selon les modules utilisés, dans lequel déclarer la structure Public ?
C'est chi@nt comme problème VBA. C'est une limitation artificielle.
Ou alors utiliser les VarPtr et CopyMem.
 

TooFatBoy

XLDnaute Barbatruc
Mais le problème c'est que lorsqu'on a des modules différents utilisant la même structure, selon les modules utilisés, dans lequel déclarer la structure Public ?
A partir du moment où c'est Public, tu fais la déclaration où tu veux. Non ???


C'est chi@nt comme problème VBA. C'est une limitation artificielle.
Ben non, c'est tout l'intérêt des portées.
 
Dernière édition:

Dudu2

XLDnaute Barbatruc
Ce qui est contradictoire dans ce VBA, c'est qu'il n'accepte pas de passer une structure Private en argument mais qu'une fonction qui retourne une structure tout aussi Private et récupérée en Private dans un autre module fonctionne !
 

patricktoulon

XLDnaute Barbatruc
au ben je te dis pas je me bat avec lui pour qu'il me pêche mon erreur sur le device depuis hier il a toujours pas trouvé
tu va devoir faire une conversion de la même manière que je l'ai fait pour une structure RECT qui doit etre transmise d'une sub vba a une sub en adressof et la reconstruire dans la "b"
ou alors une classe avec des variable public comme te la indiqué @jurassic pork
 

Discussions similaires

Les cookies sont requis pour utiliser ce site. Vous devez les accepter pour continuer à utiliser le site. En savoir plus…