Pagina precedente | 1 | Pagina successiva
Vota | Stampa | Notifica email    
Autore

Macro per funzione "somma.più.se"

Ultimo Aggiornamento: 31/12/2013 15:25
Post: 6
Registrato il: 09/08/2013
Età: 41
Utente Junior
Excel 2013
OFFLINE
31/12/2013 10:46

Buongiorno a tutti!

Premesse:
1) Uso excel 2013
2) Conoscenza di VBA: abbastanza scarsa

Negli ultimi tempi, mi trovo spesso ad utilizzare il componente aggiuntivo "Analisi dati" (Funcres.xlam), in particolare lo strumento "Statistica descrittiva"; per chi non lo conoscesse, lo strumento non fa altro che calcolare una serie una di funzioni (media, moda, mediana, varianza, curtosi ecc. ecc.) a partire da un set di dati che l'utente può selezionare tramite l'interfaccia del componente aggiuntivo.

Ora, altrettanto spesso i miei dati di partenza devono essere "splittati" in diversi gruppi, a seconda del valore che assumono delle variabili in alcune colonne; una volta splittati, posso procedere con il calcolo delle statistiche descrittive sui singoli gruppi.

Di per sè, la cosa non è difficile, ma fa sprecare parecchio tempo. Al che ho pensato che potrei superare il problema creando una macro che possa permettermi di ottenere le statistiche descrittive di cui ho bisogno senza organizzare preventivamente i dati. Questo posso farlo, ad esempio, con la media (media.più.se) e il conteggio (conta.più.se), ma non con altre (mediana, moda, varianza ecc.). Però al momento la cosa non mi interessa, preferisco concentrarmi sulla sola media, poi quando avrò acquisito dimestichezza con vba proverò a calcolare anche le altre funzioni.

Ho fatto una prova, creando una macro per il calcolo della funzione "somma.più.se". L'ho creata utilizzando la "registrazione" delle operazioni, quindi non ho scritto manualmente i comandi. Vi allego il file con i dati di partenza e la macro.

Cerco di spiegarvi come sono strutturati i dati di partenza e cosa ho fatto con la macro. (sperando di riuscirci... scusate ma non sono un fenomeno con le spiegazioni :))

Dunque: il file contiene dei dati inventati da me, organizzati in quattro colonne:
A) "Squadra": il nome di una squadra di calcio di serie A
B) "Giocatore": il nome di un possibile nuovo acquisto al calciomercato
C) "Ruolo": il ruolo ricoperto dal giocatore (quattro possibili valori: "P", "D", "C", "A")
d) "Costo": il costo legato all'acquisto del giocatore
I dati iniziano dalla riga 2 e arrivano alla riga 17; nella riga 1 vi sono, ovviamente, le intestazioni delle colonne.

Messi dentro i dati, ho fatto partire la registrazione della macro; come detto in precedenza, la macro ha come obiettivo quello di creare una tabella che mi faccia vedere quanto ha speso ogni squadra in ogni ruolo (quindi nella tabella riassuntiva non mi servono i nomi dei giocatori), utilizzando la funzione "somma.più.se".

Al termine della registrazione, ho aggiunto dei commenti ad alcuni passaggi della macro e 5-6 domande: sarei davvero felice se deste un'occhiata e mi deste un feedback; per i commenti, potreste aiutarmi a capire se ho ben capito le operazioni descritte dalle porzioni di codice; per le domande, ovviamente, potreste darmi risposte che reputo fondamentali per migliorare la macro e, più in generale, per capire meglio come funziona vba.

Ho ritenuto opportuno lasciare le domande all'interno del codice e non riportarle qui perchè mi sembrano meglio contestualizzate e più facili da capire guardando anche il codice. Tuttavia, se lo ritenete opportuno, posso copiarle e incollarle anche in questo post.

Ho altre due domande che mi frullano in testa e ve le faccio qui:
1) Il file di dati di esempio da me creato contiene 4 colonne e 17 righe; la macro da me registrata è "tarata" (almeno credo) sull'intervallo A1:D17; come posso fare per rendere valida la macro anche quando ho 100, 200 o 10.000 righe? Voglio dire, come posso "slegare" le operazioni da realizzare dal numero di righe, in modo che i calcoli vengano fatti su tutte le righe contenenti dati utili?
2) Con la seconda domanda vi propongo una possibile risposta alla prima: potrei selezionare gli intervalli di dati che mi interessano all'inizio, tramite una cosa simile a quella che vedete nell'immagine png allegata (non so come si chiami...); potrei fare diverse "selezioni": selezionare tutti i dati da sommare (segnalando che le intestazioni devono essere selezionate), selezionare la colonna con la prima variabile (quella da mettere in riga) e selezionare la colonna con la seconda variabile (quella da mettere in colonna). Eccoci alla domanda: come si fa a far "comparire" quella finestra che permette di selezionare un intervallo di celle? Cercando qui e là ho trovato qualcosa di simile con "InputBox", ma ovviamente non è quello che mi serve.

Vi ringrazio anticipatamente per aver letto il mio post e per tutto l'aiuto che vorrete/potrete darmi!! ;)
Excel 2013
Post: 965
Registrato il: 27/10/2003
Città: SESTO SAN GIOVANNI
Età: 43
Utente Senior
2010
OFFLINE
31/12/2013 10:56

Allora... intanto complimenti per l'esposizione, non è cosa di tutti i giorni vedere un post con una spiegazione CHIARA!
Un pò meno per l'esempio scelto, sono allergico al calcio [SM=g27828]

Ma passiamo al codice.
Sicuro di voler iniziare proprio con una tabella pivot creata da zero?
Cioè, io se vuoi ci metto poco a ribaltare quel codice per fare una pivot, ne ho già in una dozzina di versioni di porzioni di codice che pivottizzano, ma temo che ti risulterebbe alquanto ostrogotico [SM=g27820]

Ti consiglio di lasciarle per più avanti le pivot...
Inizia con farla a mano, registrati mentre la aggiorni e vedrai che avrai meno difficoltà.

Se invece vuoi proprio crearla ex novo ti propongo lo stesso codice in altra forma!

Ora continuo a leggere le domande! [SM=x423028]

________________________________
Excel 2010 - Win 7 Ufficio
Excel 2013 - Win 8 Casa

A poche informazioni corrispondono poche spiegazioni.
Post: 966
Registrato il: 27/10/2003
Città: SESTO SAN GIOVANNI
Età: 43
Utente Senior
2010
OFFLINE
31/12/2013 11:29

Intanto prova quesot codice, prima incollalo su word, poi passalo nell'editor VBA:

Option Explicit
Sub Prova()
''''''''''PER ULTERIORI APPROFONDIMENTI RIMANDO TUTTO ALLA GUIDA IN LINEA, SELEZIONA LA VARIABILE E PREMI F1'''''''''''
''''LE ALTERNATIVE AL CODICE, MERAMENTE DIDATTICHE, LE TROVI INDICATE E COMMENTATE AFFINCHE' NON VENGANO ESEGUITE''''''


'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
''''''' PRIMA DOMANDA: Come fare per dare un nome scelto da me al foglio??
Dim wb As Workbook 'variabile di tipo "Cartella di lavoro", semplificando molto, un file excel
Dim ws As Worksheet 'variabile di tipo "Foglio", appartiene al gruppo "Worksheets", sottoinsieme della variabile precedente
Set wb = ThisWorkbook 'iniziamo subito con la paternità degli oggetti, la variabile viene istanziata sul file da cui lanci la macro

' Aggiungo un nuovo foglio
Set ws = wb.Worksheets.Add 'come vedi abbiamo aggiunto A QUALE FILE aggiungere il foglio

'Lo rinomino
ws.Name = "Nuovo Foglio del " & Format(Now, "ddmmyyyyhhmms") '*
'* "Now" è un aggiunta per non bloccare il codice se tentasse di rinominare un foglio con un nome già esistente
' non prenderlo come buon esempio, è solo una scorciatoia
''''ALTERNATIVE
'Set ws = wb.Worksheets("Mercato") 'se conosci già il foglio ed esiste nel workbook
'Set ws = wb.Worksheets(1) 'se vuoi usare il numero del foglio (index)
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''


''''''' SECONDA DOMANDA: esiste un metodo più veloce/efficiente per fare questa operazione?
'''PREPARATI, SI VA SUL COMPLICATO!
  Dim oPvtCch As PivotCache
  Dim oPvtTbl As PivotTable
  Dim ptField As PivotField
  Dim ptItem As PivotItem
  Dim wsDati As Worksheet
  Dim rngDati As Range
  Dim lngUltRiga As Long
  
  Set wsDati = wb.Worksheets("Mercato") '"iltuofoglio"
  
  '''PARENTESI CHE RICHIAMA LA DOMANDA SULLA RIGA VARIABILE
  lngUltRiga = wsDati.Range("A" & wsDati.Rows.Count).End(xlUp).Row
  Set rngDati = wsDati.Range("A1:D" & lngUltRiga) '"iltuorange"
  
  Set oPvtCch = wsDati.Parent.PivotCaches.Create(SourceType:=xlDatabase, SourceData:=rngDati)   'crea cache per tabella dal range
  Set oPvtTbl = oPvtCch.CreatePivotTable(ws.Cells(2, 2))  'crea pivot nel foglio aggiunto alla prima domanda

  With oPvtTbl
 'Inserisco i campi che mi interessano nella tabella pivot: "squadra" in riga, "ruolo" in colonna
    .RowAxisLayout xlOutlineRow
    '.Name = wsDati.Name
    .PivotFields(1).Orientation = xlRowField    '"squadra" in riga
    .PivotFields(1).Position = 1
    .PivotFields(3).Orientation = xlColumnField    '"ruolo" in colonna
    .PivotFields(3).Position = 1
    For Each ptItem In .PivotFields(1).PivotItems
      If ptItem.Caption = "(blank)" Then ptItem.Visible = False 'tolgo eventuali campi vuoti
    Next
    '.PivotFields(6).PivotItems("(blank)").Visible = False
    .AddDataField .PivotFields(4), "Costo Squadra", xlSum    'Somma importo
    .PivotFields("Costo Squadra").NumberFormat = "_(* #,##0.00_);_(* (#,##0.00);_(* ""-""??_);_(@_)"    'formatto importi
    .RowAxisLayout xlTabularRow
    .TableStyle2 = "PivotStyleMedium9" 'stile tabella
  End With

'''PER ORA FERMIAMOCI QUI PERCH' NON HO CAPITO DOPO COSA DEVI FARE, MA SOPRATUTTO STANNO APRENDO LO SPUMANTE DI LA'!
''DISTRUGGO GLI OGGETTI CREATI PRIMA
  Set oPvtCch = Nothing
  Set oPvtTbl = Nothing
  Set rngDati = Nothing
  Set ws = Nothing
  Set wsDati = Nothing
  Set wb = Nothing
End Sub
[Modificato da Davide Turbo Neofita 31/12/2013 11:29]
________________________________
Excel 2010 - Win 7 Ufficio
Excel 2013 - Win 8 Casa

A poche informazioni corrispondono poche spiegazioni.
Post: 6
Registrato il: 09/08/2013
Età: 41
Utente Junior
Excel 2013
OFFLINE
31/12/2013 12:06

RE:
Davide, grazie mille!!!

Relativamente alla questione pivot, ti spiego meglio perchè l'ho usata:

di solito, i file che utilizzo contengono decine di migliaia di righe e, pertanto, le variabili "discriminanti" che metto in riga e colonna nella tabella riassuntiva possono assumere centinaia di valori distinti. Automatizzare anche questa parte della procedura è, pertanto, fondamentale per i miei scopi.

Detto questo, come ho scritto anche nei commenti della macro, accetto qualsiasi tipo di suggerimento che possa portare ad aggirare la creazione di una pivot; un'ipotesi potrebbe essere, ad esempio, copiare e incollare le colonne "discriminanti" in un altro foglio, applicare per ogni colonna "rimuovi duplicati" e poi utilizzare ciò che rimane per fare le intestazioni di riga e di colonna.
Excel 2013
Post: 968
Registrato il: 27/10/2003
Città: SESTO SAN GIOVANNI
Età: 43
Utente Senior
2010
OFFLINE
31/12/2013 12:29

Ariciao!

Se ne parla giovedì vista l'ora, ma a questo punto ti invito a postare un file con la struttura reale dei dati (privo di dati sensibili) in modo da trovare prima la soluzione migliore (o la meno peggio) per il tuo scopo!

Ovviamente anonimizzando i dati.
Mi è chiaro lo scopo, ma vedendo i dati sicuramente si sprecano meno idee!

Per esempio, usare una collection magari è più utile al tuo scopo, prova questo codice sul file postato:

Option Explicit

Sub unique()
  Dim rFonte As Range, rCella As Range
  Dim arrUnico As Collection
  Dim wb As Workbook
  Dim ws As Worksheet
  Dim i As Long
  Set wb = ThisWorkbook
  Set ws = wb.Worksheets("Mercato")
  Set arrUnico = New Collection
  
  With ws
     i = .Range("A" & .Rows.Count).End(xlUp).Row 'ultima riga
     Set rFonte = .Range("A2:A" & i)
  End With
  
   
  'alimento collection con valori univoci
  On Error Resume Next
  For Each rCella In rFonte
    arrUnico.Add rCella, rCella
  Next rCella

  'li riporto nella colonna H del foglio stesso
  For i = 0 To arrUnico.Count
    ws.Cells(i + 1, 8) = arrUnico(i)
  Next

  Set rFonte = Nothing
  Set wb = Nothing
  Set ws = Nothing
  Set arrUnico = Nothing
End Sub


________________________________
Excel 2010 - Win 7 Ufficio
Excel 2013 - Win 8 Casa

A poche informazioni corrispondono poche spiegazioni.
Post: 7
Registrato il: 09/08/2013
Età: 41
Utente Junior
Excel 2013
OFFLINE
31/12/2013 15:25

re
Ancora grazie per il supporto ;)

Allora ti giro un file che presenta caratteristiche simili ai file che analizzo tutti i giorni: i dati sono stati generati in maniera totalmente casuale e mancano una ventina di colonne di dati, ma ad occhio e croce la base è simile a quella che vedi.

A questo punto riprendo un tema che ho già evidenziato nel primo post e al quale forse avrei dovuto dare più rilevanza: visto che le colonne che utilizzo per fare i miei conteggi non sono sempre le stesse (nè la variabile da conteggiare, nè le variabili da mettere in riga/colonna) è fondamentale poter scegliere da quali colonne prendere i dati di volta in volta.
Excel 2013
Vota:
Amministra Discussione: | Chiudi | Sposta | Cancella | Modifica | Notifica email Pagina precedente | 1 | Pagina successiva
Nuova Discussione
 | 
Rispondi
Cerca nel forum
Tag discussione
Discussioni Simili   [vedi tutte]
Feed | Forum | Bacheca | Album | Utenti | Cerca | Login | Registrati | Amministra
Tutti gli orari sono GMT+01:00. Adesso sono le 03:57. Versione: Stampabile | Mobile | Regolamento | Privacy
FreeForumZone [v.6.1] - Copyright © 2000-2024 FFZ srl - www.freeforumzone.com