Excel UDF not appearing in drop down menu - excel

I wrote a User Defined Fucntion in Excel. It works great with no issues. I even wrote a description for it under the object properties menu.
The problem is, my UDF never shows up in the Excel drop down menu that appears when I start to type a function. I want the user to be able to see my UDF, named removeNumbers, when they go into a cell and start to type out a function.
I would also like them to be able to see the description which I wrote, just like the standard Excel functions.
And finally, is there a way that I can provide a description for each argument which my function takes as input?
Here is the actual code, although I don't think it will be necessary to answer my questions.
Function removeNumbers(sInput As String, sChoice As Boolean) As String
Dim sSpecialChars As String
Dim i As Long
If (sChoice = True) Then 'if true is selected, will remove all number including 0
sSpecialChars = "0123456789" 'This is your list of characters to be removed
For i = 1 To Len(sSpecialChars)
sInput = Replace$(sInput, Mid$(sSpecialChars, i, 1), "")
Next
End If
If (sChoice = False) Then 'if false is selected, will remove all numbers excluding zero
sSpecialChars = "123456789" 'This is your list of characters to be removed
For i = 1 To Len(sSpecialChars)
sInput = Replace$(sInput, Mid$(sSpecialChars, i, 1), "")
Next
End If
removeNumbers = sInput
End Function

To make the function appear in the drop-down you must place it in a standard module rather than the worksheet code area.

Another poster has already covered the need for the code to be in a standard module. With regards the argument descriptions, you should look at the MacroOptions code in this answer - although it only works in Excel 2010 or later.
For Excel 2007 and earlier, the only solution I have seen is in an article by JK Pieterse. This involves using the ExecuteExcel4Macro and looks a bit complicated.

Related

Filter phone numbers from open text field - Power BI, excel, VBA

I have a text field in a table where I need to substitute phone numbers where applicable.
For example the text field could have:
Call me on 08588812885 immediately
Call me on 07525812845
I need assistance please contact me
Good service
Sometimes a phone number will be in the text but not always and the phone number entered will always be different.
Is there a measure to use to replace the phone numbers with no text.
Ideally the solution would be Power BI, but can also be done in the raw data using excel or VBA
Regular expression in VBA (excel) or Python (Power BI) is a straightforward solution.
I have never used PowerBI with Python before but manage to make following python script.
In PowerBI transformation steps I created a new column that would copy [message] columns and named it [noPhoneNumber], then next step ran this python script
import re
def removePhone(x):
return re.sub('\d{10,11}', "**number removed**", x)
length = len(dataset["noPhoneNumber"])
for iRow in range(length):
dataset["noPhoneNumber"][iRow] = removePhone(dataset["noPhoneNumber"][iRow])
so column "noPhoneNumber"
Call me on 08588812885 immediately
Call me on 07525812845
I need assistance please contact me
Good service
becomes
Call me on **number removed** immediately
Call me on **number removed**
I need assistance please contact me
Good service
In VBA Preferable create UDF (user defined function) and don't create a subroutine, that would be too error prone for this kind of problem.
[Added]
If you need to make a Excel based solution, you can create a UDF function like so:
(remember early binding to import of VBScript_RegExp_55.RegExp in excel)
Function removePhoneNumber(text As String, Optional replacement As String = "**number removed**") As String
Dim regex As New RegExp
regex.Pattern = "\d{10,11}"
removePhoneNumber = regex.Replace(text, replacement)
End Function
...and then use excel function like so:
=removePhoneNumber(A2),
=removePhoneNumber(A3)
and so on...
A simple VBA function alternative
Function removePhone(s As String) As String
Const DELIM As String = " "
Dim i As Long, tokens As Variant
tokens = Split(s, DELIM)
For i = LBound(tokens) To UBound(tokens)
If IsNumeric(tokens(i)) Then
tokens(i) = "*Removed*" ' << change to your needs
Exit For ' assuming a single phone number per string
End If
Next
removePhone = Join(tokens, DELIM)
End Function
You can do this in Power Query. Create a custom column with this below code. I have considered the column name is Comments but please adjust this with your column name.
if Text.Length(Text.Select([comments], {"0".."9"})) = 11
then
Text.Replace(
[comments],
Text.Select([comments], {"0".."9"}),
""
)
else [comments]
Here is the output below. You can also replace phone numbers with other text like #### to make is anonymous.
NOTE
This will only work if there are only 1 number in the string with length 11 (You can adjust the length in code as per requirement).
This will Not work if there are more than one Numbers in the string.
If there are 1 number in the string but length not equal 11, this will keep the whole string as original.

VBA VLookup Method not working for both numbers and strings

I have a workbook full of product codes and names. Contained within a form are various text boxes where a user can enter a code and its corresponding label will update with the name found in the workbook. Each text box runs the following sub when changed
Private Sub FindItem(x As Long)
Dim Name As Variant
Name = Application.VLookup(AddStockForm.Controls("Code" & x).Text, Sheet1.Range("B:C"), 2, False)
If IsError(Name) Then
AddStockForm.Controls("Name" & x).Caption = "Unknown Code"
Else
AddStockForm.Controls("Name" & x).Caption = Name
End If
End Sub
The sub takes the user input in the target box (e.g. Code1) and finds the corresponding name and writes it to the label (e.g. Name1). HOWEVER, the product codes are either strings, alphanumeric and plain text, OR numbers. For stupid reasons beyond my control, some codes have to be numbers, others have to contain letters.
This code works PERFECTLY for any code with a character in it (MYCODE or 500A) but not numbers, it writes "Unknown code" for any number, and they are in the lookup range. I have searched around stackoverflow and answers suggest declaring as variants, I've done this, even by assigning Controls().Text as a variant before using it in VLookup. I suspect the problem is
AddStockForm.Controls("Code" & x).Text
is a string. But I cannot convert to an INT because the user input might be a number or string.
Any ideas?
One thing you can do is to create a separate function which has the separate parts you want to do. In this instance, we are checking the input value first. If this is numerical we want to try doing the lookup as a string, then as a number if that fails. If the input value is not numerical we can go ahead and do the lookup as normal.
Public Function lookupStringOrInt(inputValue As Variant, tableArray As Range, colIndexNum As Long, Optional rangeLookup As Boolean) As Variant
If IsNumeric(inputValue) Then
lookupStringOrInt = Application.IfError(Application.VLookup(inputValue & "", tableArray, colIndexNum, rangeLookup), Application.VLookup(inputValue * 1, tableArray, colIndexNum, rangeLookup))
Else
lookupStringOrInt = Application.VLookup(inputValue, tableArray, colIndexNum, rangeLookup)
End If
End Function
You can then call this in your code with the line
name = lookupStringOrInt(AddStockForm.Controls("Code" & x) & "", Sheet1.Range("B:C"), 2, False)
If the value you are looking for does not exist, the function will return 'Error 2042'. You can choose to handle this however you like.

How do I extract a series of numbers along with a single letter followed by another series of numbers?

The problem that I'm facing is that I have an entire column that has text separated by _ that contains pixel size that I want to be able to extract but currently can't. For example:
A
Example_Number_320x50_fifty_five
Example_Number_One_300x250_hundred
Example_Number_two_fifty_728x49
I have tried using Substitute function to grab the numbers which works but only grabs the numbers when I need something like: 320x50 instead I'm getting 0, as I'm not sure how to exactly extract something like this. If it was consistent I could easily do LEFT or RIGHT formula's to grab it but as you can see the data varies.
The result that I'm looking for is something along the lines of:
A | B
Example_Number_320x50_fifty_five | 320x50
Example_Number_One_300x250_hundred | 300x200
Example_Number_two_fifty_728x49 | 728x49
Any help would be much appreciated! If any further clarification is needed please let me know and I'll try to explain as best as I can!
-Maykid
I would probably use a Regular Expressions UDF to accomplish this.
First, open up the VBE by pressing Alt + F11.
Right-Click on VBAProject > Insert > Module
Then you can paste the following code in your module:
Option Explicit
Public Function getPixelDim(RawTextValue As String) As String
With CreateObject("VBScript.RegExp")
.Pattern = "\d+x\d+"
If .Test(RawTextValue) Then
getPixelDim = .Execute(RawTextValue)(0)
End If
End With
End Function
Back to your worksheet, you would use the following formula:
=getPixelDim(A1)
Looking at the pattern \d+x\d+, an escaped d (\d) refers to any digit, a + means one or more of \d, and the x is just a literal letter x. This is the pattern you want to capture as your function's return value.
Gosh, K Davis was just so fast! Here's an alternate method with similar concept.
Create a module and create a user defined function like so.
Public Function GetPixels(mycell As Range) As String
Dim Splitter As Variant
Dim ReturnValue As String
Splitter = Split(mycell.Text, "_")
For i = 0 To UBound(Splitter)
If IsNumeric(Mid(Splitter(i), 1, 1)) Then
ReturnValue = Splitter(i)
Exit For
End If
Next
GetPixels = ReturnValue
End Function
In your excel sheet, type in B1 the formula =GetPixels(A1) and you will get 320x50.
How do you create a user defined function?
Developer tab
Use this URL to add Developer tab if you don't have it: https://www.addintools.com/documents/excel/how-to-add-developer-tab.html
Click on the highlighted areas to get to Visual Basic for Applications (VBA) window.
Create module
Click Insert > Module and then type in the code.
Use the user defined function
Note how the user defined function is called.

VBA Excel : Populate TextBox with specific string of text when Option Button is selected

I developed a Form in Excel (2016) and I am trying (with VBA) to configure its behavior so that if the user selects a particular option button, two additional things happen:
A checkbox further down on the form is automatically checked.
A text box further down on the form automatically displays a set string of text.
More specifically, if the user selects OptionButtonABC, then ...
CheckBoxNone should become checked
TextBoxCompanyName (which does not display any text by default) should now display the string: 'ABC'.
I initially created a subroutine that just targeted condition 1, and everything worked fine. However, when I try to integrate the code required to handle condition 2, things start to unravel.
Below, you will see the code in its most current state. I have a Private Sub that initiates upon the Click event and then immediately defines a variable as a string. I then set up an if/then statement that specifies what should happen IF OptionButtonABC is true. Namely, CheckBoxNone should be selected (this works fine) AND TextBoxCompanyName should now display the string 'ABC'.
Private Sub OptionButtonABC_Click()
Dim Variable_ABC As String
Variable_ABC = ABC
If Me.OptionButtonABC.Value = True Then
Me.CheckBoxNone = True And Me.TextBoxCompanyName.Text = Variable_ABC
End If
End Sub
The desired behavior should (theoretically) be pretty easy to achieve, but my experience with VBA is still pretty limited, so I am reaching out to the community for a bit of advice. As I mentioned above, the code above works for the first condition. However, I am still unable to get the string of text ('ABC') to show up in the text box.
Thanks in advance for any advice you may offer.
Private Sub OptionButtonABC_Click()
Dim Variable_ABC As String
Variable_ABC = "ABC" 'String Values uses double quotes
If Me.OptionButtonABC.Value = True Then
Me.CheckBoxNone = True
Me.TextBoxCompanyName.Text = Variable_ABC
End If
End Sub
The operator AND must be used only in the IF statement comparison, not in what you want to do.

Please assist with writing a Macro to clean up data entries

Quick question that should be easy enough for a lot of you but I'm not well versed in VBA or code in general for that matter but I have a problem that only a Macro or piece of VBA code can resolve for me. I have to edit a large number of data entries in a spreadsheet, cell by cell.
So on to the question. Could you please show me an example or provide a complete macro for me to use to edit these cells?
The editing that I require is as follows:
I need to read each cell in the following range: B2 to Q383. A typical entry that needs to be examined and edited looks like this: 629.64\3.00\01:30
What needs to happen now is for everything to the left of the first "\" and everything to the right of the second "\" needs to be removed, including the "\", from each cell.
I've tried fiddling around with the LEFT and RIGHT commands and I can output the data that needs to be removed from the cells with something like this
=left(B11, Find("\", B11) - 1)
So what would be the delete command in a macro to target that data selection in that cell? Or how do I use a delete command with those parameters?
Thanks in advance for any advice or answers!
Not 100% sure what you're after - you say you want to remove the bits from the left and right, but the formula returns the bit on the left.
Anyway, here's 3 formula to do it:
Left: =TRIM(LEFT(B11,FIND("\",B11)-1))
Middle: =LEFT(MID(B11,FIND("\",B11)+1,LEN(B11)),FIND("\",MID(B11,FIND("\",B11)+1,LEN(B11)))-1)
Right: =MID(B11,FIND("\",SUBSTITUTE(B11,"\","~",1))+1,LEN(B11))
And three VBA functions to do it
(use these as you would formula - =leftbit(B11), or if you're looking for something other than backslashes - =leftbit(B11,"|") will find the I-bar as a divider. )
Public Function LeftBit(target As Range, Optional Divider As String = "\") As String
LeftBit = Trim(Left(target, InStr(target, Divider) - 1))
End Function
Public Function MiddleBit(target As Range, Optional Divider As String = "\") As String
Dim First As Long, Second As Long
First = InStr(target, Divider)
Second = InStr(First + 1, target, Divider)
MiddleBit = Mid(target, First + 1, Second - First - 1)
End Function
Public Function RightBit(target As Range, Optional Divider As String = "\") As String
RightBit = Right(target, Len(target) - InStrRev(target, Divider))
End Function

Resources