VBA Loop



  • VBA Loop
    di Raffaele_1953 (utente non iscritto) data: 12/11/2013 12:31:05

    Buona giornata a tutti

    Devo fare un Do While j <= URiga1 (Uriga1 è riferito a 8 max 64)
    Mi ritrovo un problema con le Collection

    Capita una volta ogni 10/20 volte che non può estrare un numero perchè ho messo dei "paletti restritivi"

    La mia domanda sarebbe, possso uscire dal ciclo se dopo 1000 tentativi non ha trovato la combinazione?



  • di gaetanopr (utente non iscritto) data: 12/11/2013 12:35:55

    Ciao Raffaele non ho capito bene, ma comunque per uscire dal ciclo puoi usare un contatore che si incrementa ad ogni passaggio
    esempio:

     
    Do While j <= URiga1 Or contatore < 1000
    contatore = contatore + 1
    Loop



  • di Grograman (utente non iscritto) data: 12/11/2013 13:03:56

    Ciao Raffaele!

    Sposo la soluzione di Gaetano, moooooooolto utile per evitare i loop infiniti


    Tutti i miei cicli quando ho iniziato a studiare VBA andavano in loop infinito



  • di Raffaele_53 (utente non iscritto) data: 12/11/2013 13:24:05

    Sempre nella mia ignoranza
    (J) non aumenta se la condizione non viene rispettata
    Di sicuro come avete scritto, posso combinare un qualcosa, ma dovrei dire "solo all'ultima combinazione( fai mille tentantivi ) non riesci esci.

    Ps (J) fà gia diversi tentativi per ogni estratto
    Siccome le possibilità sono ancora ampie (non fare nulla)
    L'ultima riga mi da problemi, se il numero estratto non mi dà un risultato va in Loop
    Come potrei dirgli "questa è l'ultima possibilità, dopo 1000 tentativi" Goto ERRORE dove metterei un msgbox "riprova"



  • di Raffaele_53 (utente non iscritto) data: 12/11/2013 13:28:13

    Solo all'ultima combinazione.
    Possono essere 8 o 64, non posso interrompere il ciclo qui
    Solo se la riga = ultima
    Cerca di trovare un abbinamento ( dopo 100/1000 tentativi) esci dal Loop
    Grazie mille a Voi, Gaetanopr e Grograman



  • di gaetanopr (utente non iscritto) data: 12/11/2013 13:35:26

    Quindi se ho capito bene, puoi inserire un If Then all'interno del Loop, in modo da incrementare il contatore solo quando si arriva all'ultima riga, vado bene???
     
    Do While j <= URiga1 Or contatore < 1000
     If riga = ultima Then contatore = contatore + 1
    Loop



  • di gaetanopr (utente non iscritto) data: 12/11/2013 13:39:20

    In questo modo il contatore inizierà la sua conta non appena si arriverà all'ultima riga, quindi dall'ultima riga avrai a disposizione altri 1000 passaggi e poi esce dal loop

    cit>>Tutti i miei cicli quando ho iniziato a studiare VBA andavano in loop infinito
    a chi lo dici....



  • di Raffaele_53 (utente non iscritto) data: 12/11/2013 14:16:40

    Ciao gaetanopr
    In teoria e sicuramente in pratica hai ragione.
    Usando l'ultimo Tuo codice dovrebbe funzionare.

    Una domanda se posso? Ha superato le mille possibilità per l'ultima riga
    In teoria sarebbe l'ultima delle 8/64 righe.....Giusto?


     
    Do While j <= URiga1 Or contatore < 1000
          If riga = Ultima Then contatore = contatore + 1
    	If contatore > 1000 Then contatore = contatore + 1 else Goto ERRORE
          End if
    ...ESEGUI
    Loop



  • di Raffaele_53 (utente non iscritto) data: 12/11/2013 14:19:15

    >>>If contatore > 1000 Then contatore = contatore + 1 else Goto ERRORE
    If contatore < 1000 Then contatore = contatore + 1 else Goto ERRORE



  • di gaetanopr (utente non iscritto) data: 12/11/2013 14:27:14

    cit>>Una domanda se posso? Ha superato le mille possibilità per l'ultima riga
    In teoria sarebbe l'ultima delle 8/64 righe.....Giusto?
    Giusto però dovrebbe essere scritta in questo modo, 1 più 1 meno

     
    Do While j <= URiga1 Or contatore < 1000
          If riga = Ultima Then contatore = contatore + 1 ' se minore continua ad incrementare ed esegue
    	If contatore = 1000 Then Goto ERRORE           '  se nuguale a 1000 Goto
     ...ESEGUI
    Loop



  • di Raffaele_53 (utente non iscritto) data: 12/11/2013 14:29:52

    OK, ci provo
    Grazie per adesso



  • di Raffaele_53 (utente non iscritto) data: 12/11/2013 16:29:53

    Ciao gaetanopr
    Non ho ancora applicato la soluzione sopra, vorrei chiederti un'altro consiglio.
    Questo è solo una parte del codice.
    Riga1 = Uriga1/2

    Dovrei fare una specie di doppia estrazione.
    Prima le righe dispari con righe dispari
    Poi le righe pari con righe pari

    Come ho detto sopra "se arriva all'ultima riga e non riesce" dobiamo ricominciare il tutto.
    Se l'ultimo numero estratto fosse Riga1 (la condizione è scritta in ),va in loop
    If ws2.Cells(R, C1) + Riga1 <> ws2.Cells(nCasual3, Col).Value Then

    Una cosa vorrei sapere?
    A parte di fare insieme sia la riga sinistra con quella a destra.
    Potrei scrivere solo quelle di sinistra
    Dopo scrivo quelle di destra (sempre con il loop a 1000), nel caso di ultima riga?

    Quale è la strada più veloce/sicura in base alle condizioni scritte nel codice?
    Fare sinistra e destra insieme (così avrei il parametro di controllare se il valore di sinistra non ci siano certe condizioni vere)

    Posso dire alla Collection, tirami fuori solo dispari o pari?
    Potrei prima presentare la colonna di sinistra (senza loop)
    Dopo presentare la colonna di destra con il loop
    Ricercare il valore a sinistra e confrontarlo.
    Allego un files, premi F8 continuamente e vedi cosa fà in K2:R17



  • di gaetanopr (utente non iscritto) data: 12/11/2013 19:14:43

    Ciao Raffaele potresti spiegare cosa fa attualmente la macro e cosa dovrebbe fare?, magari si possono trovare altre strade ma così mi viene difficile interpretare il codice



  • di gaetanopr (utente non iscritto) data: 12/11/2013 19:28:00

    Se ho capito bene, dovrebbe compilare le colonne K-L-M-N e O-P-Q-R prelevando i dati dalla colonna B giusto?
    I criteri quali sono?, quanti ne devi prelevare? 16 e 16 ?
    Se è così posso provare a scriverti un altro codice



  • di Raffaele_53 (utente non iscritto) data: 12/11/2013 20:16:42

    Ciao Gaetanopr
    Le Collection prelevano i dati dalla riga G , nel codice......Col = 7
    I futuri estratti, saranno tutti quelli presenti in colonna G e i dati in H:I

    Condizioni: non potrà essere il numero scelto + la meta = 16 (nella riga destra)
    Viene estratto il numero 1, l'altro non potrà essere il 17, 2 18, 3 19 ecc ecc
    Viene estratto MASTER, l'altro non potrà essere MASTER (nella riga destra)...forse qualcun'altra ancora.

    Però, la domanda principale è, posso velocizzarlo senza loop?
    Magari chiedere alla Collection di estrarmi solo numeri pari o dispari?
    Per il resto credo d'aver capito il tutto.



  • di Raffaele_53 (utente non iscritto) data: 12/11/2013 20:49:13

    Ciao Gaetanopr
    Condizioni: non potrà essere il numero scelto + la meta = 16 >>>scritto nella parte destra
    Viene estratto MASTER, l'altro non potrà essere MASTER >>>scritto nella parte destra

    Ps. Destra intendo colonne O:R



  • di Vecchio Frac data: 12/11/2013 20:57:49

    cit. "la domanda principale è, posso velocizzarlo senza loop? "
    ---> Dipende, alle volte un ciclo è preferibile rispetto ad altri artifici.

    cit. "Magari chiedere alla Collection di estrarmi solo numeri pari o dispari?"
    ---> Ma una Collection, non avendo un indice posizionale per i suoi elementi, non potrà essere ciclata su numeri pari o dispari. Al massimo puoi fare un test If col contenuto della Collection stessa e saltare una lettura sì e una no di ogni elemento.





  • di Raffaele_53 (utente non iscritto) data: 12/11/2013 21:11:46

    Ciao VF
    ---> Dipende, alle volte un ciclo è preferibile rispetto ad altri artifici.

    Puoi, per favore spiegarmelo?
    Hai qualche altra idea? in proposito.

    Pensavo solo alle Collection, per superare il quesito.



  • di gaetanopr (utente non iscritto) data: 12/11/2013 21:12:00

    cit>>>
    Magari chiedere alla Collection di estrarmi solo numeri pari o dispari?
    Per il resto credo d'aver capito il tutto.

    Se in questo modo puoi risolvere puoi usare due array, uno per i pari e uno per i dispari, e poi puoi popolare le celle usando gli array e non la collection
    ti posto un esempio
     
    On Error GoTo fine
       For n = 1 To 32
        Randomize
        Casuale = Int((32 * Rnd) + 1)
        Arr.Add Casuale, CStr(Casuale)
         If Casuale Mod 2 = 0 Then
           P = P + 1
           ReDim Preserve Pari(1 To P)
           Pari(P) = Casuale
         Else
           D = D + 1
           ReDim Preserve Dispari(1 To D)
           Dispari(D) = Casuale
         End If
    fine:
    If Err.Number = 457 Then
    n = n - 1
    End If
     Resume Next
       Next n
       
    



  • di Vecchio Frac data: 12/11/2013 21:14:22

    Vorrai scusare ma non ho Excel qui (pc ancora in assistenza e devo rassegnarmi a XUbuntu su portatile del '15-'18).
    A volte un semplice ciclo Do Loop o For Next è meglio che lambiccarsi con test condizionali... tutto questo solo in teoria.
    Nel merito del problema, non ho studiato il caso ma vedo che sei in ottime mani (gaetano ha spesso delle illuminazioni) :)





  • di gaetanopr (utente non iscritto) data: 12/11/2013 21:19:11

    Scusa Raffaele devo rivedere l'esempio l'ho scritto velocemente non dovrebbe essere corretto



  • di Vecchio Frac data: 12/11/2013 21:28:18

    @gaetano
    Ma, un array a due dimensioni, la prima per i pari e la seconda per i dispari? Senza passare dalla Collection... e senza testare l'errore 457 (bleah ^_^)





  • di Raffaele_53 (utente non iscritto) data: 12/11/2013 21:36:15

    Gaetanopr
    Non diventare scemo come me.
    La domanda non è sulle righe presenti in "G"
    Posso migliorarlo senza Loop

    Mi hai già dato la risposta dieci post fà.
    Io continuavo a chiederti una cosa PARI/DISPARI che fà già la macro.

    Domandavo solo se si poteva in qualche modo (farla piu veloce e senza loop)
    Credo daver capito, sia meglio completare la parte sinistra, poi eseguo quella destra (però alla fine ci metto un 1000 per evitare un loop.



  • di gaetanopr (utente non iscritto) data: 13/11/2013 00:17:54

    Ti allego il file con una macro che estrae i dati e inserisce nella colonna più a destra gli estratti pari e nell'altra gli estratti dispari, la macro và avanti fino a quando non vengono compilate tutte e 16 le righe oppure fino a 100 cicli, dopodichè si ferma e avvisa se l'estrazione è stata terminata o meno, nel 80% dei casi è completa, nota positiva che non va in loop.
    Non so se era quello che volevi ho cercato di seguire le tue indicazioni, cioè i due criteri

    Ciao



  • di gaetanopr (utente non iscritto) data: 13/11/2013 08:55:00

    cit>>Ma, un array a due dimensioni, la prima per i pari e la seconda per i dispari? Senza passare dalla Collection... e senza testare l'errore 457 (bleah ^_^)
    Ciao V.F l'uso della collection più che altro ci serve per metterli in ordine casuali prelevandoli tutti, se poi questo non fosse necessario, si potrebbe evitare usando solamente una matrice per i pari e dispari.



  • di Raffaele_53 (utente non iscritto) data: 13/11/2013 11:45:39

    Ciao Gaetanopr
    Nulla da eccepire sul lavoro che hai fatto, però c'è un particolare che forse Ti ho spiegato male.

    Nel Tuo codice crei due Array (pari dispari), dopo li metti in tabella, mà io dovrei fare dei controlli prima.

    Io (prima facevo riga x riga) ripensandoci adesso lo farò prima nella colonna di sinistra (nella quale non devo fare controlli), poi farò quella di destra (solo su quella di destra metterò quello che mi hai scritto qualche post fà per bloccare il Loop).

    Facevo in questo modo: i numeri da estrare possono essere 8/16/32/64 in questo caso sono 32/16 righe da compilare.
    Estraggo il primo numero dispari a sinistra, estraggo un'altro numero dispari da mettere sulla destra.
    Su questo numero (prima d'assegnarlo alla Collection) faccio alcune verifiche (non può essere maggiore di 16 in confronto di quello a sinistra) e (non può essere della stessa squadra).
    Quando fatto continua sulla prossima riga sempre con numeri dispari, pertanto si dovranno compilare 8 righe di numeri sinistri (già qui all'ottava riga d'abbinamento, rischio un loop. Perchè se gli ultimi due numeri dispari da estrare fossero 1-17 il codice va in loop). Finiti i numeri dispari passa a quelli pari. Altre 8 righe da compilare con solo numeri pari e anche qui all'ottava riga rischio ancora un Loop (ex fossero rimasti il 2-18 che non può abbinare per via della restrizione 2+16 = 18).

    Questo è quanto sono riuscito a fare sinora (chiedevo solo se ci fosse un modo più tranquillo e senza loop), La risposta l'ho già ottenuta alcuni post fà. Grazie di tutto

    Ps. Casomai volessi far prove sul Tuo codice, come potrei usufruire del
    Dim Pari(1 To 16) As Integer, Dispari(1 To 16) As Integer
    Quando in realtà non conosco ancora quanti giocatori sono inscritti? A meta codice, potrei passargli il parametro W ?
    Uriga1 = 32
    W = Uriga1 / 2
    Dim Pari(1 To W) As Integer, Dispari(1 To W) As Integer (credo di si)



  • di gaetanopr data: 13/11/2013 12:58:46

    cit>>Ps. Casomai volessi far prove sul Tuo codice, come potrei usufruire del
    Dim Pari(1 To 16) As Integer, Dispari(1 To 16) As Integer
    Quando in realtà non conosco ancora quanti giocatori sono inscritti? A meta codice, potrei passargli il parametro W ?
    Uriga1 = 32
    W = Uriga1 / 2
    Dim Pari(1 To W) As Integer, Dispari(1 To W) As Integer (credo di si)

    Ciao Raffaele, in effetti il mio file è impostato per 32 partecipanti ma ci vuole poco a renderlo dinamico
    innanzitutto
    Dim Pari(1 To 16) As Integer, Dispari(1 To 16) As Integer
    diventa
    Dim Pari() As Integer, Dispari() As Integer
    in un secondo momento dopo che ti ricavi Uriga devi ridimensionarlo, ma usando l'istruzione Redim
    Redim Pari(1 To W)
    Io non ho effettuato controlli in quanto associando un numero pari ad uno dispari, la differenza sarà sempre dispari quindi diversa da 16, l'unico controllo che faccio è sul fatto che i partecipanti siano di squadre diverse.

    CIT>>non può essere maggiore di 16 in confronto di quello a sinistra)
    Prima hai detto che si dovevano evitare accoppiamenti come
    1-17, 2-18, 3-19
    ma dire che non può essere maggiore di 16 in confronto di quello a sinistra, è diverso, oltretutto nella tua macro viene rispettato il vincolo delle squadre diverse, i vincoli degli accoppiamenti(1-17 ect), ma non quest'ultimo che hai detto infatti vengono estratti partecipanti con numerazione 12-32 dove la differenza è di 20 cioè maggiore di 16
    In definitiva l'accoppiamento 12-32 è possibile? se e si il file che ti ho allegato dovrebbe andare bene con le dovute modifiche per renderlo dinamico, altrimenti si dovrebbe aggiungere quest'altra condizione





  • di Raffaele_53 (utente non iscritto) data: 13/11/2013 13:23:06

    Adesso mi è chiaro anche il Redim Pari(1 To W)

    Per l'altra informazione che Ti ho passato in modo errato. Chiedo scusa
    Intendevo che il numero di sinistra ex = 1, quello di destra non può essere 1+16 = 17
    Che la differenza sia diversa dal numero di sinistra +16 (nel caso di 32 giocatori)

    Comunque ho fatto, quanto scritto nei primi post (ho impostato 100 invece di 1000) e anche veloce.
    Funziona benissimo, qualche volta mi appare il msgbox dove deve ricominciare da zero, mà non va più il loop
    Di nuovo grazie mille.



  • di gaetanopr (utente non iscritto) data: 13/11/2013 23:15:52

    Ok Raffaele alla prossima