PDA

View Full Version : (VBA/EXCELL '07) - Ciclo con conta ed inserimento


leomac
18-01-2010, 13:46
Salve a tutti,

ho un problema riguardo ad un ciclo di conta. Posto il codiceIf Range("G2").Text <> "" Then
For Each MESE_CONFRONTO In Range(Range("G2"), Range("G2").End(xlDown))
If MESE_CONFRONTO.Text = "" Then Exit For
If MESE_CONFRONTO.Text <> "---" Then
SOMMA = 0
POSTAZIONE_CONFRONTO = MESE_CONFRONTO.Offset(0, 2)
For Each MESE In Range(Range("G2"), Range("G2").End(xlDown))
If MESE.Text = "" Then Exit For
POSTAZIONE = MESE.Offset(0, 2)
If MESE.Text <> "---" And MESE = MESE_CONFRONTO And POSTAZIONE = POSTAZIONE_CONFRONTO Then
NUMERO = MESE.Offset(0, 3).Text
SOMMA = NUMERO + SOMMA
MESE.Offset(0, 4).Value = "---"
End If
Next MESE
Range("A11").Select
Do While ActiveCell <> 0
ActiveCell.Offset(1, 0).Activate
Loop
ActiveCell.Offset(0, 2).Value = MESE_CONFRONTO
ActiveCell.Offset(0, 1).Value = SOMMA
ActiveCell.Offset(0, 0).Value = POSTAZIONE_CONFRONTO
End If
Next MESE_CONFRONTO
End If




In pratica ho quattro colonne.Ora la sub deve sommare i numeri della 3 colonna per ogni postazione e data uguali. Esempio:


1 colonna 2colonna 3colonna 4colonna
mese postazione numero valida
1 102 5
1 103 10
1 102 8



di conseguenza alla fine dovrei avere 102 = 5+8 = 13, 103=10.

Quindi adopero 2 cicli: col primo esamino mese e postazione col secondo, interno al primo, faccio un confronto. Se il confronto risulta valido mi somma il numero e inserisce un simbolo sulla 4 colonna (in questo caso ho optato per ---) che evita di risommare il numero. Tutto pare fungere ma il problema lo trovo nella parte (che ho seganto in rosso):



Range("A11").Select
Do While ActiveCell <> 0
ActiveCell.Offset(1, 0).Activate
Loop
ActiveCell.Offset(0, 2).Value = MESE_CONFRONTO
ActiveCell.Offset(0, 1).Value = SOMMA
ActiveCell.Offset(0, 0).Value = POSTAZIONE_CONFRONTO



difatti mi ritrovo delle copie di postazioni che nn volgio siano presenti.

Avevo pensato ad uscire dal cilco incrementandolo, ma col comando (in verde): For Each MESE In Range(Range("G2"), Range("G2").End(xlDown))
If MESE.Text = "" Then Exit For

If MESE.Offset(0, 4).Value = "---" then Next mese

mi va in debug... Come risolvo. Mi dispiace non poter inserire l'allegato (non entra come .zip), ma posso postarlo.

Grazie mille x eventuali risposte.

zuper
18-01-2010, 14:21
scusami, ma una banale tabella pivot non è + comoda?

MarcoGG
18-01-2010, 17:42
Avevo pensato ad uscire dal cilco incrementandolo, ma col comando (in verde): For Each MESE In Range(Range("G2"), Range("G2").End(xlDown))
If MESE.Text = "" Then Exit For

If MESE.Offset(0, 4).Value = "---" then Next mese

mi va in debug... Come risolvo.


E ci credo che non compila. Come potrebbe ? Semmai :

For Each mese In Range(Range("G2"), Range("G2").End(xlDown))
If mese.Text = "" Then Exit For
If mese.Offset(0, 4).Value = "---" Then 'Then > COSA ???
Next mese

Manca il then del secondo IF. Specificalo.

In generale non ho chiaro cosa deve uscire sulla quarta colonna. Spiegalo meglio. Sono quasi sicuro che si possa fare con meno codice...;)

leomac
19-01-2010, 10:41
Originariamente inviato da Marco GGQuote:
Originariamente inviato da leomac

Avevo pensato ad uscire dal cilco incrementandolo, ma col comando (in verde):
Codice:
For Each MESE In Range(Range("G2"), Range("G2").End(xlDown))
If MESE.Text = "" Then Exit For

If MESE.Offset(0, 4).Value = "---" then Next mese mi va in debug... Come risolvo.

E ci credo che non compila. Come potrebbe ? Semmai :


Codice:
For Each mese In Range(Range("G2"), Range("G2").End(xlDown))
If mese.Text = "" Then Exit For
If mese.Offset(0, 4).Value = "---" Then 'Then > COSA ???
Next meseManca il then del secondo IF. Specificalo.
La parte If MESE.Offset(0, 4).Value = "---" then Next mese era solo per far capire che se nella quarta colonna era presente "---" allora trerminava il ciclo, continuandolo col mese precedente.
Per quanto riguarda la colonna4 questa serve appunto solo a non far più contare il numero che già è stato contato tutto qui.
Difatti riprendendo le colonne:
Codice:
1 colonna 2colonna 3colonna 4colonna
mese postazione numero valida
1 riga 1 102 5
2 riga 1 103 10
3riga 1 102 8

ho che il primo ciclo mi seleziona la postazione 102 e mese 1. Quindi parte il secondo il quale legge le varie postrazioni e somma i numeri se il mese e postazione del secondo cilco sono uguali al primo. Ora considerando l'esempio sopra:
1) Primo ciclo legge: 102/1 (postzione/mese);
2) Secondo ciclo legge 120/1;
3) Confronta, sono uguali e somma i numeri;
4) Inserisce "---" in quarta colonna;
5) Secondo ciclo legge 103/1;
6) Confornta e sono diversi (102/1 [primo ciclo] diverso da 103/1 [secodno ciclo];
7) non somma e non inserisce nulla in quarta colonna;
8) Secondo cilco legge 102/1 e quindi somma il numero a quello precedente inserendo "---".
Il secondo cilco finisce ripartendo però dal primo il quale fa la stessa cosa per il 103/1. Arrivati però al 102/1 col primo ciclo (3° riga per capirci), se non inserisco il "---" il secondo ciclo rifarebbe quanto già illustrato nei punti 1-> 8 ricavandomi solo un dato doppione, identico a quello iniziale.
In pratica marco alla fine la sub deve fare la somma dei numeri riferiti a ciscuna postazione in un dato mese. Nell' esempio precedente quindi avrei a fine sub:
Codice:
1 colonna 2colonna 3colonna
mese postazione numero
1 riga 1 102 13 (=5+8)
2 riga 1 103 10

Spero stavolta di essere stato più chiaro. :D
Ovviamente se avessi avuto:
Codice:
1 colonna 2colonna 3colonna 4colonna
mese postazione numero valida
1 riga 1 102 5
2 riga 1 103 10
3riga 1 102 8
4 riga 2 102 5
a fine sub avrei:
Codice:
1 colonna 2colonna 3colonna
mese postazione numero
1 riga 1 102 13 (=5+8)
2 riga 1 103 10
3 riga 2 102 5
in quanto avrei avuto 102/1 e 102/2 i cui numeri non devono essere sommati perchè hanno mese diverso.
ciaociao :)

zuper
19-01-2010, 11:13
nn capisco che schifo ti faccia la tabella pivot invece di riempire inutilmente di codice il foglio :)

leomac
19-01-2010, 12:00
zupper non posso mettere tabelle pivot perchè se mi arriva l'utonto di turno e si mette a smanettare addio... devo rinseirre tutto.
M'è già successo e ho optato per vba proprio per evitare cio.
ciaociao

zuper
19-01-2010, 20:27
zupper non posso mettere tabelle pivot perchè se mi arriva l'utonto di turno e si mette a smanettare addio... devo rinseirre tutto.
M'è già successo e ho optato per vba proprio per evitare cio.
ciaociao

puoi sempre proteggere la cella dove hai messo il range della tabella pivto e poi proteggere il foglio :)

MarcoGG
20-01-2010, 10:41
In pratica marco alla fine la sub deve fare la somma dei numeri riferiti a ciscuna postazione in un dato mese. Nell' esempio precedente quindi avrei a fine sub:
Codice:
1 colonna 2colonna 3colonna
mese postazione numero
1 riga 1 102 13 (=5+8)
2 riga 1 103 10

Spero stavolta di essere stato più chiaro. :D


Perfetto. Allora si può risolvere senza tutti quei cicli nidificati, gli Offset, e quel codice così contorto...
Inoltre si può fare a meno anche della quarta colonna di appoggio.
Premetto che non mi piace proprio l'idea di sovrascrivere direttamente la terza colonna ( eliminando le righe già processate... ).

La mia soluzione fa uso di una semplice Classe ( ebbene sì, Excel VBA ha anche le classi... ) > Classe "postazioneMese" :

Private m_mese As Integer
Private m_postazione As Integer
Private m_numero As Integer

Public Property Get Mese() As Integer
Mese = m_mese
End Property
Public Property Let Mese(Value As Integer)
m_mese = Value
End Property

Public Property Get Postazione() As Integer
Postazione = m_postazione
End Property
Public Property Let Postazione(Value As Integer)
m_postazione = Value
End Property

Public Property Get Numero() As Integer
Numero = m_numero
End Property
Public Property Let Numero(Value As Integer)
m_numero = Value
End Property

> E questo il codice di utilizzo :

Dim postazioniMese As Collection
Set postazioniMese = New Collection
Dim i As Long
i = 2
Do
If Sheets("Foglio1").Range("A" & i).Text = "" Then Exit Do
Dim PM As postazioneMese
Set PM = New postazioneMese
PM.Mese = Sheets("Foglio1").Range("A" & i).Text
PM.Postazione = Sheets("Foglio1").Range("B" & i).Text
PM.Numero = Sheets("Foglio1").Range("C" & i).Text
Dim PME As postazioneMese
Dim PMEsiste As Boolean
PMEsiste = False
For Each PME In postazioniMese
If PME.Mese = PM.Mese And PME.Postazione = PM.Postazione Then
PME.Numero = PME.Numero + PM.Numero
PMEsiste = True
Exit For
End If
Next PME
If PMEsiste = False Then postazioniMese.Add PM
i = i + 1
Loop

'TEST Collection
Dim PMTest As postazioneMese
For Each PMTest In postazioniMese
MsgBox PMTest.Mese & " - " & PMTest.Postazione & " - " & PMTest.Numero
Next PMTest

A questo punto ho la collection popolata, con cui posso comporre una nuova tabella dati o sovrascrivere quella esistente in un colpo solo... ;)

leomac
20-01-2010, 11:46
marco che dire.... risolto in pieno
Grazie mille

MarcoGG
20-01-2010, 11:49
marco che dire.... risolto in pieno
Grazie mille

;)

leomac
21-01-2010, 13:26
marco scusami 1 altra cosa. Siccome devo "tabellare" il tutto in pratica ordinare le varie postazioni in una colonna, i mesi in righe e i corrispettivi numeri nell'intersezione colonna/riga, al codice postato da te ho aggiunto:
'TEST Collection
Dim PMTest As postazioneMese
i = 2
For Each PMTest In postazioniMese
Sheets("Foglio1").Range("L" & i).Value = PMTest.Postazione
i = i + 1
Next PMTest

Range(Range("L2"), Range("L2").End(xlDown)).AdvancedFilter Action:=xlFilterInPlace, Unique:=True

For Each PMTest In postazioniMese
Dim POSTAZIO As Object

For Each POSTAZIO In Range(Range("L2"), Range("L2").End(xlDown))
If POSTAZIO = PMTest.Postazione Then
Sheets("Foglio1").Cells(POSTAZIO.Row, PMTest.Mese + 12).Value = PMTest.Numero
End If
Next POSTAZIO
Next PMTest



POSTAZIONE NUMERO MESE
100A 5 1
100B 8 1
100B 10 1
100C 19 1
100D 22 1
100D 5 2



POSTAZIONE GENNAIO FEBBRAIO
100A 5
100B 18
100C 19
100D 22 5

ora il codice fa quello che deve ma ho il problema che mi si nascondono le righe con l'advancefilter :doh: non cè un modo 1 pò più semplice di fare il tutto??:fagiano:
Grazie mille per l'attenzione :D