Inserting hyperlink into Word bookmark with AutoHotkey - vba

I have an AutoHotkey script that inserts values into various bookmarks in a Word document.
When inserting a hyperlink (email address), it inserts text. How do I pass it as a hyperlink?
I've read Hyperlinks.Add and tried implementing using the examples but I'm not sure how it translates with AutoHotkey. The examples reference ActiveDocument.
I'm inserting into a created document versus active document.
Relevant portions of my AutoHotkey script:
FilePath := A_Desktop "\Test\MyWordDoc.docx"
wdApp := ComObjCreate("Word.Application") ; Create an instance of Word.
MyDocNew := wdApp.Documents.Add(FilePath) ; Create a new document.
MyDocNew.Bookmarks("CMname").Range.Text := ManagerName
MyDocNew.Bookmarks("CMphone").Range.Text := ManagerPhone
MyDocNew.Bookmarks("CMemail").Range.Text := ManagerEmail
MyDocNew.ExportAsFixedFormat(A_Desktop "\Notice", 17) ; Export out as a PDF.
MyDocNew.Close(0) ; Close the document without saving.
wdApp.Quit()
I tried variations like
MyDocNew.Hyperlinks.Add(MyDocNew.Bookmarks("CMemail").Range, ManagerEmail)

It appears that adding .Item after MyDocNew.Bookmarks works!
Correct script:
MyDocNew.Hyperlinks.Add(MyDocNew.Bookmarks.Item("CMemail").Range, ManagerEmail)

Related

COM in AHK to operate Word. Documents.Activate unpredictable behavior

Following code was supposed to activate Document A upon pressing ^a and Document B upon pressing ^b. Both files already exist and are opened. Sometimes both work, sometimes one does and the other does not, sometimes neither work. The error message reads "bad file name". Adding or removing .docx from the file name has no effect. The first execution of the script after restarting the computer tends to work.
OS: Windows 10.
^a::
wrdApp := ComObjActive("Word.Application") ; Activate MS Word object
wrdApp.Documents("DocumentA").Activate
wrdApp.Visible := true
return
^b::
wrdApp := ComObjActive("Word.Application") ; Activate MS Word object
wrdApp.Documents("DocumentB").Activate
wrdApp.Visible := true
return
^w::
wrdApp.Selection.EndKey(wdStory)
wrdApp.Selection.Range.InsertParagraphAfter
wrdApp.Selection.TypeText("** Here")
return
[Error message][1]
[1]: https://i.stack.imgur.com/rJ0CA.png
For one thing, I think you need to make the Word instance .visible before you can do the .activate and for another, making the Doc active does not bring the Window forward. Use WinActivate after the other stuff. Here's how all that would look:
^a::
wrdApp := ComObjActive("Word.Application") ; Activate MS Word object
wrdApp.Visible := true
wrdApp.Documents("DocumentA").Activate
WinActivate DocumentA
return
But importantly, pls note, DocumentA must exist and be open but not active when you issue the command. Maybe put in a test for that condition. But why aren't you just using WinActivate anyway? With all the WinTitle options and etc., it would seem the most bullet-proof.
EDIT: Since OP said it sometimes works, I conclude my suggestion about the order of the methods is not critical, but rather, probably the doc is already the active one and so the command fails.
Hth,

Executing mailmerge removes all bookmarks. What's the alternative?

So my challange is this.
I've created a Word Macro Enabled Template (MS Word 2016) which creates a document using the MailMerge function using data from an Excel file which colleagues complete.
Once completed, they add in their signature - a scanned jpeg file of their signature from a central network.
My code worked on the principle of attaching to a bookmark, unbeknown to me that when executing a MailMerge, it removes all bookmarks.
I am thinking that if I can change my code after ActiveDocument so that instead of looking for Bookmark it looks for specific text, I can then insert this text in the specific place in the Word template so when the MailMerge is executed it places their signature in that specific [text] place.
Is this possible?
Thanks in advance.
My code is
Sub CurrentUserSignature()
Dim folder As String
folder = "C:\\MacroTemp\\"
Dim path As String
path = folder & Application.UserName & ".jpg"
Dim shape As InlineShape
Set shape = ActiveDocument.Bookmarks("Signature").Range.InlineShapes.AddPicture(path, False, True)
With shape
.LockAspectRatio = msoTrue
.Height = CentimetersToPoints(4.3)
End With
End Sub
`
You could simply insert a borderless single-cell table, a Rich Text Content Control, or a Picture Content Control at the desired location in the mailmerge main document, then access each of those in the output document. If you use a borderless single-cell table, you can give it a fixed height and width so the inserted image's size is automatically constrained to fit.
Where multiple output documents are being produced, each to be signed by the same person, you might do better to insert the signature into the mailmerge main document before execution, then close that without saving changes post-merge.
Alternatively, especially if different records require different signatures and the relevant details can be gleaned from the data source, you can add field coding to the mailmerge main document to automatically add the signature images. See Managing Mailmerge Graphics in the Mailmerge Tips and Tricks thread at:
http://www.msofficeforums.com/mail-merge/21803-mailmerge-tips-tricks.html
or:
http://windowssecrets.com/forums/showthread.php/163017-Word-Mailmerge-Tips-amp-Tricks

Autohotkey runs Excel VBA macro but changes are not applied

I have an Excel file, say Plano.xlsx and I am trying to run a VBA macro script on it using Autohotkey following the instructions stated here.
I don't want the Excel to be visible during this process. The VBA code is supposed to enter the value 99 in the cell C1 at the first sheet.
After hours of trial and error, the Autohotkey script runs smoothly without errors i.e. it opens an Excel process in the background supposedly
editing the Excel file and then exits. The problem is that the Excel file does not change at all. The VBA code works fine if I paste it manually
in a new VBA module in Excel without using Autohotkey.
Here is the code:
#SingleInstance force
#Include Acc.ahk
VBcode=
(
Sub myFunction()
Worksheets(1).Select
Worksheets(1).Range("C1").Select
Selection.Value = 99
End Sub
)
Excel_Run("myFunction")
Excel_Run(sFunction){
FilePath = C:\Users\KostasK\Desktop\Plano.xlsx
oExcel := ComObjCreate("Excel.Application")
Excel_ImportCode(VBcode)
oWorkbook := oExcel.Workbooks.Open(FilePath)
Excel_Get().Run(sFunction)
oWorkbook.Save
oExcel.Quit
}
Excel_ImportCode(VBcode){
if fileexist(A_ScriptDir . "\tempvbcode.txt")
FileDelete, %A_ScriptDir%\tempvbcode.txt
FileAppend, %VBcode%, %A_ScriptDir%\tempvbcode.txt
Excel_Get().ActiveWorkbook.VBProject
.VBComponents.Import(A_ScriptDir . "\tempvbcode.txt")
}
Excel_Get(WinTitle="ahk_class XLMAIN") { ; by Sean and Jethrow, minor modification by Learning one
ControlGet, hwnd, hwnd, , Excel71, %WinTitle%
if !hwnd
return
Window := Acc_ObjectFromWindow(hwnd, -16)
Loop
try
Application := Window.Application
catch
ControlSend, Excel71, {esc}, %WinTitle%
Until !!Application
return Application
}
To get the Acc.ahk library that is included in the script please see here. My Autohotkey version is v.1.1.23.05 and I use Excel 2013. I did not
take a closer look on Excel_Get() function but I used it instead of ComObjActive("Excel.Application") because the latter produces errors. There
is some useful info about that here. Finally, please note that I have enabled the following options in Excel Trust Center:
Enable all macros (not recommended, potentially dangerous code can run) and Trust access to the VBA project object model. Also, in Add-ins section
in COM Add-ins nothing is checked (I don't know if that matters). Finally, I always run the script as administrator.
This can be accomplished simply without VBA macro, while file being closed.
FilePath = C:\Users\KostasK\Desktop\Plano.xlsx
oExcel := ComObjGet(FilePath)
oExcel.Worksheets("Sheet1").Range("C1").VALUE := "99" ; you can put actual sheet name instead "sheet1"
oExcel.Save
oExcel.Quit
oExcel :=

COM (Component Object Model) Insert Comment in MS Office

I have used AHK and COM to do various things inside Microsoft word. For example, I have been able to write a script that finds and replaces or highlights words. However, I have not been able to find documentation on how to use COM to create or delete a comment in office.
I know that https://msdn.microsoft.com/en-us/library/ms178796.aspx is the documentation on how to add comments in C# and VBA, but how would I do this using COM.
When I answered this question I was unable to test the code at the time. I've edited it to better reflect what you asked and demonstrate a working example.
Create a COM Object Word Application
oWord := ComObjCreate("Word.Application")
Create a new Document.
oWord.Documents.Add
Add Text to our document.
oWord.Selection.TypeText("AutoHotkey is a pretty cool scripting language.")
Now lets add our comment
oWord.ActiveDocument.Comments.Add(oWord.ActiveDocument.Paragraphs[1].Range
, "This is a very true statement!.")
Make our document Visible
oWord.Visible := 1
Set a Hotkey to Delete the Comment. (Windows Key + F1)
#F1::oWord.ActiveDocument.Comments(1).Delete

VBA - Documents.Activate function does not work properly

I'm not very used to VBA language, so I come to you for help to solve my problem.
Basically, what I want to do is, while having a MS Word 2010 document opened, open a new one, set the focus on it and do stuff with it.
The problem I'm facing is that I can effectively open the new document, but the .activate function to set the function on it doesn't work, as the instructions following it are still executed in the first document.
Here is my code:
Private Sub BOK_Click()
*...instructions...*
'Opens a new document
Application.Documents.Add
'Select the latest opened document and sets the focus on it
Application.Documents(Application.Documents.Count).Activate
* do stuff *
End Sub
If it may help, the full context is :
I have a main template with 6 pre-filled templates in it, and following the choice of the user (from a drop-down form) it selects the right pre-filled template and opens it in a new Word document, then closed the main template.
What Documents.Add does:
Create a window
Render a copy of the provided (or Normal, in this case) template
Display it in the window
Raise the index of all open documents by 1
Assign index 1 to the newly added document
Bring the window to the front and give focus to it
There's (usually) no need to explicitly activate a document you just added. If you must or want to use Activate, it's best practice to reference a document by it's name, since indexes tend to drift (as described above).
doc1 = ActiveDocument.Name
Documents.Add
doc2 = ActiveDocument.Name
' Do something with document2
Documents(doc1).Activate
' Do something with document1
Documents(doc2).Activate
' Do something with document2 again