IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Macros et VBA Excel Discussion :

Passage de tableau typé en paramètre d'une fonction - Erreur de compilation


Sujet :

Macros et VBA Excel

  1. #1
    Membre Expert
    Avatar de pijaku
    Homme Profil pro
    Inscrit en
    Août 2010
    Messages
    1 817
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Août 2010
    Messages : 1 817
    Billets dans le blog
    10
    Par défaut Passage de tableau typé en paramètre d'une fonction - Erreur de compilation
    Bonjour,

    Je n'ai pas besoin de solution, mais d'une explication.
    Pourquoi ce code ne fonctionne pas?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    Public Sub Main()
    Dim Grille(8, 8) As Integer
     
        Do
            Remplit_Grille (Grille)
        Loop While Not Verifie_Colonnes(Grille)
    End Sub
     
    Private Sub Remplit_Grille(ByRef t() As Integer)
    Dim i As Integer, j As Integer
     
        Randomize Timer
        For i = 0 To 8
            For j = 0 To 8
                t(i, j) = Int(Rnd() * 9) + 1
            Next j
        Next i
    End Sub
     
    Private Function Verifie_Colonnes(Grille() As Integer) As Boolean
    Dim Colonne(8) As Integer
    Dim i As Integer, j As Integer
     
        For j = 0 To 8
            For i = 0 To 8
                Colonne(i) = Grille(i, j)
            Next i
            If TousDifferents(Colonne) = False Then Exit Function
        Next j
        Verifie_Colonnes = True
    End Function
     
    Private Function TousDifferents(t() As Integer) As Boolean
    Dim i As Integer, j As Integer
     
        For i = 0 To 7
            For j = i + 1 To 8
                If t(i) = t(j) Then Exit Function
            Next j
        Next i
        TousDifferents = True
    End Function
    Il s'agit juste d'un "exercice", je ne souhaite donc pas de codage différent.
    Je veux juste comprendre pourquoi VBA bloque sur ma variable Grille (Ligne 5 du code) dans la Sub Main en disant :
    Erreur de compilation
    Incompatibilité de type : tableau ou type défini par l'utilisateur attendu.
    La solution la plus simple est de changer le type de t() As Integer dans la Sub Remplit_Grille par ByRef t As Variant, mais je souhaiterai comprendre.

    Pourquoi ma variable Grille passe bien en paramètre des Function TousDifferents et Function Verifie_Colonnes mais pas de la Sub Remplit_Grille ?
    => certainement parce qu'elle est vide au moment de Remplit_Grille et remplie au moment des fonctions ?...

    Egalement je voudrais savoir pourquoi on ne peux pas passer autre chose qu'un variant...

    Merci d'avance.

  2. #2
    Expert confirmé
    Homme Profil pro
    aucune
    Inscrit en
    Avril 2016
    Messages
    7 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 83
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : aucune

    Informations forums :
    Inscription : Avril 2016
    Messages : 7 563
    Par défaut
    Bonjour Franck
    Parce que Grille (matrice ou non) est une variable et qu'elle doit être passée comme toute autre variable (sans la redéfinir), tant dans l'appel que dans la procédure appelée.
    Enlève les parenthèses de Grille() dans ton argument ByRef. Et ne type pas Grille dont le type est déjà connu.

  3. #3
    Membre Expert
    Avatar de pijaku
    Homme Profil pro
    Inscrit en
    Août 2010
    Messages
    1 817
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Août 2010
    Messages : 1 817
    Billets dans le blog
    10
    Par défaut
    Salut Jacques,

    Merci de ta réponse.
    Depuis toujours, je suis ,implicitement convaincu que (ByRef t) me transformerai ma variable t en Variant.
    J'aurais du le vérifier bien avant car, il n'en est effectivement rien.
    Dans mon cas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    Public Sub Main()
    Dim Grille(8, 8) As Integer
     
        Do
            Remplit_Grille (Grille)
        Loop While Not Verifie_Colonnes(Grille)
    End Sub
    Private Sub Remplit_Grille(ByRef t)
    Dim i As Integer, j As Integer
     
        MsgBox TypeName(t)
    End Sub
    Retourne bien un type Integer().

    Mais alors, pourquoi cela passe sans souci dans les Function?

  4. #4
    Membre Expert
    Avatar de pijaku
    Homme Profil pro
    Inscrit en
    Août 2010
    Messages
    1 817
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Août 2010
    Messages : 1 817
    Billets dans le blog
    10
    Par défaut
    Bonjour,

    Je relance ce sujet pour deux questions :
    1- pourquoi cela passe sans souci dans les Function?

    Si je veux absolument un tableau d'entier passé en argument de ma Sub, le seul fait de mettre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Sub Machin(truc() As Integer)
    Va renvoyer une erreur 13 si le code appelant envoie autre chose qu'un tableau d'entier.
    Je n'ai donc pas à gérer ça du côté de la Sub appelée, mais du côté appelant.
    Donc, ma seconde question :
    2- Comment imposer un type particulier dans ce cas?

  5. #5
    Expert confirmé

    Homme Profil pro
    Curieux
    Inscrit en
    Juillet 2012
    Messages
    5 161
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Curieux
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2012
    Messages : 5 161
    Billets dans le blog
    5
    Par défaut
    Bonjour,

    que cherches-tu exactement ? Du coup je n'arrive plus à suivre si :

    - tu cherches à encapsuler le contrôle au sein de la sub appelée ou alors bloquer en amont l'appel par la Sub appelante si le type n'est pas celui que tu souhaites
    - tu veux au final avoir ton paramètre typé ou le laisser en Variant

  6. #6
    Expert confirmé
    Homme Profil pro
    aucune
    Inscrit en
    Avril 2016
    Messages
    7 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 83
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : aucune

    Informations forums :
    Inscription : Avril 2016
    Messages : 7 563
    Par défaut
    Je ne te comprends plus.
    Les deux fonctionnements sont quasi-identiques
    C'est ton appel de la sub, qui prête à confusuin
    Reprend ton premier message, qui disait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    Public Sub Main()
    Dim Grille(8, 8) As Integer
     
        Do
            Remplit_Grille (Grille)
        Loop While Not Verifie_Colonnes(Grille)
    End Sub
    Private Sub Remplit_Grille(ByRef t)
    Dim i As Integer, j As Integer
     
        MsgBox TypeName(t)
    End Sub
    Ta sub n'est pas appelée correctement depuis Main
    Aucun problème avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Dim Grille(8, 8) As Integer
     
        'Do --->> débarrassons-nous de cet aspect et concentrons-nous sur le seul appel de la sub
            Remplit_Grille Grille() ' --->> voilà comment doit être appelée la sub
        'Loop While Not Verifie_Colonnes(Grille)
        MsgBox Grille(1, 1)
    Grille ne spécifie pas de type, Grille(), oui

  7. #7
    Invité
    Invité(e)
    Par défaut
    Bonjour,
    Tu ne peux pas passer un tableau à une fonction mais un variant ou un Object!

    Vue que t dans ta fonction n'est pas typé c'est un variant.

  8. #8
    Expert confirmé
    Homme Profil pro
    aucune
    Inscrit en
    Avril 2016
    Messages
    7 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 83
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : aucune

    Informations forums :
    Inscription : Avril 2016
    Messages : 7 563
    Par défaut
    Bonjour Robert
    Regarde :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    Private Sub CommandButton1_Click()
      Dim tabl(5) As Integer
      For i = 0 To 4
        tabl(i) = i
      Next
      toto = fonction_titi(tabl())
      MsgBox toto
    End Sub
     
    Private Function fonction_titi(tabl() As Integer) As String
      tabl(2) = 123
      fonction_titi = tabl(2)
    End Function

  9. #9
    Membre Expert
    Avatar de pijaku
    Homme Profil pro
    Inscrit en
    Août 2010
    Messages
    1 817
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Août 2010
    Messages : 1 817
    Billets dans le blog
    10
    Par défaut
    Bonjour tout le monde,

    Je ne sais pas ce qui m'a pris d'écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Remplit_Grille (Grille)
    J'ai utilisé la même syntaxe que pour l'utilisation de Call (mais sans le Call) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Call Remplit_Grille(Grille)
    En fait, comme le souligne unparia, mon erreur était dans le code d'appel.
    Il est, de ce fait, tout à fait possible de passer un tableau en paramètre d'une Sub ou d'une Function...

    De ce fait, Robert :
    Tu ne peux pas passer un tableau à une fonction mais un variant ou un Object!
    Vue que t dans ta fonction n'est pas typé c'est un variant.
    Et bien si.

    Il suffit de bien l'appeler :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    Public Sub Main()
    Dim Grille(8, 8) As Integer, B As Boolean
     
        'Pour une Sub
        Remplit_Grille Grille()
        ' ou :
        'Call Remplit_Grille(Grille)
        'ou :
        'Remplit_Grille Grille
        'Pour une Function
        B = TousDifferents(Grille())
    End Sub
     
    Private Sub Remplit_Grille(ByRef t() As Integer)
    Dim i As Integer, j As Integer
     
        Randomize Timer
        For i = 0 To 8
            For j = 0 To 8
                t(i, j) = Int(Rnd() * 9) + 1
            Next j
        Next i
    End Sub
     
    Private Function TousDifferents(t() As Integer) As Boolean
    Dim i As Integer, j As Integer
     
        For i = 0 To 7
            For j = i + 1 To 8
                If t(i, 1) = t(j, 1) Then Exit Function
            Next j
        Next i
        TousDifferents = True
    End Function
    Merci à tous, résolu!
    A++

  10. #10
    Inactif  

    Homme Profil pro
    cuisiniste
    Inscrit en
    Avril 2009
    Messages
    15 374
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : cuisiniste
    Secteur : Bâtiment

    Informations forums :
    Inscription : Avril 2009
    Messages : 15 374
    Billets dans le blog
    8
    Par défaut re
    re
    et oui c'est simple

    Sub Machin(truc() As Integer) as integer se sont les contenu et non le variant"truc()"

    donc quand tu injecte un tableau dans une fonction c'est le tableau qui est attendu donc un variant

    exemple

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    sub test 
    dim tableau(2)
    tableau(0)="toto"
    tableau(1)="titi"
    tableau=inverse(tableau)'on injecte le variant(tableau en entier)
    end sub
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    function inverse( t as variant )'t devient le tableau
    temp=t(1)
    t(1)=t(0)
    t(0)=temp
    end function
    maintenant si tu injecte un item et non le tableau en entier

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    msgbox truc(tableau(1)
     
    function truc(t as string)'t devient l'item injecter donc ici en l'occurrence un string attendu 
    truc=t & " et grosminet" 
    end function
    après c'est au dimensionnement que l'on peut se tromper

    dim tableau as variant 'c'est tout ce que tu veut

    dim tableau() as string 'ici c'est un tableau non dimentionné et les éléments attendus sont des string
    etc.....
    mes fichiers dans les contributions:
    mail avec CDO en vba et mail avec CDO en vbs dans un HTA
    survol des bouton dans userform
    prendre un cliché d'un range

    si ton problème est résolu n'oublie pas de pointer : : ça peut servir aux autres
    et n'oublie pas de voter

  11. #11
    Membre Expert
    Avatar de pijaku
    Homme Profil pro
    Inscrit en
    Août 2010
    Messages
    1 817
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Août 2010
    Messages : 1 817
    Billets dans le blog
    10
    Par défaut
    Bonjour,

    Je relance ce sujet, même si résolu.

    Non Patrick, je ne pense pas qu'une variable tableau soit un Variant. C'est simplement une liste de données d'un type donné.
    Comme tu le décris bien dans tes exemples.
    Cependant un tableau typé en String n'est pas un Variant.

    De plus, je relance car je me suis aperçu d'un petit quelque chose qui m'intrigue...
    J'ai voulu vérifier si le fait de ne pas typer le paramètre de la fonction (ou de la Sub) appelée, allait changer le type de ma variable.
    En fait non. Le fait d'écrire ceci, par exemple : T As Variant, ne change pas le type. Il signifie simplement que notre fonction attend n'importe quel type de variable.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Sub Main()
    Dim Tb(8, 8) As Byte
     
    RempliTb Tb()
    End Sub
     
    Sub RempliTb(T As Variant)
    'T As Variant ne change pas le type.
    End Sub
    Encore heureux vous allez me dire.
    Oui.
    Pour info, j'ai testé avec de gros tableaux de données comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    'Code appelant :
    Dim Tb(50000000, 10) As Byte
    '==>  ça passe
     
    Code appelant :
    Dim Tb(50000000, 10) As Variant
    ==> mémoire insuffisante.
     
    Code appelant :
    Dim Tb(50000000, 10) As Byte
    Code appelé :
    Sub Machin(T As Variant)
    ==> ça passe.
    Mais...
    S'il ne change pas le type, il change tout de même quelque chose d'important, le temps d'exécution.
    Faisons ce test sur un tableau de grande taille, pour vérifier...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    Sub test()
    Dim Tb(1000000, 10) As Byte
    Dim temps As Double
     
    temps = Timer
    RempliSansType Tb
    Debug.Print "sans typer le paramètre de la fonction : " & Timer - temps
     
    temps = Timer
    RempliAvecType Tb()
    Debug.Print "En ayant typer le paramètre de la fonction : " & Timer - temps
     
    Debug.Print "...test ultime pour vérifier si la différence de temps est due à une variable tableau déjà remplie..."
     
    temps = Timer
    RempliSansType Tb
    Debug.Print "sans typer le paramètre de la fonction : " & Timer - temps
    End Sub
     
    Sub RempliSansType(T)
    Dim i&, j&
     
    For i = 0 To 1000000
        For j = 0 To 10
            T(i, j) = 1
        Next
    Next
    End Sub
     
    Sub RempliAvecType(T() As Byte)
    Dim i&, j&
     
    For i = 0 To 1000000
        For j = 0 To 10
            T(i, j) = 1
        Next
    Next
    End Sub
    Le résultat est saisissant! Sur ma machine :
    sans typer le paramètre de la fonction : 2,521484375
    En ayant typer le paramètre de la fonction : 0,552734375
    ...test ultime pour vérifier si la différence de temps est due à une variable tableau déjà remplie...
    sans typer le paramètre de la fonction : 2,5
    Remarque : j'obtiens les mêmes temps d'exécution (longs) avec : Sub RempliSansType(T As Variant)

    A quoi est donc due cette différence de temps d'exécution, si le type de variable n'est pas modifié ?

  12. #12
    Expert confirmé

    Homme Profil pro
    Curieux
    Inscrit en
    Juillet 2012
    Messages
    5 161
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Curieux
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2012
    Messages : 5 161
    Billets dans le blog
    5
    Par défaut
    Bonjour,

    avec un Variant, on oblige VBA à "chercher" en fonction du contexte (données et utilisation) le bon type, ou en interrogeant "celui qui sait".
    Or ici, la procédure appelante possède déjà implicitement le type, puisque la déclaration est typée de son côté.

    on a forcément un temps rallongé, mais quand à savoir la nature des traitements ?
    Si on passe la variable ByRef, il semblerait plus cohérent qu'il y ait multiinterrogation, contrairement à un Byval qui va cloner la variable et lui définira son type une seule fois ?

    On pourrait imaginer que la procédure appelée demande à la procédure appelante le Type de la variable (ou qu'il consulte l'espace de référencement des variables courantes), ou la "devine" seule à chaque fois.
    Dans un cas comme dans l'autre, il faut également savoir si la "demande" s'effectue une fois, ou à chaque tour de boucle.

    Pour cette dernière question, on ne peut même pas se baser sur la taille du tableau je pense, car de toute façon on aura une augmentation du temps de traitement proportionnelle à la taille du tableau, qu'il soit passé en Variant ou non.

    Un premier indice serait de comparer s'il y a linéarité de temps d'exécution vis à vis de la taille du tableau.
    Si la linéarité est réelle, alors il y a interrogation à chaque tour de boucle. Sinon, on aura un temps de traitement "fixe" pour gérer l'aspect Variant + une linéarité sur le traitement dans la boucle


    Bref, pleins de suppositions

  13. #13
    Expert confirmé
    Homme Profil pro
    aucune
    Inscrit en
    Avril 2016
    Messages
    7 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 83
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : aucune

    Informations forums :
    Inscription : Avril 2016
    Messages : 7 563
    Par défaut
    Salut Franck
    J'aime les métaphores --->>
    Imaginons que je te tende un sac, t'informe de ce qu'il contient des serpents et te demande de les sortir un par un pour les peser, les mesurer, etc ...
    Crois-tu que tu mettras le même temps à accomplir ces opérations :
    a) si je ne dis pas un mot sur le(s) type(s) de serpents qui s'y trouvent (même si je sais, moi, qu'il n'y a que des couleuvres)
    b) si je t'informe de ce qu'ils sont tous des couleuvres
    sachant qu'il te faudrait prendre des précautions différentes pour chaque type de serpents ?
    (les métaphores ont du bon).

  14. #14
    Membre Expert
    Avatar de pijaku
    Homme Profil pro
    Inscrit en
    Août 2010
    Messages
    1 817
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Août 2010
    Messages : 1 817
    Billets dans le blog
    10
    Par défaut
    Bonjour Messieurs,

    J'ai bien fait de relancer.

    @joe.levrai :
    Un premier indice serait de comparer s'il y a linéarité de temps d'exécution vis à vis de la taille du tableau.
    Si la linéarité est réelle, alors il y a interrogation à chaque tour de boucle.
    C'est ce que mes tests (en augmentant progressivement la taille du tableau) tendent à prouver.
    Pour info, voici mon code de test :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    Sub test()
    Dim Tb() As Byte
    Dim temps As Double, i As Long
     
    For i = 1 To 60 Step 3
        ReDim Tb(0 To 100000, 0 To 10 + i)
        temps = Timer
        RempliSansType Tb, i
        Debug.Print "Nb Valeurs : " & Format(UBound(Tb, 1) * UBound(Tb, 2), "#,##0") & " en : " & Timer - temps
    Next i
    End Sub
     
    Sub RempliSansType(T, k As Long)
    Dim i&, j&
     
    For i = 0 To 100000
        For j = 0 To 10 + k
            T(i, j) = 1
        Next
    Next
    End Sub
    Et son résultat :
    Nb Valeurs : 1 100 000 en : 0,23046875
    Nb Valeurs : 1 400 000 en : 0,28125
    Nb Valeurs : 1 700 000 en : 0,3125
    Nb Valeurs : 2 000 000 en : 0,375
    Nb Valeurs : 2 300 000 en : 0,4375
    Nb Valeurs : 2 600 000 en : 0,46875
    Nb Valeurs : 2 900 000 en : 0,515625
    Nb Valeurs : 3 200 000 en : 0,57421875
    Nb Valeurs : 3 500 000 en : 0,640625
    Nb Valeurs : 3 800 000 en : 0,6875
    Nb Valeurs : 4 100 000 en : 0,734375
    Nb Valeurs : 4 400 000 en : 0,78125
    Nb Valeurs : 4 700 000 en : 0,84375
    Nb Valeurs : 5 000 000 en : 0,90234375
    Nb Valeurs : 5 300 000 en : 0,9375
    Nb Valeurs : 5 600 000 en : 1
    Nb Valeurs : 5 900 000 en : 1,04296875
    Nb Valeurs : 6 200 000 en : 1,109375
    Nb Valeurs : 6 500 000 en : 1,15234375
    Nb Valeurs : 6 800 000 en : 1,21875
    Il y a selon moi, linéarité, donc interrogation à chaque tour de boucle.
    Pour reprendre l'image de unparia, VB se demande à chaque serpent s'il va se faire piquer ou non...

    @unparia :
    Ta métaphore est très parlante.
    Je complète donc mon test en ajoutant simplement, en début de chaque Sub appelée :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     Debug.Print TypeName(T)
    Le résultat est donc, maintenant :
    Byte()
    sans typer le paramètre de la fonction : 1,99609375
    Byte()
    En ayant typer le paramètre de la fonction : 0,390625
    ...test ultime pour vérifier si la différence de temps est due à une variable tableau déjà remplie...
    Byte()
    sans typer le paramètre de la fonction : 1,984375
    Cela sous-entend donc que VB sait dès le début de chaque fonction, le type précis de la variable.
    Il sait donc que le sac ne contient que des couleuvres.
    Alors pourquoi prend t'il le temps, à chaque serpent, d'être précautionneux?

  15. #15
    Expert confirmé
    Homme Profil pro
    aucune
    Inscrit en
    Avril 2016
    Messages
    7 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 83
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : aucune

    Informations forums :
    Inscription : Avril 2016
    Messages : 7 563
    Par défaut
    Non, Franck
    Il ne le "sait" qu'en le "regardant", alors qu'il a déjà mis en oeuvre un mécanisme de traitement de variant (qu'il a déjà ouvert ainsi - en variant - l'espace nécessaire en mémoire).

  16. #16
    Membre Expert
    Avatar de pijaku
    Homme Profil pro
    Inscrit en
    Août 2010
    Messages
    1 817
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Août 2010
    Messages : 1 817
    Billets dans le blog
    10
    Par défaut
    alors qu'il a déjà mis en oeuvre un mécanisme de traitement de variant (qu'il a déjà ouvert ainsi - en variant - l'espace nécessaire en mémoire)
    Non Jacques, je ne le penses pas. Justement, c'est bien là mon problème avec les Variant.
    Regarde les deux tests suivants :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Sub test_1()
    Dim Tb(5000000, 10) As Variant
    'inutile d'en rajouter, il plante dès le début pour mémoire insuffisante (Erreur 7)
    End Sub
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Sub test_1Bis()
    Dim tabl As Variant
     
    ReDim tabl(0 To 5000000, 0 To 10)
    End Sub
    Tous les deux plantent sur une erreur 7 mémoire insuffisante.
    Donc, on a bien tenté d'ouvrir - en variant - l'espace nécessaire en mémoire
    et maintenant, regarde ce 3ème test :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    Sub test()
    Dim Tb(5000000, 10) As Byte
     
        RempliSansType Tb
        Debug.Print Tb(UBound(Tb, 1), UBound(Tb, 2))
    End Sub
     
    Sub RempliSansType(T As Variant)
    Dim i&, j&
     
     'Debug.Print TypeName(T)
    For i = 0 To 5000000
        For j = 0 To 10
            T(i, j) = 1
        Next
    Next
    End Sub
    Il ne plante pas et m'affiche bien le résultat.
    Par conséquent, aucun espace mémoire n'a été affecté à mon variant T...

    C'est un concept difficile à appréhender pour moi. Je ne le cache pas.

    EDIT :
    J'ai même tenté un code test1Ter pour savoir à partir de quel indice mon Variant plantait pour une erreur 7.
    Le résultat est pour i = 6 dans la boucle suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    Sub test_1Ter()
    Dim tabl As Variant, i&
     
    On Error Resume Next
     
        For i = 0 To 10
            ReDim tabl(0 To 5000000, 0 To i)
            If Err <> 0 Then GoTo Fin
        Next
     
    On Error GoTo 0
    Exit Sub
     
    Fin:
    Debug.Print i
    End Sub

  17. #17
    Inactif  

    Homme Profil pro
    cuisiniste
    Inscrit en
    Avril 2009
    Messages
    15 374
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : cuisiniste
    Secteur : Bâtiment

    Informations forums :
    Inscription : Avril 2009
    Messages : 15 374
    Billets dans le blog
    8
    Par défaut re
    re
    oulah!!!
    Non Patrick, je ne pense pas qu'une variable tableau soit un Variant.
    un variant tableau non dimensionné sera toujours un variant sinon je me demande bien comment tu pourrait le dimensionner par la suite hein!!!!!! essaie tu vera bien le message d'erreur il est plus qu'explicit

    alors effectivement comme je l'ai dis plus haut il ne faut pas confondre le tableau et son contenu

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    dim tableau as variant
    tableau=array(1,2,3,4,5,6)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    dim tableau(10) a string 
    tablau(0)="toto"
    tableau(1)="titi"
    tableau(2)="et gros minet alors"
    après selon le type de données dans ton tableau tu a une limite
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Sub test()
    Dim tableau(100000000) As Variant' déclenche une erreur fatale 
    Dim tableau2(100000000) As String' déclenche une erreur fatale et même moins 
    Dim tableau3(1000000000) As Long' déclenche une erreur fatal si moins non 
    Dim tableau4(1000000000) As Byte' déclenché une erreur fatale  si moins non 
    End Sub
    et en plus selon la puissance de la bécane ca peut se déclencher avant
    conclusion ce n'est pas la grandeur du tableau seulement mais le type de donnée a l'intérieur aussi
    un tableau est un variant son contenu peut etre ....... même des bananes
    mes fichiers dans les contributions:
    mail avec CDO en vba et mail avec CDO en vbs dans un HTA
    survol des bouton dans userform
    prendre un cliché d'un range

    si ton problème est résolu n'oublie pas de pointer : : ça peut servir aux autres
    et n'oublie pas de voter

  18. #18
    Membre Expert
    Avatar de pijaku
    Homme Profil pro
    Inscrit en
    Août 2010
    Messages
    1 817
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Août 2010
    Messages : 1 817
    Billets dans le blog
    10
    Par défaut
    Patrick,

    Qu'appelles tu : un variant tableau non dimensionné
    Peux tu, pour ma compréhension, me donner un exemple de déclaration de variant tableau non dimensionné?

    EDIT : pour être plus complet (car je ne pourrais pas vous lire avant lundi matin...),
    est ce que :
    Dim Tb(9) As Byte va "peser" 10 Octets (car 10 Byte) ou 16 car Variant ?

  19. #19
    Expert confirmé
    Homme Profil pro
    aucune
    Inscrit en
    Avril 2016
    Messages
    7 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 83
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : aucune

    Informations forums :
    Inscription : Avril 2016
    Messages : 7 563
    Par défaut
    A Franck
    Une réponse suffisamment précise et/ou complète serait trop longue.
    Le mieux est la lecture de la rubrique Résumé des types de données de l'aide VBA. Tu y trouveras tout.

    EDIT dans ton exemple : 33 octets nécessaires si typé en byte, 45 si typé en variant et contenant des bytes, beaucoup plus encore si typé en variant et contenant des données de type variant (fais donc le calcul )

  20. #20
    Inactif  

    Homme Profil pro
    cuisiniste
    Inscrit en
    Avril 2009
    Messages
    15 374
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : cuisiniste
    Secteur : Bâtiment

    Informations forums :
    Inscription : Avril 2009
    Messages : 15 374
    Billets dans le blog
    8
    Par défaut re
    re
    dans le #post17 il y a 3 code
    le premier est une déclaration de tableau non dimensionné
    dim tableau as variant ' tableau peut etre n'importe quoi et donc si c'est un tableau que l'on veut faire il faut le dimensionner par la suite
    exemple d
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    dim tableau
    tableau=range("A1:B10") 'cela devient un tableau a 2 démentions(lignes/colonne) avec des donnée en variant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    dim tableau
    set tableau=range("A1:B10") 'cela devient une plages donc object et les cellule avec des données en variant car on ne peut pas typé le contenu en late binding si je puis m'exprimer ainsi
    un tableau dimentionné en variant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    dim tableau(20) as variant 
    ' se sont les 20 item qui sont en variant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    dim tableau(50,3)as long 
    c'est un tableau variant  a 2 Dimentions (50 ligne/3colonne) avec des données numériques(long)pareil pour integer mais limité a 255
    etc.....etc......
    mes fichiers dans les contributions:
    mail avec CDO en vba et mail avec CDO en vbs dans un HTA
    survol des bouton dans userform
    prendre un cliché d'un range

    si ton problème est résolu n'oublie pas de pointer : : ça peut servir aux autres
    et n'oublie pas de voter

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Réponses: 15
    Dernier message: 06/02/2012, 00h45
  2. Réponses: 3
    Dernier message: 05/05/2011, 18h47
  3. Réponses: 2
    Dernier message: 22/12/2009, 16h01
  4. Réponses: 5
    Dernier message: 02/05/2009, 15h23
  5. Passage d'un tableau javascript en paramètres d'une URL
    Par seblo_scoqi dans le forum Général JavaScript
    Réponses: 13
    Dernier message: 02/09/2005, 11h46

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo