0

I'd like to make excel able to read an imported txt. file numbers and dates. My text files contain words, numbers and dates separated by commas but when I run my code, excel considers all the numbers as normal text so I have to manually change them to numbers. Is there a piece of code I can add to mine so that when I import the txt file, it automatically detects numbers? I was thinking of adding a sub texttonumber() but I'd like to have just one code that does everything at once instead of having a two-step process.

(Note: I`m aware I can use Power Query, but I want to go with VBA in this case)

Sub ImportText3()

    Dim ThisLine As Variant
    Dim fileFilterPattern As String
    Dim n As Long
    
    fileFilterPattern = "Text Files *.txt,*.txt"

    ThisLine = Application.GetOpenFilename(fileFilterPattern)
    
    If ThisLine = False Then
        MsgBox "No file selected."
        Exit Sub
    End If
    
    Application.ScreenUpdating = False
    
    Open ThisLine For Input As #1
    Do Until EOF(1)
        Line Input #1, ThisLine
        If Len(ThisLine) > 0 Then
            ThisLine = Replace(ThisLine, ",", Chr(9))
            ThisLine = Split(ThisLine, Chr(9))
            ActiveCell.Offset(n, 0).Resize(1, UBound(ThisLine) + 1).Value = ThisLine
        End If
        n = n + 1
    Loop
   
    Close #1

    Application.ScreenUpdating = True

End Sub
braX
  • 11,506
  • 5
  • 20
  • 33
  • Try reading it as a .csv file (change the .txt to .csv and just open it as a workbook). Excel will parse the fields automatically. You don't have to do that yourself. – RichardCook Apr 26 '23 at 02:45
  • @RichardCook you mean change my original txt files to csv? if so, it would defeat the purpose of my code + I`d like to keep them as they are. I hope this makes things a bit clear – Josue Criollo Apr 30 '23 at 02:04

1 Answers1

0

Sorry, I misunderstood the question. Your code reads a file into an Excel worksheet and parses each line into a row of cells, where cells are delimited by either a comma or a tab. Since you're splitting each line at commas/tabs, I had assumed your input files were already essentially .csv files with a .txt extension. But your code allows for lines with a variable number of fields, so reading them as csv wouldn't work anyway, even if you wanted to go that route.

I don't know a built-in way to make the text-to-number conversion, but I'm able to convert numbers using a regular expression (regex). To use a regex, you'll need to add a reference (it's version 5.5 in my Office 2019):

Tools/References: Microsoft VBScript Regular Expressions 5.5

If you're not comfortable with regex, see How to use Regular Expressions (Regex) in Microsoft Excel both in-cell and loops for an excellent reference. The pattern defined here

.Pattern = "^-?[0-9]*\.?[0-9]*$"

accepts a leading minus sign (not required), any number of digits, a decimal point (also not required), and any number of digits after the decimal (if there is a decimal).

The code tests every element of the input variant array against the regex, and converts numbers to their values. I find I have to copy the elements into a new variant for output. Excel won't allow converting the number from string to value in the original variant.

Sub ImportText3()

    Dim ThisLine As Variant
    Dim fileFilterPattern As String
    Dim n As Long
    Dim rngOutput As Range, nCells As Integer, nIndex As Integer
    Dim regexNumber As RegExp, vntRc As Variant, vntOutput As Variant
    
    fileFilterPattern = "Text Files *.txt,*.txt"

    ThisLine = Application.GetOpenFilename(fileFilterPattern)
    
    If ThisLine = False Then
        MsgBox "No file selected."
        Exit Sub
    End If
    
    ' Regular expression to look for values
    ' Accept any number of digits, with possible decimal and/or minus sign, nothing else
    Set regexNumber = New RegExp
    With regexNumber
        .Pattern = "^-?[0-9]*\.?[0-9]*$"  ' Define allowed characters to determine a number
    End With
    
    Application.ScreenUpdating = False
    
    Open ThisLine For Input As #1
    Do Until EOF(1)
        Line Input #1, ThisLine
        If Len(ThisLine) > 0 Then
            ThisLine = Replace(ThisLine, ",", Chr(9))
            ThisLine = Split(ThisLine, Chr(9))
            nCells = UBound(ThisLine)
            
            ' Use an output variant to avoid forcing a value into a string
            ReDim vntOutput(0 To nCells)
            Set rngOutput = ActiveCell.Offset(n, 0).Resize(1, nCells + 1)
            
            ' Test each element for numeric values
            For nIndex = 0 To nCells
                vntRc = regexNumber.Test(ThisLine(nIndex))
                If vntRc = True Then
                    vntOutput(nIndex) = Val(ThisLine(nIndex)) ' If numeric, convert it to value
                Else
                    vntOutput(nIndex) = ThisLine(nIndex) ' If not, copy it as is
                End If
            Next nIndex
            
            rngOutput = vntOutput
            
        End If
        n = n + 1
    Loop
   
    Close #1

    Application.ScreenUpdating = True

End Sub
RichardCook
  • 846
  • 2
  • 10