inserire riga con condizione
Hai un problema con Excel? 
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
Vuoi Approfondire?