MACRO Combinazioni mancanti



  • MACRO Combinazioni mancanti
    di isasa74 data: 19/03/2016 12:03:09

    Salve Ragazzi,

    per iniziare grazie a tutti per la grande opportunita' offerta dal Forum e per l'aiuto che date a tanti utenti.

    Avrei un bisogno estremo di una macro o un processo VBA che partendo dai dati delle due colonne A:A e B:B riesca a trovare le combinazioni mancanti fra le due colonne.
    In pratica nella Colonna A:A ho dei part number che vitualmente possono essere infiniti (di solito attorno ai 50 mila) mentre la Colonna B:B e' popolata da nove localita' espresse in codici (NL10; AU21; CH20;NL20;NO20;NZ20;RO20;SE20;ZA20).

    Tutti i part numbers dovrebbe essere ripetuti nove volte, una volta per ogni localita', con la prima, NL10, che e' sempre presente.
    Per molti part number della lista mancano delle localita' e mi servirebbe uan codice VBA che indichi quali sono quelle mancanti.

    Ho allegato un esempio su foglio excel .

    Non sono bravo con il VBA sto muovendo I primi passi, ma sono pratico con le macro, serve molta pazienza per favore ma dal mio lato metto un impegno estremo per non farmi odiare

    Grazie in anticipo



  • di patel data: 19/03/2016 15:55:38

    io non ho capito bene, ma se tu pratico con le macro descrivi le operazioni da fare col linguaggio che conosci e io te le traduco in vba





  • di isasa74 data: 19/03/2016 19:46:53

    Ciao Patel,

    Grazie mille per la tua disponibilita'.

    Il fatto e' che con la macro non riesco a farlo ecco perche' sono qui :).
    Parto dal pressuposto che hai gia' visto l' allegato giusto?
    Ne ho ora allegato uno NEW dove nel primo Tab hai " PRIMA" del VBA e nel secondo Tab "DOPO" il VBA.

    Nel sistema con il quale lavoro, periodicamente devo controllare che tutti i part number (prodotti) siano disponibili in tutte le locazioni (Plant), ma tutto quello che ho a disposizione sono i dati che vedi nelle prime due colonne dell'esempio (A:B).
    Nella Colonna A ci sono i part number e in quella B le localita' per le quali quei part number sono gia' disponibili. (NL10;NL20 etc.)

    Quindi nella Colonna A lo stesso part number puo' essere ripetuto fino a nove volte, tante quante sono le localita' disponibili sul sistema.
    Non tutti i part number sono pero' ripetuti 9 volte perche', ed e' questo il punto, molti fra questi non sono estesi a tutte le localita' ed io devo estenderli.
    Il VBA dunque dovrebbe controllare che ogni valore unico in A:A cioe', ogni ogni singolo part number, sia ripetuto sempre in A:A 9 volte e quando non lo e' il VBA dovrebbe riportate idealmente nella riga nella quale appare per la prima volta quel dato part number le locazioni che mancano in B:B, cosi' io posso estenderle sul sistema.

    Per esempio nel file allegato:

    Da A4:A13 abbiamo il part number 1xxx.000 ripetuto nove volte e in B4:B13 tutte e nove le localita', in questo caso il VBA non deve far nulla, o se vogliamo essere perfezionisti potrebbe dare un OK nelle celle da D4:K4.

    Al contrario da A13:A17 il part number 1xxx.001 e' ripetuto solo 4 volte ed in questo caso il VBA dovrebbe cercare quale sono le localita' mancanti in B13:B17 (i codici di localita' mancanti sono: AU21-CH20-SE20-ZA20) e assegnare un " missing" rispettivamente nelle Celle : D13,E13;J13;K13.

    Ovviamente io vedo il lavoro in questa maniera ma se a te per ragioni pratiche conviene organizzar eil VBA in maniera diversa, sempre partendo dale due colonne A e B per me va benissimo :)

    ancora Grazie mille








  • di Raffaele_53 data: 19/03/2016 23:36:15

    Da provare  (valido solamente se colonna A in ordine)
     
    Sub elabora()
    Dim Ur, X, Y, Tot, Rg As Object
    Ur = Range("A" & Rows.Count).End(xlUp).Row
    For X = 4 To Ur
        Range(Cells(X, 4), Cells(X, 11)) = "Missing"
        Tot = Application.WorksheetFunction.CountIf(Range("A:A"), Cells(X, 1).Value) - 1
            For Y = 1 To Tot
                Set Rg = Range("C3:K3").Find(Cells(X + Y, 2), LookIn:=xlValues, LookAt:=xlWhole)
                If Not Rg Is Nothing Then
                    r = Rg.Column
                    If Cells(X, r) = "Missing" Then Cells(X, r) = "OK" Else Cells(X, r) = "Doppia"
                End If
            Next Y
        X = X + Tot
    Next X
    End Sub



  • di isasa74 data: 20/03/2016 12:05:09

    Hi Raffaele_53,

    Grazie, funziona alla grande veramente.
    Ho solo due richieste per favore, ma se non hai tempo o ti viene troppo complesso non fa nulla, per me sei gia' stato un amico!

    1) E' possibile avere invece della parola " missing" la plant che manca?

    2) Potresti per favore aggiungere la descrizione per ogni istruzione del codice? cosi' posso studiare e se nel futuro devo aggiungere o modificare qualcosa magari me la posso cavare da solo con un po' di fortuna.

    Grazie Raffaele e Patel siete stati molto gentili ad interessarvi del mio problema.



  • di Raffaele_53 data: 20/03/2016 19:12:00

    Nulla d'impegnativo, prima incollavo la parola Missing, adesso incollo il range D3:K3 ed OK se esiste
     
    Sub elabora()
    Dim Ur, X, Y, Tot, Rg As Object
    Ur = Range("A" & Rows.Count).End(xlUp).Row
    For X = 4 To Ur
        Range(Cells(3, 4), Cells(3, 11)).Copy
        Cells(X, 4).PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
        Tot = Application.WorksheetFunction.CountIf(Range("A:A"), Cells(X, 1).Value) - 1
            For Y = 1 To Tot
                Set Rg = Range("C3:K3").Find(Cells(X + Y, 2), LookIn:=xlValues, LookAt:=xlWhole)
                If Not Rg Is Nothing Then
                    r = Rg.Column
                    Cells(X, r) = "OK"
                End If
            Next Y
        X = X + Tot
    Next X
    End Sub



  • di isasa74 data: 20/03/2016 21:51:22

    Grazie Raffaele , perfetto, per favore potresti inserire i commenti nel codice? please!! :)

    GRAZIE INFINITE






  • di Mohican1989 data: 21/03/2016 00:50:03

    Non entro nel merito del codice, tento di spiegarti a parole mie quanto esposto da Raffaele che saluto.

    Ho cercato di spiegarmi al meglio ma sicuramente sia nella guida di questo forum che online troverai informazioni + dettagliate e meglio spiegate.
     
    Sub elabora()
    Dim Ur, X, Y, Tot, Rg As Object 'Dichiarazione delle variabili come oggetti.
    Ur = Range("A" & Rows.Count).End(xlUp).Row 'UR immagino stia per ultimariga
    'letteralmente il codice esegue questa azione, prende in considerazione un range in questo caso A ed il numero di righe del foglio (rows.count) quindi va alla cella A65536 e proprio come se schiacciassi CTRL + freccia su indicata  dal codice (Xlup) torna fino alla prima cella non vuola e con la proprietà .row la variabile UR prende proprio il valore di riga della prima cella non vuota partendo dal basso, nel tuo caso la riga 49.
    For X = 4 To Ur 'usiamo la variabile X che dovrà avere valore diversi per poter effettuare le verifiche o 'operazione su più celle quindi la X ha come valore di partenza il 4 e cambiera valore di 1 unità fino ad 'arrivare (to UR) a 49
        Range(Cells(3, 4), Cells(3, 11)).Copy 'vengono copiate le celle delle PLANTS nel rigo di partenza
    'Range indica uno spazio, un intervallo, come su excel devi indicare 2 celle, in questo caso cells(3,4) ovvero la cella che corrisponde alla riga 3 e alla colonna 4 (D3) fino alla cella K3.
        Cells(X, 4).PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
    'Questo comando equivale, dopo aver copiato un range, a cliccare con il tasto destro del mouse e cliccare su
    'incolla speciale. In incolla speciale ci sono diversi opzioni come ad esempio cosa incollare, valori, formati etc in questo caso abbiamo dato l' informazione "incolla valori" xlpastevalues. Le altre opzioni non sto a spiegarle le puoi immaginare eseguendo l' operazione con il mouse.
        Tot = Application.WorksheetFunction.CountIf(Range("A:A"), Cells(X, 1).Value) - 1
    'viene data alla variabile tot un valore utilizzando una formula già esistente in excel richiamandola tramite
    applicaiton.(l'application è excel).worksheetfunction(funzioni del foglio di lavoro).countif(conta.se)
    'Cosa conta ? Nel range"A:A" c'è il valore in cella con riga 4 e colonna 1 quindi cella a4 ? Si Quante volte ? 9 ok ma togli 1 quindi TOT al primo giro diventa 8.
            For Y = 1 To Tot 'Già spiegato
                Set Rg = Range("C3:K3").Find(Cells(X + Y, 2), LookIn:=xlValues, LookAt:=xlWhole)
    'Il comando qui sopra assegna alla variabile RG un cella, ma quale ? 
    'Prima gli diamo un range("c3:k3") in cui chiediamo di cercare (metodo .find) il contenuto della cella di riga
    ' 4+1 e colonna 2 ovvero B5 ovvero "CH20".
                If Not Rg Is Nothing Then
    'Se Non RG è NIENTE o meglio in italiano, vista la doppia negazione, SE RG esiste quindi se è stato trovato il 'valore nell' intervallo e si è potuto assegnare quello spazio RG
                    r = Rg.Column 'la variabile R prende il numero di colonna di RG(CH20 è presente nella colonna E
    'ovvero la colonna 5
                    Cells(X, r) = "OK" 'La cella di riga 4 colonna 5 diventa = "OK" se il plant non fosse stato trovato 
    'sarebbe rimasto visibile al posto di diventare OK così che sapevi quale plant era mancante.
                End If
            Next Y 'ricomincia il ciclo per tutte le y (ricorda che Y parta da 1 fino a quante volte è presente il P/N 'quindi cercherà ancora 7 volte)
        X = X + Tot'infine viene assegnato alla variabile X il valore che si ottiene aggiungendo al primo rigo il totale dei P/N trovati così da 'passare al successivo P/N (X valeva 4, TOT è 8 quindi 4+8=12)
    Next X 'ricomincia il ciclo delle X ma non passa da 4 a 5 bensi da 4 a 13 perchè abbiamo dato ad x un nuovo 'valore ovvero 12 e al ricominciare del ciclo viene aggiunga 1 unita.
    End Sub



  • di isasa74 (utente non iscritto) data: 21/03/2016 10:16:23

    Grazie Mohican1989! i tuoi commenti sono chiarissimi ti ringrazio davvero tanto...purtroppo la il codice in uno scenario reale non ha funzionato...

    @ Raffaele,

    il VBA con dati e scenario reali non funziona, il risultato e'una riga di missing ogni nove part number...
    Allego il risultato cosi'se hai tempo puoi dare un'occhiata...
    Non so da cosa dipenda, forse nel tuo codice si presuppone che le plant in B siano sempre nello stesso ordine alfabetico?
     
     



  • di Raffaele_53 data: 21/03/2016 11:50:35

    >>>scenario reali non funziona

    Al tuo file originale manca un riga in alto (dopo l'aggiunta in riga 1)
    In A4 = 1AA4.002.00, da modificare il range A5:A12

    Non guardare i colori che hai messo sballano.
    PS. Potresti avere più di 9 record uguali?
    In tal caso cosa dovrebbe fare? Elimina o scrivere doppio?

    @Mohican1989
    >>>variabili come oggetti
    Ur, X, Y, Tot sono Varriant (testo o Numeri)
    Rg As Object, solo perchè se non settata non restituisce nulla.
    Infatti dimentico sempre d'eliminarla alla fine---> Set Rg = Nothing

    If Rg Is Nothing
    Else
    End if

    In Italiano Rg è popolato? ed il comando IF risponderebbe NO-SI
    Per non scrivere Else metto il Not (tanto so già che è popolato)



  • di isasa74 (utente non iscritto) data: 21/03/2016 13:22:24

    Ciao Raffaele, grazie non so davvero come ringraziarti per il tuo aiuto :)

    Avevi ragione mancava una riga, scusami...

    1) Ho notato due problemi finora, Excel hanging dopo aver lanciato la macro, forse troppe righe? (80k circa!)
    2) AU21 viene sempre riportata, non importa se presente o mancante, credo sia un problema legato all seconda versione del tuo codice quando hai rimpiazzato i missing con le plant.

    Ho allegato il secondo test.
    GRAZIE MILLE



  • di Raffaele_53 data: 21/03/2016 14:14:53

    Colpa mia (il for Y doveva cominciare da 0)

    Vedo in B14 un NL10, che non esiste in D3:K3
    L'ho aggiunto in L3, modificato il codice, ora se non trova "qualcos'altro" Ti appare un MSG

    Credo sia apposto 
     
    Sub elabora2()
    Dim Ur, X, Y, Tot, Rg As Object
    Ur = Range("A" & Rows.Count).End(xlUp).Row
    Range("C4:L" & Ur).ClearContents
    For X = 4 To Ur
        Range(Cells(3, 4), Cells(3, 12)).Copy
        Cells(X, 4).PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
        Tot = Application.WorksheetFunction.CountIf(Range("A:A"), Cells(X, 1).Value) - 1
         'If Tot = 8 Then MsgBox "s"
            For Y = 0 To Tot
                Set Rg = Range("C3:L3").Find(Cells(X + Y, 2), LookIn:=xlValues, LookAt:=xlWhole)
                If Rg Is Nothing Then
                    MsgBox "Esiste in riga " & X + Y & " " & Cells(X + Y, 2) & " che non trovo in alto"
                Else
                    r = Rg.Column
                    Cells(X, r) = "OK"
                End If
            Next Y
        X = X + Tot
    Next X
    MsgBox "Fatto"
    End Sub



  • di Isasa74 (utente non iscritto) data: 21/03/2016 15:54:15

    Ciao Raffaele,

    Grazie sei troppo gentile davvero, adesso sembra funzionare ma devo premere migliaia di volte "OK" perche' mi appare il messaggio ", possiamo eliminarlo please



  • di isasa74 (utente non iscritto) data: 21/03/2016 16:04:56

    non posso uscire piu dalla macro e non riesco piu' premere il tasto ahahahah rischio una paralisi, come posso interrompere il processo? ragazzi aiuto



  • di Raffaele_53 data: 21/03/2016 16:11:49

    Premi Ctrl + ALT + Tasto Pausa (in alto a destra prima dei numeri)
    A me funziona, ho solo messo
    >>>Vedo in B14 un NL10, che non esiste in D3:K3
    >>>L'ho aggiunto in L3,



  • di isasa74 data: 21/03/2016 19:43:01

    ah ok ho capito perche' ricevo migliaia di messaggi, perche' trova NL10, ok allora mi sono spiegato male io perdonami, NL10 c'e' per tutti i part number perche' e' la locazione di referenza, quella principale.

    Nella sostanza di questo messaggio non c'e' bisogno perche' io filtro a monte tutte quello che non sta in una delle plante in D3:K3 ed NL10 non e' inserita nel check perche' do' per scontato che sia sempre presente. quindi possiamo omettere il messaggio per favore?

    Magari quello finale " fatto" lo lascerei visto la lunghezza dell' operazione.
    Appena ho avviato il codice (su 87K righe) ho cominciato ad avere migliaia di messaggi che mi avvisavano su NL10...
    Fammi sapere se sono stato chiaro per te.

    Grazie infinite Raffaele e tutti gli altri ragazzi siete dei veri signori oltre che geniali.



  • di Raffaele_53 data: 21/03/2016 20:16:22

    Qualsiasi codice non capisce nulla di quanto scritto
    Per Esempio, se metti una riga in più/meno.
    Anche la frase sono 9 ed poi in alto sono solo 8

    1AA4.054.02, sono solamente 8 invece
    1AA4.054.03, sono 9... ed il codice cosa dovrebbe farci?

    >>>io filtro a monte tutte quello che non sta in una delle plante in D3:K3
    >>>perche' e' la locazione di referenza, quella principale.

    Allora spiegami se le hai filtrate, perchè NL10 è presente in B14, B23 ecc ecc da paralizzarti un braccio? Siccome ci sono e non sono in posizione primaria di referenza (allora, il For Y = 1 to Tot sarebbe stato giusto), come già detto il codice non capisce nulla

    Queste cose le sai solo Tu, io ho fatto un VBA in base alla Tua domanda.
    Se non desideri il MSG, metti un'aprostofo davanti ad
    >>>MsgBox "Esiste in riga................
    Cancella la cella L3, mà prima/poi troverai alcuni errori, per me meglio come scritto l'ultimo codice, almeno t'avvisa se hai scritto qualcos'altro in colonna B.



  • di isasa74 data: 21/03/2016 20:49:14


    A) Scusami, " filtro a monte tutte quelle che non sono comprese in D3:K3" , e' colpa mia, non ti ho detto che le plant sono decine e decine quindi filtro via centinaia di migliaia di righe a monte del check, non mi riferivo a NL10.
    Quelle 9 sulle quali stiamo lavorando solo solo le europee e soltanto per riparazione.

    B) NL10 e' nella lista ma non l' ho inclusa nel check D3:K3 perche' e sempre presente, mi spiace per la confusione.

    C) nel mio primo post scrivo :
    " Tutti i part numbers dovrebbe essere ripetuti nove volte, una volta per ogni localita', con la prima, NL10, che e' sempre presente."
    ora magari non e' un spiegazione da scienziato ma non mi pareva tanto confusa
    Ad ogni modo scusami ancora non ho problemi a darti ragione in quanto potevo essere piu' preciso.

    D) domaini modifico il VBA con I tuoi suggerimenti e grazie ancora.
    E) grazie mille e perdonami se ti ho fatto scazzare. Ti sono estremente grato per il tuo aiuto ad Amsterdam hai un amico, ovviamente non manchero' di donare per questo eccezionale forum.


    Buona serata a te e tutti i ragazzi che mi hanno aiutato, abbracci sinceri e sempre viva l' Italia.



  • di Raffaele_53 data: 21/03/2016 21:36:12

    Sono vecchio >>>con la prima, NL10, che e' sempre presente."
    >>>Locazione di referenza, quella principale.

    Cancello in L3
    Pensavo la prima Locazione Principale ed "adesso devo" esclure la sigla "NL10", domani digiti per errore (NL1O con zero finale) che non sarà analizzata e senza MSG.
    Il mio (credo) era un suggerimento migliore
    Buona serata 
     
    Sub elabora3()
    Dim Ur, X, Y, Tot, Rg As Object
    Ur = Range("A" & Rows.Count).End(xlUp).Row
    Range("C4:L" & Ur).ClearContents
    For X = 4 To Ur
        Range(Cells(3, 4), Cells(3, 12)).Copy
        Cells(X, 4).PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
        Tot = Application.WorksheetFunction.CountIf(Range("A:A"), Cells(X, 1).Value) - 1
            For Y = 0 To Tot
                Set Rg = Range("C3:L3").Find(Cells(X + Y, 2), LookIn:=xlValues, LookAt:=xlWhole)
                If Not Rg Is Nothing Then
                    If Cells(X + Y, 2) <> "NL10" Then 'qui escludo tutti gli NL10
                        r = Rg.Column
                        Cells(X, r) = "OK"
                    End If
                End If
            Next Y
        X = X + Tot
    Next X
    MsgBox "Fatto"
    End Sub