Home » excel » excel – VBA: Impossible to Suppress Auto Conversion of Strings in Range.TextToColumns?

excel – VBA: Impossible to Suppress Auto Conversion of Strings in Range.TextToColumns?

Posted by: admin April 23, 2020 Leave a comment

Questions:

The TextToColumns method of the Range object automatically converts strings to numbers, but it would be nice to suppress this feature. The method has a TextQualifier parameter, but it doesn’t seem to do what I’m looking for. The following data illustrates the issue. Strings in column A are delimited with semicolons that separate a text part from a number part. Note that the numbers all begin with zero, and that numbers in row 4-6 are prefixed with an apostrophe:

Column A
StringRow1;01000
StringRow2;02000
StringRow3;03000
StringRow4;'01000
StringRow5;'02000
StringRow6;'03000

The following macro splits the strings into a text part in Column B and a number part in Column C.

Sub TTC()
    Application.DisplayAlerts = False
    Dim rToSplit As Range
    Set rToSplit = ThisWorkbook.Worksheets(1).Range("A1:A6")
    rToSplit.TextToColumns _
        Destination:=Range("B1"), _
        DataType:=xlDelimited, _
        Semicolon:=True, _
        TextQualifier:=xlTextQualifierNone
End Sub

The last column illustrates the desired output:

Column A               Column B           Column C
Data                   Output             Output             Desired Output
StringRow1;01000       StringRow1            1000                 01000
StringRow2;02000       StringRow2            2000                 02000
StringRow3;03000       StringRow3            3000                 03000
StringRow4;'01000      StringRow4          '01000                 01000
StringRow5;'02000      StringRow5          '02000                 02000
StringRow6;'03000      StringRow6          '03000                 03000

I have tried formatting column C ahead of the split, like this:
rToSplit.Offset(, 3).NumberFormat = "@", but it has no effect. Switching the TextQualifier parameter to xlTextQualifierSingleQuote has the effect of treating rows 4-6 in the same way as rows 1-3.

Am I asking for the impossible? Or is there maybe some application level setting I’m not aware of? Or could I do something smart with the strings in column A?

(I could of course loop through Column C after the split and fix the issue, but for large data sets that’s not attractive. For my particular application, the strings in column A are generated by code that searches for patterns in tens of thousands of text rows in several different text files; each match is added to a dictionary and then I use array() = Dictionary.Items and DestinationRange.Value = Application.WorksheetFunction.Transpose(array) to read the data to the worksheet. This is very fast. My workaround to deal with the issue described here is to save the number strings in a separate dictionary which is read to column C after the split. This works well, so I posted this out of curiosity to see what I can learn…)

How to&Answers:

You can use the FieldInfo property to set the data type for each column. You will need to know how many columns you have beforehand though, or know which column will contain the numbers.

The FieldInfo parameter takes an array of arrays, with each of the sub-arrays having 2 values. The first value represents the column number (starting at 1), and the second number is the XLColumnDataType you would like that column to be formatted as.

In this case, you’d like everything to be formatted as text (instead of a number, like it’s currently doing), so you would use xlTextFormat (this is just a system defined constant equal to 2).

x.TextToColumns _
    Destination:=Range("B1"), _
    DataType:=xlDelimited, _
    Semicolon:=True, _
    TextQualifier:=xlTextQualifierNone, _
    FieldInfo:=Array(Array(1, xlTextFormat), Array(2, xlTextFormat)) 'Format columns 1 and 2 as text

Answer:

If you are willing to do it with a loop:

Sub TTC()

    Dim row As Long, lastRow As Long, splitSpot As Integer, cellValue As String

    Application.ScreenUpdating = False    

    With ThisWorkbook.Worksheets(1)
        lastRow = .Cells(.Rows.Count, "A").End(xlUp).row
        For row = 1 To lastRow
           cellValue = CStr(.Range("A" & row).Value)
           splitSpot = InStr(cellValue, ";")
           .Range("B" & row & ":C" & row).NumberFormat = "@"
           .Range("B" & row).Value = Left(cellValue, splitSpot - 1)
           If Mid(cellValue, splitSpot, 1) = "'" Then
               .Range("C" & row).Value = Right(cellValue, Len(cellValue) - splitSpot + 1)
           Else
               .Range("C" & row).Value = Right(cellValue, Len(cellValue) - splitSpot)
           End If
        Next
    End With

End Sub

ss:

enter image description here