Change Media Object (VBA PowerPoint) - vba

I just want to change the music of a Media Object in PowerPoint using Macros. I have a music in a Slide, but I can't figure out how I can change it to different music. Or is it possible to replace it by a new one but with the same properties...?
I tried playing around with following code but I don't know the rest...
Slide3.Shapes("bg_music").MediaFormat. 'code that I don't know to change it's music/media

You're going to need to delete the existing shape and replace it with a new one, copying the properties as needed. This MSDN article enumerates some (all?) of the MediaFormat properties.
Option Explicit
Sub ReplaceMediaFormat()
Dim sld As Slide
Dim newShp As Shape
Dim shp As Shape
Dim mf As MediaFormat
Dim path As String
Set sld = ActivePresentation.Slides(1) '// Modify as needed
Set shp = sld.Shapes("bg_music")
Set mf = shp.MediaFormat
'// Modify the path for your new media file:
path = "C:\Users\david.zemens\Downloads\2540.mp3"
Set newShp = sld.Shapes.AddMediaObject2(path)
With newShp
.Top = shp.Top
.Left = shp.Left
.Width = shp.Width
.Height = shp.Height
' etc...
End With
' // copy the mediaformat properties as needed
With newShp.MediaFormat
.StartPoint = mf.StartPoint
.EndPoint = mf.EndPoint
.FadeInDuration = mf.FadeInDuration
.FadeOutDuration = mf.FadeOutDuration
.Muted = mf.Muted
.Volume = mf.Volume
' etc...
End With
'// remove the original
shp.Delete
Dim eff As Effect
'// Creates an effect in the timeline which triggers this audio to play when the slideshow begins
Set eff = sld.TimeLine.MainSequence.AddEffect(newShp, msoAnimEffectMediaPlay, trigger:=msoAnimTriggerWithPrevious)
With newShp.AnimationSettings.PlaySettings
.LoopUntilStopped = msoCTrue
.PauseAnimation = msoFalse
.PlayOnEntry = msoCTrue
.RewindMovie = msoCTrue
.StopAfterSlides = 999
.HideWhileNotPlaying = msoTrue
End With
With help from this article, I can get the audio to play automatically by creating an effect (see above Set eff = ...).

Related

Replace a text box with a placeholder (Title or Body)

I received a PowerPoint file with multiple slides which were supposed to be templates (designs - customlayouts) but instead were regular slides.
Transforming them into SlideMaster and custom layouts and replacing the titles and bodys (textboxes) with actual placeholders by hand was a pain.
So I came with this script to make the process faster.
If anybody has a better approach, it's welcome.
Had to look for a workaround to get the customlayout object.
Several things are missing, for example error handling.
To test it, copy a textbox into a slidemaster layout slide, select it and run the ReplaceWithPHTitle macro
Option Explicit
Public Sub ReplaceWithPHTitle()
ReplaceTexboxWithPlaceholder ppPlaceholderTitle
End Sub
Public Sub ReplaceWithPHBody()
ReplaceTexboxWithPlaceholder ppPlaceholderBody
End Sub
Private Sub ReplaceTexboxWithPlaceholder(ByVal placeholderType As PpPlaceholderType)
Dim targetLayout As CustomLayout
Dim activeShape As Shape
Dim newPlaceHolder As Shape
Set activeShape = ActiveWindow.Selection.ShapeRange(1)
Set targetLayout = activeShape.Parent
Set newPlaceHolder = targetLayout.Shapes.AddPlaceholder(Type:=placeholderType, Left:=activeShape.Left, Top:=activeShape.Top, Width:=activeShape.Width + 15, Height:=activeShape.Height)
With newPlaceHolder.TextFrame
.TextRange.Font.Name = activeShape.TextFrame.TextRange.Font.Name
.TextRange.Characters.Font.Color.RGB = activeShape.TextFrame.TextRange.Characters.Font.Color.RGB
.TextRange.Font.Size = activeShape.TextFrame.TextRange.Font.Size
.TextRange.Font.Bold = activeShape.TextFrame.TextRange.Font.Bold
.TextRange.ParagraphFormat.Bullet.Type = activeShape.TextFrame.TextRange.ParagraphFormat.Bullet.Type
.TextRange.ParagraphFormat.SpaceWithin = activeShape.TextFrame.TextRange.ParagraphFormat.SpaceWithin
.TextRange.ParagraphFormat.Alignment = activeShape.TextFrame.TextRange.ParagraphFormat.Alignment
.TextRange.ParagraphFormat.SpaceBefore = activeShape.TextFrame.TextRange.ParagraphFormat.SpaceBefore
.TextRange.ParagraphFormat.SpaceAfter = activeShape.TextFrame.TextRange.ParagraphFormat.SpaceAfter
.TextRange.ParagraphFormat.BaseLineAlignment = activeShape.TextFrame.TextRange.ParagraphFormat.BaseLineAlignment
.TextRange.Text = activeShape.TextFrame.TextRange.Text
End With
With newPlaceHolder.TextFrame2
.TextRange.Font.Spacing = activeShape.TextFrame2.TextRange.Font.Spacing
End With
newPlaceHolder.ZOrder msoSendToBack
newPlaceHolder.Select
End Sub
Any improvements are welcome too.

Change the text color of the chart title in a PowerPoint Histogram chart

I am trying to change the text color of the chart title of a histogram chart in PowerPoint.
Here is what I do:
var colorFormat = chart.ChartTitle.Format.TextFrame2.TextRange.Font.Fill.ForeColor;
colorFormat.RGB = ...;
// or
colorFormat.ObjectThemeColor = ...;
This works for the standard charts like line charts. But it doesn't work for other chart types like histogram, waterfall, tree map etc.
In these cases, setting ObjectThemeColor sets the text to black. Setting RGB does actually set the correct color. However, in both cases, as soon as the user changes the selection, the text color jumps back to the one it had previously.
How can I set the text color of the title of one of these charts?
I am using VSTO and C# but a VBA solution is just as welcome as long as it can be translated to C# and still work.
Based on what info you gave I built a histogram and waterfall chart in PowerPoint and was successful using:
Sub ChartTitleFontColor()
Dim oShp As Shape
Dim oCht As Chart
'Waterfall on slide 1
Set oShp = ActivePresentation.Slides(1).Shapes(1)
If oShp.HasChart Then
Set oCht = oShp.Chart
End If
' Do stuff with your chart
If oCht.HasTitle Then
Debug.Print oCht.ChartTitle.Text
oCht.ChartTitle.Format.TextFrame2.TextRange.Font.Fill.ForeColor.RGB = RGB(251, 5, 40)
End If
'Histogram on slide 2
Set oShp = ActivePresentation.Slides(2).Shapes(1)
If oShp.HasChart Then
Set oCht = oShp.Chart
End If
' Do stuff with your chart
If oCht.HasTitle Then Debug.Print oCht.ChartTitle.Text
oCht.ChartTitle.Format.TextFrame2.TextRange.Font.Fill.ForeColor.RGB = RGB(251, 5, 40)
End If
' Clean up
Set oShp = Nothing
Set oCht = Nothing
End Sub
Your code works in my test. I created two charts in PowerPoint 2016, the first one a waterfall, and the second another type. The following code changes the title color only (and text just a proof of it being changed) and nothing else. I can select the other chart and nothing changes. I could not find a bug about this in a search. Perhaps something in the remaining code is changing it back?
Sub test()
Dim myPresentation As Presentation
Set myPresentation = ActivePresentation
Dim myShape As Shape
Set myShape = myPresentation.Slides(1).Shapes(1)
Dim theChart As Chart
If myShape.HasChart Then
Set theChart = myShape.Chart
If theChart.ChartTitle.Text = "This is blue" Then
theChart.ChartTitle.Text = "This is yellow"
theChart.ChartTitle.Format.TextFrame2.TextRange.Font.Fill.ForeColor.RGB = RGB(255, 255, 0)
Else
theChart.ChartTitle.Text = "This is blue"
theChart.ChartTitle.Format.TextFrame2.TextRange.Font.Fill.ForeColor.RGB = RGB(0, 255, 255)
End If
End If
End Sub
This is not exactly an answer but I think you should name your object.
Instead of using
ActivePresentation.Slides(1).Shapes(1)
You can name the object.

VBA Word Shape location - top left corner

I have written a small function, based on example provided by producer of Stroke Scribe ActiveX object. This is an plugin which allows us to create in Microsoft Word by VBA Macro an QR Code object.
The problem is with setting up a shape location
shp.Left = 0 + LeftMargin
shp.Top = 0 + TopMargin
I would like to put this shape (QR Code) on specific page on the most left top corner. But sometimes shape jumps to previous page (on bottom) or other location (vertical center).
Can you help me recognize a problem and fix it to locate Shape Object every time top left corner?
Code:
Sub QRCodeGenerator(SOP, BookmarkID, Page, TopMargin, LeftMargin)
Dim doc As Document
Set doc = Application.ActiveDocument
For Each sh In doc.Shapes
If sh.Type = msoOLEControlObject Then
If sh.OLEFormat.ProgID = "STROKESCRIBE.StrokeScribeCtrl.1" Then
sh.Delete
End If
End If
Next
With doc.PageSetup
usable_w = .PageWidth
usable_h = .PageHeight
End With
Dim pg As Range
Set pg = doc.GoTo(wdGoToPage, wdGoToRelative, Page)
Dim shp As Shape
Set shp = doc.Shapes.AddOLEControl(ClassType:="STROKESCRIBE.StrokeScribeCtrl.1", Anchor:=pg)
Dim sMyString As String
sMyString = ActiveDocument.Bookmarks(BookmarkID).Range.Text
sMyString = Replace(sMyString, "FORMTEXT ", "")
shp.LockAspectRatio = msoFalse
shp.Height = InchesToPoints(0.6)
shp.Width = shp.Height
shp.Left = 0 + LeftMargin
shp.Top = 0 + TopMargin ' // usable_h - shp.Height * 3 + TopMargin
Dim ss As StrokeScribe
Set ss = shp.OLEFormat.Object
ss.Alphabet = QRCODE 'StrokeScribe will draw a QR code picture
ss.Text = SOP & ";" & sMyString 'Any text you want to encode in the barcode
ss.QrECL = H 'Changes the default error correction level. This can be omitted
ss.QrMinVersion = 3 'Specifies the minimum barcode size. This can be omitted
ss.FontColor = RGB(0, 0, 0)
' ss.UTF8 = True 'Enable this, if you want to encode national characters for smartphones
If ss.Error Then
MsgBox ss.ErrorDescription
End If
End Sub
Word SHAPE objects must be anchored to a Range. The page location of that Range determines on which page the Shape will display. There's nothing you can do to "lock" a Shape to a particular page.
That said, it is possible to dictate that a Shape always appears in the same location on whichever page the anchoring Range lies.
This is always tricky if you add such a Shape before document editing is finished, because editing can move the anchoring paragraph to a different page. It can help to choose a paragraph as the anchor that's unlikely to move, for example perhaps the first paragraph on the page.
Something I did once, long ago, was write a macro that checks the page locations of Shapes before printing or saving. When inserting and positioning the Shape, I give it a Name that includes the page number. Before printing/saving the macro checks the page number in the Shape name with the page on which the Shape is located. If the two don't match, CUT the Shape and PASTE it to a paragraph on the correct page (it remembers its position settings).
The code sample below demonstrates how to name the Shape, lock the anchor to a specific paragraph and position the Shape flush to the top, left corner of the page.
Sub ShapePosTopLeft()
Dim doc As word.Document
Dim shp As word.Shape
Dim rng As word.Range
Set doc = ActiveDocument
Set rng = doc.GoTo(wdGoToPage, wdGoToRelative, Page)
Set rng = rng.Paragraphs(1).Range
Set shp = doc.Shapes.AddOLEControl(ClassType:="STROKESCRIBE.StrokeScribeCtrl.1", Anchor:=rng)
With shp
.Name = "Shape_Page" & Page
.LockAnchor = True
.RelativeHorizontalPosition = wdRelativeHorizontalPositionPage
.RelativeVerticalPosition = wdRelativeVerticalPositionPage
.Left = 0
.Top = 0
End With
End Sub

Access Shape By Name in Header

My first post so sorry for any errors.
I am trying to replace a image in the header of a document. This will be done a few thousand times.
This line of code:
Set shp = ActiveDocument.Sections(1).Headers.Shapes(strPic)
Causes:
Compile error: Method or data member not found
and
Set shp = ActiveDocument.Shapes("strPic")
Causes:
Run-time error '-2147024809(80070057): The item with the specified name wasn't found.
I have written in multiple ways and cannot get it to assign shp I feel like this is a very simple issue of how I am accessing the header or maybe this whole sub is just wrong. The strPic line before get the name of the shape fine.
Sub imagerepl()
With Selection
' \\ If we selected a InlineShape then convert to Shape
If .Type = wdSelectionInlineShape Then
.InlineShapes(1).ConvertToShape
End If
End With
strPic = Selection.ShapeRange.Name
Set shp = ActiveDocument.Sections(1).Headers.Shapes(strPic)
'Capture properties of exisitng picture such as location and size
With shp
t = .Top
l = .Left
h = .Height
w = .Width
End With
ActiveDocument.StoryRanges(wdPrimaryHeaderStory).ShapeRange(strPic).Delete
Set shp = ActiveDocument.Shapes.AddPicture("C:\Users\tk\Pictures\DFHlogo.png", msoFalse, msoTrue, l, t, w, h)
shp.Name = strPic
shp.ScaleHeight Factor:=1, RelativeToOriginalSize:=msoTrue
shp.ScaleWidth Factor:=1, RelativeToOriginalSize:=msoTrue
End Sub
You can access the header image through the Range.InlineShapes collection. For example, the following routine would delete the first image in the collection and then add new image to the header.
Dim sh As InlineShape
With ThisDocument.Sections(1).Headers(wdHeaderFooterPrimary).Range
' Get the first (possibly only, for you) image in the header...
Set sh = .InlineShapes(1)
' Delete it...
sh.Delete
' Add a new image to the header...
Set sh = .InlineShapes.AddPicture("c:\path\to\my.jpg")
' Set its properties...
sh.Width = 100
sh.Height = 100
...
End With

VBA - Power Point - Wrap text in Shape programmatically

I have been working on a small hack around with Power Point to automatically create a Text Box Shape with some preset effect in which the text is dynamically fetched from clipboard. I have quiet a bit of a problem here, the functionality works fine with the following VB script with macros.
Sub ReadFromFile()
' CLIPBOARD
Dim MyData As DataObject
Dim strClip As String
' CLIPBOARD
Set MyData = New DataObject
MyData.GetFromClipboard
strClip = MyData.GetText
Set activeDocument = ActivePresentation.Slides(1)
With activeDocument
'Set QASlide = .Slides.Add(Index:=.Slides.Count + 0, Layout:=ppLayoutBlank)
activeDocument.Shapes.AddTextEffect PresetTextEffect:=msoTextEffect28, _
Text:=strClip, _
FontName:="Garde Gothic", FontSize:=44, FontBold:=msoTrue, _
FontItalic:=msoFalse, Left:=25, Top:=25
With .Shapes(.Shapes.Count)
.Width = 200
.Height = 300
End With
End With
End Sub
Can some one help me in providing the script for wrapping the text inside the shape which has a defined width and height as in the code above?
Not sure if I understand you right but does adding .TextFrame.WordWrap = msoTrue to the block below solve your problem?
With .Shapes(.Shapes.Count)
.Width = 200
.Height = 300
End With
I think you are looking for this:
.Shapes(.Shapes.Count).TextFrame.TextRange.Text = strClip
You can set it in the same With that you are setting the height and width
If you want text to wrap within a shape, you'll have to use something other than a texteffect shape.