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

XL 2013 les machistes (utilisateurs de Mac OS peuvent ils tester ceci

patricktoulon

XLDnaute Barbatruc
Bonjour à tous
@RyuAutodidacte m' a rappelé un lien vers un amis de l'autre monde concernant une classe pseudo dictionnaire pour MAC
malgré que j'apprécie beaucoup l'auteur (avec qui j'ai même collaboré sur l’accélérateur de requête entre autres ) ,je trouve que c'est un peu usine à gaz

j'ai donc fait les choses à ma façon
mais avant d'aller plus loin car des idées j'en ai plein ,si vous êtes un utilisateur sur MAC pouvez vous tester ce pseudo dictionnaire
sur Windows ça match il me faut confirmation sur MAC

Merci pour vos retours
 

Pièces jointes

  • classe dictionary pour Mac.xlsm
    18.3 KB · Affichages: 10
Dernière édition:

patricktoulon

XLDnaute Barbatruc
re non ça j'ai pas prévu car le dictionnaire ne fonctionne pas comme ça
je vois pas pourquoi on irait faire une classe dico avec des collections pour le faire marcher comme une collection ça n'a pas de sens
je suis entrain d' ajouter le tri optionnel par clé ou items je continurerais demain
 

laurent950

XLDnaute Barbatruc
Bonjour @patricktoulon

J'ai une question le module de classe que tu as construit contient aucune Property Let / Set / Get
j'ai essayé avec ces propriété et je suis confronté a un soucis je te montre

le code fonctionne bien mais il y a un mais !!

au début de mon module standard pour tester j'inclus cette Objet (la feuille excel) c'est juste pour le test, cela peut être un range ou autres Objet (L'idée et d'y ajouter un objet d'un module de classe ensuite)

mais voila après le début du code du module standard j'explique le comportement dans le module de classe.

Module standard(Module1) le début
Code:
    Dim myCollection As New CollectionWithDictionary
    Dim key As Variant
    Dim Value As Variant
    ' Test
    Dim F As Worksheet
        Set F = ThisWorkbook.Worksheets(ActiveSheet.Name)

    ' Ajouter des éléments à la collection
        ' Object
            myCollection.Addobj F, "Key0"
        ' Variant
            myCollection.Addvar "Value1", "Key1"
            myCollection.Addvar "Value2", "Key2"


je suis obligé de construire de ADD
un ADD pour les Object = Addobj
un ADD pour les Variant = Addvar

car avec Let et Get impossible de créer un choix c'est soit type variant ou type Objet ?

Code:
' Item Variant Or Object
' Item Variant
Public Property Let itemVar(MaVariable As Variant)
    mItemVar = MaVariable
End Property
Public Property Get itemVar() As Variant
    itemVar = mItemVar
End Property

Code:
' Item Object
Public Property Let itemObj(MaVariable As Object)
    Set mItemObject = MaVariable
End Property
Public Property Get itemObj() As Object
    Set itemObj = mItemObject
End Property

j'ai essayer cela mais cela ne fonctionne pas ?

Code:
' Item Variant Or Object
Public Property Let itemVar(MaVariable)
    If IsObject(MaVariable) Then
        Set mItemVar = MaVariable
    Else
        mItemVar = MaVariable
    End If
End Property

' Item Variant
End Property
Public Property Get itemVar() As Variant
    itemVar = mItemVar
End Property

' Item Object
Public Property Get itemObj() As Object
    Set itemObj = mItemObject
End Property


avec cela mais cela ne fonctionne pas

' Méthode Object Add pour ajouter une paire clé-élément
Public Sub Addobj(MaObjItem, Optional ByVal key As String)
    Dim Cls As CollectionWithDictionary
    Set Cls = New CollectionWithDictionary
        Cls.itemObj = MaObjItem
        Cls.key = key
        mColl.Add item:=Cls, key:=Cls.key
End Sub


Alors j'ai construit le code ci dessous avec la contrainte de la variable Variant Ou Object a définir dans l'Object collection lors de l'import comme expliqué plus haut ?

il y a surement une explication ? si tu as la solution ou l'explication c'est avec plaisir d'apprendre, j'ai fait cela dans le but d'un exercice pour comprendre le principe du module de classe c'est certainement incomplet, il y a des gestion d'erreur encore j'ai pas trous tester mais cela fonctionne déjà avec le code ci-dessous.

le module de classe(CollectionWithDictionary)

VB:
' Module de classe CollectionWithDictionary
Private mIsTerminated As Boolean
Private mKey As String                              ' Obligatoire. Clé associée à l'élément ajouté.
Private mItemVar As Variant                         ' Obligatoire. Élément Variant associé à la clé ajoutée.
Private mItemObject As Object                       ' Obligatoire. Élément Object associé à la clé ajoutée.
Private mColl As New Collection

' Constructeur
Private Sub Class_Initialize()
    'Set mColl = New Collection
        mIsTerminated = False
End Sub

' Destructeur
Private Sub Class_Terminate()
        mKey = Empty: mItemVar = Empty: Set mItemObject = Nothing
    Set mColl = Nothing
        mIsTerminated = True
End Sub

' Item Variant Or Object
' Item Variant
Public Property Let itemVar(MaVariable As Variant)
    mItemVar = MaVariable
End Property
Public Property Get itemVar() As Variant
    itemVar = mItemVar
End Property

' Item Object
Public Property Let itemObj(MaVariable As Object)
    Set mItemObject = MaVariable
End Property
Public Property Get itemObj() As Object
    Set itemObj = mItemObject
End Property

' Key la clé pour la collection
Public Property Let key(MaVariable As String)
    mKey = MaVariable
End Property
Public Property Get key() As String
    key = mKey
End Property

' Lecture de la collection dans le module de classe
Public Property Get LectColl() As Collection
    Set LectColl = mColl
End Property

' Lecture de la collection dans le module de classe
Public Property Get LectCollcls() As CollectionWithDictionary
    Dim col As Collection
        Set col = LectColl
    Dim Cls As CollectionWithDictionary
        Set Cls = col.item(mKey)
End Property

' Méthode Variant Add pour ajouter une paire clé-élément
Public Sub Addvar(ByVal MaVaritem As Variant, Optional ByVal key As String)
    Dim Cls As CollectionWithDictionary
    Set Cls = New CollectionWithDictionary
    Cls.itemVar = MaVaritem
    Cls.key = key
    mColl.Add item:=Cls, key:=Cls.key
End Sub
' Méthode Object Add pour ajouter une paire clé-élément
Public Sub Addobj(ByVal MaObjItem As Object, Optional ByVal key As String)
    Dim Cls As CollectionWithDictionary
    Set Cls = New CollectionWithDictionary
    Cls.itemObj = MaObjItem
    Cls.key = key
    mColl.Add item:=Cls, key:=Cls.key
End Sub

' Méthode Exists pour vérifier si une clé existe dans la collection
' Version V0
'''''''''''Function Exists(ByVal mKey As String) As Boolean
'''''''''''' Le code suivant vérifie si une clé existe
'''''''''''    Dim col As Collection
'''''''''''        Set col = LectColl
'''''''''''    Dim Cls As CollectionWithDictionary
'''''''''''    Set Cls = col.item(mKey)
'''''''''''    On Error Resume Next
'''''''''''        IsObject (col.item(mKey))
'''''''''''            If Err.Number = 0 Then
'''''''''''                ' Aucune erreur, la clé existe
'''''''''''                    If Not Cls.itemObj Is Nothing Then
'''''''''''                        Exists = True
'''''''''''                    ElseIf Cls.itemObj Is Nothing And Cls.itemVar <> Empty Then
'''''''''''                        Exists = True
'''''''''''                    End If
'''''''''''            Else
'''''''''''                ' Une erreur s'est produite, la clé n'existe pas
'''''''''''                        Exists = False
'''''''''''            End If
'''''''''''    On Error GoTo 0 ' Rétablir la gestion des erreurs normale
'''''''''''End Function
'
' Version V1
Function Exists(ByVal mKey As String) As Boolean
    Dim col As Collection
    Set col = LectColl
    Dim Cls As CollectionWithDictionary
    On Error Resume Next
    Set Cls = col.item(mKey)
    On Error GoTo 0
    
    If Not Cls Is Nothing Then
        If Not Cls.itemObj Is Nothing Or Cls.itemVar <> Empty Then
            Exists = True
        End If
    End If
End Function

' Méthode Keys pour retourner un tableau contenant toutes les clés
Public Function Keys() As Variant()
    Dim Cls As CollectionWithDictionary
    Dim col As Collection
    Set col = LectColl
    Dim i As Integer
    Dim Result() As Variant
    ReDim Result(1 To col.Count)
    For i = 1 To col.Count
        Set Cls = col.item(i)
        Result(i) = Cls.key
    Next i
    Keys = Result
End Function

' Méthode Items pour retourner un tableau contenant tous les éléments (sauf Object !)
Public Function Items() As Variant()
    Dim Cls As CollectionWithDictionary
    Dim col As Collection
    Set col = LectColl
    Dim i As Integer
    Dim Result() As Variant
    ReDim Result(1 To col.Count)
    For i = 1 To col.Count
        Set Cls = col.item(i)
        Result(i) = Cls.itemVar
    Next i
    Items = Result
End Function

' Méthode Remove pour supprimer une paire clé-élément
Public Sub Remove(key As Variant)
    Dim Cls As CollectionWithDictionary
    Dim col As Collection
    Set col = LectColl
    Set Cls = col.item(key)
        col.Remove Cls.key
End Sub

'
' Propriété Count pour obtenir le nombre d'éléments
Public Property Get Count() As Long
    Dim col As Collection
    Set col = LectColl
    Count = col.Count
End Property
'

' Méthode RemoveAll pour supprimer toutes les paires clé-élément
Public Sub RemoveAll()
    Dim Cls As CollectionWithDictionary
    Dim col As Collection
    Set col = LectColl
    For i = 1 To col.Count
        Set Cls = col.item(1)
            col.Remove Cls.key
    Next i
End Sub

puis un module standard(Module1) pour tester
' Module standard (Module1)
Code:
Sub TestCollectionWithDictionary()
    Dim myCollection As New CollectionWithDictionary
    Dim key As Variant
    Dim Value As Variant
    ' Test
    Dim F As Worksheet
        Set F = ThisWorkbook.Worksheets(ActiveSheet.Name)


    ' Ajouter des éléments à la collection
        ' Object
            myCollection.Addobj F, "Key0"
        ' Variant
            myCollection.Addvar "Value1", "Key1"
            myCollection.Addvar "Value2", "Key2"


    ' Vérifier si une clé existe
    If myCollection.Exists("Key2") Then
        Debug.Print "La clé 'Key1' existe."
    Else
        Debug.Print "La clé 'Key1' n'existe pas."
    End If


    ' Récupérer la valeur associée à une clé
    key = "Key2"
    If myCollection.Exists(key) Then
        Dim Cls As CollectionWithDictionary
            Set Cls = myCollection.LectColl.item(key)
            Debug.Print "La valeur associée à la clé '" & Cls.key & "' est '" & Cls.itemVar & "'."
    Else
        Debug.Print "La clé '" & key & "' n'existe pas."
    End If


    ' Afficher toutes les clés de la collection
    Dim Keys() As Variant
    Keys = myCollection.Keys
    Dim i As Long
    For i = LBound(Keys) To UBound(Keys)
        Debug.Print "Clé : " & Keys(i)
    Next i
    i = Empty
    
    ' Afficher toutes les Items de la collection
    Dim Items() As Variant
    Items = myCollection.Items
    'Dim i As Long
    For i = LBound(Items) To UBound(Items)
        If Items(i) = Empty Then Debug.Print "Clé : " & "Object" Else Debug.Print "Clé : " & Items(i)
    Next i


    ' Supprimer un élément de la collection
    myCollection.Remove "Key0"


    ' Afficher le nombre d'éléments restants
    Debug.Print "Nombre d'éléments dans la collection : " & myCollection.Count


    ' Supprimer tous les éléments de la collection
    myCollection.RemoveAll
    Debug.Print "Nombre d'éléments après suppression : " & myCollection.Count
End Sub
 

patricktoulon

XLDnaute Barbatruc
re
ben tu a presque compris pourquoi je n'utilise pas les property let ou get
cela dit j'irais pas mettre les mains dans ton truc
quand je vois ça dans un module standard
VB:
 ' Récupérer la valeur associée à une clé
    key = "Key2"
    If myCollection.Exists(key) Then
        Dim Cls As CollectionWithDictionary
            Set Cls = myCollection.LectColl.item(key)
            Debug.Print "La valeur associée à la clé '" & Cls.key & "' est '" & Cls.itemVar & "'."
    Else
        Debug.Print "La clé '" & key & "' n'existe pas."
    End If
je me dis qu'il y a des choses que tu n'a pas compris
là mon ami on marche sur la tête
en même temps c'est compréhensible tu t'attaque au classe de @Dranreb avant d'avoir compris l'essentiel
alors voila sa se traduit par ce genre de code alambiqué ou même moi ne sais pas ou donner de la tête
 

laurent950

XLDnaute Barbatruc
Bonjour @patricktoulon ,
Plongé dans les codes modules de classes, il arrive un moment où cela me GET de me retrouver dans une impasse et du coup le moindre grain de sable en devient un défi insurmontable !

Alors quand @Dranreb se met à jongler avec les classes, on peut dire qu’il a vraiment la "classe" !

Même si ça parfois perdu dans mes labyrinthes, je garde le cap et c’est aussi ce qui rend le code amusant, enfin pas toujours (Rire) !

Merci Patrick pour ta réponse.
 

patricktoulon

XLDnaute Barbatruc
tu fait un module classe d'object alors tout doit être géré dans la classe
les add , les property , les returns lecture,ecriture , etc..
sinon ça n'a pas de sens
le module standard ou autre n'est et ne doit être que le pilote
regarde ma classe dico et apprends et pose des questions

alors oui le property let et get limitent drastiquement les possibilité car on est vite en dépassement de capacité
donc pour ce genre de classe ,tu oublie passe en variable public si tu dois y avoir accès en lecture ou écriture

ensuite l'object collection est déjà en lui même un object avec clé/items
pourquoi veux tu multiplier les instances de classe tu n'en a besoins de qu'une
mon instance de classe . monobjectcollection . add "x","y"
je te l'accorde tu peux faire avec x instances de classes mais bon c'est se compliquer la vie
 

laurent950

XLDnaute Barbatruc
Re @patricktoulon

Voila un essaie cela fonctionne bien

Module standard(Module1)
VB:
Sub Test()
Dim f As Worksheet
    Set f = ThisWorkbook.Worksheets(ActiveSheet.Name)
Dim r As Range
    Set r = f.Range("A1:E20")
Dim Text As String
    Text = "Le texte que j'ai écris ici"

Dim Stock As New ClasseLetGetSet ' Stock le type d'objet

    Stock.Property_Name = Text
    MsgBox Stock.Property_Name
   
    Set Stock.Property_Name = r
    MsgBox Stock.Property_Name.Address
End Sub

le module de classe(ClasseLetGetSet)


Code:
'Property - Variant
Private field_vValue As Variant

Property Get Property_Name() As Variant
    If IsObject(field_vValue) Then
        Set Property_Name = field_vValue
    Else
        Property_Name = field_vValue
    End If
End Property

' You could use either Let or Set
Property Let Property_Name(vData As Variant)
    field_vValue = vData
End Property

Property Set Property_Name(vData As Variant)
    Set field_vValue = vData
End Property
 

patricktoulon

XLDnaute Barbatruc
re
ca c'est d&ja mieux
mais pour ca nul besoins d'utiliser let get set
c'est trois procédure sont utile quand il y a décantation à faire ou calculs ou autre travail sur la donnée
une simple variable suffit pour ton exemple
de plus encore une fois utiliser une variable pour deux type de données c'est pas la meilleure idée
 

patricktoulon

XLDnaute Barbatruc
regarde deja pour ton dictionnaire a multi classe(instances)
on va commencer comme ça
nouveau classeur
un module standard
un module classe que l'on nomme dictionnaire
dans le module classe tu va lui mettre ceci
VB:
Public elements As New Collection
Public key
Public item
Public keys
Public items


Public Function Add(k, i)
     Dim cl As New dictionnaire
    cl.key = k
    cl.item = i
    Me.elements.Add cl
End Function
tu vois c'est pas compliqué
ensuite dans le module standard on va mettre ceci
VB:
Dim dico As dictionnaire
Sub ecriture()
    Set dico = New dictionnaire
    dico.Add "toto", "28"
    dico.Add "titi", "54"
    dico.Add "riri", "48"
End Sub

Sub lecture()
    MsgBox dico.elements.Count
    For Each elem In dico.elements
        MsgBox "key: " & elem.key & "--item: " & elem.item
    Next
End Sub
chiche on test!!!!
HOH... BEN CA MARCHE DIS DONC


allez tu te sent de faire la fonction exists pour eviter les doublons ?
d’après toi comment faire avec x instances de classe?
 

laurent950

XLDnaute Barbatruc
Re @patricktoulon

Je viens de corrigé, j'ai écouté mais je souhaite réussir c'est complexe quand même

Module standard(Module 1)
Code:
' Module standard (Module1)
Sub TestCollectionWithDictionary()
    Dim myCollection As New CollectionWithDictionary
    Dim key As Variant
    Dim Value As Variant
    ' Test
    Dim F As Worksheet
        Set F = ThisWorkbook.Worksheets(ActiveSheet.Name)

    ' Ajouter des éléments à la collection
        ' Object
            myCollection.Add F, "Key0"
        ' Variant
            myCollection.Add "Value1", "Key1"
            myCollection.Add "Value2", "Key2"

    ' Vérifier si une clé existe
    If myCollection.Exists("Key1") Then
        Debug.Print "La clé 'Key1' existe."
    Else
        Debug.Print "La clé 'Key1' n'existe pas."
    End If

    ' Récupérer la valeur associée à une clé
    key = "Key2"
    If myCollection.Exists(key) Then
        Dim col As Collection
            Set col = myCollection.LectColl
        Dim Cls As CollectionWithDictionary
            Set Cls = col.item(key)
            Debug.Print "La valeur associée à la clé '" & Cls.key & "' est '" & Cls.item & "'."
    Else
        Debug.Print "La clé '" & key & "' n'existe pas."
    End If

    ' Afficher toutes les clés de la collection
    Dim Keys() As Variant
    Keys = myCollection.Keys
    Dim i As Long
    For i = LBound(Keys) To UBound(Keys)
        Debug.Print "Clé : " & Keys(i)
    Next i
    i = Empty
    
    ' Afficher toutes les Items de la collection
    Dim Items() As Variant
    Items = myCollection.Items
    'Dim i As Long
    For i = LBound(Items) To UBound(Items)
        If Items(i) = Empty Then Debug.Print "Clé : " & "Object" Else Debug.Print "Clé : " & Items(i)
    Next i

    ' Supprimer un élément de la collection
    myCollection.Remove "Key0"

    ' Afficher le nombre d'éléments restants
    Debug.Print "Nombre d'éléments dans la collection : " & myCollection.Count

    ' Supprimer tous les éléments de la collection
    myCollection.RemoveAll
    Debug.Print "Nombre d'éléments après suppression : " & myCollection.Count
End Sub

Module de classe(CollectionWithDictionary)
Code:
' Module de classe CollectionWithDictionary
Private mIsTerminated As Boolean
Private mKey As String                              ' Obligatoire. Clé associée à l'élément ajouté.
Private mItem As Variant                            ' Obligatoire. Élément Variant associé à la clé ajoutée. (Variant / Object)
Private mColl As New Collection

' Constructeur
Private Sub Class_Initialize()
    'Set mColl = New Collection
        mIsTerminated = False
End Sub

' Destructeur
Private Sub Class_Terminate()
        mKey = Empty: mItemVar = Empty: Set mItemObject = Nothing
    Set mColl = Nothing
        mIsTerminated = True
End Sub

' Item Variant Or Object
Public Property Let item(MaVariable As Variant)
    mItem = MaVariable
End Property
Public Property Set item(MaVariable As Variant)
    Set mItem = MaVariable
End Property
Public Property Get item() As Variant
On Error Resume Next
    If IsObject(field_vValue) Then
        Set item = mItem
    Else
        item = mItem
    End If
On Error GoTo 0
End Property

' Key la clé pour la collection
Public Property Let key(MaVariable As String)
    mKey = MaVariable
End Property
Public Property Get key() As String
    key = mKey
End Property

' Lecture de la collection dans le module de classe
Public Property Get LectColl() As Collection
    Set LectColl = mColl
End Property

' Lecture de la collection dans le module de classe
Public Property Get LectCollcls() As CollectionWithDictionary
    Dim col As Collection
        Set col = LectColl
    Dim Cls As CollectionWithDictionary
        Set Cls = col.item(mKey)
End Property

' Méthode Variant/Object Add pour ajouter une paire clé-élément
Public Sub Add(ByVal item As Variant, Optional ByVal key As String)
    Dim Cls As CollectionWithDictionary
    Set Cls = New CollectionWithDictionary
    If IsObject(item) Then
        Set Cls.item = item
        Cls.key = key
        mColl.Add item:=Cls, key:=Cls.key
    Else
        Cls.item = item
        Cls.key = key
        mColl.Add item:=Cls, key:=Cls.key
    End If
End Sub

' Méthode Exists pour vérifier si une clé existe dans la collection'
' Version V2
Function Exists(ByVal mKey As String) As Boolean
    Dim col As Collection
    Set col = LectColl
    Dim Cls As CollectionWithDictionary
    On Error Resume Next
    Set Cls = col.item(mKey)
    On Error GoTo 0
    Debug.Print Err.Number
    If Not Cls Is Nothing Then
            Exists = True
    End If
End Function
' Méthode Keys pour retourner un tableau contenant toutes les clés
Public Function Keys() As Variant()
    Dim Cls As CollectionWithDictionary
    Dim col As Collection
    Set col = LectColl
    Dim i As Integer
    Dim Result() As Variant
    ReDim Result(1 To col.Count)
    For i = 1 To col.Count
        Set Cls = col.item(i)
        Result(i) = Cls.key
    Next i
    Keys = Result
End Function

' Méthode Items pour retourner un tableau contenant tous les éléments (sauf Object !)
Public Function Items() As Variant()
    Dim Cls As CollectionWithDictionary
    Dim col As Collection
    Set col = LectColl
    Dim i As Integer
    Dim Result() As Variant
    ReDim Result(1 To col.Count)
    For i = 1 To col.Count
        Set Cls = col.item(i)
            If Cls.item <> Empty Then
                Result(i) = Cls.item
            End If
    Next i
    Items = Result
End Function

' Méthode Remove pour supprimer une paire clé-élément
Public Sub Remove(key As Variant)
    Dim Cls As CollectionWithDictionary
    Dim col As Collection
    Set col = LectColl
    Set Cls = col.item(key)
        col.Remove Cls.key
End Sub

'
' Propriété Count pour obtenir le nombre d'éléments
Public Property Get Count() As Long
    Dim col As Collection
    Set col = LectColl
    Count = col.Count
End Property
'

' Méthode RemoveAll pour supprimer toutes les paires clé-élément
Public Sub RemoveAll()
    Dim Cls As CollectionWithDictionary
    Dim col As Collection
    Set col = LectColl
    For i = 1 To col.Count
        Set Cls = col.item(1)
            col.Remove Cls.key
    Next i
End Sub
 

patricktoulon

XLDnaute Barbatruc
re
ben bon courage avec ca
je te l'ai dis tout à l'heure à partir du moment ou je vois des choses du genre
VB:
 Dim Cls As CollectionWithDictionary
            Set Cls = col.item(key)
dans une sub du module standard je jette tout à la poubelle
ça n'a pas de sens ce que tu fait
si tu dois instancier ,supprimer des object classe dans le module standard tu t'es trompé de chemin
tu veux persister va y mais je ne te suivrais pas c'est complétement absurde
en plus tu n'en es qu'au début et c'est déjà une usine a gaz ton truc dans le module et dans la classe
sincèrement clé/item non mais tu veux rire là

enfin si tu te décide a travailler correctement fait moi signe hein
 

laurent950

XLDnaute Barbatruc
Re @patricktoulon

C'était pour l'exercice, je m'arrête maintenant. Ton code est parfait, tout comme tes explications, qui sont très claires. Je te remercie. Je m'arrête avec le module de classe, c'était pour voir, mais tu as raison, c'est complexe.

Je te remercie Patrick
 

patricktoulon

XLDnaute Barbatruc
j'ai pas mal avancé sur le principe que tu souhaite
a savoir chaque paire cle/item est une instance de classe contrairement à mon module classe fini qui n'utilise qu'une classe et deux collections
je vais te dire honnêtement c'est presque plus facile
je te le montre ou pas ?
 
Les cookies sont requis pour utiliser ce site. Vous devez les accepter pour continuer à utiliser le site. En savoir plus…