split contenuto cella



  • split contenuto cella
    di Antonio (utente non iscritto) data: 13/02/2015 15:02:59

    Salve sono nuovo nel campo di visual basic e ho il seguente problema:
    nella colonna dove ci sono gli indirizzi, vorrei che il contenuto della cella:
    A1: 7, P. maestri Del Lavoro - 20063 Cernusco sul Naviglio (MI)"
    si dividesse in:
    B1: 7
    C1: p. maestri del lavoro
    D1: 20063
    E1: cernusco sul naviglio
    F1: (MI)
    mi sapete con quale macro posso risolvere? grazie



  • di Vecchio Frac data: 13/02/2015 15:36:28

    Prima di essere un problema di macro, è un problema di logica (o di ragionamento) e di struttura dei dati.
    Sarebbe magnifico se tutti gli indirizzi avessero una struttura comune, per cui poi con una regex o con qualche colpo di left e mid, instr e split, sarebbe facile recuperare le diverse sottostringhe.
    Ma la struttura dei dati in colonna indirizzi non sarà sempre omogenea purtroppo.
    Ci sarà una virgola in più o in meno, ci sarà un punto invece del trattino, alcuni non avranno le parentesi attorno alla provincia, ecc.
    Per cortesia, tanto per capirci, prendi una ventina di righe del tuo indirizzario e allegale in un nuovo post, così vediamo la base dati reale che dobbiamo affrontare.






  • di Antonio (utente non iscritto) data: 13/02/2015 15:55:52

    queste sono le prime venti righe:
    7, P. maestri Del Lavoro - 20063 Cernusco sul Naviglio (MI)
    80/16, Str. Molina - 20060 Vignate (MI)
    Strada 6 Edificio L - 20089 Rozzano (MI)
    32/34, V. Socrate - 20128 Milano (MI)
    80, V. Battisti - 20010 Pogliano Milanese (MI)
    3, V. Aosta - 20063 Cernusco Sul Naviglio (MI)
    8, V. Goito (Presso La Standa) - 20037 Paderno Dugnano (MI)
    1, V. Zaccaria S. Antonio - 20122 Milano (MI)
    7, V. Trento Per Passirana - 20017 Rho (MI)
    47, V. Roveggia - 20100 Milano (MI)
    6, V. Tamburini - 20123 Milano (MI)
    30/34, V. Spartaco - 20135 Milano (MI)
    7, V. Umbria - 20098 San Giuliano Milanese (MI)
    13, V. Uberti - 20129 Milano (MI)
    5, V. Aosta - 20063 Cernusco Sul Naviglio (MI)
    5, Via Rosenthal Ernest Charles - 20089 Rozzano (MI)
    22/A, Via Linificio Case Alte - 20062 Cassano D'Adda (MI)
    15, Via Tanaro - 20017 Rho (MI)
    11, Localita Incugnate - 20060 Pozzuolo Martesana (MI)
    generalmente vorrei che nella prima cella mi prenda il testo prima della virgola, nella seconda dalla virgola al trattino, la terza vorrei prendesse 5 caratteri numerici, e così via



  • di Vecchio Frac data: 13/02/2015 16:25:23

    Allego un codice messo giù al volo.
    Gli indirizzi di colonna A vengono spalmati sulle colonne da B a F.
    Come vedrai, segnerà "errore" nella cella in corrispondenza della terza riga che riporta "Strada 6 Edificio L - 20089 Rozzano (MI) " e che conferma il problema di omogeneità della base dati che segnalavo (non inizia con numero e virgola).
    Ma insomma è già qualcosa :o)
     
    Option Explicit
    
    Sub split_address()
    Dim cell As Range, v As Variant
    
        '11, Localita Incugnate - 20060 Pozzuolo Martesana (MI)
        
        On Error GoTo gest_err
        
        For Each cell In Range("A:A")
            If Trim(cell) = "" Then Exit For
            
            v = Split(cell, ",")
            Cells(cell.Row, "B") = "'" & LTrim(v(0))    'numero civico
            v = Split(v(1), "-")
            Cells(cell.Row, "C") = LTrim(v(0))     'loc, piazza, via
            v = v(1)
            Cells(cell.Row, "D") = Left(LTrim(v), 5)     'cap
            v = Split(Trim(Mid(v, 7)), "(")
            Cells(cell.Row, "E") = LTrim(v(0))      'comune
            Cells(cell.Row, "F") = Left(v(1), 2)     'provincia
    resume_here:
        Next
        
        MsgBox "Ho finito!"
        Exit Sub
        
    gest_err:
        Cells(cell.Row, "B") = "* * * ERRORE * * *"
        Resume resume_here
            
    End Sub
    






  • di Antonio (utente non iscritto) data: 13/02/2015 16:37:16

    quando provo ad applicare la macro, il contenuto di tutte le celle di quella colonna diventa:
    ***ERRORE***
    anche se provo ad applicarlo ad una sola cella



  • di Vecchio Frac data: 13/02/2015 16:42:05

    Gli indirizzi sono in colonna A?





  • di Antonio (utente non iscritto) data: 13/02/2015 16:50:15

    Ok risolto, ti ringrazio molto, mi hai salvato.



  • di Vecchio Frac data: 13/02/2015 17:05:59

    Bene.
    la versione che segue, con le regexp, è più carina, più elegante e più efficiente, ma non solleva l'errore del dato errato, e quindi sbaglia a incolonnare i dati.
     
    Sub split_address_regexp()
    Dim regex As Object, cell As Range, v As Variant, i As Integer
    
        Range("B:F").ClearContents
        Set regex = CreateObject("VBScript.Regexp")
    
        With regex
            .Global = True
            .MultiLine = True
            .IgnoreCase = False
            .Pattern = "d+|(w+s+)+|(?!()[A-Z][A-Z]"
        End With
        
        For Each cell In Range("A:A")
            If Trim(cell) = "" Then Exit For
            If regex.test(cell.Value) Then
                
                i = 1
                For Each v In regex.Execute(cell.Value)
                    i = i + 1
                    Cells(cell.Row, i) = v
                Next
            Else
                Cells(cell.Row, "B") = "* * * ERRORE * * *"
            End If
        Next
    End Sub






  • di scossa data: 13/02/2015 23:17:38

    Mi sono permesso di modificare la sub di Vecchio Frac, giusto come spunto .....


    scossa's web site
    Se tu hai una mela, ed io ho una mela, e ce le scambiamo, allora tu ed io abbiamo sempre una mela per uno.
    Ma se tu hai un'idea, ed io ho un'idea, e ce le scambiamo, allora abbiamo entrambi due idee. (George Bernard Shaw)

     
    Sub split_address_regexp()
      Dim regex As Object, cell As Range, k As Long, i As Integer
      Dim oMatch As Object
    
      Range("B:F").ClearContents
      Set regex = CreateObject("VBScript.Regexp")
    
      With regex
        .Global = True
        .MultiLine = False
        .IgnoreCase = True
      End With
      
      For Each cell In Range("A:A")
        If Trim(cell) = "" Then Exit For
        regex.Pattern = "(^d*/*w*,)"
        If regex.test(cell.Value) Then
          Set oMatch = regex.Execute(cell.Value)
          cell.Offset(0, 1) = "'" & Replace(oMatch(0), ",", "")
        Else
          cell.Offset(0, 1) = "n. civico non presente"
        End If
        
        regex.Pattern = "([a-z])+(?!(,)+)([a-z.])+( |.)+(?"
        If regex.test(cell.Value) Then
          Set oMatch = regex.Execute(cell.Value)
          cell.Offset(0, 2) = Replace(oMatch(0), " -", "")
        Else
          cell.Offset(0, 2) = "via non presente"
        End If
      
        regex.Pattern = "(?:[-]{1} )(w+ )+"
        If regex.test(cell.Value) Then
          Set oMatch = regex.Execute(cell.Value)
          cell.Offset(0, 3) = Replace(oMatch(0), "- ", "")
        Else
          cell.Offset(0, 3) = "città non presente"
        End If
      
        regex.Pattern = "([a-z]{2})"
        If regex.test(cell.Value) Then
          Set oMatch = regex.Execute(cell.Value)
          cell.Offset(0, 4) = oMatch(0)
        Else
          cell.Offset(0, 4) = "provincia non presente"
        End If
          
      Next
      Set oMatch = Nothing
      Set regex = Nothing
    End Sub
    



  • di scossa data: 13/02/2015 23:20:27

    ripropongo il codice corretto.



    scossa's web site
    Se tu hai una mela, ed io ho una mela, e ce le scambiamo, allora tu ed io abbiamo sempre una mela per uno.
    Ma se tu hai un'idea, ed io ho un'idea, e ce le scambiamo, allora abbiamo entrambi due idee. (George Bernard Shaw)

     
    Sub split_address_regexp()
      Dim regex As Object, cell As Range, k As Long, i As Integer
      Dim oMatch As Object
    
      Range("B:F").ClearContents
      Set regex = CreateObject("VBScript.Regexp")
    
      With regex
        .Global = True
        .MultiLine = False
        .IgnoreCase = True
      End With
      
      For Each cell In Range("A:A")
        If Trim(cell) = "" Then Exit For
        regex.Pattern = "(^d*/*w*,)"
        If regex.test(cell.Value) Then
          Set oMatch = regex.Execute(cell.Value)
          cell.Offset(0, 1) = "'" & Replace(oMatch(0), ",", "")
        Else
          cell.Offset(0, 1) = "n. civico non presente"
        End If
        
        regex.Pattern = "([a-z])+(?!(,)+)([a-z.])+( |.)+-"
        If regex.test(cell.Value) Then
          Set oMatch = regex.Execute(cell.Value)
          cell.Offset(0, 2) = Replace(oMatch(0), " -", "")
        Else
          cell.Offset(0, 2) = "via non presente"
        End If
      
        regex.Pattern = "(?:[-]{1} )(w+ )+"
        If regex.test(cell.Value) Then
          Set oMatch = regex.Execute(cell.Value)
          cell.Offset(0, 3) = Replace(oMatch(0), "- ", "")
        Else
          cell.Offset(0, 3) = "città non presente"
        End If
      
        regex.Pattern = "([a-z]{2})"
        If regex.test(cell.Value) Then
          Set oMatch = regex.Execute(cell.Value)
          cell.Offset(0, 4) = oMatch(0)
        Else
          cell.Offset(0, 4) = "provincia non presente"
        End If
          
      Next
      Set oMatch = Nothing
      Set regex = Nothing
    End Sub
    



  • di Vecchio Frac data: 14/02/2015 12:25:28

    Nel mio codice con regex una soluzione veloce al problema era di controllare il limite superiore di v in "For Each v In regex.Execute(cell.Value)", per cui se non ci sono esattamente 5 elementi in v allora si solleva l'errore. Questo perchè ho tenuto semplice il pattern della regex che dovrebbe coprire i casi "normali". Naturalmente senza sapere a quale livello si era verificato l'errore. Scossa ha ampliato il concetto e proceduto ad una verifica puntuale su ogni singolo elemento della stringa analizzata, ridefinendo i singoli pattern.