XL pour MAC Durée : Dépassement de capacité.

Boostez vos compétences Excel avec notre communauté !

Rejoignez Excel Downloads, le rendez-vous des passionnés où l'entraide fait la force. Apprenez, échangez, progressez – et tout ça gratuitement ! 👉 Inscrivez-vous maintenant !

dionys0s

XLDnaute Impliqué
Bonjour le forum,

je ne comprends rien : j'ai développé une petite fonction qui renvoie une valeur texte d'un nombre de secondes.
1 => 1 seconde
1.01 => 1 seconde 1 centième
3602.12 => 1 heure 2 secondes 12 centièmes.

Je ne comprends pas pourquoi au delà d'une certaine valeur (248 jours 13 heures 13 minutes 56 secondes 47 centièmes, soit 2 147 483 647 centièmes de secondes.), j'ai un dépassements de capacité. J'ai l'impression d'avoir déclaré mes variables correctement pourtant.

Ci-dessous le code de mes procédures, et joint le classeur qui contient la fonction. En l'état, ça fonctionne, mais en rajoutant 1 centième à la durée (56.47 => 56.48), ça plante chez moi.

C'est pareil chez vous ? Si oui, une idée du pourquoi du comment ?
D'avance merci pour votre aide 🙂

VB:
Option Explicit

Public Enum eSingPlur: eSing: ePlur: End Enum

Public Sub Test1()

  Dim Dur As Double

  Const SecPerCnt As Double = 0.01
  Const SecPerSec As Double = 1
  Const SecPerMin As Double = 60
  Const SecPerHour As Double = 60 * SecPerMin
  Const SecPerDay As Double = 24 * SecPerHour

  Dur = _
  Cells(2, 2).Value * SecPerDay + _
  Cells(2, 3).Value * SecPerHour + _
  Cells(2, 4).Value * SecPerMin + _
  Cells(2, 5).Value * SecPerSec + _
  Cells(2, 6).Value * SecPerCnt

  MsgBox Duration(Dur)

End Sub

Public Sub Test2()

  Dim Dur As Double

  Const SecPerCnt As Double = 0.01
  Const SecPerSec As Double = 1
  Const SecPerMin As Double = 60
  Const SecPerHour As Double = 60 * SecPerMin
  Const SecPerDay As Double = 24 * SecPerHour

  Dur = _
  Cells(3, 2).Value * SecPerDay + _
  Cells(3, 3).Value * SecPerHour + _
  Cells(3, 4).Value * SecPerMin + _
  Cells(3, 5).Value * SecPerSec + _
  Cells(3, 6).Value * SecPerCnt

  MsgBox Duration(Dur)

End Sub

Public Function Duration(Seconds As Double) As String

  Dim Unts() As Variant, Lvls() As Double, Elt As Variant
  Dim Div As Double, Arr() As Double, k As Long

  Unts = VBA.Array( _
  VBA.Array("centième", "centièmes"), _
  VBA.Array("seconde", "secondes"), _
  VBA.Array("minute", "minutes"), _
  VBA.Array("heure", "heures"), _
  VBA.Array("jour", "jours"), _
  VBA.Array("année", "années"))

  ReDim Lvls(LBound(Unts) To UBound(Unts) - 1): k = LBound(Lvls): For Each Elt In VBA.Array(100, 60, 60, 24, 365)
  Lvls(k) = Elt: k = k + 1: Next Elt: Seconds = 100 * Seconds: Div = 1

  ReDim Arr(LBound(Unts) To UBound(Unts)): k = LBound(Arr) - 1: Do: k = k + 1
  If k > LBound(Lvls) Then Div = Div * Lvls(k - 1)
  If Div > Seconds Then Exit Do
  If k < UBound(Lvls) Then Arr(k) = Seconds \ Div Mod Lvls(k) Else Arr(k) = Seconds \ Div
  Loop Until k = UBound(Unts)

  k = k + 1: Do: k = k - 1
  If Arr(k) > 0 Then
  Duration = Duration & " " & Arr(k) & " " & SingPlur(Arr(k), Unts(k)(eSingPlur.eSing) & "", Unts(k)(eSingPlur.ePlur) & "")
  ElseIf k = LBound(Arr) And Duration = "" Then
  Duration = "<1 " & SingPlur(Arr(k), Unts(eSingPlur.eSing, k) & "", Unts(eSingPlur.ePlur, k) & "")
  End If: Loop Until k = LBound(Unts): Duration = VBA.Trim(Duration) & "."

End Function

Public Function SingPlur(Value As Variant, Sing As String, Plur As String) As String
  If VBA.Abs(Value) >= 2 Then SingPlur = Plur Else SingPlur = Sing
End Function
 

Pièces jointes

Dernière édition:
Re,
Bonjour P.

J'aurais dû être plus précis. Tel que le classeur exemple était initialement, il était normal qu'il fonctionne. Il fallait modifier le code.
J'ai modifié la pièce jointe : la macro Test1 fonctionne, mais pas la Test2.

À vous lire,

dionys0s
 
Re,
Bonjour tout le monde,

j'avance un peu dans mon "investigation"... Je viens de voir que ce sont les opérateurs Mod et "\" (division entière) qui font planter.
Reste à savoir pourquoi et comment contourner ça. Je continue de creuser mais si quelqu'un a déjà un début de solution je suis preneur 🙂
 
Bonjour.
Faite des divisions normales pour éviter la conversion en Long des opérandes en amont de la division.
Quotient = Int(Ddende / Diviseur): Reste = Ddende - Quotient * Diviseur
Peut être pourrez vous adapter cette fonction :
VB:
Function DuréeEnClair(ByVal D As Double) As String
Dim Z As String, M As Double, U As String, N As Long, NDét As Long
Z = ""
M = 365.2425:  U = "an":   GoSub 2
M = 30.436875: U = "mois": GoSub 2
M = 7:         U = "sem":  GoSub 2
M = 1:         U = "j.":   GoSub 2
M = 1 / 24:    U = "h.":   GoSub 2
M = 1 / 1440:  U = "min":  GoSub 2
1 DuréeEnClair = Mid$(Z, 2)
Exit Function
2 N = Int(D / M)
If N > 0 Then
   If N > 1 Then If U = "an" Then U = "ans"
   Z = Z & " " & N & " " & U
   D = D - M * N
   End If
If Len(Z) > 0 Then NDét = NDét + 1: If NDét >= 2 Then GoTo 1
Return
End Function
 
Dernière édition:
Bonjour dionys0s, gosselien, Dranreb,

Dans la première ligne du classeur on obtient un nombre de secondes : 2147483647, dans la deuxième :2147483648.

2147483647 est la limite d'un Long, est ce dû à ça ?

Si dans une sub on essaie d'écrire 2147483648 on obtient 2147483648#

La division entière pose alors souci : 2147483648 \ 1 ==> dépassement de capacité

peut-être contourner la division entière en utilisant la fonction Int().

Code:
Dim Seconds As Double
Seconds = 2147483648#
Seconds = 2147483647
Seconds = Seconds + 1

MsgBox Seconds
MsgBox Int(Seconds / 1) 'ok
MsgBox Seconds \ 1 ' dépassement capacité

A+
 
- Navigue sans publicité
- Accède à Cléa, notre assistante IA experte Excel... et pas que...
- Profite de fonctionnalités exclusives
Ton soutien permet à Excel Downloads de rester 100% gratuit et de continuer à rassembler les passionnés d'Excel.
Je deviens Supporter XLD

Discussions similaires

  • Question Question
XL 2021 VBA excel
Réponses
4
Affichages
79
Réponses
3
Affichages
599
Réponses
2
Affichages
405
Réponses
23
Affichages
2 K
Réponses
33
Affichages
3 K
Réponses
6
Affichages
671
Retour