Ordinamento scadenzario con raggruppamento clienti e somma degli importi delle loro fatture.

Fra i diversi metodi che Excel ci offre per ottenere da un elenco, per esempio uno scadenzario, il raggruppamento dei dati relativi ad una chiave prestabilita (per esempio il Codice Cliente o il nominativo Cliente), ottenibili con un filtro, e relativi sub totali del campo "Importo fattura", sempre attraverso le risorse di Excel (menù Dati/Subtotali), presento una soluzione realizzata in vba che non richiede l'uso del filtro. Vediamo un esempio, nella foto sotto vediamo una tipica tabella, che potrebbe essere anche un "Riepilogo Fatture emesse" anzichè uno scadenzario, il concetto non cambia:

Come si nota nell'elenco, i dati non sono raggruppati per Cliente, ma mescolati. Avremo bisogno quindi di eseguire un "ordinamento" in modo da riunire tutti i clienti con lo stesso nome oppure con lo stesso codice cliente, noi scegliamo la chiave "codice cliente". poichè sappiamo da quanti campi (colonne) è formato il nostro elenco, ma non possiamo sapere quante righe occuperà, useremo la funzione End per reperire i "riferimenti" delle ultime celle: sia quella verso il basso (End(xlDown) a partire dalla cella di inizio elenco (la A2), sia quella verso destra (End(xlToRight)) sempre a partire dalla stessa A2. In questo modo selezioneremo tutta l'area dati che ci interessa, e su quell'area applicheremo l'ordinamento usando come chiave di ricerca il codice cliente (SortKey1:= Range("A2")), e queste sono le istruzioni, che assoceremo ad un pulsante:

Sub Ordinadati()

giu = Range("A2").End(xlDown).Address
dx = Range("A2").End(xlToRight).Address

Range(giu & ":" & dx).Select

Selection.Sort Key1:=Range("A2"), Order1:=xlAscending, Header:=xlGuess, _
OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom, _
DataOption1:=xlSortNormal
End Sub

e questo sarà l'effetto dopo l'ordinamento; come di vede, sono stati riuniti tutti i clienti che hanno lo stesso codice uguale:

A questo punto cosa dovremo ottenere:

  • la separazione tra un cliente e l'altro con l'aggiunta di due righe, nella prima delle quali inseriremo la parola "totale" nella colonna B

  • l'inserimento nella colonna E, sempre nella prima delle due righe aggiunte, di una formula che cerchi, a salire, tutti gli importi relativi alle fatture di quel cliente, e sommi gli importi in modo da ottenere un totale cliente.

Per ottenere questo risultato:

  • useremo una InputBox nella quale inseriremo il codice cliente di cui vogliamo il totale.

  • useremo in ciclo di ricerca di questo valore in modo che venga selezionata l'ultima cella che sia uguale al codice indicato.

  • trovata questa cella, selezioniamo la riga immediatamente sotto, e con la cella in quel momento attiva, diciamo di inserire 2 nuove righe. Operazione necessaria visto che l'inserimento riga in Excel avviene sopra la cella (meglio riga) in quel momento selezionata, non sotto.

  • inseriamo nella prima delle due righe (colonna A) un trattino, nella colonna B la parola "totale" e nella colonna E la funzione SOMMA.

questo il codice impiegato:

Sub cerca()
With Worksheets(1).Range("a1:a20")
'range sui cui si opera
'istruzioni per l'imputbox che ti chiede il
'codice cliente

Dim code, mess, titolo
mess = "Inserisci il Codice Cliente :"
titolo = "Inserimento Codice"
code = InputBox(mess, titolo)
'"code" ora è uguale al codice digitato

'inizio il ciclo di ricerca nel range scelto (A1:A20), del valore che
'è stato assegnato a "code"

Set c = .Find(code, LookIn:=xlValues)
If Not c Is Nothing Then
firstAddress = c.Address
Do
'viene individuato l'ultimo "code" trovato e seleziono
'la cella sotto per poter aggiungere due righe

c.Offset(1, 0).Select
Set c = .FindNext(c)
Loop While Not c Is Nothing And c.Address <> firstAddress
End If
End With
'aggiungo due righe
ActiveCell.EntireRow.Insert Shift:=xlDown
ActiveCell.EntireRow.Insert Shift:=xlDown
'inizia l'inserimento nella prima cella di una lineetta (colonna A)
'poi inserisce "totale" nella cella accanto,

ActiveCell = "-"
ActiveCell.Offset(0, 1) = "totale"

'poi controlla la colonna importi, (la E) e ne prende i riferimenti a salire: X sarà uguale al 'riferimento cella attiva + 4, cioè la colonna E, ma la cella nella riga immediatamente 'sopra (-1). Poichè si può verificare il caso che esista un cliente con una sola fattura, 'sarebbe inutile sommare, ed allora eseguiamo un controllo sulla seconda riga a salire, colonna E, Se questa cella conterrà dati (diversa da vuota), allora si ricercano tutte le 'righe a salire con End, per prendere l'ultimo riferimento

If ActiveCell.Offset(-2, 4) <> "" Then
X = ActiveCell.Offset(-1, 4).Address

'poi preso il riferimento dell'ultima cella con End(xlUp) contenete valori Y sarà uguale al riferimento  cella attiva + 4, cioè la colonna E ma alla prima (la più in alto) cella iniziale.

'Ricordo che l'istruzione End cerca l'ultima cella occupata nella direzione indicata dalla 'costante, a partire dalla cella iniziale indicata (in questo caso: ActiveCell) e si ferma 'appena trova una cella vuota.
Y = ActiveCell.Offset(-1, 4).End(xlUp).Address

'indi applica la funzione somma
ActiveCell.Offset(0, 4).Formula = "=SUM(" & X & ":" & Y & ")"

'nel caso previsto che il cliente sia presente con una sola fattura, invece rendiamo il totale 'uguale all'importo della fattura

Else
ActiveCell.Offset(0, 4).Value = ActiveCell.Offset(-1, 4).Value
End If
End Sub

Una nota: perchè la somma si applichi in maniera corretta, sarà necessario procedere rispettando il codice progressivo: se per esempio, si cercasse di ottenere il totale del codice 3402 senza prima avere ottenuto i totali e quindi la separazione con due righe vuote del codice 3401, il codice 3402 verrebbe separato si da quello successivo, ma la somma coinvolgerebbe anche i valori relativi al codice 3401 non essendo separati.

Questa comunque l'immagine del risultato dell'istruzione sopra:

Buon Lavoro.

prelevato sul sito http://ennius.interfree.it