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:
=DATE(2013,10,28)
=A1*1
qui devrait être égale à un nombre (41575)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:
Format
et CDate
modifient-ils mes cellules en chaînes?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
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
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
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
).