How to make a toggle button in a commandbar VBA PowerPoint? - vba

I'm trying to make a toggle button on a command bar but I'm coming across two problems 1) It keeps performing 'removebleed' rather than toggling between the two. 2) it doesn't show the button being toggled. First I've attached the menu button code then after the code for the button. Many thanks for any help, Jay
Set ToggleButton = oToolbar.Controls.Add(Type:=msoControlButton)
With ToggleButton
.DescriptionText = "Switch bleed on or off"
.Caption = "Bleed on/off"
.OnAction = "ToggleButton"
.Style = msoButtonCaption
End With
Sub ToggleButton()
Static Toggle As Boolean
If Toggle = True Then
With Application.CommandBars.ActionControl
.State = Not .State
End With
Toggle = False ' changes the variable so next time it unpresses the button and runs the other macro
AddBleed
Else
RemoveBleed
End If
End Sub
Sub AddBleed()
Dim WidthBleed As String
Dim HeightBleed As String
WidthBleed = 0.125 * 72
HeightBleed = 0.25 * 72
SWidth = ActivePresentation.PageSetup.SlideWidth
SHeight = ActivePresentation.PageSetup.SlideHeight
With Application.ActivePresentation.PageSetup
.SlideWidth = SWidth + WidthBleed
.SlideHeight = SHeight + HeightBleed
End With
End Sub
Sub RemoveBleed()
Dim WidthBleed As String
Dim HeightBleed As String
Dim SWidth As String
Dim SHeight As String
WidthBleed = 0.125 * 72
HeightBleed = 0.25 * 72
SWidth = ActivePresentation.PageSetup.SlideWidth
SHeight = ActivePresentation.PageSetup.SlideHeight
With Application.ActivePresentation.PageSetup
.SlideWidth = SWidth - WidthBleed
.SlideHeight = SHeight - HeightBleed
End With
End Sub

I needed to add the Toggle True to the 'Else' side
Sub ToggleButton()
Static Toggle As Boolean
If Toggle = True Then
With Application.CommandBars.ActionControl
.State = Not .State
End With
Toggle = False ' changes the variable so next time it unpresses the button and runs the other macro
RemoveBleed
Else
With Application.CommandBars.ActionControl 'unpresses the button
.State = Not .State
End With
Toggle = True 'changes the variable so next time it operates the other macro
AddBleed
End If
End Sub

Related

Modify ms Access chart ValueAxis Minimum value

I'm struggling with charts in an Access report. The default Y axis minimum is zero, I would like to change this dynamically as the report loads.
I have tried a number of options using variations on the code below but to no avail. Could someone point me in the direction where I can access and modify the Y axis minimum value. I have tried to use Chart.PrimaryValuesAxisMaximum but this has always resulted in a 'Doesn't support this property or method' Error
Using Office Professional Plus 2019. VB 7.1
Private Sub Report_Load()
Dim MyChart As Object
Dim MyAxis As ChartAxisCollection
Set MyChart = Me.Graph4
Debug.Print MyChart.Name 'This appears to show the chart is available
Set MyAxis = MyChart.ChartAxisCollection
For Each MyAxis In MyChart
Debug.Print MyAxis.Count
Next
End Sub
Any help would be very much appreciated.
Thank you
I can give example from my project which uses classic chart control, not Modern Charts. This procedure is called by a form button click and a report Detail section Format event.
Sub FormatVibGraph(strObject As String, strLabNum As String, booMetric As Boolean)
'format Vibratory graph form and report
Dim obj As Object
Dim gc As Object
Dim MinDD As Double
Dim MaxDD As Double
MinDD = Nz(DMin("Den", "GraphVibratory"), 0)
MaxDD = Nz(DMax("Den", "GraphVibratory"), 0)
If strObject Like "Lab*" Then
Set obj = Reports(strObject)
Else
Set obj = Forms(strObject).Controls("ctrVibratory").Form
End If
Set gc = obj("gphDensity")
gc.Activate
If MinDD > 0 Then
With gc
.Axes(xlValue).MinimumScale = MinDD
If booMetric = True Then
MaxDD = Int(MaxDD / 100) * 100 + 100
MinDD = MaxDD - 1000
.Axes(xlValue).MaximumScale = MaxDD
.Axes(xlValue).MinimumScale = MinDD
.Axes(xlValue).MajorUnit = 200
.Axes(xlValue).MinorUnit = 40
Else
MaxDD = Int(MaxDD / 5) * 5 + 5
MinDD = MaxDD - 50
.Axes(xlValue).MaximumScale = MaxDD
.Axes(xlValue).MinimumScale = MinDD
.Axes(xlValue).MajorUnit = 10
.Axes(xlValue).MinorUnit = 2
End If
.Axes(xlValue, xlPrimary).HasTitle = True
If booMetric = True Then
.Axes(xlValue, xlPrimary).AxisTitle.Text = "Max. Dry Density, Kg/cu.m"
End If
.Axes(xlCategory, xlPrimary).HasTitle = True
If booMetric = True Then
.Axes(xlCategory, xlPrimary).AxisTitle.Text = "Percent Passing 4.75 mm Sieve"
End If
End With
End If
End Sub
So your code might be simply:
Private Sub Detail_Format(Cancel As Integer, FormatCount As Integer)
Dim MyChart As Object
Set MyChart = Me.Graph4
MyChart.Axes(xlValue).MinimumScale = something
End Sub

Screen blinking issue when updating Userform

I'm trying to create a teleprompter by using Word VBA and Userform. I made it by dragging a Userform's label to the top every xxx millisecond to give the text scrolling effect.
My problem is the blinking screen as probably the code runs much faster than the graphic update.
Is there a way out to prevent the blinking screen?
EDIT:
Below is the code
Private Sub UserForm_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
Dim i As Double
Dim dblScrollHeight As Double
Dim sglPause As Single, sglStart As Single
Dim dblEndPos As Double
If KeyAscii = 32 Then bolScroll = Not bolScroll
If bolScroll = True Then
dblEndPos = 50
dblScrollHeight = 0.1
sglPause = 0.0005 'Alter this number to adjust scroll speed.
i = dblCurrTop
Do
sglStart = Timer 'Set Start time.
Do
DoEvents
Loop Until Timer - sglStart > sglPause
i = i - dblScrollHeight
dblCurrTop = i
'Application.ScreenUpdating = False
Me.lblPrompter.Top = dblCurrTop
'Application.ScreenUpdating = True
If i + Me.lblPrompter.Height <= dblEndPos Then bolScroll = False
Loop Until bolScroll = False
End If
End Sub

Microsoft ActiveX Controls

Is there a way to change the index value of a ActiveX Button that inserted onto a spreadsheet. I currently have four buttons and two are hidden and two are visible. I would like to re-order the them to not have a large gap between objects. I have some VBA code that runs when the document is opened to ensure that they are the right size and location. Because it loops through the OLEObjects Collection; it will not matter what order they are in on the spreadsheet they will always appear with a gap because of the index value in the OLE Object collection. Below is the code:
Private Sub Workbook_Open()
Application.ErrorCheckingOptions.EvaluateToError = False
ActiveWorkbook.Worksheets("SITE").Activate
Dim button As OLEObject
Dim name As String, top As Integer
top = 15
For Each button In ActiveWorkbook.Worksheets("SITE").OLEObjects
Debug.Print button.name & " " & button.ZOrder
name = button.name
If button.OLEType = xlButtonOnly And InStr(name, "btn") = 1 Then
With button
.Height = 21.75
.Width = 174.75
.Left = 1114.5
.top = top
End With
top = top + 30
End If
Next button
End Sub
If you give them proper names with an integer code in it reflecting their intended position (e.g.: "btn...01", "btn...02",...) then you could try this code (sorry for not being able to format it as code by now):
Private Sub Workbook_Open()
Application.ErrorCheckingOptions.EvaluateToError = False
ActiveWorkbook.Worksheets("SITE").Activate
Dim button As OLEObject
Dim name As String
Dim btnRnk As Long
For Each button In ActiveWorkbook.Worksheets("SITE").OLEObjects
name = button.name
If button.OLEType = xlButtonOnly And InStr(name, "btn") = 1 Then
btnRnk = CLng(Right(name,2))
With button
.Height = 21.75
.Width = 174.75
.Left = 1114.5
.top = 15 + (btnRank - 1) * 30
End With
End If
Next button
End Sub

VBA - Trapping events on dynamically created Textbox

I am writing a VBA application in Excel. I have a Userform that dynamically builds itself based upon the data contained in one of the worksheets.
All of the code that creates the various comboboxes, textboxes and labels is working.
I created a class module to trap OnChange events for the Comboboxes, and again this works as expected.
Now I have a need to trap OnChange events for some of the textboxes, so I created a new class module modelled on that for the comboboxes to trap the events.
Public WithEvents tbx As MSForms.TextBox
Sub SetTextBox(ctl As MSForms.TextBox)
Set tbx = ctl
End Sub
Public Sub tbx_Change()
Dim LblName As String
MsgBox "You clicked on " & tbx.Name, vbOKOnly
End Sub
The message box is just so that I can confirm it works before I go further.
The problem I'm getting is in the UserForm code module:
Dim TBox As TextBox
Dim tbx As c_TextBoxes
'[...]
Set TBox = lbl
Set tbx = New c_TextBoxes
tbx.SetTextBox lbl
pTextBoxes.Add tbx
This throws up a type mismatch error at Set TBox=lbl. It's the exact same code that works fine for the ComboBox, just with the variables given approriate names. I've stared at this for 2 hours.
Anyone got any ideas? Thanks for any pointers.
Edit - Here's the full userform module that I'm having trouble with:
Private Sub AddLines(FrameName As String, PageName As String)
Dim Counter As Integer, Column As Integer
Dim obj As Object
Dim CBox As ComboBox
Dim cbx As c_ComboBox
Dim TBox As TextBox
Dim tbx As c_TextBoxes
Dim lbl As Control
Set obj = Me.MultiPage1.Pages(PageName).Controls(FrameName)
If pComboBoxes Is Nothing Then Set pComboBoxes = New Collection
If pTextBoxes Is Nothing Then Set pTextBoxes = New Collection
For Counter = LBound(Vehicles) To UBound(Vehicles)
For Column = 1 To 8
Select Case Column
Case 1
Set lbl = obj.Add("Forms.Label.1", "LblMachine" & FrameName & Counter, True)
Case 2
Set lbl = obj.Add("Forms.Label.1", "LblFleetNo" & FrameName & Counter, True)
Case 3
Set lbl = obj.Add("Forms.Label.1", "LblRate" & FrameName & Counter, True)
Case 4
Set lbl = obj.Add("Forms.Label.1", "LblUnit" & FrameName & Counter, True)
Case 5
Set lbl = obj.Add("Forms.ComboBox.1", "CBDriver" & FrameName & Counter, True)
Case 6
Set lbl = obj.Add("Forms.Label.1", "LblDriverRate" & FrameName & Counter, True)
Case 7
Set lbltbx = obj.Add("Forms.TextBox.1", "TBBookHours" & FrameName & Counter, True)
Case 8
Set lbl = obj.Add("Forms.Label.1", "LblCost" & FrameName & Counter, True)
End Select
With lbl
Select Case Column
Case 1
.Left = 1
.Width = 60
.Top = 10 + (Counter) * 20
.Caption = Vehicles(Counter).VType
Case 2
.Left = 65
.Width = 40
.Top = 10 + (Counter) * 20
.Caption = Vehicles(Counter).VFleetNo
Case 3
.Left = 119
.Width = 50
.Top = 10 + (Counter) * 20
.Caption = Vehicles(Counter).VRate
Case 4
.Left = 163
.Width = 30
.Top = 10 + (Counter) * 20
.Caption = Vehicles(Counter).VUnit
Case 5
.Left = 197
.Width = 130
.Top = 10 + (Counter) * 20
Set CBox = lbl 'WORKS OK
Call CBDriver_Fill(Counter, CBox)
Set cbx = New c_ComboBox
cbx.SetCombobox CBox
pComboBoxes.Add cbx
Case 6
.Left = 331
.Width = 30
.Top = 10 + (Counter) * 20
Case 7
.Left = 365
.Width = 30
.Top = 10 + (Counter) * 20
Set TBox = lbl 'Results in Type Mismatch
Set tbx = New c_TextBoxes
tbx.SetTextBox TBox
pTextBoxes.Add tbx
Case 8
.Left = 400
.Width = 30
.Top = 10 + (Counter) * 20
End Select
End With
Next
Next
obj.ScrollHeight = (Counter * 20) + 20
obj.ScrollBars = 2
End Sub
And here's the c_Combobox class module:
Public WithEvents cbx As MSForms.ComboBox
Sub SetCombobox(ctl As MSForms.ComboBox)
Set cbx = ctl
End Sub
Public Sub cbx_Change()
Dim LblName As String
Dim LblDriverRate As Control
Dim i As Integer
'MsgBox "You clicked on " & cbx.Name, vbOKOnly
LblName = "LblDriverRate" & Right(cbx.Name, Len(cbx.Name) - 8)
'MsgBox "This is " & LblName, vbOKOnly
'Set obj = Me.MultiPage1.Pages(PageName).Controls(FrameName)
Set LblDriverRate = UFBookMachines.Controls(LblName)
For i = LBound(Drivers) To UBound(Drivers)
If Drivers(i).Name = cbx.Value Then LblDriverRate.Caption = Drivers(i).Rate
Next
End Sub
And finally, here's the c_TextBoxes class module:
Public WithEvents tbx As MSForms.TextBox
Sub SetTextBox(ctl As MSForms.TextBox)
Set tbx = ctl
End Sub
Public Sub tbx_Change()
Dim LblName As String
'Does nothing useful yet, message box for testing
MsgBox "You clicked on " & tbx.Name, vbOKOnly
End Sub
After some quick testing, I am able to reproduce your error if I declare TBox as TextBox. I do not get an error if I declare TBox as MSForms.TextBox. I would recommend declaring all your TextBox variables with the MSForms qualifier.
Test code is situated similar to yours. I have a MultiPage with a Frame where I am adding a Control.
Private Sub CommandButton1_Click()
Dim obj As Object
Set obj = Me.MultiPage1.Pages(0).Controls("Frame1")
Dim lbl As Control
Set lbl = obj.Add("Forms.TextBox.1", "txt", True)
If TypeOf lbl Is TextBox Then
Debug.Print "textbox found1" 'does not execute
End If
If TypeOf lbl Is MSForms.TextBox Then
Debug.Print "textbox found2"
Dim txt1 As MSForms.TextBox
Set txt1 = lbl 'no error
End If
If TypeOf lbl Is MSForms.TextBox Then
Debug.Print "textbox found3"
Dim txt As TextBox
Set txt = lbl 'throws an error
End If
End Sub
I am not sure why the qualifier is needed for TextBox and not ComboBox. As you can see above, a good test for this is the If TypeOf ... Is ... Then to test which objects are which types. I included the first block to show that lbl is not a "bare" TextBox, but, again, I have no idea why that is. Maybe there is another type of TextBox out there that overrides the default declaration?

Converting VB to VBA

Please Help me in following problem:
this code work in VB but doesn't work in VBA:
also I add in beginning a combobox with index 0 to form1
For i = 1 To 5
Load Combo1(i)
Combo1(i).Visible = True
Combo1(i).Left = Combo1(i - 1).Left + Combo1(0).Width
Next i
I will have this code in VBA.
thank you
Are you thinking of something on the lines of:
Sub AddControls()
Dim frm As Form
Dim iTop, iWidth, iHeight, iLeft
DoCmd.OpenForm "FormNameHere", acDesign
Set frm = Forms!FormNameHere
iTop = 100
iWidth = 1500
iHeight = 300
iLeft = 100
For i = 1 To 5
Set ctl = CreateControl(frm.Name, acComboBox, , , , iLeft, iTop, iWidth, iHeight)
ctl.Visible = True
ctl.Name = "Combo1" & i
iLeft = ctl.Left + ctl.Width
Next i
DoCmd.Restore
End Sub
I think the index property is not available in VBA; I am not sure how it works in VB though.