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 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
| Option Explicit
Function Fact(Nombre) As Single
Dim Boucle As Integer
Fact = 1
If Int(Nombre) >= 2 Then
For Boucle = 2 To Int(Nombre)
Fact = Fact * Boucle
Next Boucle
End If
End Function
Function CompteDoublons(Uplet, Col) As Single ' Comptage du nombre de répetitions NbR pour chacun des membres de l'uplet
Dim i As Integer 'correction de cette ligne aussi C est déclaré mais jamais utilisé
Dim NbR As Integer
CompteDoublons = 1
For i = 0 To 8
NbR = 0
If Col(i) > 0 Then
NbR = Len(Uplet) - Len(Replace(Uplet, i, ""))
End If
CompteDoublons = CompteDoublons * Fact(NbR)
Next
End Function
Function CalculProba(MaxN As Integer, NbrMembres As Integer, ByRef Col() As Single, Cible As Integer)
'MaxN correspond a ton ancienne variable N
ReDim Xx(NbrMembres - 1) As Integer 'valeur de 0 à NbrMembres-1
Dim xDim As Integer
Dim SomX As Integer
Dim bPositif As Boolean
Dim sCol As Single
ReDim Tab_vTmp(NbrMembres - 1) As String
ReDim Tab_Retour(2, 0) As Variant
'Initialisation
CalculProba = False
Do
'Traitement
'On control que tous les membres de col soit > 0
bPositif = True
SomX = 0
sCol = 1
For xDim = 0 To NbrMembres - 1
If Col(Xx(xDim)) <= 0 Then
bPositif = False
Exit For
End If
SomX = SomX + Xx(xDim)
sCol = sCol * Col(Xx(xDim))
Next
If bPositif And (Cible = 0 Or SomX = Cible) Then
For xDim = 0 To UBound(Xx)
Tab_vTmp(xDim) = CStr(Xx(xDim))
Next
Tab_Retour(0, UBound(Tab_Retour, 2)) = "( " & Join(Tab_vTmp, " ; ") & " )"
Tab_Retour(1, UBound(Tab_Retour, 2)) = sCol
Tab_Retour(2, UBound(Tab_Retour, 2)) = Fact(NbrMembres) / CompteDoublons(Tab_Retour(0, UBound(Tab_Retour, 2)), Col)
CalculProba = Tab_Retour
ReDim Preserve Tab_Retour(2, UBound(Tab_Retour, 2) + 1)
End If
'Calcul des membres
'On incremente le tableau de poid fort
Xx(NbrMembres - 1) = Xx(NbrMembres - 1) + 1
'On boucle du tableau de poid le plus faible jusqu'a tableau d'indice NbrMembres-1
For xDim = NbrMembres - 1 To 1 Step -1
If Xx(xDim) > MaxN Then Xx(xDim - 1) = Xx(xDim - 1) + 1
Next
For xDim = 1 To NbrMembres - 1
If Xx(xDim) > MaxN Then Xx(xDim) = Xx(xDim - 1)
Next
Loop While Xx(0) <= MaxN
End Function
Private Sub Worksheet_Change(ByVal Target As Range)
'Declaration
Dim xDest As Integer
Dim Tab_Result As Variant
Dim bVide As Boolean
Dim Cible As Integer, NbM As Integer, cNbM As Integer
Dim x As Integer, N As Integer, R As Integer
'On verifie les conditions d'execution
If Intersect(Target, Union([Data], [NbMembres], [SomCible])) Is Nothing Then Exit Sub
If Intersect(Target, Union([Data], [NbMembres], [SomCible])).Cells.Count <> 1 Then
MsgBox "Vous ne devez pas modifier simultanément le contenu de plusieurs cellules bleues" & vbCrLf & "Les calculs n'ont pas été effectués."
Exit Sub
End If
'Initialisation
Cible = [SomCible].Value
NbM = [NbMembres].Value
ReDim Col([Data].Cells.Count - 1) As Single
R = 0
For x = 1 To [Data].Cells.Count
Col(x - 1) = [Data].Cells(x).Value2
If [Data].Cells(x) > 0 Then
N = x - 1 'Nbre maxi correspondant à la dernière donnée non-nulle
R = R + 1 'Nbre réel de données non nulles (sans celles nulles avant N)
End If
Next x
If Not 2 <= (UBound(Col) - 1) <= 9 Then
MsgBox "Le Nombre de Probabilité(s) Différente(s) de Zéro n'est pas correct"
Exit Sub
End If
If 1 > NbM Then
MsgBox "Le Nombre de Membres doit être un Entier superieur a 1"
Exit Sub
End If
'Cette partie du code n'etait valable que pour les versions precedant Excel 2007, qui gere plus de 2M de lignes (Integer avant et maintenant Long)
'Je l'ai rend independante de la version d'excel
x = 0
While Fact(R + x) / (Fact(x) * Fact(R)) < (Rows.Count - 1) And x <= NbM 'Protection anti-saturation
cNbM = x 'Nbre de membres max/uplet corrigé
x = x + 1
Wend
ReDim DestRange(2 To cNbM) As Range 'a rendre polyvalent
For xDest = 2 To cNbM 'a rendre polyvalent
Set DestRange(xDest) = Cells(2, (xDest - 2) * 3 + 12)
Next
Application.EnableEvents = False
[Results].Cells.ClearContents
Application.EnableEvents = True
'Traitement
'On empeche la mise a jour a l'ecran
Application.ScreenUpdating = False
bVide = True
'On boucle en fonction du nombre de membre
For x = 2 To cNbM 'a rendre polyvalent
Tab_Result = CalculProba(N, x, Col, Cible)
If IsArray(Tab_Result) Then
bVide = False
Application.EnableEvents = False
DestRange(x).Resize(UBound(Tab_Result, 2) + 1, 3) = WorksheetFunction.Transpose(Tab_Result)
Application.EnableEvents = True
End If
Next
'On verifie qu'il y a des resultats sinon on vide tout et on quitte
If bVide Then
MsgBox "Aucune permutation ne répond à votre critère de somme (" & Cible & ")"
Application.EnableEvents = False
[Results].Cells.ClearContents
Application.EnableEvents = True
Exit Sub
End If
Application.ScreenUpdating = True
If cNbM < NbM Then
MsgBox "Les permutations " & cNbM + 1 & "-uplets à " & NbM & "-uplets répondant à votre critère de somme (" & Cible & ") n'ont pas été calculés car plus de 65000 possibilités."
End If
End Sub |
Partager