Quindi:
mat(1,1)="pippo"
mat(1,2)=indirizzo <- il tipo non e' rilevante per il problema.
Ho anche un file di testo formattato con n righe(record) formattate in m
campi. In uno di questi campi (sempre lo stesso per tutto il file) trovo
la corrispondenza di quanto memorizzato in mat(x,1).
Tale file lo apro con OPEN e uso INPUT# oppure LINE INPUT#.
Tutto cio' mi serve per associare alcuni campi del file di testo, al
relativo indirizzo puntato da mat(x,2).
Puo' pero' succedere che di mat(x,1) che punti ad uno unico record nel
file, ce ne sia piu' di uno [molti a uno, direbbero in Access. Credo..].
Io pensavo di risolvere leggendo una riga dal file, prelevare il codice
di campo di ricerca, ciclare tutta la mat(x,1) alla ricerca del/i
relativo/i valore/i, eseguire le operazioni di copia dei campi
interessati, e ricominciare leggendo la riga successiva.
Pero', mi sembra una procedura estremamente lunga: dovrei processare
migliaia di valori di mat(x,1) per migliaia di record nel file (ad es.
se mat(x,y) ha 2000 valori e record file ha 2000 valori, dovrei eseguire
4.000.000 di cicli, un po' tantini!!).
Come potrei fare per velocizzare e snellire il tutto?
Io pensavo:
a. Esiste una funzione che permette di trovare la posizione di una
corrispondenza all'interno di un amatrice (un po' come "instr")
oppure
b. Tenere la tecnica del "ciclo" ma poter eliminare dalla matrice
mat(x,y) gli elementi gia' processati: man mano che si va avnti nella
procedura, i record di matrice da gestire diventano sempre meno.
Chiedo pareri.
PS
Non posso e non voglio fare dei cerca direttamente su foglio excel per
vari motivi. Uno tra tutti, e' la possibilita', una volta trovata "la
soluzione", di esportare tale procedura anche su altri applicativi (VBA
Autocad, per esempio).
Saluti!!
Lele
Ciao, Lele.
Potresti usare una ricerca binaria invece che sequenziale, oppure usare
una Collection con chiave cio' che attualmente poni nella prima dimensione.
--
(Facci sapere se ed eventualmente come hai risolto. Grazie.)
Ciao :o)
Maurizio Borrelli, Microsoft Office Access MVP
--------
?SPQR(C)
X
--------
--
----------------------------
Mauro Gamberini
Ciao Maurizio.
Ti ringrazio per i consigli, ma credo che si tratti di raggiungere "un
piano superiore" che al momento le mie capacita' mi precludono...
Se hai voglia e tempo, potresti indicarmi qualche modo per capire quanto
sopra? Nel senso che:
- binary search -> ho cercato sullhelp di VBA ma non ho trovato. Su
google, sia lurkando che sui siti, ho trovato qualche cosa ma non mi
risulta molto chiaro (ho trovato un post di Cinquegrani dl 2002 ma non
mi risulta chiaro)
- sulle collection -> anche qui devo approfondire. Ho trovato un tuo
post del 2003 in cui mostravi tre vie per eseguire qualcosa di simile a
quanto devo fare io. Ora me lo studio. Pero', gestire le collection,
come funziona? Nel senso, credo di aver capito che creo una "collezione"
con tutti i valori che avrei in mat(x,y), e poi l'accesso avviene con il
metodo item? posso cioe' puntare direttamente
nomeCollection.item(stringaDaCercare)
Corretto?
Ma come si farebbe con i nomi doppi?
(a parte che, come scritto sopra, devo studiarmi bene come creare la
collection...)
Riassumendo, se mi puoi dare qualche dritta, te ne sarei grato.
LEle
Per quanto riguarda la tecnica con Collection, mi e' chiaro il
meccanismo di ricerca e di "popolamento" della Collection, ma non la
"costruzione" della stessa.
Utilizzare la tecnica della ricerca binaria mi stuzzica, pero' nascono
altri problemi "in cascata":
1.1 mi sembra che funzioni per ricerca di valori numerici (dovendo, una
volta trovato che l'elemento mediano della matrice non risponde al
"match", comparare se la "voce da cercare" sia maggiore o minore del
valore corrispondente all'elemento mediano).
1.2 Superato questo problema (potrei usare solo numeri invece di
caratteri alfanumerici), bisognerebbe fare un ordinamento della matrice
(altro problema).
1.3 Superati i due precedenti, rimane un altro grosso problema: Io
vorrei, per semplicita', leggere una riga alla volta dal file,
"estrarre" il valore da cercare, e poi trovare TUTTE le corrispondenze
nella matrice (in quanto uno o piu' elementi della matrice corrispondono
ad un elemento del file, mentre, ovviamente, un elemento del file puo'
trovare piu' di una corrispondenza nella matrice). Da qui nasce il nuovo
post (per non parlere di due argomenti differenti nello stesso).
Per maggiore chiarezza: una volta trovata la corrispondenza nella
matrice bidimensionale, da questa prelevo un "handler" che mi collega ad
un blocco di un disegno Autocad, e dalla riga letta dal file estraggo
una serie di attributi (varibile da 10 a non_so_quanti a seconda del
file) da "compilare" nel blocco.
Saluti!
Lele
Ciao, Lele.
In pratica per ogni record (o riga) del tuo file di testo dovrai
verificare se esiste o meno un elemento della Collection, che potremmo
chiamare principale, con chiave uguale al valore del primo campo del record.
Se esiste creerai un nuovo elemento della Collection "secondaria" della
Collection "principale" con tale chiave, mentre se non esiste creerai un
nuovo elemento della Collection "principale" e la sua relativa Collection
"secondaria". Come vedi le Collection in ballo potrebbero essere due.
Analogamente potresti comportarti con gli Array. Un Array "principale" o
di "indice" ed un Array dei valori con una dimensione che "punta" all'Array
dei valori.
La questione della ricerca binaria è un metodo che permette di scandire
un Array *ordinato* alla ricerca di un elemento operando per successive
divisioni ideali dell'Array in due, confrontando l'elemento cercato con
quello mediano: se il valore dell'elemento mediano è inferiore al valore
cercato allora il valore cercato è collocato nella seconda metà. Quindi si
confronta il valore mediano della seconda metà... e così via. In questo
modo, a prezzo di una codifica leggermente più complessa, si ottiene un
minor numero di confronti, quindi maggior velocità.
Nel tuo caso però credo che potrebbe essere interessante approfondire la
tecnica che si basa sulle Collection e lo farei con un esempio,
eventualmente da discutere:
Option Base 0
Option Compare Binary
Option Explicit
Public Sub test()
Dim colMain As Collection
Dim colChild As Collection
Dim varItem As Variant
Dim varArray As Variant
Dim varValue As Variant
Set colMain = New Collection
' Esempio di caricamento dati nella Collection
'
AddItem colMain, "Pippo", Array("Pippo", "Pippo1")
AddItem colMain, "Pluto", Array("Pluto", "Pluto1")
AddItem colMain, "Pippo", Array("Pippo", "Pippo2")
AddItem colMain, "Pluto", Array("Pluto", "Pluto2")
AddItem colMain, "Pippo", Array("Pippo", "Pippo3")
' Esempio di lettura della Collection
'
Debug.Print "******"
For Each colChild In colMain
For Each varItem In colChild
For Each varArray In varItem
For Each varValue In varArray
Debug.Print varValue
Next
Next
Debug.Print
Next
Debug.Print
Next
Debug.Print
' Esempio di accesso diretto ad un elemento
' della Collection
'
Debug.Print "******"
Set colChild = colMain("Pluto")
For Each varItem In colChild
For Each varArray In varItem
For Each varValue In varArray
Debug.Print varValue
Next
Next
Debug.Print
Next
Debug.Print
Set colChild = Nothing
Set colMain = Nothing
End Sub
Public Function AddItem( _
ByVal CollectionObject As Collection _
, ByVal Key As String _
, ParamArray Values() As Variant _
) As Long
Dim colChild As Collection
Dim lngErrNum As Long
Dim strErrSrc As String
Dim strErrDes As String
Dim lngRetVal As Long
On Error Resume Next
Set colChild = CollectionObject.Item(Key)
With Err
lngErrNum = .Number
strErrSrc = .Source
strErrDes = .Description
End With
On Error GoTo ErrorHandler
Select Case lngErrNum
Case 0
' L'elemento esiste
colChild.Add Values
Case 5
' L'elemento NON esiste. Lo creiamo
Set colChild = New Collection
colChild.Add Values
CollectionObject.Add colChild, Key
Case Else
' Errore imprevisto
Err.Raise lngErrNum, strErrSrc, strErrDes
End Select
ExitProcedure:
AddItem = lngRetVal
Set colChild = Nothing
Exit Function
ErrorHandler:
With Err
lngRetVal = .Number
Debug.Print "ERR#"; CStr(lngRetVal); "::"; .Description
End With
Resume ExitProcedure
End Function
Ciao, Mauro.
:)
--
[cut]
Grazie! Molta carne al fuoco!
Ora mi studio i tuoi suggerimenti!
Lele
PS
Grazie per la cortesia..
Si tratta di un "gioco di scatole cinesi", vero?
Crei una prima collection [colMain] dove ogni item e' univoco (si ripete
una sola volta) e corrisponde agli elementi della prima dimensione "x"
della mia matrice [mat(x,y)]. Ad ogni item di colMain fai corrispondere
un'ulteriore collection [colChild] dove si "riassumono" tutte le
ricorrenze di quell'elemento: quindi una collection che puo' avere da
uno a n items. In questa collection viene memorizzato l'intero elemento
della mia matrice [ossia, nel caso stia puntando elemento 12: mat(12,1)
e mat(12,2), dato che la mia e' una matrice con la seconda dimensione di
2 elementi].
In parole povere, "raggruppo" tutti gli elementi diversi sotto lo stesso
comune denominatore (dimensione uno), come una specie di "rubrica".
Ho capito bene il meccanismo?
Quindi, trasponendo il tutto sul mio problema concreto, posso dividere
il tutto in "passi":
1.0 CREAZIONE COLLECTIONs:
1.1 Facendo la scansione della matrice, ad ogni elemento, dovrei pescare
la prima dimensione, verificare che esiste nella colMain, e:
- se NON esiste, creo la nuova voce e passo al punto 1.2
- se esiste passo al punto 1.2
1.2 Aggiungo i valori dell'elemento della matrice alla collection
colChild: sia la dimensione uno che la dimensione due
2.0 Una volta completato il "popolamento" delle col, posso eseguire la
"ricerca" di ogni voce caricata dal file.
Se quanto finora scritto corrisponde a quanto da te prospettato, vorrei
chiederti un chiarimento.
Non mi e' ben chiaro il codice della function AddItem, in particolare la
gestione degli errori:
Public Function AddItem( _
ByVal CollectionObject As Collection _
, ByVal Key As String _
, ParamArray Values() As Variant _
) As Long
Dim colChild As Collection
Dim lngErrNum As Long
Dim strErrSrc As String
Dim strErrDes As String
Dim lngRetVal As Long
On Error Resume Next
Set colChild = CollectionObject.Item(Key)
->Inizio_1
With Err
lngErrNum = .Number
strErrSrc = .Source
strErrDes = .Description
End With
On Error GoTo ErrorHandler
Select Case lngErrNum
Case 0
' L'elemento esiste
colChild.Add Values
Case 5
' L'elemento NON esiste. Lo creiamo
Set colChild = New Collection
colChild.Add Values
CollectionObject.Add colChild, Key
Case Else
->Fine_1
' Errore imprevisto
Err.Raise lngErrNum, strErrSrc, strErrDes
End Select
ExitProcedure:
AddItem = lngRetVal
Set colChild = Nothing
Exit Function
ErrorHandler:
With Err
lngRetVal = .Number
Debug.Print "ERR#"; CStr(lngRetVal); "::"; .Description
End With
Resume ExitProcedure
End Function
- Tra Inizio_1 e Fine_1 serve per determinare l'esistenza o meno
dell'Item nella colMain. E qui ti seguo...
Non capisco poi la gestione dell'Errore Imprevisto, e la riga:
AddItem = lngRetVal
lngRetVal dove lo hai assegnato??
***********
Dato che il tuo listato l'ho letto stanotte, ieri nel frattempo ho
studiato un'altra soluzione con gli array (dopo che ho trovato
(lurkando) un' idea di come risolvere il problema degli array con
dimensioni variabili).
In questo array memorizzo tutte le righe lette dal file.
Definisco un tipo di dati
Private Type mioTipo
a As String
b() As Variant
End Type
dove "a" rappresenta la chiave di ricerca pescata da uno dei campi della
riga letta, mentre l'array b() viene dimensionato per il numero di campi
della riga del file, e memorizza ciascuno di questi campi.
Private Sub pippo()
Dim t() As mioTipo
ReDim t(10)
For i = 0 To 10
ReDim t(i).b(10)
t(i).b(1) = i
Debug.Print t(i).b(1)
Next i
End Sub
t()viene quindi dimensionato per quanti record ho nel file.
Siccome i dati presenti nel file sono gia' ordinati in base alla chiave
di ricerca, posso eseguire la procedura di Binary Search.
Ora, ho imparato molto, devo solo valutare quello che risulta piu'
comodo per me e poi applicarlo.
Saluti, Lele
Ciao, Lele.
Scatole cinesi o Matrioske il concetto e' sempre quello che vedi
illustrato nella Guida in linea di Microsoft Visual Basic di ciascun
applicativo Office alla pagina:
Modello di oggetti di Microsoft Excel|Word|Access|...
dove per esempio riferendoci a Excel si vede che l'oggetto principale
Application "possiede" una collezione o insieme Workbooks di elementi di
tipo Workbook. E ogni oggetto Workbook "possiede" una collezione o insieme
Sheets di elementi di tipo Chart o Worksheet. E ogni oggetto Worksheet
"possiede" una collezione o insieme Range ... Ecc.
L'esempio che ti ho fatto e' ridotto all'osso, ovviamente. Dunque si',
hai capito il meccanismo. :)
In ordine alla gestione dell'errore nella funzione AddItem considera
prima di tutto che tale funzione e' disegnata in modo che restituisca il
valore 0 (zero) in caso di esito positivo, o in caso di errore il valore
dell'errore, di modo che quando la si invoca si possa valutare se procedere
o meno. In particolare in questo modo otteniamo una funzione che non
"rimanda" un errore alla procedura chiamante; cioe' AddItem non va mai in
errore ma "informa" sull'eventuale errore il codice che l'ha chiamata.
Quindi la si puo' per esempio chiamare cosi':
Dim lngVal As Long
' ...
lngVal = AddItem(...)
If (lngVal) Then
' Errore
Else
' Continua
End If
L'istruzione che puo' generare errore e':
Set colChild = CollectionObject.Item(Key)
che puo' generare un errore "previsto". Un errore che in realta' non e'
un'errore ma una informazione in ordine al fatto che non esiste un elemento
della collezione avente chiave di valore "Key". Tale errore viene usato
appunto per decidere cosa fare quindi tutto regolare. In teoria dovrebbero
esserci solo due casi, nessun errore o errore 5. Dato pero' che abbiamo
deciso di rendere assolutamente sicura tale funzione gestiamo l'eventuale
errore diverso da 5, con "Case Else" dove pero' arriviamo con il gestore
degli errori "scarico" perche' "On Error Resume Next" permette il
proseguimento dell'elaborazione. Pero' con il successivo "On Error GoTo
ErrorHandler" abbiamo attivato la gestione degli errori quindi e'
sufficiente generare ("forzare") per mezzo di "Err.Raise" un errore del tipo
intercettato da "On Error Resume Next" del quale abbiamo memorizzato le
caratteristiche nelle variabili lngErrNum, strErrSrc e strErrDes. Ed e'
appunto cio' che facciamo. Questo principalmente al fine di essere
perfettamente informati su cosa sta accadendo piu' nella fase di
progettazione e scrittura del codice, quando non tutto il codice cioe' e'
ancora testato e perfettamente funzionante e puo' capitare (e ca'pita!) di
domandarsi perche' mai sta succedendo qualche strana cosa. Come dicevo in
realta' il codice in "Case Else" non dovrebbe mai essere eseguito una volta
che il progetto e' a punto.
--
Ciao, Lele.
Concordo ovviamente col fatto che devi decidere quale strada e' piu'
conveniente per te. A questo proposito vorrei farti notare che le strade
sono appunto tali, cioe' sono veri e propri percorsi, sentieri, indirizzi,
tecniche diverse e mischiarle puo' essere rischioso. L'uso degli Array, di
Type..End Type, ecc. appartiene (pertiene) ad un mondo e ad un modo di
programmare che ha logiche in certo modo diverse da quello delle Collection.
In una parola questo ultimo modo e' la "programmazione orientata agli
oggetti". Leggermente piu' complessa di quella "tradizionale" (quella con
gli Array e gli udt=tipi definiti dall'utente) ma in teoria (e in pratica,
se la si riesce a dominare e possedere decentemente) piu' efficace e
flessibile. Specialmente se consideri che stai programmando "dentro" un
mondo di oggetti (Excel, Word & C.).
--
Ciao, Lele.
Ho riletto il codice che ho postato e non m'e' piaciuto. :) Lo riscrivo.
Public Sub Test1()
Dim colMain As Collection
Dim colChild As Collection
Dim varItem As Variant
Dim varValue As Variant
Set colMain = New Collection
' Esempio di caricamento dati nella Collection
'
AddItem1 colMain, "Pippo", Array("Pippo", "Pippo1")
AddItem1 colMain, "Pluto", Array("Pluto", "Pluto1")
AddItem1 colMain, "Pippo", Array("Pippo", "Pippo2")
AddItem1 colMain, "Pluto", Array("Pluto", "Pluto2")
AddItem1 colMain, "Pippo", Array("Pippo", "Pippo3")
' Esempio di lettura della Collection
'
Debug.Print "******"
For Each colChild In colMain
For Each varItem In colChild
For Each varValue In varItem
Debug.Print varValue
Next
Debug.Print
Next
Debug.Print
Next
Debug.Print
Set colChild = Nothing
Set colMain = Nothing
End Sub
Public Sub Test2()
Dim colMain As Collection
Dim colChild As Collection
Dim varItem As Variant
Dim varValue As Variant
Set colMain = New Collection
' Esempio di caricamento dati nella Collection
'
AddItem2 colMain, "Pippo", "Pippo", "Pippo1"
AddItem2 colMain, "Pluto", "Pluto", "Pluto1"
AddItem2 colMain, "Pippo", "Pippo", "Pippo2"
AddItem2 colMain, "Pluto", "Pluto", "Pluto2"
AddItem2 colMain, "Pippo", "Pippo", "Pippo3"
' Esempio di lettura della Collection
'
Debug.Print "******"
For Each colChild In colMain
For Each varItem In colChild
For Each varValue In varItem
Debug.Print varValue
Next
Debug.Print
Next
Debug.Print
Next
Debug.Print
Set colChild = Nothing
Set colMain = Nothing
End Sub
Public Function AddItem1( _
ByVal CollectionObject As Collection _
, ByVal Key As String _
, ByVal Values As Variant _
) As Long
' Come routine gia' postata
End Function
Public Function AddItem2( _
ByVal CollectionObject As Collection _
, ByVal Key As String _
, ParamArray Values() As Variant _
) As Long
' Come routine gia' postata
End Function
Come puoi notare avevo frettolosamente mescolato due metodi. Scusa(te).
--
Ho deciso di adottare la soluzione con le Collections.
Tutto ok, tutto funziona, ma..
Nel testare le funzionalita', ho pensato di, una volta create le
collections madre e figlia, di mettere in una combo-box i nomi degli
elemtni della collection madre.. Ma.. Non ci sono riuscito! per le
collection, mi da opportunita' di scegliere solo alcuni metodi e non di
ricavare la proprieta' del nome (o chive) di ciascun item.
Quale procedura adottare per ricavarlo?
In pratica io vorrei una cosa del tipo:
CollectionMain.Item(1).Name oppure .Value
Esiste quialche "giro" losco per ottenerlo?
Ti ringrazio.
Lele
Ciao, Lele.
Forse non hai avuto la possibilita' di notare che negli esempi da me
postati prevedevo appunto la possibilita' di accedere al valore della chiave
in quanto ne ho previsto la memorizzazione nel primo elemento di ciascun
insieme.
Prova per esempio ad aggiungere le seguenti istruzioni alla routine
Test1:
' Lista degli elementi
' della Collection Main
'
Debug.Print "******"
For Each colChild In colMain
Debug.Print colChild.Item(1)(0)
Next
Debug.Print
Comunque si'. Esiste la possibilita' di fare tutto cio' che vuoi, a
prezzo di un maggiore approfondimento della programmazione a oggetti in
Visual Basic.
Allo stato delle cose attuale, cioe' gli esempi da me proposti, non si
puo' dire propriamente che stiamo programmando ad oggetti ma solo che stiamo
usando un oggetto del linguaggio (Visual Basic): l'oggetto Collection.
Programmare ad oggetti invece vuol dire creare oggetti e usarli nel proprio
progetto. In Visual Basic il concetto astratto di oggetto viene realizzato
praticamente per mezzo di un modulo di classe. Tutto questo richiede un po'
di studio e di allenamento.
Un esempio veloce veloce di cio' che intendo dire, senza commenti,
quindi se hai bisogno domanda e qualcuno rispondera'.
' Modulo2 Modulo
'
Option Base 0
Option Compare Binary
Option Explicit
Public Sub Main()
Dim objParents As clsParents
Dim objParent As clsParent
Dim vntChild As Variant
Dim vntItem As Variant
Set objParents = New clsParents
objParents.AddItem "Pippo" _
, Array("Pippo1.1", "Pippo1.2")
objParents.AddItem "Pluto" _
, Array("Pluto1.1", "Pluto1.2")
objParents.AddItem "Pippo" _
, Array("Pippo2.1", "Pippo2.2")
objParents.AddItem "Pluto" _
, Array("Pluto2.1", "Pluto2.2")
objParents.AddItem "Pippo" _
, Array("Pippo3.1", "Pippo3.2")
Debug.Print objParents.Count
Debug.Print
Set objParent = objParents.Item("Pippo")
With objParent
Debug.Print .Key
For Each vntChild In .Children
For Each vntItem In vntChild
Debug.Print , vntItem
Next
Next
Debug.Print .Children.Count
End With
Debug.Print
Set objParent = Nothing
Set objParents = Nothing
End Sub
' clsParents ClassModule
'
Option Base 0
Option Compare Binary
Option Explicit
Private p_colItems As VBA.Collection
Public Function AddItem( _
ByVal KeyString As String _
, ByVal ValuesArray As Variant _
) As clsParent
Dim objParent As clsParent
Set objParent = Me.Item(KeyString)
If (objParent Is Nothing) Then
Set objParent = New clsParent
With objParent
.Start KeyString
Me.Items.Add objParent, .Key
End With
End If
objParent.Children.Add ValuesArray
Set AddItem = objParent
Set objParent = Nothing
End Function
Public Property Get Count( _
) As Long
Count = Me.Items.Count
End Property
Public Property Get Item( _
ByVal Index As Variant _
) As clsParent
On Error Resume Next
Set Item = Me.Items.Item(Index)
End Property
Public Property Get Items( _
) As VBA.Collection
Set Items = p_colItems
End Property
Private Sub Class_Initialize()
Debug.Print TypeName(Me); "::Class_Initialize"
Set p_colItems = New VBA.Collection
End Sub
Private Sub Class_Terminate()
Set p_colItems = Nothing
Debug.Print TypeName(Me); "::Class_Terminate"
End Sub
' clsParent ClassModule
'
Option Base 0
Option Compare Binary
Option Explicit
Private p_colChildren As VBA.Collection
Private p_strKey As String
Public Property Get Children( _
) As VBA.Collection
Set Children = p_colChildren
End Property
Public Property Get Key( _
) As String
Key = p_strKey
End Property
Public Sub Start( _
ByVal KeyString As String)
p_strKey = KeyString
Set p_colChildren = New VBA.Collection
End Sub
Private Sub Class_Initialize()
Debug.Print TypeName(Me); "::Class_Initialize"
End Sub
Private Sub Class_Terminate()
Set p_colChildren = Nothing
Debug.Print TypeName(Me); "::Class_Terminate"
End Sub
Lele
Sull'onda del 3D di Thunder, riguardo i feedback, ti dico: Non ho capito
molto (perche' ancora non conosco nulla sull'argomento: credo di capirne
le linee guida, ma nello specifico devo approfondire) sulla parte di
listato che hai postato, ma ci spendero' un po' di tempo per capire il
funzionamento delle classi. Poi eventulamente postero' richieste piu'
mirate.
Per quanto riguarda la soluzione al topic, beh, com escritto nel 3d
sopra citato di Thunder, ci sto ancora lavorando..
Comunque ho adottato pari-pari la soluzione con le collections (in
particolare la soluzione 2 per la funzione "AddItem") e funziona
egregiamente, anzi di piu'!! ;-))
Saluti, Lele
Ciao, Lele.
:-)