I have a macro that creates a new slide at the beginning of a section in my PowerPoint presentation.
Is there a method to replace .MoveToSectionStart that would move the slide to the end?
The method is found in the Sub at the end called Sub AddCustomSlide().
Private Function GetSectionNumber( _
ByVal sectionName As String, _
Optional ParentPresentation As Presentation = Nothing) As Long
If ParentPresentation Is Nothing Then
Set ParentPresentation = ActivePresentation
End If
GetSectionNumber = -1
With ParentPresentation.SectionProperties
Dim i As Long
For i = 1 To .Count
If .Name(i) = sectionName Then
GetSectionNumber = i
Exit Function
End If
Next i
End With
End Function
Public Function GetLayout( _
LayoutName As String, _
Optional ParentPresentation As Presentation = Nothing) As CustomLayout
If ParentPresentation Is Nothing Then
Set ParentPresentation = ActivePresentation
End If
Dim oLayout As CustomLayout
For Each oLayout In ParentPresentation.SlideMaster.CustomLayouts
If oLayout.Name = LayoutName Then
Set GetLayout = oLayout
Exit For
End If
Next
End Function
Sub AddCustomSlide()
Dim oSlides As Slides, oSlide As Slide
Dim Shp As Shape
Dim Sld As Slide
Set oSlides = ActivePresentation.Slides
Set oSlide = oSlides.AddSlide(oSlides.Count - 2, GetLayout("Processwindow"))
oSlide.MoveToSectionStart GetSectionNumber("Main Process")
End Sub
Sorry, there's no such method. Here's how to insert one at the end:
Sub AddCustomSlide()
Dim oSlides As Slides, oSlide As Slide
Dim Shp As Shape
Dim Sld As Slide
Dim SecNum As Integer, SlideCount As Integer, FirstSecSlide As Integer
Set oSlides = ActivePresentation.Slides
Set oSlide = oSlides.AddSlide(oSlides.Count - 2, GetLayout("Processwindow"))
SecNum = GetSectionNumber("Main Process")
With ActivePresentation.SectionProperties
SlideCount = .SlidesCount(SecNum)
FirstSecSlide = .FirstSlide(SecNum)
End With
oSlide.MoveTo toPos:=FirstSecSlide + SlideCount - 1
End Sub
Related
I am trying to copy all true or checked boxes on all slides and paste them onto one slide within my presentation. I can't seem to figure it out. Below is the code that I am using. Any help is appreciated.
`Sub ckbxCopy()
Dim shp As Shape
Dim sld As Slide
Dim i As Integer
On Error Resume Next
For Each sld In ActivePresentation.Slides
For i = 1 To 4
shp = ActivePresentation.Slides("CheckBox" & CStr(i))
If Err.Number = 0 Then ' shape exists
If shp.OLEFormat.Object.Value = True Then
shp.Copy
ActivePresentation.Slides(3).Shapes.Paste
End If
End If
Next i
Next sld
End Sub`
This works for me:
Sub ckbxCopy()
Dim shp As Shape, pres As Presentation
Dim sld As Slide, sldDest As Slide
Dim i As Integer, t As Long
Set pres = ActivePresentation
Set sldDest = pres.Slides(3) 'where shapes are to be pasted
sldDest.Shapes.Range.Delete 'remove existing shapes
t = 20
For Each sld In pres.Slides
If sld.SlideIndex <> sldDest.SlideIndex Then
For i = 1 To 4
Set shp = Nothing
Set shp = SlideShape(sld, "CheckBox" & CStr(i))
If Not shp Is Nothing Then
If shp.OLEFormat.Object.Value = True Then
shp.Copy
pres.Slides(3).Shapes.Paste.Top = t 'paste and position
t = t + 20
End If
End If
Next i
End If
Next sld
End Sub
'Return a named shape from a slide (or Nothing if the shape doesn't exist)
Function SlideShape(sld As Slide, shapeName As String) As Shape
On Error Resume Next
Set SlideShape = sld.Shapes(shapeName)
End Function
Sub changelinkspp()
Dim oshp As Shape
Dim osld As Slide
Const replacethis As_String= _
"file:///C:\Users\admin\Desktop\file%20name%old\"
Const replacewith As String = _
"file:///\\local\new%20folder\file%20name%new"
On Error Resume Next
For Each osld In ActivePresentation.Slides
For Each oshp In osld.Shapes
If oshp.LinkFormat.SourceFullName Like "*admin*" Then
oshp.LinkFormat.SourceFullName = _
Replace(oshp.LinkFormat.SourceFullName, replacethis, replacewith)
it is where the main problem occurs. It does not work.
It seems like replace function in vba does not have an affect on oshp.LinkFormat.SourceFullName
oshp.LinkFormat.Update
End If
Next oshp
Next osld
End Sub
{Steve Rindsberg added:}
Try this as a test:
Sub SimpleTest()
Dim oshp As Shape
Dim osld As Slide
' For test purposes:
Dim sSource As String
sSource = "file:///C:\Users\admin\Desktop\file%20name%old\"
Const replacethis As String = _
"file:///C:\Users\admin\Desktop\file%20name%old\"
Const replacewith As String = _
"file:///\\local\new%20folder\file%20name%new"
On Error Resume Next
If sSource Like "*admin*" Then
Debug.Print Replace(sSource, replacethis, replacewith)
End If
End Sub
I am trying to add a slide, created with the below code, to a specific section called "Index".
Currently it is going two slides below the last one but because the number of slides will be chaining I can't reference using -2 function so I have to resort to section referencing.
Public Function GetLayout( _
LayoutName As String, _
Optional ParentPresentation As Presentation = Nothing) As CustomLayout
If ParentPresentation Is Nothing Then
Set ParentPresentation = ActivePresentation
End If
Dim oLayout As CustomLayout
For Each oLayout In ParentPresentation.SlideMaster.CustomLayouts
If oLayout.Name = LayoutName Then
Set GetLayout = oLayout
Exit For
End If
Next
End Function
Sub AddCustomSlide()
Dim oSlides As Slides, oSlide As Slide
Set oSlides = ActivePresentation.Slides
Set oSlide = oSlides.AddSlide(oSlides.Count - 2, GetLayout("Processwindow"))
End Sub
The solution is to use the .MoveToSectionStart method of the Slide object.
In your AddCustomSlide routine, add one line:
Sub AddCustomSlide()
Dim oSlides As Slides, oSlide As Slide
Set oSlides = ActivePresentation.Slides
Set oSlide = oSlides.AddSlide(oSlides.Count - 2, GetLayout("Title Only"))
oSlide.MoveToSectionStart GetSectionNumber("Index")
End Sub
Since you need the section number of the "Index" section, I've written a quick function to return that number:
Private Function GetSectionNumber( _
ByVal sectionName As String, _
Optional ParentPresentation As Presentation = Nothing) As Long
If ParentPresentation Is Nothing Then
Set ParentPresentation = ActivePresentation
End If
GetSectionNumber = -1
With ParentPresentation.SectionProperties
Dim i As Long
For i = 1 To .Count
If .Name(i) = sectionName Then
GetSectionNumber = i
Exit Function
End If
Next i
End With
End Function
I am trying to create a hyperlink on the newly created shape oSh to the newly created slide oSlide through VBA.
The shape is on a different slide than the newly created slide.
Code to create the shape and the slide.
Private Function GetSectionNumber( _
ByVal sectionName As String, _
Optional ParentPresentation As Presentation = Nothing) As Long
If ParentPresentation Is Nothing Then
Set ParentPresentation = ActivePresentation
End If
GetSectionNumber = -1
With ParentPresentation.SectionProperties
Dim i As Long
For i = 1 To .Count
If .Name(i) = sectionName Then
GetSectionNumber = i
Exit Function
End If
Next i
End With
End Function
Public Function GetLayout( _
LayoutName As String, _
Optional ParentPresentation As Presentation = Nothing) As CustomLayout
If ParentPresentation Is Nothing Then
Set ParentPresentation = ActivePresentation
End If
Dim oLayout As CustomLayout
For Each oLayout In ParentPresentation.SlideMaster.CustomLayouts
If oLayout.Name = LayoutName Then
Set GetLayout = oLayout
Exit For
End If
Next
End Function
Private Sub CommandButton1_Click()
Dim Sld As Slide
Dim Shp As Shape
'ERROR HANDLING
If ActivePresentation.Slides.Count < 5 Then
MsgBox "You do not have any slides in your PowerPoint project."
Exit Sub
End If
Set Sld = Application.ActiveWindow.View.Slide
If Sld.SlideIndex <> 5 Then
MsgBox "You are not on the correct slide."
Exit Sub
End If
Set Sld = Application.ActiveWindow.View.Slide
Call AddCustomSlide
Unload UserForm1
End Sub
Sub AddCustomSlide()
'Create new slide
Dim oSlides As Slides, oSlide As Slide
Dim Shp As Shape
Dim Sld As Slide
Dim SecNum As Integer, SlideCount As Integer, FirstSecSlide As Integer
Set oSlides = ActivePresentation.Slides
Set oSlide = oSlides.AddSlide(oSlides.Count - 2, GetLayout("Processwindow"))
SecNum = GetSectionNumber("Main Process")
With ActivePresentation.SectionProperties
SlideCount = .SlidesCount(SecNum)
FirstSecSlide = .FirstSlide(SecNum)
End With
oSlide.MoveTo toPos:=FirstSecSlide + SlideCount - 1
If oSlide.Shapes.HasTitle = msoTrue Then
oSlide.Shapes.Title.TextFrame.TextRange.Text = TextBox1
End If
'Add SmartArt
'Set Shp = oSlide.Shapes.AddSmartArtApplication.SmartArtLayouts(1)
'Create Flowchart Shape
Dim oSh As Shape
Set oSh = ActiveWindow.Selection.SlideRange.Shapes.AddShape(msoShapeFlowchartPredefinedProcess, 50, 100, 83.52, 41.62)
With oSh
With .TextFrame.TextRange
.Text = TextBox1
With .Font
.Name = "Verdana (Body)"
.Size = 8
.Bold = msoFalse
.Italic = msoFalse
.Underline = msoFalse
.Shadow = msoFalse
.Emboss = msoFalse
.BaselineOffset = 0
.AutoRotateNumbers = msoFalse
'.Color.SchemeColor = RGB(255, 255, 255)
End With ' Font
End With ' TextRange
End With ' oSh, the shape itself
End Sub
I'm guessing you want this in the last part that does the font formatting:
Dim URLorLinkLocationText as String
With oSh.TextFrame.TextRange.ActionSettings(ppMouseClick)
.Action = ppActionHyperlink
.Hyperlink.SubAddress = URLorLinkLocationText
End With
I have PPTs that are being generated via software that I have no control over. Upon generation, the software puts all text into TextBoxes instead of my Placeholders.
I created a script to move the text from the TextBoxes into the placeholders and this works great; however, I am unable to maintain the links and the lists are always showing as Bulleted despite some being numbers. Basically, if there is a link in the textbox, it should still be a link in the Placeholder. FYI, this script also changes shape 3 on each slide into the Title Placeholder
How can I preserve the formatting when I am moving the text over? I attempted to use pastespecial, but that still was only moving the text into the format of the placeholder.
Sub TextBoxFix()
Dim osld As Slide, oshp As Shape, oTxR As TextRange, SlideIndex As Long, myCount As Integer, numShapesOnSlide As Integer
Dim tempBulletFormat As PowerPoint.PpBulletType
For Each osld In ActivePresentation.Slides
myCount = 1
With ActivePresentation
'For Each oshp In osld.Shapes
osld.CustomLayout = ActivePresentation.Designs(1).SlideMaster.CustomLayouts(2)
For i = osld.Shapes.Count To 1 Step -1
Set oshp = osld.Shapes(i)
If i = 3 Then
osld.Shapes.Placeholders.Item(1).TextFrame.TextRange = oshp.TextFrame.TextRange.Characters
osld.Shapes.Placeholders.Item(1).Visible = msoTrue
oshp.Delete
ElseIf i > 3 And oshp.Type = msoTextBox Then
oshp.TextFrame.TextRange.Copy
osld.Shapes.Placeholders.Item(2).TextFrame.TextRange.InsertBefore(oshp.TextFrame.TextRange.TrimText).ParagraphFormat.Bullet.Type = oshp.TextFrame.TextRange.ParagraphFormat.Bullet.Type
oshp.Delete
End If
Next i
End With
Next osld
End Sub
This may have some formatting issues that need to be addressed, but this will insert the hyperlinks that you are looking for. Code is likely not the cleanest, but it works. You will also need to set the vba to break only on unhandled errors, or it will break in the middle of the code. See here.
Class Module - Hyper
Private shp As Shape
Private chrStart As Integer
Private hypAddr As String
Private hypText As String
Private Sub Class_Initialize()
End Sub
Public Sub InitializeWithValues(newShp As Shape, newChrStart As Integer, newHypAddress As String, newHypText As String)
Set shp = newShp
chrStart = newChrStart
hypAddr = newHypAddress
hypText = newHypText
End Sub
Public Function getShape() As Shape
Set getShape = shp
End Function
Public Function getchrStart() As Integer
getchrStart = chrStart
End Function
Public Function getHypAddr() As String
getHypAddr = hypAddr
End Function
Public Function getHypText() As String
getHypText = hypText
End Function
Class Module - hyperColl
Private myCollection As Collection
Private Sub Class_Initialize()
Set myCollection = New Collection
End Sub
Public Sub Add_Item(newHyper As Hyper)
Dim newArray() As Hyper
If Me.Exists(newHyper.getShape().Name) Then
newArray = myCollection(newHyper.getShape().Name)
ReDim Preserve newArray(0 To UBound(newArray) + 1)
Set newArray(UBound(newArray)) = newHyper
myCollection.Remove (newHyper.getShape().Name)
myCollection.Add newArray, newHyper.getShape().Name
Else
ReDim newArray(0)
Set newArray(0) = newHyper
myCollection.Add newArray, newHyper.getShape().Name
End If
End Sub
Public Function GetArray(shapeName As String) As Hyper()
GetArray = myCollection(shapeName)
End Function
Public Function Exists(shapeName As String) As Boolean
Dim myHyper() As Hyper
On Error Resume Next
myHyper = myCollection(shapeName)
On Error GoTo 0
If Err.Number = 5 Then 'Not found in collection
Exists = False
Else
Exists = True
End If
Err.Clear
End Function
Regular Module (Call it whatever you want)
Sub textBoxFix()
Dim sld As Slide
Dim shp As Shape
Dim shp2 As Shape
Dim oHl As Hyperlink
Dim hypAddr As String
Dim hypText As String
Dim hypTextLen As Integer
Dim hypTextStart As Integer
Dim hypShape As Shape
Dim hypCollection As hyperColl
Dim newHyper As Hyper
Dim hypArray() As Hyper
Dim hypToAdd As Hyper
Dim i As Long
Dim j As Long
Dim bolCopy As Boolean
Set sld = ActivePresentation.Slides(1)
sld.CustomLayout = ActivePresentation.Designs(1).SlideMaster.CustomLayouts(2)
Set hypCollection = New hyperColl 'Set the collection of arrays - 1 for each shape
Set shp = sld.Shapes(1)
For Each oHl In sld.Hyperlinks
If oHl.Type = msoHyperlinkRange Then 'Hyperlink is associated with part of a TextRange, not a whole shape
hypAddr = oHl.Address
hypText = oHl.TextToDisplay
hypTextLen = Len(hypText)
If TypeName(oHl.Parent.Parent) = "TextRange" Then
hypTextStart = oHl.Parent.Parent.start
Set hypShape = oHl.Parent.Parent.Parent.Parent
End If
Set newHyper = New Hyper
newHyper.InitializeWithValues hypShape, hypTextStart, hypAddr, hypText
hypCollection.Add_Item newHyper
End If
Next oHl
For j = sld.Shapes.Count To 1 Step -1
Set shp = sld.Shapes(j)
bolCopy = False
If j = 3 Then
Set shp2 = sld.Shapes.Placeholders.Item(1)
bolCopy = True
ElseIf j > 3 And shp.Type = msoTextBox Then
Set shp2 = sld.Shapes.Placeholders.Item(2)
bolCopy = True
End If
If bolCopy = True Then
shp2.TextFrame.TextRange.InsertBefore(shp.TextFrame.TextRange.TrimText).ParagraphFormat.Bullet.Type = shp.TextFrame.TextRange.ParagraphFormat.Bullet.Type
If hypCollection.Exists(shp.Name) Then
hypArray = hypCollection.GetArray(shp.Name)
For i = LBound(hypArray) To UBound(hypArray)
Set hypToAdd = hypArray(i)
With shp2.TextFrame.TextRange.Characters(hypToAdd.getchrStart, Len(hypToAdd.getHypText)).ActionSettings.Item(1)
.Action = ppActionHyperlink
.Hyperlink.Address = hypToAdd.getHypAddr
End With
Next i
End If
End If
shp.Delete
Next j
End Sub
I used OpiesDad's code as a starting point, and made some minor modifications. I was getting an error related to the GetArray function when textboxes didn't exist. In addition, I modified the code to run on all slides of the PPT. I also had to make some modifications to the TextBoxFix Sub because the content was being deleted, but wasn't populating in my Placeholders.
See my updates below:
Reused Class Module - Hyper
Removed "On Error GoTo 0" from the Exists Function in hyperColl
Revised TextBoxFix below:
Sub TextBoxFix()
Dim shp As Shape
Dim shp2 As Shape
Dim oHl As Hyperlink
Dim hypAddr As String
Dim hypText As String
Dim hypTextLen As Integer
Dim hypTextStart As Integer
Dim hypShape As Shape
Dim hypCollection As hyperColl
Dim newHyper As Hyper
Dim hypArray() As Hyper
Dim hypToAdd As Hyper
Dim i As Long
Dim j As Long
Dim bolCopy As Boolean
For Each sld In ActivePresentation.Slides
With ActivePresentation
sld.CustomLayout = ActivePresentation.Designs(1).SlideMaster.CustomLayouts(2)
Set hypCollection = New hyperColl 'Set the collection of arrays - 1 for each shape
Set shp = sld.Shapes(1)
For Each oHl In sld.Hyperlinks
If oHl.Type = msoHyperlinkRange Then 'Hyperlink is associated with part of a TextRange, not a whole shape
hypAddr = oHl.Address
hypText = oHl.TextToDisplay
hypTextLen = Len(hypText)
If TypeName(oHl.Parent.Parent) = "TextRange" Then
hypTextStart = oHl.Parent.Parent.Start
Set hypShape = oHl.Parent.Parent.Parent.Parent
End If
Set newHyper = New Hyper
newHyper.InitializeWithValues hypShape, hypTextStart, hypAddr, hypText
hypCollection.Add_Item newHyper
End If
Next oHl
For j = sld.Shapes.Count To 1 Step -1
Set shp = sld.Shapes(j)
bolCopy = False
If j = 3 Then
sld.Shapes.Placeholders.Item(1).TextFrame.TextRange = shp.TextFrame.TextRange.Characters
sld.Shapes.Placeholders.Item(1).Visible = msoTrue
shp.Delete
ElseIf j > 3 And shp.Type = msoTextBox Then
sld.Shapes.Placeholders.Item(2).TextFrame.TextRange.InsertBefore(shp.TextFrame.TextRange.TrimText).ParagraphFormat.Bullet.Type = shp.TextFrame.TextRange.ParagraphFormat.Bullet.Type
If hypCollection.Exists(shp.Name) Then
hypArray = hypCollection.GetArray(shp.Name)
For i = LBound(hypArray) To UBound(hypArray)
Set hypToAdd = hypArray(i)
With sld.Shapes.Placeholders.Item(2).TextFrame.TextRange.Characters(hypToAdd.getchrStart, Len(hypToAdd.getHypText)).ActionSettings.Item(1)
.Action = ppActionHyperlink
.Hyperlink.Address = hypToAdd.getHypAddr
End With
Next i
End If
shp.Delete
End If
Next j
End With
Next sld
End Sub