Copying animation and sequence information between powerpoint shapes - vba

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

Related

The specified value is out of range

I am trying to write some code that returns in the Immediate Window the slide number of every slide that contains at least one Text Box with a red font, but the following error keeps popping up. Do you have ideas on how I can solve the problem?
Below the error I get:
Run-time error'-2147024809(80070057)
The specified value is out of range.
The line that causes it is:
ElseIf shp.TextFrame.TextRange.Font.Color.RGB = RGB(255, 0, 0) Then
This is the full code of the Subroutine:
Sub redfont()
Dim sld As Slide
Dim shp As Shape
Dim x As Byte
Dim z, i
With ActivePresentation
z = .Slides(.Slides.Count).SlideNumber
MsgBox z, vbDefaultButton1, "Total Slides"
End With
Dim myCol As Collection
Set myCol = New Collection
For i = 2 To z
Set sld = ActivePresentation.Slides(i)
For Each shp In sld.Shapes
If x = 1 Then
x = 1
ElseIf shp.TextFrame.TextRange.Font.Color.RGB = RGB(255, 0, 0) Then
myCol.Add CStr(i), CStr(i)
x = 1
End If
Next shp
x = 0
Next
Dim j As Long
For j = 1 To myCol.Count
Debug.Print myCol.Item(j)
Next j
End Sub
Since not all Shapes have a TextFrame, you need to check first whether your shape has one or not before trying to access it.
Use the .HasTextFrame property for that purpose.
The general pattern is:
If shp.HasTextFrame Then
'Access shp.TextFrame inside here
'For example:
shp.TextFrame.TextRange.Text = "New Text"
End If
In your specific case the correct code would look like this:
For i = 2 To z
Set sld = ActivePresentation.Slides(i)
For Each shp In sld.Shapes
If shp.HasTextFrame Then
If shp.TextFrame.TextRange.Font.Color.RGB = RGB(255, 0, 0) Then
myCol.Add CStr(i), CStr(i)
Exit For
End If
End If
Next
Next
BTW: you don't need the x variable, just exit the loop when the first condition is met.

vba excel combo box in userform

Basically the module Onboarding is asking the path of the tracker i want to update. I am updating details in the
sheet1 of the tracker.
I am setting the values of fields in userform 'OnboardingForm' to blank(so that the values entered last time to the
form is not visible when I am opening the form this time.
Now I am opening the form 'OnboardingForm' and entering values in the subsequent fields.
I have put a check button in my userform 'OnboardingForm' which is invisible to the front end user.
Now in the tracker there is a sheet named 'Project Tracks' which has information of all current projects
Once the submit button is clicked the control will go to the tracker's 'Project Tracks' sheet. It will validate the
track entered in the userform 'OnboardingForm' with the tracks present in the tracker's 'Project Tracks' sheet. Once found the other details against that particular track will get fetched to the tracker's sheet1(this I have done so that I will not have to enter values manually to the userform 'OnboardingForm' so that the form looks simple). There are no chances of the track not
matching.
Now one command button new track has been put in my current userform 'OnboardingForm'. Once clicked this will take the control to
the userform2 'ProjectTracksForm'.This is basically put so that if I am adding a new track, the form takes the detail and enters in the
tracker's 'Project Tracks' sheet.
Question 1> My current userform's Track button is a combo box. How do I add values in the dropdown from the tracker's
'Project Tracker' sheet to the dropdown.
Question 2> Once I add a new track in userform2 'ProjectTracksForm',submit and then when I come back to my current
userform 'OnboardingForm' that added track should be shown in the dropdown of Track combo box.
Please find below my piece of code.
This is my module for onboarding
Public Sub OnBoarding()
On Error GoTo ErrorHandler
Dim Owb As Object
Dim ran As Range
strTalentTrackerPath = shTracker.Cells(2, 2).Value
'Default the form values to null
With OnboardingForm
.combTrackofWork.Value = ""
.txtFirstName.Text = ""
.txtLastName.Text = ""
.combResCat.Value = ""
.combBFTE.Value = ""
.combLevel.Value = ""
.combLocType = ""
.txtAccessInfo.Text = ""
End With
OnboardingForm.Show
SetFocus.combTrackofWork
With OnboardingForm
'Details to be entered in the form'
strTOW = Trim$(.combTrackofWork.Value)
strFN = Trim$(.txtFirstName.Text)
strLN = Trim$(.txtLastName.Text)
strResCat = Trim$(.combResCat.Value)
strBilFTE = Trim$(.combBFTE.Value)
strLevel = Trim$(.combLevel.Value)
strLocType = (.combLocType.Value)
strAccessInfo = (.txtAccessInfo.Text)
End With
If OnboardingForm.chkOKButtonClick = True Then
Set oExcel = New Excel.Application
strMyFolder = strTalentTrackerPath
Set Owb = oExcel.Workbooks.Open(strMyFolder)
IntRowCount = Owb.Sheets(1).UsedRange.Rows.Count
With Owb.Sheets(1)
With Owb.Sheets("Project Tracks")
IntTrackRowCount = .UsedRange.Rows.Count
For IntCurrentRow = 1 To IntTrackRowCount
If .Cells(IntCurrentRow, 1) = strTOW Then
Owb.Sheets(1).Cells(IntRowCount + 1, OnboardingFormcolumn.colTrackofWork) _
= .Cells(IntCurrentRow, ProjectTrackscolumn.colTrack)
Owb.Sheets(1).Cells(IntRowCount + 1, OnboardingFormcolumn.colBPO) = .Cells _
(IntCurrentRow, ProjectTrackscolumn.colBPO)
Owb.Sheets(1).Cells(IntRowCount + 1, OnboardingFormcolumn.colCostCenter) _
= .Cells(IntCurrentRow, ProjectTrackscolumn.colCostCenter)
Owb.Sheets(1).Cells(IntRowCount + 1, OnboardingFormcolumn.colGroup) _
= .Cells(IntCurrentRow, ProjectTrackscolumn.colGroup)
Exit For
End If
Next
End With
End With
.Cells(IntRowCount + 1, OnboardingFormcolumn.colTrackofWork) = strTOW
.Cells(IntRowCount + 1, OnboardingFormcolumn.colFirstName) = strFN
.Cells(IntRowCount + 1, OnboardingFormcolumn.colLastName) = strLN
.Cells(IntRowCount + 1, OnboardingFormcolumn.colResourceCategory) = strResCat
.Cells(IntRowCount + 1, OnboardingFormcolumn.colBilledFTE) = strBilFTE
.Cells(IntRowCount + 1, OnboardingFormcolumn.colLevel) = strLevel
.Cells(IntRowCount + 1, OnboardingFormcolumn.colLocationType) = strLocType
.Cells(IntRowCount + 1, OnboardingFormcolumn.colAccessInformation) = strAccessInfo
Owb.Close True
Set Owb = Nothing
Set oExcel = Nothing
Else
Exit Sub
End If
Exit Sub
ErrorHandler:
If Owb Is Nothing Then
Else
Owb.Close False
End If
If oExcel Is Nothing Then
Else
Set oExcel = Nothing
End If
MsgBox "Unhandled Error. Please Report" & vbCrLf & "Error Description: " & _
Err.Description, vbExclamation
End Sub
This is for cancel button of Onboarding Form
Private Sub cmdbtn_Cancel_Click()
OnboardingForm.Hide
MsgBox ("No data entered")
End Sub
This is for OnboardingForm submit button
Private Sub cmdbtn_Submit_Click()
If Trim(OnboardingForm.combTrackOfWork.Value) = "" Then
OnboardingForm.combTOW.SetFocus
MsgBox ("Track of Work cannot be blank")
Exit Sub
End If
If Trim(OnboardingForm.txtFirstName.Value) = "" Then
OnboardingForm.txtFN.SetFocus
MsgBox ("First name cannot be blank")
Exit Sub
End If
If Trim(OnboardingForm.txtLastName.Value) = "" Then
OnboardingForm.txtLN.SetFocus
MsgBox ("Last name cannot be blank")
Exit Sub
End If
End Sub
Module for Project Tracks
Public Sub prjctTracks()
On Error GoTo ErrorHandler
Dim Owb As Object
strTalentTrackerPath = shTracker.Cells(2, 2).Value
With ProjectTracksForm
.txtTOW = ""
.txtBPO = ""
.txtCOCE = ""
.txtSOW = ""
.txtGroup = ""
End With
ProjectTracksForm.Show
With ProjectTracksForm
strTOW = Trim$(.txtTOW.Text)
strBPO = Trim$(.txtBPO.Text)
strCOCE = Trim$(.txtCOCE.Text)
strSOW = Trim$(.txtSOW.Value)
strGroup = Trim$(.txtGroup.Value)
End With
ProjectTracksForm.Hide
If ProjectTracksForm.chkbtn_OKclick = True Then
Set oExcel = New Excel.Application
strMyFolder = strTalentTrackerPath
Set Owb = oExcel.Workbooks.Open(strMyFolder)
With Owb.Sheets("Project Tracks")
intUsedRowCount = .UsedRange.Rows.Count
.Cells(intUsedRowCount + 1, Trackscolumn.colTrack) = strTOW
.Cells(intUsedRowCount + 1, Trackscolumn.colBPO) = strBPO
.Cells(intUsedRowCount + 1, Trackscolumn.colCostCenter) = strCOCE
.Cells(intUsedRowCount + 1, Trackscolumn.colSOW) = strSOW
.Cells(intUsedRowCount + 1, Trackscolumn.colGroup) = strGroup
End With
Owb.Close True
Set Owb = Nothing
Set oExcel = Nothing
Else
Exit Sub
End If
Exit Sub
ErrorHandler:
If Owb Is Nothing Then
Else
Owb.Close False
End If
If oExcel Is Nothing Then
Else
Set oExcel = Nothing
End If
MsgBox "Unhandled Error. Please Report" & vbCrLf & "Error Description: " & _
Err.Description, vbExclamation
End Sub
Question 1> My current userform's Track button is a combo box. How do
I add values in the dropdown from the tracker's 'Project Tracker'
sheet to the dropdown.
I am calling the combobox "ComboBox1" in this example
The Range to place in the combobox would look like this...
The code to populate the combobox would be in the Userform Module.
Private Sub UserForm_Initialize()
Dim LstRw As Long
Dim Rng As Range
Dim ws As Worksheet
Set ws = Sheets("Project Tracker")
With ws
LstRw = .Cells(.Rows.Count, 1).End(xlUp).Row
Set Rng = .Range("A2:A" & LstRw)
End With
ComboBox1.List = Rng.Value
End Sub
Question 2> Once I add a new track in userform2
'ProjectTracksForm',submit and then when I come back to my current
userform 'OnboardingForm' that added track should be shown in the
dropdown of Track combo box
When you activate your userform again, you can clear the combobox and repopulate it with the new list.
Private Sub UserForm_Activate()
Dim LstRw As Long
Dim Rng As Range
Dim ws As Worksheet
Set ws = Sheets("Project Tracker")
With ws
LstRw = .Cells(.Rows.Count, 1).End(xlUp).Row
Set Rng = .Range("A2:A" & LstRw)
End With
ComboBox1.Clear
ComboBox1.List = Rng.Value
End Sub
I assume that somewhere you would have a code that will add a new item to the List in sheet("Project Tracker"),
Something like:
Private Sub CommandButton1_Click()
'THIS IS IN THE OTHER USERFORM
'add item to first blank cell in column A sheets("Project Tracker")
Dim sh As Worksheet
Dim LstRws As Long
Set sh = Sheets("Project Tracker")
With sh
LstRws = .Cells(.Rows.Count, "A").End(xlUp).Row + 1
.Cells(LstRws, 1) = "SomeThingNew" 'whatever you are adding to the list
End With
End Sub
The code will add something new to the list in your worksheet.
When you show the form again, the new item will be in the combobox.
You can either use a Button, Combobox event, textbox event, to add the item to the new list.

Correct placement and syntax of On error go to

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

Change Shape color in a loop VBA PPT

I need to change Colors of certain Shapes in a slide, based on the criteria if the shape is an EndConnectedShape of certain Connectors (the connectors are selected based on some data in a .txt file, but the data input part works fine).
Although it must be straightforward, the part where I try to get the Shape by its Name is still not working:
Sub test()
Dim oFSO As FileSystemObject
Set oFSO = New FileSystemObject
Dim oFS As TextStream
Dim i, j As Long
Dim filePath, smth As String
filePath = "C:\MyPath\MyFile.txt"
If oFSO.FileExists(filePath) Then
On Error GoTo Err
Set oFS = oFSO.OpenTextFile(filePath)
For i = 1 To 1
smth = VecNames(j) ' ADDED
wholeLine1 = oFS.ReadLine
VecNames = Split(wholeLine1, ",")
wholeLine2 = oFS.ReadLine
VecSIs = Split(wholeLine2, ",")
For j = 1 To UBound(VecNames)
With ActivePresentation.Slides(i)
For Each oSh In ActivePresentation.Slides(i).Shapes
If oSh.Connector And oSh.Name = smth Then
'Degub.Print oSh.Name
oSh.Line.ForeColor.RGB = RGB(255, 0, 0)
oSh.Line.Weight = VecSIs(j) * 5
strShNm = oSh.ConnectorFormat.EndConnectedShape.Name
' NEXT LINE IS NOT WORKING :
mySh = ActivePresentation.Slides(i).Shapes(strShNm)
' When tried to change the line above to the one below which is commented out, it DOESN'T work either:
' mySh = Selection.ShapeRange(strShNm)
With mySh
mySh.Line.ForeColor.RGB = RGB(255, 0, 0)
End With
ElseIf oSh.Type = msoTextBox Then
If mySh.TextFrame.TextRange.Text = VecNames(j) Then
oSh.TextFrame.TextRange.Font.Color = RGB(255, 0, 0)
End If
End If
Next oSh
End With
Next j
Next i
oFS.Close
Else
MsgBox "The file path is invalid.", vbCritical, vbNullString
Exit Sub
End If
Exit Sub
Err:
MsgBox "Error while reading the file.", vbCritical, vbNullString
oFS.Close
Exit Sub
End Sub
Any idea what am I doing wrong? Thanks!
In this code:
strShNm = oSh.ConnectorFormat.EndConnectedShape.Name
mySh = ActivePresentation.Slides(i).Shapes(strShNm)
You're getting the name from the shape, then trying to get the shape from the name...
Much easier to do this (and don't forget to use Set):
Set mySh = oSh.ConnectorFormat.EndConnectedShape

Powerpoint & VBA New slide if table bottom exceeds the bottom of the slide

So i have been struggling with this for the past few days, i have this powerpoint 2007 presentation that i fill with information from a button in a from in a access file using VBA.
And in the first slide (and only by now) i have a table that will receive part of the information, however i can't make the table content break to another slide if the table exceeds the bottom of the slide, it just goes out of range.
I have the method to create a the new slide, and that works fine. But i can't seem to find an example that could get me started.
I think i should be something like check the table bottom exceeds slide bottom if it does create a new slide, cut the overlap cells and paste them in the new slide?
Thanks in Advance.
The code example:
' Open PowerPoint
Dim pptobj As PowerPoint.Application
Dim Presentation As PowerPoint.Presentation
Dim oSl as Slide
Set pptobj = New PowerPoint.Application
Set pptobj = CreateObject("Powerpoint.Application")
pptobj.Activate
Set Presentation = pptobj.Presentations.Open("C:\Users\some.pptx")
pptobj.Visible = True
pptobj.WindowState = ppWindowMaximized
If ((Len(Forms!Some!Name> 0) Then
pptobj.ActivePresentation.Slides(1).Shapes("TableNome").Table.Cell(1, 1).Shape.TextFrame.TextRange.Text = (CStr(Forms!Some!Name))
End If
Set oSl = pptobj.ActivePresentation.Slides(1)
With oSl
.Shapes("TableCategory").Table.Cell(1, 1).Shape.TextFrame.TextRange.Text = (CStr(Forms!CVLong!TxtCategory))
.Shapes("TableEmail").Table.Cell(1, 2).Shape.TextFrame.TextRange.Text = (CStr(Forms!Some!TxtEmail))
.Shapes("TableData").Table.Cell(1, 2).Shape.TextFrame.TextRange.Text = (CStr(Forms!Some!TxtTlf))
.Shapes("TableData").Table.Cell(2, 2).Shape.TextFrame.TextRange.Text = (CStr(Forms!Some!TxtCell))
End With
Dim oSh as Shape
Dim overhang
Set oSh = pptobj.ActivePresentation.Slides(1).Shapes.AddTable(1, 3, 50, 100, 493)
'One
If ((Len(Forms!Some!One)) > 0) Then
pptobj.ActivePresentation.Slides(1).Shapes("TableInfo").Table.Cell(1, 3).Shape.TextFrame.TextRange.Text = (CStr(Forms!Some!One)) & vbNewLine & vbNewLine
pptobj.ActivePresentation.Slides(1).Shapes("TableInfo").Table.Cell(1, 1).Shape.TextFrame.TextRange.Text = "One"
End If
'Two
If (Len(Forms!Some!Two> 0) Then
pptobj.ActivePresentation.Slides(1).Shapes("TableInfo").Table.Cell(5, 3).Shape.TextFrame.TextRange.Text = (CStr(Forms!Some!Two)) & vbNewLine
pptobj.ActivePresentation.Slides(1).Shapes("TableInfo").Table.Cell(5, 1).Shape.TextFrame.TextRange.Text = "Two"
End If
'Three
If (Len(Forms!Some!Three) > 0) Then
pptobj.ActivePresentation.Slides(1).Shapes("TableInfo").Table.Cell(4, 3).Shape.TextFrame.TextRange.Text = (CStr(Forms!Some!Three)) & vbNewLine & vbNewLine
pptobj.ActivePresentation.Slides(1).Shapes("TableInfo").Table.Cell(4, 1).Shape.TextFrame.TextRange.Text = "Three"
End If
'Add Slide
Dim Sld As Slide
Dim x As Integer
x = 1
Set Sld = pptobj.ActivePresentation.Slides.Add(Index:=pptobj.ActivePresentation.Slides.Count + 1, Layout:=ppLayoutBlank)
For Each Sld In pptobj.ActivePresentation.Slides
If x >= 2 Then
pptobj.ActivePresentation.Slides(1).Shapes("Text Placeholder 15").Copy
pptobj.ActivePresentation.Slides(x).Shapes.Paste
pptobj.ActivePresentation.Slides(x).Shapes("Text Placeholder 15").ZOrder msoSendToBack
pptobj.ActivePresentation.Slides(x).Shapes("Text Placeholder 15").Height = 810
pptobj.ActivePresentation.Slides(x).Shapes("Text Placeholder 15").Top = 19
End If
x = x + 1
Next
End If
'Put table top border
Dim n As Integer
Dim r As Integer
n = 3
r = 1
While r <= n
If Len(pptobj.ActivePresentation.Slides(1).Shapes("TableInfo").Table.Cell(r, 3).Shape.TextFrame.TextRange.Text) > 0 Then
pptobj.ActivePresentation.Slides(1).Shapes("TableInfo").Table.Cell(r, 3).Borders(ppBorderTop).Visible = msoTrue
pptobj.ActivePresentation.Slides(1).Shapes("TableInfo").Table.Cell(r, 3).Borders(ppBorderTop).ForeColor.RGB = RGB(220, 105, 0)
Else
pptobj.ActivePresentation.Slides(1).Shapes("TableInfo").Table.Rows(r).Delete
n = n - 1
r = r - 1
End If
r = r + 1
Wend
'Add Photo
pptobj.ActivePresentation.Slides(1).Shapes.AddPicture(FileName:="\\someplace\" & [Id] & ".jpg", linktofile:=mostrue, savewithdocument:=msoTrue, Left:=52, Top:=115).Select
With pptobj.ActivePresentation.Slides(1).Shapes("Picture 7")
.LockAspectRatio = msoTrue
.Width = 85
.Left = 38
.Top = 80
End With
'add footer
Dim page As Integer
page = 1
Dim s As Slide
For Each s In pptobj.ActivePresentation.Slides
On Error Resume Next
Set oSh = s.HeadersFooters.Footer
If Err.Number <> 0 Then
Call s.Master.Shapes.AddPlaceholder(ppPlaceholderFooter, 219, 805, 342, 19)
End If
On Error GoTo 0
s.HeadersFooters.Footer.Visible = msoTrue
s.HeadersFooters.Footer.Text = (CStr(Forms!Some!Name)) & " - Page " & page & " of " & pptobj.ActivePresentation.Slides.Count
page = page + 1
Next
The following code snippet may give you some inspiration. Right now it just determines that the table is too large and gives you a message. Without more information about the type of data and how you obtained it, it's hard to give an answer to the second part of the problem. Most likely you would create a table, add one row at a time and check the size of the table; when the table gets too large (or within a certain distance from the bottom) you create a new slide and continue the process. That is probably better than creating a table that's too large, then trying to figure out where to cut it.
Here is the code:
Sub createTable()
Dim oSl As Slide
Dim oSh As Shape
Dim overhang
Set oSl = ActivePresentation.Slides(1)
Set oSh = oSl.Shapes.AddTable(28, 3)
overhang = ActivePresentation.PageSetup.SlideHeight - (oSh.Height + oSh.Top)
If overhang > 0 Then
MsgBox "the table fits"
Else
MsgBox "the table is too big!"
End If
End Sub