Vous êtes sur la page 1sur 17

Corrigés des TD / TP - L3 SPI VBA

v1.1 - marc.lemaire@iupge.u-cergy.fr
3 octobre 2005

1 TD 1 : initiation VBA
1.1 exercice 1 : puissances de 2
Affichage des puissances de 2 en décimal et en hexadécimal jusqu’à 230 , avec et sans l’opérateur puissance
(i.e. en écrivant une fonction de calcul de la puissance).
Remarque : les positions sont relatives et correspondent aux décalages (offset ) en ligne et en colonne.
fonction tp1_afficher_puissances
début
entier i, p
pour i <- 0 à 30
p <- 2 ^ i ’ à remplacer ultérieurement par p <- power(2, i)
afficher (i) en position (i+1, 0)
afficher (p) en position (i+1, 1)
afficher (p) en position (i+1, 2) et en hexa
fin pour
fin

fonction power(entier val, entier pow)


début
entier i
entier produit <- 1
pour i <- 1 à pow
produit <- produit * val
fin pour
retourner produit
fin

1.2 exercice 2 : table ASCII


Affichage de la table ASCII
fonction afficherTableASCII
début
entier ligne, colonne, t
// affichage des titres des lignes et colonnes
pour t <- 0 à 15
afficher (t) en hexa en position(t+1, 0) // colonne 0
afficher (t) en hexa en position(0, t+1) // ligne 0
fin pour
pour ligne <- 0 à 15
pour colonne <- 0 à 15
afficherCaractère(ligne * 16 + colonne) en position (ligne+1, co-
lonne+1)
fin pour
fin pour
fin

1
1.3 exercice 3 : numéro INSEE
Remarque : la fonction “extraireCaractères” permet l’extraction partielle d’une chaı̂ne de caractères, à partir
d’une position, de n caractères. Les positions commencent à 1.
fonction decomposerNumeroINSEE
debut
string numeroINSEE
string caracteristiques
saisir (numeroINSEE)
si verifierClef(numeroINSEE) = true alors
afficher ("clef vérifiée avec succés")
caractèristiques <- analyserINSEE (numeroINSEE)
afficher (caractéristiques)
sinon
afficher ("erreur de numéro INSEE")
fin si
fin

fonction analyserINSEE (string numeroINSEE)


debut
string tmp, reponse
entier val
string[12] tabNomsMois = { "Janvier", "Fé-
vrier", "Mars", "Avril", "Mai", "Juin", "Juillet", "Ao^ut", "Septembre", "Oc-
tobre", "Novembre", "Décembre" }
tmp <- extraireCaracteres (numeroINSEE, 1, 1) // le sexe
si tmp = "1" alors
reponse <- "vous ^etes un homme né en "
sinon
reponse <- "vous ^etes une femme née en "
fin si
tmp <- extraireCaracteres (numeroINSEE, 4, 2) // le mois de naissance
val <- convertirEntier (tmp)
reponse <- reponse + tabNomsMois[val - 1] // l’indice des tableaux commence à 0
tmp <- extraireCaracteres (numeroINSEE, 2, 2) // les deux der-
niers chiffres de l’année de naissance
reponse <- reponse + "19" + tmp
tmp <- extraireCaracteres (numeroINSEE, 6, 2)
reponse <- reponse + " dans le département : " + tmp
retourner reponse
fin

fonction verifierClef (string numero)


debut
boolean clefOk <- false
entier valNum, valClef
valNum <- extraireCaracteres (numero, 1, 13)
valClef <- extraireCarcteres (numero, 14, 2)
si (97 - valNum modulo 97) = valClef alors
clefOk <- true
fin si
retourner clefOk
fin

2 TP 1 : initiation VBA
Sont présentés dans cette partie des exemples de solution (code VBA) aux exercices de TP.

2.1 exercice 1 : puissances de 2


Attribute VB_Name = "Module5"

2
’ TP1 : affichage des puissances de 2
’ L3 SPI - Algo et VBA
’ ml v1.3 - 28 / 09 / 2005

’ fonction principale d’affichage des puissances de 2


Public Sub tp1_ex1_afficher_puissance()

’declaration des variables locales


Dim i As Integer
Dim p As Long

’ affichage des puissances de 2


’ titres des colonnes
With Application.ActiveWorkbook.ActiveSheet
.Range("A1") = "i"
.Range("B1") = "2^i"
.Range("C1") = "décimal"
.Range("D1") = "hexadécimal"
End With

’ affichage des données (i et 2^i en décimal et en hexa)


For i = 0 To 30 ’ Remarque : la fonction de conversion hex ne supporte pas les valeurs (depassement
p = 2 ^ i ’ a remplacer ultérieurement par power(2, i)
Application.ActiveWorkbook.ActiveSheet.Range("A1").Offset(i + 1, 0) = i
Application.ActiveWorkbook.ActiveSheet.Range("A1").Offset(i + 1, 1) = "2^" & i & " ="
Application.ActiveWorkbook.ActiveSheet.Range("A1").Offset(i + 1, 2) = p
Application.ActiveWorkbook.ActiveSheet.Range("A1").Offset(i + 1, 3) = Hex(p)
Next i
End Sub

’ fonction permettant de calculer la puissance de 2 : remplace l’opérateur ^


Function power(valeur As Integer, puissance As Integer) As Long
Dim resultat As Long
Dim i

resultat = 1

For i = 1 To puissance
resultat = resultat * valeur
Next i

power = resultat
End Function

2.2 exercice 2 : table ASCII


Attribute VB_Name = "Module2"

’ TP 1 : affichage de la table ASCII


’ L3 SPI : Algo & VBA
’ ml v1.2 - 28 / 09 / 2005

Public Sub tableASCII()

Const title = "A1"


Const data = "B4"
Dim i As Integer

3
Dim lig As Integer
Dim col As Integer

’ raz de la feuille Feuil2


Application.ActiveWorkbook.Worksheets("Feuil2").Activate
Cells.Select
Selection.Clear
Range("A1").Select

With Application.ActiveWorkbook.Worksheets("Feuil2")
.Range(title) = "Table ASCII"

’affichage des titres de lignes et de colonnes


For i = 0 To 15
.Range(data).Offset(0, i + 1).HorizontalAlignment = xlCenter
.Range(data).Offset(0, i + 1).Font.Bold = True
.Range(data).Offset(0, i + 1).Font.Size = 12
.Range(data).Offset(0, i + 1) = Hex$(i) ’ offset(ligne, colonne)

.Range(data).Offset(i + 1, 0).HorizontalAlignment = xlCenter


.Range(data).Offset(i + 1, 0).Font.Bold = True
.Range(data).Offset(i + 1, 0).Font.Size = 12
.Range(data).Offset(i + 1, 0) = Hex$(i)
Next i

’ remplissage de la table ASCII


For lig = 0 To 15
For col = 0 To 15
.Range(data).Offset(lig + 1, col + 1).HorizontalAlignment = xlCenter
.Range(data).Offset(lig + 1, col + 1) = Chr(16 * lig + col)
Next col
Next lig
End With

End Sub

2.3 exercice 3 : numéro INSEE


Attribute VB_Name = "Module3"

’ saisie et verification d’un numero INSEE


’ gestion des E / S avec InputBox et MsgBox
’ ml v1.1 - 28 / 09 / 2005

’ fonction principale de saisie et de vérification d’un numéro INSEE, et d’affichage des resultats de l’
Public Sub verifCodeINSEE()

Dim code As String


Dim message As String

code = InputBox("valeur du code INSEE (15 chiffre) : ", " verification numero Secu ")

’ verification simple de la saisie (la longueur)


If Len(Trim(code)) <> 15 Then ’ trim supprime les espaces a gauche et a droite
MsgBox " nombre de caracteres saisis incorrect !", vbOKOnly + vbCritical, " erreur saisie "
Else
’ verification de la clef
If Not verifClef(code) Then
MsgBox " numero / clef invalide !", vbOKOnly + vbExclamation, " erreur numero "
Else
’traitement du numero INSEE

4
message = traitement(code)
MsgBox message, vbOKOnly + vbInformation, " code INSEE traite "
End If
End If

End Sub

’ fonction de verification de la clef


Private Function verifClef(ByVal codeINSEE As String) As Boolean

Dim clef As Integer


Dim numero As Variant ’ numero est de type decimal mais ne peut etre declare comme tel (cf. restrict
Dim clefValide As Boolean
Const MULTIPLE = 100000

clef = Val(Right$(codeINSEE, 2)) ’ les 2 derniers chiffres constituent la clef

numero = CDec(Left$(codeINSEE, 13)) ’ les 13 premiers chiffres constituent le numero, on peut aussi

While numero >= (97 * MULTIPLE) ’ on traite l’operateur modulo par une boucle...
numero = numero - (97 * MULTIPLE) ’ ... car l’utilisation de l’operateur modulo directement (num
Wend
If (97 - (numero Mod 97)) = clef Then
clefValide = True
Else
clefValide = False
End If

verifClef = clefValide
End Function

’ fonction d’analyse d’un numero INSEE


Private Function traitement(codeINSEE As String) As String

Dim sexe As String


Dim anneeNaissance As Integer
Dim moisNaissance As Integer
Dim departementNaissance As String
Dim msg As String
Dim tabMois As Variant ’ meme s’il s’agit d’un tableau de String (cf. restriction dans la doc. sur l

tabMois = Array("janvier", "février", "mars", "avril", "mai", "juin", "juillet", "ao^


ut", "septembre"

sexe = Left$(codeINSEE, 1)
Select Case sexe
Case 1
msg = " vous etes un homme " & vbCrLf
Case 2
msg = " vous etes une femme " & vbCrLf
Case Else
’ do Nothing : cas particulier pour les numéros temporaires
End Select

moisNaissance = Val(Mid$(codeINSEE, 4, 2))


msg = msg + " né(e) en " & tabMois(moisNaissance - 1) ’ les mois commencent à 1 (un) mais les indice

anneeNaissance = Val(Mid$(codeINSEE, 2, 2)) + 1900


msg = msg + " " & anneeNaissance & vbCrLf

departementNaissance = Mid$(codeINSEE, 6, 2)
msg = msg + " dans le departement : " & departementNaissance & vbCrLf

5
traitement = msg

End Function

3 TD 2 : calendrier
3.1 année bissextile
fonction estBissextile (entier annee)
debut
booleen bissextile <- false
si (annee modulo 4 = 0 et annee modulo 100 6= 0) ou (annee modulo 400 = 0) alors
bisextile <- true
fin si
retourner bisextile
fin

3.2 calendrier annuel


Affichage d’un calendrier d’une année sur une feuille Excel en précisant l’année, les noms des mois (en
français), les numéros des jours dans l’année, les noms des jours (en français) et les dates (numéro du jour dans
le mois). On suppose l’existence d’une fonction weekDayNumber(date) renvoyant le numéro du jour dans la
semaine (1 pour lundi, 7 pour dimanche).

// les 3 tableaux ci-dessous sont utilisés par l’ensemble des fonctions : ils peuvent ^
etre déclarés
String[ ] nomsJours <- { "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi", "dimanche"
String[ ] nomsMois <- { "janvier", "février", "mars", "avril", "mai", "juin", "juillet", "ao^ut",
entier[ ] nbJoursMensuel <- { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }

fonction afficherCalendrierAnnuel
debut
entier annee <- 2005 // on peut aussi saisir l’annee
entier numJourAnnuel <- 1
entier numSemaine <- 1
entier mois, jour
date tmp

si (estBissextile(annee)) alors
nbJoursMensuel[1] <- 29
fin si
afficher (annee)
pour (mois <- 1 a 12)
afficher(nomsMois[mois - 1]
fin pour
pour mois <- 1 a 12
pour jour <- 1 a nbJoursMensuel[mois - 1]
afficher(numJourAnnuel)
tmp <- creerDate(jour, mois, annee)
afficher(nomsJour[weekDayNumber(tmp) - 1])
afficher(jour)
si (weekDayNumber(tmp) = 1) alors // si c’est un lundi
afficher(numSemaine)
numSemaine <- numSemaine + 1
fin si
numJourAnnuel <- numJourAnnuel + 1
fin pour
// réinitialiser les décalages pour l’affichage en colonnes
fin pour

6
fin

3.3 calendrier mensuel


Afficher chaque mois sur une feuille Excel (une feuille par mois) sur 7 colonnes (une par jour).
fonction afficherCalendrierMensuel
debut
entier annee <- 2005 // ou saisie de l’année
entier mois

si (estBissextile(annee)) alors
nbJoursMensuel[1] <- 29
fin si

pour (mois <- 1 à 12)


creerFeuilleExcel(nomsMois[mois - 1]
afficherMois(annee, mois)
fin pour
fin

fonction afficherMois(entier annee, entier mois)


debut
entier jour
entier ligne <- 1
entier colonne <- weekDayNumber(creerDate(1, mois, annee)

afficher nomsMois[mois - 1]
pour jour <- 1 a 7
afficher nomsJours[jour - 1]
fin pour
pour jour <- 1 a nbJoursMensuel[mois - 1]
afficher(jour) en position ligne et colonne // du lundi (1) au dimanche (7)
colonne <- colonne + 1
si colonne > 7 alors
ligne <- ligne + 1
colonne <- 1
fin si
fin pour
fin

4 TP 2 : calendrier
Attribute VB_Name = "Module1"
’ TP2 : module de gestion d’un calendrier
’ ml v 1.1 - 01 / 10 / 2005

’ declaration des variables du module


’ déclaration des tableaux
Dim nbJours As Variant ’ le type doit obligatoirement etre Variant meme s’il s’agit d’un tableau de Stri
Dim nomsJours As Variant
Dim nomsMois As Variant

Public Sub CreerCalendrier()

’ declaration des variables de la procédure


Dim jour As Integer
Dim mois As Integer
Dim annee As Integer
Dim numeroJourAnnee As Integer

7
Dim numSemaine As Integer
Const NBCOLS = 4 ’ nombre de colonnes consacrees a chaque mois

’ initialisation des variables de la procédure


annee = Year(Date) ’ a remplacer ulterieurement par InputBox avec default = Year(Date)
numeroJourAnnee = 1
numSemaine = 1

’ initialisation des variables du module : ces insructions doivent obligatoirement etre dans une pro
nbJours = Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
If isAnneeBissextile(annee) Then
nbJours(1) = 29
End If
nomsJours = Array("lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi", "dimanche")
nomsMois = Array("janvier", "février", "mars", "avril", "mai", "juin", "juillet", "ao^
ut", "septembre

’ le calendrier annuel
Application.ActiveWorkbook.ActiveSheet.Name = annee
For mois = 1 To 12
’ on affiche le nom du mois pour les NBCOLS colonnes
’ NB : la seletion multiple de cellule pour une fusion (merge) n’est pas tres simple...
Application.ActiveWorkbook.ActiveSheet.Range("A2:D2").Offset(-1, (mois - 1) * NBCOLS).Select
Selection.Merge
Selection.Borders.Color = RGB(&HFF, &H0, &H0)
Selection.Borders.Weight = xlMedium
Selection.HorizontalAlignment = xlCenter
Selection.Font.Bold = True
Selection.Font.Size = 15
Selection.Formula = nomsMois(mois - 1)

’ on affiche le nom des jours, leur numero dans le mois et leur numero dans l’annee
’ on affiche egalement le numero de semaine
For jour = 1 To nbJours(mois - 1)
Application.ActiveWorkbook.ActiveSheet.Range("A2").Offset(jour, (mois - 1) * NBCOLS) = numer
Application.ActiveWorkbook.ActiveSheet.Range("A2").Offset(jour, (mois - 1) * NBCOLS + 1) = n
Application.ActiveWorkbook.ActiveSheet.Range("A2").Offset(jour, (mois - 1) * NBCOLS + 2) = D
If (WeekDay(DateSerial(annee, mois, jour), vbMonday) = 1) Then ’ si c’est un lundi
Application.ActiveWorkbook.ActiveSheet.Range("A2").Offset(jour, (mois - 1) * NBCOLS + 3)
numSemaine = numSemaine + 1
End If
’ on grise les samedi et les dimanche
If (WeekDay(DateSerial(annee, mois, jour), vbMonday) = 6 Or WeekDay(DateSerial(annee, mois,
Application.ActiveWorkbook.ActiveSheet.Range("A2:D2").Offset(jour, (mois - 1) * NBCOLS).
End If
numeroJourAnnee = numeroJourAnnee + 1
Next jour
’ on optimise la largeur des colonnes pour une lecture a l’ecran plus facile
Application.ActiveWorkbook.ActiveSheet.Columns("A:BZ").EntireColumn.AutoFit
Next mois

’ les calendriers mensuels


For mois = 1 To 12
creerMois mois, annee
Next mois

End Sub

’ determine si une annee est bissextile ou non


’ @param annee : l’annee a evaluer
’ @return true si l’annee est bissextile, faux sinon
Private Function isAnneeBissextile(annee As Integer) As Boolean

8
’ une annee est bissextile si elle est multiple de 4 sauf les annee seculaires non multiples de 400
’ 1600 et 2000 sont bissextile ; 1700, 1800, 1900 et 2100 ne sont pas bissextiles
Dim bissextile As Boolean

bissextile = False
If (annee Mod 4 = 0 And annee Mod 100 <> 0) Or annee Mod 400 = 0 Then
bissextile = True
End If

isAnneeBissextile = bissextile

End Function

’ cree une feuille de calcul supplementaire dans le classeur courant et affiche le mois
’ @param mois : le numero du mois a afficher
’ @param annee : l’annee du mois a afficher
Private Sub creerMois(mois As Integer, annee As Integer)
Dim feuille As Worksheet ’ la nouvelle feuille cree pour le mois traite
Dim last As Worksheet ’ la derniere feuille du classeur
Dim colonne As Integer
Dim ligne As Integer
Dim numFeuille As Integer ’ le numero de la derniere feuille du classeur
Const titre = "B2:H2" ’ la position du titre (le nom du mois)
Const start = "B4" ’ la position de depart du contenu

numFeuille = Application.ActiveWorkbook.Worksheets.Count
Set last = Application.ActiveWorkbook.Worksheets(numFeuille)

Set feuille = Application.ActiveWorkbook.Worksheets.Add(, last) ’ ou (,last, 1, xlWorksheet) car 1 e


’ feuille devient la feuille active
feuille.Name = nomsMois(mois - 1)

’ titre (nom du mois) sur la feuille avec plein de decorations pour le titre ;-)
With feuille
.Range(titre).Select
With Selection
.MergeCells = True
.HorizontalAlignment = xlCenter
.Font.Bold = True
.Font.Size = 17
.Cells.Borders.Weight = 3
.Cells.Borders.Color = RGB(&HFF, &HFF, &H0)
.Interior.Color = RGB(&H0, &HFF, &H0)
.Font.Color = RGB(&HFF, &H0, &H0)
.Formula = nomsMois(mois - 1) & " " & annee
End With
End With

’ entete des jours de la semaine


For i = 0 To 6
feuille.Range(start).Offset(0, i).Font.Bold = True
feuille.Range(start).Offset(0, i) = nomsJours(i)
Next i

’ on recherche la position du premier jour du mois par rapport au lundi


colonne = WeekDay(DateSerial(annee, mois, 1), vbMonday) - 1
ligne = 1
jour = 1

While jour <= nbJours(mois - 1)


feuille.Range(start).Offset(ligne, colonne) = jour

9
’ on grise les samedi et les dimanche
If (WeekDay(DateSerial(annee, mois, jour), vbMonday) = 6 Or WeekDay(DateSerial(annee, mois, jour
feuille.Range(start).Offset(ligne, colonne).Interior.Color = RGB(&HD0, &HD0, &HD0)
End If

colonne = colonne + 1
If WeekDay(DateSerial(annee, mois, jour), vbMonday) = 7 Then
colonne = 0
ligne = ligne + 1
End If
jour = jour + 1
Wend
End Sub

5 TD 3 : algorithmes de recherche et tri


5.1 génération d’un tableau pré-trié
On suppose l’existence d’une fonction random(n) renvoyant une valeur entière pseudo-aléatoire comprise
entre 0 et n
fonction initTab (entier[ ] tab)
debut
constante MAX <- 9
entier i
tab[0] <- random(MAX)

pour i <- 1 a taille(tab) - 1


tab[i] <- tab[i-1] + random(MAX)
fin pour
fin

5.2 recherche séquentielle


fonction rechercheSequentielle (entier[ ] tab, entier val)
début
booleen trouve <- false
entier i <- 0

tant que (trouve = false et i < nbElts(tab))


si tab[i] = val alors
trouve <- true
fin si
i <- i+1
fin tant que
retourne trouve
fin

5.3 recherche dichotomique


5.3.1 forme recursive
lors du premier appel à la fonction debut = 0 et fin = nombre d’éléments - 1

rechercheDichotomiqueRecursive(entier[ ] tab, entier val, entier debut, entier fin)


debut
entier milieu <- (debut + fin) / 2
booleen trouve <- faux

si debut > fin alors


trouve <- faux

10
sinon
si tab[milieu] = val
trouve <- vrai
sinon
si tab[milieu] > val alors
trouve <- rechercheDichotomiqueRecursive(tab, val, debut, milieu - 1)
sinon
trouve <- rechercheDichotomiqueRecursive(tab, val, milieu + 1, fin)
fin si
fin si
fin si
retourner trouve
fin

5.3.2 forme itérative


rechercheDichotomiqueIterative(entier[ ] tab, entier val)
debut
entier debut <- 0
entier fin <- taille(tab) - 1
entier milieu
booleen trouve <- faux

tant que (trouve = faux et fin >= debut)


milieu <- (debut + fin) / 2
si tab[milieu] = val alors
trouve <- vrai
sinon
si tab[milieu] > val alors
fin <- milieu - 1
sinon
debut <- milieu + 1
fin si
fin tant que
retourner trouve
fin

6 TP 3 : algorithmes de recherche et tri


Attribute VB_Name = "Module2"
’ module de comparaison d_algorithmes de recherche

Option Base 0 ’ c’est aussi l’option par defaut...

’ declaration des constantes locales au module


Private Const NBELTS = 5000 ’ la taille du tableau (nombre elements)

’ point d_entree du programme (main)


Sub mainSearch()

Dim tabEntiers(0 To NBELTS - 1) As Long ’ il est preferable de gerer les indices manuellement
’ car tabEntiers(MAX) contient MAX + 1 valeurs ...
Dim searchedValue As Long
Dim founded As Boolean
Dim tstart As Single
Dim tstop As Single
Dim i As Long

initSortedTab tabEntiers ’ rappel pour les procedures, il n_y a pas de parentheses lors de l’appel .

11
clearSheet (3) ’ numero de la feuille Excel pour l’affichage
Call afficheTab(tabEntiers, 3) ’ numero de la feuille Excel pour l’affichage

’ on recherchera sur le m^
eme tableau quel que soit l’algorithme
Debug.Print " tableau pre-trie cree ... "

’ 10000 recherches sequentielles d’une valeur quelconque sur le meme tableau


tstart = Timer ’ on lance le chronometre
For i = 1 To 10000
searchedValue = Rnd * tabEntiers(UBound(tabEntiers))
founded = sequentialSearch(tabEntiers, searchedValue) ’ on recherche
Next i
tstop = Timer ’ on arrete le chronometre
Debug.Print " 10000 Sequential searches elapsed time = " & tstop - tstart & " second(s), for a last

’ 10000 recherches dichotomiques d’une valeur quelconque sur le meme tableau


tstart = Timer ’ on lance le chronometre
For i = 1 To 10000
searchedValue = Rnd * tabEntiers(UBound(tabEntiers))
founded = dichotomicSearch(tabEntiers, searchedValue, LBound(tabEntiers), UBound(tabEntiers)) ’
Next i
tstop = Timer ’ on arrete le chronometre
Debug.Print " 10000 Dichotomic searches elapsed time = " & tstop - tstart & " second(s), for a last

’ 10000 recherches dichotomiques (SANS recursivite) d’une valeur quelconque sur le meme tableau
tstart = Timer ’ on lance le chronometre
For i = 1 To 10000
searchedValue = Rnd * tabEntiers(UBound(tabEntiers))
founded = rechercherDichotomique(tabEntiers, searchedValue) ’ on recherche
Next i
tstop = Timer ’ on arrete le chronometre
Debug.Print " 10000 Dichotomic searches (WITHOUT recursivity) elapsed time = " & tstop - tstart & "

End Sub

’ =====================================================================
’ definition des différentes fonctions (et procédures)

’ initialisation d’un tableau pre-trie d’entiers avec des valeurs pseudo-aleatoires


Sub initSortedTab(ByRef tabToInit() As Long)
Dim i As Long

Randomize
tabToInit(0) = Rnd * 10
For i = 1 To UBound(tabToInit)
tabToInit(i) = tabToInit(i - 1) + Rnd * 10 ’ Rnd renvoie une valeur comprise entre 0 et 1
Next i

End Sub

’ affichage d’un tableau dans la feuille active


Sub afficheTab(ByRef tableau() As Long, ByVal numFeuille As Integer)

Const MAXIMUM = 10000 ’ nombre maximum d’elements affiches dans une feuille

Dim i As Long
Dim lig As Integer ’ les lignes d’une feuille (de 1 a 65536)
Dim col As Integer ’ les colonnes d’une feuille (de A à IV)
Dim maxCells As Integer

12
lig = 0
col = 0
If (UBound(tableau) > MAXIMUM) Then
maxCells = MAXIMUM
Else
maxCells = UBound(tableau)
End If

For i = 0 To maxCells ’ tous les elements ne sont pas necessairement affiches


Application.ActiveWorkbook.Worksheets(numFeuille).Range("A1").Offset(lig, col).Value = tableau(i
col = col + 1
If (col > 19) Then
col = 0
lig = lig + 1
End If
Next i
End Sub

’ calul de la taille d’un tableau, puisque cette fonction ne semble pas integree a VB...
Function tabLength(ByRef tableau() As Long) As Long

tabLength = UBound(tableau) - LBound(tableau) + 1


End Function

’ effacement du contenu d’une feuille Excel


Sub clearSheet(ByVal numFeuille As Integer)

Application.ActiveWorkbook.Worksheets(numFeuille).Activate
Cells.Select
Selection.Clear ’ ou ClearContents
Range("A1").Select

End Sub

’ recherche sequentielle sur un tableau trie


Function sequentialSearch(ByRef tableau() As Long, ByVal valeur As Long) As Boolean
Dim i As Long
Dim trouve As Boolean

trouve = False

For i = 0 To UBound(tableau)
If tableau(i) = valeur Then
trouve = True
Exit For
End If
Next i

sequentialSearch = trouve

End Function

’ recherche dichotomique sur un tableau trie


Function dichotomicSearch(ByRef tableau() As Long, ByVal valeur As Long, ByVal debut As Long, ByVal fin
Dim milieu As Long
Dim trouve As Boolean

trouve = False

milieu = (debut + fin) / 2


If tableau(milieu) = valeur Then

13
trouve = True
Else
If fin > debut Then ’ soit fin = debut = milieu => deja teste, soit fin < debut donc la vale
If valeur > tableau(milieu) Then ’ on recherche a droite (partie haute)
trouve = dichotomicSearch(tableau, valeur, milieu + 1, fin)
Else ’ valeur < tableau(milieu) et on recherche a gauche (partie basse)
trouve = dichotomicSearch(tableau, valeur, debut, milieu - 1)
End If
End If
End If

dichotomicSearch = trouve

End Function

’ recherche dichotomique sur un tableau trie SANS recursivite


Function rechercherDichotomique(ByRef tableau() As Long, ByVal valeur As Long) As Boolean
Dim debut As Long
Dim milieu As Long
Dim fin As Long
Dim trouve As Boolean

debut = 0
fin = UBound(tableau)
trouve = False

Do
milieu = (debut + fin) / 2
If (tableau(milieu) = valeur) Then
trouve = True
Else
If tableau(milieu) = valeur Then
fin = milieu - 1
Else
debut = milieu + 1
End If
End If
Loop While (trouve = False And fin >= debut)

rechercherDichotomique = trouve
End Function

7 TD 4 : formulaire (userform) : password


7.0.3 génération du tableau de caractères
fonction creerTab( )
debut
caractere[ ] tab
entier tailleTab <- 0
entier nbElts <- 0

selon(caseACocher) // les différents cas ne sont pas exclusifs


cas majuscules
taille <- taille + 26
cas minuscules
taille <- taille + 26
cas chiffres
taille <- taille + 10
cas special
taille <- taille + 1

14
fin selon
tab <- creerTableau(tailleTab)
selon(caseACocher) // les différents cas ne sont pas exclusifs
cas majuscules
pour i <- 0 a 25
tab[nbElts + i] <- ’A’ + i // 0x41 + i
fin pour
nbElts <- nbElts + 26
cas minuscules
pour i <- 0 a 25
tab[nbElts + i] <- ’a’ + i // 0x61 + i
fin pour
nbElts <- nbElts + 26
cas chiffres
pour i <- 0 a 9
tab[nbElts + i] <- ’0’ + i // 0x30 + i
fin pour
nbElts <- nbElts + 10
cas special
tab[nbElts] <- caractere(boutonRadio)
nbElts <- nbElts + 1
fin selon
retourner tab
fin

7.0.4 mélange du tableau


principe : prendre 2 cases aléatoirement et les permuter.
fonction melangerTab(caractere[ ] tab)
debut
entier i, indiceA, indiceB
caractere tmp

pour i <- 1 a 100 * taille(tab)


indiceA <- random(taille(tab) - 1)
indiceB <- random(taille(tab) - 1)
tmp <- tab[indiceA]
tab[indiceA] <- tab[indiceB]
tab[indiceB] <- tmp
fin pour
fin

7.0.5 génération du mot de passe


fonction calculerMotDePasse(caracteres[ ] tab)
debut
entier i
entier nbCar <- textField.value()
String password

pour i <- 0 a nbCar


password <- password & tab[random(taille(tab) - 1)]
fin pour
retourner password
fin

8 TP 4 : formulaire (userform) password


Private Sub ChkCarSpecial_Click()
If ChkCarSpecial Then

15
FrmMotPasse.Height = 210
Else
FrmMotPasse.Height = 155
End If
End Sub

Private Sub CmdAnnuler_Click()


Unload FrmMotPasse
End Sub

Private Sub CmdAucun_Click()


ChkMinuscules = False
ChkChiffres = False
ChkMajuscules = False
ChkCarSpecial = False
FrmMotPasse.Height = 155
End Sub

Private Sub CmdOK_Click()


Dim pwd As String

If (ChkMinuscules = False And ChkMajuscules = False) Then


’ NB : si on ne met pas les parentheses, MsgBox est assimilee a une procedure, il n’est donc pas
MsgBox "Cochez au minimum les minuscules et /ou les majuscules", vbExclamation + vbOKOnly, "aver
Else
’ c’est ici qu’on appel la fonction de traitement
pwd = calculerMotDePasse()
TxtMotDePasse = pwd
End If
End Sub

Private Sub CmdTous_Click()


ChkMinuscules = True
ChkChiffres = True
ChkMajuscules = True
ChkCarSpecial = True
FrmMotPasse.Height = 210
End Sub

Private Sub SpbNbre_Change()


TxtNbCar = SpbNbre
End Sub

Private Function calculerMotDePasse() As String


’ c’est ici qu’on realise le traitement
Dim tabCar As String
Dim password As String
Dim indice As Integer

’ on remplit le tableau de caractères en fonctions des cases cochées


If ChkMinuscules = True Then
’ les 26 lettres minuscules
For i = 0 To 25
tabCar = tabCar & Chr(&H61 + i)
Next i
End If
If ChkMajuscules = True Then
’ les 26 lettres majuscules
For i = 0 To 25
tabCar = tabCar & Chr(&H41 + i)

16
Next i
End If
If ChkChiffres = True Then
’ les 10 chiffres
For i = 0 To 9
tabCar = tabCar & Chr(&H30 + i)
Next i
End If
If ChkCarSpecial = True Then
’ le caractère spécial
If optDiese.Value = True Then
tabCar = tabCar & "#"
End If
If optDollar.Value = True Then
tabCar = tabCar & "$"
End If
If optExclamation.Value = True Then
tabCar = tabCar & "!"
End If
If optParagraphe.Value = True Then
tabCar = tabCar & " "
End If
If optAmp.Value = True Then
tabCar = tabCar & "&"
End If
End If
’ Debug.Print tabCar
Randomize
melanger tabCar
For i = 1 To TxtNbCar
indice = 1 + Rnd * (Len(tabCar) - 1) ’ dans une chaine de caracteres, les indices commencent a 1
password = password & Mid$(tabCar, indice, 1)
Debug.Print indice
Next i
calculerMotDePasse = password
End Function

Private Sub melanger(ByRef tableau As String)

Dim indic1 As Integer


Dim indic2 As Integer
Dim tmp As String ’ le caractere

For i = 1 To 100 * Len(tableau)


indic1 = 1 + Rnd * (Len(tableau) - 1)
indic2 = 1 + Rnd * (Len(tableau) - 1)
’ on permute
tmp = Mid$(tableau, indic1, 1)
Mid(tableau, indic1, 1) = Mid$(tableau, indic2, 1)
Mid(tableau, indic2, 1) = tmp
Next i
Debug.Print tableau
End Sub

17

Vous aimerez peut-être aussi