Chemin = ThisWorkbook.Path & "\" With Feuille 'Transfère les données du fichier texte dans la feuille : "Feuil3" With .QueryTables.Add(Connection:="TEXT;" & Chemin & "Dico et compteur.txt", Destination:=.Range("$A$1")) .Name = "aa"
Je travaille un peu la présentation, car si je poste le projet complet, il ne faut pas que ce soit trop moche quand même.
Option Explicit '--------------- CREATION DU DICTIONNAIRE (à partir du dictionnaire txt joint au classeur) 'A L'OUVERTURE DU CLASSEUR Private Sub Workbook_Open() 'Sources : ucfoutu 'http://codes-sources.commentcamarche.net/forum/affich-10019292-vba-excel-recursivite-jeu-du-boggle#82 Dim Chemin As String Set Feuille = Sheets("Feuil3") Chemin = ThisWorkbook.Path & "\" With Feuille 'Transfère les données du fichier texte dans la feuille : "Feuil3" With .QueryTables.Add(Connection:="TEXT;" & Chemin & "Dico et compteur.txt", Destination:=.Range("$A$1")) .Name = "aa" .FieldNames = True .SaveData = True .RefreshPeriod = 0 .TextFilePromptOnRefresh = False .TextFileStartRow = 1 .TextFileParseType = xlDelimited .TextFileTabDelimiter = True .TextFileSemicolonDelimiter = True .Refresh BackgroundQuery:=False End With End With Sheets("Feuil1").Select End Sub '--------------- DESTRUCTION DU DICTIONNAIRE 'A LA FERMETURE DU CLASSEUR Private Sub Workbook_BeforeClose(Cancel As Boolean) With Sheets("Feuil3") .Columns("A:AA").Delete Shift:=xlToLeft End With Sheets("Feuil1").Select ThisWorkbook.Save End Sub
Option Explicit '--------------- EFFACE LES SOLUTIONS Private Sub CommandButton1_Click() Rows("11:1000").Delete Shift:=xlUp Sheets("Feuil1").Range("Q10").ClearContents End Sub '--------------- TIRAGE Private Sub CommandButton2_Click() Call Tirage 'code dans le Module Procédures End Sub Private Sub CommandButton3_Click() Call Solutions 'code dans le Module Procédures End Sub
Option Explicit '--------- Module contenant les procédures nécessaires au jeu ------------------ Public DicoReduit As Object Public Feuille As Worksheet Public CelVoisines(15) As Range, Cellules, Chemin(), ListeMots(), Voisines(15) As Range Dim t As Single '--------------- TIRAGE ALEATOIRE DES 16 LETTRES Sub Tirage() 'Cette procédure est commandée par le bouton TIRAGE (Cf : Module Feuil1) Dim cubes As Variant, Cel As Range, cpt As Byte, tirag As String t = Timer 'la grille choisie : Range("D3:G6") Sheets("Feuil1").Range("Grille").ClearContents Randomize Timer cubes = Array("ETUKNO", "EVGTIN", "IELRUW", "DECAMP", "EHIFSE", "RECALS", "ENTDOS", "OFXRIA", "NAVEDZ", "EIOATA", "GLENYU", "BMAQJO", "TLIBRA", "SPULTE", "AIMSOR", "ENHRIS") touille_cubes cubes '----- MERCI UCFOUTU ! cpt = 0 tirag = "" For Each Cel In Range("Grille") Cel.Value = Mid(cubes(cpt), CInt((5 * Rnd()) + 1), 1) cpt = cpt + 1 tirag = tirag & Cel.Value & " - " Next Cel Sheets("Feuil2").Columns(3).Find("*", , , , xlByColumns, xlPrevious).Offset(1, 0) = "Tirage " & Left(tirag, Len(tirag) - 3) & " en : " & Timer - t & " secondes." Call TriDicoEnFonctionTirage End Sub 'Mélange les dés Private Sub touille_cubes(ByRef cubes) 'Sources : ucfoutu 'http://codes-sources.commentcamarche.net/forum/affich-10019292-vba-excel-recursivite-jeu-du-boggle#41 Dim i As Integer, nb As Integer, ou As Integer Dim temp As String nb = UBound(cubes) For i = 0 To nb / 2 ou = Int(((15 - i) * Rnd)) temp = cubes(ou) cubes(ou) = cubes(nb - i) cubes(nb - i) = temp Next End Sub Sub TriDicoEnFonctionTirage() Dim Tb(), OccurLettres As Object, Cel As Range, i As Long, j As Byte, Flag As Boolean Set Feuille = Sheets("Feuil3") Set OccurLettres = CreateObject("Scripting.Dictionary") For Each Cel In Range("Grille") OccurLettres(Cel.Value) = OccurLettres(Cel.Value) + 1 Next Cel Set DicoReduit = CreateObject("Scripting.Dictionary") Tb = Feuille.Range("A1:AA" & Feuille.Range("A" & Rows.Count).End(xlUp).Row).Value For i = LBound(Tb) To UBound(Tb) Flag = True For j = 2 To 27 If Tb(i, j) <> "" Then If Tb(i, j) > OccurLettres(Chr(63 + j)) Or Not OccurLettres.Exists(Chr(63 + j)) Then Flag = False: Exit For End If Next If Flag Then DicoReduit(Tb(i, 1)) = "" Next i ListeMots = DicoReduit.Keys Sheets("Feuil2").Columns(1).Find("*", , , , xlByColumns, xlPrevious).Offset(1, 0) = "Tirage en : " & Timer - t & " secondes." End Sub Sub Solutions() Dim strText As String, Cel As Range, CptResult As Long, Resultats(), i As Long, j As Integer, route() t = Timer 'Numérotation des cellules de 0 à 15, dans cet ordre : Cellules = Array("$D$3", "$E$3", "$F$3", "$G$3", "$D$4", "$E$4", "$F$4", "$G$4", "$D$5", "$E$5", "$F$5", "$G$5", "$D$6", "$E$6", "$F$6", "$G$6") 'Boucle sur les mots de la liste For i = LBound(ListeMots) To UBound(ListeMots) strText = ListeMots(i) '"REEES" ' '-------------------- Recherche de la 1ère lettre du mot dans la grille For Each Cel In Sheets("Feuil1").Range("Grille") If Cel.Value = Left(strText, 1) Then 'Initialisation des variables tableaux représentants les cellules et leurs voisines Initialisation '---------- Lettre trouvée Erase Chemin ' = nouveau chemin ReDim Preserve Chemin(0) Chemin(0) = Application.Match(Cel.Address, Cellules, 0) - 1 ' Chemin(0) = n° de la cellule Call Retire(Cel.Address) For j = LBound(CelVoisines) To UBound(CelVoisines) Set Voisines(j) = CelVoisines(j) Next j If SolucesRecurs(strText, 2) = True Then ReDim Preserve Resultats(CptResult) Resultats(CptResult) = strText ReDim Preserve route(CptResult) For j = LBound(Chemin) To UBound(Chemin) route(CptResult) = route(CptResult) & Chemin(j) & " - " Next j route(CptResult) = Left(route(CptResult), Len(route(CptResult)) - 3) CptResult = CptResult + 1 End If End If Next Cel Next i Sheets("Feuil1").Range("Q10") = CptResult & " mots trouvés en : " & Timer - t & " secondes." Sheets("Feuil2").Columns(2).Find("*", , , , xlByColumns, xlPrevious).Offset(1, 0) = CptResult & " mots trouvés en : " & Timer - t & " secondes." For i = LBound(Resultats) To UBound(Resultats) Sheets("Feuil1").Cells(Columns(Len(Resultats(i))).Find("*", , , , xlByColumns, xlPrevious).Row + 1, Len(Resultats(i))) = Resultats(i) & " (" & route(i) & ")" Next i End Sub Sub Retire(Cellu As String) 'Retire de toutes les "Cellules voisines", la cellule initiale trouvée dans la proc "Solutions" Dim i As Byte, monRng As Range Set monRng = Sheets("Feuil1").Range(Cellu) For i = LBound(CelVoisines) To UBound(CelVoisines) If Not Application.Intersect(CelVoisines(i), monRng) Is Nothing Then Set CelVoisines(i) = SubtractFirstPrinciples(CelVoisines(i), monRng) End If Next i End Sub Sub Initialisation() 'Voisines de "D3" pour le Chemin : D3 = 0 Set CelVoisines(0) = Sheets("Feuil1").Range("$E$3,$D$4:$E$4") 'Voisines de "E3" pour le Chemin : E3 = 1 Set CelVoisines(1) = Sheets("Feuil1").Range("$D$3,$F$3,$D$4:$F$4") 'Voisines de "F3" etc.... Set CelVoisines(2) = Sheets("Feuil1").Range("$E$3,$E$4:$G$4,$G$3") Set CelVoisines(3) = Sheets("Feuil1").Range("$F$3,$F$4:$G$4") Set CelVoisines(4) = Sheets("Feuil1").Range("$D$3:$E$3,$E$4,$D$5:$E$5") Set CelVoisines(5) = Sheets("Feuil1").Range("$D$3:$F$3,$D$4,$F$4,$D$5:$F$5") Set CelVoisines(6) = Sheets("Feuil1").Range("$E$3:$G$3,$E$4,$G$4,$E$5:$G$5") Set CelVoisines(7) = Sheets("Feuil1").Range("$F$3:$G$3,$F$4,$F$5:$G$5") Set CelVoisines(8) = Sheets("Feuil1").Range("$D$4:$E$4,$E$5,$D$6:$E$6") Set CelVoisines(9) = Sheets("Feuil1").Range("$D$4:$F$4,$D$5,$F$5,$D$6:$F$6") Set CelVoisines(10) = Sheets("Feuil1").Range("$E$4:$G$4,$E$5,$G$5,$E$6:$G$6") Set CelVoisines(11) = Sheets("Feuil1").Range("$F$4:$G$4,$F$5,$F$6:$G$6") Set CelVoisines(12) = Sheets("Feuil1").Range("$D$5:$E$5,$E$6") Set CelVoisines(13) = Sheets("Feuil1").Range("$D$5:$F$5,$D$6,$F$6") Set CelVoisines(14) = Sheets("Feuil1").Range("$E$5:$G$5,$E$6,$G$6") Set CelVoisines(15) = Sheets("Feuil1").Range("$F$5:$G$5,$F$6") End Sub
Option Explicit '--------- Module contenant les fonctions nécessaires au jeu ------------------ Function SolucesRecurs(Mot As String, i As Byte) As Boolean Dim j As Byte, indic As Byte, rng As Range If i = 0 Then SolucesRecurs = False Else If i <= Len(Mot) Then Set rng = Voisines(Chemin(UBound(Chemin))).Cells.Find(Mid(Mot, i, 1)) If Not rng Is Nothing And DejaPasseParIci(rng) = False Then 'Debug.Print rng.Address If Len(Voisines(Chemin(UBound(Chemin))).Address) > 4 Then If Not Application.Intersect(Voisines(Chemin(UBound(Chemin))), rng) Is Nothing Then 'Debug.Print Voisines(Chemin(UBound(Chemin))).Address Set Voisines(Chemin(UBound(Chemin))) = SubtractFirstPrinciples(Voisines(Chemin(UBound(Chemin))), rng) 'Debug.Print Voisines(Chemin(UBound(Chemin))).Address End If indic = UBound(Chemin) + 1 ReDim Preserve Chemin(indic) Chemin(indic) = Application.Match(rng.Address, Cellules, 0) - 1 SolucesRecurs = SolucesRecurs(Mot, i + 1) ElseIf UBound(Chemin) = 0 Then SolucesRecurs = False Else indic = UBound(Chemin) - 1 ReDim Preserve Chemin(indic) SolucesRecurs = SolucesRecurs(Mot, i - 1) End If ElseIf Not rng Is Nothing And DejaPasseParIci(rng) = True Then If Not Application.Intersect(Voisines(Chemin(UBound(Chemin))), rng) Is Nothing Then 'Debug.Print Voisines(Chemin(UBound(Chemin))).Address Set Voisines(Chemin(UBound(Chemin))) = SubtractFirstPrinciples(Voisines(Chemin(UBound(Chemin))), rng) 'Debug.Print Voisines(Chemin(UBound(Chemin))).Address End If SolucesRecurs = SolucesRecurs(Mot, i) ' i + 1 ******************** Else If UBound(Chemin) > 0 Then indic = UBound(Chemin) - 1 ReDim Preserve Chemin(indic) '************************************************************* SolucesRecurs = SolucesRecurs(Mot, i - 1) Else SolucesRecurs = False End If End If Else SolucesRecurs = True End If End If End Function Function DejaPasseParIci(Cel As Range) As Boolean Dim i As Integer DejaPasseParIci = False If Cel Is Nothing Then DejaPasseParIci = True: Exit Function For i = LBound(Chemin) To UBound(Chemin) If Cellules(Chemin(i)) = Cel.Address Then DejaPasseParIci = True: Exit For Next i End Function 'Sources : Tushar Mehta (profil : http://dailydoseofexcel.com/archives/author/Tushar-Mehta/) 'http://dailydoseofexcel.com/archives/2007/08/17/two-new-range-functions-union-and-subtract/ Function SubtractFirstPrinciples(Rng1 As Range, Rng2 As Range) As Range On Error Resume Next If Application.Intersect(Rng1, Rng2).Address <> Rng2.Address Then Exit Function On Error GoTo 0 Dim aCell As Range For Each aCell In Rng1 Dim Rslt As Range If Application.Intersect(aCell, Rng2) Is Nothing Then Set Rslt = Union(Rslt, aCell) End If Next aCell Set SubtractFirstPrinciples = Rslt End Function Function Union(Rng1 As Range, Rng2 As Range) As Range If Rng1 Is Nothing Then Set Union = Rng2 ElseIf Rng2 Is Nothing Then Set Union = Rng1 Else Set Union = Application.Union(Rng1, Rng2) End If End Function
Option Explicit
Private requete As String, deb As Double, cible As Range
Const ou As String = "A1"
Const dossier As String = "D:\pijaku" '====>>> remplacer bien sur par le chemin du dossier contenant le dico dico3.txt
Private Sub CommandButton1_Click()
Columns("A").ClearContents
deb = Timer
Application.ScreenUpdating = False
requete = "SELECT mot FROM dico3.csv"
ext_don requete
Columns("A").AutoFit
Application.ScreenUpdating = True
MsgBox " en " & Timer - deb & " seconde(s)"
End Sub
Private Sub CommandButton2_Click()
Columns("A").ClearContents
deb = Timer
Application.ScreenUpdating = False
requete = "SELECT mot FROM dico3.txt WHERE len(mot) = 4"
ext_don requete
Columns("A:IV").AutoFit
Application.ScreenUpdating = True
MsgBox " en " & Timer - deb & " seconde(s)"
End Sub
Private Sub CommandButton3_Click()
Columns("A").ClearContents
deb = Timer
Application.ScreenUpdating = False
requete = "SELECT mot FROM dico3.txt WHERE mot like 'CO%'"
ext_don requete
Columns("A:IV").AutoFit
Application.ScreenUpdating = True
MsgBox " en " & Timer - deb & " seconde(s)"
End Sub
Private Sub CommandButton4_Click()
Columns("A").ClearContents
Dim filtre As String, i As Integer, sep As String, titi
deb = Timer
Application.ScreenUpdating = False
titi = Array("H", "O", "P", "E", "A", "D", "K", "Y", "Z", "L", "N")
For i = 0 To UBound(titi)
sep = IIf(i = 0, "", ",")
filtre = filtre & sep & titi(i)
Next
filtre = "%[" & filtre & "]%"
requete = "SELECT mot FROM dico3.txt WHERE mot not like '" & filtre & "'"
ext_don requete
Columns("A:IV").AutoFit
Application.ScreenUpdating = True
MsgBox " en " & Timer - deb & " seconde(s)"
End Sub
Private Sub CommandButton5_Click()
Columns("A").ClearContents
deb = Timer
Application.ScreenUpdating = False
requete = "SELECT mot FROM dico3.txt WHERE mot like 'CO%' and mot like '%DA%'"
ext_don requete
Columns("A:IV").AutoFit
Application.ScreenUpdating = True
MsgBox " en " & Timer - deb & " seconde(s)"
End Sub
Private Sub CommandButton6_Click()
Columns("A").ClearContents
Dim filtre As String, i As Integer, sep As String, titi
deb = Timer
Application.ScreenUpdating = False
titi = Array("D", "O", "U", "E")
For i = 0 To UBound(titi)
sep = IIf(i = 0, "", ",")
filtre = filtre & sep & titi(i)
Next
filtre = "%[" & filtre & "]%"
requete = "SELECT mot FROM dico3.txt WHERE mot not like '" & filtre & "' and mot like 'CA%'"
ext_don requete
Columns("A").AutoFit
Application.ScreenUpdating = True
MsgBox " en " & Timer - deb & " seconde(s)"
End Sub
Private Sub CommandButton7_Click()
Columns("A").ClearContents
Dim filtre As String, titi
deb = Timer
Application.ScreenUpdating = False
titi = Array("H", "O", "U")
filtre = "%[" & filtre & "]%"
requete = "SELECT mot FROM dico3.txt WHERE mot like 'PR%' and mot like '%[" & _
titi(0) & "]%' and mot like '%[" & titi(1) & "]%' and mot like '%[" & titi(2) & "]%' order by len(mot)"
ext_don requete
Columns("A:IV").AutoFit
Application.ScreenUpdating = True
MsgBox " en " & Timer - deb & " seconde(s)"
End Sub
Private Sub CommandButton8_Click()
Columns("A").ClearContents
deb = Timer
Application.ScreenUpdating = False
requete = "SELECT mot FROM dico3.txt WHERE len(mot) = 5 and mot like 'LU%'"
ext_don requete
Columns("A:IV").AutoFit
Application.ScreenUpdating = True
MsgBox " en " & Timer - deb & " seconde(s)"
End Sub
'==================================================
Sub ext_don(requete As String)
Set cible = Range(ou)
Dim connex As ADODB.Connection, jeu_enr As ADODB.Recordset, i As Integer
If cible Is Nothing Then Exit Sub
Set connex = New ADODB.Connection
On Error Resume Next
connex.Open "Driver={Microsoft Text Driver (*.txt; *.csv)};" & "Dbq=" & dossier & ";" & _
"Extensions=asc,csv,tab,txt;"
On Error GoTo 0
If connex.State <> adStateOpen Then Exit Sub
Set jeu_enr = New ADODB.Recordset
On Error Resume Next
jeu_enr.Open requete, connex, adOpenForwardOnly, adLockReadOnly, adCmdText
On Error GoTo 0
If jeu_enr.State <> adStateOpen Then
connex.Close
Set connex = Nothing
Exit Sub
End If
'For i = 0 To jeu_enr.Fields.Count - 1
'cible.Offset(0, i).Formula = jeu_enr.Fields(i).Name
'Next i
'cible.Offset(1, 0).CopyFromRecordset jeu_enr
cible.CopyFromRecordset jeu_enr
jeu_enr.Close
Set jeu_enr = Nothing
connex.Close
Set connex = Nothing
End Sub
titi = titi = Array("H", "O", "P", "E", "A", "D", "K", "Y", "Z", "L", "N") For i = 0 To UBound(titi) sep = IIf(i = 0, "", ",") filtre = filtre & sep & titi(i) Next filtre = "%[" & filtre & "]%" requete = "SELECT mot FROM dico3.txt WHERE mot not like '" & filtre & "'"
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre questionOption Explicit- modifie les valeurs des constantes en début du code pour correspondre à tes emplacements à toi, etc ...
Private grille As Range
Const nom_de_mon_dico As String = "dico3.txt" ' ===>> nom SEUL du fichier texte "dictionnaire"
Const dossier_de_mon_dico As String = "d:\pijaku" ' =====>> chemin du dossier contenant le dico (sans \ final)
Const feuille_affichage As String = "Feuil3" ' ===>> nom de la feuille où afficher le résultat "réduit"
Const col_affichage As String = "A" ' ====>> colonne où afficher le résultat
Const ou_commencer_affichage As Integer = 1 '===> N° de la ligne où commencer l'affichage
Const affiche_nom_champs As Boolean = False ' ===>> True pour afficher les noms de champs en en-tête, False sinon
Const LA As String * 26 = "ABCDEFGHIJKLMNOPQRSTUV"
Private Sub CommandButton1_Click()
Dim cubes As Variant, Cel As Range, cpt As Byte, carac As Byte, filtre As String
Dim sep As String, lettres_absentes As String, deb As Double, requete As String, indesirables
Randomize Timer
lettres_absentes = LA
If grille Is Nothing Then ' pas la peine de les réinitialser si déjà fait
Set grille = Range("j11:M14")
End If
Application.ScreenUpdating = True
cpt = 0
cubes = Array("ETUKNO", "EVGTIN", "IELRUW", "DECAMP", "EHIFSE", "RECALS", "ENTDOS", "OFXRIA", "NAVEDZ", "EIOATA", "GLENYU", "BMAQJO", "TLIBRA", "SPULTE", "AIMSOR", "ENHRIS")
touille_cubes cubes '================> voir cette proc plus bas
grille.ClearContents
For Each Cel In grille
Cel.Value = Mid(cubes(cpt), CInt((5 * Rnd()) + 1), 1)
lettres_absentes = Replace(lettres_absentes, Cel.Value, "")
cpt = cpt + 1
Next Cel
indesirables = Split(StrConv(lettres_absentes, vbUnicode), Chr(0))
Worksheets(feuille_affichage).Range(col_affichage & ":" & col_affichage).ClearContents
Application.ScreenUpdating = False
deb = Timer
sep = ""
For cpt = 0 To UBound(indesirables) - 1
If cpt > 0 Then sep = ","
filtre = filtre & sep & indesirables(cpt)
Next
filtre = "%[" & filtre & "]%"
requete = "SELECT mot FROM " & nom_de_mon_dico & " WHERE mot not like '" & filtre & "'"
ext_don requete
Application.ScreenUpdating = True
MsgBox " en " & Timer - deb & " seconde(s)"
End Sub
Private Sub touille_cubes(ByRef cubes)
Dim i As Integer, nb As Integer, ou As Integer, temp As String
nb = UBound(cubes)
For i = 0 To nb / 2
ou = Int(((15 - i) * Rnd))
temp = cubes(ou)
cubes(ou) = cubes(nb - i)
cubes(nb - i) = temp
Next
End Sub
Sub ext_don(requete As String)
Dim cible As Range
Set cible = Worksheets(feuille_affichage).Range(col_affichage & ou_commencer_affichage)
Dim connex As ADODB.Connection, jeu_enr As ADODB.Recordset, i As Integer
If cible Is Nothing Then Exit Sub
Set connex = New ADODB.Connection
On Error Resume Next
connex.Open "Driver={Microsoft Text Driver (*.txt; *.csv)};" & "Dbq=" & dossier_de_mon_dico & ";" & "Extensions=asc,csv,tab,txt;"
On Error GoTo 0
If connex.State <> adStateOpen Then Exit Sub
Set jeu_enr = New ADODB.Recordset
On Error Resume Next
jeu_enr.Open requete, connex, adOpenForwardOnly, adLockReadOnly, adCmdText
On Error GoTo 0
If jeu_enr.State <> adStateOpen Then
connex.Close
Set connex = Nothing
Exit Sub
End If
If affiche_nom_champs Then
For i = 0 To jeu_enr.Fields.Count - 1
cible.Offset(0, i).Formula = jeu_enr.Fields(i).Name
Next i
cible.Offset(1, 0).CopyFromRecordset jeu_enr
End If
cible.CopyFromRecordset jeu_enr
jeu_enr.Close
Set jeu_enr = Nothing
connex.Close
Set connex = Nothing
End Sub
prenons par exemple la demande récemment faite à propos d'une cave à vins et de mes réponses/solutions y apportées.Pour avoir suivi ce sujet, j'avoue ne pas trop voir par quel bout tu le saisirais... Conserver les données dans un fichier texte?
si on ne le détruisais pas pour ensuite, à partir de lui, faire d'autres requêtes et obtenir d'autres recordset, hein ... ?C'est exactement ce que je me disais en testant ton code du 16 février à 18:46. Les listes de mots obtenues pourraient encore être réduites.
Const affiche_nom_champs As Boolean = TrueJ'avance bien dans mes tests.
Le plus simple est de dresser ce nouveau jeu d'enregistrement à partir non du premier jeu, mais de la plage Range("A1:AXXX") où il se trouve.Ne serais ce pas plus rapide ou plus simple encore d'utiliser une variable tableau?
Sub TriDicoEnFonctionTirage() Dim Tb(), OccurLettres As Object, Cel As Range, i As Long, j As Byte, Flag As Boolean Set Feuille = Sheets("Feuil3") Set OccurLettres = CreateObject("Scripting.Dictionary") For Each Cel In Range("Grille") OccurLettres(Cel.Value) = OccurLettres(Cel.Value) + 1 Next Cel Set DicoReduit = CreateObject("Scripting.Dictionary") Tb = Feuille.Range("A1:A" & Feuille.Range("A" & Rows.Count).End(xlUp).Row).Value For i = LBound(Tb) To UBound(Tb) 'Ici la zone ou l'on teste... If TEST Then DicoReduit(Tb(i, 1)) = "" Next i ListeMots = DicoReduit.Keys End Sub
... where len(mot) = 4 and mot like '%BO%' ...(donc tous les mots de 4 lettres et contenant "BO")
where len(mot) < 6 and mot like '%BO%' ORDER by len(mot)(tous les mots de moins de 6 lettres, contenant "BO", triés par longueur de mot !)
Sub test() Dim Tb(), Tb_Out(), k As Long, i As Long, t As Single t = Timer Tb = Range("A1:A" & Range("A" & Rows.Count).End(xlUp).Row).Value For i = LBound(Tb) To UBound(Tb) 'Ici la zone ou l'on teste... If Len(Tb(i, 1)) >= 4 And Tb(i, 1) Like "*CA*" Then ReDim Preserve Tb_Out(k) Tb_Out(k) = Tb(i, 1) k = k + 1 End If Next i Range("C2") = UBound(Tb) & " - " & UBound(Tb_Out) & " - " & Timer - t End Sub
If Len(Tb(i, 1)) >= 4 And Tb(i, 1) Like "*CA*" Thenne garde que les mots de plus de 4 lettres possédant la chaine "CA"
WHERE Len(mot) - Len(Replace(mot, "E", "")) < 2A tester
Sub TriDico_Dictionary() Dim Tb(), OccurLettres As Object, Cel As Range, i As Long, j As Byte Dim Flag As Boolean, t As Single t = Timer Set Feuille = Sheets("Feuil3") Set OccurLettres = CreateObject("Scripting.Dictionary") For Each Cel In Range("Grille") OccurLettres(Cel.Value) = OccurLettres(Cel.Value) + 1 Next Cel Set DicoReduit = CreateObject("Scripting.Dictionary") Tb = Feuille.Range("A1:A" & Feuille.Range("A" & Rows.Count).End(xlUp).Row).Value For i = LBound(Tb) To UBound(Tb) Flag = True For j = 1 To Len(Tb(i, 1)) If Len(Tb(i, 1)) - Len(Replace(Tb(i, 1), Mid(Tb(i, 1), j, 1), "")) > OccurLettres(Mid(Tb(i, 1), j, 1)) Then Flag = False: Exit For Next j If Flag Then DicoReduit(Tb(i, 1)) = "" Next i ListeMots = DicoReduit.Keys MsgBox Timer - t & " secondes." End Sub
Sub TriDico_CountIf() Dim Tb(), OccurLettres As Object, Cel As Range, i As Long, j As Byte Dim Flag As Boolean, t As Single t = Timer Set Feuille = Sheets("Feuil3") Set DicoReduit = CreateObject("Scripting.Dictionary") Tb = Feuille.Range("A1:A" & Feuille.Range("A" & Rows.Count).End(xlUp).Row).Value For i = LBound(Tb) To UBound(Tb) Flag = True For j = 1 To Len(Tb(i, 1)) If Len(Tb(i, 1)) - Len(Replace(Tb(i, 1), Mid(Tb(i, 1), j, 1), "")) > WorksheetFunction.CountIf(Range("Grille"), (Mid(Tb(i, 1), j, 1))) Then Flag = False: Exit For Next j If Flag Then DicoReduit(Tb(i, 1)) = "" Next i ListeMots = DicoReduit.Keys MsgBox Timer - t & " secondes." End Sub
Option ExplicitNe pas oublier :
Private grille As Range
Const nom_de_mon_dico As String = "dico3.txt" ' ===>> nom SEUL du fichier texte "dictionnaire"
Const dossier_de_mon_dico As String = "d:\pijaku" ' =====>> chemin du dossier contenant le dico (sans \ final)
Const feuille_affichage As String = "Feuil3" ' ===>> nom de la feuille où afficher le résultat "réduit"
Const col_affichage As String = "A" ' ====>> colonne où afficher le résultat
Const ou_commencer_affichage As Integer = 1 '===> N° de la ligne où commencer l'affichage
Const affiche_nom_champs As Boolean = True ' ===>> True pour afficher les noms de champs en en-tête, False sinon
Const LA As String * 26 = "ABCDEFGHIJKLMNOPQRSTUV"
Private strCon As String
Private Sub CommandButton1_Click()
Dim cubes As Variant, Cel As Range, cpt As Byte, carac As Byte, filtre As String
Dim sep As String, lettres_absentes As String, deb As Double, requete As String, indesirables
Randomize Timer
lettres_absentes = LA
If grille Is Nothing Then ' pas la peine de les réinitialser si déjà fait
Set grille = Range("j11:M14")
End If
Application.ScreenUpdating = False
cpt = 0
cubes = Array("ETUKNO", "EVGTIN", "IELRUW", "DECAMP", "EHIFSE", "RECALS", "ENTDOS", "OFXRIA", "NAVEDZ", "EIOATA", "GLENYU", "BMAQJO", "TLIBRA", "SPULTE", "AIMSOR", "ENHRIS")
touille_cubes cubes '================> voir cette proc plus bas
grille.ClearContents
For Each Cel In grille
Cel.Value = Mid(cubes(cpt), CInt((5 * Rnd()) + 1), 1)
lettres_absentes = Replace(lettres_absentes, Cel.Value, "")
cpt = cpt + 1
Next Cel
Application.ScreenUpdating = True
indesirables = Split(StrConv(lettres_absentes, vbUnicode), Chr(0))
Worksheets(feuille_affichage).Range(col_affichage & ":" & col_affichage).ClearContents
Application.ScreenUpdating = False
deb = Timer
sep = ""
For cpt = 0 To UBound(indesirables) - 1
If cpt > 0 Then sep = ","
filtre = filtre & sep & indesirables(cpt)
Next
filtre = "%[" & filtre & "]%"
requete = "SELECT mot FROM " & nom_de_mon_dico & " WHERE mot not like '" & filtre & "'"
ext_don requete
'msgbox timer - DEB
eclate_par_lettre Worksheets(feuille_affichage)
Application.ScreenUpdating = True
MsgBox " en " & Timer - deb & " seconde(s)"
End Sub
Private Sub touille_cubes(ByRef cubes)
Dim i As Integer, nb As Integer, ou As Integer, temp As String
nb = UBound(cubes)
For i = 0 To nb / 2
ou = Int(((15 - i) * Rnd))
temp = cubes(ou)
cubes(ou) = cubes(nb - i)
cubes(nb - i) = temp
Next
End Sub
Sub ext_don(requete As String)
Dim cible As Range
Set cible = Worksheets(feuille_affichage).Range(col_affichage & ou_commencer_affichage)
Dim connex As ADODB.Connection, jeu_enr As ADODB.Recordset, i As Integer, jeu_enr1 As ADODB.Recordset
If cible Is Nothing Then Exit Sub
Set connex = New ADODB.Connection
On Error Resume Next
connex.Open "Driver={Microsoft Text Driver (*.txt; *.csv)};" & "Dbq=" & dossier_de_mon_dico & ";" & "Extensions=asc,csv,tab,txt;"
On Error GoTo 0
If connex.State <> adStateOpen Then Exit Sub
Set jeu_enr = New ADODB.Recordset
On Error Resume Next
jeu_enr.Open requete, connex, adOpenForwardOnly, adLockReadOnly, adCmdText
On Error GoTo 0
If jeu_enr.State <> adStateOpen Then
connex.Close
Set connex = Nothing
Exit Sub
End If
If affiche_nom_champs Then
For i = 0 To jeu_enr.Fields.Count - 1
cible.Offset(0, i).Formula = jeu_enr.Fields(i).Name
Next i
cible.Offset(1, 0).CopyFromRecordset jeu_enr
End If
cible.CopyFromRecordset jeu_enr
jeu_enr.Close
Set jeu_enr = Nothing
connex.Close
Set connex = Nothing
End Sub
Private Sub eclate_par_lettre(affiche As Worksheet)
'deb = Timer
Dim DL As Long, i As Long, lettre As String, cpt As Long, tablo, temp
With affiche
DL = .Range(col_affichage & Rows.Count).End(xlUp).Row
tablo = .Range(col_affichage & ou_commencer_affichage & ":" & col_affichage & DL)
.Cells.ClearContents
ReDim temp(1 To DL, 1 To 2)
temp(1, 1) = "coucou"
lettre = Mid(tablo(2, 1), 1, 1)
cpt = 1
For i = 2 To DL
Do While Mid(tablo(i, 1), 1, 1) = lettre
temp(cpt, 1) = tablo(i, 1)
cpt = cpt + 1
If i = DL Then Exit Do
i = i + 1
Loop
affiche.Range(lettre & "1:" & lettre & DL) = temp
ReDim temp(1 To DL, 1 To 2)
lettre = Mid(tablo(i, 1), 1, 1)
temp(1, 1) = tablo(i, 1)
cpt = 2
Next
End With
'MsgBox Timer - deb
Erase temp
End Sub
Sub TroisLettres() Dim cel As Range, cel2 As Range, cel3 As Range, Dico3L As Object, Liste(), DicoReduit As Object, i As Long, cpt As Long cptResult = 0 'A ce stade, nous n'avons pas encore de résultat. Set Dico3L = CreateObject("Scripting.Dictionary") Set DicoReduit = CreateObject("Scripting.Dictionary") For Each cel In Range("Grille") For Each cel2 In cel.Offset(-1, -1).Resize(3, 3) If cel2.Value <> "" And cel2.Address <> cel.Address Then For Each cel3 In cel2.Offset(-1, -1).Resize(3, 3) If cel3.Value <> "" And cel3.Address <> cel2.Address And cel3.Address <> cel.Address Then Dico3L(cel3.Value & cel2.Value & cel.Value) = "" End If Next cel3 End If Next cel2 Next cel With Sheets("Feuil3") Liste() = .Range("A1:A" & .Range("A" & Rows.Count).End(xlUp).Row).Value For i = LBound(Liste) To UBound(Liste) If Dico3L.Exists(Left(Liste(i, 1), 3)) Then If Len(Liste(i, 1)) = 3 Then 'stockage des solutions de 3 lettres ReDim Preserve Solutions(cptResult) Solutions(cptResult) = Liste(i, 1) cptResult = cptResult + 1 Else 'sinon "réduction" de la liste des mots DicoReduit(Liste(i, 1)) = "" End If End If Next i .Columns(col_affichage).ClearContents .Range(col_affichage & 1).Resize(DicoReduit.Count) = Application.Transpose(DicoReduit.keys) End With End Sub
Private Solutions() As String Private cptResult As Long
Private Sub CommandButton1_Click() 'Blablabla 'Appel des trois procédures permettant d'établir la liste des mots, par colonne en feuille d'affichage 'recherche dans le dictionnaire txt, avec une requête de filtre ext_don requete 'tri du résultat en fonction de tous les chemins de 3 lettres possibles dans la grille Call TroisLettres 'répartition, par ordre alphabétique, de la liste triée, en 26 colonnes eclate_par_lettre Worksheets(feuille_affichage) Application.ScreenUpdating = True MsgBox " en " & Timer - deb & " seconde(s)" End Sub
" " " " " "
O E N Y " O E N Y "
O L T R " O L T R "
E S A A " E S A A "
F T V R " F T V R "
" " " " " "
Option Explicit Private Sub Workbook_Open() Initialisation 'cf Module Procédures End Sub
Option Explicit Public CelVoisines(15) As String Public rngCellules(15) As Range 'Utilité : Stockage, dans deux variables tableaux déclarées As Range : 'rngCellules(15) = Objets Range de chacune des cellules composant la grille 'CelVoisines(15) = Strings composés des adresses des cellules voisines ET non vides de chaque rngCellules 'A appeler depuis le Workbook_Open() : Sub Initialisation() Dim rngCel As Range, rngAdja As Range, i As Byte Erase CelVoisines Erase rngCellules i = 0 For Each rngCel In Range(StrGrille) Set rngCellules(i) = rngCel For Each rngAdja In rngCellules(i).Offset(-1, -1).Resize(3, 3) If rngAdja.Value <> "" And rngAdja <> rngCellules(i).Address Then CelVoisines(i) = CelVoisines(i) & ";" & rngAdja.Address Next rngAdja CelVoisines(i) = Right(CelVoisines(i), Len(CelVoisines(i)) - 1) i = i + 1 Next rngCel End Sub 'test pour utilisation dans boucle (récursive ou non) Sub essai() Dim cellu As String, rngPosition As Range cellu = Split(CelVoisines(3), ";")(4) Set rngPosition = Sheets("Feuil1").Range(cellu) End Sub
parce qu'une fois atteinte cette limité, inutile de chercher du "plus long possible"oui c'est sûr.
TD
P EH R
Dim toto, titi As Integeraboutit à ne typer en Integer que titi (toto étant typé en variant par défaut de précision sur le type)
Dim toto as integer, titi As Integer
Tu as à corriger ces notations un peu partout. Cela agilisera ton projet.
For i = 1 To 4et utiliser à la place et avantageusement le "tout-cuit" VBA/Excel :
For j = 1 To 4
Cells(i, j) = Tirage(i, j)
Next j
Next i
Range("A1:D4").Value = Tirage
Public grille_du_jeu As rangeet dans ton code (après chargement) :
Set grille_du_jeu = worksheets("tirage"):Range("A1:D4")tu pourras alors ainsi te référer quand tu le voudras dan,s ton code à cette plage, au lieu de cells(..,..)
Private Nombre_Mots As LongIl convient à ce propos de garder à l'esprot que le défaut de déclaration de portée est Public.
Private Mot, Partie As String
Private Debut, Noeud, Noeud_Actuel As Classe_Noeud
Private Maillon, Solution As Classe_Solution
Private Tirage(1 To 4, 1 To 4) As String
Private Dico_Charge As Boolean
If Dico_Charge Then Exit Subet en toute dernière ligne (avant le end sub) :
Set Noeud_Actuel = Nothing
Set Solution = Nothing
Erase Pris
14 févr. 2014 à 20:23
Ce que j'ai dit plus haut n'est pas malin, dans la mesure où les autres (ceux qui n'auraient ni le dico, ni le classeur, ne pourraient suivre !
On va donc procéder en deux étapes :
étape 1 : faire votre moulinette pour arriver à un fichier .txt, nommé dico3.txt et revêtant cet aspect :
Si vous voulez éviter de faire cette moulinette (facile) pour y parvenir, je vous la donne ...
Le transformer ensuite en y ajoutant une ligne (par le bloc-notes, par exemple) pour avoir ceci :
Observer la ligne ajoutée (elle dit "mot").
Je continue lorsque vous m'aurez fait savoir que vous êtes maintenant prêts, ce fichier texte ayant ainsi été constitué.
Modifié par ucfoutu le 14/02/2014 à 23:54
Testé : recherche des mots ne contenant aucune de ces lettres : "H", "O", "P", "E", "A", "D", "K", "Y", "Z", "L", "N" ===>> liste de 287 mots extraite du dico en 0,75 secondes ! Intéressant, non ?
PS ! et inutile d'attendre que la grille soit remplie pour déterminer les lettres de l'alphabet qui y sont absentes.
Il suffit, juste avant le tirage, de constituer une collection (A,B,C,D ....X,Y,Z) puis, à chaque lettre tirée (dans le module de tirage) de retirer cette lettre de la collection (avec au besoin un on error pour le cas où déjà plus dans la collection). Routes celles restant dans la collection sont ainsi les lettres de l'alphabet absentes de la grille..
De cette manière, le joueur n'a même pas le temps de dire ouf et ne s'aperçoit même pas du travail fait en même temps que le tirage.
15 févr. 2014 à 08:03
Cette première réduction du dico doit effectivement faire gagner du temps par la suite.
Je reviens vers vous une fois testé.
PS: j'ai effectué plusieurs centaines de tirage pour essayer de trouver aléatoirement une grille ayant au moins un mot de onze lettres ou plus. J'en ai trouvé une! Je la posterai plus tard.
Modifié par ucfoutu le 15/02/2014 à 08:27
tu as eu de la patience ! J'avais essayé et abandonné.
Il reste qu'il sera assez rare de "tomber" sur une telle grille. Dans la très grande majorité des cas : la grille comportant 16 lettres distinctes maximum (car moins si lettres en double, triple, etc..) et l'alphabet 26, on pourra écarter un grand nombre de mots qui contiennent l'une des au moins 10 lettres absentes. Ce nombre sera très rarement faible (et la recherche sera alors ralentie) et très souvent élevé (et la recherche sera alors accélérée de manière significative).
Dites-moi tous les deux lorsque vous aurez fait votre dico comme dit juste plus haut.
Je vous montrerai alors code et requêtes non dénuées d'intérêt.
15 févr. 2014 à 08:32
J'ai fait une boucle de 100 tirages qui se stoppe si un mot de onze lettres au moins existe.
J'ai lancé cette boucle toute la soirée jusqu'à ce qu'elle obtienne un résultat.
Pour le dico, le format type csv me va très bien vu que je le charge dans une liste de string.