I want to use vba to read and write "Description" & "Visualize in the Bill of Material" of selected catia object. I use highlight in the picture below. Help me please, Thank you!
Dim s as Selection
Set s = Catia.ActiveDocument.selection 'selection of your document
For i = 1 to s.Count2 'if your selection contains more than 1 selection
Dim p as Product
Set p = s.Item2(i).LeafProduct 'leafproduct to get your product
p.DescriptionInst = "test" 'to set your description
Next
It's not possible to get/set Visualize in The Bill of Material
Related
I am trying to write a code in Word that allows me to fetch data from Content Control Drop Down lists. This data is being pulled from a previously saved Word file, that I reference at the start of script (but don't show here as that is not the problem).
I have this working for other types of Content Control (example below), but I cannot figure out how this will work for Drop Down lists.
Here is my ineffective code:
For l = 1 To 28
Windows(ReportWindowName).Activate
TagName = "Rating" & l
Set doc = ActiveDocument
Set ccs = doc.SelectContentControlsByTag(TagName)
Set cc = ccs(1)
cc.Range.Select
ccc = Selection.Text
OriginalDocument.Activate
TagName = "Rating" & l
Set doc = ActiveDocument
Set ccs = doc.SelectContentControlsByTag(TagName)
Set cc = ccs(1)
cc.Range.Select
Selection.Text = ccc
Next l
The code falls over at Selection.Text. I need to modify something to allow the code to fetch entries in Drop Down lists.
Below is another very similar code from the same command, that works, but returns data from text fields rather than Drop Down lists saved in the dame file:
For j = 1 To 6
Windows(ReportWindowName).Activate
TagName = "Mandatory" & j
Set doc = ActiveDocument
Set ccs = doc.SelectContentControlsByTag(TagName)
Set cc = ccs(1)
cc.Range.Select
ccc = Selection.Text
OriginalDocument.Activate
TagName = "Mandatory" & j
Set doc = ActiveDocument
Set ccs = doc.SelectContentControlsByTag(TagName)
Set cc = ccs(1)
cc.Range.Select
Selection.Text = ccc
Next j
Would appreciate any help modifying my loop code to fetch the Drop Down list results.
Many thanks!
If you are trying to get text from the Content Control, what you need is at most
Set ccs = doc.SelectContentControlsByTag(TagName)
Set cc = ccs(1)
' Let's just show the "display name"
Debug.Print cc.Range.Text
You could shorten that to
Set ccs = doc.SelectContentControlsByTag(TagName)
' Let's just show the "display name"
Debug.Print ccs(1).Range.Text
or even further if you like.
The reason that the code you have at the moment fails is because it's actually trying to put text into the Content Control. You can do that with a Text control but not with a Dropdown List
(Following up on your comment) If you want to set the dropdownlist to a certain value, you basically have to identify which item in the DropDownListEntries collection is the correct one, then select it. Each DropDownListEntry within a ContentControl has a unique Index, unique Text (display text) and Value (hidden value).
You can get the Text from a dropdown by looking at the .Range.Text of the source ContentControl, but you can't use that as an index into the target ContentControl's list entries, so you have to iterate:
So, if ccc contains the text you want to display, you would need something like
Set ccs = doc.SelectContentControlsByTag(TagName)
Set cc = ccs(1)
' This asumes you know this is a dropdown list cc
Dim ddle as Word.ContentControlListEntry
For Each ddle in cc.DropdownListEntries
If ddle.Text = ccc Then
ddle.Select
Exit For
End If
Next
Or, you can get the Index from the source control (and you would have to iterate the source control's listentries to do that). Let's say it's in variable idx. Then all you need is
Set ccs = doc.SelectContentControlsByTag(TagName)
Set cc = ccs(1)
cc.DropdownListEntries(idx).Select
(In fact you can do it all in one
doc.SelectContentControlsByTag(TagName)(1).DropDownlistEntries(idx).Select
but I generally find using multiple statements makes debugging easier).
So using this approach, you either have to iterate one set of list entries or the other (or both, if you want to use the Value).
The other technique would be to map the control to an Element in a CustomXMLPart and just update the Element value. Word then propagates the value to all the ContentControls mapped to that Element. There is quite a bit to learn and it may seem like complication that you don't need, but when you get to the end I hope you will see why this is actually quite a neat approach.
At its simplest, it works like this. Let's suppose you have one DropDown Content Control in your document.
Then you can (re) create an XML Part and map the content control to it like this. You would only need to execute this piece of code once for a document. If your documents are based on templates or made from copies of other documents, that's once for the template/original.
Option Explicit
' A namespace URI can just be a piece of text, but its better if you can use
' something that you "own" such as a domain name.
' There is nothing special about this name.
Const myNameSpace As String = "myns0"
Sub recreateCXPandMapCCs()
Dim ccs As Word.ContentControls
Dim cxp As Office.CustomXMLPart
Dim i As Integer
Dim r As Word.Range
Dim s As String
' There is nothing special about these element names.
' You can use your own
s = ""
s = s & "<?xml version=""1.0"" encoding=""UTF-8""?>" & vbCrLf
s = s & "<ccvalues1 xmlns='" & myNameSpace & "'>" & vbCrLf
s = s & " <dropdown1/>" & vbCrLf
s = s & "</ccvalues1>"
With ActiveDocument
' select and delete any existing CXPs with this namespace
For Each cxp In .CustomXMLParts.SelectByNamespace(myNameSpace)
cxp.Delete
Next
' Create a new CXP
Set cxp = .CustomXMLParts.Add(s)
' Connect your dropdown. Instead, you can do this manually in the XML Mapping
' Pane in the Developer tab
' For an XML Part that only has one namespace the prefix mapping should always be "ns0".
.ContentControls(1).XMLMapping.SetMapping "/ns0:ccvalues[1]/ns0:dropdown1[1]", , cxp
Set cxp = Nothing
End With
End Sub
Then, to set the value of your DropDown (and it needs to be the hidden Value, not the Index or the Text, you can do something like this within the same module so you have the myNameSpace constant set up. Let's say you want to set the constant value "xyzvalue"
Sub populateDropdown1Element()
With ActiveDocument.CustomXMLParts.SelectByNamespace(myNameSpace)(1)
.SelectSingleNode("/ns0:ccvalues1[1]/ns0:dropdown1[1]").Text = "xyzvalue"
End With
End Sub
Of course if the source document has the same mappings, you can get the value of the source document dropdown from the same element in the source document's XML. The fact is that if you have the same XML, same mappings etc., ideally you should be able to replace the entire CustomXMLPart in the target document by the one from the "source" document. One of the reasons CustomXMLParts were invented was to allow people using the Office Open XML SDK to do exactly that. Unfortunately it does not work in VBA with the document open because Word tends to disconnect the Content Controls from the part.
But what you can do is iterate all the Element and Attribute nodes (for example) and replace the text in the target by the text from the source. Like this:
' You would need to pass in a reference to the document you want to get your data *from*
Sub replaceXML(sourceDocument As Word.Document)
Dim s As String
Dim cxn As Office.CustomXMLNode
Dim sourcePart As Office.CustomXMLPart
' You still need that definition of "myNameSpace"
Set sourcePart = sourceDocument.CustomXMLParts.SelectByNamespace(myNameSpace)(1)
With ActiveDocument
For Each cxn In .CustomXMLParts.SelectByNamespace(myNameSpace).Item(1).SelectNodes("//*[not(*)] | //#*")
cxn.Text = sourcePart.SelectSingleNode(cxn.XPath).Text
Next
End With
End Sub
What does "//*[not(*)] | //#*" select? Well, "//*[not(*)]" selects leaf Elements (including Elements that have attributes), "//#*" selects all attributes (which are always leaf nodes) and | is basically "Or" or "union".
Most custom xml I have seen in Word only stores data in Elements, and in that case you would only need "//*[not(*)]"
i want to move 3 placeholders with same name "Content Placeholder 7". When i write the code to select it selects the original placeholder and ignore the rest. I also want to move the two arrows little upwards.
Here is the code i have been writing: I might be writing the shape names incorrectly, please correct if wrong.
Sub Export_Range()
Dim pp As New PowerPoint.Application
Set ppapp = GetObject(class:="PowerPoint.Application")
Dim intTableRows As Integer, intTableCols As Integer
Sheet2.Columns("B:C").ClearContents
First = Sheet1.Range("J3").Value
Last = Sheet1.Range("K3").Value
For j = First To Last
With ppapp.ActivePresentation.Slides(j).Shapes.Range(Array("Content Placeholder 7", "Arrow:Left 12", "Arrow:Left 13"))
.Top = 150
End With
End Sub
Many Thanks!
I'm trying to alter a user selected parameter of a selected CATPart in an assembly via CADSelection. Ultimatelly this will go into a GUI in VBA and the user will, select the CATPart, open the macro and via the GUI change whatever parameters he requires.
I've recorded the macro and tweaked around with this for a while now, but i can't seem to finish this.
My tree is:
Product;
-Part;
-Part_Teste_2;
-Part_Teste_3;
-Part_Teste_4;
-Part_Teste_5;
All of the above "Part_Teste" have 3 parameters one of them is called "Comprimento"
How do I change make sure that the macro alters the selected CATPArt's parameter instead of ("Part_Teste_3.CATPart")?
The macro that I have so far is:
Language="VBSCRIPT"
Sub CATMain()
Set oProductDoc = CATIA.ActiveDocument
Set oProd = oProductDoc.Product
Set oDocs = CATIA.Documents
Set oSelection = CATIA.ActiveDocument.Selection
If oSelection.Count < 1 then
MsgBox "Pick some components using cad selection.","No components were selected"
Else
Set oPartDoc = oDocs.Item("Part_Teste_3.CATPart")
Set oPart = oPartDoc.Part
Set oParam = oPart.Parameters
Set oLength = oParam.Item("Comprimento")
oLength.Value = 50.000000
End If
oSelection.Clear
oProd.Update
End Sub
When you select in an assembly, the LeafProduct property of the SelectedEntity object returned by Selection.Item() will contain the instance product owning the selected object.
So, if you are selecting something which belongs to a part while working in an assembly, get the instance product of the part...
Dim oInstProd as Product
Set oInstProd = oSel.Item(1).LeafProduct
Then from there get the part object:
Set oPart = oInstProd.ReferenceProduct.Parent.Part
I insert an image from VBA to Excel in Cell F31.
With Worksheets("CheckListIndustrialisation").Pictures.Insert(image)
'.Top = [F31].Top
'.Left = [F31].Left
'.Width = [F31].Width
'.Height = [F31].Height
But what I would like to do is to insert my image in the same sheet of excel but in one special case for image and not F31. The code inside the special case of image is:
=INCORPORER("Forms.Image.1";"")
I don't find how to change my code.
What you're trying to do is add an OleObject in the worksheet.
Try below:
'First add the OleOject
Dim img As OLEObject, sh As Worksheet
Set sh = Worksheets("CheckListIndustrialisation")
Set img = sh.OLEObjects.Add(ClassType:="Forms.Image.1", Link:=False, _
DisplayAsIcon:=False, Left:=147, Top:=42, Width:=85.5, Height:=37.5)
'Second add image to your OleObject
Dim iobj As MSForms.Image
Set iobj = img.Object
iobj.Picture = LoadPicture("C:\Users\User.Name\Pictures\SamplePicture.gif")
I declared and set the object types so you'll know what type of object you're working on.
In VBA, certain type of objects belong to certain collection of objects.
You'll need to check the specific type of object you want so work on so you can view the available properties and method for it and thus execute the correct code. HTH.
OP Update:
Thanks for the code KazJaw, it prompted me to change the approach I am trying to tackle the problem with. This is my current code:
Sub Method3()
Dim intFieldCount As Integer
Dim i As Integer
Dim vSt1 As String
intFieldCount = ActiveDocument.Fields.Count
For i = 1 To intFieldCount
ActiveDocument.Fields(i).Select 'selects the first field in the doc
Selection.Expand
vSt1 = Selection.Fields(1).Code
'MsgBox vSt1
vSt1 = Split(vSt1, " ")(2) 'Find out what the (2) does
MsgBox vSt1
ActiveDocument.Bookmarks(vSt1).Select 'Selects the current crossreference in the ref list
Next i
End Sub
Ok the so the Code currently finds the first field in the document, reads its field code and then jumps to the location in the document to mimic a CTRL+Click.
However, It does this for all types of fields Bookmarks, endnotes, figures, tables etc. I only want to find Reference fields. I thought I could deduce this from the field code but it turns out figures and bookmarks use the same field code layout ie.
A Reference/Boookmark has a field code {REF_REF4123123214\h}
A Figure cross ref has the field code {REF_REF407133655\h}
Is there an effective way to get VBA to distinguish between the two? I was thinking as reference fields in the document are written as (Reference 1) I could find the field and then string compare the word on the left to see if it says "Reference".
I was thinking of using the MoveLeft Method to do this
Selection.MoveLeft
But I can't work out how to move left 1 word from the current selection and select that word instead to do the strcomp
Or perhaps I can check the field type? with...
If Selection.Type = wdFieldRef Then
Do Something
End If
But I am not sure which "Type" i should be looking for.
Any advice is appreciated
All REF fields "reference" bookmarks. Word sets bookmarks on all objects that get a reference for a REF field: figures, headings, etc. There's no way to distinguish from the content of the field what's at the other end. You need to "inspect" that target, which you can do without actually selecting it. For example, you could check whether the first six letters are "Figure".
The code you have is inefficient - there's no need to use the Selection object to get the field code. The following is more efficient:
Sub Method3()
Dim fld As Word.Field
Dim rng as Word.Range
Dim vSt1 As String
ForEach fld in ActiveDocument.Fields
vSt1 = fld.Code
'MsgBox vSt1
vSt1 = Split(vSt1, " ")(2) 'Find out what the (2) does
MsgBox vSt1
Set rng = ActiveDocument.Bookmarks(vSt1).Range
If Left(rng.Text, 6) <> "Figure" Then
rng.Select
End If
Next
End Sub