VBA (excel) - How do I feed UserForm Textbox to function? - vba

I have a sub that works to clear values from a userform textbox but I tried to convert it to a function so I can use it with multiple userforms.
Here's my userForm Code (the command button code)
Private Sub pdclear_Click()
Dim passform As UserForm
Set passform = NoteEntryForm1
Dim inputtext As TextBox
Set inputtext = frmBigInputBox
Call clear(passform, inputtext)
End Sub
Here is my function
Function clear(passform As UserForm, inputbox As TextBox)
passform.inputbox.Value = vbNullString
End Function
Trying to execute returns "Type missmatch" error.
I set it as a userform and a textbox. What am I doing wrong?
thank you :)

You define the function to have two parameters. Then in the function you concatenate the parameters as if one is a member of the other. That will give an error. To address the input box on the user form, use:
Function clear(passform As UserForm, inputbox As TextBox)
passform.Controls(inputbox.Name).Value = vbNullString
End Function
or even more simple:
Function clear(inputbox As TextBox)
inputbox.Value = vbNullString
End Function
(I have not been able to test this as I have no test module with forms in Excel.)

The error Type Mismatch is very clear, you're setting into a variable declared as TextBox something that, apparently, is not a TextBox.
My suggestions:
Check the type using the function TypeName(object), and make sure it's actually a TextBox:
Debug.Print TypeName(frmBigInputbox)
If the TextBox is a child of the passform, then tell this to VBA :
Set inputtext = passform.frmBigInputBox

Related

VBA How to programaticly select an item in a listbox without triggering the on click event

I am using Excel 2010, Windows 10, with VBA. I have a function which runs upon clicking an item in an ActiveX ListBox control. The issue is that if you click the list box I ask if they are sure if they want to change the selection. If you click "yes" I continue, but if you say "no" I set the selection back to what it previously was.
So the issue is that when I programmatically set the list box selection back to the previous selection my function will re-run the code that runs if a user clicks an item in the list box ...which is what I don't want.
Does anyone have a better way to stop a list box selection and change it back to the old one without causing the on list box selection event to trigger?
Function prototype for on click of the list box
lsQuestions_Click()
Code for setting the list box selection
'Prototype: setListBoxSelection(query As String, listBoxName As String) As Boolean
' Purpose: Set listbox selection based on text
Public Function setListBoxSelection(query As String, listBoxName As String) As Boolean
Dim lsBox As MSForms.listBox
Set lsBox = Workbooks(mainFile).Worksheets(entrySheet).OLEObjects(listBoxName).Object
Dim I As Integer
For I = 0 To lsBox.ListCount - 1
If lsBox.List(I) = query Then
lsBox.Selected(I) = True
setListBoxSelection = True
Exit Function
End If
Next I
setListBoxSelection = False
End Function
Please note that I think the line of code below is what is triggering my click event which is what I don't want.
lsBox.Selected(I) = True
The way I do this with my VB6 projects is to define a module-scope variable
Private blnChangingInCode As Boolean
Then, when I need to utilize it, I set it to true, call the even/sub, set it back to false.
blnChangingInCode = True
btnLogin_Click()
blnChangingInCode = False
Inside the affected subs/events I start with
If blnChangingInCode Then
Exit Sub ' or Exit Function
End if
This might not be elegant, but it works, and I don't need to do it very often.

VBA Word Macro to Allow User to Select and Copy Text Multiple Times

I am working on a VBA script with Microsoft Word that allows the user to select text that will be be copied to the clipboard so that it can exported to an Excel file. The user will make a number of selections and finally indicate he/she is done when the contents of the clipboard will be copied to a template Excel file.
There are two forms: the first (UserForm1 in the code below) queries the user for the Word filename. The filename variable is passed to the second form. The second form (frmModeLessForInput) is a modeless form. The behavior I need is that program control goes to the second form with two buttons "Continue" and "Done".
The user is allowed to navigate the document and place the cursor anywhere in the document. Then when "Continue" is pressed the form will call a subroutine (Highlight_Sentence) to copy the selected text to a "clipboard" variable. When "Done" is pressed control will be passed to called main module which will then copy the clipboard to the Excel file.
Below is the code. I have noted with comments where I am trouble with the code. One problem is the variables defined as Public in the ThisDocument module are not defined in the userforms and their subroutines.
The second problem is in the main module that the frmModelessForInput is supposed to be displayed and control is not supposed to be transferred to next statement {MsgBox "Sentences will now be copied to Excel file"....this is where I will put the code to copy the clipboard to the Excel file.} but the message appears before the frmModelessForInput form is run...thus the clipboard will be empty.
The third problem is that in frmModelessForInput form the statement str_clipboard = str_clipboard + str_clipboard_line is not working. Each time the "Continue" button is pushed str_clipboard loses it previous contents.
Any assistance in resolving these problems is appreciated. As VBA programming is a sideline for me I am still learning.
Note this an updated question Pause VBA Word macro, allow user to make a selection, and restart where it left off adding some more detail on the requirement and the sample code.
MAIN MODULE:
Option Explicit
Public str_clipboard As String
Public txt_active_document As String
Public i_how_many_sentences As Integer
Private Sub Test_master_macro()
UserForm1.Show
i_how_many_sentences = 0
Call DisplayModeless
MsgBox "Sentences will now be copied to Excel file" 'Problem: this msg displays before the frmModelessForInput is displayed
End Sub
Sub DisplayModeless()
Dim frm As frmModelessForInput
Set frm = New frmModelessForInput
With frmModelessForInput
.str_word_doc_filename = txt_active_document
.str_no_copied = "0"
.Show False
End With
Set frm = Nothing
End Sub
USERFORM1: form has field for user entering the document filename to user (str_filename) and a command button to close form (cmd_start_selecting_text)
Private Sub cmd_start_selecting_text_Click()
'User enters filename on form for use in frmModelessForInput subroutine
txt_active_document = UserForm1.str_filename 'Problem: VBA reports txt_active_document as undefined even though it is a Public variable
Unload Me
End Sub
FRMMODELESSFORINPUT: Form displays filename of Word file entered in UserForm1 and how many sentences have been copied to the clipboard
Option Explicit
Private Sub cmdContinue_Click()
Dim str_clipboard, str_clipboard_line As String
Call Highlight_Sentence(str_clipboard_line)
i_how_many_sentences = i_how_many_sentences + 1 'Problem: VBA reports i_how_many_sentences as undefined even though it is a Public variable
frmModelessForInput.str_no_copied = i_how_many_sentences 'Same Problem
str_clipboard = str_clipboard + str_clipboard_line 'Problem: each time I select a new text/sentence str_clipboard does not contain the contents of the previous selection
End Sub
Private Sub cmdDone_Click()
Me.Hide
End Sub
Private Sub UserForm_Activate()
'Position the form near the top-left of the window
'So that the user can work with the document
Me.Top = Application.ActiveWindow.Top + 15
Me.Left = Application.ActiveWindow.Left + 15
End Sub
Private Sub Highlight_Sentence(clipboard As String)
'This sub extends the selection to the entire sentence and copies the selection, the page number on which the selection is contained and the filename to the clipboard variable
Dim txt_sentence, txt_page_no As String
With Selection
' Collapse current selection.
.Collapse
' Expand selection to current sentence.
.Expand Unit:=wdSentence
End With
txt_sentence = Selection.Text
txt_page_no = Selection.Information(wdActiveEndPageNumber)
clipboard = txt_active_document & vbTab & txt_page_no & vbTab & txt_sentence & vbCrLf 'Problem: VBA reports txt_active_document as undefined even though it is a Public variable
End Sub
From what you stated you are running this from the ThisDocument Class Module and unless you fully qualify your references to those Public variables with the Class Name that is why you cannot access them from the UserForms Class Modules.
If you are going to leave your "Main Module" code in the ThisDocument Class Module then whenever you reference those Public variable you need to add ThisDocument.str_clipboard to the command.
I recommend however, to place your Main Module in a general Module such as NewModule and if you need to run it at a Document_Open event that you put a call to the Main Module and its Public variables in the Private Sub Document_Open event of the ThisDocument Class Module.
Your Msgbox is appearing at the wrong time because you are displaying a modeless user form, which means the VBA script thread continues to run after the UserForm is displayed. Move the Msgbox to the UserForm_Activate routine of the second UserForm you are displaying or move it to the Click_Done routine of the first UserForm before you Hide or Unload it.
Finally, you are not really using the Clipboard and using that term makes your code confusing in my opinion. I think you should rename it. Your code also appears to just be building one continuous string of text. Is that really what you want to do? Or, do you really mean to capture each selected text string and ultimately place each into separate cells within an Excel Worksheet? If that is the case, use an Array for the separate text strings.

How can assign macro that is in WorkSheet module and has several arguments to a command button for Insert new TableRow in protected Sheet?

I have a Command button in my Worksheet ("Sheet1"), under a Table.
My sheet is protected and I need let user add new rows.
Bellow macro was wrote for do that: (This is in a WorkSheet module)
Sub TblNewLine(Sht As String, Tbl As String, Pass as String, Filtering As Boolean, Pivot As Boolean)
if Nor Pass = vbNullString then
Dim strP as String
strP = InputBox ("Please input Password","Password")
if Not strP = Pass Then
if not strP = vbNullString Then MsgBox "Wrong Password!", vbCritical, "Error!"
Exit Sub
End If
End If
Sheets(Sht).Unprotect
Sheets(Sht).ListObjects(Tbl).ListRows.Add
Sheets(Sht).Protect AllowFiltering:=Filtering, AllowUsingPivotTables:=Pivot
End Sub 'TblNewLine
for example: arguments are:
sht:= "sheet1", Tbl:="PvtReport", Pass:="", Filtering:=True, Pivot:= True
Thus I need assign this macro to prepared command button that is under Table.
And passing arguments with pressing button.
In assign macro form, I cant find above macro in Macro names combo box.
How can I assign above macro and its related arguments to a command button?
Or is there any better solution for Insert new row to protected sheet Table?
Try something like below:
Sub Button1_Click()
Call TblNewLine("Sheet1", "PvtReport", True, True)
End Sub
Sub TblNewLine(Sht As String, Tbl As String, Filtering As Boolean, Pivot As Boolean)
Sheets(Sht).Unprotect
Sheets(Sht).ListObjects(Tbl).ListRows.Add
Sheets(Sht).Protect AllowFiltering:=Filtering, AllowUsingPivotTables:=Pivot
End Sub
EDIT :
See image for reference
With great thanks from Mrig's guidance; For more explanation I Present whats i reached, as an answer:
there is a way for passing arguments with Command button, that I read in QA Collective's Answer for a related question.
At first i encountered 'cannot run Macro' error from Microsoft Excel, but when I closed and open workbooks document, looked Macro name field in Assign Macro was changed as bellow and my subroutine called truly by passing constants with click on button.
'FileName.xlsm'!'TblNewLine "SheetName", "tblReminder","",True,False'
Please not that ' character for enclose subroutine name and arguments list string, both in twisted '.
in above example, my sub needs 5 arguments so they pass with each command button that want calling this sub.
The point about assign macro that has no arguments, and there is in Worksheet module is there are listed below of Asign Macro combo list and not in order of subroutines are in other modules.
if subroutine macros has argument, there not listed in Asign Macro and should input them in related field as above example i explained.

Get editbox value on "Return in Excel ribbon with VBA

My first question here.
I'm trying to add a custom search field in Excel ribbon. My problem with the usual research : its default range is "this worksheet" whereas I'd want the whole Workbook (or even other known workbooks).
So I created an editbox in the ribbon. I use "onChange" to validate my input and trigger my custom research sub.
But I'd prefer it to be triggered only when I press "Enter" key on my keyboard, or give focus to another ribbon button (a button "search" wich would trigger the research sub with my editbox value, and wich would be activated when pressing Return while focus is still on editbox.
My other problem is that leaving the field also triggers the sub (onChange is activated when leaving) ; it doesn't trigger the event if editbox has not been changed ; and I can't catch the "Enter pressed" action.
Are there ways to solve what I'm trying to do ?
If not, is there a way to call the native search function with "workbook" range as default range, instead of "this worksheet"?
Thank you for help.
JP
What I did in the end (I just need to scan the first column):
an editbox in the ribbon wich updates a variable whose range is my module.
a "Go" button in the ribbon, wich launches the research of the string stored in the variable.
The code I used (for sure that's simple, but may help other beginners such as me):
Private nomPatientRecherche As String
Public Sub RecherchePatient(control As IRibbonControl)
Dim feuille As Worksheet, zone As Range, cellule As Range
For Each feuille In ThisWorkbook.Worksheets
feuille.Activate
Set zone = feuille.Range("A2:A" & ActiveSheet.UsedRange.SpecialCells(xlCellTypeLastCell).Row)
For Each cellule In zone
If Not cellule.Find(nomPatientRecherche) Is Nothing Then
cellule.Activate
If Not MsgBox("Continuer ?", vbOKCancel, "Continuer ?") = vbOK Then
Exit Sub
End If
End If
Next cellule
Next feuille
End Sub
Public Sub DefineNomPatientRecherche(control As IRibbonControl, nom As String)
nomPatientRecherche = nom
End Sub
Thanks again #Rory for your help

Use VLOOKUP to pass cell reference to a public variable?

I have a userform that opens on cell change in a column.
That userform contains checkboxes, which all trigger a second userform with a text box which looks up a cell on a hidden sheet for its contents. (The checkbox that's ticked determines which cell the textbox looks for). The user then edits the box, clicks a button, and the new text is written back to the same cell.
This is the VBA for when the checkbox is ticked. It works great. Hooray!
Dim vln As Variant
Dim reta As Worksheet
Set reta = ActiveWorkbook.Sheets("RetailerActivity")
Set vln = ActiveCell.Offset(-1, -3)
UserForm2.TextBox1.Text = Application.WorksheetFunction.VLookup(vln, reta.Range("A1:Z100"), 3, False)
UserForm2.TescoSave.Visible = True
UserForm2.Show
End Sub
When the textbox has been edited, I would like to write it back to the same cell it came from. I figure the easiest way to do that is to have a public variable (as range), and to pass the result of the vlookup into that variable so the second userform can have a line which reads
Private Sub ASave_Click()
publicvariable.Value = TextBox1.Value
userform1.hide
End Sub
Nice and easy, rather than doing a VLookup again. Right?
Either way, I can't seem to set the public variable as the lookup.
Outside of any sub I have
Public bums As Range
And in the code above, after the bit where I've set the text box, I've tried to add the line
Set bums = Application.WorksheetFunction.VLookup(vln, reta.Range("A1:Z100"), 3, False)
But the code errors with a "type mismatch".
If I try
Set bums = Range(Application.WorksheetFunction.VLookup(vln, reta.Range("A1:Z100"), 3, False))
I get method "Range" of object "_global" failed.
I code by cobbling bits off the internet, as you can probably tell, so this is I don't doubt a complete kludge.
Any advice would be super appreciated.
VLookup returns a value, not a Range. You could use Match to find the row and then Cells to get the actual reference - for example:
Dim vMatch
vMatch = Application.Match(vln, reta.Range("A1:A100"),0)
If Not IsError(vMatch) then
Set bums = reta.Cells(vMatch, "C")
else
msgbox "No match for " & vln
Exit Sub
End If
Personally I would also not use a public variable, but create a property for Userform2 to which you can assign the range.