web-dev-qa-db-fra.com

Formats de date Excel VBA

J'ai un tableur qui contient un certain nombre de dates. Ceux-ci apparaissent généralement dans mm/dd/yyyy ou mm/dd/yyyy hh:mm.

Le problème est que les dates ne sont pas toujours insérées correctement et je veux avoir des contrôles pour m'assurer qu'elles sont bien dans le code.

Ma pensée initiale était d’utiliser IsDate pour vérifier ou CDate mais cela ne semblait pas fonctionner: il retournait toujours des chaînes au lieu de dates.

Depuis, j’ai organisé une petite expérience qui montre que ces fonctions ne fonctionnent pas comme je l’attendais. La méthodologie est:

  1. Dans une cellule A1, j'entre la formule =DATE(2013,10,28)
  2. Cellule B1 Formule =A1*1 qui devrait être égale à un nombre (41575)
  3. Exécuter ce petit script

    Sub test()
    
    MsgBox ("Start:" & TypeName(ActiveCell.Value) & " " & IsDate(ActiveCell.Value))
    
    ActiveCell.Value = Format(ActiveCell.Value, "mm/dd/yyyy")
    MsgBox ("After format: " & TypeName(ActiveCell.Value) & " " & IsDate(ActiveCell.Value))
    
    ActiveCell.Value = CDate(ActiveCell.Value)
    MsgBox ("After Cdate: " & TypeName(ActiveCell.Value) & " " & IsDate(ActiveCell.Value))
    
    End Sub
    

Lorsque le script démarre, la cellule est de type date et IsDate renvoie true. Une fois qu'il a été exécuté via Format, il est de type chaîne mais IsDate renvoie toujours la valeur true. CDate convertira également la cellule en chaîne. La cellule B1 renvoie également 0 (puisqu'il s'agit d'une chaîne * 1).

Donc, je suppose que pour résumer les questions:

  1. Pourquoi Format et CDate modifient-ils mes cellules en chaînes?
  2. Comment puis-je m'assurer qu'une cellule retournera une valeur de date et pas seulement une chaîne qui ressemble à une date?
12
gtwebb

Il est important de faire la distinction entre le contenu des cellules, leur format d'affichage, le type de données lu à partir de cellules par VBA et le type de données écrit écrit dans les cellules de VBA - et comment Excel l'interprète automatiquement. (Voir par exemple cette réponse précédente .) La relation entre ceux-ci peut être un peu compliquée, car Excel fera des choses comme interpréter les valeurs d'un type (par exemple, chaîne) comme étant un certain autre type de données (par exemple, date), puis changer automatiquement le format d'affichage en fonction de cela. Votre pari le plus sûr est de tout faire explicitement et de ne pas compter sur ce système automatique. 

J'ai couru ton expérience et je n'obtiens pas les mêmes résultats que toi. Ma cellule A1 reste une date tout le temps et B1 41575. Je ne peux donc pas répondre à votre question n ° 1. Les résultats dépendent probablement de la manière dont votre version/vos paramètres Excel choisissent de détecter/modifier automatiquement le format numérique d'une cellule en fonction de son contenu. 

Question n ° 2, "Comment puis-je m'assurer qu'une cellule retournera une valeur de date": eh bien, je ne sais pas ce que vous entendez par "renvoyer" une valeur de date, mais si vous souhaitez qu'elle contienne une valeur numérique qui est affiché en tant que date, en fonction de ce que vous écrivez à partir de VBA, vous pouvez alors:

  • Ecrivez dans la cellule une valeur de chaîne que vous espérez qu'Excel interprétera automatiquement comme une date et un format. Croiser les doigts. Évidemment ce n'est pas très robuste. Ou, 

  • Ecrivez une valeur numérique dans la cellule à partir de VBA (il est évident que le type Date est le type souhaité, mais un entier, long, simple ou double peut également servir) et définissez explicitement le format numérique des cellules sur le format de date souhaité à l'aide du .NumberFormat. propriété (ou manuellement dans Excel). C'est beaucoup plus robuste. 

Si vous souhaitez vérifier que le contenu de la cellule existante peut être affiché sous forme de date, voici une fonction qui vous aidera:

Function CellContentCanBeInterpretedAsADate(cell As Range) As Boolean
    Dim d As Date
    On Error Resume Next
    d = CDate(cell.Value)
    If Err.Number <> 0 Then
        CellContentCanBeInterpretedAsADate = False
    Else
        CellContentCanBeInterpretedAsADate = True
    End If
    On Error GoTo 0
End Function

Exemple d'utilisation:

Dim cell As Range
Set cell = Range("A1")

If CellContentCanBeInterpretedAsADate(cell) Then
    cell.NumberFormat = "mm/dd/yyyy hh:mm"
Else
    cell.NumberFormat = "General"
End If
16

Format convertit les valeurs en chaînes. IsDate retourne toujours true car il peut analyser cette chaîne et obtenir une date valide.

Si vous ne souhaitez pas modifier les cellules en chaîne, n'utilisez pas Format. (IOW, ne les convertissez pas en chaînes en premier lieu.) Utilisez le Cell.NumberFormat et réglez-le au format de date que vous souhaitez afficher.

ActiveCell.NumberFormat = "mm/dd/yy"   ' Outputs 10/28/13
ActiveCell.NumberFormat = "dd/mm/yyyy" ' Outputs 28/10/2013
2
Ken White

Merci pour la contribution. De toute évidence, je vois des problèmes qui ne sont pas reproduits sur d’autres machines. Sur la base de la réponse de Jean, j'ai proposé une solution moins élégante qui semble fonctionner.

Étant donné que si je transmets à une cellule une valeur directement à partir de cdate, ou la formate simplement en tant que nombre, elle conserve la valeur de cellule sous forme de chaîne. 

Function CellContentCanBeInterpretedAsADate(cell As Range) As Boolean
    Dim d As Date
    On Error Resume Next
    d = CDate(cell.Value)
    If Err.Number <> 0 Then
        CellContentCanBeInterpretedAsADate = False
    Else
        CellContentCanBeInterpretedAsADate = True
    End If
    On Error GoTo 0
End Function

Exemple d'utilisation:

Dim cell As Range
dim cvalue as double
Set cell = Range("A1")

If CellContentCanBeInterpretedAsADate(cell) Then
    cvalue = cdate(cell.value)
    cell.value = cvalue
    cell.NumberFormat = "mm/dd/yyyy hh:mm"
Else
    cell.NumberFormat = "General"
End If
1
gtwebb

Utilisez value(cellref) sur le côté pour évaluer les cellules. Les chaînes produisent l'erreur "#Value", mais les dates se résolvent en nombre (par exemple, 43173).

0
Craig