Condividi tramite

Inserimento progressivo di valori tramite macro.

Anonimo
2020-01-17T23:53:24+00:00

Ciao,

a prescindere che il risultato, grazie ai vari suggerimenti del forum, l'ho già ricavato, mi farebbe piacere capire se per caso ho esagerato ad inserire troppo codice rispetto ad un risultato secondo me piuttosto banale.

Dunque, quello che a me serve è, ad ogni click di un pulsante, copiare il valore che il quel momento si trova nella cella E11 e incollarlo nella colonna A : A dell'altro foglio di lavoro chiamato STORICO partendo dalla cella A2.

Il codice usato è il seguente:

Option Explicit

Public Function LastRow(SH As Worksheet, _

                        Optional Rng As Range, _

                        Optional minRow As Long = 1)

    Dim bProtected As Boolean

    With SH

        If Rng Is Nothing Then

            Set Rng = .Cells

        End If

        bProtected = .ProtectContents = True

        If bProtected Then

            Application.ScreenUpdating = False

        End If

    End With

    On Error Resume Next

    LastRow = Rng.Find(What:="*", _

                       after:=Rng.Cells(1), _

                       Lookat:=xlPart, _

                       LookIn:=xlFormulas, _

                       SearchOrder:=xlByRows, _

                       SearchDirection:=xlPrevious, _

                       MatchCase:=False).Row

    On Error GoTo 0

    If LastRow < minRow Then

        LastRow = minRow

    End If

    Application.ScreenUpdating = True

End Function

Sub Vinta_Click()

Dim SH As Worksheet

Dim srcRng As Range, destRng As Range

Dim LRow As Long

    Set SH = ThisWorkbook.Worksheets("STORICO")

    With SH

        LRow = LastRow(SH, .Columns("A:A"))

        Set destRng = .Range("A" & LRow)

    End With

    With destRng

        .Cells(2, 1) = Range("E11")

    End With

End Sub

Vladimiro

Microsoft 365 e Office | Excel | Per la casa | Windows

Domanda bloccata. Questa domanda è stata eseguita dalla community del supporto tecnico Microsoft. È possibile votare se è utile, ma non è possibile aggiungere commenti o risposte o seguire la domanda.

0 commenti Nessun commento

Risposta accettata dall'autore della domanda

Anonimo
2020-01-18T12:19:17+00:00

Scusami Vlad,

Public Sub Vinta_Click()    Worksheets("STORICO").Range("A" & Worksheets("STORICO").Range("A" & Rows.Count).End(xlUp).row + 1) = ActiveSheet.Range("E11")End Sub

Ovviamente il tasto deve essere nel foglio dal quale prendi i dati di E11, altrimenti devi cambiare

ActiveSheet.Range("E11")

in 

Worksheets("NomeFoglioDatiE11").Range("E11")

Ovviamente non metto in dubbio quello che ha scritto Normann ma probabilmente lo scopo era un altro, nel tuo caso partire dall'ultima riga e cercare la prima occupata in alto (.End(xlUp)) e' piu che sufficiente oltre che meglio performante. Come ti ho detto .End(xlUp) cerca la prima cella occupata da testo/formule, e' la stessa cosa di fare CTRL+Freccia Su partendo dal basso, per ottenere quella immediatamente successiva e quindi vuota, basta aggiungere un .Offset(1) oppure + 1 alla riga come ho fatto io.

Spero sia chiaro.

Saluti,

Daniele

La risposta è stata utile?

1 persona ha trovato utile questa risposta.
0 commenti Nessun commento

7 risposte aggiuntive

Ordina per: Più utili
  1. Anonimo
    2020-01-19T13:07:32+00:00

    Ciao Vladimiro,

    Visto i commenti di Daniele in relazione alla mia funzione LastRow, vorrei offire i seguenti chiarimenti:

    La versione generica della funzione è:

    '=========>>

    Public Function LastRow(SH As Worksheet, _

                            Optional Rng As Range, _

                            Optional minRow As Long = 1, _

                            Optional sPassword As String)

        Dim bProtected As Boolean

        With SH

            If Rng Is Nothing Then

                Set Rng = .Cells

            End If

            bProtected = .ProtectContents = True

            If bProtected Then

                .Unprotect Password:=sPassword

            End If

        End With

        On Error Resume Next

        LastRow = Rng.Find(What:="*", _

                           After:=Rng.Cells(1), _

                           Lookat:=xlPart, _

                           LookIn:=xlFormulas, _

                           SearchOrder:=xlByRows, _

                           SearchDirection:=xlPrevious, _

                           MatchCase:=False).Row

        On Error GoTo 0

        If LastRow < minRow Then

            LastRow = minRow

        End If

        If bProtected Then

            SH.Protect Password:=sPassword

        End If

    End Function

    '<<=========

    • La lunghezza della funzione ha ben poco da fare con la sua efficienza o la velocità di esecuzione;  un codice lungo può essere molto più veloce di un'istruzione di una sola riga. Detto questo, la verbosità del codice non necessaria dovrebbe essere evitata :-) A questo proposito, il tempo di esecuzione della funzione e piccolissimo. Utilizzando il mio computer più vecchio (più di 10 anni e con pochissima memoria) il tempo di esecuzione per 100 chiamate alla funzione è stato misurato in centesimi di secondo. Puoi verificarlo con la seguente semplice procedura:

    '=========>>

    Public Sub Tester()

        Dim i As Long

        Dim dStart As Double, elapsedTime as double

        dStart = Timer

        For i = 1 To 100

            Call LastRow(ActiveSheet)

        Next i

        elapsedTime = Timer - dStart

        Call MsgBox( _

             Prompt:=elapsedTime, _

             Buttons:=vbInformation, _

             Title:="TEMPO DI ESECUZIONE")

    End Sub

    '<<=========

    • L'uso del codice proposto da Daniel è soggetto ad alcune limitazioni che di solito sono sufficienti per dissuadermi dal suo uso. Ad esempio, il codice di Daniel ignorerà le righe nascoste nella parte inferiore dei dati e poiché restituirà solo informazioni per la colonna specificata, non può essere utilizzato in modo affidabile per trovare l'ultima riga popolata
    • Poiché quasi tutti i miei progetti di codice richiedono la definizione della prima riga vuota, è conveniente per me includere la mia funzione nella mia Personal.xlsb anziché dover riscrivere le istruzioni ogni volta.
    • In conclusione, Daniel suggerisce che non è corretto dichiarare nomi di variabili in lettere maiuscole. Non sono d'accordo: il suggerimento di Daniel rappresenta solo una convenzione adottata da alcuni programmatori; ci sono altre convenzioni e, secondo la mia modesta opinione, i fattori decisivi in qualsiasi convenzione di denominazione dovrebbero essere chiarezza e coerenza. A questo proposito, potrebbe essere interessante vedere i commenti di Chip Pearson:

    Many programmers prefer to use what is called Hungarian Notation (so named because the originator of this method was Hungarian-born Charles Simonyi, first at Xerox PARC and later a top level software architect at Microsoft). In Hungarian Notation, every variable name begins with letters that identify the data type. For example, anInteger type variable would be named intCounter, where the int prefix indicates that this is an Integertype. I have never adopted Hungarian Notation in straight VBA code, but I always use it when naming controls on a form. If you like the idea behind Hungarian Notation, I encourage you to use it. Just be consistent -- once you decide on a set of identifier prefixes, use them consistently in all your code.

    Personalmente, utilizzo invariabilmente lettere maiuscole per una variabile che rappresenta una cartella di lavoro o un foglio e non vedo alcun motivo per cambiare la mia pratica.

    Nulla di ciò che ho scritto dovrebbe essere interpretato come una polemica: è perfettamente possibile che la gente abbia opinioni diverse e io ho semplicemente voluto ristabilire l'equilibrio.

    ===

    Regards,

    Norman

    La risposta è stata utile?

    0 commenti Nessun commento
  2. Anonimo
    2020-01-18T15:20:41+00:00

    Scusami Vlad,

    Public Sub Vinta_Click()    Worksheets("STORICO").Range("A" & Worksheets("STORICO").Range("A" & Rows.Count).End(xlUp).row + 1) = ActiveSheet.Range("E11")End Sub
    

    Ovviamente il tasto deve essere nel foglio dal quale prendi i dati di E11, altrimenti devi cambiare

    ActiveSheet.Range("E11")

    in 

    Worksheets("NomeFoglioDatiE11").Range("E11")

    Ovviamente non metto in dubbio quello che ha scritto Normann ma probabilmente lo scopo era un altro, nel tuo caso partire dall'ultima riga e cercare la prima occupata in alto (.End(xlUp)) e' piu che sufficiente oltre che meglio performante. Come ti ho detto .End(xlUp) cerca la prima cella occupata da testo/formule, e' la stessa cosa di fare CTRL+Freccia Su partendo dal basso, per ottenere quella immediatamente successiva e quindi vuota, basta aggiungere un .Offset(1) oppure + 1 alla riga come ho fatto io.

    Spero sia chiaro.

    Saluti,

    Daniele

    Ciao Daniele,

    adesso va bene.

    Grazie e alla prossima,

    Vladimiro

    La risposta è stata utile?

    0 commenti Nessun commento
  3. Anonimo
    2020-01-18T10:36:20+00:00

    Ciao Vladimiro e bentornato tra noi! 

    ormai ci conosciamo! 

    Grazie Daniele.

    Ho notato un po di cose che possono essere migliorate in termini di qualità di scrittura del codice. 

    Proprio quello che cerco di ottenere.

    1. E' cosa buona e giusta evitare di splittare le dichiarazioni di funzioni su più righe se non sono poi cosi lunghe. 
    2. Inutile dichiarare una variabile che viene utilizzata una sola volta, preferisci in questi casi un utilizzo in loco, bProtected non serve a niente, fai il check direttamente nell'if. 
    3. A che ti serve disabilitare l'update dello schermo se il foglio e' protetto? O meglio, se serve, perche non farlo a prescindere senza controllare niente? 
    4. le variabili si dichiarano utilizzando la convenzione camelCase e comunque mai usando tutte le lettere maiuscole (SH) 

    Bene.

    Infine, dopo averti dato questi consigli per un futuro voglio dirti che la funzione LastRow non serve a nulla, 

    L'ho copiata da una risposta di Norman per un problema abbastanza simile ed è proprio il motivo dell'apertura di questo thread.

    1. Per trovare l'ultima riga usata del foglio usa .End(xlUp) 

    Suggerimento molto utile!

    Pertanto la tua mega funzione si riduce in: 

    Sub Vinta_Click()
    Dim ws As Workwseet
    Dim destrng As Range
        Set ws = ThisWorkbook.Worksheets("STORICO")
        Set destrng = ws.Range("A" & Range("A" & rows.count).end(xlUp).row + 1)
        destrng = Range("E11")
    End Sub
    

    o ancora più estremo in una sola riga di codice 

    Sub Vinta_Click()
    ThisWorkbook.Worksheets("STORICO").Range("A" & ActiveSheet.Range("A" & rows.count).end(xlUp).row + 1) = ActiveSheet.Range("E11")
    End Sub
    

    Purtroppo i conti non tornano, nel senso che mi incolla sempre sulla stessa cella A2 dello STORICO, mentre io ho bisogno che mi incolli man mano a scendere in colonna:

    ==================================================================

    ... incollarlo nella colonna A : A dell'altro foglio di lavoro chiamato STORICO partendo dalla cella A2.

    ==================================================================

    A2

    A3

    A4

    A5

    ...

    A1000

    ps

    ws è stata dichiarata male.

    Vladimiro

    La risposta è stata utile?

    0 commenti Nessun commento
  4. Anonimo
    2020-01-18T01:14:07+00:00

    Ciao Vladimiro e bentornato tra noi!

    ormai ci conosciamo!

    Ho notato un po di cose che possono essere migliorate in termini di qualità di scrittura del codice.

    1. E' cosa buona e giusta evitare di splittare le dichiarazioni di funzioni su più righe se non sono poi cosi lunghe.
    2. Inutile dichiarare una variabile che viene utilizzata una sola volta, preferisci in questi casi un utilizzo in loco, bProtected non serve a niente, fai il check direttamente nell'if.
    3. A che ti serve disabilitare l'update dello schermo se il foglio e' protetto? O meglio, se serve, perche non farlo a prescindere senza controllare niente?
    4. le variabili si dichiarano utilizzando la convenzione camelCase e comunque mai usando tutte le lettere maiuscole (SH)

    Infine, dopo averti dato questi consigli per un futuro voglio dirti che la funzione LastRow non serve a nulla,

    1. Per trovare l'ultima riga usata del foglio usa .End(xlUp)

    Pertanto la tua mega funzione si riduce in:

    Sub Vinta_Click()
    Dim ws As Workwseet
    Dim destrng As Range
        Set ws = ThisWorkbook.Worksheets("STORICO")
        Set destrng = ws.Range("A" & Range("A" & rows.count).end(xlUp).row + 1)
        destrng = Range("E11")
    End Sub
    

    o ancora più estremo in una sola riga di codice

    Sub Vinta_Click()
    ThisWorkbook.Worksheets("STORICO").Range("A" & ActiveSheet.Range("A" & rows.count).end(xlUp).row + 1) = ActiveSheet.Range("E11")
    End Sub
    

    Saluti.

    La risposta è stata utile?

    0 commenti Nessun commento