Related
I have an array which contains customer's names as arrNama variable
I use a code to filter as I type which I've found in the internet (I am sorry I don't remember the link), something like this :
Sub cbNama_Populate(Optional fltr As String)
cbNama.List = Filter(arrNama, fltr, , vbTextCompare)
End Sub
Private Sub cbNama_KeyUp(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
Call cbNama_Populate(cbNama.Text)
If cbNama.ListCount = 1 Then cbNama.ListIndex = 0 Else cbNama.DropDown
End Sub
The If cbNama.ListCount = 1 Then cbNama.ListIndex = 0 Else cbNama.DropDown line is my modification, the original I found in the internet is just cbNama.DropDown.
I modified that line, because I thought with that IF conditon, it won't show the drop-down list if the list count of the combo box is only one. Yet it still show the drop-down list with that one item only, just like as if in the original code which has no IF condition.
Below is the example of what I mean :
At the time the combobox has only one item, the cbNama.ListIndex = 0 trigger the cbNama_Click sub. But the combobox still show the drop-down list, highlighted with blue on that one item.
My question:
How to prevent it showing the drop-down list when there is only one item?
Any kind of response would be greatly appreciated.
Thank you in advanced.
For the time being, I use cbNama.Enabled = False, this prevent the dropdown shows if there is one item only.
In Excel 2007, how do I add a description and parameter hints to a user-defined function? When I start typing a function invocation for a built-in function, Excel shows a description and parameter list--a tooltip. I'd like to do the same for the functions I define.
Not just for the formula insert wizard, but in the formula box, so if I key "=myFun(", at the "(" the tooltip pops up just like it does for "=average("
There's no help in VBA Help, none on MSDN and none on any of the Excel and VBA dedicated forums I can find, so this is clearly a long shot.
Not a tooltip solution but an adequate workaround:
Start typing the UDF =MyUDF( then press CTRL + Shift + A and your function parameters will be displayed. So long as those parameters have meaningful names you at-least have a viable prompt
For example, this:
=MyUDF( + CTRL + Shift + A
Turns into this:
=MyUDF(sPath, sFileName)
Professional Excel Development by
Stephen Bullen describes how to
register UDFs, which allows a
description to appear in the Function
Arguments dialog:
Function IFERROR(ByRef ToEvaluate As Variant, ByRef Default As Variant) As Variant
If IsError(ToEvaluate) Then
IFERROR = Default
Else
IFERROR = ToEvaluate
End If
End Function
Sub RegisterUDF()
Dim s As String
s = "Provides a shortcut replacement for the common worksheet construct" & vbLf _
& "IF(ISERROR(<expression>), <default>, <expression>)"
Application.MacroOptions macro:="IFERROR", Description:=s, Category:=9
End Sub
Sub UnregisterUDF()
Application.MacroOptions Macro:="IFERROR", Description:=Empty, Category:=Empty
End Sub
From: http://www.ozgrid.com/forum/showthread.php?t=78123&page=1
To show the Function Arguments dialog, type the function name and press CtrlA. Alternatively, click the "fx" symbol in the formula bar:
I know you've accepted an answer for this, but there's now a solution that lets you get an intellisense style completion box pop up like for the other excel functions, via an Excel-DNA add in, or by registering an intellisense server inside your own add in. See here.
Now, i prefer the C# way of doing it - it's much simpler, as inside Excel-DNA, any class that implements IExcelAddin is picked up by the addin framework and has AutoOpen() and AutoClose() run when you open/close the add in. So you just need this:
namespace MyNameSpace {
public class Intellisense : IExcelAddIn {
public void AutoClose() {
}
public void AutoOpen() {
IntelliSenseServer.Register();
}
}
}
and then (and this is just taken from the github page), you just need to use the ExcelDNA annotations on your functions:
[ExcelFunction(Description = "A useful test function that adds two numbers, and returns the sum.")]
public static double AddThem(
[ExcelArgument(Name = "Augend", Description = "is the first number, to which will be added")]
double v1,
[ExcelArgument(Name = "Addend", Description = "is the second number that will be added")]
double v2)
{
return v1 + v2;
}
which are annotated using the ExcelDNA annotations, the intellisense server will pick up the argument names and descriptions.
There are examples for using it with just VBA too, but i'm not too into my VBA, so i don't use those parts.
Also you can use, this Macro to assign Descriptions to arguments and the UDF:
Private Sub RegisterMyFunction()
Application.MacroOptions _
Macro:="SampleFunction", _ '' Your UDF name
Description:="calculates a result based on provided inputs", _
Category:="My UDF Category", _ '' Or use numbers, a list in the link below
ArgumentDescriptions:=Array( _ '' One by each argument
"is the first argument. tell the user what it does", _
"is the second argument. tell the user what it does")
End Sub
Credits to Kendall and the original post here.
For the UDF Categories
I just create a "help" version of the function. Shows up right below the function in autocomplete - the user can select it instead in an adjacent cell for instructions.
Public Function Foo(param1 as range, param2 as string) As String
Foo = "Hello world"
End Function
Public Function Foo_Help() as String
Foo_Help = "The Foo function was designed to return the Foo value for a specified range a cells given a specified constant." & CHR(10) & "Parameters:" & CHR(10)
& " param1 as Range : Specifies the range of cells the Foo function should operate on." & CHR(10)
&" param2 as String : Specifies the constant the function should use to calculate Foo"
&" contact the Foo master at master#foo.com for more information."
END FUNCTION
The carriage returns improve readability with wordwrap on. 2 birds with one stone, now the function has some documentation.
#will's method is the best. Just add few lines about the details for the people didn't use ExcelDNA before like me.
Download Excel-DNA IntelliSense from https://github.com/Excel-DNA/IntelliSense/releases
There are two version, one is for 64, check your Excel version. For my case, I'm using 64 version.
Open Excel/Developer/Add-Ins/Browse and select ExcelDna.IntelliSense64.xll.
Insert a new sheet, change name to "IntelliSense", add function description, as https://github.com/Excel-DNA/IntelliSense/wiki/Getting-Started
Then enjoy! :)
Unfortunately there is no way to add Tooltips for UDF Arguments.
To extend Remou's reply you can find a fuller but more complex approach to descriptions for the Function Wizard at
http://www.jkp-ads.com/Articles/RegisterUDF00.asp
I tried #ScottK's approach, first as a side feature of my functional UDF, then as a standalone _Help suffix version when I ran into trouble (see below). In hindsight, the latter approach is better anyway--more obvious to a user attentive enough to see a tool tip, and it doesn't clutter up the functional code.
I figured if an inattentive user just typed the function name and closed the parentheses while he thought it over, help would appear and he would be on his way. But dumping a bunch of text into a single cell that I cannot format didn't seem like a good idea. Instead, When the function is entered in a cell with no arguments i.e.
= interpolateLinear()
or
= interpolateLinear_Help()
a msgBox opens with the help text. A msgBox is limited to ~1000 characters, maybe it's 1024. But that's enough (barely 8^/) for my overly tricked out interpolation function. If it's not, you can always open a user form and go to town.
The first time the message box opened, it looked like success. But there are a couple of problems. First of course, the user has to know to enter the function with no arguments (+1 for the _Help suffix UDF).
The big problem is, the msgBox reopens several times in succession, spontaneously while working in unrelated parts of the workbook. Needless to say, it's very annoying. Sometimes it goes on until I get a circular reference warning. Go figure. If a UDF could change the cell formula, I would have done that to shut it up.
I don't know why Excel feels the need recalculate the formula over and over; neither the _Help standalone, nor the full up version (in help mode) has precedents or dependents. There's not an application.volatile statement anywhere. Of course the function returns a value to the calling cell. Maybe that triggers the recalc? But that's what UDFs do. I don't think you can not return a value.
Since you can't modify a worksheet formula from a UDF, I tried to return a specific string --a value --to the calling cell (the only one you can change the value of from a UDF), figuring I would inspect the cell value using application.caller on the next cycle, spot my string, and know not to re-display the help message. Seemed like a good idea at the time--didn't work. Maybe I did something stupid in my sleep-deprived state. I still like the idea. I'll update this when (if) I fix the problem. My quick fix was to add a line on the help box: "Seek help only in an emergency. Delete the offending formula to end the misery.
In the meantime, I tried the Application.MacroOptions approach. Pretty easy, and it looks professional. Just one problem to work out. I'll post a separate answer on that approach later.
A lot of dancing around the answer. You can add the UDF context help, but you have to export the Module and edit the contents in a text editor, then re-import it to VBA. Here's the example from Chip Pearson: Adding Code Attributes
I am creating an Excel Macro-Enabled Workbook for both Windows & Mac. One platform on the Mac I want it to run on is Excel 2011.
My workbook uses a custom Ribbon tab. Sometimes, depending on what the user does, I want the text of the ribbon buttons to change. So I have code that does this.
I know that a custom Ribbon tab is not possible in Excel 2011. That is okay. However, there is a line in my code that is giving me a compile error on that version of Excel. I thought I had it set that it would not compile the code if running on this version of Excel, but it doesn't seem to be working.
I am defining a variable of type IRibbonUI for use inside a standard module. (The module is Module3, and it is dedicated to code having to do with the Ribbon.) I wrap the variable definition code (along with the rest of the code in this module) in an #IF statement, like so:
#If Not Mac or MAC_OFFICE_VERSION >=15 Then
Dim ribbonUI As IRibbonUI
... rest of the code in Module3 ...
#End If
This means it should not compile at run-time on Excel 2011.
When the workbook opens, I do not get any errors. However, when I am running a sub (let's call it "UpdateOptions", and it is in Module1) that calls a sub that changes the Ribbon (let's call that one "ChangeRibbon", which is in Module3*), I get a compile error on the ribbonUI line: User-defined type not defined
I don't understand why, because as far as I understand, the code in that module shouldn't be compiling at run-time.
*ChangeRibbon should never actually be run on Excel 2011. I have an IF statement that makes sure it is not, like so:
Sub UpdateOptions()
... some code ...
#If Not Mac or MAC_OFFICE_VERSION >=15 Then
Module3.ChangeRibbon
End If
... some other code ...
End Sub
When I step through the code, the error happens when UpdateOptions is first called by another sub. The step-through highlights the name of the sub as the line that is causing the error:
Sub UpdateOptions()
Does anyone know why this is happening? It doesn't make any sense to me.
I'll post it as an answer since it won't fit into the comment section.
It seems that you enter your code, even thought it should not. The easiest explanation is, that your if statement is not evaluated properly. You should check the values of Mac and MAC_OFFICE_VERSION, this should already show you what went wrong. Another reason could be that you made a wrong assumption about how VBA evaluates logic clauses: https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/operator-precedence
If you split/nest the the If-Block it is easier to see which evaluation goes wrong:
Public Sub testVer()
#If Not Mac Then
Debug.Print "Not a Mac"
#Else
#If MAC_OFFICE_VERSION >= 15 Then
Debug.Print "Mac Version equal or above 15: ", MAC_OFFICE_VERSION
#Else
Debug.Print "Mac Version below 15: ", MAC_OFFICE_VERSION
#End If
#End If
End Sub
Here is a small example to see how your if clause gets evaluated:
In VBA the clause Not A Or B is the same as (Not A) Or B, so maybe you just mixed up logic.
Sub testOrNot()
printNotAOrB True, True
printNotAOrB True, False
printNotAOrB False, True
printNotAOrB False, False
End Sub
Private Sub printNotAOrB(A As Boolean, B As Boolean)
Debug.Print "A = " & A, "B = " & B
Debug.Print "Not A Or B :", Not A Or B
Debug.Print "Not (A Or B):", Not (A Or B)
Debug.Print "(Not A) Or B:", (Not A) Or B
Debug.Print
End Sub
I had the thought of if I could possibly "fake out" Excel 2011 into thinking I had created a custom data type for IRibbonUI (and, as it turned out, I had to do it for another type, too) and that worked. In my module dealing with all my Ribbon code, I put this at the top:
#If Mac And MAC_OFFICE_VERSION < 15 Then
Type IRibbonUI
ribbontype As String
End Type
Type IRibbonControl
ribboncontrol As String
End Type
#End If
I no longer receive the compile error.
In regards to L8n's answer, I don't believe the logic of the IF statement was a problem. I had also tried calling on a Function I created long ago to test if the version of Excel was Excel 2011 for Mac. So my IF statement started like this:
#IF ExcelForMac2011 = False Then
I know my function works properly, because I call it many other times in my workbook, and it has always worked correctly. So I don't think it was a logic problem in the IF statement. I think this was a bug in Excel 2011. Unfortunately, it has MANY, MANY bugs.
Alright this is my first post on here so be gentle.
I have a Userform with a listbox containing x amount of values. I have a separate module that calls this Userform and then performs some procedures based on the values chosen in the listbox. I have the following:
Dim lb as ListBox
lb = Userform1.Listbox1
For x = 0 to lb.ListCount - 1 Then
'Do the stuff I need it to
Next x
The problem I am getting is that lb returns a "Nothing".
I am sure this is something simple but I can't figure it out. Appreciate the help.
Are you closing your userform before you are running your code, as if this the case then your listbox is effectively non existent in memory and you listcount will not return anything. You can also remove the line where you are assigning your lb variable and directly get the listcount of the listbox like the code below. Also if you dont want the userform to show when you code is doing the loop just hide the userform run the loop and then unload the userform after that. This way you list box is still in memory long enough for the loop to get the correct value
for x = 1 to userform.listbox.listcount
'' Do you stuff
next x
I tried the code and it gave me the correct value. If there is anything else let me know and hope this helps :)
Declare the module just like that.
Sub listboxpopulate(listb as string,usf as userform)
for i=0 Usf.controls(listb).listcount-1
Do ur stuff
Next
End sub
This will help
In Excel 2007, how do I add a description and parameter hints to a user-defined function? When I start typing a function invocation for a built-in function, Excel shows a description and parameter list--a tooltip. I'd like to do the same for the functions I define.
Not just for the formula insert wizard, but in the formula box, so if I key "=myFun(", at the "(" the tooltip pops up just like it does for "=average("
There's no help in VBA Help, none on MSDN and none on any of the Excel and VBA dedicated forums I can find, so this is clearly a long shot.
Not a tooltip solution but an adequate workaround:
Start typing the UDF =MyUDF( then press CTRL + Shift + A and your function parameters will be displayed. So long as those parameters have meaningful names you at-least have a viable prompt
For example, this:
=MyUDF( + CTRL + Shift + A
Turns into this:
=MyUDF(sPath, sFileName)
Professional Excel Development by
Stephen Bullen describes how to
register UDFs, which allows a
description to appear in the Function
Arguments dialog:
Function IFERROR(ByRef ToEvaluate As Variant, ByRef Default As Variant) As Variant
If IsError(ToEvaluate) Then
IFERROR = Default
Else
IFERROR = ToEvaluate
End If
End Function
Sub RegisterUDF()
Dim s As String
s = "Provides a shortcut replacement for the common worksheet construct" & vbLf _
& "IF(ISERROR(<expression>), <default>, <expression>)"
Application.MacroOptions macro:="IFERROR", Description:=s, Category:=9
End Sub
Sub UnregisterUDF()
Application.MacroOptions Macro:="IFERROR", Description:=Empty, Category:=Empty
End Sub
From: http://www.ozgrid.com/forum/showthread.php?t=78123&page=1
To show the Function Arguments dialog, type the function name and press CtrlA. Alternatively, click the "fx" symbol in the formula bar:
I know you've accepted an answer for this, but there's now a solution that lets you get an intellisense style completion box pop up like for the other excel functions, via an Excel-DNA add in, or by registering an intellisense server inside your own add in. See here.
Now, i prefer the C# way of doing it - it's much simpler, as inside Excel-DNA, any class that implements IExcelAddin is picked up by the addin framework and has AutoOpen() and AutoClose() run when you open/close the add in. So you just need this:
namespace MyNameSpace {
public class Intellisense : IExcelAddIn {
public void AutoClose() {
}
public void AutoOpen() {
IntelliSenseServer.Register();
}
}
}
and then (and this is just taken from the github page), you just need to use the ExcelDNA annotations on your functions:
[ExcelFunction(Description = "A useful test function that adds two numbers, and returns the sum.")]
public static double AddThem(
[ExcelArgument(Name = "Augend", Description = "is the first number, to which will be added")]
double v1,
[ExcelArgument(Name = "Addend", Description = "is the second number that will be added")]
double v2)
{
return v1 + v2;
}
which are annotated using the ExcelDNA annotations, the intellisense server will pick up the argument names and descriptions.
There are examples for using it with just VBA too, but i'm not too into my VBA, so i don't use those parts.
Also you can use, this Macro to assign Descriptions to arguments and the UDF:
Private Sub RegisterMyFunction()
Application.MacroOptions _
Macro:="SampleFunction", _ '' Your UDF name
Description:="calculates a result based on provided inputs", _
Category:="My UDF Category", _ '' Or use numbers, a list in the link below
ArgumentDescriptions:=Array( _ '' One by each argument
"is the first argument. tell the user what it does", _
"is the second argument. tell the user what it does")
End Sub
Credits to Kendall and the original post here.
For the UDF Categories
I just create a "help" version of the function. Shows up right below the function in autocomplete - the user can select it instead in an adjacent cell for instructions.
Public Function Foo(param1 as range, param2 as string) As String
Foo = "Hello world"
End Function
Public Function Foo_Help() as String
Foo_Help = "The Foo function was designed to return the Foo value for a specified range a cells given a specified constant." & CHR(10) & "Parameters:" & CHR(10)
& " param1 as Range : Specifies the range of cells the Foo function should operate on." & CHR(10)
&" param2 as String : Specifies the constant the function should use to calculate Foo"
&" contact the Foo master at master#foo.com for more information."
END FUNCTION
The carriage returns improve readability with wordwrap on. 2 birds with one stone, now the function has some documentation.
#will's method is the best. Just add few lines about the details for the people didn't use ExcelDNA before like me.
Download Excel-DNA IntelliSense from https://github.com/Excel-DNA/IntelliSense/releases
There are two version, one is for 64, check your Excel version. For my case, I'm using 64 version.
Open Excel/Developer/Add-Ins/Browse and select ExcelDna.IntelliSense64.xll.
Insert a new sheet, change name to "IntelliSense", add function description, as https://github.com/Excel-DNA/IntelliSense/wiki/Getting-Started
Then enjoy! :)
Unfortunately there is no way to add Tooltips for UDF Arguments.
To extend Remou's reply you can find a fuller but more complex approach to descriptions for the Function Wizard at
http://www.jkp-ads.com/Articles/RegisterUDF00.asp
I tried #ScottK's approach, first as a side feature of my functional UDF, then as a standalone _Help suffix version when I ran into trouble (see below). In hindsight, the latter approach is better anyway--more obvious to a user attentive enough to see a tool tip, and it doesn't clutter up the functional code.
I figured if an inattentive user just typed the function name and closed the parentheses while he thought it over, help would appear and he would be on his way. But dumping a bunch of text into a single cell that I cannot format didn't seem like a good idea. Instead, When the function is entered in a cell with no arguments i.e.
= interpolateLinear()
or
= interpolateLinear_Help()
a msgBox opens with the help text. A msgBox is limited to ~1000 characters, maybe it's 1024. But that's enough (barely 8^/) for my overly tricked out interpolation function. If it's not, you can always open a user form and go to town.
The first time the message box opened, it looked like success. But there are a couple of problems. First of course, the user has to know to enter the function with no arguments (+1 for the _Help suffix UDF).
The big problem is, the msgBox reopens several times in succession, spontaneously while working in unrelated parts of the workbook. Needless to say, it's very annoying. Sometimes it goes on until I get a circular reference warning. Go figure. If a UDF could change the cell formula, I would have done that to shut it up.
I don't know why Excel feels the need recalculate the formula over and over; neither the _Help standalone, nor the full up version (in help mode) has precedents or dependents. There's not an application.volatile statement anywhere. Of course the function returns a value to the calling cell. Maybe that triggers the recalc? But that's what UDFs do. I don't think you can not return a value.
Since you can't modify a worksheet formula from a UDF, I tried to return a specific string --a value --to the calling cell (the only one you can change the value of from a UDF), figuring I would inspect the cell value using application.caller on the next cycle, spot my string, and know not to re-display the help message. Seemed like a good idea at the time--didn't work. Maybe I did something stupid in my sleep-deprived state. I still like the idea. I'll update this when (if) I fix the problem. My quick fix was to add a line on the help box: "Seek help only in an emergency. Delete the offending formula to end the misery.
In the meantime, I tried the Application.MacroOptions approach. Pretty easy, and it looks professional. Just one problem to work out. I'll post a separate answer on that approach later.
A lot of dancing around the answer. You can add the UDF context help, but you have to export the Module and edit the contents in a text editor, then re-import it to VBA. Here's the example from Chip Pearson: Adding Code Attributes