How to use embedded dotx in Word.Documents.Add() from Excel? - excel

I want to embed a word template in an Excel workbook so that the user can click on a generate report button and have word open a new document using the word template.
The below code directly edits the dotx and allows changes to be made to the template, which is undesirable as the template contains formatting and markup that supports the auto-report generation.
Public Sub ExportReportEmbedded()
Set curSheet = ActiveSheet
Application.ScreenUpdating = False
Dim wdApp As Word.Application, wdDoc As Word.Document
Set ole = Sheets("Report").Shapes("Object 4").OLEFormat
ole.Activate
' rather than activating it, I want to use the dotx in a new Word.Documents.Add().
' But how?
' wdApp.Documents.Add(ole.???)
curSheet.Activate
Set wdDoc = ole.Object.Object
Set q = Sheets("Report")
With wdDoc.ContentControls
For i = 1 To 62 Step 1
.Item(i).Range.Text = q.Range("b" & i)
Next
End With
Application.ScreenUpdating = True
End Sub

The below code directly edits the dotx and allows changes to be made to the template, which is undesirable as the template contains formatting and markup that supports the auto-report generation.
To directly answer your question, you can open the embedded Dotx in the following way so that the template itself is not opened but another word document based on the template.
Hope this is what you wanted?
Sub Sample()
Dim shp As Shape
Set shp = Sheets("Report").Shapes.Range(Array("Object 4"))
shp.Select
Selection.Verb Verb:=xlPrimary
End Sub
FOLLOWUP
Try this. I am using the GetTempPath API to get the user's temp folder and then saving the embedded document to that folder. Once the document is saved then I am using the .Add to create the new file. Also I am using Late Binding with MS Word so you do not need to set any references to MS Word Object Library. Do let me know if you have any queries :)
Private Declare Function GetTempPath Lib "kernel32" _
Alias "GetTempPathA" (ByVal nBufferLength As Long, _
ByVal lpBuffer As String) As Long
Public Sub ExportReportEmbedded()
Dim oWordApp As Object, oWordDoc As Object, objWord As Object
Dim FlName As String
Dim sh As Shape
Dim objOLE As OLEObject
'~~> Decide on a temporary file name which will be saved in the
'~~> users temporary folder
FlName = GetTempDirectory & "\Template.dotx"
Set sh = Sheets("Report").Shapes("Object 4")
sh.OLEFormat.Activate
Set objOLE = sh.OLEFormat.Object
Set objWord = objOLE.Object
'~~> Save the file to the relevant temp folder
objWord.SaveAs2 fileName:=FlName, FileFormat:=wdFormatXMLTemplate
'~~> Establish an Word application object
On Error Resume Next
Set oWordApp = GetObject(, "Word.Application")
If Err.Number <> 0 Then
Set oWordApp = CreateObject("Word.Application")
End If
Err.Clear
On Error GoTo 0
oWordApp.Visible = True
'~~> Create new document based on the template
Set oWordDoc = oWordApp.Documents.Add(Template:=FlName, NewTemplate:=False, DocumentType:=0)
'~~> Close the actual template that opened
objWord.Close savechanges:=False
'~~> Rest of the code
'~~> now you can work with oWordDoc. This will not save the actual template
'~~> In the end Clean Up (Delete the template saved in the temp directory)
Kill FlName
End Sub
'~~> Function to get the user's temp directory
Function GetTempDirectory() As String
Dim buffer As String
Dim bufferLen As Long
buffer = Space$(256)
bufferLen = GetTempPath(Len(buffer), buffer)
If bufferLen > 0 And bufferLen < 256 Then
buffer = Left$(buffer, bufferLen)
End If
If InStr(buffer, Chr$(0)) <> 0 Then
GetTempDirectory = Left$(buffer, InStr(buffer, Chr$(0)) - 1)
Else
GetTempDirectory = buffer
End If
End Function

Related

Copy content of Excel attachment in Outlook VBA without saving the file

I get 50 mails with Excel sheets per day. I want to add the first line of each Excel sheet to an existing Excel sheet located on my computer.
I know how to save a file from an email, and then access the first line. I would like to directly access it, without having to save the file.
Something like this:
Sub Merge_Reports(itm As Outlook.MailItem)
Dim wb_path As String
Dim app_master As Object
Dim wb_master As Object
Dim ws_master As Object
Dim objAtt As Outlook.Attachment
Dim ws_email As Object
Dim content As String
wb_path = "\\swi56prof01\UserData$\heinreca\Documents\Outlook-Dateien\AllData.xlsx"
Set app_master = CreateObject("Excel.Application")
Set wb_master = app_master.Workbooks.Open(wb_path)
Set ws_master = wb_master.Sheets(1)
For Each objAtt In itm.Attachments
Set ws_email = objAtt.Sheets(1)
content = ws_email.Cells("A1")
ws_master.Cells("A1") = content
End Sub
I am struggling with ws_email = objAtt.Sheets(1). I get the error
object doesn't support this property or method
I tried this instead of the line that results in the error.
Set app_email = CreateObject("Excel.Application")
Set wb_email = app_email.Workbooks.Open(objAtt)
Set ws_email = wb_email.Sheets(1)
I don't know what objAtt is in terms of data type and how to address the worksheet, so that I can copy the first line from it.
I found Copy Contents of Outlook Attachment and that I have to save the file before accessing it. Is there no other way?
There is no way to access the workbook without saving it to the disk. After saving the attached file to the disk you can use the same code:
Set wb_master = app_master.Workbooks.Open(wb_path)
Set ws_master = wb_master.Sheets(1)
where wb_path is the file path of your saved attachment (Excel file).
The Attachment.SaveAsFile method saves the attachment to the specified path. For example:
Sub SaveAttachment()
Dim myInspector As Outlook.Inspector
Dim myItem As Outlook.MailItem
Dim myAttachments As Outlook.Attachments
Set myInspector = Application.ActiveInspector
If Not TypeName(myInspector) = "Nothing" Then
If TypeName(myInspector.CurrentItem) = "MailItem" Then
Set myItem = myInspector.CurrentItem
Set myAttachments = myItem.Attachments
'Prompt the user for confirmation
Dim strPrompt As String
strPrompt = "Are you sure you want to save the first attachment in the current item to the Documents folder? If a file with the same name already exists in the destination folder, it will be overwritten with this copy of the file."
If MsgBox(strPrompt, vbYesNo + vbQuestion) = vbYes Then
myAttachments.Item(1).SaveAsFile Environ("HOMEPATH") & "\My Documents\" & _
myAttachments.Item(1).DisplayName
End If
Else
MsgBox "The item is of the wrong type."
End If
End If
End Sub

Find and copying text highlighted in a specific color

Hi I have a code (see below) that is working like a charm to find and copy text from a specific style and paste it in another document. It is in an excel file because I preferred this option to share with friends that would only need to click in the button, chose the input file and save as their preferred output file name.
Now I'm trying without success to perform the same task with text highlighted in a specific color (e. Turquoise). Please find below the code that is working with a specific word or style, I made some experiences with code I found here and there, but all I could get was to copy all highlighted text instead of my choice of color. See below. Any help is much appreciated.
Note on Edit: The code below is the closer I get to the desired result. It was a little chaotic due to my try and error attempts.
' Objects
Dim wrdApp, objWord As Object
Dim wrdDoc, newwrdDoc As Object
Dim myPath As String, myPath1 As String
Dim folderPath As String
Dim myFile As String
Dim numberStart As Long
Dim Rng, srchRng As Excel.Range
'Dim objDoc As Document, objDocAdd As Document
Dim objRange As Range
Dim strFindColor As String
Dim highliteColor As Variant
Dim i As Long
' Close MS Word if it's already opened
On Error Resume Next
Set objWord = GetObject(, "Word.Application")
If Not objWord Is Nothing Then
objWord.Quit SaveChanges:=0
Set objWord = Nothing
End If
'Defining input file name
myFile = Application.GetOpenFilename()
'Open MS Word
Set wrdApp = CreateObject("Word.Application")
wrdApp.Visible = True
' Folder Location
myPath = Application.ThisWorkbook.Path & "\"
' Input File
Set wrdDoc = wrdApp.Documents.Open(myFile)
' Output File
Set newwrdDoc = wrdApp.Documents.Add
myPath1 = Application.GetSaveAsFilename(FileFilter:="Word files(*.docx),*.docx")
' Text you want to search
'Dim FindWord As String
'Dim result As String
'FindWord = ""
highliteColor = Array(wdTurquoise)
'Style
'mystyle = wdTurquoise
'Defines selection for Word's find function
wrdDoc.SelectAllEditableRanges
' Find Functionality in MS Word
For i = LBound(wdTurquoise) To UBound(wdTurquoise)
objDoc.Activate
Selection.HomeKey Unit:=wdStory
objRange.Collapse wdCollapseEnd
With wrdDoc.ActiveWindow.Selection.Find
.HighlightColorIndex = wdTurquoise
.Highlight = True
.Forward = True
.Wrap = wdFindStop
objRange = Selection.Range
objDocAdd.Range.InsertAfter objRange & vbCr
Selection.Collapse wdCollapseEnd
End With
Next
' Execute find method
wrdDoc.ActiveWindow.Selection.Find.Execute
' Store Selected text
result = wrdDoc.ActiveWindow.Selection.Text
' Check if result contains non-blank text
If Len(result) > 1 Then
' -------------------------------------------------------------
' Loop through multiple find content (Find All functionality)
' -------------------------------------------------------------
While wrdDoc.ActiveWindow.Selection.Find.Found
wrdDoc.ActiveWindow.Selection.Copy
'Activate the new document
newwrdDoc.Activate
'New Word Doc
Set Rng = newwrdDoc.Content
Rng.Collapse Direction:=wdCollapseEnd
Rng.Paste
'Word Document
wrdDoc.Activate
wrdDoc.ActiveWindow.Selection.Find.Execute
Wend
' If style not found
Else
MsgBox "Text Not Found"
End If
'Close and don't save application
wrdDoc.Close SaveChanges:=False
'Save As New Word Document
newwrdDoc.SaveAs myPath1
newwrdDoc.Close SaveChanges:=True
'Close all word documents
wrdApp.Quit SaveChanges:=0
'Message when done
MsgBox "Task Accomplished"
End Sub

Select Word Doc using Excel VBA

I want to create Excel VBA code that asks the user to open a pre-existing Word document with text form fields and input existing Excel data in these form fields.
I have code that writes the Excel data into the Word text form field.
Sub NewMacro()
Dim wdApp As Object, wd As Object, ac As Long, ws As Worksheet
Set ws = Sheets("Tables")
On Error Resume Next
Set wdApp = GetObject(, "Word.Application")
If Err.Number <> 0 Then
Set wdApp = CreateObject("Word.Application")
End If
On Error GoTo 0
Set wd = wdApp.Documents.Open("C:\Test\Test.docx")
wdApp.Visible = True
With wd
.FormFields("CustomerName").Result = ws.Range("D4").Value
End With
Set wd = Nothing
Set wdApp = Nothing
End Sub
I am lost as to converting the Set wd= wdApp.Documents.Open("FilePath") line into a dialog box.
Does a function exist where the user can select the file by clicking through Windows Explorer as opposed to typing the path?
Do you want the user to input the name of a Word file? Do you want the InputBox method?
Dim strWord As String
strWord = InputBox(prompt:="Type the file path and name of the Word file.", title:="Which file?", default:="C:\Path\File.docx")
Set wd = wdApp.Documents.Open(strWord)
Tell me if I didn't understand your question.

Unable to edit custom field in word through excel 2016 VBA

I have been struggling quite a bit with trying to get this to work. I have an Excel workbook that contains information for clients. I want to click a button that runs a macro that takes a word document--a template--and update the fields in the template according to the data stored in the Excel workbook (i.e. I want the "client" custom property field in the template to change its value to "John Smith").
I am able to open the word document fine, and have had some success in updating the fields from word VBA, but I have not been able to get excel vba to update the fields of the word document. The error i get is 4248, ~"no document is open", which occurs at the for loop. If I place the for loop inside the OpenWordDoc, I still get the 4248 error. Any help is appreciated.
Here is the code I have been working with:
Sub GenDraftLetter()
Dim i As Long
Dim j As Double
Dim k As Object
Dim filenam As String
Dim prop As DocumentProperty
Dim oppname As String
Dim clientname As String
Dim objWord As Object
Dim ow As Window
Dim wd As Object
Dim fwd As Object
Set objWord = GetObject(, "Word.Application")
If objWord Is Nothing Then
Set objWord = CreateObject("Word.Application")
End If
i = InputBox("Number of row for the Client", "Row for Client")
j = 1
Do Until Mid(Cells(i, 1), j, 1) = ","
j = j + 1
Loop
clientname = Right(Cells(i, 1), Len(Cells(i, 1)) - j - 1) & " " & Left(Cells(i, 1), j - 1)
filenam = "template.docx"
OpenWordDoc (filenam)
For Each prop In ActiveDocument.CustomDocumentProperties
If LCase(prop.Name) = "client" Then
prop.Value = clientname
Exit For
End If
Next
End Sub
Private Sub OpenWordDoc(filenam)
Dim fullname As String
Dim driv As String
Dim filepat As String
Set wordapp = CreateObject("word.Application")
wordapp.Documents.Open filepat Thisworkbook.Path & "\" & filenam
wordapp.Visible = True
wordapp.Activate
The code in the question has a number of problems. I'll start with the "simple" one, even though it's not the first one.
Excel VBA doesn't "know" ActiveDocument
The following line should be triggering a compile error in Excel VBA, although it will work fine from within Word VBA:
For Each prop In ActiveDocument.CustomDocumentProperties
Excel VBA doesn't have an object ActiveDocument, only Word VBA has this. If the code is running in any environment other than Word VBA, this won't work. The VBA environment needs to be told in which library it can find this object; the Word library needs to be specified using the Application object for Word:
For Each prop In objWord.ActiveDocument.CustomDocumentProperties
Don't use ActiveDocument if at all possible
While ActiveDocument does work, it's not as reliable as working directly with an object. Since this code opens a document, it's possible to assign that document to an object variable when it's opened, then work with the object variable.
As the code in the question uses a separate procedure for opening the document, this can be changed from Sub to Function in order to return the document object.
Documents need to be searched in the same Word instance
In addition, the Word.Application object should be passed to the "open" procedure. The code in the question starts an instance of the Word application in both the first procedure and in the "open" procedure. These are separate instances, so a document opened in the "open" procedure won't be visible to the first procedure. That's the reason for the error reported.
The code can be changed to this (some "Dims" removed for clarity):
Sub GenDraftLetter()
Dim i As Long
Dim j As Double
Dim filenam As String
Dim prop As Variant
Dim clientname As String
Dim objWord As Object
Dim objDoc as Object
Set objWord = GetObject(, "Word.Application")
If objWord Is Nothing Then
Set objWord = CreateObject("Word.Application")
End If
i = InputBox("Number of row for the Client", "Row for Client")
j = 1
Do Until Mid(Cells(i, 1), j, 1) = ","
j = j + 1
Loop
clientname = Right(Cells(i, 1), Len(Cells(i, 1)) - j - 1) & " " & Left(Cells(i, 1), j - 1)
filenam = "template.docx"
Set objDoc = OpenWordDoc(filenam, objWord)
For Each prop In objDoc.CustomDocumentProperties
If LCase(prop.Name) = "client" Then
prop.Value = clientname
Exit For
End If
Next
End Sub
Private Function OpenWordDoc(filenam, objWord) as Object
Dim objDoc as Object
'In case the code is called where no Word object is open
'Can be removed if this is not the intention of this procedure
If objWord Is Nothing Then
Set objWord = GetObject(, "Word.Application")
If objWord Is NOthing Then
Set objWord = CreateObject("Word.Application")
End If
End If
Set objDoc = objWord.Documents.Open(Thisworkbook.Path & "\" & filenam)
Set OpenWordDoc = objDoc
End Function

Excel VBA - Cross Referencing Bookmark/Form Field to Word

I have very minimal knowledge about VBA but still learning as it goes.
I've been using bookmarks in the word in order to populate data from excel. However, due to the content that some data need to repeat in a document, I tried using Text Form Field/Bookmark and REF Field to duplicate the same data.
The problem came in when once I populated data to the word, the text form field/bookmark disappear which causes REF Field unable to track the data that was referred to, hence, the "Error! Reference source not found."
In conclusion, what I'm trying to do is to populate data from excel to a locked word document and at the same time to retain Text Field Form/Bookmark in order to let REF field to track and duplicate the same data.
Is there any way to retain the Text Field Form/Bookmark placeholder after data is populated to the word? Here's my code that I am unable to solve in excel VBA.
Appreciate your help in advance!
Private Sub CommandButton1_Click()
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("Sheet1")
Dim objWord As Object
Set objWord = CreateObject("Word.Application")
objWord.Visible = True
objWord.Documents.Open "C:\Users\" & Environ("username") & "\Desktop\XXX\XXX"
objWord.ActiveDocument.Unprotect Password:="xxx"
With objWord.ActiveDocument
Dim objBMRange As Range
Set objBMRange = .Bookmarks("pr1").Range.Text = ws.Range("C28").Value
objBMRange.Text = pr1
.Bookmarks.Add "pr1", BMRange
.Fields.Update
objWord.ActiveDocument.Protect Password:="xxx", NoReset:=False, Type:=wdAllowOnlyFormFields
End With
Set objWord = Nothing
End Sub
You were almost there. Very near, but you didn't get the Range object sorted out. Please try this code (only partially tested).
Private Sub CommandButton1_Click()
Dim Ws As Worksheet
Dim objWord As Object
Dim Mark As String
Dim Txt As String
Dim BmkStart As Long
Mark = "pr1"
Set Ws = ThisWorkbook.Sheets("Sheet1")
Txt = Ws.Range("C28").Value
Set objWord = CreateObject("Word.Application")
With objWord
.Visible = True
.Documents.Open "C:\Users\" & Environ("username") & "\Desktop\XXX\XXX"
With .ActiveDocument
.Unprotect Password:="xxx"
If .Bookmarks.Exists(Mark) Then
With .Bookmarks(Mark).Range
BmkStart = .Start
.Text = Txt
End With
.Bookmarks.Add Mark, .Range(BmkStart, BmkStart + Len(Txt))
End If
.Fields.Update
.Protect Password:="xxx", NoReset:=False, Type:=wdAllowOnlyFormFields
End With
End With
Set objWord = Nothing
End Sub
One point is that the Bookmark defines a Word.Range (different from an Excel.Range which you get when you specify no application while working in Excel). The other, that Bookmark defines a range but isn't a range itself, not even a Word.Range. Therefore you get or set its text by modifying it's range's Text property.

Resources