Replace auto filled text via userform - vba

I've developed a user form for the letters we use at work that auto fill the document after required data has been entered.
At this current point in time - when you hit OK the data will be entered and the data will fill the form. Some users are just trying to keep entering information over the top of the already filled form and stacking previously entered data into the letter.
Question: How do I get the user form to replace entered data rather than add entered data.
So if I enter the name as John Wayne, complete my letter and decide to write another letter on the same open document - how do I reopen my macro, populate the data and then overwrite all the previous information of the previous letter.
Option Explicit
Private Sub CheckBox1_Click()
Dim en As Boolean
en = Not CheckBox1.Value
EnableControls Array(TBLPGN, TBLPFN), en
If CheckBox1.Value = True Then ComboBoxLodge.Value = "Applicant"
If CheckBox1.Value = False Then ComboBoxLodge.Value = "Lodging parent"
End Sub
'utility sub: enable/disable controls
Private Sub EnableControls(cons, bEnable As Boolean)
Dim con
For Each con In cons
With con
.Enabled = bEnable
.BackColor = IIf(bEnable, vbWhite, RGB(200, 200, 200))
End With
Next con
End Sub
Private Sub cmdCancel_Click()
Unload Me
End Sub
Private Sub cmdClear_Click()
tbForm.Value = Null
tbFN.Value = Null
tbGN.Value = Null
tbDOB.Value = Null
cbLT.Value = Null
tbPN.Value = Null
tbissue.Value = Null
tbexpiry.Value = Null
tbLTD.Value = Null
tbNarrative.Value = Null
tbPRR.Value = Null
cbRecommendation.Value = Null
CheckBox1.Value = False
ComboBoxLodge.Value = Null
End Sub
Private Sub cmdOk_Click()
Dim useAforB As Boolean
useAforB = CheckBox1.Value
Application.ScreenUpdating = False
With ActiveDocument
.Bookmarks("Lodge").Range.Text = ComboBoxLodge.Value
.Bookmarks("Form").Range.Text = tbForm.Value
.Bookmarks("Form2").Range.Text = tbForm.Value
.Bookmarks("AGN").Range.Text = tbGN.Value
.Bookmarks("AFN").Range.Text = tbFN.Value
.Bookmarks("LGN").Range.Text = IIf(useAforB, _
tbGN.Value, TBLPGN.Value)
.Bookmarks("RGN").Range.Text = IIf(useAforB, _
tbGN.Value, TBLPGN.Value)
.Bookmarks("LFN").Range.Text = IIf(useAforB, _
tbFN.Value, TBLPFN.Value)
.Bookmarks("RFN").Range.Text = IIf(useAforB, _
tbFN.Value, TBLPFN.Value)
.Bookmarks("DOB").Range.Text = tbDOB.Value
.Bookmarks("LT").Range.Text = cbLT.Value
.Bookmarks("PN").Range.Text = tbPN.Value
.Bookmarks("PN2").Range.Text = tbPN.Value
.Bookmarks("PN3").Range.Text = tbPN.Value
.Bookmarks("PN4").Range.Text = tbPN.Value
.Bookmarks("Issued").Range.Text = tbissue.Value
.Bookmarks("Expiry").Range.Text = tbexpiry.Value
.Bookmarks("LTD").Range.Text = tbLTD.Value
.Bookmarks("LTD2").Range.Text = tbLTD.Value
.Bookmarks("Narrative").Range.Text = tbNarrative.Value
.Bookmarks("PRR").Range.Text = tbPRR.Value
.Bookmarks("Recommendation").Range.Text = cbRecommendation.Value
End With
Application.ScreenUpdating = True
Unload Me
End Sub
Private Sub Tbform_Change()
tbForm = UCase(tbForm)
End Sub
Private Sub Tbfn_Change()
tbFN = UCase(tbFN)
End Sub
Private Sub Tblpfn_Change()
TBLPFN = UCase(TBLPFN)
End Sub
Private Sub Tbpn_Change()
tbPN = UCase(tbPN)
End Sub
Private Sub UserForm_Initialize()
With cbLT
.AddItem "lost"
.AddItem "stolen"
End With
With cbRecommendation
.AddItem "I believe there is an entitlement to have the l/t flag turned off as the applicant has not contributed to the loss of Passport number: "
.AddItem "I believe there is no entitlement to have the l/t flag turned off as the applicant has contributed to the loss of Passport number: "
End With
With ComboBoxLodge
.AddItem "Lodging parent"
.AddItem "Applicant"
End With
With CheckBox1
CheckBox1.Value = True
End With
lbl_Exit:
Exit Sub
End Sub
Public Sub AutoOpen()
frmminute.Show
End Sub
Sub CallUF()
Dim oFrm As frmminute
Set oFrm = New frmminute
oFrm.Show
Unload oFrm
Set oFrm = Nothing
lbl_Exit:
Exit Sub
End Sub
Sub AutoNew()
CallUF
lbl_Exit:
Exit Sub
End Sub
new code currently getting a runtime error:
Private Sub CommandButtonOk_Click()
Dim useAforB As Boolean
useAforB = CheckBox1.Value
Application.ScreenUpdating = False
With ActiveDocument
Call UpdateBookmark("Title", ComboBoxTitle.Value)
Call UpdateBookmark("GN", TextBoxGN.Value)
Call UpdateBookmark("FN", TextBoxFN.Value)
Call UpdateBookmark("FN2", TextBoxFN.Value)
Call UpdateBookmark("Street", TextBoxStreet.Value)
Call UpdateBookmark("suburb", TextBoxSuburb.Value)
Call UpdateBookmark("postcode", TextBoxpostcode.Value)
Call UpdateBookmark("state", ComboBoxState.Value)
Call UpdateBookmark("street2", .Range.Text = IIf(useAforB, _
TextBoxStreet.Value, TextBoxStreet2.Value))
Call UpdateBookmark("Suburb2", .Range.Text = IIf(useAforB, _
TextBoxSuburb.Value, TextBoxSuburb2.Value))
Call UpdateBookmark("State2", .Range.Text = IIf(useAforB, _
ComboBoxState.Value, ComboBoxState2.Value))
Call UpdateBookmark("PostCode2", .Range.Text = IIf(useAforB, _
TextBoxpostcode.Value, TextBoxPostcode2.Value))
Call UpdateBookmark("CD", TextBoxCD.Value)
Call UpdateBookmark("MPN", TextboxMPN.Value)
Call UpdateBookmark("MPN2", TextboxMPN.Value)
Call UpdateBookmark("MPN3", TextboxMPN.Value)
Call UpdateBookmark("MPN4", TextboxMPN.Value)
Call UpdateBookmark("MPN5", TextboxMPN.Value)
Call UpdateBookmark("MPDD", TextBoxMPDD.Value)
Call UpdateBookmark("NPN", TextBoxNPN.Value)
Call UpdateBookmark("NPDD", TextBoxNPDD.Value)
End With
Application.ScreenUpdating = True
Unload Me
End Sub
Sub UpdateBookmark(BookmarkToUpdate As String, TextAtBookmark As String)
Dim BookmarkRange As Range
Set BookmarkRange = ActiveDocument.Bookmarks(BookmarkToUpdate).Range
BookmarkRange.Text = TextAtBookmark
ActiveDocument.Bookmarks.Add BookmarkToUpdate, BookmarkRange

After reading through your question, I realised what you wanted to do was updating the bookmark at the word document.
Private Sub cmdOk_Click()
Dim useAforB As Boolean
useAforB = CheckBox1.Value
Application.ScreenUpdating = False
Call UpdateBookmark("Lodge", ComboBoxLodge.Value)
Call UpdateBookmark("Form", tbForm.Value)
'Do for the rest.....
Application.ScreenUpdating = True
Unload Me
End Sub
Sub UpdateBookmark(BookmarkToUpdate As String, TextAtBookmark as string)
Dim BookmarkRange As Range
Set BookmarkRange = ActiveDocument.Bookmarks(BookmarkToUpdate).Range
BookmarkRange.Text = TextAtBookmark
ActiveDocument.Bookmarks.Add BookmarkToUpdate, BookmarkRange
End Sub

Related

Make a button visible if a key is press down

I am trying to make a button visible only if a key (example Control) is press down.
My code:
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
If KeyCode = 17 Then
Me.btn1.Visible = True
Else
Me.btn1.Visible = False
End If
End Sub
Private Sub Form_Load()
Me.btn1.Visible = False
End Sub
I need to have visible and active the button only when the CONTROL key is press down and the user click on btn1.
Thank you.
Update Code:
Option Compare Database
Option Explicit
Private Sub btnHide_Click()
DoCmd.Close acForm, "frmDemo", acSaveYes
End Sub
Private Sub btnFake_KeyDown(KeyCode As Integer, Shift As Integer)
On Error GoTo Err_Handler
If vbKeyControl = 17 Then
Me.btnHide.Visible = True
FormTimer
Me.btnFake.SetFocus
Me.btnHide.Visible = False
Else
Me.btnHide.Visible = False
End If
Exit_This_Sub:
Exit Sub
Err_Handler:
If Err = 2467 Then '<== Form is closed.
Resume Exit_This_Sub
Else
MsgBox "Error #: " & Err.Number & " " & Err.Description
End If
Resume Exit_This_Sub
End Sub
Private Sub Form_Load()
Me.btnHide.Visible = False
Me.btnFake.SetFocus
End Sub
Sub FormTimer()
Dim PauseTime, Start, Finish, TotalTime
PauseTime = 0.1 ' Set duration.
Start = Timer ' Set start time.
Do While Timer < Start + PauseTime
DoEvents ' Yield to other processes.
Loop
End Sub
I test it and it is working fine. Simple code.
If CONTROL is press btnHide is visible for 0.1sec.
Any ideas?

Close UserForm if All Data Captured

Say you have aUserForm with TextBox1, TextBox3, TextBox3 and an OK Button.
To only allow the UserForm to close if all three TextBox have data I would use the following script assigned to the OK Button:
Private Sub CommandButton1_Click()
If Len(TextBox1.Value) >= 1 And _
Len(TextBox2.Value) >= 1 And _
Len(TextBox3.Value) >= 1 Then
Me.Hide
Else
MsgBox "Please Complete All Fields!"
End If
End Sub
Is there another way to do this besides an If statement?
Direct User Before Errors Are Made
Preferable to informing a user after an invalid action has been made is to prevent the user from performing that invalid action in the first place[1]. One way to do this is to use the Textbox_AfterUpdate event to call a shared validation routine that controls the Enabled property of your OK button, and also controls the display of a status label. The result is a more informative interface that only allows valid actions, thereby limiting the nuisance of msgbox popups. Here's some example code and screenshots.
Private Sub TextBox1_AfterUpdate()
RunValidation
End Sub
Private Sub TextBox2_AfterUpdate()
RunValidation
End Sub
Private Sub TextBox3_AfterUpdate()
RunValidation
End Sub
Private Sub RunValidation()
If Len(TextBox1.Value) = 0 Or Len(TextBox2.Value) = 0 Or Len(TextBox3.Value) = 0 Then
CommandButton1.Enabled = False
Label1.Visible = True
Else
CommandButton1.Enabled = True
Label1.Visible = False
End If
End Sub
Private Sub CommandButton1_Click()
Me.Hide
End Sub
The If Statement
As far as the If statement is concerned, there are a ton of ways that can be done, but I think anything other than directly evaluating TextBox.Value leads to unnecessary plumbing and code complexity, so I think it's hard to argue for anything other than the If statement in the OP. That being said, this particular If statement can be slightly condensed by capitalizing on its numeric nature, which allows for
Len(TextBox1.Value) = 0 Or Len(TextBox2.Value) = 0 Or Len(TextBox3.Value) = 0
to be replaced with
Len(TextBox1.Value) * Len(TextBox2.Value) * Len(TextBox3.Value) = 0
Although that doesn't gain you much and is arguably less readable code, it does allow for a condensed one liner, especially if the textboxes are renamed...
If Len(TB1.Value) * Len(TB2.Value) * Len(TB3.Value) = 0 Then
.Value vs .Text
Lastly, in this case, I think .Value should be used instead of .Text. .Text is more suited for validating a textbox entry while its being typed, but in this case, you're looking to validate a textbox's saved data, which is what you get from .Value.
More User feedback - Colorization
I almost forgot, I wanted to include this example of how to include even more user feedback. There is a balance between providing useful feedback and overwhelming with too much. This is especially true if the overall form is complicated, or if the intended user has preferences, but color indication for key fields is usually beneficial. A lot of applications may present the form without color at first and then colorize it if the user is having trouble.
Private InvalidColor
Private ValidColor
Private Sub UserForm_Initialize()
InvalidColor = RGB(255, 180, 180)
ValidColor = RGB(180, 255, 180)
TextBox1.BackColor = InvalidColor
TextBox2.BackColor = InvalidColor
TextBox3.BackColor = InvalidColor
End Sub
Private Sub TextBox1_AfterUpdate()
RunValidation Me.ActiveControl
End Sub
Private Sub TextBox2_AfterUpdate()
RunValidation Me.ActiveControl
End Sub
Private Sub TextBox3_AfterUpdate()
RunValidation Me.ActiveControl
End Sub
Private Sub RunValidation(ByRef tb As MSForms.TextBox)
If Len(tb.Value) > 0 Then
tb.BackColor = ValidColor
Else
tb.BackColor = InvalidColor
End If
If Len(TextBox1.Value) * Len(TextBox2.Value) * Len(TextBox3.Value) = 0 Then
CommandButton1.Enabled = False
Label1.Visible = True
Else
CommandButton1.Enabled = True
Label1.Visible = False
End If
End Sub
Private Sub CommandButton1_Click()
Me.Hide
End Sub
As I said in my comment, that is an ok way to do it. But i'll post this just so you have an example of another way. This would allow you to evaluate what is going into the text boxes as they are set.
Option Explicit
Dim bBox1Value As Boolean
Dim bBox2Value As Boolean
Dim bBox3Value As Boolean
Private Sub TextBox1_Change()
If Trim(TextBox1.Text) <> "" Then
bBox1Value = True
End If
End Sub
Private Sub TextBox2_Change()
If Trim(TextBox2.Text) <> "" Then
bBox2Value = True
End If
End Sub
Private Sub TextBox3_Change()
If Trim(TextBox3.Text) <> "" Then
bBox3Value = True
End If
End Sub
Private Sub CommandButton1_Click()
If bBox1Value = True And bBox2Value = True And bBox3Value = True Then
Me.Hide
Else
MsgBox "Please Complete All Fields!"
End If
End Sub
You can use a loop:
Private Sub CommandButton1_Click()
Dim n as long
For n = 1 to 3
If Len(Trim(Me.Controls("TextBox" & n).Value)) = 0 Then
MsgBox "Please Complete All Fields!"
Exit Sub
End If
Next n
Me.Hide
End Sub
You can use the below code
Private Sub CommandButton1_Click()
If Trim(TextBox1.Value & vbNullString) = vbNullString And _
Trim(TextBox2.Value & vbNullString) = vbNullString And _
Trim(TextBox3.Value & vbNullString) = vbNullString Then
Me.Hide
Else
MsgBox "Please Complete All Fields!"
End If
End Sub
I got the answer from this question
VBA to verify if text exists in a textbox, then check if date is in the correct format

excel vba userform enableevents

I'm having a problem with Excel VBA UserForm Events in Office Excel 2013 as follows
Simple userform with three check boxes (CB1,2,3) and two buttons Cancel and OK
When checking CB1 set CB3 = false
When checking CB2 set CB3 = false
When checking CB3 set CB1 = false and CB2 = false
I have read and understood http://www.cpearson.com/excel/SuppressChangeInForms.htm regarding the suppression of UserForm Events and to part it works...
In the list above 2. and 3. above work correctly in code (shown below) and no-events are fired for CB3. However when I do 4. Check CB3 - it fires events for CB1 and CB2, even though I have set it to not fire events.
Any help gratefully received,
Best regards
Seán
Code:
Public EnableEvents As Boolean
Private Sub UserForm_Initialize()
Me.EnableEvents = True
End Sub
Private Sub vboInputsSelected_Click()
Me.EnableEvents = False
vboPracticesSelected.value = False 'this line does NOT fire an event
Me.EnableEvents = True
End Sub
Private Sub vboOutputsSelected_Click()
Me.EnableEvents = False
vboPracticesSelected.value = False 'this line does NOT fire an event
Me.EnableEvents = True
End Sub
Private Sub vboPracticesSelected_Click()
Me.EnableEvents = False
vboInputsSelected.value = False 'this line DOES fire an event
vboOutputsSelected.value = False 'this line DOES fire an event
Me.EnableEvents = True
End Sub
This works well for me. The If bails out when an event is in progress. Realize that the EnableEvents variable does nothing on its own to prevent events. It is only a boolean you created. You need to check it, before allowing an event to occur, for it to do anything.
Public EnableEvents As Boolean
Private Sub vboInputsSelected_Click()
If Not EnableEvents Then Exit Sub
Me.EnableEvents = False
vboPracticesSelected.Value = False
Me.EnableEvents = True
End Sub
Private Sub vboOutputsSelected_Click()
If Not EnableEvents Then Exit Sub
Me.EnableEvents = False
vboPracticesSelected.Value = False
Me.EnableEvents = True
End Sub
Private Sub vboPracticesSelected_Click()
If Not EnableEvents Then Exit Sub
Me.EnableEvents = False
vboInputsSelected.Value = False
vboOutputsSelected.Value = False
Me.EnableEvents = True
End Sub
According to this reference:
it's a better practice to work with a new instance of the class
Below trying to adapt the code:
'http://www.cpearson.com/excel/SuppressChangeInForms.htm
'https://riptutorial.com/vba/example/19036/best-practices
Private Type TView
IsCancelled As Boolean
EnableEvents As Boolean
End Type
Private this As TView
Public Property Get IsCancelled() As Boolean
IsCancelled = this.IsCancelled
End Property
Public Property Get EnableEvents() As Boolean
EnableEvents = this.EnableEvents
End Property
Private Sub UserForm_Initialize()
'...
this.EnableEvents = True
End Sub
Private Sub TextBox1_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)
On Error GoTo ExceptionHandling
this.EnableEvents = False
'some code that would cause an event to run
CleanUp:
On Error Resume Next
this.EnableEvents = True
Exit Sub
ExceptionHandling:
MsgBox "Error: " & Err.description & vbLf & Err.Number
Resume CleanUp
Resume 'for debugging
End Sub
Private Sub TextBox2_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)
'check example
If this.EnableEvents = False Then Cancel = True
'some code to run
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
If CloseMode = VbQueryClose.vbFormControlMenu Then
Cancel = True
this.IsCancelled = True
Me.Hide
End If
End Sub
See Also
VBA UserForm – A Guide for Everyone, Paul Kelly

VBA Word macro to stop user input

I'm writing a big macro for MS Word 2013 and one of the parts of it should be sub that prevents user from writing text; user should be able to use hotkey (eg. ctrl+q) to stop (or start) this sub (I already know how to assign a hotkey to a sub). I'm pretty new to VBA. I've googled for the answer but there's only instruction how to write such macro for Excel, but it doesn't work in Word. Is there a way to do this? How?
Thank you in advance.
Dim startTime As Single
Dim stopTime As Single
Dim timeToRun
Dim totalTime
Dim tmpTime
Dim avg As Long
Public isStart As Boolean
Public Sub hotkeyPressed() 'I wrote module to handle this'
If isStart = True Then
stopButton_Click
Else
startButton_Click
End If
End Sub
Private Sub startButton_Click()
totalTime = tmpTime
startTime = Timer
isStart = True
startButton.Enabled = False
stopButton.Enabled = True
ActiveDocument.Protect _
Type:=wdNoProtection
End Sub
Private Sub stopButton_Click()
isStart = False
stopTime = Timer
tmpTime = totalTime + tmpTime
startButton.Enabled = True
stopButton.Enabled = False
ActiveDocument.Protect _
Type:=wdAllowOnlyReading
End Sub
Private Sub Document_New()
startButton.Caption = "Start!"
stopButton.Caption = "Stop"
isStart = False
Call scheduler
ActiveDocument.Protect _
Type:=wdAllowOnlyReading
On Error GoTo Handler:
Open "KM\" + ActiveDocument.Name + ".txt" For Input As #1
Input #1, line
tmpTime = line
Close #1
Exit Sub
Handler:
tmpTime = 0
End Sub
Private Sub Document_Close()
MyFile1 = "KM\" + ActiveDocument.Name + ".txt"
fnum = FreeFile()
Open MyFile1 For Output As fnum
Print #fnum, totalTime
Close fnum
End Sub
Private Sub scheduler()
timeToRun = Now + TimeValue("00:00:01")
Application.OnTime timeToRun, "getNumberOfLetters"
End Sub
Sub getNumberOfLetters()
If isStart = True Then
numOfLetters = ActiveDocument.Characters.Count
totalTime = Timer - startTime
timeLabel.Caption = totalTime + tmpTime
charLabel.Caption = numOfLetters
setResult
End If
Call scheduler
End Sub
Private Sub setResult()
avg = 60 * numOfLetters / czasLabel.Caption
avg.Caption = avg
End Sub
Have you tried simply using the .Protect method?
Sub ProtectDocument()
ActiveDocument.Protect _
Type:=wdAllowOnlyReading
End Sub
This will prevent user input. You can unprotect the document using VBA if necessary:
Sub UnprotectDocument()
ActiveDocument.Protect _
Type:=wdNoProtection
End Sub

How to perform an action on clicking a custom context menu created in excel using Excel Add-In created with visual studio 2010

I am creating an Excel Add-In using Visual Studio 2010. My intention was to add a context menu to a cell and perform some action on the selected cell or cells. Here is the code I have got as of now
Public Class CC
Private Sub ThisAddIn_Startup() Handles Me.Startup
AddMenu()
End Sub
Private Sub ThisAddIn_Shutdown() Handles Me.Shutdown
DeleteMenu()
End Sub
'AddMenu add context menu to excel
Sub AddMenu()
On Error Resume Next
Dim Bar As Microsoft.Office.Core.CommandBar
Dim NewControl As Microsoft.Office.Core.CommandBarControl
Application.CommandBars("Cell").Controls("A").Delete()
Bar = Application.CommandBars("Cell")
NewControl = Bar.Controls.Add(Microsoft.Office.Core.MsoControlType.msoControlPopup, Id:=1, Temporary:=True)
With NewControl
.Caption = "A"
.BeginGroup = True
.TooltipText = "Change case of selected cells."
End With
With NewControl.Controls.Add(Microsoft.Office.Core.MsoControlType.msoControlButton)
.Caption = "A1"
.FaceId = 1144
.OnAction = "A1"
End With
With NewControl.Controls.Add(Microsoft.Office.Core.MsoControlType.msoControlButton)
.Caption = "A2"
.FaceId = 1145
.OnAction = "A2"
End With
With NewControl.Controls.Add(Microsoft.Office.Core.MsoControlType.msoControlButton)
.Caption = "A3"
.FaceId = 1155
.OnAction = "A3"
End With
End Sub
'DeleteMenu deletes the context meny added to excel
Sub DeleteMenu()
On Error Resume Next
Application.CommandBars("Cell").Controls("A").Delete()
End Sub
Sub A1()
MsgBox "A1"
End Sub
Sub A2()
MsgBox "A2"
End Sub
Sub A3()
MsgBox "A3"
End Sub
End Class
When I install this Add-In the context menu appears in excel, but when I click on the menu buttons I get an error saying that the macro is not available in the workbook. Can anyone please tell me how to make it work?
Your methods A1, A2 and A3 will not automatically be registered as macros with Excel. As a result setting their names into the OnAction strings of the buttons have no effect - Excel doesn't know about a macro called "A1". So in this sense the VSTO add-in does not behave like the code in VBA would at all.
There is another approach though: For the CommandBar Buttons you can add event handlers - you'd use the WithEvents keyword and then handle the Click event of the buttons. Some examples that might get you started are here: http://msdn.microsoft.com/en-us/library/aa189726(v=office.10).aspx
Using Excel-DNA (an open source .NET / Excel integration library that I develop) the methods and user-defined functions in your .NET code are registered with Excel through the C API. As a result the behaviour is closer to that of VBA, and your code with the OnAction="..." strings would work too.
Public Class CC
Private WithEvents A1 As Office.CommandBarButton
Private WithEvents A2 As Office.CommandBarButton
Private WithEvents A3 As Office.CommandBarButton
Private Sub ThisAddIn_Startup() Handles Me.Startup
AddMenu()
End Sub
Private Sub ThisAddIn_Shutdown() Handles Me.Shutdown
DeleteMenu()
End Sub
'AddMenu add context menu to excel
Sub AddMenu()
On Error Resume Next
Dim Bar As Microsoft.Office.Core.CommandBar
Dim NewControl As Microsoft.Office.Core.CommandBarControl
Application.CommandBars("Cell").Controls("A").Delete()
Bar = Application.CommandBars("Cell")
NewControl = Bar.Controls.Add(Microsoft.Office.Core.MsoControlType.msoControlPopup, Id:=1, Temporary:=True)
With NewControl
.Caption = "A"
.BeginGroup = True
.TooltipText = "Change case of selected cells."
End With
A1 = NewControl.Controls.Add(Microsoft.Office.Core.MsoControlType.msoControlButton)
With NewControl.Controls.Add(Microsoft.Office.Core.MsoControlType.msoControlButton)
.Caption = "A1"
.FaceId = 1144
End With
A2 = NewControl.Controls.Add(Microsoft.Office.Core.MsoControlType.msoControlButton)
With NewControl.Controls.Add(Microsoft.Office.Core.MsoControlType.msoControlButton)
.Caption = "A2"
.FaceId = 1145
End With
A3 = NewControl.Controls.Add(Microsoft.Office.Core.MsoControlType.msoControlButton)
With NewControl.Controls.Add(Microsoft.Office.Core.MsoControlType.msoControlButton)
.Caption = "A3"
.FaceId = 1155
End With
End Sub
'DeleteMenu deletes the context meny added to excel
Sub DeleteMenu()
On Error Resume Next
Application.CommandBars("Cell").Controls("A").Delete()
End Sub
Sub A1()
MsgBox "A1"
End Sub
Sub A2()
MsgBox "A2"
End Sub
Sub A3()
MsgBox "A3"
End Sub
Private Sub A1_Click(ByVal Ctrl As Office.CommandBarButton, ByRef CancelDefault As Boolean) Handles A1.Click
A1()
End Sub
Private Sub A2_Click(ByVal Ctrl As Office.CommandBarButton, ByRef CancelDefault As Boolean) Handles A2.Click
A2()
End Sub
Private Sub A3_Click(ByVal Ctrl As Office.CommandBarButton, ByRef CancelDefault As Boolean) Handles A3.Click
A3()
End Sub
End Class
This is the solution that I found for the above problem
This is a bear of a problem. Very little info anywhere on creating excel popups in vb.net. This is my version of creating semi dynamic menus. The menu items come from dictionaries in this case but could come from anywhere. Created this class and loaded it on workbook startup event.
Public Class Popups
Private mCmdBarPopFH As Microsoft.Office.Core.CommandBarPopup
Private mCmdBarPopPH As Microsoft.Office.Core.CommandBarPopup
Private mCmdBarPopRH As Microsoft.Office.Core.CommandBarPopup
Private WithEvents tagFH1 As Microsoft.Office.Core.CommandBarButton
Private WithEvents tagFH2 As Microsoft.Office.Core.CommandBarButton
Private WithEvents tagFH3 As Microsoft.Office.Core.CommandBarButton
Private WithEvents tagPH1 As Microsoft.Office.Core.CommandBarButton
Private WithEvents tagPH2 As Microsoft.Office.Core.CommandBarButton
Private WithEvents tagPH3 As Microsoft.Office.Core.CommandBarButton
Private WithEvents tagRH1 As Microsoft.Office.Core.CommandBarButton
Private WithEvents tagRH2 As Microsoft.Office.Core.CommandBarButton
Private WithEvents tagRH3 As Microsoft.Office.Core.CommandBarButton
Private WithEvents tag1st As Microsoft.Office.Core.CommandBarButton
Private WithEvents tag2nd As Microsoft.Office.Core.CommandBarButton
Private WithEvents tagClr As Microsoft.Office.Core.CommandBarButton
Private mFHDefDict As New Dictionary(Of String, HeaderDef)
Private mPHDefDict As New Dictionary(Of String, HeaderDef)
Private mRHDefDict As New Dictionary(Of String, HeaderDef)
Private mPHSheet As Excel.Worksheet 'temp until sheet management
Private mRHSheet As Excel.Worksheet
Private mFHSheet As Excel.Worksheet
'************************************************************************************
'Add popup menu for marking sample file.
'************************************************************************************
Public Sub TagsMenuAdd()
Dim oHeaderDefs As New HeaderDefs
Dim oCmdBar As Microsoft.Office.Core.CommandBar
mFHSheet = CType(Globals.ThisWorkbook.Application.Sheets("File Headers"), Excel.Worksheet)
mPHSheet = CType(Globals.ThisWorkbook.Application.Sheets("Plate Headers"), Excel.Worksheet)
mRHSheet = CType(Globals.ThisWorkbook.Application.Sheets("Read Headers"), Excel.Worksheet)
mFHDefDict = oHeaderDefs.DefDictLoad(mFHSheet) 'temp until sheet management
mPHDefDict = oHeaderDefs.DefDictLoad(mPHSheet)
mRHDefDict = oHeaderDefs.DefDictLoad(mRHSheet)
oCmdBar = Globals.ThisWorkbook.Application.CommandBars.Add(Name:="Fil_CellMarking", Position:=Microsoft.Office.Core.MsoBarPosition.msoBarPopup, Temporary:=True)
With oCmdBar
tag1st = CType(.Controls.Add(Type:=Microsoft.Office.Core.MsoControlType.msoControlButton), Microsoft.Office.Core.CommandBarButton)
tag1st.Caption = "Mark 1st Well of 1st data set"
tag1st.Tag = "1st"
tag2nd = CType(.Controls.Add(Type:=Microsoft.Office.Core.MsoControlType.msoControlButton), Microsoft.Office.Core.CommandBarButton)
tag2nd.Caption = "Mark 1st Well of 2nd data set"
tag2nd.Tag = "2nd"
mCmdBarPopFH = CType(.Controls.Add(Type:=Microsoft.Office.Core.MsoControlType.msoControlPopup), Microsoft.Office.Core.CommandBarPopup)
With mCmdBarPopFH
.Caption = "Mark File Headers"
.Enabled = True
End With
mCmdBarPopPH = CType(.Controls.Add(Type:=Microsoft.Office.Core.MsoControlType.msoControlPopup), Microsoft.Office.Core.CommandBarPopup)
With mCmdBarPopPH
.Caption = "Mark Plate Headers"
.Enabled = True
End With
mCmdBarPopRH = CType(.Controls.Add(Type:=Microsoft.Office.Core.MsoControlType.msoControlPopup), Microsoft.Office.Core.CommandBarPopup)
With mCmdBarPopRH
.Caption = "Mark Read Headers"
.Enabled = True
End With
tagClr = CType(.Controls.Add(Type:=Microsoft.Office.Core.MsoControlType.msoControlButton), Microsoft.Office.Core.CommandBarButton)
tagClr.Caption = "Clear All Markings"
tagClr.Tag = "clr"
End With
TagsMenuItemsFH(mFHDefDict)
TagsMenuItemsPH(mPHDefDict)
TagsMenuItemsRH(mRHDefDict)
End Sub
'************************************************************************************
'Add popup menu items for marking sample file.
'************************************************************************************
Public Sub TagsMenuItemsFH(DefDict As Dictionary(Of String, HeaderDef))
Dim iButtons As Integer
iButtons = 1
For Each sKey As String In DefDict.Keys
Select Case iButtons
Case 1
With mCmdBarPopFH
tagFH1 = CType(.Controls.Add(Type:=Microsoft.Office.Core.MsoControlType.msoControlButton), Microsoft.Office.Core.CommandBarButton)
tagFH1.Caption = DefDict(sKey).HeaderName
tagFH1.Tag = "FH1"
End With
Case 2
With mCmdBarPopFH
tagFH2 = CType(.Controls.Add(Type:=Microsoft.Office.Core.MsoControlType.msoControlButton), Microsoft.Office.Core.CommandBarButton)
tagFH2.Caption = DefDict(sKey).HeaderName
tagFH2.Tag = "FH2"
End With
Case 3
With mCmdBarPopFH
tagFH3 = CType(.Controls.Add(Type:=Microsoft.Office.Core.MsoControlType.msoControlButton), Microsoft.Office.Core.CommandBarButton)
tagFH3.Caption = DefDict(sKey).HeaderName
tagFH3.Tag = "FH3"
End With
End Select
iButtons = iButtons + 1
Next
End Sub
Public Sub TagsMenuItemsPH(DefDict As Dictionary(Of String, HeaderDef))
Dim iButtons As Integer
iButtons = 1
For Each sKey As String In DefDict.Keys
With mCmdBarPopPH
Select iButtons
Case 1
tagPH1 = CType(.Controls.Add(Type:=Microsoft.Office.Core.MsoControlType.msoControlButton), Microsoft.Office.Core.CommandBarButton)
tagPH1.Caption = DefDict(sKey).HeaderName
tagPH1.Tag = "PH1"
Case 2
tagPH2 = CType(.Controls.Add(Type:=Microsoft.Office.Core.MsoControlType.msoControlButton), Microsoft.Office.Core.CommandBarButton)
tagPH2.Caption = DefDict(sKey).HeaderName
tagPH2.Tag = "PH2"
Case 3
tagPH3 = CType(.Controls.Add(Type:=Microsoft.Office.Core.MsoControlType.msoControlButton), Microsoft.Office.Core.CommandBarButton)
tagPH3.Caption = DefDict(sKey).HeaderName
tagPH3.Tag = "PH3"
End Select
End With
iButtons = iButtons + 1
Next
End Sub
Public Sub TagsMenuItemsRH(DefDict As Dictionary(Of String, HeaderDef))
Dim iButtons As Integer
iButtons = 1
For Each sKey As String In DefDict.Keys
With mCmdBarPopRH
Select Case iButtons
Case 1
tagRH1 = CType(.Controls.Add(Type:=Microsoft.Office.Core.MsoControlType.msoControlButton), Microsoft.Office.Core.CommandBarButton)
tagRH1.Caption = DefDict(sKey).HeaderName
tagRH1.Tag = "RH1"
Case 2
tagRH2 = CType(.Controls.Add(Type:=Microsoft.Office.Core.MsoControlType.msoControlButton), Microsoft.Office.Core.CommandBarButton)
tagRH2.Caption = DefDict(sKey).HeaderName
tagRH2.Tag = "RH2"
Case 3
tagRH3 = CType(.Controls.Add(Type:=Microsoft.Office.Core.MsoControlType.msoControlButton), Microsoft.Office.Core.CommandBarButton)
tagRH3.Caption = DefDict(sKey).HeaderName
tagRH3.Tag = "RH3"
End Select
End With
iButtons = iButtons + 1
Next
End Sub
Private Sub Button_Click(ByVal Ctrl As Microsoft.Office.Core.CommandBarButton, ByRef CancelDefault As Boolean) Handles tag1st.Click, tag2nd.Click, tagClr.Click
Select Case Ctrl.Tag
Case "1st"
MsgBox("1st")
Case "2nd"
MsgBox("2nd")
Case "clr"
MsgBox("clr")
End Select
End Sub
Private Sub Header_Click(ByVal Ctrl As Microsoft.Office.Core.CommandBarButton, ByRef CancelDefault As Boolean) Handles tagFH1.Click, tagFH2.Click, tagFH3.Click, tagPH1.Click, tagPH2.Click, tagPH3.Click, tagRH1.Click, tagRH2.Click, tagRH3.Click
Select Case Ctrl.Tag
Case "FH1"
MsgBox("FH1")
Case "FH2"
MsgBox("FH2")
Case "FH3"
MsgBox("FH3")
Case "PH1"
MsgBox("PH1")
Case "PH2"
MsgBox("PH2")
Case "PH3"
MsgBox("PH3")
Case "RH1"
MsgBox("RH1")
Case "RH2"
MsgBox("RH2")
Case "RH3"
MsgBox("RH3")
End Select
End Sub
End Class