How to reset Excel internal button count? - vba

I have an an Excel sheet that uses VBA to generate some form control buttons on the fly.
the buttons are cleared and then new buttons are created.
I have noticed that even though old buttons are deleted Excel is keeping an internal register of each button. New buttons have button name of over 11K
I don't know if there is some sort of limit excel will allow for this and I don't want to run out of buttons.
I am not sure if this growing registry of buttons past is causing the file size to grow.
I would like to be able to reset the increment back to 0
Anyone have any idea how I can go back to button_0 ? (without starting a whole new Excel sheet)

Seems internal button count is sheet specific. Solution is to copy sheet, rename old sheet, then rename new sheet to old sheet name. Then delete old sheet. Viola! button count reset.

I found the answer somewhere in a forum, but I couldn't retrace it.
You could also pragmatically create the button by a function/sub-routine as a workaround.
Example: below function adds a button and limits the count to a fixed number (in my case, it is the total buttons available).
In my sheet, the first button is named "Button 687" (before I use the macro) and the second button is named "Button 2".
But, it is quite not dynamic when you want to add Drop Down or other form control etc. Macro recording helps you figure out the syntax, methods and properties of the form control you want to add though.
I am not sure why "buttons" is not listed in Properties/Methods after you typed "Activesheet." but Activesheet.Buttons(1).Name or Activesheet.buttons.add are valid codes.
Public Sub Add_Button(ButtonLabel$, ButtonSize#, BFontSize#, BFontName$)
Dim Button__ As Object
Dim One_Unit#: Per_Unit = Application.CentimetersToPoints(1)
'Creates a button at the sheet's first cell (row 1, col 1) with the height and width being 1cm.
Set Button__ = ActiveSheet.Buttons.Add(1, 1, One_Unit, One_Unit)
'button count will be restricted to the number set by user.
With Button__
.Name = "Button " & ActiveSheet.Buttons.Count
With .Characters
.Text = UCase(BLabel)
.Font.Name = BFontName
.Font.Size = BFontSize
End With
End With
End Sub
Sub AddAButton()
Add_Button BLabel:="SAVE"
Debug.Print ActiveSheet.Buttons(ActiveSheet.Buttons.Count).Name
End Sub

Related

Get value from command button VBA

I have created A userform with few command buttons.
I can't seem to figure out how do I get the information from them.
I want to open this userform from another one and then I want the user to choose an option from one of the buttons which will change a specific cell in the table itself
the userform I created
I did not write anything on this userform therefor there is no code from it to show only the design.
how do get the information from the buttons to be written in A specific cell on a specific worksheet?
double click on one of the buttons, in the code menu a new sub should appear. this looks something like:
Sub CommandButton1_onClick()
End sub
Alongside this event method, it also has a few properties. The one that is usefull here is the CommandButton1.Value, this represents the state of the button (either true or false iirc).
So build for each button (I strongly advice giving them custom names to prevent getting lost in the trouble) as sub like this:
Sub CommandButton1_onClick()
if CommandButton1.Value then
ThisWorkBook.WorkSheets("WorksheetName").Range("YourRange").Value = "Some value"
else
ThisWorkBook.WorkSheets("WorksheetName").Range("YourRange").Value = ""
end if
End sub

VBA Executing Sub Oddly

I have made this simple invoice control worksheet in excel and I use VBA to make it easier to visualize and add new items. I have made dozens of other VBA programmed Worksheets, and all of them have a "New" active x button, programmed just like this:
Private Sub ButtNew2_Click()
Dim Guia As Worksheet
Dim UltLin As Integer
Set Guia = Workbooks("Notas Fiscais.xlsm").Worksheets("SaĆ­da")
UltLin = Guia.UsedRange.Rows.Count + 1
Guia.Application.Goto Reference:="R" & UltLin & "C1"
FormNotasSaida.Show
FormNotasSaida.BoxDataEmiss.SetFocus
End Sub
Simple as that. Just select the first blank line so that the form loads blank. It works fine in any other Workbook. But in this one, if and every time I click this button, after closing the form, the next time (and only once) I load the form again in any possible way (either double clicking an item, pressing the "Show" button or pressing the "New" button again), it loads either blank or showing the last launched item (case you did so).
After closing it, I can click wherever or press the "Show" button whenever, they work fine, as they always have. The problem occurs exclusively once, after pressing the "New" button.
What am I possibly doing wrong, specially knowing that this method works perfectly in all other workbooks?
FormNotasSaida.Show
FormNotasSaida.BoxDataEmiss.SetFocus
Forms are a special kind of class modules with a designer and a predeclared ID attribute. This "predeclared ID" is what's at play here: you're using/reusing the default global instance of the class, and [unless you close it with the X button in the control box,] never unload it so you're always showing the same form.
A best practice is to create a new instance of the form every time you use it:
Set frm = New FormNotasSaida
frm.Show
frm.BoxDataEmiss.SetFocus

How to use VBA to add a button to a sheet and assign its click event upon another button press

I am trying to automate a quarterly patient report for a local pharmacy and in doing so I have transferred it to excel. One portion of the automation is an add patient button on the cover page of the report that goes to a form for relevent information. The ok button on the form takes the information and formats it in a new sheet named according to the patient's name. The button also adds two newly created buttons to the patient sheet, a delete and edit button. I can create the buttons and place them, but I can not find any way to assign a click event to the buttons, since they are considered new objects on each page.
I have moved the button's main code to the workbook itself, so all I really need to put in the button's click event is a call to that method, but I can't find any way to access the new buttons' click events through vba, and since I need to call a method in VBA itself, I'm not sure I can use a macro either (fair note, I am not all that familiar with excel macros, so if the solution lies in them, I can use that too).
Here is the code that instantiates and places/sizes the delete button on the new sheet:
Dim btn As OLEObject
Set btn = ActiveSheet.OLEObjects.Add(ClassType:="Forms.CommandButton.1", Link:=False, DisplayAsIcon:=False)
With btn
.Name = "deletePatientButton"
.Object.Caption = "Delete Patient"
.Top = 5.25
.Left = 290.25
.Width = 75
.Height = 24.75
.PrintObject = False
End With
Here is the main method of the delete button placed in the workbook code itself (note it only really calls another verification form, so this may be redundant, but I wanted to put it in the workbook section for testing since I assumed it would have the largest scope):
Public Sub mainDeleteButton(sheet As Worksheet)
Dim confirmer As New deleteConfirmationForm
sheet.Activate
confirmer.Show
End Sub
Finally, here is an example of the click event I am hoping to be able to place, or replace with another solution:
Private Sub deletePatientButton_Click()
Call ThisWorkbook.mainDeleteButton(Me)
End Sub
Any help is more than appreciated!
It is possible to add the event code programmatically to the worksheet module (see this post). However, it may be easier to keep your buttons on template worksheets that already have the event code in them. Just copy your template to a new sheet, rename it, and add your patient data.

Excel macro to remove rows that have been added via another macro

I have recently added a macro to add a selection from Sheets("Activities") and insert it into a new row positioned at row 25 on Sheets("EP2"). - Thus adding new pre-written "activities" into the sheet.
There are a number of different selections (pre-written activities) from Sheets("Activities") that have been assigned their own buttons.
When the button is pressed, the appropriate selection from Sheets("Activities") is inserted into the same position (row 25 on Sheets("EP2"))
This means that each time another activity is added, the last addition moves down the page. This is all fine.
HOWEVER, I am wanting to add coinciding buttons to then remove certain activities (from Sheets("EP2") at a later date. this poses a problem because when a certain activity is added to the sheet it may not have the same cell reference as when it was 1st added via the macro. Is there a way around this?
Basically, this form has to be for people that have almost no understanding of excel whatsoever and needs to have these prewritten activities add-able at a click of a button and then removable at the click of a button. The code I am using is as follows..
Sub Insert_CV()
Dim Answer As VbMsgBoxResult
Answer = MsgBox("Are you sure you want to insert a CV agreement" & vbNewLine & "This cannot be undone.", vbOKCancel, "CV Agreement")
If Answer = vbOK Then
Sheets("Activities").Select
Rows("1:4").Select
Selection.Copy
Sheets("EP2").Select
Rows("24:24").Select
Range("C24").Activate
Selection.Insert Shift:=xlDown
Range("D20:U20").Select
End If
End Sub
Thanks for your help

Order of Events for the SheetFollowHyperlink Event

I have a workbook that lists people's names and overall performance for the past few weeks. I was asked to make it so that when their names are clicked, the details for that person would show. The solution I came up with at the time was to point all of the hyperlinks to a sheet that reminded them to turn on their macros.
In the WorkSheet_Activate event, I redirected them to another sheet that populated with the details for the person they had selected. This works fine. If the user doesn't have their macros turned on, they get a friendly reminder, but if they do, they immediately get redirected. There's just one problem. Because the hyperlink takes them somewhere else first, it causes the infamous "screen flicker".
On researching, I found the FollowHyperlink Events (I think the workbook level event would be most suitable for my purposes, though). However, before I get started rebuilding it, I wanted to make sure that this would solve the "screen flicker".
On MSDN, it states that the Event occurs when the user clicks the hyperlink. I can't seem to find anywhere that directly states whether this Event is triggered before or after the user is directed to the other sheet, though. If it gets triggered right after, that wouldn't really help me, but if it gets triggered before, I could put an Application.ScreenUpdates = False in the event, and it would solve my problem.
TL;DR (Get to the point already):
Does the Workbook_SheetFollowHyperlink Event happen before or after the user is directed to where ever the hyperlink is pointed?
To answer your question, the event is triggered after the hyperlink is followed. You can demonstrate this using the code below:
Private Sub Workbook_SheetFollowHyperlink(ByVal Sh As Object, ByVal Target As Hyperlink)
Debug.Print "Workbook level: " & ActiveSheet.Name
End Sub
When the event is triggered, the ActiveSheet is the sheet directed to by the hyperlink.
I'm not sure of a way to solve your problem directly, even the Click() event won't be raised when you click a hyperlink. However, the Worksheet level hyperlink event handler will be called before the Workbook level handler and this may speed the process up enough to not see the flicker.
You can prove this if you leave the Workbook level event as is and add the following code to the Worksheet containing the hyperlinks:
Private Sub Worksheet_FollowHyperlink(ByVal Target As Hyperlink)
Debug.Print "Worksheet level: " & ActiveSheet.Name
Sleep 1000
Debug.Print "Leaving worksheet level event"
End Sub
After a few experiments (see below) I concluded that:
Allow the user to use the hyperlink columns when macros are disabled.
When macros are enabled, hide the current hyperlink column and show another column that gives the user a different "hyperlink" that takes them directly to where you want them to go.
The 2nd hyperlink can easily be "simulated" such that it picks up the other columns hyperlink. (See below)
I hope his helps
Interesting, here's a few things I tried
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
' This does not fire if the user clicks directly on the hyperlink text
' it only fires if when click on the cell space that is not text
With ActiveCell
If Hyperlinks.Count Then
MsgBox "hi" & .Hyperlinks(1).Range
.Hyperlinks(1).Follow
End If
End With
End Sub
However you could make the text in the cells look like a hyperlink but actually just be blue underlined text. You could then use the Worksheet_SelectionChange to go to a related cell.
The question then become how to store the related cell.
You want to store it so that if row and column are inserted on the destination sheet, the reference will adjust. (eg NOT in comments, or the description of named ranges etc..)
Depending on how much data you have there's a variety of ways you could choose from.
I think I would favour this:
Having a hidden column next to the cell on display that has a hyperlink. The cell on display has a formula that is set to pick up the value from the hidden column (I quite like the sound of this as you have the hyperlink column already - so just modify the above code to get the hyperlink from the column next to the clicked cell using offset perhaps)
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
' This does not fire if the user clicks directly on the hyperlink text
With ActiveCell.offset(0,1)
If Hyperlinks.Count Then
.Hyperlinks(1).Follow
End If
End With
End Sub
You could mess around with named ranges, but it will be a pain.
I've just realised that what I tried won't help much as you need the hyperlink to work when macros have not been enabled!
So to get the above to work you could change the columns displayed when the user enables macros. ie the hyperlink column is shown when macros are disabled (and the column to the left of it is not).
When macros are enabled hide the hyperlink column and show the one to the left of it that will cause the SelectionChange event to run.
(You need to beware how other hyperlinks are used as any cell with a hyperlink next to it will respond to the event. You may need to use intersection to check the cell clicked is in a namedrange that contains "all the cells that need to respond to a user clicking them in the manner".
All the above sounds a bit mad, but it would appear the event model does not facilitate stopping the screen flickering.
I hope there is a better way of doing what you want, but for what it's worth, the above might help.
Harvey