Reset ToggleButtons - vba

I am hoping to set all of the togglebuttons in a powerpoint to "false" (unpressed) upon starting the program. Any ideas why this sort of code is working?
Sub Start()
ActivePresentation.Slides(4).ToggleButton1.Value = 0
ActivePresentation.Slides(4).ToggleButton4.Value = 0
ActivePresentation.SlideShowWindow.View.Next
End Sub
Thank you!

The syntax
ActivePresentation.Slides(4).ToggleButton1.Value = 0
is correct; I've just tested it and it works.
Are you actually calling the Sub at any point though? Simply naming it Start() is not enough.
Related question re. running code on startup, could be helpful.

I had an issue calling this
ActivePresentation.Slides(4).ToggleButton1.Value = 0
Getting the error Method or data member not found which im assuming is a scope issue. The VBA editor doesnt autocomplete .ToggleButton1 which supports the error i was getting.
So, it appears im referencing the object incorrectly.
To correct this I have done the following.
Public Sub ToggleThisButton()
' This is code on Slide 1 referencing control on slide 4
ActivePresentation.Slides(4).Shapes("ToggleButton1").OLEFormat.Object.Value = 1
End Sub
Excerpt from MSDN
Use the OLEFormat property for a shape, inline shape, or field to
return the OLEFormat object. The following example displays the class
type for the first shape on the active document.
Use the Object
property to return an object that represents an ActiveX control or OLE
object. With this object, you can use the properties and methods of
the container application or the ActiveX control.

Related

How would you access the Shape objects WITHIN a SmartArt object without getting Type Mismatch errors?

Question: Is there any way to access Shape objects for each node inside of a SmartArt object? It seems like SmartArtNode objects have a Shapes property that could be used for this purpose, but I am getting Type mismatch errors when I try to send shapes from the SmartArtNode.Shapes to other subroutines.
Background: I am writing an iterator subroutine that takes in 2 parameters: a SmartArt object and a custom class object that has a method to perform actions on Shape objects. The subroutine is supposed to iterate over the Shape objects for each node inside the SmartArt, and call a method from the custom class object on each Shape.
Here is code for the iterator subroutine:
Public Sub IterateOverShapesInSmartArt(mySmartArt As SmartArt, manipulator As ShapeManipulator)
Dim node As SmartArtNode
Dim shpRange As ShapeRange
For Each node In mySmartArt.AllNodes
Set shpRange = node.Shapes
If shpRange.count > 0 Then
manipulator.ManipulateShape shpRange.Item(1)
End If
Next node
End Sub
For reference, the signature on the custom class (ShapeManipulator) method being called is as follows:
Public Sub ManipulateShape(myShape As Shape)
Specific Problem: When I try running this code, I get a Run-time error '13': Type mismatch triggered by the line Set shpRange = node.Shapes. Actually, I originally tried forgoing assignment of node.Shapes to a temporary variable and using the method call manipulator.ManipulateShape node.Shapes(1) instead, but then that method call produced the same Type mismatch error. I've also tried using a For loop with counter variables instead of For Each loop only to get the same error message. What is going on? When I debug, the Locals window shows the right types that match my declarations, so I am at a loss.
I tested your code and I can confirm that Set shpRange = node.Shapes causes a type mismatch error.
I noticed, though, if shpRange is declared as a generic object instead (ie Dim shpRange as Object), it gets resolved to a ShapeRange, and there's no error.
In any case, you can avoid the assignment as follows...
Public Sub IterateOverShapesInSmartArt(mySmartArt As SmartArt, manipulator As ShapeManipulator)
Dim node As SmartArtNode
For Each node In mySmartArt.AllNodes
With node
If .Shapes.Count > 0 Then
manipulator.ManipulateShape .Shapes.Item(1)
End If
End With
Next node
End Sub

Pass value from form to button text vb.net

I am learning vb.net and I'm having issues searching for what I need. I want to create a button that is "re-usable" throughout my application without needing to write code for each instance. So, what I would like to start with is take a variable in a form, example, public integer value and when this value changes I want to write to the text of a button. I know I can easily do this by writing code in the form btn_xxx.text = variable, but what if I have several buttons and each button looks at the same variable? Currently what I do is create a component which inherits a button and have a timer that on tick will look at the variable and write to the text. I'm sure there is a better way. Can anyone point me in the right direction? I know part of my problem is I don't know the nomenclature on what things are called, so hopefully I asked my question without too much confusion.
I saw this, https://www.daniweb.com/programming/software-development/threads/124842/detect-variable-change, but I don't see how to adapt that to my situation.
Here is what I have:
Private WithEvents Active_Alarm As New Nav_Active_Alarm
Then inside of a sub that calculates the count:
Active_Alarm.Count = CInt(dt_Active_Alarms.Rows.Count)
The user control:
Public Class Nav_Active_Alarm
Private mActive_Alarm_Count As Integer
Public Event Active_Alarm_Count_Changed(ByVal mvalue As Integer)
Public Property Count() As Integer
Get
Count = mActive_Alarm_Count
End Get
Set(ByVal value As Integer)
mActive_Alarm_Count = value
If Not Me.DesignMode Then
RaiseEvent Active_Alarm_Count_Changed(mActive_Alarm_Count)
test()
End If
End Set
End Property
Private Sub test()
If Not Me.DesignMode Then
If mActive_Alarm_Count = 0 Then
Me.btn_Goto_Active_Alarm.Image = My.Resources.Alarm_Clock_Static
'console or msgbox will work but updating the image will not
Else
Me.btn_Goto_Active_Alarm.Image = My.Resources.Alarm_Clock_Animation
'console or msgbox will work but updating the image will not
End If
End If
End Sub
End Class
If I write to console or add a msgbox I will see the event working. But, the image will not change. If I call the test sub from a timer it will work. Why won't the button update (by the way, I did try refresh and update in the code)?
Observer pattern is what you probably looking for.
This is quick and dirty.
Create a class to hold the variable value. Add a method that adds a button instance to a list.
Then a button that needs to know about the variable calls the register method.
When the value of the variable changes, it iterates through the list of buttons and sets the Text property of each one.
You might have jumped in a bit too deep too quick here. Google Custom data binding in .net, there's loads of built in stuff you can use. Though do it yourself is a good exercise.
A simple method to do this might be:
Create a form level list to hold the buttons you are interested in
Add the buttons you are interested in, into the list (maybe in form load or some other place where you have initialization code)
Create a private property in your form with a backing variable to hold the value you want to have applied to the buttons. In the setter portion spin through the list and set each buttons text.
Dim lstButtons As New List(Of Button)
Sub SetupButtons()
'call from form load or other init code
lstButtons.Add(btnPopulate)
lstButtons.Add(btnPopulate)
End Sub
Private _buttonText As String
Private Property ButtonText As String
Get
Return _buttonText
End Get
Set(value As String)
_buttonText = value
For Each b As Button In lstButtons
b.Text = value
Next
End Set
End Property
When you set the property - which now acts as your variable - it will update all of your textboxes for you.
I realize you mentioned without having to write code - but something has to tie things together. Even if you used the observer pattern (which is an elegant solution for this - so props to those who suggested it) you'd probably end up creating a class to hold the property and have that class implement the INotifyPropertyChanged from System.ComponentModel, and then you'd also have to have each button have a databinding for its text property to the property in the object of your class. There isn't really a way (that I can think of) to get around having to write some code for each form you do this in (though the class part you'd only have to write once of course).

Proper release of COM objects in code

I have just started to migrate some code from VBA to VB.Net. So I am an absolute beginner in VB.Net – but I want to do things right. Maybe some of my questions are stupid but I guess that is because I am a beginner.
So as a first exercise I have developed my first piece of code (see below). Now I thought I have to release ALL COM objects again. Two of them throw errors already while writing the code. And others throw errors at runtime.
But the funny thing is: Weather I release the rest of the COM objects or not (by making the relevant not yet commented lines of Marshal.Release to comments as well – then all lines starting with Marshal.Release are comment lines) the behavior of the code is absolutely the same to my eyes.
Can anybody tell me where I can see/find the difference?
The internet tells me that there must be a difference?
But I guess I just don’t understand (till now).
Besides this many more questions are in my head:
Does every “Dim” statement create a COM Object - that has to be released later on?
If not how do I detect whether a COM object has been created or not? Which “Dim” statements create COM object and which don't?
In this example: Dim ActiveWindow As Object = Nothing Try ActiveWindow = Me.HostApplication.ActiveWindow() Catch End Try
Is
Marshal.ReleaseComObject(ActiveWindow)
identical to
Marshal.ReleaseComObject(Me.HostApplication.ActiveWindow())?
According to this:
http://www.codeproject.com/Tips/235230/Proper-Way-of-Releasing-COM-Objects-in-NET
Would it not be better to release each "level" separately like this:
Marshal.ReleaseComObject(Me.HostApplication.ActiveWindow())
Marshal.ReleaseComObject(Me.HostApplication)
Marshal.ReleaseComObject(Me)
Overall: Am I trying to release too much? Or is it correct / good practie?
And what does "GC.Collect()" and "… = Null" have to do with all this? I have not used it at all. Should I better use it? Why? ( "... = Null" I have seen here:
http://www.codeproject.com/Tips/162691/Proper-Way-of-Releasing-COM-Objects-in-NET)
Why do I get “ShapeCount was not declared …” - Error if I try to do “Marshal.ReleaseComObject(ShapeCount)”? The same with “ShRange”. I think these are COM objects as well?!?
How do I notice when is the best time to release the COM object again? When I process/debug my code step by step with F11 will it be possible for me to determine the best (soonest) point of release? So far I have no “feeling” about when the COM object is not needed anymore and I can release it.
Any help and explanations very welcome.
Here is the code I am talking about:
Imports System.Runtime.InteropServices
Imports System.ComponentModel
Imports System.Windows.Forms
Imports AddinExpress.MSO
Imports PowerPoint = Microsoft.Office.Interop.PowerPoint
'Add-in Express Add-in Module
<GuidAttribute("D75C609E-7632-400F-8A6F-6A6E6E744E75"),
ProgIdAttribute("MyAddin8.AddinModule")> _
Public Class AddinModule
Inherits AddinExpress.MSO.ADXAddinModule
#Region " Add-in Express automatic code "
[…]
#End Region
Public Shared Shadows ReadOnly Property CurrentInstance() As AddinModule
Get
Return CType(AddinExpress.MSO.ADXAddinModule.CurrentInstance, AddinModule)
End Get
End Property
Public ReadOnly Property PowerPointApp() As PowerPoint._Application
Get
Return CType(HostApplication, PowerPoint._Application)
End Get
End Property
Private Sub AdxRibbonButton2_OnClick(sender As Object, control As IRibbonControl, pressed As Boolean) Handles AdxRibbonButton2.OnClick
MsgBox(GetInfoString2())
End Sub
Friend Function GetInfoString2() As String
Dim ActiveWindow As Object = Nothing
Try
ActiveWindow = Me.HostApplication.ActiveWindow()
Catch
End Try
Dim Result As String = "No document window found!"
If Not ActiveWindow Is Nothing Then
Select Case Me.HostType
Case ADXOfficeHostApp.ohaPowerPoint
Dim Selection As PowerPoint.Selection =
CType(ActiveWindow, PowerPoint.DocumentWindow).Selection
Dim WindowViewType As PowerPoint.PpViewType = PowerPoint.PpViewType.ppViewNormal
Dim SlideRange As PowerPoint.SlideRange = Selection.SlideRange
Dim SlideCountString = SlideRange.Count.ToString()
If WindowViewType = 9 And SlideCountString < 2 Then
Dim ShRange As PowerPoint.ShapeRange = Nothing
Try
ShRange = Selection.ShapeRange
Catch
End Try
If Not ShRange Is Nothing Then
Dim ShapeCount = ShRange.Count.ToString()
Result = "You have " + ShapeCount _
+ " shapes selected."
Else
Result = "You have 0 shapes selected."
End If
End If
'Marshal.ReleaseComObject(ShapeCount)
'Marshal.ReleaseComObject(ShRange)
'Marshal.ReleaseComObject(WindowViewType)
'Marshal.ReleaseComObject(SlideCountString)
Marshal.ReleaseComObject(SlideRange)
Marshal.ReleaseComObject(Selection)
Case Else
Result = AddinName + " doesn't support " + HostName
End Select
'Marshal.ReleaseComObject(Me.HostType)
'Marshal.ReleaseComObject(Result)
Marshal.ReleaseComObject(Me.HostApplication.ActiveWindow())
Marshal.ReleaseComObject(Me.HostApplication)
'Marshal.ReleaseComObject(Me)
End If
Return Result
End Function
End Class
The ReleaseComObject method of the Marshal class decrements the reference count of the specified Runtime Callable Wrapper (RCW) associated with the specified COM object, it doesn't release an object. It comes from the COM nature.
Typically you need to release every object returned from the Office (PowerPoint in your case) object model. Exceptions are objects passed to event handlers as parameters.
You may read more about that and find answers to your multiple questions in the When to release COM objects in Office add-ins developed in .NET article.
FinalReleaseComObject calls ReleaseComObject til it returns 0 which means release of COM object. Calling them in reverse order as in Excel objects(Application, Workbook, Worksheet) is the proper way to dispose of COM objects that are related.
Exception Condition
ArgumentException
o is not a valid COM object.
ArgumentNullException
o is null.

Getting A NullRefrenceException And Cannot Find Out Why?

My goal here is to create a web browser that has a tab system in VB. Since I cannot explicitly name every single new tab the user will use, I have to make more generalized callings. Here's the conflicting code (my btnGo):
Dim thisBrowser As newWebBrowser = Me.tabBrowser.SelectedTab.Tag
If txtAdressSearch.Text.Contains(".com") Or txtAdressSearch.Text.Contains(".net") Or txtAdressSearch.Text.Contains(".gov") Or txtAdressSearch.Text.Contains(".edu") Or txtAdressSearch.Text.Contains(".org") Then 'More to be checked for
thisBrowser.Navigate(txtAdressSearch.Text)
Else
thisBrowser.Navigate("https://www.google.com/search?sourceid=chrome-psyapi2&rlz=1C1ASAA_enUS445&ion=1&espv=2&ie=UTF-8&q=" + txtAdressSearch.Text)
End If
And here's the newWebBrowser code:
Public Class newWebBrowser
Inherits WebBrowser
Private Sub webBrowserComplete() Handles Me.DocumentCompleted
Dim newTab As TabPage = frmBrowser.Tag()
Dim frmSK As New frmBrowser
Dim hi As String
newTab.Text = Me.DocumentTitle
frmSK.txtAdressSearch.Text = Me.Url.ToString
End Sub
End Class
Any time I enter something into txtAdressSearch, Visual Studio raises a NullRefrenceException and highlights thisBrowser.Navigate(txtAdressSearch.Text). As a side note, it says "Object reference not set to an instance of an object."
Anyone know whats the problem here? Thank you.
After debugging for more than an hour, I looked over my code and saw I was missing a big part of it. I wrote it all in and it worked fine. The issue was the tags weren't being defined correctly (and in some cases, not at all) so .Tag was returning Nothing.
Thanks to all who helped.

How can I load a 'future' forms controls before I use them? Explained in detail:

I am performing a migration on a vb6 program, to vb.net. The basic knowledge you need to understand this question is that there are two forms that need to talk to each other, frmInput1 and frmInput2. I have the following code (behind frmInput1) that checks if a textbox on frmInput2 has a certain value, seemingly before it has loaded:
If frminput2.lblInputMac.Text <> "(no filename)" Then
Dim calc As CalculationCaster = New CalculationCaster
Call calc.FillMac()
cmdNext.Enabled = False
frminput2.FraInner.Enabled = True
I get the following error on the If line when i run it:
"Object reference not set to an instance of an object."
Which i assume means that the object in frmInput2 has not been loaded yet. How can i load frmInput2 before i show it?
Thanks
Nick
frminput2 is probably the implicit global instance of the type frminput2.
If you define a form type in VB6 called MyForm, the platform automatically creates an implicit global variable of the same name MyForm. Whenever you refer to this variable in code, it automatically loads an instance of the form for you.
It's rather as if you had this code.
Public Function MyForm() As MyForm
Static f As MyForm
If f Is Nothing Then
f = New MyForm
End If
Return f
End Function
dim frm1 as new frmInput1
dim frm2 as new frmInput2
At this point, you should be able to communicate between forms without them being displayed. You should not reference forms without explicitly instantiating them.
Create an instance of the form.
Dim f As New frmInput2
Then you can use any properties, methods, or controls on the form.
If f.lblInputMac.Text <> "(no filename)" Then
...
End If