Autres Pourquoi le format Date semble être différent malgré même formule ? (excel / VBA)

Scoub

XLDnaute Nouveau
Bonjour,

Pourriez-vous m'éclairer svp ? j'en perds mon latin... si je le connaissais. ;)

J'ai l'impression d'inscrire les mêmes lignes et pourtant le résultat n'est pas tout à fait identique (visualisation durant débog pas à pas)

J'essaie tant bien que mal de réaliser un programme pour filtrer dans une base de données et dans un segment TCD excel une période entre 2 dates (liste dates du fichier évolutif et non consécutif) (et appliquer par la suite la même sélection sur d'autres onglets données et TCD).

J'ai un soucis avec les formats des dates et la valeur de case vide ou "" dans la liste surtout dans le segment.


VB:
    choixDateMIN = Worksheets("Selections").Range("I10").Value
    choixDateMAX = Worksheets("Selections").Range("K10").Value
    NUMDateMIN = Format(CDate(choixDateMIN), "0000") 'transforme date en valeur numérique Windows / CDate(choixDateMIN) 'transforme uniquement les valeurs et texte en date
    NUMDateMAX = Format(CDate(choixDateMAX), "0000")
    DateMIN = Format(NUMDateMIN, "mm/dd/yyyy") 'transforme en format date americain / CDate(choixDateMIN) 'transforme uniquement les valeurs et texte en date
    DateMAX = Format(NUMDateMAX, "mm/dd/yyyy")

par exemple
en I10 = 01/06/2021
en K10 = 30/08/2021

choixDateMIN donne 01/06/2021
choixDateMAX donne 30/08/2021
CDate(choixDateMIN) donne 01/06/2021
CDate(choixDateMAX) donne 30/08/2021
NUMDateMIN donne "44348"
NUMDateMAX donne 44438
DateMIN donne "01/06/2021"
DateMAX donne 30/08/2021

Pourquoi certains résultats sont en "guillemet" ? importance pour la suite du programme pour filtrer ?

Comment gérer les cases vide ou "" du segment pour réaliser le filtre svp ?

L'objectif est de réaliser le filtre suivant le choix de l'utilisateur soit date mini soit date max soit entre date mini et max...
J'avais réussi pour la date mini mais aussitôt que je tente d'intégrer une autre partie du programme, cela plante.

Merci d'avance pour vos lumières,
Cordialement,
Scoub

pour info voici le code en cours....

Code:
With ActiveSheet
   
    'filtre pour les segments TCD
   
        With ActiveWorkbook.SlicerCaches("Segment_ORDER_DATE2")
           
                For I = 1 To .SlicerItems.Count
                    'valeur = Format(.SlicerItems(I).Caption, "0000") - Format(choixDateMIN, "0000")
                    If Format(.SlicerItems(I).Caption, "0000") >= NUMDateMIN Then
                        If Format(.SlicerItems(I - 1).Caption, "0000") < NUMDateMIN Then
                        PosDateMIN = I
                        Else
                        End If
                    Else
                        If Format(.SlicerItems(I).Caption, "0000") < NUMDateMAX Then
                         'rien
                        Else
'                            If Format(.SlicerItems(I - 1).Caption, "0000") <= NUMDateMAX Then
                           
                            PosDateMAX = I - 1
'                            Else
                           
                           
                           
'                            End If
                        End If
                    '.SlicerItems(I).Selected = True
                    End If
                Next I
               
                'PosDateMAX = 12
               
               
                For c = 1 To .SlicerItems.Count
                    If c >= PosDateMIN And c <= PosDateMAX Then
                        .SlicerItems(c).Selected = True
                    Else
                       
                        .SlicerItems(c).Selected = False
                    End If
                Next c
         
           
        End With
    End With
 
Dernière édition:
Solution
Re,

Traitez une seule chose à la fois. Résolvez un problème à la fois.
Commencez par apprendre les bases :
Code:
Dim choixDateMIN, choixDateMAX, NUMDateMIN, NUMDateMAX As Long

Ne suffit pas à ce que toutes les variables de la ligne soient des Long, seule la dernière (NUMDateMAX ) sera un Long :)

J'ai un sérieux doute quant à l' efficience de la ligne ci-dessous :
VB:
If Format(.SlicerItems(I).Caption, "0000") >= NUMDateMIN Then

Hasco

XLDnaute Barbatruc
Repose en paix
Bonjour,

Vos résultats sont entre guillemets parce que vous faites appel à la fonction Format qui retourne un texte (string) pas un nombre.

Format(CDate(choixDateMIN), "0000") 'transforme date en valeur numérique Windows

Le texte en gras est faut.

Pour avoir la valeur numérique d'une date (une date pas un texte représentant une date) contenue dans une cellule faites appel à la propriété .Value2 de l'objet range qui fait abstraction de tout formatage de la cellule et contient toujours la valeur originale et numérique de la date en type double.


Si vous avez une date en Worksheets("Selections").Range("I10") :

Déclarez vos variables au type attendu

Dim choixDateMin As Date
Dim NUMDateMIN As Double

' Donnera une valeur de type Date
choixDateMin = Worksheets("Selections").Range("I10").Value

'Donnera une valeur de type double
NUMDateMin = Worksheets("Selections").Range("I10").Value

Pour la deuxième, préférez .Value2 même si .Value fonctionne sur une variable déclarée en double

Cordialement
 

Scoub

XLDnaute Nouveau
Bonjour,

Vos résultats sont entre guillemets parce que vous faites appel à la fonction Format qui retourne un texte (string) pas un nombre.

Format(CDate(choixDateMIN), "0000") 'transforme date en valeur numérique Windows

Le texte en gras est faut.

Pour avoir la valeur numérique d'une date (une date pas un texte représentant une date) contenue dans une cellule faites appel à la propriété .Value2 de l'objet range qui fait abstraction de tout formatage de la cellule et contient toujours la valeur originale et numérique de la date en type double.


Si vous avez une date en Worksheets("Selections").Range("I10") :

Déclarez vos variables au type attendu

Dim choixDateMin As Date
Dim NUMDateMIN As Double

' Donnera une valeur de type Date
choixDateMin = Worksheets("Selections").Range("I10").Value

'Donnera une valeur de type double
NUMDateMin = Worksheets("Selections").Range("I10").Value

Pour la deuxième, préférez .Value2 même si .Value fonctionne sur une variable déclarée en double

Cordialement

Merci Hasco pour ces précieuses informations.
Je vais découvrir la ".Value2" et une variable type "double"
Je vais tester pour voir si j'ai bien compris.

Par contre, vu mes formules pourquoi pour mes variables MIN le résultat donne le format texte entre "" et pour mes variables MAX cela semble donner des valeurs sans "" ?

NUMDateMIN donne "44348"
VB:
NUMDateMIN = Format(CDate(choixDateMIN), "0000")
NUMDateMAX donne 44438
Code:
NUMDateMAX = Format(CDate(choixDateMAX), "0000")
DateMIN donne "01/06/2021"
Code:
 DateMIN = Format(NUMDateMIN, "mm/dd/yyyy")
DateMAX donne 30/08/2021
Code:
DateMAX = Format(NUMDateMAX, "mm/dd/yyyy")

je ne comprends pas du tout pourquoi cela change le format entre les 2...

Auriez-vous une piste ?

Merci d'avance,
Cordialement,
Scoub
 
Dernière édition:

Hasco

XLDnaute Barbatruc
Repose en paix
Re,

Difficile d'être certain sur un bout isolé de code et sans le classeur mais sans doute n'avez vous pas déclaré vos variables ou alors sans leur type attendu, ce qui leur permettrait de contenir à peu près tout et n'importe quoi.

Avec des variables non déclarée et ou sans type VBA va tenter au petit bonheur la chance de faire des conversions implicite et s'arrêtera sur la première qui fonctionne.

Avec des variables déclarées vba va tenter une conversion au type attendu et vous alertera (bug) s'il y a conflit de typage, une variable Double à laquelle on affecte une valeur de type String.

Ceci étant faux :
Format(CDate(choixDateMIN), "0000") 'transforme date en valeur numérique Windows

Vous aurez d'autres erreurs ailleurs... Ne les évitez pas par des On Error Resume Next, car ce sont elles qui vous apprendront.
La gestion des erreurs vient en dernier, lorsqu'on a éliminer toutes les possibilités envisageables d'erreur.
Il faut que les erreurs soient des exceptions ou qu'elles servent un but attendu.

En Bref DECLAREZ VOS VARIABLES AU TYPES ATTENDU et vous avancerez dans la compréhension de ce que vous faites.

Cordialement
 

Scoub

XLDnaute Nouveau
Re,

Difficile d'être certain sur un bout isolé de code et sans le classeur mais sans doute n'avez vous pas déclaré vos variables ou alors sans leur type attendu, ce qui leur permettrait de contenir à peu près tout et n'importe quoi.

Avec des variables non déclarée et ou sans type VBA va tenter au petit bonheur la chance de faire des conversions implicite et s'arrêtera sur la première qui fonctionne.

Avec des variables déclarées vba va tenter une conversion au type attendu et vous alertera (bug) s'il y a conflit de typage, une variable Double à laquelle on affecte une valeur de type String.

Ceci étant faux :
Format(CDate(choixDateMIN), "0000") 'transforme date en valeur numérique Windows

Vous aurez d'autres erreurs ailleurs... Ne les évitez pas par des On Error Resume Next, car ce sont elles qui vous apprendront.
La gestion des erreurs vient en dernier, lorsqu'on a éliminer toutes les possibilités envisageables d'erreur.
Il faut que les erreurs soient des exceptions ou qu'elles servent un but attendu.

En Bref DECLAREZ VOS VARIABLES AU TYPES ATTENDU et vous avancerez dans la compréhension de ce que vous faites.

Cordialement
J'ai peut-être été vague sur la déclaration des variables...

VB:
Dim choixDateMIN, choixDateMAX, NUMDateMIN, NUMDateMAX As Long

Dim DateMIN, DateMAX As Date

En même temps, basiquement pour éviter des soucis de format (et mon soucis de traitement)...
j'ai utiliser la 1ère cellule et copier/coller avec le format dans excel puis recopier les mêmes lignes dans vba après avoir réalisé un test avec les variables MIN pour être sûr de faire les mêmes démarches...
mais a priori, j'ai loupé qqchose ou vba prend en compte un autre élément.
choix date.png



En effet, il s'agit d'un apprentissage très intéressant.
Actuellement, j'ai beaucoup de mal avec la gestion des dates.
L'objectif est de profiter de cette occasion pour comprendre et annoter correctement afin de progresser ;)

Et en effet, j'ai d'autres erreurs :

- dans mon filtre dans l'onglet base de donnée : les dates sont inscrites dans filtres personnalisés mais aucune ligne ne ressort. Sauf quand j'appuie manuellement sur "ok" lors de la consultation du filtre personnalisé (et tout fonctionne)
filtrepersodate.png

Dans l'exemple j'avais tenté de rajouter 30j à la date de fin dans le programme vba (à la place de les déduire)


Code:
Sheets("Affectation Vision Cde Client").Activate 
         Selection.AutoFilter _
         Field:=22, Criteria1:=">=" & DateMIN, _
         Operator:=xlAnd, Criteria2:="<=" & DateMAX

- dans le segment du TCD, la date max n'est pas reconnue pour identifier quelles valeurs supérieures exclurent...
segmentdate.png

Code:
With ActiveSheet
 
    'filtre pour les segments TCD
 
        With ActiveWorkbook.SlicerCaches("Segment_ORDER_DATE2")
         
                For I = 1 To .SlicerItems.Count
                    'valeur = Format(.SlicerItems(I).Caption, "0000") - Format(choixDateMIN, "0000")
                    If Format(.SlicerItems(I).Caption, "0000") >= NUMDateMIN Then
                        If Format(.SlicerItems(I - 1).Caption, "0000") < NUMDateMIN Then
                        PosDateMIN = I
                        Else
                        End If
                    Else
                        If Format(.SlicerItems(I).Caption, "0000") < NUMDateMAX Then
                         'rien
                        Else
'                            If Format(.SlicerItems(I - 1).Caption, "0000") <= NUMDateMAX Then
                         
                            PosDateMAX = I - 1
'                            Else
                         
                         
                         
'                            End If
                        End If
                    '.SlicerItems(I).Selected = True
                    End If
                Next I
             
                'PosDateMAX = 12
             
             
                For c = 1 To .SlicerItems.Count
                    If c >= PosDateMIN And c <= PosDateMAX Then
                        .SlicerItems(c).Selected = True
                    Else
                     
                        .SlicerItems(c).Selected = False
                    End If
                Next c
       
         
        End With
    End With

surement tout est lié à ce format "date" à bien paramétrer 🤔

Avec ces informations, je vais creuser de nouveau le sujet... cela fait plusieurs jours que j'essaie d'appréhender le traitement des dates en vba (toujours sur le même fichier)...

Un jour cela va fonctionner... en espérant que cela sera aujourd'hui ;)

encore merci
 

Hasco

XLDnaute Barbatruc
Repose en paix
Re,

Traitez une seule chose à la fois. Résolvez un problème à la fois.
Commencez par apprendre les bases :
Code:
Dim choixDateMIN, choixDateMAX, NUMDateMIN, NUMDateMAX As Long

Ne suffit pas à ce que toutes les variables de la ligne soient des Long, seule la dernière (NUMDateMAX ) sera un Long :)

J'ai un sérieux doute quant à l' efficience de la ligne ci-dessous :
VB:
If Format(.SlicerItems(I).Caption, "0000") >= NUMDateMIN Then
 

Scoub

XLDnaute Nouveau
Re,

Traitez une seule chose à la fois. Résolvez un problème à la fois.
Commencez par apprendre les bases :
Code:
Dim choixDateMIN, choixDateMAX, NUMDateMIN, NUMDateMAX As Long

Ne suffit pas à ce que toutes les variables de la ligne soient des Long, seule la dernière (NUMDateMAX ) sera un Long :)

J'ai un sérieux doute quant à l' efficience de la ligne ci-dessous :
VB:
If Format(.SlicerItems(I).Caption, "0000") >= NUMDateMIN Then
Bonjour Hasco,

En effet, en corrigeant la déclaration des variables, toutes les valeurs étaient du même style.
La suite du code a du être changé.
VB:
[CODE=vb]If Format(.SlicerItems(I).Caption, "0000") >= NUMDateMIN Then
[/CODE] ne fonctionnant plus.

Maintenant cela semble fonctionner...
Par contre j'ai des gros doutes concernant la simplicité et l'efficacité de ma tentative...
il y a surement une manière plus rapide et simple de codifier ce passage.

L'objectif est de pouvoir filtre les dates sur un onglet de base de donnée et sur un autre onglet dans le segment de TCD
  • soit uniquement date début/min
  • soit uniquement date fin/max
  • soit période entre date min et date de fin

Code:
Sub FiltreDate() ' pour affecter filtre date sur les onglets base de données et sur segment dans TCD

Dim choixDateMIN2 As Double, choixDateMAX2 As Double

Dim NUMDateMIN As Long, NUMDateMAX As Long

Dim choixDateMIN As Date, choixDateMAX As Date

Dim DateMIN As String, DateMAX As String

Dim I As Long, c As Long, PosDateMIN As Long, PosDateMAX As Long

Application.ScreenUpdating = False

Sheets("Selections").Activate

If Worksheets("Selections").Range("K8").Value = "Ne pas utiliser" Then
    NUMDateMIN = 0
    NUMDateMAX = 0
    Else
    If Worksheets("Selections").Range("M11").Value = "" Then
        choixDateMIN = 0
        choixDateMIN2 = 0
        Else
        choixDateMIN = Worksheets("Selections").Range("M11").Value
        choixDateMIN2 = Worksheets("Selections").Range("M11").Value2 '".value2" récupére la valeur cellule sans format (date ou currency...) soit obtient valeur numérique Windows pour une date
    End If
    If Worksheets("Selections").Range("N11").Value = "" Then
        choixDateMAX = 0
        choixDateMAX2 = 0
        Else
        choixDateMAX = Worksheets("Selections").Range("N11").Value '- Worksheets("Selections").Range("J12")
        choixDateMAX2 = Worksheets("Selections").Range("N11").Value2 '- Worksheets("Selections").Range("J12")
    End If
   
    NUMDateMIN = Format(CDate(choixDateMIN), "0000") 'fonction format transforme en texte chiffre / CDate(choixDateMIN) 'transforme uniquement les valeurs et texte en date
    NUMDateMAX = Format(CDate(choixDateMAX), "0000")
    DateMIN = Format(NUMDateMIN, "mm/dd/yyyy") 'transforme en format date americain / CDate(choixDateMIN) 'transforme uniquement les valeurs et texte en date
    DateMAX = Format(NUMDateMAX, "mm/dd/yyyy")
 
End If

'etape filtre Order_Date

   
   If NUMDateMIN = 0 And NUMDateMAX = 0 Then ' vérifie si une sélection est faite pour ce critère et opère si absent
   
    'filtre pour les bases de données
   
   
    Sheets("Affectation Vision Cde Client").Activate 'vérifier la colonne
    Selection.AutoFilter _
    Field:=22
    Range("A2").Select
   
    'filtre pour TCDles segments TCD
   

   
    Sheets("TCD Vision client").Activate
    With ActiveSheet
        'vérifier nom du segment
        ActiveWorkbook.SlicerCaches("Segment_ORDER_DATE2").ClearManualFilter 'fonctionne pour enlever toutes les sélections dans segment
   
   
    End With

 
  Else 'si choix inscrit réalise le filtre
   
        ' format date US pour les filtres mais ne coche pas les différentes dates dans le filtre même si indiqué dans filtre personnalisé
        If choixDateMIN2 <> 0 And choixDateMAX2 = 0 Then
            Sheets("Affectation Vision Cde Client").Activate
            Selection.AutoFilter _
            Field:=22, Criteria1:=">=" & DateMIN, _
            Operator:=xlAnd ', Criteria2:="<=" & DateMAX
            Else
            If choixDateMAX2 <> 0 And choixDateMIN2 = 0 Then
                Sheets("Affectation Vision Cde Client").Activate
                Selection.AutoFilter _
                Field:=22, Criteria1:="<=" & DateMAX, _
                Operator:=xlAnd ', Criteria2:="<=" & DateMAX
               
                Else
                Sheets("Affectation Vision Cde Client").Activate
                Selection.AutoFilter _
                Field:=22, Criteria1:=">=" & DateMIN, _
                Operator:=xlAnd, Criteria2:="<=" & DateMAX
            End If
        End If
       
         Range("A2").Select
 
   'etape filtre pour TCD
 
    Sheets("TCD Vision client").Activate
    With ActiveSheet
   
    'filtre pour les segments TCD
   
        With ActiveWorkbook.SlicerCaches("Segment_ORDER_DATE2")
           
                For I = 1 To .SlicerItems.Count - 1
                    If .SlicerItems(I).Caption = "" Or IsEmpty(.SlicerItems(I).Caption) Then
                    Else
                       
                        If DateValue(.SlicerItems(I).Caption) < choixDateMAX2 Or choixDateMAX2 = 0 Then
                            PosDateMAX = .SlicerItems.Count
                            If choixDateMIN2 = 0 Then
                                PosDateMIN = 0
                                Else
                                If DateValue(.SlicerItems(I).Caption) >= choixDateMIN2 Then
                                    If DateValue(.SlicerItems(I - 1).Caption) < choixDateMIN2 Or .SlicerItems(I - 1).Caption = "" Or IsEmpty(.SlicerItems(I - 1).Caption) Then
                                       
                                        PosDateMIN = I
                                                                             
                                        Else
                                    End If
                                    Else
                                End If
                            End If
                               
                        Else
                            If DateValue(.SlicerItems(I - 1).Caption) <= choixDateMAX2 Or .SlicerItems(I - 1).Caption = "" Or IsEmpty(.SlicerItems(I - 1).Caption) Then
                           
                                PosDateMAX = I - 1

                                Else
                                                                                 
                            End If

                        End If
                    End If
                Next I
    End With
   
   
 
  End If
 
Application.ScreenUpdating = True

End Sub

Je suis preneur de pistes d'optimisation de cette programmation.

Merci d'avance pour mon apprentissage du VBA ;)

Cordialement,
Scoub
 
Dernière édition:

dysorthographie

XLDnaute Accro
Bonsoir,
Il faut bien comprendre qu'Excel utilise les paramètres régionaux et VBA le format US en concequnce les dates inférieur au 13 du mois peuvent être inversées! Le 12/12 ne posant pas de risques d'inversion le 4 janvier devient un poisson d'avril !

Il faut toujours formater ses date au format international yyyy-mm-dd
Code:
DateMIN = Format(choixDateMIN, "yyyy-mm-dd")
DateMAX= Format(choixDateMAX "yyyy-mm-dd")
 
Dernière édition:

Scoub

XLDnaute Nouveau
Bonsoir,
Il faut bien comprendre qu'Excel utilise les paramètres régionaux et VBA le format US en concequnce les dates inférieur au 13 du mois peuvent être inversées! Le 12/12 ne posant pas de risques d'inversion le 4 janvier devient un poisson d'avril !

Il faut toujours formater ses date au format international yyyy-mm-dd
Code:
DateMIN = Format(choixDateMIN, "yyyy-mm-dd")
DateMAX= Format(choixDateMAX "yyyy-mm-dd")
Bonjour Dysorthographie,

Merci pour l'information je vais vérifier ce point.

Cordialement,
Scoub