We are a group of users of Blackbaud products and are not affiliated with Blackbaud. We'd love to have you join our community to help and be helped in getting the most from your Blackbaud software.
Register now to join us to get independant advice on your system, connect with 3rd party consultants to help you maximize your database and have a real alternative to the official Blackbaud website.
I'm relatively new to RE/VBA and have created a little script that shows a google map for a constituent's primary address as a learning exercise.
I've pasted the code below (feel free to use it or provide feedback) and have a couple of questions about how to make it available in the application:
Q 1. I would like users to be able to run this script when they are viewing a constituent. How do you test to see what the user's 'currently active constituent record' is in RE? I can't seem to find anything on this in the help files.
Q 2. I would like users to be able to run this script by clicking a button (currently they would have to run it by using Tools/Run Macro/System Macros/ScriptName) - is there an easy way to run the script from a toolbar button?
NB We are using RE 7.5 - but I imagine it should work for all versions.
Here is the code:
Code:
Option Explicit
Public Sub DisplayGoogleMap()
Dim ReService As REServices
Set ReService = New REServices
ReService.Init REApplication.SessionContext ' Init the ServiceObject for the search screen
'Create an instance of an IBBSearchScreen object and create the service object bbsoSearchScreen
Dim oSearch As IBBSearchScreen
Set oSearch = ReService.CreateServiceObject(bbsoSearchScreen)
'Create a CRecord object to hold the returned constituent
Dim oRecord As CRecord
Set oRecord = New CRecord
oRecord.Init REApplication.SessionContext
With oSearch
.Init REApplication.SessionContext
.AddSearchType SEARCH_CONSTITUENT 'Look only for constituents
.ShowSearchForm
If .SelectedID > 0 Then
Set oRecord = .SelectedDataObject
' Get the preferred address
Dim strAddress As String
strAddress = oRecord.PreferredAddress.Fields(CONSTIT_ADDRESS_fld_ADDRESS_BLOCK)
If InStr(strAddress, "/") > 0 Then
strAddress = Right(strAddress, Len(strAddress) - InStr(strAddress, "/"))
End If
strAddress = strAddress & ", " _
& oRecord.PreferredAddress.Fields(CONSTIT_ADDRESS_fld_CITY) & " " _
& oRecord.PreferredAddress.Fields(CONSTIT_ADDRESS_fld_STATE) & " " _
& oRecord.PreferredAddress.Fields(CONSTIT_ADDRESS_fld_POST_CODE) & " " _
& oRecord.PreferredAddress.Fields(CONSTIT_ADDRESS_fld_COUNTRY)
' Open the URL in IE
Dim IE As Object
Set IE = CreateObject("InternetExplorer.application")
IE.Visible = True
' Format example = http://maps.google.com/maps?q=13%20Elizabeth%20St%20+Artarmon+New%20South%20Wales+1570+Australia
IE.Navigate "http://maps.google.com/maps?q=" & strAddress
End If
End With
'Clean up the object references
oSearch.CloseDown
Set oSearch = Nothing
oRecord.CloseDown
Set oRecord = Nothing
ReService.CloseDown
Set ReService = Nothing
End Sub
The best way for a user to run the script on a constituent by constituent basis is to write the script that accepts the IBBDataObject as a single parameter. If you then put this in your user or system macros it will appear in the macro button drop down and you can run it from there per constituent.
Code:
Public Sub ShowMap(oRecord As IBBDataObject)
If TypeOf oRecord Is CRecord Then
........
End If
End Sub
When you upgrade to 7.81 you can also implement the IBBMacroProperties interface and select which objects will see this macro and what the name of it is in the drop down and which icon to show (although the last time I tested this it didn't work properly but it may have been fixed by now)
Quote:
How do you test to see what the user's 'currently active constituent record' is in RE?
I am not quite sure what you mean by this. As you can have many constituents open at the same time there is no current as such. You have to simply develop code that works on the current constituent (as the above example shows) or use the active objects in the VBA environment to capture events for the current object.
That was very helpful - picking up the IBBDataObject gave me the current constituent I was after in the second question. My code is now located in the System_Macro module and our staff can use the 'magic macro button' to view maps for their constituents!
I have posted the updated code below if anyone wants to use it:
PS I ended up having to eliminate the 'clean up' bit for the oConstit as I was getting an error about needing to init the oConstit record when I went to close the constituent. Not sure why this was happening!
Code:
Public Sub ShowGoogleMap(oRecord As IBBDataObject)
' Shows a google map of the constituent's preferred address
If TypeOf oRecord Is CRecord Then
Dim oConstit As CRecord
Set oConstit = New CRecord
oConstit.Init REApplication.SessionContext
Set oConstit = oRecord
Dim strAddress As String
strAddress = oConstit.PreferredAddress.Fields(CONSTIT_ADDRESS_fld_ADDRESS_BLOCK) & ", "
' Tidy up address
If InStr(strAddress, "/") > 0 Then
strAddress = Right(strAddress, Len(strAddress) - InStr(strAddress, "/"))
ElseIf InStr(strAddress, "PO Box") > 0 Then
strAddress = ""
End If
strAddress = strAddress & oConstit.PreferredAddress.Fields(CONSTIT_ADDRESS_fld_CITY) & " " _
& oConstit.PreferredAddress.Fields(CONSTIT_ADDRESS_fld_STATE) & " " _
& oConstit.PreferredAddress.Fields(CONSTIT_ADDRESS_fld_POST_CODE) & " " _
& oConstit.PreferredAddress.Fields(CONSTIT_ADDRESS_fld_COUNTRY)
' Open the URL in IE
Dim IE As Object
Set IE = CreateObject("InternetExplorer.application")
IE.Visible = True
IE.Navigate "http://maps.google.com/maps?q=" & strAddress
End If
End Sub
I ended up having to eliminate the 'clean up' bit for the oConstit as I was getting an error about needing to init the oConstit
Hi Mobius,
The general rule of thumb with RE objects is "If you didn't init it, don't close it down". With data object macros (the type of macro you created), RE hands you the object fully init'ed (and in-use) and it expects you to hand it back in the same init'ed state. If you close it down and then hand it back, RE will fail when it goes to use the object. There are a few exceptions to this rule, but for data object macros you can use it pretty reliably.
You are instantiating and init'ing a new constituent object, then you set the object to the constit that was passed in, effectively blowing away the the object you just instantiated. You can safely remove these two lines of code near the beginning:
Code:
Set oConstit = New CRecord
oConstit.Init REApplication.SessionContext