Divisione stringhe - casi particolari

Ultima modifica: 29-05-2016

In questo esempio articolo abbiamo visto come comportarci per dividere una normale stringa di testo in altre sottostringhe usando un carattere separatore (negli esempi il carattere separatore era uno spazio).

A questo punto potrebbe sembrare che l'argomento possa essere considerato come liquidato. Ma non è così.

Osserviamo i seguenti casi.

Ho preparato delle tabelle in cui i dati sono memorizzati in maniera diversa.

Tabella 1: Nomi e Cognomi:

1Tabella 1
2Migliavacca Luigi
2Rizzi Carlo
3Liberali Franca
4Di Maggio Mario
5Scicchitano Andrea
6Maggi Massimo

 

In questa tabella c'è un elenco di contatti registrati per Cognome e Nome. Vorrei invertire l'elenco registrando i contatti per Nome e Cognome.

Normalmente i cognomi possono essere composti da una, due o più parti:
Di Maggio, De Curti, ecc
mentre i nomi sono rappresentati da un'unica parte:
Giuseppe, Antonio, Giorgio, ecc

In questo caso è sufficiente trovare la posizione dell'ultimo spazio e da qui spezzare in due la stringa:
la prima parte rappresenterà il Cognome, la seconda parte il nome

Es:
Di Maggio Mario: l'ultimo spazio si trova alla 10' posizione
appurato questo è sufficiente perndere i primi 9 caratteri della stringa originale e poi i restanti:

Le funzioni da usare sono:

InStrRevper trovare la posizione dello spazio
Leftper prelevare la parte sinistra del nome intero
Midper prelevare la parte restante

Fatto questo basta un semplice concatenamento delle due stringhe nel modo voluto interponendo uno spazio tra le due:

Questa potrebbe essere una probabile routine per compiere questa operazione:

Sub PrimaTabella()
Dim Riga, Uriga, I
Dim NomeCompleto, NomeInvertito, Pos
Dim A1, A2
Riga = 1
While Cells(Riga, 1) <> "tabella 1"
Riga = Riga + 1
Wend
Riga = Riga + 1
Uriga = Cells(Riga, 1).End(xlDown).Row
' prova di inversione di nome e cognome e non serve a questa routine
NomeCompleto = "Di Maggio Mario"
Pos = InStrRev(NomeCompleto, " ")
A1 = Left(NomeCompleto, Pos - 1)
A2 = Mid(NomeCompleto, Pos + 1)
NomeInvertito = A2 + " " + A1
' fine prova
For I = Riga To Uriga
NomeCompleto = Cells(I, 1)
Pos = InStrRev(NomeCompleto, " ")
A1 = Left(NomeCompleto, Pos - 1)
A2 = Mid(NomeCompleto, Pos + 1)
Cells(I, 2) = A1
Cells(I, 3) = A2
Cells(I, 4) = A2 & " " & A1
Next
End Sub

Tabella 2: gli spazi che dividono le varie sottostringhe non sono omogenei

1tabella 2
2 11.355.796  06/06/04  A    01  Il Piccolo Principe atto II.wav
317.353.480  07/06/04   A    02  Volavo.wav
4 21.766.544  06/06/04  A    03  Io guardo le stelle 1.wav
5 21.472.536  07/06/04  A    04  Ehi aviatore come stai 1.wav
6 15.743.744  07/06/04  A    05  La speranza dello aviatore.wav
7 32.015.820  07/06/04  A    06  Be' eccomi qua 1.wav
8 6.769.400  07/06/04  A    07  Intermezzo I 1.wav
9 24.240.344  07/06/04  A    08  Ecco il Piccolo Principe 1.wav
10 26.751.104  07/06/04  A    09  Siamo ancora insieme 1.wav
11 25.114.996  07/06/04  A    10  Dici bene amico mio 1.wav
12 17.808.760  07/06/04  A    11  L' aviatore vide tante casettine 1.wav
13 13.597.544  07/06/04  A    12  Intermezzo II.wav
14 43.460.628  07/06/04  A    13  La risposta dello aviatore 1.wav
15 16.295.272  07/06/04  A    14  Caro amico 1.wav
16 23.405.680  06/06/04  A    15  La proposta 2.wav

 

In questo elenco notiamo che ogni stringa è composta da queste porzioni:

In questo elenco vediamo che gli spazi che dividono le varie sottostringhe non sono omogenei:

come è visibile nello schema qui di seguito riportato.

11.355.796  06/06/04  A    01  Il Piccolo Principe atto II.wav

 

La difficoltà per suddividere una simile sottostringa viene aumentata dal fatto che la porzione di stringa che rappresenta il nome del file contiene ancora degli spazi.

In questo caso mi viene in mente di usare la funzione Split e come pattern separatore una coppia di spazi: "  "

In questo modo ottengo che l'intera stringa iniziale venga suddivisa in sottostringhe solo dove si incontrano le coppie di spazi consecutivi, anche se dove ci sono quattro spazi viene creata una stringa vuota. Questo non rappresenta un problema in quanto c'è la possibilità di rifiutare la stringa vuota tramite l'istruzione:

If StringheDerivate(C) <> "" Then

Un probabile esempio potrebbe essere questo codice:

Sub SecondaTabella()
Sheets("tabelle").Select
Dim Riga, URiga, I, Co, C
Dim StringaIntera, StringheDerivate, SottoStringa
Riga = 1
While Cells(Riga, 1) <> "tabella 2"
Riga = Riga + 1
Wend
Riga = Riga + 1
URiga = Cells(Riga, 1).End(xlDown).Row
' la solita prova (anche qui ho evidenziato gli spazi tra le varie sottostringhe)
StringaIntera = "11.355.796  06/06/04  A    01  Il Piccolo Principe atto II.wav"
StringheDerivate = Split(StringaIntera, " ")
For C = LBound(StringheDerivate) To UBound(StringheDerivate)
SottoStringa = StringheDerivate(C)
Next
' fine prova
For I = Riga To URiga
StringaIntera = Cells(I, 1)
StringheDerivate = Split(StringaIntera, " ")
Co = 2
For C = LBound(StringheDerivate) To UBound(StringheDerivate)
If StringheDerivate(C) <> "" Then
Cells(I, Co) = StringheDerivate(C)
Co = Co + 1
End If
Next
Next
End Sub

Tabella 3: le stringhe rappresentano un elenco apparentemente disordinato di dati

1 tabella 2
2 35031 VEN PD 049 Abano Terme Bagni
3 84040 CAM SA Abatemarco
4 67030 ABR AQ Abazia di Sulmona
5 48012 EMI RA Abbadesse
6 10060 PIE TO Abbadia Alpina
7 20070 LOM LO 0371 Abbadia Cerreto
8 53040 TOS SI Abbadia di Montepulciano
9 61040 MAR PS Abbadia di Naro
10 22050 LOM LC 0341 Abbadia Lariana
11 53021 TOS SI 0577 Abbadia S. Salvatore
12 09071 SAR OR 0785 Abbasanta
13 65020 ABR PE 085 Abbatieggio
14 15024 PIE AL Abbazia
15 24021 LOM BG Abbazia
16 04010 LAZ LT Abbazia di Fossanova
17 07020 SAR SS Abbiadori Porto Cervo
18 21049 LOM VA Abbiate Guazzone
19 20081 LOM MI 02 Abbiategrasso
20 23030 LOM SO Abetina Vallesana
21 06040 UMB PG Abeto
22 51021 TOS PT 0573 Abetone

Questo è un elenco che presenta alcuni problemi.

Abbiamo questi elementi:

I problemi che presenta questa tabella sono due:

Dividendo la stringa principale per estrarrne i vari elementi dobbiamo porre attenzione al qarto valore che in una struttura completa dell'intera stringa dovrebbe essere un valore numerico, ma anche all'ultimo valore che dovrebbe essere il nome della città.

Questa situazione non è di facile soluzione per cui bisogna ragionarci un po'.

Dobbiamo intercettare il quarto elemento per controllare se è un valore numerico e dobbiamo intercettare la parte l'ultima parte della stringa di origine.

Per questo lavoro ho usato un contatore, Co, che mi serve per scrivere la stringa derivata nella giusta cella, nel modo che si vede nel seguente listato:

Sub terzaTabella()
Dim Riga, Uriga, I, Co
Dim StringaIntera, StringaDerivata, Pos, Po
Riga = 1
While Cells(Riga, 1) <> "tabella 3"
Riga = Riga + 1
Wend
Riga = Riga + 1
Uriga = Cells(Riga, 1).End(xlDown).Row
For I = Riga To Uriga
StringaIntera = Cells(I, 1)
Co = 1
Pos = 1
While Pos <> 0
Po = InStr(Pos, StringaIntera, " ")
StringaDerivata = Left(StringaIntera, ((Po - 1) * -(Po <> 0)))
If Co = 4 And IsNumeric(StringaDerivata) = False Then
Co = Co + 1: Pos = 0
End If
If Co = 5 Then Pos = 0
If Pos = 0 Then StringaDerivata = StringaIntera
Cells(I, Co + 1).NumberFormat = "@"
Cells(I, Co + 1) = StringaDerivata
Co = Co + 1
StringaIntera = Trim(Mid(StringaIntera, Po + 1))
Wend
Next
End Sub

Per ora possiamo anche riposarci. Buona lettura.

Questoè il file file da scaricare con cui mi sono esercitato