Evitare Ripetizioni (nell'inserimento di dati in una tabella)   (14/01/03)

Praticamente si tratta di un "Controllo inserimento dati". Un'altra dimostrazione che tramite Vba, si possono comporre istruzioni che mirino allo stesso scopo, variando completamente il modo di controllo. Questa volta ci occuperemo della trasposizione in codice di una funzione del foglio di lavoro : la funzione =CONTA.SE

Questa funzione, l'abbiamo già vista impiegare in " Usare Convalida (2)" , nella sezione "formule". L' istruzione controlla se le celle di un determinato Range contengono lo stesso valore che si troverà in una cella (che useremo come vettore per la ricerca), se tale vettore sarà trovato sarà  pari a 1,  e la formula riscontra VERO, altrimenti restituisce FALSO. L'istruzione andrebbe compilata così e verrebbe posta in una cella, per esempio la C1:

=CONTA.SE(A1:A100;B1)=1

e dice praticamente: controlla se il valore che è in B1 è presente nel range che va da A1 a A100, se lo trovi  scrivi (in C1) VERO, altrimenti scrivi FALSO.

Questo potrebbe essere un modo alternativo per il controllo dell'inserimento dati, peraltro ottenibile usando la "Convalida Dati" di Excel. In genere questi controlli si eseguono quando si debbano introdurre dati "univoci", come un numero di fattura, oppure un codice articolo. Volendo quindi applicare in Vba questa funzione, faremo un esempio: supponiamo di avere una colonna dove inseriremo il numero di fattura, e lo posizioniamo nella colonna A, a partire dalla prima cella. Seguendo la falsariga della funzione sopracitata, avremo bisogno di una cella che funzioni da vettore, e di una cella dove "alloggiare" la formula stessa. Visto che ci apprestiamo ad usare del codice, perchè non usare una finestra di introduzione dati, una InputBox, che renderà un pò più "professionale" il nostro lavoro? Avremo bisogno anche di "convertire" il risultato della funzione (VERO, FALSO) in un istruzione che ci consenta di annullare la scrittura se il numero fattura che vorremo inserire esiste già, mentre vorremo che il numero stesso venga scritto, se non presente, e venga scritto nella riga successiva all'ultimo numero presente nel range previsto. Ecco quindi una routine che ci consente di fare quanto detto (in verde sono le spiegazioni):

Sub introduzionedati()

'dichiarazione delle variabili per la InputBox
Dim messaggio, titoto, Valore
titolo = "Introduzione dati"
 'ciò che vedremo nella barra del titolo dell'inpputbox
messaggio = "Introduci il numero"
'il testo che appare come istruzione da seguire
Valore = InputBox(messaggio, titolo)
'Valore sarà uguale al dato inserito nella casella di 'testo della inputbox.
If Valore = "" Then Exit Sub '
se non scriveremo niente, si esce dalla routine


'anzichè una cella visibile, assegno la cella B60000 a contenere il valore che fungerà da 'vettore (valore), cioè il secondo argomento della funzione Cerca.Se (CountIf)
Range("B60000") = Valore

'assegno a X la cella A60000 (una cella sicuramente non visibile), che sarà la cella dove 'avremo il risultato della funzione (come per la C1 della formula iniziale)
Set X = Range("A60000")
'pongo in A60000 (X) la formula =CONTA.SE
X.Formula = "=COUNTIF(A1:A100,B60000)=1"

'inizio il ciclo di controllo sulla X, cioè la cella A60000
If X.Value = True Then
'se il valore sara uguale a vero, cioè sarà stato trovato il numero 'nell'elenco previsto A1:A100
MsgBox "Valore Già presente"
'si viene avvisati da un messaggio
X = ""
'viene pulita la cella A60000
Range("B60000") = ""
'viene pulita la cella B60000
Exit Sub 
'si esce dalla routine
Else
'invece (in caso contrario, cioè se il numero non è presente nell'elenco)
Range("A1").End(xlDown).Select 
'seleziono l'ultima cella occupata  a partire dalla A1
ActiveCell.Offset(1, 0).Select  
'seleziono la cella sotto che è vuota
ActiveCell = Valore
'nella cella attiva copio il vettore (valore) scritto nella inputbox
X = "" 
 'poi viene pulita la cella A60000
Range("B60000") = ""  
'poi viene pulita la cella B60000
End If
End Sub

E questa è la variante con la descrizione nel messaggio della InputBox dell'ultimo numero presente, in modo che si sappia comunque qual'è l'ultimo numero inserito (non ripeto le spiegazioni già fornite nella routine sopra):

Sub introducicontrolla()
Dim Z
Z = Range("A1").End(xlDown).Value
'a Z viene assegnato il valore presente nell'ultima 'cella occupata partendo dalla A1
Dim messaggio, titoto, Valore
titolo = "Introduzione dati"
messaggio = "Introduci il numero, l'ultimo usato è il N° " & Z & ""
'ho aggiunto nel 'messaggio l'ultimo numero presente (Z)
Valore = InputBox(messaggio, titolo)

If Valore = "" Then Exit Sub

Range("B60000") = Valore
Set X = Range("A60000")

X.Formula = "=COUNTIF(A1:A100,B60000)=1"
If X.Value = True Then
MsgBox "Valore Già presente"
X = ""
Range("B60000") = ""
Exit Sub
Else
Range("a1").End(xlDown).Select
ActiveCell.Offset(1, 0).Select
ActiveCell = Valore
X = ""
Range("B60000") = ""
End If
End Sub