inserire riga con condizione



  • inserire riga con condizione
    di wilmina (utente non iscritto) data: 27/08/2012 14:16:31

    Sono nuova del Forum, non so se qualcuno può essermi di aiuto ma avrei bisogno di creare una macro VBA.

    Ho una tabella nella quale devo inserire una riga vuota a secondo del risultato di una cella, esempio:

    pippo A vero
    pluto B falso
    inserire riga vuota
    paperino C falso
    inserire riga vuota
    pluto B falso
    inserire riga vuota
    pippo A vero
    paperino C falso
    inserire riga vuota
    eccetera

    In sostanza se nella colonna B le celle contengono un risultato = "b" o "c" inserisco, sotto, una riga vuota, invece, se le celle contengono un risultato = "a" resto tutto invariato

    C'è nessuno che sa indicarmi come devo fare?



  • di HarryBosch data: 27/08/2012 14:57:07

    Ciao Wilmina
    certo che possiamo indicarti come fare... ma immagino che qualcosina avrai già tentato, o sbaglio?
    Hai qualche conoscenza di base del vba? Perchè così potresti pubblicare il tuo codice in modo da correggerlo assieme...

    Inoltre bisogna anche determinare in base a quale evento vuoi che la riga vuota si inserisca; ad esempio:
    - tramite un pulsante?
    - vuoi attivare la macro manualmente?
    - dopo la modifica della colonna B?

    Fai sapere,
    Ciao Vanni



  • di wilmina (utente non iscritto) data: 27/08/2012 15:58:03

    Ciao Vanni, effettivamente ho tentato qualcosa con scarsi risultati in quanto non ho nessuna conoscenza di VBA (quale sarebbe il mio codice?) e quindi mi sono limitata a copiare ed incollare quello che ho trovato navigando in internet come ad esempio:

    Public Sub InsRiga()

    Dim rng As Range
    Dim cella As Range
    Dim j As Long

    Set rng = Selection
    For j = rng.Rows.Count To 2 Step -1
    Set cella = rng.Cells(j, 1)
    With cella
    If .Value <> .Offset(-1).Value Then
    .EntireRow.Insert
    End If
    End With
    Next j
    Set rng = Nothing
    Set cella = Nothing

    End Sub

    ma il risultato non è quello desiderato perchè la macro lavora solo sulla colonna A (non so ancora in quale colonna verrà inserito il risultato) e comunque inserisce una riga al cambiare del risultato, invece io ho necessità di inserire la riga vuota solo se in una determinata cella ho un determinato risultato.

    la macro al momento sarà da attivare manualmente
    Grazie Vanni



  • di HarryBosch data: 27/08/2012 17:30:25

    OK, nessuna conoscenza...
    Il codice che hai copiato/riportato si basa sulla selezione di un range, quindi funziona se prima selezioni ad esempio la colonna B.
    Però non verifica quello che hai chiesto, ma controlla se i valori delle celle relative alla colonna selezionata è uguale alla cella precedente e, in quel caso, aggiunge una riga (sopra).

    Senza scriverti nuovi codici, sotto ho modificato quello che hai postato; verifica se funzia a dovere.. magari, se vuoi imparare, più tardi ti commento la macro.

    attenzione che questa macro esegue il lavoro una sola volta... intanto provala e poi mi dici se invece ti serve una macro che controlli ogni volta i valori della colonna B, e quindi risistemi le righe vuote in base al valore trovato.

    Ciao Vanni
     
    Sub InsRiga()
    
        Dim rng As Range
        Dim cella As Range
        Dim j As Long
        
        Set rng = Range(Cells(1, 2), Cells(1, 2).End(xlDown))
        
        For j = rng.Rows.Count To 1 Step -1
            Set cella = rng.Cells(j, 1)
            cella.Select
            With cella
                If .Text = "B" Or .Text = "C" Then
                    .Offset(1, 0).EntireRow.Insert
                End If
            End With
        Next j
       
    End Sub
    



  • di wilmina data: 27/08/2012 18:23:48

    Ho verificato il funzionamento ma non succede nulla, pur selezionando la colonna con la condizione.
    Sono molto interessata ad imparare mi farebbe molto piacere se hai la possibilità di spiegare la macro.
    Ciao Wilmina



  • di wilmina data: 27/08/2012 18:28:58

    ho allegato la tabella in questione ed evidenziato la colonna con la condizione in verde.
    Grazie ancora per l'aiuto.
    Ciao Wilmina



  • di HarryBosch data: 27/08/2012 18:37:54

    Molto bene... ora con il file allegato la cosa si risolve meglio, senza andarci attorno.
    Anche perché la colonna di riferimento è la Z! e non la B...
    e le prime righe sono vuote...

    stasera, con calma, ti posto il codice da applicare al tuo esempio e lo commento.



  • di HarryBosch data: 27/08/2012 19:14:30

    Ho trovato un pò di tempo..
    ti riposto il file dove ho già inserito il modulo con il codice.
    Attiva la macro e verifica il funzionamento.
    Ho continuato a correggere il codice che hai postato in partenza, ma è possibile arrivare allo stesso risultato anche attraverso altre strade...
    che magari qualcun'altro potrebbe aggiungere...

    Fammi sapere se qualcosa non è chiaro; riporto anche qua sotto il codice commentato

    Ciao Vanni

     
    Sub InsRiga()
    
        Dim rng As Range
        Dim cella As Range
        Dim j As Long
    
        'imposto il range dove controllare, ovvero a partire dalla riga 11
        'fino all'ultima cella occupata della colonna Z
        Set rng = Range(Cells(11, 26), Cells(Rows.Count, 26).End(xlUp))
    
        'parte il ciclo dall'ultima cella piena della colonna Z
        'e torno a ritroso (step -1)
        For j = rng.Rows.Count To 1 Step -1
    
            'seleziono il valore di ogni cella della colonna
            Set cella = rng.Cells(j, 1)
    
            'con la cella in questione...
            With cella
                'controllo se contiene a o b
                If .Text = "b" Or .Text = "c" Then
                    'se vero inserisco una riga vuota sotto (con Offset)
                    .Offset(1, 0).EntireRow.Insert
                End If
            End With
        'passo alla successiva cella
        Next j
    
    End Sub
    



  • di Vecchio Frac data: 27/08/2012 20:50:26

    La mia proposta, rispettando le condizioni iniziali e ricalcando il codice di Vanni, leggermente modificato.
    Da notare che 'rng' si adatta automagicamente quando viene inserita una riga, per cui non serve un controllo sull'effettiva lunghezza del range da controllare.
     
    Sub InsRiga2()
    Dim rng As Range, cella As Range
    
        Set rng = Range(Cells(11, "Z"), Cells(Rows.Count, "Z").End(xlUp))
    
        For Each cella In rng
            'se il contenuto della cella è 'a' oppure 'b' (minuscoli), inserisce una riga sotto la 'cella' corrente
            If LCase(cella) Like "[ab]" Then cella.Offset(1, 0).EntireRow.Insert
        Next
    
        MsgBox "Ho finito."
    End Sub






  • di Vecchio Frac data: 27/08/2012 21:01:16

    E inserendo application.ScreenUpdating = false all'inizio della procedura i tempi di esecuzione si abbattono drasticamente... da tre secondi e mezzo a tre decimi (con la mia versione); da quattro secondi e mezzo a cinque decimi con la versione di Vanni).
    Direi che ScreenUpdating offre un ottimo servizio quanto a miglioramento delle prestazioni :)





  • di wilmina data: 28/08/2012 09:58:35

    entrabi le sintassi funzionano ma hanno un problema.
    la colonna "Z" della tabella verrà di volta in volta aggiornata e verranno anche aggiunte nuove righe quindi quando eseguo la macro questa mi ripete ogni volta l'operazione di aggiungere una riga dove trova "B" o "C" con il risultato di avere più di una riga vuota.
    Si può risolvere?
    Grazie a entrambi, Wilmina



  • di Vecchio Frac data: 28/08/2012 10:35:42

    Vedi nel riquadro le correzioni da fare nel luogo opportuno.
    E' necessario però in entrambe le versioni che nella colonna Z la riga vuota rimanga vuota, soprattutto la cella immediatamente sotto quella che contiene "a" o "b", altrimenti l'If non viene eseguito.
     
    ' versione HarryBosch
    If .Text = "b" Or .Text = "c" And cella.Offset(1, 0) <> "" Then
        'se vero inserisco una riga vuota sotto (con Offset)
        .Offset(1, 0).EntireRow.Insert
    End If
    
    ' versione Vecchio Frac
    If LCase(cella) Like "[ab]" And cella.Offset(1, 0) <> "" Then 
        cella.Offset(1, 0).EntireRow.Insert
    End If






  • di wilmina data: 28/08/2012 12:58:30

    Fantastico! mi si è aperto un mondo.
    Sono riuscita a far funzionare il tutto con la soluzione proposta da Vecchio Frac ho solo dovuto correggere nella sintassi le lettere relative alla condizione. Inoltre, per far funzionare il tutto è necessario che le celle relative alle righe di descrizione della tabella (riche orizzontali gialle o grige) contengano la lettera “a” (vedi celle Z9-Z25-Z26 ecc.) altrimenti anche per queste viene inserita una riga vuota.
    Ringrazio per la spettacolare disponibilità, di cui spero poter approffittare anche in futuro.
    Willelmina





  • di Vecchio Frac data: 28/08/2012 13:15:11

    La proposta di Vanni è nella sostanza (.EntireRow.Insert) identica alla mia, che è solo leggermente più ottimizzata (non dimenticare lo ScreenUpdating = True ad inizio Sub e ScreenUpdating = False prima di End Sub).
    Ti chiedo scusa se hai dovuto correggere le letterine che imponevano la condizione, è perché mi è sfuggito nel confezionare l'esempio che tu parlavi di celle b e c; ma come hai visto una volta afferrato il concetto non è stato difficile adattarlo :)
    Inoltre quando non vuoi una riga vuota basta che nella cella in colonna Z non ci sia niente, non è necessario inserire una "a".

    Se ritieni di aver "risolto", spunta "Discussione risolta" in una nuova risposta, thx :)





  • di wilmina (utente non iscritto) data: 28/08/2012 14:48:23

    E' vero non sarebbe necessario riempire le celle delle righe di descrizione, ma se la cella che si trova al di sotto dell'ultima cella riempita con "c" o "b" è vuota, la macro non inserisce la riga perchè trova la cella già vuota in quanto la condizione della macro fa riferimento alle celle di detta colonna.



  • di wilmina (utente non iscritto) data: 28/08/2012 14:53:55

    P.S. : chiaramente, la stessa cosa capita anche quando l'ultima cella vuota non è quella della riga di descrizione (celle gialle e grige) ma righe che compongono la tabella stessa.



  • di wilmina (utente non iscritto) data: 28/08/2012 15:03:17

    La versione di Vanni funziona in parte. Ha lo stesso problema sopra descritto della versione di vecchio Frac, in più alle successive esecuzioni della macro aggiunge nuove righe vuote sotto le celle che contengono "b". Forse ho ricopiato male la sintassi ?



  • di HarryBosch data: 28/08/2012 15:24:00

    Ciao wilmina
    crea la seconda riga solo quando trova la lettera c; prova a modificare il codice come sotto.
    Per risolvere l'ultimo questito che hai posto, si potrebbe verificare la cella dell'intestazione, e non quella direttamente sotto la lettera: l'unica condizione è che la scritta dell'intestazione deve trovarsi sempre in quella cella.
    Nel tuo foglio le intestazioni gialle sono scritte in D1, quelle grigie in B1; basta metterle nella stessa colonna, nell'esempio ( - 22 ) in D1.
    Ho aggiunto anche lo ScreenUpdating sull'ottimo suggerimento di Francesco.

     
    Sub InsRiga()
    
        Dim rng As Range
        Dim cella As Range
        Dim j As Long
    
        Application.ScreenUpdating = False
        Set rng = Range(Cells(11, 26), Cells(Rows.Count, 26).End(xlUp))
    
        For j = rng.Rows.Count To 1 Step -1
    
            Set cella = rng.Cells(j, 1)
            With cella
    
                If .Text = "b" Or .Text = "c" Then
                    'controllo la cella D1 a patto di avere tutte le intestazioni
                    'in questo campo!
                    If .Offset(1, -22) <> "" Then
                        .Offset(1, 0).EntireRow.Insert
                    End If
                End If
            End With
    
        Next j
        Application.ScreenUpdating = True
    End Sub
    



  • di Vecchio Frac data: 28/08/2012 15:27:46

    Colpa mia... bisogna separare gli OR dagli AND come segue.
    La mia versione affida a Like il compito di verificare che la cella in esame sia b oppure c, mentre se verifichi separatamente questa condizione è necessario avvolgerla con parentesi altrimenti l'AND ha la precedenza (in pratica senza le parentesi: viene aggiunta la riga sempre, purché la cella contenga "b" OPPURE la cella contiene "c" E la successiva è vuota).
    Modifica come appresso e risolvi anche con la versione di Vanni.
     
    If (.Text = "b" Or .Text = "c") And cella.Offset(1, 0) <> "" Then
        .Offset(1, 0).EntireRow.Insert
    End If






  • di wilmina (utente non iscritto) data: 28/08/2012 16:32:55

    Modificando la macro come indicato da Vanni ed inserendo le intestazioni di tabella nelle celle della colonna D come per le celle gialle funziona tutto; e se volessi spostare le intestazioni di tabella nella colonna B delle intestazioni di tabella delle righe grige ?
    Mentre la macro di vecchio Frac non mi funziona correttamente con le ultime modifiche.

     
    Sub InsRiga()
    
        Dim rng As Range
        Dim cella As Range
        Dim j As Long
    
        Application.ScreenUpdating = False
        Set rng = Range(Cells(11, 26), Cells(Rows.Count, 26).End(xlUp))
    
        For j = rng.Rows.Count To 1 Step -1
    
            Set cella = rng.Cells(j, 1)
            With cella
    
                If .Text = "b" Or .Text = "c" Then
                    'controllo la cella D1 a patto di avere tutte le intestazioni
                    'in questo campo!
                    If .Offset(1, -22) <> "" Then
                        .Offset(1, 0).EntireRow.Insert
                    End If
                End If
            End With
    
        Next j
        Application.ScreenUpdating = True
    End Sub
     
    



  • di HarryBosch data: 28/08/2012 16:58:56

    allora bisogna leggermente modificare la proprietà Offset del range in questione.
    Nel codice che ho corretto si fa riferimento al range:
    Set rng = Range(Cells(11, 26), Cells(Rows.Count, 26).End(xlUp))
    ovvero relativo alla colonna Z.

    Vengono quindi prese in considerazione tutte le celle di questa colonna con:
    Set cella = rng.Cells(j, 1)

    il controllo della cella vuota sulla riga successiva avviene con Offset:
    .Offset(1, -22) <> ""
    dove il primo valore indica la riga e il secondo la colonna. Visto che siamo in Z, è come se scrivessimo:
    .Offset(0, 0)
    pertanto la riga successiva si troverà con 1 e la colonna precedente con -22 (in questo caso, ovvero dalla Z alla D)

    per trovare la colonna B, basterà cambiare in:
    .Offset(1, -24) <> ""

    Non so se sono stato abbastanza chiaro... magari Vecchio Frac ti illustra il passaggio in maniera più tecnica



  • di wilmina (utente non iscritto) data: 29/08/2012 09:48:26

    Sei stato chiarissimo
    grazie a tutti per l'aiuto