Program example/sample with a good structure
Outlook 2013 addin that create a toolbar and a button on it
Also define a handler to call a sub with the button we added
Once upon a time, I programmed multiple dimension arrays, all numbered and dynamically accessibles by numbers.
A year later I told myself: never again!
Why? Because a program like this is like diving. When you are 30 feet deep, you are comfortable. But when you restart from the top a year later, the descent is long...
So i decided to adopt a standard, a plan to follow, and here it is.
Situation:
You get some code example on internet
You try to run it in visual studio, but a lot of objects are not reconized
Problem:
You are missing libraries (references, dll)
Solution:
Always include comments with what library to include in the code
Example:
'=== this is a addin for outlook 2013
'=== target framework: .net framework 4.5
'=== compile: any cpu
'=== programming: visual studio 2013
'=== references: just default office 15 references and visual studio ones, no custom
'=== software: office 15 (2013) must be installed
'=== software: .net framework 4.5 must be installed but office 2013 requires it anyway
'=== system: windows 7 64 bits sp1
---------------------------------------
Situation:
You have many functions and subs in your program
Problem:
You have to add a parameter to that sub you call because you forgot a situation that just emerged
But you already have 100 lines calling this sub...
You have to change all the line calling it for that
Solution:
use structures variables (vb)
or type variables (scripts)
You pass the structure as parameter to the sub or function
When you add one more parameter, you can reprogram the code inside the sub, but you do not have to change all the lines calling it, they still pass only one structure to the sub
Example:
'=== structure to pass to a function to create a toolbar in outlook
Public Structure bar_param
Dim bar_Exist01 As Integer '=== if bar exist we do not recreate
Dim bar_Caption01 As String '=== name of bar
Dim bar_inexplorer01 As Integer '=== create in main outlook window
Dim bar_ininspector01 As Integer '=== create in message window
End Structure
'=== strucutre to pass to a function to create a button in the bar we created just before
Public Structure but_param
Dim bar_obj As Object
Dim but_exist01 As Integer
Dim but_Caption01 As String
Dim but_tooltip01 As String
Dim but_onaction01 As String
Dim but_face01 As Integer '=== icon
Dim but_inexplorer01 As Integer '=== in main outlook window
Dim but_ininspector01 As Integer '=== in message window
Dim but_bar01 As Object '=== bar to add button to
End Structure
As you can see, but is abbreviation for button
Some poeple would say get a more significative name
But no, we also need clarity of code (and i am too lazy to type long names)
Too much text and you drown in your own code
The number at the end of the parameters are to show that these variables are not system variables, but custom/user made
------------------------------------------
Situation:
Your code is spaghetti
Your main loop is 1000 lines
Problem:
You have no main sub to look at to understand the program with one look
It's all a big pack of lines with lots of exceptions add along the way
You had to do that because you have many global variables used everywhere
Solution:
You main sub should be 1 to 2 screen big
Use functions even if you have to pass them lots of parameters to make them work
Always verify if the function return something
Then your main sub can continue processing only if the functions did return something
Example:
Private Sub ThisAddIn_Startup() Handles Me.Startup
Dim button01 As Office.CommandBarButton
Dim bar01 As Office.CommandBar
Dim objNet = CreateObject("WScript.Network")
'=== get username logon from local machine
usenam = LCase(objNet.UserName)
'====== BAR addition
Dim toolbarcnt = 0
'=== dynamic number of parameters by passing a structure to the function
'=== you can add parameters you want to opass to the functon in structure without modifying the code that call the function
Dim bar_param01 As bar_param
bar_param01.bar_Exist01 = 0
bar_param01.bar_Caption01 = "Hyperzip01"
bar_param01.bar_inexplorer01 = 1
bar_param01.bar_ininspector01 = 0
'=== if we want more toolbars, we extend the array and repeat same thing with a different bar name
bar01 = toolbar_Add(bar_param01)
Dim buttoncnt = 0
Dim but_param01(buttoncnt) As but_param
If Not bar01 Is Nothing Then
'====== buttons creation in explorer (main outlook windows)
In this example, we call a function to create the outlook bar
If the resulting bar (bar01) is nothing we obviously cannot continue and create the buttons on the bar
We create only one bar, so we defined a structure (bar_param01) as one variable, not an array of variables
The next time we use structures as an array containing many buttons parameters to create
We ony have one button here, but we can define the array of parameters to be bigger if we want to create more than one
'====== buttons creation in explorer (main outlook windows)
but_param01(buttoncnt).but_exist01 = 0
but_param01(buttoncnt).but_Caption01 = "HyperZIP"
but_param01(buttoncnt).but_tooltip01 = "Zip des fichiers ou dossiers et envoie un lien de téléchargement"
but_param01(buttoncnt).but_onaction01 = "hyperZIP"
but_param01(buttoncnt).but_face01 = 5432
but_param01(buttoncnt).but_inexplorer01 = 1
but_param01(buttoncnt).but_ininspector01 = 0
but_param01(buttoncnt).but_bar01 = bar01
'=== redim of more buttons to create
'buttoncnt = buttoncnt + 1
'ReDim Preserve but_param01(buttoncnt)
Loop through the array of parameters to create all buttons
For i = 0 To buttoncnt
button01 = button_Add(but_param01(buttoncnt))
If Not button01 Is Nothing Then
'=== button created in a bar
'MsgBox("bar name: " & bar01.name & vbCrLf & "Button name: " & button01.Caption)
'=== every handler must be connected to a sub, so we cant use dynamic name for the call here, we use fixed name hyperzip_click_01
If but_param01(buttoncnt).but_Caption01 = "HyperZIP" Then AddHandler button01.Click, AddressOf hyperzip_click_01
if the button was not created, we will have a fatal error
Else
'=== error the button was not created
MsgBox("WARNING - button (explorer - outlook window) not existing or created" & vbCrLf & but_param01(buttoncnt).but_Caption01 & vbCrLf & "next button")
End If
Next
Else
if the bar was not created we will have a fatal error
'=== error bar was not created
MsgBox("ERROR - fatal - toolbar (explorer - outlook window) not existing or created" & vbCrLf & bar_param01.bar_Caption01 & vbCrLf & "exiting program")
Exit Sub
End If
As you can see, we create a bar, and continue the main sub only if the bar exist
Then we create a button in the bar and continue only if the button exist
As this addin will be called by thoses buttons, there is no need to continue if the bar or the button does not exist after we tried to create it
Debugging:
There is no error trapping, but eventually, there should be only in the lower level sub
If you trap error before calling a function (in main sub), you will never know where the program crash as it will mostly report an error at the line calling the function
(this happen if your function is in another class, in same class, it's usually not a problem)
here is the rest of the code:
Function toolbar_Add(bar_param01 As bar_param) As Office.CommandBar
'=== add a toolbar object in outlook explorer or inspector (message)
'=== with a structure as parameter, we can add as many arguments we want before calling this function without modifying all the line that use it
'=== outlook objects for "complements"
Dim explorer01 As Microsoft.Office.Interop.Outlook.Explorer
Dim inspector01 As Microsoft.Office.Interop.Outlook.Inspector
explorer01 = Globals.ThisAddIn.Application.ActiveExplorer
inspector01 = Globals.ThisAddIn.Application.ActiveInspector
Dim bars01 As Object
If bar_param01.bar_inexplorer01 = 1 Then
'=== 1 = in message
bars01 = explorer01.CommandBars
End If
If bar_param01.bar_ininspector01 = 1 Then
'=== 0 = in outlook (main)
bars01 = inspector01.CommandBars
End If
'=== check if in all bars in a bar with same name exist
For Each bar01 In bars01
If Trim(LCase(bar01.Name)) = Trim(LCase(bar_param01.bar_Caption01)) Then
'bar01.Delete
If InStr(LCase(bar01.Name), "test01") Then
'MsgBox("stas2 found")
End If
bar_param01.bar_Exist01 = 1
toolbar_Add = bar01
End If
Next
'=== add tolbar if not already there
If bar_param01.bar_Exist01 = 0 Then
'=== we are in outlook main window
If bar_param01.bar_inexplorer01 = 1 Then
toolbar_Add = explorer01.CommandBars.Add(bar_param01.bar_Caption01)
ElseIf bar_param01.bar_ininspector01 = 1 Then
'=== we are in a message
toolbar_Add = inspector01.CommandBars.Add(bar_param01.bar_Caption01)
End If
End If
'=== make toolbar visible
If toolbar_Add IsNot Nothing Then
toolbar_Add.Name = bar_param01.bar_Caption01
toolbar_Add.Visible = True
If bar_param01.bar_Exist01 = 0 Then
toolbar_Add.Position = Office.MsoBarPosition.msoBarTop
End If
End If
Return toolbar_Add
End Function
Function button_Add(but_param01 As but_param) As Office.CommandBarButton
'=== add a button in a toolbar
'=== the bar to add the button to is in the parameters structure
'=== compteur de boutons pour pouvoir en ajouter n'importe où dans la matrice
'========================= button in toolbar
'=== outlook objects for "complements"
Dim inspector01 As Microsoft.Office.Interop.Outlook.Inspector
Dim explorer01 As Microsoft.Office.Interop.Outlook.Explorer
explorer01 = Globals.ThisAddIn.Application.ActiveExplorer
inspector01 = Globals.ThisAddIn.Application.ActiveInspector
Dim button01 As Object
'=== delete all buttons in bar
For Each button01 In but_param01.but_bar01.Controls
button01.Delete()
Next
'=== button add
If but_param01.but_inexplorer01 = 1 Then
'=== in outlook main windows
button01 = explorer01.CommandBars(but_param01.but_bar01.name).Controls.Add(Type:=Office.MsoControlType.msoControlButton, Before:=1)
ElseIf but_param01.but_ininspector01 = 1 Then
'=== in message
button01 = inspector01.CommandBars(but_param01.but_bar01.name).Controls.Add(Type:=Office.MsoControlType.msoControlButton, Before:=1)
End If
If Not button01 Is Nothing Then
With button01
'buttons(depnum, 0)
.Caption = but_param01.but_Caption01
.TooltipText = but_param01.but_tooltip01
.Enabled = True
.Visible = True
.OnAction = but_param01.but_onaction01
'.OnAction = "!<" & & ">"
.tag = but_param01.but_Caption01
.Style = Office.MsoButtonStyle.msoButtonIconAndCaption
.FaceId = but_param01.but_face01
'Dim Icon01 = LoadPicture("C:\_stas\outlook\bou_HYPERZIP.bmp")
End With
End If
button_Add = button01
End Function
Private Sub hyperzip_click_01(ByVal ctrl As Office.CommandBarButton, ByRef Cancel As Boolean)
'MsgBox("You clicked: " + ctrl.Caption)
'=== in 2013, you create a class called "form", then create a new object (window aka form) from this class, then use it
Dim form01 As New Form1
'=== show the form
form01.Show()
End Sub
Private Sub ThisAddIn_Shutdown() Handles Me.Shutdown
hyperzip = Nothing
End Sub
End Class