TOP

VBA-Lezione 13.3. Utilizzo degli array (Arrays) (Esercizi)

YouLibreCalc for Excel logo

Per esercitarci nell'uso degli array, creeremo la nostra versione della macro che abbiamo utilizzato per dimostrare il vantaggio in termini di velocità degli array, passo dopo passo...


Ecco il punto di partenza di questo esercizio (vedrai che il set di dati è stato ridotto a 1000 righe):

Qui puoi scaricare il file di esempio Excel: arrays_exercise.xls

Obiettivo dell'esercizio: la procedura dovrebbe scorrere i dati nel set di dati e contare il numero di risposte SÌ o NO per ogni anno e per ciascun numero di cliente (SÌ o NO a seconda della scelta dell'utente) e inserire questa quantità nella cella specificata di il foglio di lavoro.

Completa la seguente macro per salvare i dati dal foglio di lavoro "DS" in un array:

Sub actualize()
     Dim last_row As Integer
     
     'L'ultima riga del set di dati
     '...
        
     'Salvataggio di un set di dati in un array dinamico
     Dim array_db()
     '...
        
End Sub

Ecco una soluzione di esempio:

Sub actualize()
     Dim last_row As Integer
     
     'L'ultima riga del database
     last_row = Sheets("DS").Range("A1").End(xlDown).Row

     'Salvataggio di un set di dati in un array dinamico
     Dim array_db()
     ReDim array_db(last_row - 2, 2)
     
     For row_number = 2 To last_row
         array_db(row_number - 2, 0) = Sheets("DS").Range("A" & row_number)
         array_db(row_number - 2, 1) = Sheets("DS").Range("B" & row_number)
         array_db(row_number - 2, 2) = Sheets("DS").Range("C" & row_number)
     Next
End Sub

Questo sostanzialmente ripete ciò che abbiamo fatto nella lezione precedente...

Ma ora dobbiamo modificare la nostra macro aggiungendo le seguenti azioni:

  • Determinare la scelta dell'utente ("SI" o "NO");
  • Contare il numero di risposte "SI" o "NO" nel set di dati per determinare la dimensione dell'array (Redim);
  • Salviamo solo le righe del set di dati che contengono le risposte "SÌ" o "NO" nell'array (ciò significa che non è necessario salvare i dati dalla terza colonna).
  • Ecco una soluzione di esempio:

    Sub actualize()
         Dim last_row As Integer, search_value As String, insert_row As Integer, value_yes_no As String, rows_number As Integer
         
         'L'ultima riga del database
         last_row = Sheets("DS").Range("A1").End(xlDown).Row
    
         'Valore di ricerca (YES o NO)
         If Sheets("RES").OptionButton_yes.Value = True Then
             search_value = "YES"
         Else
             search_value = "NO"
         End If
         
         'Numero di risposte YES o NO
         rows_number = WorksheetFunction.CountIf(Sheets("DS").Range("C2:C" & last_row), search_value)
         
         'Salvataggio di un set di dati in un array
         Dim array_db()
         ReDim array_db(rows_number - 1, 1)
    
         insert_row = 0
         
         For row_number = 2 To last_row
             value_yes_no = Sheets("DS").Range("C" & row_number)
             
             If value_yes_no = search_value Then
                 array_db(insert_row, 0) = Sheets("DS").Range("A" & row_number)
                 array_db(insert_row, 1) = Sheets("DS").Range("B" & row_number)
                 insert_row = insert_row + 1
             End If
         Next
    End Sub
    

    La ricerca per scelta dell'utente è determinata all'inizio della procedura dal seguente codice:

     'Valore di ricerca (YES o NO)
     If Sheets("RES").OptionButton_yes.Value = True Then
         search_value = "YES"
     Else
         search_value = "NO"
     End If
    

    Utilizzeremo la funzione CountIF per determinare il numero di risposte "SI" o "NO":

     'Numero di risposte YES o NO
     rows_number = WorksheetFunction.CountIf(Sheets("DS").Range("C2:C" & last_row), search_value)
    

    L'array è stato ridimensionato per adattarsi al numero di risposte SI o NO e ridotto a due colonne:

    ReDim array_db(rows_number - 1, 1)
    

    Questi dati verranno ora archiviati nell'array quando la sua terza colonna corrisponde alla selezione dell'utente:

     'Inserimento di un numero in un array
     insert_row = 0
    
     'Elaborazione del set di dati
     For row_number = 2 To last_row
         'Valore della colonna C (YES o NO)
         value_yes_no = Sheets("DS").Range("C" & row_number)
         
         'Se il valore corrisponde alla selezione dell'utente, la stringa viene archiviata nell'array
         If value_yes_no = search_value Then
             'Salvataggio del valore nella colonna A
             array_db(insert_row, 0) = Sheets("DS").Range("A" & row_number)
             'Salvataggio del valore nella colonna B
             array_db(insert_row, 1) = Sheets("DS").Range("B" & row_number)
             'Una riga è stata salvata => il numero di inserimento nell'array viene incrementato di 1
             insert_row = insert_row + 1
         End If
     Next
    

    Il nostro array contiene solo i dati che ci interessano.

    Tutto ciò che resta da fare è:

  • Elabora ogni elemento della tabella sul foglio di lavoro "RES" utilizzando 2 cicli (stessa idea dell'esercizio della scacchiera);
  • Inserire il numero totale di occorrenze su questo foglio per ogni anno per ciascun numero cliente per ogni cella.
  • Ecco una soluzione di esempio:

     'Numero di risposte "YES"/"NO"
     For no_years = 2011 To 2026
         For no_client = 1 To 30
             counter = 0
             
             For i = 0 To UBound(array_db)
                 If Year(array_db(i, 0)) = no_years And array_db(i, 1) = no_client Then
                     counter = counter + 1
                 End If
             Next
             
             Cells(no_years - 2009, no_client + 1) = counter
         Next
     Next
    

    Problema risolto con i commenti che lo spiegano in dettaglio:

     'Ciclo per ogni riga
     For no_years = 2011 To 2026
     
         'Ciclo per ogni colonna
         For no_client = 1 To 30
             'Reset del contatore
             counter = 0
             
             'Elaborazione di matrici
             For i = 0 To UBound(array_db)
                 'Verificare che la riga della tabella corrisponda all'anno e al numero cliente
                 If Year(array_db(i, 0)) = no_years And array_db(i, 1) = no_client Then
                     'Se l'anno e il numero cliente coincidono il contatore aumenta di 1
                     counter = counter + 1
                 End If
             Next
             
             'Dopo aver elaborato l'array, il risultato viene inserito nella cella corrispondente
             Cells(no_years - 2009, no_client + 1) = counter
         Next
     Next
    

    E infine, il codice per la nostra intera macro:

    Sub actualize()
         Dim last_row As Integer, search_value As String, insert_row As Integer, value_yes_no As String, rows_number As Integer, counter As Integer
         
         'Eliminazione di contenuti
         Range("B2:AE17").ClearContents
         
         'L'ultima riga nel set di dati
         last_row = Sheets("DS").Range("A1").End(xlDown).Row
    
         'Valore di ricerca (YES o NO)
         If Sheets("RES").OptionButton_yes.Value = True Then
             search_value = "YES"
         Else
             search_value = "NO"
         End If
         
         'Numero di risposte YES o NO
         rows_number = WorksheetFunction.CountIf(Sheets("DS").Range("C2:C" & last_row), search_value)
         
         'Salvataggio di valori in un array
         Dim array_db()
         ReDim array_db(rows_number - 1, 1)
    
         insert_row = 0
         
         For row_number = 2 To last_row
             value_yes_no = Sheets("DS").Range("C" & row_number)
             
             If value_yes_no = search_value Then
                 array_db(insert_row, 0) = Sheets("DS").Range("A" & row_number)
                 array_db(insert_row, 1) = Sheets("DS").Range("B" & row_number)
                 insert_row = insert_row + 1
             End If
         Next
         
         'Conteggio delle risposte YES o NO
         For no_years = 2011 To 2026
             For no_client = 1 To 30
                 counter = 0
                 
                 For i = 0 To UBound(array_db)
                     If Year(array_db(i, 0)) = no_years And array_db(i, 1) = no_client Then
                         counter = counter + 1
                     End If
                 Next
                 Cells(no_years - 2009, no_client + 1) = counter
             Next
         Next
    End Sub
    

    Qui puoi scaricare il file di esempio Excel: arrays_exercise_completed.xls