Ho bisogno di scrivere un programmino che, dopo aver analizzato dei
files contenenti dei particolari tracciati, estragga dei dati da un foglio
di Excel e tramite questi generi dei files di testo con una particolare
struttura determinata dal file del tracciato.
<< Continua dalla parte 1
Per sviluppare questo progetto utilizzeremo il controllo RichTextBox e
DAO 3.5 per accedere al foglio di Excel. Pertanto è necessario
selezionare il controllo Microsoft Rich Textbox Control
dalla voce Componenti del menu Progetto. È anche necessario
inserire un riferimento a Microsoft DAO 3.5 Object Library
tramite la voce Riferimenti del menu Progetto.
Il progetto si compone di due forms ed
un modulo
standard. Quest'ultimo conterrà due variabili globali, un nuvo
tipo di dati
di nome TIPOSEZIONE ed alcune funzioni che utilizzeremo parecchie
volte all'interno del nostro progetto.
Nei due form invece avremo gli strumenti minimi per definire la struttura
del tracciato ed il form principale, molto semplice, per la scelta dei
files da utilizzare.
Prima di addentrarci nei forms vediamo il contenuto del nostro modulo:
- Option Explicit
- Public Type TIPOSEZIONE
- INIZIO As Integer
- FINE As Integer
- CAMPO As Integer
- RIGAFISSA As Integer
- LUNGHEZZAFISSA As Integer
- ALLINEAMENTO As Integer
- FILLER As String * 1
- End Type
- Public FILEXLS As DAO.Database
- Public FOGLIOXLS As DAO.Recordset
Alla riga 3 definiamo il tipo di dati
TIPOSEZIONE. In sostanza una sezione è un segmento del file tracciato
con una posizione iniziale e una finale, associato ad un campo del foglio
Excel e con dei dati aggiuntivi che stabiliscono se la sezione è
fissa o si ripete per ogni record, se la lunghezza è fissa o regolata
dall'ampiezza del campo associato. Nel caso sia fissa è necessario
definire l'allineamento che i dati devono avere (sinistra o destra) ed
il carattere di riempimento per raggiungere la lunghezza desiderata.
Così il tipo dati TIPOSEZIONE si compone di 7 campi:
- INIZIO
Definisce la posizione iniziale della sezione all'interno del file tracciato
- FINE
Definisce la posizione finale della sezione
- CAMPO
Indica l'ordine del campo associato del foglio XLS
- RIGAFISSA
Indica in maniera numerica se la riga è fissa o si ripete per
ogni riga del file XLS
- LARGHEZZAFISSA
Indica in maniera numerica se la larghezza della sezione è variabile,
determinata dal campo, oppure è
- ALLINEAMENTO
Indica, nel caso di larghezza fissa della sezione, se i dati devono
essere allineati a sinistra o a destra
- FILLER
Indica, in caso di larghezza fissa, quale carattere deve essere utilizzato
per riempire gli spazi fino a raggiungere la larghezza della sezione
Alle righe 13 e 14 abbiamo definito due variabili globali. La prima è
FILEXLS ed indica il database Excel per i dati da estrarre. La
seconda variabile è il Recordset FOGLIOXLS che conterrà
i dati da estrarre dal database FILEXLS.
Seguono, nel modulo, un paio di funzioni che utilizzeremo più
avanti.
- Public Function FileEsiste(ByVal NOMEFILE As String) As Boolean
- On Error GoTo ERRORE
- Dim FILENR As Integer
- FileEsiste = False
- FILENR = FreeFile
- Open NOMEFILE For Input As FILENR
- Close FILENR
- FileEsiste = True
- Exit Function
- ERRORE:
- FileEsiste = False
- End Function
La funzione FileEsiste viene spiegata approfonditamente nell'HowTo
dedicato alla verifica se un dato file esiste.
- Public Function Sezione2Riga(ByRef SEZIONE As TIPOSEZIONE) As String
- Sezione2Riga = SEZIONE.INIZIO & ";"
- Sezione2Riga = Sezione2Riga & SEZIONE.FINE
& ";"
- Sezione2Riga = Sezione2Riga & SEZIONE.CAMPO
& ";"
- Sezione2Riga = Sezione2Riga & SEZIONE.RIGAFISSA
& ";"
- Sezione2Riga = Sezione2Riga & SEZIONE.LUNGHEZZAFISSA
& ";"
- Sezione2Riga = Sezione2Riga & SEZIONE.FILLER
& ";"
- Sezione2Riga = Sezione2Riga & SEZIONE.ALLINEAMENTO
- End Function
La funzione Sezione2Riga serve per trasformare una sezione di
tipo TIPOSEZIONE in una stringa. Questo perché le singole sezioni
saranno tenute all'interno di una Collection;
con Visual Basic 5, tuttavia, non è possibile inserire elementi
di tipi definiti dall'utente all'interno di una Collection. A tale scopo,
nel momento in cui inseriremo i dati nella Collection convertiremo la
sezione in una stringa ed inseriremo quella.
La funzione Sezione2Riga unisce i singoli campi della sezione
in una stringa separandoli temite un punto e virgola.
Segue un'altra funzione che effettua l'operazione inversa, cioé
converte una stringa in una sezione di tipo TIPOSEZIONE.
- Public Sub Riga2Sezione(ByVal RIGA As String, ByRef SEZIONE As TIPOSEZIONE)
- Dim TMPSEZIONE As String
- TMPSEZIONE = RIGA
- SEZIONE.INIZIO = Mid(TMPSEZIONE, 1, InStr(1,
TMPSEZIONE, ";") - 1)
- TMPSEZIONE = Mid(TMPSEZIONE, Len(CStr(SEZIONE.INIZIO))
+ 2)
- SEZIONE.FINE = Mid(TMPSEZIONE, 1, InStr(1,
TMPSEZIONE, ";") - 1)
- TMPSEZIONE = Mid(TMPSEZIONE, Len(CStr(SEZIONE.FINE))
+ 2)
- SEZIONE.CAMPO = Mid(TMPSEZIONE, 1, InStr(1,
TMPSEZIONE, ";") - 1)
- TMPSEZIONE = Mid(TMPSEZIONE, Len(CStr(SEZIONE.CAMPO))
+ 2)
- SEZIONE.RIGAFISSA = Mid(TMPSEZIONE, 1, InStr(1,
TMPSEZIONE, ";") - 1)
- TMPSEZIONE = Mid(TMPSEZIONE, Len(CStr(SEZIONE.RIGAFISSA))
+ 2)
- SEZIONE.LUNGHEZZAFISSA = Mid(TMPSEZIONE, 1,
InStr(1, TMPSEZIONE, ";") - 1)
- TMPSEZIONE = Mid(TMPSEZIONE, Len(CStr(SEZIONE.LUNGHEZZAFISSA))
+ 2)
- SEZIONE.FILLER = Mid(TMPSEZIONE, 1, InStr(1,
TMPSEZIONE, ";") - 1)
- TMPSEZIONE = Mid(TMPSEZIONE, Len(CStr(SEZIONE.FILLER))
+ 2)
- SEZIONE.ALLINEAMENTO = TMPSEZIONE
- End Sub
La funzione effettua la ricerca dei punto e virgola ed inserisce i dati
all'interno della sezione passata per riferimento.
L'ultima Sub del modulo è OrdinaSezioni e, come dice il
nome stesso, effettua l'ordinamento delle sezioni in base al punto di
inizio della sezione.
Essa richiede come parametro la Collection contenente gli elementi da
ordinare, sempre passata per riferimento, affinché sia possibile
scrivere gli elementi una volta ordinati.
Il metodo di ordinamento è il classico Bubble sort (ordinamento
a bolle), approfondito nella sezione Informazioni
aggiuntive.
- Public Sub OrdinaSezioni(ByRef SEZIONI As Collection)
- Dim ARRAYSEZIONI() As String
- Dim CONTA As Integer
- Dim CONTA2 As Integer
- Dim TMPSEZIONE As TIPOSEZIONE
- Dim SUCCSEZIONE As TIPOSEZIONE
- ReDim ARRAYSEZIONI(5)
Alla riga 65 abbiamo dichiarato un'array (matrice)
di stringhe di nome ARRAYSEZIONI senza specificare la sua ampiezza.
Questo perché vogliamo utilizzare un dimensionamento dinamico effettuato
in fase di esecuzione.
Infatti abbiamo il primo ridimensionamento alla riga 70 impostando la
dimensione della matrice a 5.
Alle righe 68 e 69 abbiamo dichiarato due variabili di tipo TIPOSEZIONE.
Esse saranno utilizzate per estrarre due valori dalla Collection
e confrontarli per l'ordinamento.
- For CONTA = 1 To SEZIONI.Count
- If UBound(ARRAYSEZIONI)
< CONTA Then ReDim Preserve ARRAYSEZIONI(UBound(ARRAYSEZIONI) + 5)
- ARRAYSEZIONI(CONTA)
= SEZIONI.Item(CONTA)
- Next CONTA
Come prima operazione della Sub eseguiamo una copia dei dati della Collection
SEZIONI nella matrice ARRAYSEZIONI.
Non conoscendo a priori la dimensione della Collection abbiamo voluto
effettuare il ridimensionamento della matrice a 5 elementi per volta.
Infatti, quando la dimensione dell'array è minore dell'elemento
in corso di estrazione, viene incrementata la dimensione dell'array di
5 elementi, preservando il contenuto dell'array.
Esistono modi più semplici ed efficienti per effettuare questa
operazione, ma abbiamo voluto sfruttare l'occasione per mostrare il funzionamento
del dimensionamento dinamico.
Alla riga 73 abbiamo l'inserimento dell'elemento dalla Collection alla
matrice.
- For CONTA = 1 To SEZIONI.Count - 1
- For CONTA2 = CONTA
+ 1 To SEZIONI.Count
- Riga2Sezione
ARRAYSEZIONI(CONTA), TMPSEZIONE
- Riga2Sezione
ARRAYSEZIONI(CONTA2), SUCCSEZIONE
- If
TMPSEZIONE.INIZIO > SUCCSEZIONE.INIZIO Then
- ARRAYSEZIONI(0)
= ARRAYSEZIONI(CONTA2)
- ARRAYSEZIONI(CONTA2)
= ARRAYSEZIONI(CONTA)
- ARRAYSEZIONI(CONTA)
= ARRAYSEZIONI(0)
- ARRAYSEZIONI(0)
= ""
- End
If
- Next CONTA2
- Next CONTA
In questo ciclo abbiamo l'operazione di sorting (ordinamento) tramite
Bubble sort. L'elemento 0 della matrice serve per effettuare lo scambio
dei dati tra due celle dell'array.
- CONTA2 = SEZIONI.Count
- While SEZIONI.Count > 0
- SEZIONI.Remove 1
- Wend
- For CONTA = 1 To CONTA2
- SEZIONI.Add ARRAYSEZIONI(CONTA)
- Next CONTA
- End Sub
Effettuato il sorting sarà necessario rimettere tutti i dati nella
Collection in maniera ordinata. Per questo alla riga 87 salviamo la dimensione
della Collection nella variabile CONTA2.
Avendo messo in salvo la dimensione originale, possiamo tranquillamente
svuotare la Collection (righe 88-90) e poi riempirla nuovamente utilizzando
la dimensione salvata precedentemente (righe 91-93).
|