I am having an issue with setting a Content Control value using VBS. Here is what I am doing:
Sub saveToWord
Set docObj = CreateObject("Word.Application")
docObj.visible =true
docObj.Documents.open "C:\Users\User\Desktop\test.docx"
docObj.SelectContentControlsByTitle("Title").Item(1).Range.Text = "Test title"
End Sub
It works perfectly in VBA,but it doesn't work for VBScript. There is an error:
Object doesn't support this property or method: 'docObj.SelectContentControlsByTitle'
Are there any alternatives to achieve this? I had a look into ContentControls Object Docu, but couldn't find any suitable way.
The problem is that you assign the Word.Application to the variable docObject. SelectContentControlsByTitle is a member of the DOCUMENT, not the Application object. You need something more like
Set wdApp = CreateObject("Word.Application")
wdApp.Visible = true
Set docObject = Documents.Open(fileName)
'Etc.
Related
I'm trying to understand how to work with the new Attachment field that is available in Access 2010. I would like to assign the value from the table directly into a variable. I know that I can do this if I use an intermediary form, but this seems like sloppy coding to rely on a form in order to grab a value from a table. Is there some way to grab what is in an attachment field and assign it directly to a variable? I have multiple instances where this would be handy for me. The first instance is I want to grab a photo stored in an attachment field to assign to the ribbon. A second instance is to load a company logo from a table into a variable and keep it in memory to use throughout the program as needed.
The code I have so far is this, but it gives me a type mismatch error:
Dim ParentRS As Recordset, ChildRS As Recordset, Img As Attachment
Set ParentRS = CurrentDb.OpenRecordset("SELECT * FROM LtblImg;", dbOpenSnapshot)
If ParentRS.RecordCount > 0 Then
Set ChildRS = ParentRS("Img").Value
If ChildRS.RecordCount > 0 Then
Set Img = ChildRS("FileData")
End If
ChildRS.Close
End If
ParentRS.Close
Yes, Dim Img As Attachment looks tempting, but Attachment (which is actually Access.Attachment) refers to an Attachment control that could be used on a form (just like Access.TextBox) and does not appear to be suitable for your intended purpose.
The only native VBA type for storing this sort of binary data is an array of Byte values, but often when dealing with byte arrays we wind up looping through and processing them byte-by-byte, which is tedious and inefficient.
You might consider using a binary ADODB.Stream object as your "variable". You could create a function to retrieve the attachment bytes and return them in a Stream like so
Option Compare Database
Option Explicit
Public Function GetLogoAsStream() As ADODB.Stream
Dim cdb As DAO.Database, rstMain As DAO.Recordset, rstAttach As DAO.Recordset2, fldAttach As DAO.Field2
' Project references required for early binding:
' Windows Script Host Object Model
' Microsoft ActiveX Data Objects 2.8 Library
Dim fso As FileSystemObject, tempFileSpec As String
Static strm As ADODB.Stream
If strm Is Nothing Then
Set fso = New FileSystemObject
tempFileSpec = fso.GetSpecialFolder(TemporaryFolder) & "\" & fso.GetTempName
Set fso = Nothing
Set cdb = CurrentDb
Set rstMain = cdb.OpenRecordset( _
"SELECT [AttachmentFiles] " & _
"FROM [AttachmentsTable] " & _
"WHERE [Description]='SO logo'", _
dbOpenSnapshot)
Set rstAttach = rstMain("AttachmentFiles").Value
' make sure we use the correct file extension
tempFileSpec = tempFileSpec & "." & rstAttach.Fields("FileType").Value
Set fldAttach = rstAttach.Fields("FileData")
fldAttach.SaveToFile tempFileSpec
Set fldAttach = Nothing
rstAttach.Close
Set rstAttach = Nothing
rstMain.Close
Set rstMain = Nothing
Set cdb = Nothing
Set strm = New ADODB.Stream
strm.Type = adTypeBinary
strm.Open
strm.LoadFromFile tempFileSpec
Kill tempFileSpec
End If
strm.Position = 0
Set GetLogoAsStream = strm
End Function
and then if you had, say, a Report like this with an empty Image control
and an On Load event procedure like this to load the Image control's .PictureData from your "variable" (actually a Function returning an ADODB.Stream)
Private Sub Report_Load()
Me.LogoImage.PictureData = GetLogoAsStream.Read
End Sub
it could produce something like this
Microsoft Word is offering some default document properties to be set in Word documents.
There is a number of default properties, for which vbscript has constants.
But Word (2011) is offering some more properties, e.g. companyfaxnumber, publishingdate,keywords.
There is a possibility to access the builtin properties by calling
Set oWord = CreateObject("Word.Application")
oWord.Visible = True
oWord.Documents.Open(strFilePath)
For Each prop In oWord.ActiveDocument.BuiltInDocumentProperties
WScript.Echo prop.Name + "::" + oWord.ActiveDocument.BuiltInDocumentProperties(prop.Name).Value
Next
But how do i find the names of the "custom" properties that are offered by word, but are not present in vbscript as constant?
There is the function
Document.CustomDocumentProperties
But if i do a listing like the one above, i get properties named info1, info2, etc.
Too access the Word CustomDocumentProperties, you will need to be able to access the OLE File Property Reader. This expands beyond the normal/simple document properties because it allows you too add custom properties as well.
There is a Tales from the Script article from 2005 detailing the installation and usage of utilizing CustomDocumentProperties within Word -> Here
For the download to install the OLE Property Reader DLL, Go -> Here
Here is an example of property set/get once the property read is installed:
Const msoPropertyTypeBoolean = 2
Set objFile = CreateObject("DSOFile.OleDocumentProperties")
objFile.Open("C:\Scripts\New_users.xls")
'Set
'=======================================================================
objFile.CustomProperties.Add "Document Reviewed", msoPropertyTypeBoolean
objFile.Save
'Get
'=======================================================================
Set objProperty = objFile.CustomProperties.Item("Document Reviewed")
wscript.echo objProperty.Value
Enjoy!
Hi recently figured out how to get there myself:
The Word "Frontend Editor" is cheating on the document properties. There is a hard defined set of properties like author,category, keywords etc.
The additional properties offered by the editor are so called custom properties which are defined in an external XML structure inside the docx-container.
So there is no easy vbscript function to modify the values of these custom properties.
Thanks to the web, someone did some hacking and this is the solution for it:
Sub WriteCustomCoverProperties(ByRef wordInstance, strProp, strText)
Dim oCustPart
Dim oNode
Dim strXPath
strProp = Replace(strProp, " ", "")
Select Case strProp
Case "Abstract" strXPath = "/ns0:CoverPageProperties[1]/ns0:Abstract[1]"
Case "PublishDate" strXPath = "/ns0:CoverPageProperties[1]/ns0:PublishDate[1]"
Case "CompanyAddress" strXPath = "/ns0:CoverPageProperties[1]/ns0:CompanyAddress[1]"
Case "CompanyPhone" strXPath = "/ns0:CoverPageProperties[1]/ns0:CompanyPhone[1]"
Case "CompanyFax" strXPath = "/ns0:CoverPageProperties[1]/ns0:CompanyFax[1]"
Case "CompanyEmail" strXPath = "/ns0:CoverPageProperties[1]/ns0:CompanyEmail[1]"
Case Else
Exit Sub
End Select
Set oCustPart = wordInstance.ActiveDocument.CustomXMLParts(3)
Set oNode = oCustPart.SelectSingleNode(strXPath)
oNode.Text = strText
Set oCustPart = Nothing
Set oNode = Nothing
End Sub
May it be of help =)
I am using vba code to get information out of the web.
Everything is going fine, but it takes soooo long :(
I remember darkly that there is another way to get the information instead of creating an IE Object.
I think I dont need the IE Controlls. I am just loading one link after each other out of an sheet.
How is the other "way" working? Its something like XMLHttp?
Is there a difference for the code? shoudnt be, or?
thanks!
This is what I use:
Function getPage(URLStr As String) As MSHTML.HTMLDocument
Dim oHttpRequest As MSXML2.XMLHTTP60
Set oHttpRequest = New MSXML2.XMLHTTP60
With oHttpRequest
.Open "GET", URLStr, False
.send
End With
Dim oHTMLDoc As MSHTML.HTMLDocument
Set oHTMLDoc = New MSHTML.HTMLDocument
oHTMLDoc.body.innerHTML = oHttpRequest.responseText
Set getPage = oHTMLDoc
End Function
To call the function, use something like this:
Dim oHTMLDoc as MSHTML.HTMLDocument
Set oHTMLDoc = getPage("http://www.example.com")
For this, you'll need to add references to both "Microsoft XML, v6.0" and "Microsoft HTML Object Library", then you can use the MSHTML library to parse through the code as you need.
I am using the following script to grab parcel and address information from one layer to fill the attribute table of a newly created feature.
There is no returned error, but the problem I am having is that there seems to be the wrong information stuck in the memory of recordselect function. No matter where I place a point it gives the same parcel # and address. Or maybe it isn’t actually be performing the IF function properly.
Sub Address
Dim rsCurrentXY
Set rsCurrentXY = Map.Layers("Violations").records
rsCurrentXY.movelast
Dim objXYShape
Set objXYShape = rsCurrentXY.Fields.Shape
Dim pControls
Set pControls= Application.Map.selectionlayer.Forms("EDITFORM").Pages(“PAGE1”).Controls
Dim rsGrid
' Find corresponding map page to the valve point
Set rsGrid = Map.Layers("ACPA_parcels").records
rsGrid.movefirst
Do While Not rsGrid.eof
If rsGrid.fields.shape.Ispointin(objXYShape) Then
pControls("txtAddress").value = rsGrid.Fields("ADD1").Value
Exit Do
End If
rsGrid.Movenext
Loop
' Clean Up
Set rsCurrentXY = Nothing
Set objXYShape = Nothing
Set rsGrid = Nothing
End Sub
(I have another subroutine called "PIN" that would do the exact same thing.)
I have them called when their respective edit boxes in the custom form are activated by the inspector.
Thanks for the help,
Robert
Accessing the EDITFORM via Application.Map.selectionlayer.Forms("EDITFORM") will be problematic. Whenever working with controls on an EDITFORM you should using ThisEvent.Object to discover all your objects. For example, if your event handler is Page_OnLoad then ThisEvent.Object will refer to your current page. You should have code like this:
Dim pPage1
Set pPage1 = ThisEvent.Object
Dim pControls
Set pControls = pPage1.Controls
What XPath query should I use to get to the GetLogisticsOfferDateResult Node?
I have attached the vbscript that I'm using.
I suspect the problem has to do with the multiple namespaces in the document. But how do I reference the second namespace in the XPath?
Dim responseXML
responseXML = '"<s:Envelope xmlns:s=""http://schemas.xmlsoap.org/soap/envelope/""><s:Body><GetLogisticsOfferDateResponse xmlns=""http://schneider-electric.com/OrderEntryService""><GetLogisticsOfferDateResult>2010-07-20</GetLogisticsOfferDateResult></GetLogisticsOfferDateResponse></s:Body></s:Envelope>"'
Dim responseDoc
Set responseDoc = WScript.CreateObject("MSXML2.DOMDocument.6.0")
responseDoc.loadXML(responseXML)
responseDoc.setProperty "SelectionNamespaces", "xmlns:s='http://schemas.xmlsoap.org/soap/envelope/'"
Dim requestedNode
'This node is not found
'Set requestedNode = responseDoc.selectSingleNode("//s:Envelope//s:Body//GetLogisticsOfferDateResponse//GetLogisticsOfferDateResult")
'This node is found
Set requestedNode = responseDoc.selectSingleNode("//s:Envelope//s:Body")
'This node is found
'Set requestedNode = responseDoc.selectSingleNode("//s:Envelope")
If requestedNode Is Nothing Then
WScript.Echo "Node not found"
Else
WScript.Echo requestedNode.text
End If
Set responseDoc = Nothing
Set LODateNode = Nothing
Turns out my setting of selectionNamespaces had to be as follows:
responseDoc.setProperty "SelectionNamespaces", "xmlns:sc='http://schneider-electric.com/OrderEntryService' xmlns:s='http://schemas.xmlsoap.org/soap/envelope/'"
Then the XPath query had to be:
Set requestedNode = responseDoc.selectSingleNode("//s:Envelope//s:Body//sc:GetLogisticsOfferDateResponse//sc:GetLogisticsOfferDateResult")
You have not defined the default namespace of the document (http://schneider-electric.com/OrderEntryService) in your code.
responseDoc.setProperty "SelectionNamespaces", "'http://schemas.xmlsoap.org/soap/envelope/' 'http://schneider-electric.com/OrderEntryService'"
You will either need to add it, or prefix the elements that belong to it with it.