Conta celle



  • Conta celle
    di Leopold data: 20/10/2012 19:02:19

    Buongiorno a tutti sono alle prime con vba,
    ma qualcosa ho imparato leggendo qua e la in rete.
    Ovviamente la mia conoscenza rimane comunque
    di base ed ogni volta che trovo un problema mi
    appare come insormontabile.

    Ora il quesito è questo:
    in una colonna di excel ho una serie di valori che possono essere
    testo o numero non ha importanza. So come contare i valori delle celle attive, ma non riesco a separarli per il dato presente. Vengo all'esempio pratico per farmi capire meglio.
    Nella colonna A ho una serie di xxxxxxyyyyyyxxxxxyyxxxxxyyyy

    ora come faccio a restituire in una serie di celle (contigue o non, non ha importanza) i valori di x e di y
    che in questo caso sarebbero: 6 - 6 - 5 - 2 - 5 - 4
    Sono stato chiaro?

    Vi ringrazio!



  • di HarryBosch data: 20/10/2012 20:27:36

    Mi sembra di aver capito cosa vuoi realizzare.
    Credo che si potrebbe ciclare il contenuto della cella, passando tutte le lettere (o numeri) uno a uno e, nel momento in cui il valore considerato risulti diverso da precedente, partire con un nuovo conteggio.
    Vediamo se riesco a scriverti subito l'algoritmo, altrimenti le ore notturne sono per me più produttive



  • di HarryBosch data: 20/10/2012 20:49:29

    scrivi la tua stringa in A1 e prova questa routine

    Però mi è venuto il dubbio se invece di contare i valori, non vuoi invece proprio i valori divisi per celle..
     
    Sub conta_valori_cella()
        Dim x As Integer, i As Integer, col As Integer
        Dim conta As Integer, a As String, b As String
        a = ""
        b = ""
        col = 2
        x = Len([a1])
        For i = 1 To x
            a = Mid([a1], i, 1)
            conta = conta + 1
            If i > 1 And a <> b Then
                Cells(1, col) = conta - 1
                col = col + 1
                conta = 1
            ElseIf i = x Then
                Cells(1, col) = conta
            End If
            b = a
        Next
    End Sub
    



  • di Vecchio Frac data: 20/10/2012 20:50:36

    Voglio dare una mano anch'io (a Vanni, ma nessuno vieta a chiunque di provare a scrivere da solo il codice secondo un algoritmo diverso ^_^).
    Io ti suggerisco di fare così:
    - Usa una Collection per ottenere con pochissimo sforzo un elenco di valori univoci (scorri la stringa, aggiungi alla Collection l'elemento con chiave uguale a se stesso, ogni volta che aggiungi un valore con la stessa chiave si genera un errore che puoi saltare con On Error Resume Next... alla fine avrai una Collection con i valori presi una volta sola)
    - Usa il codice che posto qui per avere rapidamente un conteggio di una sottostringa in una stringa (es. count_of("xxxyy", "x") restituisce 3). Avendo la Collection in mano, con un For Each per ogni elemento avrai il conteggio richiesto, che potrai restituire o in un'altra Collection, o in un'Array, o in una String (come sembra richiedere Leopold).

    Buon lavoro :)

     
    Function count_of(text As String, find As String) As Integer
        count_of = Len(Replace(text, find, find & "*")) - Len(text)
    End Function






  • di Vecchio Frac data: 20/10/2012 20:52:51

    Vedo solo ora il nuovo post di Vanni.
    Carino e funziona, ma, chissà perchè, l'idea di sporcare il foglio non mi piace.. preferisco un risultato in memoria, quindi una funzione che restituisce un valore al chiamante, che poi l'utente può manipolare a piacimento.
    De gustibus, per restare in tema in latino ^_^





  • di HarryBosch data: 20/10/2012 20:58:23

    eventualmente fai queste due aggiunte:
    - subito sotto "il For i" metti
    Cells(2, col) = Cells(2, col) & a

    - e dopo "ElseIf i = x" metti ancora
    Cells(2, col) = Cells(2, col) & a

    e così ottieni anche la divisione dei valori.



  • di Vecchio Frac data: 21/10/2012 09:08:43

    Ecco la mia proposta per il quesito.
    Inserito in un modulo il codice mette a disposizione a Function alla quale va passato un valore stringa (anche una cella di Excel) che restituisce una stringa con l'elenco dei singoli elementi che compongono la stringa e il numero di loro ripetizioni. La forma che ho scelto per la rappresentazione è simile a quella dei "dizionari" di Python visto che son strutture flessibili e molto potenti, che rappresentano coppie di dati nella forma "chiave:valore" :)

    L'istruzione:
    result = conta_valori([A1])

    Risultato: "x: 3; y: 2"
     
    Option Explicit
    
    Function conta_valori(s As String)
    Dim my_coll As Collection, i As Integer, v As Variant, m As String
        Set my_coll = New Collection
        On Error Resume Next
        For i = 1 To Len(s)
            my_coll.Add Mid(s, i, 1), Mid(s, i, 1)
        Next
        On Error GoTo 0
        
        For Each v In my_coll
            m = m & v & ": " & count_of(s, v) & "; "
        Next
        
        conta_valori = Replace(m & "@", "; @", "")
    
    End Function
    
    Private Function count_of(ByVal text As String, ByVal find As String) As Integer
        count_of = Len(Replace(text, find, find & "*")) - Len(text)
    End Function






  • di Leopold (utente non iscritto) data: 21/10/2012 09:11:24

    Innanzitutto grazie per darmi una mano.
    Seguendo il consiglio di Harry ho provato ad inserire il codice
    che mi hai consigliato, ma non viene ciò che cerco.
    In pratica seguendo il tuo consiglio avrei un risultato del genere:
    X 1 1
    X x x
    X
    Y
    Y
    X
    Y

    Invece ciò che voglio è questo:
    N° ripetizioni di x N° ripetizioni di y
    X 3 2
    X 1 1
    X
    Y
    Y
    X
    Y
    ecc..

    La stringa più facile per me che ho trovato è questa:
    es: For each Inc in Range("A1:A50")
    If Inc = "x" then
    Dato = Dato +1
    End if
    Next

    Ma purtroppo tale modo come capirete mi restituisce il numero
    totale delle x presenti nel range.



  • di Vecchio Frac data: 21/10/2012 10:00:02

    Il primo codice postato da HarryBosch fa quello che chiedi.
    Certo lo devi adattare perchè ogni cella contiene il valore di ogni elemento diverso incontrato nella stringa :)

    Anche quello che ho postato io lo devi adattare: è più flessibile perchè è generico e universale, ma devi rielaborare il risultato finale con una serie di Split (in "x: 3; y: 2" prima fai SPlit su ; per ottenere x: 3 e y: 2 e poi nuovamente split su : per ottenere il dettaglio di ogni singolo valore).





  • di HarryBosch data: 21/10/2012 13:05:58

    La soluzione proposta da VecchioFrac è sicuramente più carina della mia. Anche li devi adattare il metodo per il riferimento, che non sarà più una stringa in una cella ma la colonna.

    Ti modifico la mia proposta, che come vedrai rimane pressochè identica; cambia solo il riferimento di confronto, che non sarà più determinato scorrendo la stringa (Len... Mid), ma scorendo le righe della colonna (counta...cells(i,1)).

    Nota che viene trovata qualsiasi lettera o parola, anche con successioni di lettere diverse (x,x,w,w,w,z,e,r,r ecc...)
    Se vuoi vedere solo il conteggio, e non anche la lettera di riferimento, basta semplicemente togliere all'interno degli IF:
    b & ": " &
    a & ": " &
     
    Sub conta_cella()
        Dim x As Integer, i As Integer, col As Integer
        Dim conta As Integer, a As String, b As String
        b = ""
        col = 2
        x = [counta(a:a)]
        For i = 1 To x
            a = Cells(i, 1)
            conta = conta + 1
            If i > 1 And a <> b Then
                Cells(1, col) = b & ": " & conta - 1
                col = col + 1
                conta = 1
            End If
            If i = x Then
                Cells(1, col) = a & ": " & conta
            End If
            b = a
        Next
    End Sub



  • di Vecchio Frac data: 21/10/2012 14:00:23

    La mia funzione non fa esattamente quello che chiedeva Leopold :)
    Mentre la variante messa in campo da Vanni con l'ultimo post lo fa bene.
    In pratica, Leopold vuole scorrere il range raggruppando elementi simili e effettuando il conteggio.
    Una sorta di =SUBTOTALE.
    Chissà quindi se WorksheetFunction.Subtotal può venirci in aiuto ;)





  • di Vecchio Frac data: 21/10/2012 17:46:40

    Per esempio:
    Se in colonna A ci sono i valori incolonnati, cella per cella, l'istruzione per creare un subtotale è:
    [A1].Subtotal GroupBy:=1, Function:=xlCount, TotalList:=array(1)

    che naturalmente crea i subtotali al variare dei dati in colonna A e li mette sotto, nel formato usuale per Subtotale.