XL 2016 VBA - Comment pouvoir traiter normalement une structure perso

Dudu2

XLDnaute Barbatruc
Bonjour,
Avec Excel VBA on ne peut pas passer une structure utilisateur en argument d'une fonction ni en faire un retour de fonction.
Y a-t-il un moyen ? En faire une classe ?
VB:
Private Type TabAreas
    TabValues() As Variant
End Type

Dim TabAreasVal() As TabAreas
 
Dernière édition:
Solution
Bonjour,
ThisWorbook est un module de classe pas un module standard !
Code:
set wb=ThisWorbook

Par conséquent tu n'as pas accès à tous ce qui est privé.

Il est vrai que tout ce qui est privé devrait être accessible de l'intérieur du module de classe mais c'est comme ça !

Notes également que tout ce qui est privé dans un module standard n'est pas viable d'un autre monde !

laurent950

XLDnaute Accro
Bonsoir @Dudu2 , @Dranreb

Peut être que c'est comme cela ? c'est des Array a dimensionner

VB:
Private Type TabAreas
    TabValues() As Variant
End Type

Sub test()
    Dim TabAreasVal() As TabAreas
    ReDim TabAreasVal(0)
    ReDim TabAreasVal(0).TabValues(0)
    TabAreasVal(0).TabValues(0) = "Test"
    MsgBox TabAreasVal(0).TabValues(0)
End Sub
 
Dernière édition:

Dranreb

XLDnaute Barbatruc
Là je pensais à de petits Array d'une dimension qui ne change pas. Ils peuvent stocker des données disparates, sans avoir les inconvénient ni des classes ni des autre types définis par l'utilisateur. Par contre évidemment ses composants n'ont pas de nom, on ne peut y accéder que positionnellement par un indice.
 

dysorthographie

XLDnaute Accro
Bonjour,
Avec Excel VBA on ne peut pas passer une structure utilisateur en argument d'une fonction ni en faire un retour de fonction.
Y a-t-il un moyen ? En faire une classe ?
VB:
Private Type TabAreas
    TabValues() As Variant
End Type

Dim TabAreasVal() As TabAreas
bonjour,
je ne comprends pas pourrais tu expliciter!
VB:
Private Type TabAreas
    TabValues() As Variant
End Type

Dim TabAreasVal() As TabAreas
Function test(V() As TabAreas, I As Integer) As TabAreas()
ReDim Preserve V(I)
ReDim Preserve V(I).TabValues(I)
test = V()
End Function

Sub Test1()
Dim A() As TabAreas, I As Integer
For I = 0 To 10
 A() = test(TabAreasVal(), I)
Next
End Sub
 

Dranreb

XLDnaute Barbatruc
Oui c'est vrai la 1ère impossibilité évoquée n'existe pas. On peut tout à fait transmettre une variable d'un type défini par l'instruction Type à une procédure. C'est même souvent comme ça que sont transmis les paramètres aux API, Sub ou Function déclarées par instruction Declare. D'autres limitations existent néanmoins, venant surtout de ce qu'on ne peut l'affecter à un Variant, ni du coup le ranger dans une collection ni un Dictionary.
 

Dudu2

XLDnaute Barbatruc
Bonjour @Dranreb, @laurent950, @dysorthographie

Merci de vous être penchés sur cette affaire.
Je viens de découvrir pourquoi j'ai ce problème sans en comprendre la raison précise.

1629965264586.png


En fait, dans le fichier "OK" joint le passage de paramètres d'un type privé et le retour de fonction d'un type privé marchent très bien dès lors qu'ils sont dans un Module de code.

Si dans le fichier "KO" joint je place exactement le même code dans la classe/module(?) ThisWorbook (et ma question vient de cette situation) j'ai ce message d'erreur.

Ça veut dire que d'un point de vue pratique il faut que je gère ce genre de situation en plaçant le code dans un Module.
 

Pièces jointes

  • KO.xlsm
    18 KB · Affichages: 6
  • OK.xlsm
    21 KB · Affichages: 5

dysorthographie

XLDnaute Accro
Bonjour,
ThisWorbook est un module de classe pas un module standard !
Code:
set wb=ThisWorbook

Par conséquent tu n'as pas accès à tous ce qui est privé.

Il est vrai que tout ce qui est privé devrait être accessible de l'intérieur du module de classe mais c'est comme ça !

Notes également que tout ce qui est privé dans un module standard n'est pas viable d'un autre monde !
 
Dernière édition:

Dranreb

XLDnaute Barbatruc
Bonjour.
Il y aura à terme d'autre choses à coté du TabValues() As Variant dans votre Private Type TabAreas j'espère !
Sinon je ne vois pas pourquoi vous vous compliquez la vie avec ce type.
Mais vous auriez alors aussi mons de problèmes si c'était par exemple un tableau (0 to 2) As Variant dont le poste 2 était déstiné à contenir votre TabValues par exemple.
 

Dudu2

XLDnaute Barbatruc
Mais vous auriez alors aussi mons de problèmes si c'était par exemple un tableau (0 to 2) As Variant dont le poste 2 était déstiné à contenir votre TabValues par exemple.
Oui j'ai pensé à tout mettre dans 1 seul tableau à 3 dimensions (1 dimension Area et 2 dimensions Values) mais je ne peux plus identifier la largeur de chaque Area. A moins que tu ne penses autre chose car je ne comprends pas ce 0 to 2. Ajouter le n° d'Area en 0 ?
Il y aura à terme d'autre choses à coté du TabValues() As Variant dans votre Private Type TabAreas j'espère !
En effet, il y a l'adresse de la feuille de l'Area. J'hésite à mettre le Range de l'Area qui peut évoluer indépendamment du contenu.
 

Dudu2

XLDnaute Barbatruc
Je veux stocker des valeurs de Range:
VB:
Private Type TabAreas
    Area As Range
    TabValues() As Variant
End Type

Sub Test()
    Dim TabAreasVal() As TabAreas
    
    If TypeOf Selection Is Range Then TabAreasVal = LoadTabAreas(Selection)
End Sub

'-------------------------------------------------------------
'Place les valeurs d'un Range dans un tableau de Type TabAreas
'-------------------------------------------------------------
Function LoadTabAreas(Rng As Range) As TabAreas()
    Dim TabAreasVal() As TabAreas
    Dim Area As Range
    Dim AreaIndex As Integer
   
    'Range vide
    If Rng Is Nothing Then GoTo ExitFunction
   
    'Nombre d'Areas
    ReDim TabAreasVal(1 To Rng.Areas.Count)
   
    For Each Area In Rng.Areas
        AreaIndex = AreaIndex + 1
        Set TabAreasVal(AreaIndex).Area = Area
       
        If Area.Cells.Count = 1 Then
            ReDim TabAreasVal(AreaIndex).TabValues(1 To 1, 1 To 1)
            TabAreasVal(AreaIndex).TabValues(1, 1) = Area.Value
        Else
            TabAreasVal(AreaIndex).TabValues = Area.Value
        End If
    Next Area
   
ExitFunction:
    LoadTabAreas = TabAreasVal
End Function
 

Dranreb

XLDnaute Barbatruc
Peut être comme ça, avec l'adresse devant :
VB:
Function AdrZonVal(ByVal R As Range) As Variant()
   AdrZonVal = Array(R.Address(External:=True), ZonVal(R))
   End Function
Function ZonVal(ByVal R As Range) As Variant()
   CréerZonVal ZonVal, R
   End Function
Sub CréerZonVal(TZon(), ByVal Rng As Range)
   Dim Zon As Range, A&, TV(1 To 1, 1 To 1)
   ReDim TZon(1 To Rng.Areas.Count)
   For Each Zon In Rng.Areas
      A = A + 1
      If Zon.Cells.Count = 1 Then
         TV(1, 1) = Zon.Value
         TZon(A) = TV
      Else
        TZon(A) = Zon.Value
        End If
      Next Zon
   End Sub
 

Discussions similaires

Réponses
3
Affichages
288
Réponses
2
Affichages
452

Statistiques des forums

Discussions
312 464
Messages
2 088 630
Membres
103 895
dernier inscrit
jrlauret