I m trying to inactivate the edge fillet and chamfer feature to simplify the CATIA model.
I made the macro code as follow.
However, obiously, if the other features refer the fillet or chamfer, the part cannot be updated.
Thus, I want to inactivate the all children features, but I cannot find how to get the children relationship of selected feature.
Please give me help or insight to solve this problem
Thank you for your help
Sub CATMain()
Dim partDocument1 As Document
Set partDocument1 = CATIA.ActiveDocument
Dim part1 As Part
Set part1 = partDocument1.Part
If Err.Number = 0 Then
Dim selection1 As Selection
Set selection1 = partDocument1.Selection
selection1.Search "Name=*fillet*,all"
If selection1.Count = 0 Then
MsgBox "No fillet features"
Else
For i = 1 To selection1.Count
part1.Inactivate (selection1.Item2(i).Value)
Next 'i
'part1.Update
End If
Dim selection2 As Selection
Set selection2 = partDocument1.Selection
selection2.Search "Name=*chamfer*,all"
If selection2.Count = 0 Then
MsgBox "No chamfer features"
Else
For j = 1 To selection2.Count
part1.Inactivate (selection2.Item2(j).Value)
Next 'j
'part1.Update
End If
part1.Update
MsgBox ( tot_f_c_num & " features are inactivated.")
Else
MsgBox "Not a part document! Open a single part document."
End If
End Sub
#Shrotter I modified my macro as follow; it seems to work well at this time, but may have problem ::
Sub CATMain()
Dim partDocument1 As Document
Set partDocument1 = CATIA.ActiveDocument
Dim part1 As Part
Set part1 = partDocument1.Part
If Err.Number = 0 Then
Dim selection1 As Selection
Set selection1 = partDocument1.Selection
selection1.Search "Name=*fillet*,all"
If selection1.Count = 0 Then
MsgBox "No fillet features"
Else
For i = 1 To selection1.Count
part1.Inactivate (selection1.Item2(i).Value)
Next 'i
End If
Dim selection2 As Selection
Set selection2 = partDocument1.Selection
selection2.Search "Name=*chamfer*,all"
If selection2.Count = 0 Then
MsgBox "No chamfer features"
Else
For j = 1 To selection2.Count
part1.Inactivate (selection2.Item2(j).Value)
Next 'j
End If
Dim selection3 As Selection
Set selection3 = partDocument1.Selection
selection3.Search "Name=*,all"
For k = 1 To selection3.Count
On Error Resume Next
part1.UpdateObject (selection3.Item2(k).Value)
If Err.Number <> 0 Then
part1.Inactivate (selection3.Item2(k).Value)
End If
Next 'k
Else
MsgBox "Not a part document! Open a single part document."
End If
End Sub
I have been working on this code that takes misspelled words from a document and then turns them into a table with all the misspelled words on one column. Then the words are spellchecked and the corrections appear on the other column. My code does everything that I want it to, however only the first word appears on each cell. What am I doing wrong?
Sub SuperSpellCheck()
Dim doc1 As Document
Dim doc2 As Document
Dim tb As Table
Set doc1 = ActiveDocument
Set doc2 = Documents.Add
doc1.Activate
Dim badw As Range
Dim rng As Range
Dim sugg As SpellingSuggestions
Dim sug As Variant
err = doc1.SpellingErrors.Count
For Each badw In doc1.SpellingErrors
doc2.Range.InsertAfter badw & vbCr
Next
doc2.Activate
Set tb = ActiveDocument.Content.ConvertToTable(Separator:=wdSeparateByParagraphs, NumColumns:=1,
NumRows:=ActiveDocument.SpellingErrors.Count, AutoFitBehavior:=wdAutoFitFixed)
With tb
.Style = "Table Grid"
.ApplyStyleHeadingRows = True
.ApplyStyleLastRow = False
.ApplyStyleFirstColumn = True
.ApplyStyleLastColumn = False
.Columns.Add
.PreferredWidthType = wdPreferredWidthPercent
.PreferredWidth = 100
End With
err2 = ActiveDocument.SpellingErrors.Count
i = 1
Set sugg = doc2.Range.GetSpellingSuggestions
For Each rng In doc2.Range.SpellingErrors
With rng
If sugg.Count > 0 Then
Set sug = .GetSpellingSuggestions
tb.Cell(i, 2).Range.InsertAfter sug(1)
End If
End With
Next
End Sub
Not connected to your problem but you need to change these lines
Err = doc1.SpellingErrors.Count
err2 = ActiveDocument.SpellingErrors.Count
To:
Dim errors1 as Long, dim errors2 as Long
errors1 = doc1.SpellingErrors.Count
errors2 = doc2.SpellingErrors.Count
Err is an object in VBA that holds the errors generated by your code. You also haven't declared those variables. Add Option Explicit at the very top of your code module and you will be alerted to any undeclared variables. To turn this on automatically in future go to Tools | Options | Editor and ensure that Require Variable Declaration is checked.
I would change
Dim sugg As SpellingSuggestions
Dim sug As Variant
to
Dim docSugg As SpellingSuggestions
Dim rngSugg As SpellingSuggestions
Dim sug As SpellingSuggestion
This will make it clearer what each of these represents.
SpellingSuggestions is a collection of SpellingSuggestion objects so you can use sug to loop through the collection.
i = 1
Set sugg = doc2.Range.GetSpellingSuggestions
For Each rng In doc2.Range.SpellingErrors
With rng
If sugg.Count > 0 Then
Set sug = .GetSpellingSuggestions
tb.Cell(i, 2).Range.InsertAfter sug(1)
End If
End With
Next
In this block of code you start off by setting the undeclared variable i to a value of 1, but you don't then increase that value. This will result in all your spelling suggestions being inserted in the same cell. Also, when you insert the spelling suggestion you only ever insert the first one as you don't have a means of looping through them. So I would rewrite this as:
i = 1
Set docSugg = doc2.Range.GetSpellingSuggestions
For Each rng In doc2.Range.SpellingErrors
With rng
If docSugg.Count > 0 Then
Set rngSugg = .GetSpellingSuggestions
For Each sug In rngSugg
tb.Cell(i, 2).Range.InsertAfter sug
Next
End If
End With
i = i + 1
Next
EDIT: If you only want the first suggested spelling then use:
i = 1
Set docSugg = doc2.Range.GetSpellingSuggestions
For Each rng In doc2.Range.SpellingErrors
With rng
If docSugg.Count > 0 Then
Set rngSugg = .GetSpellingSuggestions
tb.Cell(i, 2).Range.InsertAfter rngSugg(1)
End If
End With
i = i + 1
Next
I dont do much word work, but I need to amend the address in the headers of a batch of letters. The address is held in tables in the headers. I also need to retain the formatting.
Below is the code I have ended up with - am I getting close?
Dim doc As Word.Document
Dim hf As Word.HeaderFooter
Dim lr As ListRow
Dim updated As Boolean
Dim tableCount As Integer
Dim t As Integer
Dim c As Cell
Set doc = wd.Documents.Open(Filename:=fi.Path, ReadOnly:=False)
For Each hf In doc.Sections(1).Headers()
tableCount = hf.Range.Tables.Count
For t = 1 To tableCount
For Each c In hf.Range.Tables(t).Range.Cells
If InStr(1, c.Range.Text, AddLOneOld) > 0 Then
updated = True
c.Range.Text = Replace(c.Range.Text, AddLOneOld, AddLOneNew)
End If
If InStr(1, c.Range.Text, AddLTwoOld) > 0 Then
updated = True
c.Range.Text = Replace(c.Range.Text, AddLTwoOld, AddLTwoNew)
End If
If InStr(1, c.Range.Text, AddLThreeOld) > 0 Then
updated = True
c.Range.Text = Replace(c.Range.Text, AddLThreeOld, AddLThreeNew)
End If
Next c
Next t
Next hf
If updated Then
Set lr = filesUpdated.ListRows.Add
lr.Range(1, 1) = fi.Path
doc.Save
End If
doc.Close False
This is the nearest I have got it to go as far as running, but all it does now is produce the error
"Microsoft Excel is waiting for another application to complete an OLE action"
Thanks
I guess this is a easy one but I can't figure it out.
I have a vba code in Excel which opens a Powerpoint presentation, find a certain type of shape ("Retângulo de cantos arredondados 9" = "Round corner' rectangle") and replace the existing text (MMM/AA) to another (TESTE).
Sub replace()
caminho_pptx = Cells(2, 2).Value
mes_ano = Cells(4, 2).Value
cx = "Retângulo de cantos arredondados 9"
Set ObjPPT = CreateObject("PowerPoint.Application")
Set ObjPresentation = ObjPPT.Presentations.Open("" & caminho_pptx & "")
For i = 1 To ObjPresentation.Slides.Count
ObjPresentation.Slides(i).Select
On Error GoTo Prox:
ObjPresentation.Slides(i).Shapes(cx).Select
If ObjPresentation.Slides(i).Shapes(cx).HasTextFrame Then
If ObjPresentation.Slides(i).Shapes(cx).TextFrame.HasText Then
If Obj + Presentation.Slides(i).Shapes(cx).TextFrame.TextRange.Find("MMM/AA") = "MMM/AA" Then
m = ObjPresentation.Slides(i).Shapes(cx).TextFrame.TextRange.Find("MMM/AA").Characters.Start
ObjPresentation.Slides(i).Shapes(cx).TextFrame.TextRange.Characters(m).InsertBefore ("TESTE")
ObjPresentation.Slides(i).Shapes(cx).TextFrame.TextRange.Find("MMM/AA").Delete
End If
End If
End If
Next i
Prox:
Next i
End Sub
The problem is that some slides doesn't have this shape, so if ObjPresentation.Slides(i).Shapes(cx).Select was not found the program have to go to the next i, but it doesn't work.
Both syntax of Prox: and its position seems to be wrong.
Any ideas?
You can use an On Error Resume Next statement to assign the shape to a variable, then test if that variable is not Nothing before trying to use it:
Sub replace()
Dim oShp As Object
caminho_pptx = Cells(2, 2).Value
mes_ano = Cells(4, 2).Value
cx = "Retângulo de cantos arredondados 9"
Set ObjPPT = CreateObject("PowerPoint.Application")
Set ObjPresentation = ObjPPT.Presentations.Open("" & caminho_pptx & "")
For i = 1 To ObjPresentation.Slides.Count
ObjPresentation.Slides(i).Select
On Error Resume Next
Set oShp = ObjPresentation.Slides(i).Shapes(cx)
On Error GoTo 0
If Not oShp Is Nothing Then
With oShp
If .HasTextFrame Then
If .TextFrame.HasText Then
If Obj + .TextFrame.TextRange.Find("MMM/AA") = "MMM/AA" Then
m = .TextFrame.TextRange.Find("MMM/AA").Characters.Start
.TextFrame.TextRange.Characters(m).InsertBefore ("TESTE")
.TextFrame.TextRange.Find("MMM/AA").Delete
End If
End If
End If
End With
Set oShp = Nothing
End If
Next i
End Sub
I'm trying to replace all shape objects on the slide (pictures) with shape objects of another type (rectangular shape). I can delete old object and create new, but i will loose all animation information and sequence order. Is it possible to store animation information and order in timeline, and copy it to the new shape object?
Well, i have found a solution myself, hope someone could find it useful. So, it is not necessary to copy animation information from old shape to a new one, just cycle through sequence's items and replace the shape object refrence to the new shape. Like this:
On Error Resume Next
Dim shp1 As Shape 'old shape
Set shp1 = ActivePresentation.Slides(1).Shapes(3)
Dim shp2 As Shape 'new shape
Set shp2 = ActivePresentation.Slides(1).Shapes.AddPicture("c:\imgres2.jpg", msoFalse, msoTrue, 0, 0) 'it is important to create new shape before cycling through existing ones.
For i = ActivePresentation.Slides(1).TimeLine.MainSequence.count To 1 Step -1
'using "is" opeartor to compare refrences
If shp1 Is ActivePresentation.Slides(1).TimeLine.MainSequence.Item(i).Shape Then
ActivePresentation.Slides(1).TimeLine.MainSequence.Item(i).Shape = shp2
End If
Next i
shp1.Delete 'delete the old shape
Try something like this code to copy the animation into new added shape:
Sub PasteAnimationBehaviours()
Dim SHP As Shape 'for existing shape
Set SHP = ActivePresentation.Slides(1).Shapes(1)
SHP.PickupAnimation
Dim newSHP As Shape 'pasting to new shape
Set newSHP = ActivePresentation.Slides(1).Shapes.AddShape(msoShapeRectangle, 100, 100, 100, 100)
newSHP.ApplyAnimation
End Sub
Added after comment: If you only need to replace type of shape try to use something like this:
Sub ShapeSubstition()
Dim SHP As Shape 'for existing shape
'test for 1st shape in 1st slide
Set SHP = ActivePresentation.Slides(1).Shapes(1)
SHP.AutoShapeType = msoShapeRectangle 'to rectangle
SHP.AutoShapeType = msoShapeOval 'to oval
End Sub
I think it is probably easier to just use the "Animation Painter" command button to copy the animations and apply them to another object. The Animation Painter functions in the same way as the Format Painter. After you have copied the desired animations, you can reorder the individual animations using the Animation Pane.
This code shows how to copy effects from one shape to another. Select a shape before running routine "SetSourceShape" and select one or more shapes before running "PaintEffects".
Option Explicit
' resources:
' http://msdn.microsoft.com/en-us/library/aa168134(v=office.11).aspx
' http://msdn.microsoft.com/en-us/library/aa168135(office.11).aspx
' http://skp.mvps.org/ppttimeline1.htm
' uses functions from:
' https://answers.microsoft.com/en-us/msoffice/forum/all/how-to-copy-paste-animation-effect-in-powerpoint/c0f255c0-167a-4a12-ae37-1e713ee1d8df
Public MySourceShapeId As Long
Public MySourceSlideIndex As Long ' need this with shape id for unique selection
Sub SetSourceShape() ' sets source shape id value if successfull
Dim oShp As PowerPoint.Shape
Dim myShp As PowerPoint.Shape
Dim oSld As Slide
Dim oEffect As Effect
Dim HowMany As Long
Dim FoundEffect As Boolean
HowMany = 0 ' default value for nothing selected
MySourceShapeId = 0 ' default value for nothing available to copy
MySourceSlideIndex = 0
FoundEffect = False ' default value unless selected shape has any effect(s)
On Error Resume Next ' handles error when nothing is selected
HowMany = ActiveWindow.Selection.ShapeRange.Count
On Error GoTo 0 ' restore normal error handling
If HowMany = 0 Then
MsgBox "Nothing is selected"
Else
If HowMany = 1 Then
Set oShp = ActiveWindow.Selection.ShapeRange(1) ' selection on a single slide
For Each oEffect In ActiveWindow.Selection.SlideRange(1).TimeLine.MainSequence
If oEffect.Shape.Id = oShp.Id Then
MySourceShapeId = oShp.Id
MySourceSlideIndex = ActiveWindow.Selection.SlideRange(1).SlideIndex
FoundEffect = True
End If
Next
If FoundEffect Then
MsgBox "Source is selected, Slide: " & MySourceSlideIndex & ", ShapeID: " & MySourceShapeId
Else
MsgBox "Selected item has no effect(s)"
End If
Else
MsgBox "Select only one item"
End If
End If
End Sub
Sub PaintEffects()
Dim oShp As PowerPoint.Shape
Dim oEffect As Effect
Dim HowMany As Long
Dim msg As String
HowMany = 0 ' default value for nothing selected
If MySourceShapeId = 0 Then
MsgBox "No source is selected"
Exit Sub
End If
On Error Resume Next ' handles error when nothing is selected
HowMany = ActiveWindow.Selection.ShapeRange.Count
On Error GoTo 0 ' restore normal error handling
If HowMany = 0 Then
MsgBox "Nothing is selected to paint"
Else
' make sure source is not in this selection
If ActiveWindow.Selection.SlideRange(1).SlideIndex = MySourceSlideIndex Then ' check shapes
For Each oShp In ActiveWindow.Selection.ShapeRange
If oShp.Id = MySourceShapeId Then ' complain
MsgBox "Target selection must not include source item"
Exit Sub
End If
Next
End If
' OK, proceed
For Each oShp In ActiveWindow.Selection.ShapeRange
For Each oEffect In ActivePresentation.Slides(MySourceSlideIndex).TimeLine.MainSequence
If oEffect.Shape.Id = MySourceShapeId Then
Call TransferEffects(oEffect, ActiveWindow.Selection.SlideRange(1), oShp)
End If
Next
Next
End If
End Sub
Sub TransferEffects(oEffectA As PowerPoint.Effect, oSlide As Slide, oShape As PowerPoint.Shape)
Dim oEffectB As Effect
Dim IsMotion As Boolean
Set oEffectB = oSlide.TimeLine.MainSequence.AddEffect(oShape, oEffectA.EffectType)
DoEvents
On Error Resume Next
oEffectB.EffectParameters.Amount = oEffectA.EffectParameters.Amount
If Err.Number = 0 Then
Select Case oEffectA.EffectParameters.Color2.Type
Case Is = msoColorTypeScheme
oEffectB.EffectParameters.Color2.SchemeColor = oEffectA.EffectParameters.Color2.SchemeColor
Case Is = msoColorTypeRGB
oEffectB.EffectParameters.Color2.RGB = oEffectA.EffectParameters.Color2.RGB
End Select
End If
oEffectB.EffectParameters.Direction = oEffectA.EffectParameters.Direction
oEffectB.EffectParameters.FontName = oEffectA.EffectParameters.FontName
If oEffectA.EffectType <> msoAnimEffectGrowShrink Then
oEffectB.EffectParameters.Size = oEffectA.EffectParameters.Size
Else
oEffectB.Behaviors(1).ScaleEffect.ByX = oEffectA.Behaviors(1).ScaleEffect.ByX
oEffectB.Behaviors(1).ScaleEffect.ByY = oEffectA.Behaviors(1).ScaleEffect.ByY
End If
oEffectB.Timing.Duration = oEffectA.Timing.Duration
oEffectB.Timing.Accelerate = oEffectA.Timing.Accelerate
oEffectB.Timing.AutoReverse = oEffectA.Timing.AutoReverse
oEffectB.Timing.Decelerate = oEffectA.Timing.Decelerate
oEffectB.Timing.Restart = oEffectA.Timing.Restart
oEffectB.Timing.RewindAtEnd = oEffectA.Timing.RewindAtEnd
oEffectB.Timing.SmoothStart = oEffectA.Timing.SmoothStart
oEffectB.Timing.SmoothEnd = oEffectA.Timing.SmoothEnd
oEffectB.Exit = oEffectA.Exit
oEffectB.Timing.TriggerType = oEffectA.Timing.TriggerType
oEffectB.Timing.TriggerDelayTime = oEffectA.Timing.TriggerDelayTime
oEffectB.Timing.RepeatCount = oEffectA.Timing.RepeatCount
oEffectB.Timing.RepeatDuration = oEffectA.Timing.RepeatDuration
oEffectB.Timing.Speed = oEffectA.Timing.Speed
With oSlide.TimeLine.MainSequence
If oEffectA.Shape.HasTextFrame Then
Call .ConvertToAnimateBackground(oEffectB, oEffectA.EffectInformation.AnimateBackground)
Else
Call .ConvertToAnimateBackground(oEffectB, True)
End If
Select Case oEffectA.EffectInformation.AfterEffect
Case 2 ' Hide
Call .ConvertToAfterEffect(oEffectB, oEffectA.EffectInformation.AfterEffect)
Case 1 ' Dim
Call .ConvertToAfterEffect(oEffectB, oEffectA.EffectInformation.AfterEffect, oEffectA.EffectInformation.Dim)
Case 3 ' Hide on click
Call .ConvertToAfterEffect(oEffectB, oEffectA.EffectInformation.AfterEffect)
End Select
Call .ConvertToAnimateInReverse(oEffectB, oEffectA.EffectInformation.AnimateTextInReverse)
Call .ConvertToTextUnitEffect(oEffectB, oEffectA.EffectInformation.TextUnitEffect)
End With
Err.Clear
oEffectB.EffectParameters.Relative = oEffectA.EffectParameters.Relative
If Err.Number <> 0 Then
IsMotion = False
Else
IsMotion = True
End If
If IsMotion Then
oEffectB.Behaviors(1).MotionEffect.Path = oEffectA.Behaviors(1).MotionEffect.Path
On Error GoTo 0
If Sgn(Val(oEffectA.Behaviors(1).Timing.Speed)) = -1 Then
oEffectB.Behaviors(1).MotionEffect.Path = Left(oEffectA.Behaviors(1).MotionEffect.Path, 1) & " " & ReversePathInfo(Trim(Mid(oEffectA.Behaviors(1).MotionEffect.Path, 2)))
End If
End If
Exit Sub
errHandler:
If MsgBox(Err.Number & " " & Err.Description & vbCrLf & "Do you wish to continue?", vbQuestion + vbYesNo, "APP_NAME") = vbYes Then
Resume Next
End If
End Sub
Function ReversePathInfo(sPath As String) As String
Dim sItems() As String
Dim i As Integer
Dim sPositions() As String
Dim sReversedPath As String
Dim sClosedPath As String
If Not IsNumeric(Right(sPath, 1)) Then
sClosedPath = Right(sPath, 1)
sPath = Left(sPath, Len(sPath) - 1)
End If
sPath = Replace(sPath, " ", "~")
sItems = Split(sPath, "~")
ReDim sPositions(0 To UBound(sItems))
For i = LBound(sItems) To UBound(sItems)
If Left(sItems(i), 1) = "L" Then sPositions(i) = "L"
If Left(sItems(i), 1) = "C" Then sPositions(i) = "C"
If Left(sItems(i), 1) = "c" Then sPositions(i) = "c"
If Left(sItems(i), 1) = "l" Then sPositions(i) = "l"
Next i
For i = LBound(sPositions) To UBound(sPositions)
If LCase(sPositions(i)) = "c" Then
sPositions(i + 2) = sPositions(i)
sPositions(i) = ""
i = i + 2
End If
Next i
For i = UBound(sItems) To LBound(sItems) Step -1
Select Case Left(sItems(i), 1)
Case "L", "C", "c", "l"
sItems(i) = Trim(Mid(sItems(i), 2))
End Select
sReversedPath = sReversedPath & sItems(i) & " " & sPositions(i) & IIf(sPositions(i) <> "", " ", "")
Next i
ReversePathInfo = Trim(sReversedPath) & IIf(sClosedPath = "", "", " " & sClosedPath)
End Function