Add hyperlink into Word Content Control with VBA - vba

I have a Word 2010 template. When used, a form is presented to the user and they are prompted to enter a string in a textbox named BugNumTextBox. Upon command, I wish to construct a URL, create a hyperlink, and insert that into the document.
The desired insertion point (anchor) is a Rich Text Content Control with a tag name of "foo".
For the address parameter I have attempted:
1) To specify the range of the content control
2) To specify the range of a bookmark (named BugNum) that I created inside of the content control.
Neither have worked, resulting in run-time errors.
Can anyone suggest a method to achieve this?
Below is a non-working example of method 2 above.
ActiveDocument.Hyperlinks.Add Anchor:=.Bookmark("BugNum").Range, Address:= _
"http://bugs.fubar.net/show_bug.cgi?id=" & BugNumTextBox, _
SubAddress:="", ScreenTip:="", TextToDisplay:=""
Thank you much.

Why don't you access the ContentControls Object Collection instead.
Something like:
Dim ccRtxt As ContentControl
Set ccRtxt = ActiveDocument.ContentControls(1)
ccRtxt.Range.Hyperlinks.Add ccRtxt.Range, _
"http://stackoverflow.com/questions/26538906/" & _
"add-hyperlink-into-word-content-control-with-vba"
Above will work on the scenario you describe where you only have 1 ContentControl.
If you have many such objects, you can do this:
Dim ccRtxt As ContentControl
For Each ccRtxt In ActiveDocument.ContentControls
If ccRtxt.Tag = "foo" Then
ccRtxt.Range.Hyperlinks.Add ccRtxt.Range, _
"http://stackoverflow.com/questions/26538906/" & _
"add-hyperlink-into-word-content-control-with-vba"
End If
Next
This adds this question as hyperlink address in your Rich Text Content Control.
You can adjust the address property to suit your needs. HTH.

Related

How to make a textbox receive changes from comboboxes and another textbox?

Essentially I am taking the inputs from these ComboBoxes shown below:
Along with the changes from this textbox:
And place both of these changes towards another, sole textbox. For instance, if I have my file name format adjusted the following way from the first screenshot, and I type in my client/company name as "apples", the textbox for "File Name" should output to this:
I want the user to type in their preferred "client name" and make my program add those changes automatically, without compromising the values/inputs from the ComboBoxes and "Client Name". I tried to look online for something like this, but the solutions provided made very little sense, or were just too confusing for me to understand. Any help will be greatly appreciated!
This is fairly broad; there are many ways it could be solved but I think I'd make it fairly simple:
I'd have the comboboxes in a list in left to right order:
Dim combos = { combobox1, combobox2, combobox3, combobox4, combobox5, combobox6 }
I'd have the replacements in a dictionary in any order, so this Dictionary is essentially a list of KeyValuePairs, the Key is what we find, and the Value is what we replace it with:
Dim repl = New Dictionary(Of String, String) From _
{ _
{"Client Name", _companyClientName.Text}, _
{"Month", DateTime.Now.ToString("MMM")}, _
{"Year", DateTime.Now.ToString("yyyy")}, _
{"Please Select", ""} _
}
And perform a set of replacements in a loop:
filenameTextBox.Clear()
For Each c as ComboBox in combos
'to track if we perform any replacement
Dim changed = False
'for each r in the list of replacements
For Each r as KeyValuePair(Of String, String) in repl
'if the text in the combo is something we replace
If c.Text = r.Key Then
'append a replacement-performed version
fileNameTextBox.AppendText(c.Text.Replace(r.Key, r.Value))
changed = True 'track that we made a change
Exit For 'don't make any more replacements
End If
End For
'if we didn't change anything, just put the text of the combo in literally
If Not changed Then fileNameTextBox.AppendText(c.Text)
End For
All this code would go in a method and then event handlers for "combo selected item changed" and/or "company name text box text chnaged" would call the method

Getting .value property when using a string and variable

I am creating a form in Access which will be used as an order sheet for classroom materials. I have the available resources listed and a text box next to the resource where the user inputs the quantity they desire.
My VBA code checks to see if any entries have been made by using the following. (I am using Nz() to allow for Null results):
QuantCheck = Nz(Box1.Value, 0) + Nz(Box2.Value, 0) + Nz(Box3.Value, 0)
Where "QuantCheck" is the variable I am using in the IF statement which begins the workflow:
If QuantCheck > 0 Then
I would like to clean this up by using some kind of loop statement, however I am not able to extract the .value from a string. I would love something like the following which I could incorporate into a loop:
"Box"&VariableNumber.Value
From what I can tell, I am not able to use a string (concatenated or otherwise) as the base for the .value call.
It is interesting that there is a way to accomplish this when using a SQL statement. I have this elsewhere in the code which works nicely:
SQLStr = "INSERT INTO OrderRequests VALUES (cbSchool, txtName, Title" & x & ".caption, Box" & x & ")"
Here I have a variable "x" which increases with each loop to change the Title line, and the Box line.
Any help is appreciated.
I suggest you use the Tag property of the controls. Put "QuantCheck" in the Tag property of any control you want to include. Then
Function QuantitiesExist(frm As Form) As Boolean
Dim Ctrl As Control
Const sQUANTCHK As String = "QuantCheck"
For Each Ctrl In frm.Controls
If Ctrl.Tag = sQUANTCHK Then
If Nz(Ctrl.Value) > 0 Then
QuantitiesExist = True
Exit For
End If
End If
Next Ctrl
End Function
Now you get self documenting code
If QuantitiesExist(Me) Then
And when you add/delete/change controls, you don't have to edit your code. Just set up new controls with the proper tags.
You could loop through the control on the for checking the names and then if it is the one you wanted take an action on it, is this what you was thinking of?
Dim Ctrl As Control
For Each Ctrl In Me.Controls
If Ctrl.Name = "TxtPath" Then ' "Box" & VariableNumber Then
MsgBox Ctrl.Value
End If
Next

Identify which ribbon control was clicked from a macro (MS Word VBA)

I have several macros that all do near identical things: each one opens a separate file. I have them activated through controls on a customized ribbon. But instead of having several macros that look like this:
ChangeFileOpenDirectory SeriesPath
Documents.Open FileName:="Doc1.docx", _
ConfirmConversions:=False, ReadOnly:=False, AddToRecentFiles:=False, _
PasswordDocument:=Password$, PasswordTemplate:="", Revert:=False, _
WritePasswordDocument:="", WritePasswordTemplate:="", Format:= _
wdOpenFormatAuto, XMLTransform:=""
but with only the filename changed, I'd like to have one macro that can open any one document depending on which ribbon element was clicked. Problem is, I need to know the ID of the ribbon element that was clicked. I've been through several web sites that all suggest using the IRibbonUI.ID property, but when I try that, I get an error message from Word: "Runtime error 91: Object variable or With block variable not set."
Here's a sample of the exported XML code for my ribbon:
<mso:button idQ="x1:Open_00_1_549FAC6" label="00" imageMso="BlackAndWhiteDontShow" onAction="Open_00" visible="true"/>
<mso:button idQ="x1:Open_01_10_549FAC6" label="01" imageMso="AppointmentColor0" onAction="Open_01" visible="true"/>
<mso:button idQ="x1:Open_02_9_549FAC6" label="02" imageMso="AppointmentColor1" onAction="Open_02" visible="true"/>
<mso:button idQ="x1:Open_03_8_549FAC6" label="03" imageMso="AppointmentColor2" onAction="Open_03" visible="true"/>
Does anyone know what I'm doing wrong?
First, please excuse any syntax errors, these answers are in psuedo vba/xml.
1) I would suggest using the id parameter of the ribbon control object to determine the callee, instead of using a different function. You could possibly rename them to something more clean such as:
idQ="x1:Open_00" label="00" ... onAction="Open_OnAction"
idQ="x1:Open_01" label="01" ... onAction="Open_OnAction"
2) You can then 'parse' based on the ID, or just do a case/switch statement on the entire ID
Sub Open_OnAction(control As IRibbonControl)
Dim filename As String
Select Case control.id
Case "x1:Open_00"
filename = "somefilename00.xml"
Case "x1:Open_01"
filename = "somefilename01.xml"
End Select
'The rest of your code here
End Sub
*Note: If you wanted to be even more slick, you could put filename into the ID (via XML), and not even use a case statement, and parse it out. EG:
idQ="Open_myfilenamepathhere" ... onAction="Open_OnAction"
Sub Open_OnAction(control As IRibbonControl)
Dim filename As String
'This splits the control into multiple array elements based on delimeter of "_", then grabs the 2nd element (since the array's first element is 0)
filename = Split(control.id,"_")(1)
'The rest of your code here
End Sub

Word CheckBox ContentContol OnChange Event

I try to make a word document with two checkboxes where each checkbox will show/hide a part of the document with a custom style.
I plan to set value Style.Font.Hidden = True/False depending from checkbox values, but...
I found that there are 3 types of controls:
Legacy Controls - This seems old the ugly.
ActiveX Controls - I can easyly attach to checkbox onChange events, but these are also ugly and I think it's not that secure, also this is probably now working on mac.
ContentControls - This seems like the right way to do this, but I just can't attach to the right event. (Also there is some XML attachment described, but I'm not using this, this seem too complicated, I don't know.)
Can you tell me how to atach to onChange event of CheckBox ContentContol? I need the same behaviour like it's ActiveX CheckBox.
Content Controls do not have "onChange" events, so you can't get a content control to behave like the ActiveX checkbox in a simple manner. Similarly to form fields, the code for ContentControls fires when the control is entered/exited.
The only way to emulate "onChange" for a Content Control is to link the content control to a node in a CustomXMLPart in the document then work with the Document_ContentControlBeforeStoreUpdate event that triggers when the content of the node in the CustomXMLPart is going to be changed.
If, as your question indicates, this is too complex for your purposes you could use a MacroButton field that displays a font character (Symbol) that looks like a checkbox. Clicking the field would exchange that character for a different one, that looks checked. And the reverse again for the next click. Here's some sample code to get you started. If you don't like the checkboxes I chose, you can pick something else from Insert/Symbols/Symbol. Just change the character numbers and the font name.
By default a MacroButton field triggers on double click. You can change this to a single click when the document is opened in an AutoOpen macro.
Sub AutoOpen()
Application.Options.ButtonFieldClicks = 1
End Sub
Sub ToggleCheckBox()
Dim iNotChecked As Integer, iChecked As Integer
Dim rngCheck As word.Range
Dim sBkmName As String, sFontName as String
iNotChecked = 111
iChecked = 253
sBkmName = "bkmCheck"
sFontName = "Wingdings"
Set rngCheck = ActiveDocument.Bookmarks(sBkmName).Range
If Asc(rngCheck.Text) = iNotChecked Then
rngCheck.Text = Chr(iChecked)
ActiveDocument.Bookmarks.Add sBkmName, rngCheck
rngCheck.Font.Name = sFontName
ElseIf Asc(rngCheck.Text) = iChecked Then
rngCheck.Text = Chr(iNotChecked)
rngCheck.Font.Name = sFontName
ActiveDocument.Bookmarks.Add sBkmName, rngCheck
End If
End Sub

VBA Code to change font and size in an email from access

I have an access form that runs a query. There is a command button on the form that I want to send an email with the query results attached in an excel spreadsheet. Using the code below I am able to attach the results and send the email ok. I would like to be able to format the email body so that it is more noticeable. I'm not really sure how to go about doing this and still have my query attached. I have also created an email template that I would use but I haven't been able to figure out how to use the template and attach the query results. I'm open for any suggestions. Any help would be greatly appreciated.
DoCmd.SendObject acQuery, "BoxOrder", "ExcelWorkbook(*.xlsx)", "me#home.com", _
"John#hishome.com", "", "BOX ORDER", _
"ALL BOXES STITCHED" & vbCrLf & "Questions: Please Call Me" & _
vbCrLf & "555-555-5555 x 66654", True, True
You could follow the Article from MS.
A proportion of the code is as follows:
Set ola1 = New Outlook.Application
Set mai1 = ola1.CreateItem(olMailItem)
mai1.To = strTo
mai1.Subject = strSubj
If bolHTML = True Then
mai1.HTMLBody = strBody
Else
mai1.Body = strBody
End If
mai1.Display
If you use the HTML (set bolHTML = True) version you can either have an RTF control on a Form and pass the formatted text over or hardcode your HTML with the formatting you need. Just set the "strBody" to the message you want.
Then you need to look into the Attachments.Add (MS Article) if you want to use the above code with your original purpose.
There's a full 599CD Email Seminar you could follow if you're going to be doing a lot with Email in Access.