Remove leading zeros from textbox VBA - excel

User inputs only numerical values in textbox name tbID, in my file, that column value is saved as numerical. However, if user input 00120 instead of 120. After attempting to remove the leading zeros, there seems to be a space before 120.
When I input Criteria1:="120" it works
tbIDf = Cint(tbID) 'Debug.Print tbIDf gives " 120" and renders my filter criteria to a blank
ActiveSheet.ListObjects("Table1").Range.AutoFilter Field:=IDN, Criteria1:="tbID"
How do I remove both the leading zeros and the " " in front of 120?

Here is a thought, I would make sure data that makes it to your sheet is actually correct usable data. To do so you could use:
Trim(Val(tbID))
The use of Val would return a double value ignoring non-numeric values, 120. Alternatively CLng is also a possibility returning a long value. Just don't use CInt as there is no need to use integers (range only from -32,768 to 32,767)
The TRIM function will remove leading and trailing spaces.
You can/should also implement a keypress event described here to make sure only numerical values are entered.

This should work:
Option Explicit
Sub test()
'just for testing (this comes from your textbox)
Dim tbID As String
tbID = "00120"
If IsNumeric(tbID) Then 'test if numeric to prevent errors
Dim MyCriteria As String
MyCriteria = CStr(CLng(tbID))
ActiveSheet.ListObjects("Table1").Range.AutoFilter Field:=IDN, Criteria1:=MyCriteria
End If
End Sub
If not use Trim(CStr(CLng(tbID)))

Related

Add text for under character limit

Just wondering if this is possible, and how I would go about doing it... I'm not sure if I can use conditional formatting, or if it requires VBA, or what.
I have a vlookup that I split coding for, but it only works when they include ".000000.00000.0000.0000" at the end. How would I go about adding ".000000.00000.0000.0000" when the character limit is under 46 for that cell? The coding will always be 46 characters when the zeroes are included, so anything under is invalid.
I was able to use =IF(LEN(A2) < 23, "0" & LEFT(A2,15),LEFT(A2,16)) to truncate what I needed and add leading zeroes if not included to have the end result do what I needed without all of the zeroes.
try this
Sub test()
Dim i As Long
Dim text As String
For i = 1 To 32767
text = text & "a"
Next
text = text & "end"
Range("A1").Value = text
'"end" will be lost
End Sub

Differentiate full stop from decimal values

I'm working on a formula that checks a cell for a "£" sign, then checks the value after it. If the value is anything other than a rounded value, e.g. "£30" or "£30.00", it would be an error.
My problem is, the text has a full stop after the decimal value. This results in the 'DECIMAL' value being returned. How do I not count £30. as an error.
Below is the formula as input through VBA
=IF(ISERROR(SEARCH(""."",LEFT((RIGHT(RC[-2],LEN(RC[-2])-SEARCH(""£"",RC[-2]))),SEARCH("" "",(RIGHT(RC[-2],LEN(RC[-2])-SEARCH(""£"",RC[-2])))))))=FALSE,IF(ISERROR(SEARCH("".00"",LEFT((RIGHT(RC[-2],LEN(RC[-2])-SEARCH(""£"",RC[-2]))),SEARCH("" "",(RIGHT(RC[-2],LEN(RC[-2])-SEARCH(""£"",RC[-2])))))))=FALSE,"""",""DECIMAL""),"""")
Here is a User Defined Function that should do what you want. It looks for a substring that starts with the € currency sign and then some number of digits. If there is a dot following, it looks at the dot and the next two digits (or nothing if no digits). If the value of that sequence is zero, then the function returns TRUE, else FALSE
Obviously, you can modify this to return whatever you want, or use it within an IF formula on the worksheet.
Note that it will only work on strings, and not on values formatted as currency.
Option Explicit
Function ValidCurrency(S As String) As Boolean
Dim RE As Object, MC As Object
Const sPattern As String = "€\s*\d+(\.\d{2})?"
ValidCurrency = False
Set RE = CreateObject("vbscript.regexp")
With RE
.Pattern = sPattern
If .test(S) = True Then
Set MC = .Execute(S)
ValidCurrency = (MC(0).submatches(0) = 0)
End If
End With
End Function
Assuming the string you want to check is in F1, I think you could do something like this:
=IF(ISNUMBER(FIND("£",F1)),IF(TRIM(MID(F1&"00",FIND("£",F1)+1,5))="30.00",TRUE,FALSE),FALSE)
This:
assumes the £ number you want to inspect is the first occurrence of that "£" character in the string.
Assumes that an occurrence of "£30." would occur at the end of the sentence, as you assert in your comments above.
But perhaps you left out some details for examples in which it won't work.
For your follow up question, the following would work for all two-digit whole number values (10 thru 99). Note that I'm comparing the value in the string to its ROUND()ed value to see if the two match, and thus make sure there's nothing after the decimal. This should be enough for you to adapt it further on your own if you need to cover a broader range of values, but at this point, I think I've answered your original question and then some.
=IF(ISNUMBER(FIND("£",F1)),IF(VALUE(TRIM(MID(F1&"00",FIND("£",F1)+1,5)))=ROUND(VALUE(TRIM(MID(F1&"00",FIND("£",F1)+1,5))),0),TRUE,FALSE),FALSE)

Add a space after colored text

I'm Using Microsoft Excel 2013.
I have a lot of data that I need to separate in Excel that is in a single cell. The "Text to Columns" feature works great except for one snag.
In a single cell, I have First Name, Last Name & Email address. The last name and email addresses do not have a space between them, but the color of the names are different than the email.
Example (all caps represent colored names RGB (1, 91, 167), lowercase is the email which is just standard black text):
JOHN DOEjohndoe#acmerockets.com
So I need to put a space after DOE so that it reads:
JOHN DOE johndoe#acmerockets.com
I have about 20k rows to go through so any tips would be appreciated. I just need to get a space or something in between that last name and email so I can use the "Text to Columns" feature and split those up.
Not a complete answer, but I would do it way:
Step 1 to get rid of the formatting:
Copy all text that you have to the notepad
Then copy-paste text from Notepad to excel as text
I think this should remove all the formatting issues
Step 2 is to use VBA to grab emails. I assume that you have all your emails as lowercase. Therefore something like this should do the trick (link link2):
([a-z0-9\-_+]*#([a-z0-9\-_+].)?[a-z0-9\-_+].[a-z0-9]{2,6})
Step 3 is to exclude emails that you extracted from Step2 from your main text. Something like this via simple Excel function:
=TRIM(SUBSTITUTE(FULLTEXT,EMAIL,""))
Since you removed all the formatting in Step1, you can apply it back when you done
You can knock this out pretty quickly taking advantage of a how Font returns the Color for a set of characters that do not have the same color: it returns Null! Knowing this, you can iterate through the characters 2 at a time and find the first spot where it throws Null. You now know that the color shift is there and can spit out the pieces using Mid.
Code makes use of this behavior and IsNull to iterate through a fixed Range. Define the Range however you want to get the cells. By default it spits them out in the neighboring two columns with Offset.
Sub FindChangeInColor()
Dim rng_cell As Range
Dim i As Integer
For Each rng_cell In Range("B2:B4")
For i = 1 To Len(rng_cell.Text) - 1
If IsNull(rng_cell.Characters(i, 2).Font.Color) Then
rng_cell.Offset(0, 1) = Mid(rng_cell, 1, i)
rng_cell.Offset(0, 2) = Mid(rng_cell, i + 1)
End If
Next
Next
End Sub
Picture of ranges and results
The nice thing about this approach is that the actual colors involved don't matter. You also don't have to manually search for a switch, although that would have been the next step.
Also your neighboring cells will be blank if no color change was found, so it's decently robust against bad inputs.
Edit adds ability to change original string if you want that instead:
Sub FindChangeInColorAndAddChar()
Dim rng_cell As Range
Dim i As Integer
For Each rng_cell In Range("B2:B4")
For i = 1 To Len(rng_cell.Text) - 1
If IsNull(rng_cell.Characters(i, 2).Font.Color) Then
rng_cell = Mid(rng_cell, 1, i) & "|" & Mid(rng_cell, i + 1)
End If
Next
Next
End Sub
Picture of results again use same input as above.

Excel Substrings

I have two unordered sets of data here:
blah blah:2020:50::7.1:45
movie blah:blahbah, The:1914:54:
I want to extract all the data to the left of the year (aka, 1915 and 1914).
What excel formula would I use for this?
I tried this formula
=IF(ISNUMBER(SEARCH(":",A1)),MID(A1,SEARCH(":",A1),300),A1)
these were the results below:
: blahblah, The:1914:54::7
:1915:50::7.1:45:
This is because there is a colon in the movie title.
The results I need consistently are:
:1914:54::7.9:17::
:1915:50::7.1:45::
Can someone help with this?
You can use Regular Expressions, make sure you include a reference for it in your VBA editor. The following UDF will do the job.
Function ExtractNumber(cell As Range) As String
ExtractNumber = ""
Dim rex As New RegExp
rex.Pattern = "(:\d{4}:\d{2}::\d\.\d:\d{2}::\d:\d:\d:\d:\d:\d:\d)"
rex.Global = True
Dim mtch As Object, sbmtch As Object
For Each mtch In rex.Execute(cell.Value)
ExtractNumber = ExtractNumber & mtch.SubMatches(0)
Next mtch
End Function
Without VBA:
In reality you don't want to find the : You want to find either :1 or :2 since the year will either start with 1 or 2This formula should do it:
=MID(A1,MIN(IFERROR(FIND(":1",A1,1),9999),IFERROR(FIND(":2",A1),9999)),9999)
Look for a four digit string, in a certain range, bounded by colons.
For example:
=MID(A1,MIN(FIND(":" &ROW(INDIRECT("1900:2100"))&":",A1 &":" &ROW(INDIRECT("1900:2100"))&":")),99)
entered as an array formula by holding down ctrl-shift while hitting Enter would ensure years in the range 1900 to 2100. Change those values as appropriate for your data. The 99 at the end represents the longest possible string. Again, that can be increased as required.
You can use the same approach to return just the left hand part, up to the colon preceding the year:
=LEFT(A1,-1+MIN(FIND(":" &ROW(INDIRECT("1900:2100"))&":",A1 &":" &ROW(INDIRECT("1900:2100"))&":")))
Here is a screen shot, showing the original data in B1:B2, with the results of the first part in B4:B5, and the formula for B4 showing in the formula bar.
The results for the 2nd part are in B7:B9

Deleting variable number of leading characters from a variable-length string

If I am having G4ED7883666 and I want the output to be 7883666
and I have to apply this on a range of cells and they are not the same length and the only common thing is that I have to delete anything before the number that lies before the alphabet?
This formula finds the last number in a string, that is, all digits to the right of the last alpha character in the string.
=RIGHT(A1,MATCH(99,IFERROR(1*MID(A1,LEN(A1)+1-ROW($1:$25),1),99),0)-1)
Note that this is an array formula and must be entered with the Control-Shift-Enter keyboard combination.
How the formula works
Let's assume that the target string is fairly simple: "G4E78"
Working outward from the middle of the formula, the first thing to do is create an array with the elements 1 through 25. (Although this might seem to limit the formula to strings with no more than 25 characters, it actually places a limit of 25 digits on the size of the number that may be extracted by the formula.
ROW($1:$25) = {1;2;3;4;5;6;7; etc.}
Subtracting from this array the value of (1 + the length of the target string) produces a new array, the elements of which count down from the length of string. The first five elements will correspond to the position of the characters of the string - in reverse order!
LEN(A1)+1-ROW($1:$25) = {5;4;3;2;1;0;-1;-2;-3;-4; etc.}
The MID function then creates a new array that reverses the order of the characters of the string.
For example, the first element of the new array is the result of MID(A1, 5, 1), the second of MID(A1, 4, 1) and so on. The #VALUE! errors reflect the fact that MID cannot evaluate 0 or negative values as the position of a string, e.g., MID(A1,0,1) = #VALUE!.
MID(A1,LEN(A1)+1-ROW($1:$25),1) = {"8";"7";"E";"4";"G";#VALUE!;#VALUE!; etc.}
Multiplying the elements of the array by 1 turns the character elements of that array to #VALUE! errors as well.
=1*MID(A1,LEN(A1)+1-ROW($1:$25),1) = {"8";"7";#VALUE!;"4";#VALUE!;#VALUE!;#VALUE!; etc.}
And the IFERROR function turns the #VALUES into 99, which is just an arbitrary number greater than the value of a single digit.
IFERROR(1*MID(A1,LEN(A1)+1-ROW($1:$25),1),99) = {8;7;99;4;99;99;99; etc.}
Matching on the 99 gives the position of the first non-digit character counting from the right end of the string. In this case, "E" is the first non-digit in the reversed string "87E4G", at position 3. This is equivalent to saying that the number we are looking for at the end of the string, plus the "E", is 3 characters long.
MATCH(99,IFERROR(1*MID(A1,LEN(A1)+1-ROW($1:$25),1),99),0) = 3
So, for the final step, we take 3 - 1 (for the "E) characters from the right of string.
RIGHT(A1,MATCH(99,IFERROR(1*MID(A1,LEN(A1)+1-ROW($1:$25),1),99),0)-1) = "78"
One more submission for you to consider. This VBA function will get the right most digits before the first non-numeric character
Public Function GetRightNumbers(str As String)
Dim i As Integer
For i = Len(str) To 0 Step -1
If Not IsNumeric(Mid(str, i, 1)) Then
Exit For
End If
Next i
GetRightNumbers = Mid(str, i + 1)
End Function
You can write some VBA to format the data (just starting at the end and working back until you hit a non-number.)
Or you could (if you're happy to get an addin like Excelicious) then you can use regular expressions to format the text via a formula. An expression like [0-9]+$ would return all the numbers at the end of a string IIRC.
NOTE: This uses the regex pattern in James Snell's answer, so please upvote his answer if you find this useful.
Your best bet is to use a regular expression. You need to set a reference to VBScript Regular Expressions for this to work. Tools --> References...
Now you can use regex in your VBA.
This will find the numbers at the end of each cell. I am placing the result next to the original so that you can verify it is working the way you want. You can modify it to replace the cell as soon as you feel comfortable with it. The code works regardless of the length of the string you are evaluating, and will skip the cell if it doesn't find a match.
Sub GetTrailingNumbers()
Dim ws As Worksheet
Dim rng As Range
Dim cell As Range
Dim result As Object, results As Object
Dim regEx As New VBScript_RegExp_55.RegExp
Set ws = ThisWorkbook.Sheets("Sheet1")
' range is hard-coded here, but you can define
' it programatically based on the shape of your data
Set rng = ws.Range("A1:A3")
' pattern from James Snell's answer
regEx.Pattern = "[0-9]+$"
For Each cell In rng
If regEx.Test(cell.Value) Then
Set results = regEx.Execute(cell.Value)
For Each result In results
cell.Offset(, 1).Value = result.Value
Next result
End If
Next cell
End Sub
Takes the first 4 digits from the right of num:
num1=Right(num,4)
Takes the first 5 digits from the left of num:
num1=Left(num,5)
First takes the first ten digits from the left then takes the first four digits from the right:
num1=Right(Left(num, 10),4)
In your case:
num=G4ED7883666
num1=Right(num,7)

Resources