How to display quick part > document property in word using macro? - vba

I have two custom column in quick part mapped from sharepoint edit template.
DocSigner and DSigneromment
Now i have write macro code in word for get all builtinproperties and custom properties. I am able to get all built in document properties like Author ,Title and all but not able to get that custom column using "CustomDocumentProperties"..
Here is my macro code..
Sub ListAllProperties()
Dim rngDoc As Range
Dim proDoc As DocumentProperty
Set rngDoc = ActiveDocument.Content
rngDoc.Collapse Direction:=wdCollapseEnd
For Each proDoc In ActiveDocument.CustomDocumentProperties
With rngDoc
.InsertParagraphAfter
.InsertAfter proDoc.Name & "= "
On Error Resume Next
.InsertAfter proDoc.Value
End With
Next
End Sub
So any code changes that i can get all document property from quick part.

To get the values of properties coming from custom SharePoint columns, use the Document's ContentTypeProperties collection.

#bibadia Thanks a lot for your contribution
Here is finally i have tried for custom property and it works...
Sub ListContentTypeProperty()
Dim signer As String
signer = ActiveDocument.ContentTypeProperties.Item("DocSigner")
MsgBox signer
End Sub

Related

How to reset style in VBA after adding a hyperlink in word

I am using code that I have adapted from here https://wordribbon.tips.net/T000672_Making_Hyperlinks_from_Coded_Text.html to automatically generate hyperlinks in word based on matched text.
I have an issue though, I would like to preserve the original formatting (style) of the selection. The key part of the code which I am trying to get to work is:
Dim my_hyperlink As Hyperlink
Dim curStyle As Object
...
... ' find the text I want to match now apply hyperlink
With Selection
curStyle = .Style
Set my_hyperlink =ActiveDocument.Hyperlinks.Add(Anchor:=Selection.Range,_
Address:="https://example.com",SubAddress:="")
my_hyperlink.Range.Style = curStyle
End With
I am trying to store the current style in curStyle, apply the hyper link and then reset the style.
I am getting the error though "object variable or with block variable not "
Is there some trick to store the style apply hyperlink and then restore the original style?
I can offer two options to do it
Modifying Hyperlink style (once)
Reset font style (after)
Sub OldStyleHyperlinkStyleChange()
Dim my_hyperlink As Hyperlink
'...
'... ' find the text I want to match now apply hyperlink
With ActiveDocument.Styles(wdStyleHyperlink).Font
.ColorIndex = wdAuto
.Underline = wdUnderlineNone
End With
With Selection
Set my_hyperlink = ActiveDocument.Hyperlinks.Add(Anchor:=.Range, _
Address:="https://example.com", SubAddress:="")
End With
End Sub
Sub OldStyleReset()
Dim my_hyperlink As Hyperlink
'...
'... ' find the text I want to match now apply hyperlink
With Selection
Set my_hyperlink = ActiveDocument.Hyperlinks.Add(Anchor:=.Range, _
Address:="https://example.com", SubAddress:="")
my_hyperlink.Range.Font.Reset
End With
End Sub

VBA: Can't change SubAddress property of Hyperlinks in Word Document

I'm trying to fix the hyperlinks in a Word document. I need to change the SubAddress property of some hyperlinks. To that end, I'm looping through them. Unfortunately, I get a very weird error saying method 'subaddress' of object 'hyperlink' failed when I try to change any SubAddress. Apparently this happens because something is broken with VBA itself.
Sub FixHyperlinks()
'
' FixHyperlinks Macro
'
'
ActiveDocument.Hyperlinks(1).SubAddress = "some new subaddress"
End Sub
I'm rocking Office 2016 Professional Plus. Can anybody tell me if this works for you?
It's easy to test. Just create a new document, type two one-word lines. Make the second line style "Heading 1". Go to first line, hit CTRK + K (to create hyperlink) point it to "a place in this document", select the heading you just created. DO NOT enter any address. Now go to Macros, paste the above and hit F5 while your caret is inside the code.
The hyperlink works fine when clicked with the mouse (first line hyperlink will take you to the 2nd line Heading).
Although Hyperlink.SubAddress Property is supposed to be a read/write string, writing to it fails - even in Word 2010. Try something along the lines of:
Dim Rng As Range, StrAddr As String, StrTxt As String
With ActiveDocument
With .Hyperlinks(1)
Set Rng = .Range
StrAddr = .Address
StrTxt = .TextToDisplay
.Delete
End With
.Hyperlinks.Add Anchor:=Rng, Address:=StrAddr, SubAddress:="new_sub_address"
End With

Update all fields in a Word document when user types anything

I want a way of updating all the fields on a document automatically. I currently have a macro which is linked to F9. This macro updates all the fields in the header and footer, as well as all the ones in the main document.
Sub UpdateFields()
Dim oStory As Range
For Each oStory In ActiveDocument.StoryRanges
oStory.Fields.Update
If oStory.StoryType <> wdMainTextStory Then
While Not (oStory.NextStoryRange Is Nothing)
Set oStory = oStory.NextStoryRange
oStory.Fields.Update
Wend
End If
Next oStory
Set oStory = Nothing
End Sub
Apart from setting the macro on every key, how would I make it so this macro runs when the user types anything?
For example a user may place a field in the footer or header which shows the amount of characters. If this was the case I would like to be able to see the characters field update as I type.
Here are the events in Word VBA :
For the application :
https://msdn.microsoft.com/EN-US/library/office/dn320473.aspx
For the document :
https://msdn.microsoft.com/EN-US/library/office/dn320613.aspx
I would suggest that you use the Application.WindowSelectionChange event (Occurs when the selection changes in the active document window) : https://msdn.microsoft.com/EN-US/library/office/ff192791.aspx
Public WithEvents appWord As Word.Application
Private Sub appWord_WindowSelectionChange(ByVal Sel As Selection)
UpdateFields
End Sub
And if you need more details on that, you'll find some here : https://msdn.microsoft.com/library/office/ff746018.aspx

How do I specify "where" when using the insert method for build blocks in word 10

I'm trying to add a custom building block at the click of a button in MS word 10. Below is the code currently attached to my activeX button.
Private Sub CommandButton1_Click()
Dim objTemplate As Template
Dim objBB As BuildingBlock
' Set the template to store the building block
Set objTemplate = ActiveDocument.AttachedTemplate
' Access the building block through the type and category
Set objBB = objTemplate.BuildingBlockTypes(wdTypeCustom5) _
.Categories("General").BuildingBlocks("Experience")
' Insert the building block into the document replacing any selected text.
objBB.Insert Selection.Range
End Sub
My problem is, as this code is invoked at the click of a button, the button becomes the "Selection.Range" and is thus replaced. I looked all around for alternate codes that mention of different "where" specification and found nothing.
I only found two links(can't find the urls in my history rightnow, will update shortly)
It mentioned "Paragraphs(1)" instead of "Selection.Range", but this
is an absolute location while I would need something relative
(Before the button)
Using InsertBefore method which I suppose applies only to text (it
was used to insert text in the example) as when I tried it for
building blocks it didnt work
P.S I'm relatively new to VBA
Ok, I solved the problem with the following code, posting it for others who might drop by in the future.
Private Sub CommandButton1_Click()
Dim objTemplate As Template
Dim objBB As BuildingBlock
' Set the template to store the building block
Set objTemplate = ActiveDocument.AttachedTemplate
' Access the building block through the type and category
Set objBB = objTemplate.BuildingBlockTypes(wdTypeCustom5) _
.Categories("General").BuildingBlocks("Experience")
' Insert the building block into the document replacing any selected text.
Selection.MoveUp Unit:=wdLine, Count:=1
objBB.Insert Selection.Range
End Sub
Basically just added the following lines just before inserting the BuildingBlock
Selection.MoveUp Unit:=wdLine, Count:=1
Thanks everyone for the assistance.
When in "Creation mode", goto the "properties" toolbox of your CommandButton1, change the property TakeFocusOnClick from True to False:
The focus will stay onto the paragraph you selected.
If you want it just after your CommandButton you can add the following at the end of your sub:
...
CommandButton1.Select
Selection.HomeKey wdLine
objBB.Insert Selection.Range
End Sub

Return different values from a vba user form depending on the button pressed

I have been creating an acronym finding macro that will sit on a custom toolbar in word. When run it searches the document for acronyms and places them in a table. I want to include some user forms so that as the macro finds an acronym the user can select the predefined definition (got from an excel document) or enter their own new one (I know multiple acronyms meanings is frowned upon but it happens).
Anyway I am stuck. I have created a user form with three buttons. A text input and a label. Now I have managed to set the label text with the acronym that was found however I can't seem to get the buttons to change a variable, userChoice, and if applicable save the newly entered definition.
below is the test macro i have been trying this out on
Sub userFormTest()
Dim objExcel As Object
Dim objWbk As Object
Dim rngSearch As Object
Dim rngFound As Object
Dim targetCellValue As String
Dim userChoice As Integer
Set objDoc = ActiveDocument
Set objExcel = CreateObject("Excel.Application")
Set objWbk = objExcel.Workbooks.Open("C:\Users\Dave\Documents\Test_Definitions.xlsx")
objExcel.Visible = True
objWbk.Activate
With objWbk.Sheets("Sheet1")
Set rngSearch = .Range(.Range("A1"), .Range("A" & .Rows.Count).End(-4162))
Set rngFound = rngSearch.Find(What:="AA", After:=.Range("A1"), LookAt:=1)
If rngFound Is Nothing Then
UserForm1.Label1.Caption = "Acronym: AA" & vbCr & _
"Definition: Not found, please enter a definition below" & vbCr & _
" or choose to ignore this acronym"
UserForm1.Show
'an if statement here so that if the add button was pressed it adds to doc etc
Else
targetCellValue = .Cells(rngFound.Row, 2).Value
UserForm2.Label1.Caption = "Acronym: AA" & vbCr & _
"Definition: " & targetCellValue
UserForm2.Show
'an if statement here so that if the add button was pressed it adds to doc etc
End If
End With
objWbk.Close Saved = True
Set rngFound = Nothing
Set rngSearch = Nothing
Set objWbk = Nothing
objExcel.Visible = True
Set objExcel = Nothing
Set objDoc = Nothing
End Sub
I do realise that this could be done in the button_click() subs however I already have all the documents open etc in the other macro. Or is it possible to link to those already open documents? To be honest either way I would prefer to return to the main macro and just use the form to the user input.
I do realise that this could be done in the button_click() subs. However I already have all the documents open etc in the other macro. Or is it possible to link to those already open documents?
You can definitely link between button_click() subs and your main macro to modify the value of userChoice.
Answer:
What you need is some userform element (like a textbox) that can hold your value so you can refer back to it in your main macro. It looks like you already have this element (based upon your caption "Not found, please enter a definition below"). Let's say that element is a TextBox called Definition. Then let's say you want to return to the main macro after people push an "Add" button, as it appears you do (based upon your comment "so that if the add button was pressed it adds to doc").
In each of both Userform1 and Userform2, you would want something like this:
Private Sub AddButton_Click()
Userform1/Userform2.Hide
End Sub
That would return you to your main macro, where you could follow up with:
If Userform1/Userform2.Definition.Value = Whatever Then
'if the add button was pressed it adds to doc etc
End If
right where your existing comments are. Note that you could set userChoice = Userform1.Definition.Value here, but you don't need to because Userform1.Definition.Value already contains the information you need to track.
Additional material:
Rather than using the default instance of your Userform1 and Userform2 by using .Show on them immediately without assigning new instances of them to variables, may I suggest creating Userform variables to contain New instances of them like this:
Dim UnknownDefinition As Userform1
Set UnknownDefinition = New Userform1
UnknownDefinition.Show
Or if you want to get really optimal, you could follow more of the approach recommended here on how to make a properly instanced, abstracted userform:
Rubberduck VBA: How to create a properly instanced, abstracted userform
And now with bonus quotes from the post's author, #Mathieu Guindon:
make Definition a proper property, with the Property Let mutator changing the label value on top of changing its private backing field's value; avoid accessing form controls outside the form, treat them as private even if VBA makes them public.
Calling code wants data, not controls. You can extract properties/data, but not controls, into a dedicated model class.