XL 2016 Collection d'objets personnalisés avec propriété tableau dans VBA excel

CyrilleB

XLDnaute Nouveau
Je tente de programmer une sorte de Jeu Tetris pour lequel je voudrais stocker les pièces dans une collection d'objet
J'ai créé une classe d'objet dans un module de classe appelé "Piece"
J'ai créé une collection dans un module appelé "Pieces", la collection comprendra l'ensemble des pièces
Le module standard instancie une collection ColP
Et ajoute un objet pièce à la collection ColP, la pièce est définie par sa Forme (tableau de booléen)

A l'execution, j'ai un message d'erreur sur la ligne .Forme = bForme de la fonction CreatePiece
Le message dit succinctement "Internal Error"

J'ai tenté de remplacer
VB:
CreatePiece(ByRef bForme() As Boolean)
par
VB:
CreatePiece(bForme() As Boolean)

Mais ça ne change rien

Voici le module standard
VB:
Sub NouvellePartie()

Dim colP As Pieces
Dim Forme() As Boolean

'Initialisation de forme à false
ReDim Forme(0 To 5, 0 To 5)
For i = 1 To 5
    For j = 1 To 5
        Forme(i, j) = False
    Next
Next

Set colP = New Pieces
With colP
   .Add .CreatePiece(Forme)
End With

End sub

Le module de classe appelé "Piece" (au sigulier)
VB:
'---------------------
' Module de Classe Pièce de Puzzle
'---------------------

'Forme de la pièce dans un tableau de booléens
Private mbForme() As Boolean

'Forme
'--------------------------
Property Get Forme() As Boolean()

  ' Propriété en lecture
   Forme = mbForme
End Property

Property Let Forme(ByRef MaForme() As Boolean)

    ' Propriété en écriture
    mbForme = MaForme
End Property

Le module de classe appelé "Pieces" (au pluriel), la collection comprendra l'ensemble des pièces
VB:
Private mcolPieces As Collection

Property Get Count() As Long
    Count = mcolPieces.Count
End Property

Public Sub Add(ByRef objPiece As Piece, _
                    Optional ByVal NumPiece As String = "")

'Si aucune clé key n'est fournit on en génère une automatiquement
    If Len(NumPiece) = 0 Then
        NumPiece = CStr(objPiece.ID)
    End If
    mcolPieces.Add objPiece, NumPiece
    Set objPiece = Nothing
End Sub


Public Sub Remove(ByVal Index As Variant)
    mcolPieces.Remove (Index)
End Function

Public Function Item(ByVal Index As Variant) As Piece
    Set Item = mcolPieces.Item(Index)
End Function

Public Function CreatePiece(ByRef bForme() As Boolean) As Piece
Dim objPiece  As Piece

    Set objPiece = New Piece
    With objPiece
             .Forme = bForme
    End With

    Set CreatePiece = objPiece

    If Not (objPiece Is Nothing) Then Set objPiece = Nothing
End Function


Ce qui est étonnant c'est que lorsque je crée et j'ajoute la pièce à la collection Colp directement dans le module standard je n'ai pas d'erreur:
VB:
Sub NouvellePartie()

Dim colP As Pieces
Dim objPiece  As Piece

ReDim Forme(0 To 5, 0 To 5)
For i = 1 To 5
    For j = 1 To 5
        Forme(i, j) = False
    Next
Next

Set colP = New Pieces
Set objPiece = New Piece

With objPiece
        .Forme = Forme
End With
colP.Add objPiece
If Not (objPiece Is Nothing) Then Set objPiece = Nothing

end sub

Merci d'avance pour votre aide précieuse.
 

CyrilleB

XLDnaute Nouveau
@patricktoulon : Dans le fichier que j'ai transmis j'ai simplifié et retiré ce qui ne concerne pas ma demande pour rendre plus lisible le fichier à debogger. Les objets "Pieces" ont d'autres propriétés et d'autres méthodes que j'ai retirées. Le fait que Forme soit un tableau m'est précieux pour cela.

Merci @dysorthographie pour le fichier que tu as transmis et qui fonctionne mais si c'est possible je souhaite conserver la variable Forme de type tableau.

Merci @Danreb pour la solution avec méthode init, ça fonctionne !
Par contre je n'ai pas compris pourquoi il faut passer objPiece byVal dans
VB:
Public Sub Add(ByVal objPiece As Piece, Optional ByVal NumPiece As String = "")
ça fonctionne bien quand on passe objPiece ByRef et dans son tutoriel, Michel Blavin l'écrit de cette façon : https://sinarf.developpez.com/access/vbaclass/

Merci d'avance
 

dysorthographie

XLDnaute Accro
Ce n'est pas possible !
Soit tu place ton tableau dans la partie haute d'un module standard soit tu passe tu passes un objet !

Un tableau n'est pas un objet !

tu peux comme je l'ai dis plus haut placer ton tableau en publique dans un module de classe et la ça devient un objet!
classe Forme!
VB:
Public Forme As Variant
Private Sub Class_Initialize()
Dim T(0 To 5, 0 To 5) As Boolean
Forme = T
End Sub
Code:
Sub NouvellePartie()

Dim colP As New Pieces
Dim objPiece  As Piece

Dim ID As Integer
Dim Forme As New Forme

ID = 1

'------- Crée la collection de pièces ColP --------------------------
'J'aurais dû utiliser les lignes suivantes mais ça bug
    With colP
        .Add .CreatePiece(ID, Forme)
    End With
 
Dernière édition:

Dranreb

XLDnaute Barbatruc
Par contre je n'ai pas compris pourquoi il faut passer objPiece byVal dans
VB:
VB:
Public Sub Add(ByVal objPiece As Piece, Optional ByVal NumPiece As String = "")
ça fonctionne bien quand on passe objPiece ByRef et dans son tutoriel, Michel Blavin l'écrit de cette façon
Oui mais c'est idiot !
Le passage ByRef d'un argument objet ne se justifierait que si ces 2 conditions étaient réunies lors d'un appel :
1) — C'est une variable de ce type d'objet qui est spécifiée et non une expression qui en désigne un de déjà défini,
2) — La procédure est chargée de le définir par un Set pour un besoin externe à elle.
Pent être peut-on mieux comprendre ça si on sait qu'une variable objet correspond à une zone faite pour contenir l'adresse des structures d'un exemplaire d'objet. Ce qui consiste à le modifier c'est de changer cette adresse, c'est à dire initialiser la variable par un Set et non pas de s'en servir pour accéder à ses propriétés et méthodes. Ces accès ne sont nullement impactés par le passage ByRef ou ByVal. Mais ByVal est beaucoup plus simple: il transmet simplement l'adresse de l'exemplaire puisque techniquement celle ci est la valeur de la variable objet. Avec ByRef il doit transmettre l'adresse d'une zone qui contient cette adresse de l'exemplaire. Quand c'est une variable objet ça va encore: c'est l'adresse de la variable. Mais quand c'est une expression, il doit fabriquer la variable objet temporaire dans une zone de travail, et transmettre l'adresse de cette zone. Complètement idiot !
C'est pour ça que les objets sont toujours transmis ByVal au procédures de prise en charge d'évènements Excel.
 
Dernière édition:

Dranreb

XLDnaute Barbatruc
Bonjour.
Effectivement un Set sur un argument objet passé ByVal ne changera pas l'exemplaire désigné par la variable correspondante qui aura été spécifiée. En revanche aucun problème pour la manipulation de l'objet par la procédure, ou sa transmission, etc.
 

Discussions similaires

Statistiques des forums

Discussions
314 729
Messages
2 112 268
Membres
111 481
dernier inscrit
zrk