Insert a line break from Excel VBA in a Word document - excel

From my Excel Sheet I open up a Word document. Excel generates some text within the document. Between the text I want a LineBreak.
The code results in an error message stating: parameter value out of acceptable range
Using the following documentation this should be possible using InsertBreak.
Sub InsertLineBreak()
Set wrd = CreateObject("Word.Application") 'Open Word
Set objDoc = wrd.Documents.Add 'Add new document
Set objSelection = wrd.Selection 'Select this document
objSelection.InsertBreak Type:=wdLineBreak 'Insert Break
End Sub

It works perfectly fine for me, are you sure you have added correct reference?
Try objSelection.InsertBreak Type:=6 or add Microsoft Word 16.0 Object Library reference, or declare a globar variable wdLineBreak

For future readers:
In this case the Microsoft Word 16.0 Object Library was missing.
It can be added Tools-> References and selecting the corresponding Library

Related

Find / replace text in embedded word object code stopped working

I have used this code successfully to replace content in an embedded word object from excel. I copied the code for a new excel file but now it doesn't work. It opens the file but doesn't replace although I can see that it IS finding the right text and replacement text. I'm kind of lost as to what is happening.
Dim strFindText As Range
Dim strReplaceText As Range
Dim nSplitItem As Long
Set strFindText = ActiveWorkbook.Worksheets("Utilisation Form").Range("c11:c20")
Set strReplaceText = ActiveWorkbook.Worksheets("Utilisation Form").Range("a11:a20")
nSplitItem = strFindText.Count
Debug.Print strFindText.Item(0)
For Each sh In ThisWorkbook.Sheets("Utilisation Form").Shapes
If sh.Name <> "Object 1" Then sh.Delete
Next
Set urobj = ThisWorkbook.Sheets("Utilisation Form").OLEObjects("Object 1")
Set wordtemp = urobj.Duplicate
wordtemp.Verb Verb:=xlOpen
Set wordtemp2 = wordtemp.Object
For x = 1 To nSplitItem
With wordtemp2.Content.Find
.Forward = True
.Text = strFindText.Item(x)
.ClearFormatting
.Replacement.Text = strReplaceText.Item(x)
.Execute Replace:=wdReplaceAll
End With
Next x
End Sub
Thanks for the support
When the early-binding technology is used in the code you need to add a corresponding COM reference to be able to use data types. Otherwise, you need to declare everything from the Word object model as Object in the code and use the late-binding technology.
To use early binding on an object, you need to know what its v-table looks like. In Visual Basic, you can do this by adding a reference to a type library that describes the object, its interface (v-table), and all the functions that can be called on the object. Once that is done, you can declare an object as being a certain type, then set and use that object using the v-table. For example, if you wanted to Automate Microsoft Office Excel using early binding, you would add a reference to the Microsoft Excel X.0 Object Library from the Project|References dialog, and then declare your variable as being of the type Excel.Application. From then on, all calls made to your object variable would be early bound.
Read more about that in the Using early binding and late binding in Automation article.

Find Workflow objects 3D in visio

I´m trying to create a code in vba excel to detect what´s inside the work flow objects - 3D as the ones shown in the following picture:
The pictures are always the same. I have been able to find and select the sentence inside the cell. But I need it to search for all the work flow objects in different visio.
This is where I got to:
Dim DiagramServices As Integer
DiagramServices = ActiveDocument.DiagramServicesEnabled
ActiveDocument.DiagramServicesEnabled = visServiceVersion140 + visServiceVersion150
Dim vsoCharacters1 As Visio.Characters
Set vsoCharacters1 = Application.ActiveWindow.Page.Shapes.ItemFromID(228).Characters
Debug.Print vsoCharacters1
I need the code to first find all the work flow objects in different pages in visio and then obtain the sentence within (vsoCharacters1)
Please try this simple code
Sub ttt()
Dim doc As Document ' Variable for Document
Dim pg As Page ' Variable for Page
Dim shp As Shape ' Variable for Shape
Dim txt As String ' Variable for Shape's text
For Each doc In Documents ' Iterate all documents in Visio application session
For Each pg In doc.Pages ' Iterate all pages in 'doc'
For Each shp In pg.Shapes ' Iterate all docunents in 'pg'
txt = shp.Text ' Define 'txt' variable
Select Case txt ' Criterion
Case "ololo", "trololo" ' Found text
ActiveWindow.Page = pg ' Activate page with criterion
ActiveWindow.Select shp, visSelect ' Select shape with criterion
MsgBox "Page: " & pg.Name & ", ShapeID: " & shp.ID, , "A shape was found, the text of which matches the criterion: " & txt
End Select
ActiveWindow.DeselectAll ' Unselect a shape
Next shp
Next pg
Next doc
MsgBox "TheEnd!!!"
End Sub
Note:
This code started in MS Visio, code without recursion, dont find shapes into groups !
May I propose a more systematic approach?
Drawing explorer
Make sure you're in developer mode.
Switch the drawing explorer on.
Identify the shape to explore
Expand its tree to see its sub-shapes
If you're lucky a pro has made this shape and named the subshapes eg Label, Frame, what ever. This will simplify the access to this shape.
in VBA:
shp being your group shape object
access the sub-shape via: set subshp = shp.Shapes(name_of_subshape)
This works also for the sub-shapes of the sub-shape.
Otherwise - the sub-shapes are named sheet.234 - you need to find another identification method.
Open the shapesheet of the sub-shape (right-mouse-click)
Inspect it and try to figure out in how far it differs from the other sub-shapes. That can be a text, user or prop field, a geometry section ... etc.
in VBA you would then loop over all the sub-shapes and check for this property.
eg:
for each subshape in shp.Shapes:
if subshape.CellExists("soAndSo",0) then
if subshape.Cells("soAndso").ResultStr("") = "thisAndThat" then
'you found it, do your stuff.
By the way, you don't need to access the characters object of a shape to get its text. It is simply "shp.Text". The characters object is more complexe and lets you do funny stuff with the text.

Pushing data from Excel to Word throws error 5844 when text contains apostrophe

My Excel macro reads the values of a bunch of cells in Excel and pushes them to corresponding "content controls" in a Word template file. Everything works as planned unless the source cell contains a string with an apostrophe, e.g. "Children's Hospital". In this case execution stops:
"Run time error 5844 One of the values to this method or property is incorrect".
I have tried to read the cell value into an auxiliary string variable before assigning that to the content control but that did not help.
I also tried to force the source value to string using the CStr function - no good.
What do I do wrong?
Help please.
Sub PushToWord()
Dim oAppWord As Word.Application
Dim oDoc As Word.Document
...
With ThisWorkbook.Worksheets("Results")
...
oDoc.SelectContentControlsByTitle("Institution").Item(1).Range.Text = .Cells(18, iSCol).Value
...
End With
...

Change built-in Document properties without opening

I am attempting to run the below line of code in a sub. The purpose of the sub overall is to automatically create agendas for recurring meetings, and notify the relevant people.
'Values for example;
MtgDate = CDate("11/06/2020")
Agenda ="Z:\Business Manual\10000 Management\11000 Management\11000 Communications\Operations Meetings\11335 - OPS CCAR Performance Review Agenda 11.06.20.docx" 'NB it's a string
'and the problematic line:
Word.Application.Documents(Agenda).BuiltinDocumentProperties("Publish Date") = MtgDate
Two questions:
1) Can I assign a document property just like that without opening the document? (bear in mind this vba is running from an excel sheet where the data is stored)
2) Will word.application.documents accept the document name as a string, or does it have to be some other sort of object or something? I don't really understand Word VBA.
Attempts so far have only resulted in
runtime error 427 "remote server machine does not exist or is
unavailable"
or something about a bad file name.
Although Publish Date can be found under Insert > Quick Parts > Document Property it isn't actually a document property. It is a "built-in" CustomXML part, a node of CoverPageProperties, and can be addressed in VBA using the CustomXMLParts collection.
The CustomXML part is only added to the document once the mapped content control is inserted.
Below is the code I use.
As already pointed out for document properties the document must be open.
Public Sub WriteCoverPageProp(ByVal strNodeName As String, ByVal strValue As String, _
Optional ByRef docTarget As Document = Nothing)
'* Nodes: Abstract, CompanyAddress, CompanyEmail, CompanyFax, CompanyPhone, PublishDate
'* NOTE: If writing PublishDate set the content control to store just the date (default is date and time).
'* The date is stored in the xml as YYYY-MM-DD so must be written in this format.
'* The content control setting will determine how the date is displayed.
Dim cxpTarget As CustomXMLPart
Dim cxnTarget As CustomXMLNode
Dim strNamespace As String
If docTarget Is Nothing Then Set docTarget = ActiveDocument
strNodeName = "/ns0:CoverPageProperties[1]/ns0:" & strNodeName
strNamespace = "http://schemas.microsoft.com/office/2006/coverPageProps"
Set cxpTarget = docTarget.CustomXMLParts.SelectByNamespace(strNamespace).item(1)
Set cxnTarget = cxpTarget.SelectSingleNode(strNodeName)
cxnTarget.Text = strValue
Set cxnTarget = Nothing
Set cxpTarget = Nothing
End Sub
You cannot modify a document without opening it. In any event, "Publish Date" is not a Built-in Document Property; if it exists, it's a custom one.
Contrary to what you've been told, not all BuiltinDocumentProperties are read-only; some, like wdPropertyAuthor ("Author"), are read-write.
There are three main ways you could modify a Word document or "traditional" property (which are the ones you can access via .BuiltInDocumentProperties and .CustomProperties):
a. via the Object Model (as you are currently trying to do)
b. for a .docx, either unzipping the .docx, modifying the relevant XML part, and re-zipping the .docx.
c. For "traditional" properties, i.e. the things that you can access via .BuiltInDocumentProperties and .CustomDocumentProperties, in theory you can use a Microsoft .dll called dsofile.dll. But it hasn't been supported for a long time, won't work on Mac Word and the Microsoft download won't work on 64-bit Word. You'd also have to distribute and support it.
But in any case, "Publish Date" is not a traditional built-in property. It's probably, but not necessarily, a newer type of property called a "Cover Page Property". Those properties are in fact pretty much as "built-in" as the traditional properties but cannot be accessed via .BuiltInDocumentProperties.
To modify Cover Page properties, you can either use the object model or method (b) to access the Custom XML Part in which their data is stored. Method (c) is no help there.
Not sure where your error 427 is coming from, but I would guess from what you say that you are trying to see if you can modify the property in a single line, using the fullname of the document in an attempt to get Word to open it. No, you can't do that - you have to use GetObject/CreateObject/New to make a reference to an instance of Word (let's call it "wapp"), then (say)
Dim wdoc As Word.Document ' or As Object
Set wdoc = wapp.Documents.Open("the fullname of the document")
Then you can access its properties, e.g. for the read/write Title property you can do
wdoc.BuiltInDocumentProperties("Title") = "your new title"
wdoc.Save
If Publish Date is the Cover Page Property, once you have a reference to the Word Application and have ensured the document is open you can use code along the following lines:
Sub modPublishDate(theDoc As Word.Document, theDate As String)
' You need to format theDate - by default, Word expects an xsd:dateTime,
' e.g. 2020-06-11T00:00:00 if you only care about the date.
Const CPPUri As String = "http://schemas.microsoft.com/office/2006/coverPageProps"
Dim cxn As Office.CustomXMLNode
Dim cxps As Office.CustomXMLParts
Dim nsprefix As String
Set cxps = theDoc.CustomXMLParts.SelectByNamespace(CPPUri)
If cxps.Count > 0 Then
With cxps(1)
nsprefix = .NamespaceManager.LookupPrefix(CPPUri)
Set cxn = .SelectSingleNode(nsprefix & ":CoverPageProperties[1]/" & nsprefix & ":PublishDate[1]") '/PublishDate[1]")
If Not (cxn Is Nothing) Then
cxn.Text = theDate
Set cxn = Nothing
End If
End With
End If
Set cxps = Nothing
As for this, "Will word.application.documents accept the document name as a string", the answer is "yes", but Word has to have opened the document already. as mentioned above. Word can also accept an integer index into the .Documents collection and may accept just the name part of the FullName string.
Finally, if you do end up using a "traditional Custom Document Property", even after you have set the property and saved the document (approximately as above) you may find that the new property value has not actually saved! If so, that's down to an old error in Word where it won't save unless you have actually visited the Custom Document Property Dialog or have modified the document content in some way, e.g. adding a space at the end.

Inserting into Multiple Bookmark Locations - Excel VBA

I am using an Excel macro where I am inserting the same text to several bookmarks in a Word doc. How can I do this by specifying the insert command once and apply it to all the bookmark locations?
Now I am doing the following for all bookmarks?
Dim monYear As String
monYear = Format(DateAdd("m", -1, Now), "mmmm yyyy")
wdApp.Selection.GoTo what:=-1, Name:="Front_Page_Month_Year"
wdApp.Selection.TypeText monYear
wdApp.Selection.GoTo what:=-1, Name:="Page2_Month_Year"
wdApp.Selection.TypeText monYear
And on and on....
There's no way to use a single command to write to multiple bookmark locations. What you can do, however, is reference one bookmark location in order to display that bookmark's content in multiple locations.
Create the bookmark, then insert a cross-reference to it in each location where you want to display the bookmark contents. (Or create one cross-reference, then copy/paste to the other locations.)
A tip for your code: the approach you're using with the Selection object is not optimal. As in Excel, it's better to work with the object model, rather than rely on a Selection. Thus:
Dim doc as Word.Document
Set doc = wdApp.ActiveDocument 'Note: if you're opening a document, set in the Open method
doc.Bookmarks("Front_Page_Month_Year").Range.Text = monYear
'When you're done, update the REF fields (references)
doc.Fields.Update

Resources