excelvbatext-to-column

text to column in excel using VBA


I will really appreciate your help if anyone can advise me how to separate the given data shown in the image into separate columns. I have tried using fixed length but you can separate the first 2 to 3 numbers correctly into the columns but the 4th, 5th onwards will not be able to separate into the columns properly. I even tried redadusting the break line but the breakline moves when you go beyond 4th and 5th column and you cannot let the complete phone number to place in the single column. I tried several VBA techniques too but none works.

Thanks for your help.

IMG1


Solution

  • Como 2.1 feat. the Non-Printables

    I used one of my previous solutions, changed a few lines to approximately fit your needs. The comments in the program might be wrong, but essentially it loops through column A in this workbook's ActiveSheet and splits the data by the first non-printable character it finds and puts the result in a newly created worksheet. So there is no danger for your initial worksheet. Let me know what does not work for you, so I can make a nice version or do it yourself (it's pretty overcommented).

    'With Source
      '.Title: Excel formula or SQL script that would put bulk text
      '        into individual cell
      '.Type: Question
      '.URL: https://stackoverflow.com/questions/52852141/excel-formula-or-sql-script-that-would-put-bulk-text-into-individual-cell
    
    Option Explicit
    
    '-------------------------------------------------------------------------------
    Sub MultilineCellExtractor2() ' A work in progress
    '-------------------------------------------------------------------------------
    'Description
      'Copies the contents of each cell of a specified COLUMN in a worksheet,
      'skipping blank cells and converting multiple lines in cells each to a new
      'cell, and returns the result in a COLUMN of a newly created worksheet.
    'Arguments as constants
      'cStrColumn
        'The Column of the Initial Data in ThisWorkbook's ActiveSheet
      'cStrColumnResult
        'The Column of the Resulting Data in a Newly to be Created Worksheet
      'cLoRow
        'The First Row of the Resulting Data in the Newly Created Worksheet
    'Returns
      'A new worksheet with a column of the processed data.
    'Usage
      'Open the workbook to be processed. Go to VBE and insert a new module. Copy
      'this script ('MultilineCellExtractor') and the function 'FirstNonPrintable'
      'and paste them into the module. Edit the 'customize section' to fit your
      'needs. Exit VBE and start the Run Macro Dialog (Play Button). DoubleClick or
      'select 'MultilineCellExtractor' and click Run to execute.
    'Remarks
      'If there is no data in the column to be processed a message pops up (the only
      'error handling done so far). If there are no multiline cells, the data is
      'just copied while skipping the blanks.
      'There can be no damage done using this script in the previously described way
      'because the worksheet is only to be READ from, and the result is always
      'pasted into a NEW worksheet.
    
    '-------------------------------------------------------------------------------
    '-- CUSTOMIZE BEGIN --------------------
      Const cStrColumn As String = "A" 'Initial Data Column
    
      Const cStrColumnResult As String = "A" 'Resulting Data Column
      Const cLoRow As Long = 0 '0 to use the first row of the initial data range.
    '-- CUSTOMIZE END ----------------------
    
    '-------------------------------------------------------------------------------
      Dim oRng As Range 'Initial Colum, Initial Range, Resulting Range
    
      Dim arrRng As Variant 'Array Containing the Initial Data Range (Column)
      Dim arrSplit As Variant 'Array Containing the Cell Lines
      Dim arrData() As Variant 'Array Containing the Resulting Data Range (Column)
    
      Dim loRow1 As Long 'First Row of the Initial Data Range (Column)
      Dim loRow2 As Long 'Last Row of the Initial Data Range (Column)
      Dim loRowResult As Long 'First Row of the Resulting Data Range (Column)
    
      Dim loRng As Long 'Initial Array Rows Counter
      Dim iSplit As Integer 'Multiline Cell Lines Counter
      Dim loData As Long 'Resulting Array(Range) Rows Calculator and Counter
    
      Dim strRng As String 'Initial Data Reader: Shortcut for arrRng(loRng, 1).
    
      Dim str1 As String 'Debug String Writer
      Dim lo1 As Long 'Debug String Array Data Counter
    
    '-------------------------------------------------------------------------------
      'Column of Initial Data
        'Needed to calculate first and last rows of data.
      Set oRng = ThisWorkbook.ActiveSheet.Range(cStrColumn & ":" & cStrColumn)
      'First Row Containing Data
      On Error Resume Next
        loRow1 = oRng.Find(What:="*", After:=Cells(Rows.Count, cStrColumn), _
            LookIn:=xlValues, LookAt:=xlPart, _
            SearchOrder:=xlByRows, SearchDirection:=xlNext).Row
        If Err Then
          MsgBox "You have probably selected a column with no data."
          GoTo ProcedureExit
        End If
      'Last Row Containing Data
      loRow2 = oRng.Find(What:="*", After:=Cells(1, cStrColumn), _
        LookIn:=xlValues, LookAt:=xlPart, _
        SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
      'Calculate Initial Range
      Set oRng = ThisWorkbook.ActiveSheet.Range(Cells(loRow1, cStrColumn), _
          Cells(loRow2, cStrColumn))
    
    '  str1 = "Calculate Initial Range (Results):"
    '  str1 = str1 & vbCrLf & Space(2) & "loRow1 = " & loRow1
    '  str1 = str1 & vbCrLf & Space(2) & "loRow2 = " & loRow2
    '  str1 = str1 & vbCrLf & Space(2) & "oRng.Address: " & oRng.Address
    '  Debug.Print str1 & vbCrLf
    
      'Paste range into array
      arrRng = oRng
      Set oRng = Nothing 'Release the variable, initial data is in arrRng.
    
    '  str1 = "arrRng Contents:"
    '  For lo1 = LBound(arrRng) To UBound(arrRng)
    '      str1 = str1 & vbCrLf & Space(2) & lo1 & ". " & arrRng(lo1, 1)
    '  Next
    '  Debug.Print str1 & vbCrLf
    
    '-------------------------------------------------------------------------------
    'Now arrays are taking over
    
    '***
    Dim iData As Integer
    
      'Count data in arrRng to calculate size of arrData.
      For loRng = LBound(arrRng) To UBound(arrRng)
        strRng = arrRng(loRng, 1)
        If strRng <> "" Then 'Not empty cell, continue.
          If FirstNonPrintable(strRng) > 0 Then 'Non printable character found.
            'Splitting arrSplit by 'FirstNonPrintable'
            arrSplit = Split(strRng, Chr(FirstNonPrintable(strRng)))
    '***
            If iData < UBound(arrSplit) + 1 Then
    '***
              iData = UBound(arrSplit) + 1
    '***
            End If
            loData = loData + 1  '+ 1 i.e. arrSplit is 0-based.
           Else 'Nonprintable character not found.
            loData = loData + 1
          End If
    '     Else 'Empty cell, do nothing.
        End If
      Next
    
      'Redeclare arrData using the result of the counting (loData).
      ReDim Preserve arrData(1 To loData, 1 To iData)
    
      'Reset counter for counting.
      loData = 0
      iData = 0
      'Read data from arrRng and write to array.
      For loRng = LBound(arrRng) To UBound(arrRng)
        strRng = arrRng(loRng, 1)
        If strRng <> "" Then 'Not empty cell, continue.
          If FirstNonPrintable(strRng) > 0 Then 'Non printable character found.
            'Splitting arrSplit by 'FirstNonPrintable'
            arrSplit = Split(strRng, Chr(FirstNonPrintable(strRng)))
    '
      str1 = "arrSplit Contents:"
      For lo1 = LBound(arrSplit) To UBound(arrSplit)
          str1 = str1 & vbCrLf & Space(2) & lo1 + 1 & ". " & arrSplit(lo1)
      Next
      Debug.Print str1 & vbCrLf
    
              loData = loData + 1
    
            'Writing arrSplit data to arrData.
            For iSplit = LBound(arrSplit) To UBound(arrSplit)
              arrData(loData, iSplit + 1) = arrSplit(iSplit)
            Next
    
            Erase arrSplit 'Is repeatedly newly created to write data to arrData.
    
           Else 'Nonprintable character not found.
            loData = loData + 1
            arrData(loData, 1) = strRng
          End If
    '     Else 'Empty cell, do nothing.
        End If
      Next
    
      Erase arrRng 'No longer needed, resulting data is in arrData.
    '
      Dim i1 As Integer
      str1 = "arrData Contents:"
      For lo1 = LBound(arrData) To UBound(arrData)
        For i1 = LBound(arrData, 2) To UBound(arrData, 2)
          str1 = str1 & vbCrLf & Space(2) & lo1 & ". " & arrData(lo1, i1)
        Next
      Next
      Debug.Print str1
    '
    '-------------------------------------------------------------------------------
    'Return data in new worksheet
    
      'Calculate the first row of data in the resulting worksheet.
      If cLoRow > 0 Then
        loRowResult = cLoRow 'Row as the constant in the 'customize section'.
       Else
        loRowResult = loRow1 'Same row as in the initial worksheet.
      End If
      'Add a new (resulting) worksheet positioned after the initial worksheet.
      ThisWorkbook.Worksheets.Add _
          After:=ActiveSheet 'The resulting worksheet is active now.
      'Calculate the resulting range in the new worksheet.
      Set oRng = ActiveSheet.Cells(loRowResult, cStrColumnResult). _
          Resize(UBound(arrData), UBound(arrData, 2))
    
    Debug.Print oRng.Address
      'Paste data into the resulting range.
      oRng = arrData
      Erase arrData 'No longer needed, all data is in oRng.
    
    '-------------------------------------------------------------------------------
    ProcedureExit:
      Set oRng = Nothing 'Release the variable, all data is in the worksheet.
    
    End Sub
    '-------------------------------------------------------------------------------
    
    '-------------------------------------------------------------------------------
    Function FirstNonPrintable(StringToClean As String, _
        Optional Code0Position1String2 As Integer = 0) As Variant
    '-------------------------------------------------------------------------------
    'Description
      'Finds the first character in a string that is different from the character
      'at the same position in the cleaned version of the same string and returns
      'its code, position or string.
    'Arguments
      'StringToClean (String)
        'The string to clean.
      'Code0Position1String2 (Integer)
        'Returns for
          '0, the character code (Asc) of the found character to be used with
            'the Chr function.
          '1, the position of the found character.
          '2, the found character.
    
      Dim strCleaned As String
      Dim loLen As Long
    
      strCleaned = WorksheetFunction.Clean(StringToClean)
    
      If StringToClean = strCleaned Then Exit Function
    
      For loLen = 1 To Len(StringToClean)
        If Mid(StringToClean, loLen, 1) <> Mid(strCleaned, loLen, 1) Then
          Select Case Code0Position1String2
            Case 0
              FirstNonPrintable = Asc(Mid(StringToClean, loLen, 1))
            Case 1
              FirstNonPrintable = loLen
            Case 2
              FirstNonPrintable = Mid(StringToClean, loLen, 1)
          End Select
          Exit Function
        End If
      Next
    
    End Function
    '-------------------------------------------------------------------------------
    

    This is the file from the link you posted:

    enter image description here

    And this is the result in a new worksheet after the program runs:

    enter image description here

    You said put the values into separate columns. There are 120 lines on your sheet that aren't blank, including the line with phone in it. And there are 120 lines in the newly created resulting sheet and the data is split into columns. Now, if you could explain to me what is wrong with the output so I can fix it. BTW the program will run til the end of the column no matter how many blank lines. Only a memory shortage can crash it.

    'With Source
      '.Title: Excel formula or SQL script that would put bulk text
      '        into individual cell
      '.Type: Question
      '.URL: https://stackoverflow.com/questions/52852141/excel-formula-or-sql-script-that-would-put-bulk-text-into-individual-cell
    
    Option Explicit
    
    '-------------------------------------------------------------------------------
    Sub MultilineCellExtractor()
    '-------------------------------------------------------------------------------
    'Description
      'Copies the contents of each cell of a specified COLUMN in a worksheet,
      'skipping blank cells and converting multiple lines in cells each to a new
      'cell, and returns the result in a COLUMN of a newly created worksheet.
    'Arguments as constants
      'cStrColumn
        'The Column of the Initial Data in ThisWorkbook's ActiveSheet
      'cStrColumnResult
        'The Column of the Resulting Data in a Newly to be Created Worksheet
      'cLoRow
        'The First Row of the Resulting Data in the Newly Created Worksheet
    'Returns
      'A new worksheet with a column of the processed data.
    'Usage
      'Open the workbook to be processed. Go to VBE and insert a new module. Copy
      'this script ('MultilineCellExtractor') and the function 'FirstNonPrintable'
      'and paste them into the module. Edit the 'customize section' to fit your
      'needs. Exit VBE and start the Run Macro Dialog (Play Button). DoubleClick or
      'select 'MultilineCellExtractor' and click Run to execute.
    'Remarks
      'If there is no data in the column to be processed a message pops up (the only
      'error handling done so far). If there are no multiline cells, the data is
      'just copied while skipping the blanks.
      'There can be no damage done using this script in the previously described way
      'because the worksheet is only to be READ from, and the result is always
      'pasted into a NEW worksheet.
    
    '-------------------------------------------------------------------------------
    '-- CUSTOMIZE BEGIN --------------------
      Const cStrColumn As String = "A" 'Initial Data Column
    
      Const cStrColumnResult As String = "A" 'Resulting Data Column
      Const cLoRow As Long = 0 '0 to use the first row of the initial data range.
    '-- CUSTOMIZE END ----------------------
    
    '-------------------------------------------------------------------------------
      Dim oRng As Range 'Initial Colum, Initial Range, Resulting Range
    
      Dim arrRng As Variant 'Array Containing the Initial Data Range (Column)
      Dim arrSplit As Variant 'Array Containing the Cell Lines
      Dim arrData() As Variant 'Array Containing the Resulting Data Range (Column)
    
      Dim loRow1 As Long 'First Row of the Initial Data Range (Column)
      Dim loRow2 As Long 'Last Row of the Initial Data Range (Column)
      Dim loRowResult As Long 'First Row of the Resulting Data Range (Column)
    
      Dim loRng As Long 'Initial Array Rows Counter
      Dim iSplit As Integer 'Multiline Cell Lines Counter
      Dim loData As Long 'Resulting Array(Range) Rows Calculator and Counter
    
      Dim strRng As String 'Initial Data Reader: Shortcut for arrRng(loRng, 1).
    
      Dim str1 As String 'Debug String Writer
      Dim lo1 As Long 'Debug String Array Data Counter
    
    '-------------------------------------------------------------------------------
      'Column of Initial Data
        'Needed to calculate first and last rows of data.
      Set oRng = ThisWorkbook.ActiveSheet.Range(cStrColumn & ":" & cStrColumn)
      'First Row Containing Data
      On Error Resume Next
        loRow1 = oRng.Find(What:="*", After:=Cells(Rows.Count, cStrColumn), _
            LookIn:=xlValues, LookAt:=xlPart, _
            SearchOrder:=xlByRows, SearchDirection:=xlNext).Row
        If Err Then
          MsgBox "You have probably selected a column with no data."
          GoTo ProcedureExit
        End If
      'Last Row Containing Data
      loRow2 = oRng.Find(What:="*", After:=Cells(1, cStrColumn), _
        LookIn:=xlValues, LookAt:=xlPart, _
        SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
      'Calculate Initial Range
      Set oRng = ThisWorkbook.ActiveSheet.Range(Cells(loRow1, cStrColumn), _
          Cells(loRow2, cStrColumn))
    
    '  str1 = "Calculate Initial Range (Results):"
    '  str1 = str1 & vbCrLf & Space(2) & "loRow1 = " & loRow1
    '  str1 = str1 & vbCrLf & Space(2) & "loRow2 = " & loRow2
    '  str1 = str1 & vbCrLf & Space(2) & "oRng.Address: " & oRng.Address
    '  Debug.Print str1 & vbCrLf
    
      'Paste range into array
      arrRng = oRng
      Set oRng = Nothing 'Release the variable, initial data is in arrRng.
    
    '  str1 = "arrRng Contents:"
    '  For lo1 = LBound(arrRng) To UBound(arrRng)
    '      str1 = str1 & vbCrLf & Space(2) & lo1 & ". " & arrRng(lo1, 1)
    '  Next
    '  Debug.Print str1 & vbCrLf
    
    '-------------------------------------------------------------------------------
    'Now arrays are taking over
    
    '***
    Dim iData As Integer
    
      'Count data in arrRng to calculate size of arrData.
      For loRng = LBound(arrRng) To UBound(arrRng)
        strRng = arrRng(loRng, 1)
    '    If strRng <> "" Then 'Not empty cell, continue.
          If FirstNonPrintable(strRng) > 0 Then 'Non printable character found.
            'Splitting arrSplit by 'FirstNonPrintable'
            arrSplit = Split(strRng, Chr(FirstNonPrintable(strRng)))
    '***
            If iData < UBound(arrSplit) + 1 Then
    '***
              iData = UBound(arrSplit) + 1
    '***
            End If
            loData = loData + 1  '+ 1 i.e. arrSplit is 0-based.
           Else 'Nonprintable character not found.
            loData = loData + 1
          End If
    '     Else 'Empty cell, do nothing.
    '    End If
      Next
    
      'Redeclare arrData using the result of the counting (loData).
      ReDim Preserve arrData(1 To loData, 1 To iData)
    
      'Reset counter for counting.
      loData = 0
      iData = 0
      'Read data from arrRng and write to array.
      For loRng = LBound(arrRng) To UBound(arrRng)
        strRng = arrRng(loRng, 1)
    '    If strRng <> "" Then 'Not empty cell, continue.
          If FirstNonPrintable(strRng) > 0 Then 'Non printable character found.
            'Splitting arrSplit by 'FirstNonPrintable'
            arrSplit = Split(strRng, Chr(FirstNonPrintable(strRng)))
    '
      str1 = "arrSplit Contents:"
      For lo1 = LBound(arrSplit) To UBound(arrSplit)
          str1 = str1 & vbCrLf & Space(2) & lo1 + 1 & ". " & arrSplit(lo1)
      Next
      Debug.Print str1 & vbCrLf
    
              loData = loData + 1
    
            'Writing arrSplit data to arrData.
            For iSplit = LBound(arrSplit) To UBound(arrSplit)
              arrData(loData, iSplit + 1) = arrSplit(iSplit)
            Next
    
            Erase arrSplit 'Is repeatedly newly created to write data to arrData.
    
           Else 'Nonprintable character not found.
            loData = loData + 1
            arrData(loData, 1) = strRng
          End If
    '     Else 'Empty cell, do nothing.
    '    End If
      Next
    
      Erase arrRng 'No longer needed, resulting data is in arrData.
    '
      Dim i1 As Integer
      str1 = "arrData Contents:"
      For lo1 = LBound(arrData) To UBound(arrData)
        For i1 = LBound(arrData, 2) To UBound(arrData, 2)
          str1 = str1 & vbCrLf & Space(2) & lo1 & ". " & arrData(lo1, i1)
        Next
      Next
      Debug.Print str1
    '
    '-------------------------------------------------------------------------------
    'Return data in new worksheet
    
      'Calculate the first row of data in the resulting worksheet.
      If cLoRow > 0 Then
        loRowResult = cLoRow 'Row as the constant in the 'customize section'.
       Else
        loRowResult = loRow1 'Same row as in the initial worksheet.
      End If
      'Add a new (resulting) worksheet positioned after the initial worksheet.
      ThisWorkbook.Worksheets.Add _
          After:=ActiveSheet 'The resulting worksheet is active now.
      'Calculate the resulting range in the new worksheet.
      Set oRng = ActiveSheet.Cells(loRowResult, cStrColumnResult). _
          Resize(UBound(arrData), UBound(arrData, 2))
    
    Debug.Print oRng.Address
      'Paste data into the resulting range.
      oRng = arrData
      Erase arrData 'No longer needed, all data is in oRng.
    
    '-------------------------------------------------------------------------------
    ProcedureExit:
      Set oRng = Nothing 'Release the variable, all data is in the worksheet.
    
    End Sub
    '-------------------------------------------------------------------------------
    
    '-------------------------------------------------------------------------------
    Function FirstNonPrintable(StringToClean As String, _
        Optional Code0Position1String2 As Integer = 0) As Variant
    '-------------------------------------------------------------------------------
    'Description
      'Finds the first character in a string that is different from the character
      'at the same position in the cleaned version of the same string and returns
      'its code, position or string.
    'Arguments
      'StringToClean (String)
        'The string to clean.
      'Code0Position1String2 (Integer)
        'Returns for
          '0, the character code (Asc) of the found character to be used with
            'the Chr function.
          '1, the position of the found character.
          '2, the found character.
    
      Dim strCleaned As String
      Dim loLen As Long
    
      strCleaned = WorksheetFunction.Clean(StringToClean)
    
      If StringToClean = strCleaned Then Exit Function
    
      For loLen = 1 To Len(StringToClean)
        If Mid(StringToClean, loLen, 1) <> Mid(strCleaned, loLen, 1) Then
          Select Case Code0Position1String2
            Case 0
              FirstNonPrintable = Asc(Mid(StringToClean, loLen, 1))
            Case 1
              FirstNonPrintable = loLen
            Case 2
              FirstNonPrintable = Mid(StringToClean, loLen, 1)
          End Select
          Exit Function
        End If
      Next
    
    End Function
    '-------------------------------------------------------------------------------
    

    Todays Results should be what you're looking for.

    enter image description here