VBA: Convert Text to Number - excel

I have columns of numbers that, for whatever reason, are formatted as text. This prevents me from using arithmetic functions such as the subtotal function. What is the best way to convert these "text numbers" to true numbers?
Here is a screenshot of the specific issue:
I've tried these snippets to no avail:
Columns(5).NumberFormat = "0"
and
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False

Use the below function (changing [E:E] to the appropriate range for your needs) to circumvent this issue (or change to any other format such as "mm/dd/yyyy"):
[E:E].Select
With Selection
.NumberFormat = "General"
.Value = .Value
End With
P.S. In my experience, this VBA solution works SIGNIFICANTLY faster on large data sets and is less likely to crash Excel than using the 'warning box' method.

I had this problem earlier and this was my solution.
With Worksheets("Sheet1").Columns(5)
.NumberFormat = "0"
.Value = .Value
End With

This can be used to find all the numeric values (even those formatted as text) in a sheet and convert them to single (CSng function).
For Each r In Sheets("Sheet1").UsedRange.SpecialCells(xlCellTypeConstants)
If IsNumeric(r) Then
r.Value = CSng(r.Value)
r.NumberFormat = "0.00"
End If
Next

This converts all text in columns of an Excel Workbook to numbers.
Sub ConvertTextToNumbers()
Dim wBook As Workbook
Dim LastRow As Long, LastCol As Long
Dim Rangetemp As Range
'Enter here the path of your workbook
Set wBook = Workbooks.Open("yourWorkbook")
LastRow = Cells.Find(What:="*", After:=Range("A1"), SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
LastCol = Cells.Find(What:="*", After:=Range("A1"), SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column
For c = 1 To LastCol
Set Rangetemp = Cells(c).EntireColumn
Rangetemp.TextToColumns DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=True, _
Semicolon:=False, Comma:=False, Space:=False, Other:=False, FieldInfo _
:=Array(1, 1), TrailingMinusNumbers:=True
Next c
End Sub

''Convert text to Number with ZERO Digits and Number convert ZERO Digits
Sub ZERO_DIGIT()
On Error Resume Next
Dim rSelection As Range
Set rSelection = rSelection
rSelection.Select
With Selection
Selection.NumberFormat = "General"
.Value = .Value
End With
rSelection.Select
Selection.NumberFormat = "0"
Set rSelection = Nothing
End Sub
''Convert text to Number with TWO Digits and Number convert TWO Digits
Sub TWO_DIGIT()
On Error Resume Next
Dim rSelection As Range
Set rSelection = rSelection
rSelection.Select
With Selection
Selection.NumberFormat = "General"
.Value = .Value
End With
rSelection.Select
Selection.NumberFormat = "0.00"
Set rSelection = Nothing
End Sub
''Convert text to Number with SIX Digits and Number convert SIX Digits
Sub SIX_DIGIT()
On Error Resume Next
Dim rSelection As Range
Set rSelection = rSelection
rSelection.Select
With Selection
Selection.NumberFormat = "General"
.Value = .Value
End With
rSelection.Select
Selection.NumberFormat = "0.000000"
Set rSelection = Nothing
End Sub

The solution that for me works is:
For Each xCell In Selection
xCell.Value = CDec(xCell.Value)
Next xCell

Using aLearningLady's answer above, you can make your selection range dynamic by looking for the last row with data in it instead of just selecting the entire column.
The below code worked for me.
Dim lastrow as Integer
lastrow = Cells(Rows.Count, 2).End(xlUp).Row
Range("C2:C" & lastrow).Select
With Selection
.NumberFormat = "General"
.Value = .Value
End With

The solution that worked for me many times is:
Sub ConvertTextToNumber()
With Range("A1:CX500") 'you can change the range
.NumberFormat = "General"
.Value = .Value
End With
End Sub

For large datasets a faster solution is required.
Making use of 'Text to Columns' functionality provides a fast solution.
Example based on column F, starting range at 25 to LastRow
Sub ConvTxt2Nr()
Dim SelectR As Range
Dim sht As Worksheet
Dim LastRow As Long
Set sht = ThisWorkbook.Sheets("DumpDB")
LastRow = sht.Cells(sht.Rows.Count, "F").End(xlUp).Row
Set SelectR = ThisWorkbook.Sheets("DumpDB").Range("F25:F" & LastRow)
SelectR.TextToColumns Destination:=Range("F25"), DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=True, _
Semicolon:=False, Comma:=False, Space:=False, Other:=False, FieldInfo _
:=Array(1, 1), TrailingMinusNumbers:=True
End Sub

From the recorded macro one gets the code below; for a new application you just need to update selection and range:
Sub num()
Columns("B:B").Select
Selection.TextToColumns Destination:=Range("B1"), DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=True, _
Semicolon:=False, Comma:=False, Space:=False, Other:=False, FieldInfo _
:=Array(1, 1), TrailingMinusNumbers:=True
End Sub

I had problems making above codes work. To me multiplying with 1 did the trick:-)
Cells(1, 1).Select
Cells(1, 1) = ActiveCell * 1

Related

vba loop texttocolumns in all worksheets

So, in a workbook I have a lot of sheets from which I want to use texttocolumns for a Date, the date is usually something like "11/22/2018 10:59:59 AM" and I only want it to do a MDY with a delimited text to columns. The delimiter must be false.
Sub LoopCertain() 'Excel VBA to exclude sheets
'SP Edit, error handler
On Error Goto errHandler
If False Then
errHandler:
MsgBox Err.Description
'This will cause the routine to carry on where it left off
Resume Next
End If
'SP End of Edit
Dim ws As Worksheet
Dim objRange1 As Range
Dim objRange2 As Range
For Each ws In ActiveWorkbook.Worksheets
Select Case ws.Name
Case Is = "General", "Verification", "OEM Plant Summary"
'No Code here if excluded
Case Else
'Set up the ranges
Set objRange1 = Range("C:C")
Set objRange2 = Range("I:I")
Set ws = ActiveSheet
'Do the first parse
objRange1.TextToColumns _
Destination:=Range("C1"), _
DataType:=xlDelimited, _
Tab:=False, _
Semicolon:=False, _
Comma:=False, _
Space:=False, _
Other:=False, _
OtherChar:="-"
'Do the second parse
objRange2.TextToColumns _
Destination:=Range("I1"), _
DataType:=xlDelimited, _
Tab:=False, _
Semicolon:=False, _
Comma:=False, _
Space:=False, _
Other:=False, _
OtherChar:="-"
End Select
Next ws
End Sub
I get errors when trying to run this. I need to change Columns "I" and "C" and results must be in the same column. Appreaciate if you can help since I have been like the whole week trying different types of loops and nothing works. This one work if I remove the Loop though...
Here is the sample data:
A fixed width would probably be more appropriate. Your sample data leaves some unanswered questions but I'll assume a mmddyyyy (not mdyyyy) date format and data that either starts in row 1 or has a header label in row 1 with 10 or less characters.
For Each ws In ActiveWorkbook.Worksheets
Select Case ws.Name
Case "General", "Verification", "OEM Plant Summary"
'No Code here if excluded
Case Else
With ws.Range("C:C")
.TextToColumns Destination:=.Cells(1), DataType:=xlFixedWidth, _
FieldInfo:=Array(Array(0, xlMDYFormat), Array(10, xlSkipColumn))
End With
With ws.Range("I:I")
.TextToColumns Destination:=.Cells(1), DataType:=xlFixedWidth, _
FieldInfo:=Array(Array(0, xlMDYFormat), Array(10, xlSkipColumn))
End With
End Select
Next ws
Why do you need to use TextToColumns? I would be tempted to convert the text to a proper date (meaning a date serial number) and then format the column in whichever way you want to display the date. The advantage of this method would be that you can actually retain the time value contained in the date if case you want to know it later but without displaying it.
However, since you are intending to manipulate the text I think the code below is more efficient. Please try it.
Sub ReformatDate()
Const FirstDataRow As Long = 1 ' change as appropriate
Dim Ws As Worksheet
Dim Rng As Range
Dim Arr As Variant
Dim C As Long
Dim i As Long
For Each Ws In Worksheets
If InStr(1, ",General,Verification,OEM Plant Summary", "," & Ws.Name, _
vbTextCompare) = 0 Then
With Ws
For C = 3 To 9 Step (9 - 3) ' columns C & I
Set Rng = .Range(.Cells(FirstDataRow, C), _
.Cells(.Rows.Count, C).End(xlUp))
Arr = Rng.Value
For i = 1 To UBound(Arr)
If Len(Arr(i, 1)) Then Arr(i, 1) = Split(Arr(i, 1))(0)
Next i
Rng.Value = Arr
.Columns(C).AutoFit
Next C
End With
Next Ws
End Sub

How to extract text from between brackets?

I wrote VBA code that opens all of the .xls files in a folder, and copies and pastes desired information out of those files into a new workbook.
Each row in the new workbook is associated with a file from the folder.
Column1, Column2, Column3
FileName1, ABC, XYZ
FileName2, DEF, TUV
The info in Column3 has the formatting of
ArbitraryString1(Very_Important_Info)ArbitraryString2
Because I wanted Column3 to look nice, I iterated over every row and used
Range("C"&X).TextToColumns DataType:=xlDelimited, Other:=True _
OtherChar:="("
Columns("E:E").Insert Shift:=xlToRight *
Range("D"&X).TextToColumn DataType:=xlDelimited, Other:=True _
OtherChar:=")"
Range("C"&X).TextToColumns DataType:=xlDelimited, Other:=True _
OtherChar:="(" **
Columns("E:Z").Delete
Columns("C:C").Delete
*This is needed so when I call TextToColumn the second time I do not get a message asking if I want to overwrite what is already in that column.
I end up with
Column1, Column2, Column3
FileName1, ABC, Very_Important_Info_1
FileName2, DEF, Very_Important_Info_2
After calling OtherChar:="(" the first time I end up seeing
(Very_Important_Info)ArbitraryString2
with the left bracket still attached.
I call the method a second time or ColumnC would look like
(Very_Important_Info
Might work better with SPLIT
Sub TextToCols()
Dim rng As Range
Dim r As Range
Dim l As Long
Dim arr As Variant
With ActiveSheet
l = .Cells(.Rows.Count, "C").End(xlUp).Row
Set rng = Range("C2:C" & l)
For Each r In rng
r.Value = Application.WorksheetFunction.Substitute(r.Value, ")", "(")
arr = Split(r.Value, "(")
Cells(r.Row, 3).Value = arr(1)
Next r
End With
End Sub
Or text-to-columns:
Sub TextToCols()
Dim rng As Range
Dim r As Range
Dim l As Long
With ActiveSheet
l = .Cells(.Rows.Count, "C").End(xlUp).Row
Set rng = Range("C2:C" & l)
For Each r In rng
r.Value = Application.WorksheetFunction.Substitute(r.Value, ")", "(")
Next r
With .UsedRange.Columns("C").Cells
.TextToColumns Destination:=Range("C1"), _
DataType:=xlDelimited, _
OtherChar:="("
End With
End With
End Sub
Here is a simplified version of Michal Rosa's code:
Sub BeautifyIt()
With Worksheets("Sheet1")
With .Range("C2", .Range("C" & .Rows.Count).End(xlUp))
.Replace ")", "("
.TextToColumns Destination:=.Cells(1, 1), DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=True, _
Semicolon:=False, Comma:=False, Space:=False, Other:=True, _
OtherChar:="(", FieldInfo:=Array(Array(1, 1), Array(2, 1)), TrailingMinusNumbers:=True
End With
End With
End Sub

Excel - How do I filter by "word contained"?

I have data in the following format:
I would like to filter or pivot filter by every unique word in the list. I know how to retrieve a list of unique words, like so:
so I have that data. But how do I filter by all these values. I want to see a report of all the Popularity and Price summed up for each of these words. This of course implies overlapping, as "Bike Parts" data would affect both Bike and Parts numbers. Thoughts? :)
To answer your ultimate question, use a =SUMIF formula.
To get this all automated, use VBA with a combination of text-to-columns, remove duplicates and the =SUMIF formula.
I was able to create the desired results with the following, although getting a sum of the Popularity seems odd...
Sub test1()
Application.ScreenUpdating = False
Dim lRow As Integer
Dim sRange As Range
lRow = ActiveSheet.Cells(ActiveSheet.Rows.Count, "A").End(xlUp).Row
Columns("F:H").ClearContents
Range("A2:A" & lRow).Select
Selection.Copy
Range("F2").Select
ActiveSheet.Paste
Columns("F:F").Select
Application.CutCopyMode = False
Selection.TextToColumns Destination:=Range("F1"), DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=True, _
Semicolon:=False, Comma:=False, Space:=False, Other:=True, OtherChar _
:=" ", FieldInfo:=Array(Array(1, 1), Array(2, 1)), TrailingMinusNumbers:=True
Set sRange = Range("G1")
sRange.Select
While Selection.End(xlDown).Value <> ""
sRange.Offset(1, 0).Select
Range(ActiveCell, ActiveCell.Offset(lRow - 1, 0)).Select
Selection.Cut
Range("F2").Select
Selection.End(xlDown).Select
Selection.Offset(1, 0).Select
ActiveSheet.Paste
Set sRange = sRange.Offset(0, 1)
sRange.Select
Wend
lRow = ActiveSheet.Cells(ActiveSheet.Rows.Count, "F").End(xlUp).Row
Columns("F:F").Select
ActiveSheet.Range("$F$1:$F$" & lRow).RemoveDuplicates Columns:=1, Header:=xlNo
lRow = ActiveSheet.Cells(ActiveSheet.Rows.Count, "F").End(xlUp).Row
Range("F2").Select
ActiveCell.Offset(0, 1).Value = "=SUMIF($A:$A,""*""&$F2&""*"",$B:$B)"
ActiveCell.Offset(0, 1).Style = "Percent"
ActiveCell.Offset(0, 2).Value = "=SUMIF($A:$A,""*""&$F2&""*"",$C:$C)"
ActiveCell.Offset(0, 2).Style = "Currency"
Range(ActiveCell.Offset(0, 1), ActiveCell.Offset(lRow - 2, 2)).FillDown
Range("F1").Value = Range("A1").Value
Range("G1").Value = Range("B1").Value
Range("H1").Value = Range("C1").Value
Range("A1").Select
Application.ScreenUpdating = True
End Sub

Text To Columns for variable number of lines

The code attached below is to split text to columns. I get an error when I run this code.
The data to be split is as follows:
NAME,1244
NAME,4356
NAME,5678
The number of lines with NAME is variable. I get run time error 1004, No data was selected to parse. How to solve this?
Sub SplitNameToColumns()
Dim rowCount As Long
rowCount = Cells(Rows.Count, "F").End(xlUp).Row
Range("F2").Select
For Counter = 1 To rowCount Step 1
Selection.TextToColumns Destination:=ActiveCell, DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, _
Tab:=False, Semicolon:=False, Comma:=True, Space:=False, _
Other:=False, _
FieldInfo:=Array(Array(1, 1)), _
TrailingMinusNumbers:=True
ActiveCell.Offset(1, 0).Select
Next Counter
End Sub
Try this:
Sub SplitAndScatter()
Dim LastRow As Long
LastRow = Cells(Rows.Count, "F").End(xlUp).Row
With Range("F2:F" & LastRow)
.TextToColumns Destination:=Range("F2"), DataType:=xlDelimited, Comma:=True
End With
End Sub
This is taken and modified from another question I answered here.
Let us know if this helps.

Excel, VBA, I need to sent rng to lastcolumn. Currently MsgBox will display it

basically i am using the TextToColumns function to separate out data separated by a semi colon in the same cell. problem is there are 2 columns of data that needs this function done and i have to insert the data without overwriting.
(go easy, first time with VBA and excel) this is what i currently have:
Sub Button1_Click()
Dim rng As Range
Dim sh As Worksheet
Set sh = Worksheets("Sheet1")
With sh
Set rng = .[Q1]
Set rng = .Range(rng, .Cells(.Rows.Count, rng.Column).End(xlUp))
num = Application.WorksheetFunction.Max(Columns("P"))
rng.Offset(0, 1).Resize(1, num).EntireColumn.Insert
rng.TextToColumns Destination:=rng, DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=False, _
Semicolon:=True, Comma:=False, Space:=False, Other:=False, _
FieldInfo:=Array(Array(1, 1), Array(2, 1), Array(3, 1)), TrailingMinusNumbers:=True
End With
Set sh2 = Worksheets("Sheet1")
With sh2
num2 = Application.WorksheetFunction.Max(Columns("P"))
Dim lastColumn As Integer
lastColumn = ActiveSheet.UsedRange.Column - 1 + ActiveSheet.UsedRange.Columns.Count
MsgBox Replace(Cells(1, lastColumn).Address(False, False), "1", "")
MsgBox lastColumn
Set rng = .[W1]
Set rng = .Range(rng, .Cells(.Rows.Count, rng.Column).End(xlUp))
rng.TextToColumns Destination:=rng, DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=False, _
Semicolon:=True, Comma:=False, Space:=False, Other:=False, _
FieldInfo:=Array(Array(1, 1), Array(2, 1), Array(3, 1)), TrailingMinusNumbers:=True
End With
End Sub
ok so what i am trying to fix is setting the rng manually in the second part to W1. the rng needs to be the next empty column. so lastColumn using the MsgBox DOES return the column "W" but i cannot set that to rng (type mismatch). oh and the num variable is set to the amount of columns i need to insert. my data looks like this:
count | column with ; data need separating | column with ; data need separating
5 | 5 sets of data separated by semi colons | don't care because this is the end of sheet
is there any easier way to do this? am i even close?
... Easiest solution if I understand your question correctly... Why don't you just make a THIRD column that equals Column1 & ";" & Column2, then just do text-to-columns on that single column??
Or am I missing something??
Assuming I'm understanding your setup correctly, the following code should work.
If you process the data columns from right to left, you don't have to worry about the change in address references when the columns are inserted. That means you can use a single block of insertion/conversion code, iterated over the two data address references, which I've assumed are Q1 and R1.
Note also that I added an offset to the TextToColumns destination to avoid overwriting the original data.
Option Explicit
Sub myTextToColumns()
Dim sh As Worksheet
Dim rng As Range
Dim num As Long
Dim arr As Variant
Dim i As Long
Set sh = Worksheets("Sheet1")
arr = Array("R1", "Q1")
num = Application.WorksheetFunction.Max(Columns("P"))
With sh
For i = LBound(arr) To UBound(arr)
Set rng = .Range(arr(i))
Set rng = .Range(rng, .Cells(.Rows.Count, rng.Column).End(xlUp))
rng.Offset(0, 1).Resize(1, num).EntireColumn.Insert
rng.TextToColumns Destination:=rng.Offset(0, 1), DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=False, _
Semicolon:=True, Comma:=False, Space:=False, Other:=False, _
FieldInfo:=Array(Array(1, 1), Array(2, 1), Array(3, 1)), TrailingMinusNumbers:=True
Next
End With
End Sub

Resources