oggetto range



  • oggetto range
    di orsomiki data: 30/03/2013 07:13:59

    ho scritto il codice per il file di excel allegato
    mi da errore non si posiziona sulla prima cella del range che ho tentato di nominare ( nomiid)
    mi dite per favore che cosa c'è di sbagliato?
    l'idea è quella di cercare nel range indicato tutti i valori che compaiono ripetuti e scriverli in un area a fianco la tabella
    c'è qualche funzione in Excel che lo fa senza ricorrere al codice?
    Grazie
     
    Sub ricercaduplicati()
    Dim nomiid As Range
    Set nomiid = Range("D7:D3695")
    Range("nomiid").Cells(1, 1).Select
    End Sub



  • di Vecchio Frac data: 30/03/2013 09:32:58

    Il Select deve agire solo sulla cella n° 1:
    Range("nomiid").Cells(1).Select

    Non c'è una funzione predefinita per la ricerca dei duplicati.
    Però qui se ne è parlato tante volte; ti passo una mia funzioncina che restituisce una Collection dei valori duplicati.
    Passa alla funzione il range dei valori e ti restituirà una Collection in cui ciclare per ottenere i valori duplicati.
    Ad esempio così (sia A1:A20 un range che contiene valori duplicati):
    set c = duplicates_collection([A1:A20])
    for each v in c
    msgbox v
    next

     
    Function duplicates_collection(vettore As Variant) As Collection
    Dim v As Variant, dups As Collection
        
        Set dups = New Collection
        
        On Error Resume Next
        
        For Each v In vettore
            dups.Add v, CStr(v)
        Next
        
        On Error GoTo 0
        Set duplicates_collection = dups
    
    End Function
    






  • di Textomb data: 30/03/2013 10:34:39

    interessante...
    quell'istruzione riferita all'oggetto collection sarebbe nome e chiave. Giusto?
    L'istruzione estesa sarebbe una cosa del genere...(vd codice)
    Ovviamente hai dovuto inserire On Error Resume Next...
    Ma posso evitare la chiave primaria e quindi l'oggetto collection avrebbe al suo interno anche eventuali duplicati?
    Altra domanda.
    Posso convertire una Collection in un Array?

     
    For Each v In vettore
            dups.Add Item:=v, Key:=CStr(v)
    Next
    



  • di Vecchio Frac data: 30/03/2013 11:50:31

    Item e Key, la denominazione dei parametri è corretta.
    Forse la denominazione della funzione non è del tutto corretta perchè restituisce un elenco univoco degli elementi, non di quelli duplicati soltanto (me ne accorgo adesso che l'ho isolata dalla sua funzione gemella, count_occurrences, la quale serve appunto a stabilire se un elemento della prima collezione ricorre più di una volta nella lista originale).
    Comunque, con finalità didattica:
    - On Error è fondamentale per inserire univocamente gli elementi della lista originale in una collezione se si assegna loro la stessa Key (non si possono avere elementi duplicati in una Collection: ed è il trucco su cui si basa il codice)
    - Item è un parametro obbligatorio, ma Key viene generato automaticamente
    - omettendo On Error e lasciando la Key automatica puoi avere una Collection con tutti gli elementi del range originale
    - puoi avere in modo molto semplice e veloce un array di valori utilizzando WorksheetFunction.Transpose:
    v = WorksheetFunction.Transpose([A1:A10])
    l'array che ne risulta ha base uno invece che zero: v(1 to 10)
    - per trasformare una Collection in Array devi scorrere i suoi elementi e inserirli nell'array
     
    Option Explicit
    
    Function duplicates_collection(vettore As Variant) As Collection
    Dim v As Variant, dups As Collection
        
        Set dups = New Collection
        
        For Each v In vettore
            dups.Add (v)
        Next
        
        Set duplicates_collection = dups
    
    End Function
    






  • di Vecchio Frac data: 30/03/2013 12:37:36

    Ecco qui sotto la correzione della Function precedente, affinchè dato un range di valori restituisca una Collection con i soli valori duplicati.
    Sfrutto allo scopo la funzione CONTA.SE del foglio di lavoro (utilizzata in VBA, fa parte dell'oggetto WorksheetFunctions e bisogna usare la versione inglese della funzione, CountIf).

    Esempio di utilizzo:
    For Each v in duplicates_collection([A1:A10])
    msgbox v
    Next
     
    Function duplicates_collection(vettore As Variant) As Collection
    Dim itm As Variant, duplicates As Collection
    
        Set duplicates = New Collection
        On Error Resume Next
        For Each itm In vettore
            If WorksheetFunction.CountIf(vettore, itm) > 1 Then duplicates.Add itm, CStr(itm)
        Next
        On Error GoTo 0
        Set duplicates_collection = duplicates
    End Function





  • oggetto range
    di orsomiki data: 30/03/2013 12:41:12

    urca che vivacità di risposte
    Grazie boys! proverò tutto poi vi so dire!



  • di Vecchio Frac data: 30/03/2013 12:44:29

    Una proposta per trasformare una Collection in un Array a base zero.

    @orsomiki
    Ho un po' divagato :) ma rimaniamo a disposizione per le applicazioni al tuo caso. Fai sapere.
     
    Function collection_to_array(ByRef coll As Collection) As Variant
    Dim v As Variant, arr() As Variant, i As Integer
        ReDim arr(0 To coll.Count - 1)
        i = 0
        For Each v In coll
            arr(i) = v
            i = i + 1
        Next
    
        collection_to_array = arr()
    
    End Function






  • di Textomb data: 30/03/2013 16:02:34

    Grazie Mille VF.
    Qual è la differenza tra ByRef e ByVal quando crei una Function..?
    Function collection_to_array(ByRef coll As Collection) As Variant



  • di Vecchio Frac (utente non iscritto) data: 30/03/2013 16:54:46

    ByRef si poteva anche omettere.
    Con ByVal, il parametro viene passato come valore (alla funzione viene passata una copia della variabile), eventuali modifiche apportate alla copia non influiscono sul valore della variabile originale passata come parametro.
    Con ByRef, viene invece passato il riferimento alla variabile, cioè la locazione di memoria in cui risiede il dato. Ne consegue che la procedura a cui viene passato il parametro accede direttamente alla variabile in questione e può modificarne il valore in modo permanente, anche dopo l’uscita dalla procedura.
    Di passaggio faccio notare che passando una variabile tra parentesi tonde (val), il parametro viene passato alla funzione come copia, anche se nella firma della stessa era indicato ByRef come modalità di passaggio del parametro.
    L'argomento può sembrare semplice ma è più complicato di così, e comunque nei moderni VB.NET ogni cosa è un oggetto, e ogni cosa è passata per valore, sicchè non è possibile modificare l'oggetto originale.
    Il sito di cpearson.com spiega le cose molto più chiaramente di come posso fare io:
    cpearson.com/excel/byrefbyval.aspx
     
    Sub test()
    Dim num1 As Long, num2 As Long
        num1 = 123
        num2 = 456
        MsgBox "Valori prima della chiamata alla Sub: num1 = " & num1 & "; num2 = " & num2
        test_byref_byval X:=num1, Y:=num2
        MsgBox "Valori dopo la chiamata alla Sub: num1 = " & num1 & "; num2 = " & num2
    End Sub
        
    Sub test_byref_byval(ByRef X As Long, ByVal Y As Long)
        X = 321
        Y = 654
    End Sub


  • oggetto range
    di orsomiki data: 02/04/2013 19:35:32

    ragazzi mi sa che ho fatto il passo più lungo della gamba la mia conoscenza 'non arriva a capire il codice che mi avete scritto e che ho riportato sotto
    l'ho provato e ho visto come agisce ma ... se una cosa non la capisco non c'è verso non riesco ad usarla
    cmq
    correggetemi se sbaglio:
    la mia idea è di esplorare il range a7:a3659 ( almeno fino alla fine delle righe)
    prendere i duplicati e copiarli a fianco della tabella stessa ...
    se qualcuno mi da la spiega del codice scritto anche sinteticamenteùGrazie!
     
    set c = duplicates_collection([A1:A20])
    for each v in c
    msgbox v
    next
    
     
    Function duplicates_collection(vettore As Variant) As Collection
    Dim v As Variant, dups As Collection
        
        Set dups = New Collection
        
        On Error Resume Next
        
        For Each v In vettore
            dups.Add v, CStr(v)
        Next
        
        On Error GoTo 0
        Set duplicates_collection = dups
    
    End Function



  • di Vecchio Frac data: 02/04/2013 20:39:07

    Quel codice, come dicevo, è della prima versione: ti fornisce un insieme di tutti i valori, univocamente considerati, non solamente di quelli duplicati.
    Per ottenere un elenco dei soli valori duplicati (che compaiono più di due volte) devi considerare la routine della sconda versione, con WorksheetFunction.CountIf.






  • di Textomb data: 02/04/2013 20:42:23

    Prova questa routine. Dovrebbe funzionare
    ricopia il codice su un modulo e poi lanciala
    Questa analizza il range che hai chiesto "a1:a3659".
    Nella colonna C riporta solo i valori della colonna A che vengono ripetuti.
    Mentre nella colonna D riporta solo i valori univoci.
    Prima di uscire effettua un ordinamento crescente delle colonne C ed D.
     
    Sub Duplicates()
    Dim R As Variant, V As Variant, z As Integer, NOdups As New Collection, Dups As New Collection
    Set R = [a1:a3659]
    
    Cells(1, 3).CurrentRegion.ClearContents ' Pulisce gli eventuali dati precedenti
    
    On Error Resume Next
    For Each V In R
    NOdups.Add Item:=V, Key:=CStr(V)
        If Err.Number <> 0 Then
        Dups.Add Item:=V, Key:=CStr(V)
        Err.Number = 0
        End If
    Next
    
    [c1] = "Duplicati"
    z = 2 'Lascia la prima riga alla intestazione
    For Each V In Dups
    z = z + 1
    Cells(z, 3).Value = V
    Next
    
    [d1] = "Univoci"
    z = 2 'Lascia la prima riga alla intestazione
    For Each V In NOdups
    z = z + 1
    Cells(z, 4).Value = V
    Next
    
    [c:c].Sort key1:=[c:c], Header:=xlYes ' Ordiniamo i valori della colonna c
    [d:d].Sort key1:=[d:d], Header:=xlYes ' idem ma della colonna d
    
    End Sub