Aggiungi righe vuote in Tabella
Hai un problema con Excel? 
Aggiungi righe vuote in Tabella
di Perry data: 16/11/2013 18:27:57
Grazie anticipate
Nel foglio Sh_TITOLI ho una tabella (circa 300 righe) a cui ho associato il nome TITOLI, vorrei, associando ad un pulsante "Aggiungi Righe", una macro per aggiungere n.righe vuote in fondo alla tabella TITOLI.
Grazie 1K per la vostra comprensione.
di Vecchio Frac data: 16/11/2013 18:34:50
Mi sembra che nelle Tabelle create in Excel esiste già il pulsantino in fondo alla tabella per aggiungere un nuovo set di dati, a forma di asterisco.
di Perry (utente non iscritto) data: 16/11/2013 18:49:02
Scusa Vecchio Frac
Credo di non essermi spiegato bene, il mio è un insieme di righe che ho associato ad un nome (TITOLI), devo trovare l' ultima riga e aggiungere a questa alcune righe vuote per implementare le righe di immissione.
di Perry (utente non iscritto) data: 16/11/2013 18:58:02
Per la precisione dovrei copiare l' ultima riga vuota (ma che contiene formule e Formati) e aggiungerla n.volte in fondo.
Scusa, grazie 1K
di Vecchio Frac data: 17/11/2013 12:59:30
cit. "dovrei copiare l' ultima riga vuota (ma che contiene formule e Formati)"
---> E questa è un'informazione importante, che cambia parecchio lo scenario, ma perchè bisogna sempre tirare fuori con le pinze i particolari che contano?
Serviranno alcune righe di codice per raggiungere l'automatismo desiderato.
di Perry (utente non iscritto) data: 18/11/2013 14:58:45
per Vecchio Frack, hai perfettamente ragione e mi scuso per la superficialità della mia richiesta, aspetto con impazienza tuoi suggerimenti e codice.
Grazie
di Grograman (utente non iscritto) data: 18/11/2013 15:08:58
Siamo noi che aspettiamo con trepidazione il tuo file di esempio
di Grograman (utente non iscritto) data: 18/11/2013 15:16:01
Allegato esempietto:
Option Explicit
Sub Righe()
Dim oTbl As Object
Dim x As Long
Set oTbl = ActiveSheet.ListObjects("Tabella1")
With oTbl
x = oTbl.ListRows.Count
.ListRows.Add (x)
End With
Set oTbl = Nothing
End Sub
|
di Grograman (utente non iscritto) data: 18/11/2013 15:17:22
Scusate, meglio sarebbe:
di Perry (utente non iscritto) data: 18/11/2013 15:48:42
Grazie 1K
Ho provato la Sub Righe, ma ottengo il seguente errore :
Indice non incluso nell' intervallo - Errore di run-time '90 , all specifica
Set oTbl = ActiveSheet.ListObjects("Tabella1")
Alle righe/Celle del mio intervallo ho associato il Nome Tabella1
Option Explicit
Sub Righe()
Dim oTbl As ListObject
Dim x As Long
Set oTbl = ActiveSheet.ListObjects("Tabella1")
With oTbl
x = oTbl.ListRows.Count
.ListRows.Add (x)
End With
Set oTbl = Nothing
End Sub |
di Grograman (utente non iscritto) data: 18/11/2013 16:35:00
cit: "Alle righe/Celle del mio intervallo ho associato il Nome Tabella1"
E qui volevo arrivare.
Seleziona l'intervallo e premi CTRL+T
Per magia ti compariranno le tabelle!
di Perry (utente non iscritto) data: 18/11/2013 18:36:02
Grazie Grograman
Ho fatto come mi hai suggerito (creato Tabella) ma mi aggiunge una riga (SENZA le formule contenute nelle celle) PRIMA dell' ultima riga. Facendo il debug ho visto che conteggia -1 riga rispetto all' intervallo
Scusa se ti Rompo, ma è proprio necessario creare una Tabella ? non è possibile operare sul range di righe/colonne chiamato "Campi_Excel" ?
Quando eseguivo la Copia-Incolla da macro funzionava ma mi imposta il range della riga sorgente, mentre io volevo renderlo variabile pescando sempre l' ultima riga
Ti allego il file cosi potrai vedere a cosa mi serve.
Grazie 1k
di Grograman (utente non iscritto) data: 19/11/2013 09:21:16
Porca vacca hai ragione... non copia le formule.
Se riesco vedo di capire cosa bisogna aggiungere.
Per aggiunger euna riga SOTTO l'ultima devi modificare così:
With E_oTbl
.ListRows.Add (.ListRows.Count + 1), True
End With |
di Perry (utente non iscritto) data: 19/11/2013 12:31:08
Grazie Grograman
In effetti ora aggiunge una riga all' ultima, aspetto fiducioso la modifca per la copia delle formule.
Nel precedente ti chiedevo lumi tra l' operare con una tabella e un range di nomi, credo sia un fatto di sintassi VBA non so come sostituire al range di ultima riga con il nome dell' insieme "Excel_Campi" ecco un esempio :
Sub Macro3()
Rows("368:368").Select ' <--- ultima riga del range "Excel_Campi"
Selection.Copy
Rows("368:368").Select '<---qui vorrei sostituire con il range "Excel_Campi"
Selection.Insert Shift:=xlDown
Application.CutCopyMode = False
End Sub
che funziona e mi copia la riga e le formule, ma associando la macro ad un pulsante il range non è ovviamente variabile.
Ancora grazie 1k per la tua disponibilità
di Perry (utente non iscritto) data: 20/11/2013 16:03:10
salve a tutti in particolare a Grograman
sul mio precedente avete lumi ???
Grazie 1K
di Perry (utente non iscritto) data: 21/11/2013 15:04:39
salve a tutti in particolare a Grograman
sul mio precedente avete lumi ???
Grazie 1K
x grograman
di Perry (utente non iscritto) data: 22/11/2013 18:42:02
Gent.mo grograman,
aspetto fiducioso tue nuove circa il mio post,
ho attivato la macro e mi aggiunge una riga senza copiare formati e formule.
Ho aggiunto nel foglio la macro di Raffaele_53 (post 5310 - Eliminare i doppioni) che mi pareva particolarmente utile, ma quando clicco sul bottone per inserire una riga mi da un errore di run-time 13 - tipo non corrispondente
--->> If Application.WorksheetFunction.CountIf(Range("D:D"), Nome) > 1 Then
Se tu avessi la gentilezza di darci un' occhiata Ri-allego il mio file e aspetto con fiducia.
Grazie 1k
di Perry (utente non iscritto) data: 24/11/2013 18:28:48
Resto sempre in attesa di illuminanti soluzioni.
di Vecchio Frac data: 24/11/2013 20:15:45
Probabilmente Grograman non ha avuto la possibilità di occuparsi della questione in questi giorni.
Il consiglio è che è sempre meglio non rivolgersi mai a un utente specifico, ma all'intera comunità, perchè a volte accade che quell'utente non possa o non sappia rispondere.
Nel caso specifico, "Nome" è valorizzato? è un numero o una stringa?
di Perry (utente non iscritto) data: 25/11/2013 16:49:48
Scusa ma non capisco la tua domanda :
"Nome" è valorizzato? è un numero o una stringa?
--->> If Application.WorksheetFunction.CountIf(Range("D:D"), Nome) > 1 Then
Ho utilizzato questa istruzione (foglio1 in VBA) modificando esclusivamente il range della colonna "D:D" dove si trovano le celle di testo, eventualmente doppio, che sto inserendo con un copia/incolla ed esegue il suo lavoro egregiamente, solo quando aggiungo una riga nuova-vuota (con VBA da modulo)mi da errore. Ecco l' insieme del codice.:
Option Explicit
Dim x As Long
' per aggiungere una riga da modulo tramite botton.:
Sub Pulsante1_Click()
E_Righe
End Sub
Sub E_Righe()
Dim E_oTbl As ListObject
' Dim x As Long
Set E_oTbl = ActiveSheet.ListObjects("Excel_Tab")
With E_oTbl
.ListRows.Add (.ListRows.Count + 1), True
End With
Set E_oTbl = Nothing
End Sub
' per testare inserimento doppioni da foglio1.:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("D:D")) Is Nothing Then
Nome = Target.Offset(0, 0).Value
If Application.WorksheetFunction.CountIf(Range("D:D"), Nome) > 1 Then
' qui ricevo errore di run-time 13 - tipo non corrispondente
MsgBox "Titolo già inserito", , "EXCEL"
Target.Offset(0, 0) = ""
End If
End If
End Sub |
di Vecchio Frac data: 25/11/2013 23:18:47
Bè, mi sembrava importante specificare il tipo di "Nome".
Comunque ho testato la tua routine, funziona perfettamente, attenzione solo a specificare Application.EnableEvents prima di modificare il target per evitare ricorsioni.
Inoltre nota che Target.Offset(0,0) non ha senso, è sufficiente Target.
Per l'estetica e per l'utente, ho riposizionato la selezione sulla cella annullata casomai venisse individuato un doppione.
Hai ancora problemi col codice?
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Dim nome As String
If Not Intersect(Target, Range("D:D")) Is Nothing Then
nome = Target
If Application.CountIf(Range("D:D"), nome) > 1 Then
Application.EnableEvents = False
MsgBox "Titolo già inserito", , "EXCEL"
Target = ""
Application.EnableEvents = True
Target.Select
End If
End If
End Sub |
di Perry (utente non iscritto) data: 28/11/2013 15:49:17
Mi da errore quando aggiungo una riga
Private Sub Worksheet_Change(ByVal Target As Range)
Dim nome As String
If Not Intersect(Target, Range("D:D")) Is Nothing Then
nome = Target '<---- errore run time 13 - tipo non corrispondente
If Application.CountIf(Range("D:D"), nome) > 1 Then
Application.EnableEvents = False
MsgBox "Titolo già inserito", , "EXCEL"
Target = ""
Application.EnableEvents = True
Target.Select
End If
End If
End Sub
Allego il mio progetto per verifica; Il test sui doppioni funziona, ma quando aggiungo una riga (vedi pulsante) va in errore
ancora grazie per la pazienza.
di scossa data: 28/11/2013 16:01:13
Dim nome As String
.....
nome = Target '<---- errore run time 13 - tipo non corrispondente
nome è una variabile String, tu vuoi assegnarle un Range ....
quindi, o:
nome = Target.Text
oppure (risparmiando la variabile "nome"):
If Application.CountIf(Range("D:D"), Target.Text) > 1 Then
di Perry (utente non iscritto) data: 28/11/2013 17:15:06
Funziona, ma devo testare che il campo non sia vuoto, quando aggiungo una riga dal pulsante " Aggiungi Riga" associato alla Sub E_Righe() è vuoto.
Vedi file allegato.
Grazoe 1k
di Vecchio Frac data: 28/11/2013 21:16:43
cit. "nome è una variabile String, tu vuoi assegnarle un Range .... "
---> Dissento da scossa, non è quello il motivo ^_^
Quando il compilatore arriva a
nome = Target
non fa altro che prelevare il valore dell'oggetto Target, e assegnarlo a "nome". Il cast implicito lo converte in stringa.
Se avessi voluto riferirmi a Target come a un range avrei usato Set che si utilizza per assegnare ad una variabile un oggetto.
Naturalmente prelevare il valore text dal Target elimina ogni dubbio.
Mi sembra davvero strano che Perry abbia un errore di tipo non corrispondente su un codice che invece funziona benissimo.
E' molto più probabile che l'errore venga sollevato da questa operazione: seleziono più celle e inserisco un valore multiplo (con Ctrl-Invio). Oppure premo Canc. Allora sì: si scatena l'errore proprio su "nome = Target" ed è logico che sia così, perchè il Target è multicella mentre "nome" è - poverina - una semplice variabile stringa ^_^
Sono invece d'accordo sul risparmiare anche la variabile "nome".
di Perry (utente non iscritto) data: 30/11/2013 18:08:34
Vorrei ringraziare tutti coloro che hanno dato suggerimenti al mio progetto, ma purtroppo non ho risolto i problemi che si sono evidenziati.
Provo a sintetizzare ed evidenziare lo scopo del progetto, nato dalla volontà di tenere traccia di tutte le discussioni che si succedono in questo bellissimo sito.
Regolarmente memorizzo il link (una volta) di ogni singola discussione sul foglio "Elenco titoli EXCEL".
Su vostro suggerimento ho tramutato l' insieme di celle a cui avevo attribuito il nome "EXCEL_Campi" in una Tabella che ho chiamato Excel.Tab"
Avendo la necessità di aggiungere in automatico delle righe, ho applicato al pulsante1 "Aggiungi riga" la seguente macro (in modulo1):
Option Explicit
Dim x As Long
Sub Pulsante1_Click()
E_Righe
End Sub
Sub E_Righe()
Dim E_oTbl As ListObject
' Dim x As Long
Set E_oTbl = ActiveSheet.ListObjects("Excel_Tab")
With E_oTbl
' x = E_oTbl.ListRows.Count
' .ListRows.Add (x)
.ListRows.Add (.ListRows.Count + 1), True
End With
Set E_oTbl = Nothing
End Sub
Questa macro mi aggiunge una riga in fondo ma NON COPIA le FORMULE e la FORMATTAZIONE delle righe precedenti o quantomeno dell' ultima riga inserita.
Ho poi aggiunto la seguente macro per controllare eventuali doppioni in Foglio1:
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Dim nome As String
If Not Intersect(Target, Range("D:D")) Is Nothing Then
nome = Target.Text
If Application.CountIf(Range("D:D"), nome) > 1 Then
Application.EnableEvents = False
MsgBox "Titolo già inserito", , "EXCEL"
Target = ""
Application.EnableEvents = True
Target.Select
End If
End If
End Sub
Che fa il suo dovere e mi controlla di non aver inserito in una riga vuota un link già esistente.
Ora nascono i problemi :
1- quando aggiungo una riga esce il msgbox - titolo già inserito (è vuoto !)
2 - se copio la formattazione (pennello) dell' ultima riga valida mi da errore run-time "94" - utilizzo non valido di Null
Spero di aver evidenziato correttamente i miei problemi e conto sulla vostra pazienza e disponibilità invitandovi a testare il progetto che ho allegato.
In ogni caso vi ringrazio e confermo la mia stima a tutti voi
Grazie
di Vecchio Frac data: 30/11/2013 18:15:35
cit. "lo scopo del progetto, nato dalla volontà di tenere traccia di tutte le discussioni che si succedono in questo bellissimo sito"
---> Cioè stai riprogettando uno storico? ^_^
Prova ad allegare uno stralcio del file così vediamo com'è esattamente lo scenario.
E aggiungo, lodevole iniziativa :)
di Perry (utente non iscritto) data: 30/11/2013 18:27:12
Ho allegato il progetto completo
Grazie
di Vecchio Frac data: 30/11/2013 18:47:28
Bel lavoro, complimenti.
Però devo avviare il mio Excel 2010 in macchina virtuale altrimenti ottengo solo una serie di errori :)
di Vecchio Frac data: 30/11/2013 18:56:53
Ma quando fai "aggiungi riga", si limita a inserire una riga vuota?
Le formule le devi aggiungere a mano?
Dovresti fargliele inserire in automatico.
In questo modo avresti la nuova riga col numero progressivo già compilato e, nella Worksheet_Change del foglio relativo agli inserimenti di Excel (ma uguale ragionamento per quello al foglio Word: poi si penserà ad ottimizzare visto che il codice è identico e potrai spostare la routine in nu evento di Workbook piuttosto che di Worksheet) potresti evitare l'errore di Titolo già inserito semplicemente testando se la prima cella contiene qualcosa:
If Not Intersect(Target, Range("D:D")) Is Nothing And Target(1) <> "" Then
Questo per il problema n° 1, ma risolveresti di colpo anche il problema n° 2 ^_^
di Vecchio Frac data: 30/11/2013 19:03:53
Guarda, ti risolvo io il problema della copia della formula soprastante.
Tu fai anche la modifica della sub che intercetta l'evento Change del foglio come detto prima.
Sub E_Righe()
Dim E_oTbl As ListObject
Set E_oTbl = ActiveSheet.ListObjects("Excel_Tab")
With E_oTbl
.ListRows.Add alwaysinsert:=True
.ListRows(.ListRows.Count).Range(1).Offset(-1).Copy .ListRows(.ListRows.Count).Range(1) '<<<<< nuova riga
End With
Set E_oTbl = Nothing
End Sub |
di Perry (utente non iscritto) data: 30/11/2013 20:15:13
Perfetto,
ora mi copia le formule della riga precedente, ma non mi copia il formato delle varie celle (es. altezza riga 15)
ho fatto la modifica della sub che intercetta l'evento Change del foglio come detto prima ma continuava a darmi errore l' ho modificata ed ora funziona :
If Not Intersect(Target, Range("D:D")) Is Nothing And Target(1) <> "" Then
' nome = Target.Text <-- vecchia versione
nome = Target(1).Text <-- nuova versione
ma non mi è chiaro il perchè, anche il range "D:D" non mi piace perchè se per sbaglio inserisco un link fuori della tabella (sempre in colonna D) mi fa lo stesso il controllo di univocità che vorrei fosse limitato solo alle righe della tabella.
Dici di spostare l' evento da Worksheet a Workbook però perderei la personalizzazione EXCEL o WORD ??
Grazie, grazie 1k
di Vecchio Frac data: 30/11/2013 20:30:51
Sono perplesso su quel Target(1).Text, che significa solo "la prima cella del range del target", anche perchè le mie prove riguardano l'uso del solo "Target" senza .text ^_^ ma verificherò.
Il copia formato lo fai col Copy e poi col PasteSpecial su riga separata. Tra poco vedo se ci rimetto le mani.
Per il range dell'intera colonna basta forse solo verificare di essere all'interno della tabella.
Gestirei tutto a livello di Workbook senza temere la personalizzazione del foglio perchè l'evento sa a quale foglio ti stai riferendo in quel momento.
di Vecchio Frac data: 01/12/2013 12:00:34
Allora, intanto aggiustiamo la copia dei formati.
Sostituisci le sub E_Righe e W_Righe con quelle che seguono.
Adesso mi occupo di limitare il range di inserimento alla porzione di D:D che contiene la tabella.
Poi penseremo a come sfruttare gli eventi di Workbook per non duplicare il codice (E_Righe e W_Righe non servono distinte, se ne potrà fare una sola passando come parametro la tabella su cui intervenire).
Sub E_Righe()
Dim E_oTbl As ListObject
Set E_oTbl = ActiveSheet.ListObjects("Excel_Tab")
Application.EnableEvents = False
With E_oTbl
.ListRows.Add alwaysinsert:=True
With .ListRows(.ListRows.Count)
.Range(1).Offset(-1).Copy .Range(1)
.Range.Offset(-1).Copy
.Range.PasteSpecial xlPasteFormats
End With
End With
Application.EnableEvents = True
Application.CutCopyMode = False
Set E_oTbl = Nothing
End Sub
Sub W_Righe()
Dim W_oTbl As ListObject
Application.EnableEvents = False
With W_oTbl
.ListRows.Add alwaysinsert:=True
With .ListRows(.ListRows.Count)
.Range(1).Offset(-1).Copy .Range(1)
.Range.Offset(-1).Copy
.Range.PasteSpecial xlPasteFormats
End With
End With
Application.EnableEvents = True
Application.CutCopyMode = False
Set W_oTbl = Nothing
End Sub
|
di Vecchio Frac data: 01/12/2013 12:07:48
Vabbè, era più facile di quel che pensassi ^_^
Modifica l'If dell'evento Worksheet_Change come segue.
La stessa modifica va fatta nel foglio per Word, solo che invece di [excel_tab] metterai [word_tab] (così tu stesso hai chiamato le tabelle ^_^)
Private Sub Worksheet_Change(ByVal Target As Range)
Dim nome As String
If Not Intersect(Target, [excel_tab].Columns(4)) Is Nothing And Target(1) <> "" Then
....
end sub |
di Perry (utente non iscritto) data: 02/12/2013 18:13:10
Perfetto funziona tutto, mi rimane un unico dubbio sul range "D:D".:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim nome As String
If Not Intersect(Target, [excel_tab].Columns(4)) Is Nothing And Target(1) <> "" Then
nome = Target(1).Text
If Application.CountIf(Range("D:D"), nome) > 1 Then ' <--- ? perchè rimane questo Range
Application.EnableEvents = False
MsgBox "Titolo già inserito", , "EXCEL"
Target = ""
Application.EnableEvents = True
Target.Select
End If
End If
End Sub
Spero di non abusare troppo della vostra disponibilità in ogno caso grazie 1+2K
di Vecchio Frac data: 02/12/2013 19:52:27
Bè sì, hai ragione a evidenziare l'incongruenza nel senso che dovrebbe essere
If Application.CountIf([excel_tab].Columns(4), nome) > 1 Then
visto che poco sopra abbiamo deciso di testare soltanto la zona della colonna D relativa a Excel_Tab.
All'atto pratico non cambia niente.
All'atto teorico invece direi che è un filino più performante e, dal punto di vista del programma, anche più logicamente corretto.
Fai la stessa modifica anche all'evento del foglio relativo a Word... se riesco ti getto le basi epr rivedere l'impianto del programma in modo da non duplicare i codici degli eventi _Change.
di Perry (utente non iscritto) data: 03/12/2013 18:14:17
OK, ho allineato tutto e funziona perfettamente, resto in attesa della revisione del progetto (la curiosità è femmina).
Grazie 1+2+3K
di Vecchio Frac data: 03/12/2013 21:59:24
Il tuo progetto mi piace e, pur con la difficoltà che ho a far girare bene questa macchina virtuale, ci darò un'occhiata volentieri asap.
di Perry (utente non iscritto) data: 15/12/2013 19:23:32
Attendo con curiosità.
Nel frattempo potresti spiegarmi la differenza che esiste nello strutturare le celle in una tabella piuttosto che limitarsi ad un insieme con NOME ?
Come puoi vedere ero partito con quest' ultimo metodo e mi è stato suggerito di trasformare l' insieme in una tabella (Grograman), cosa che ho fatto ma non ho capito il perchè.
Grazie per le presiose risposte.
Perry
Vuoi Approfondire?