PowerPoint Relink Movie Files
When movies are inserted into PowerPoint presentations, PowerPoint apparently always saves the absolute path to the media file. In case that the presentation is copied or moved to another computer, videos will no longer work. One work around is the Visual Basic script listed below. It iterates over all media objects, extracts the referenced filenames, searches for them either in the subfolders of the presentation (RelinkMoviesToDefaultLocation) or another folder chosen by the user (RelinkMoviesAndAskForLocation). When searching for the best match, the function GetBestMatchingFile requires at least that the filename (without path) matches exactly, but will return the longest match (i.e., matching most of the path).
Install
- open the VBA editor (Tools→Macro→Visual basic editor)
- Add a new module (Insert→Module)
- Paste the code below inside that module
After this, you can simply run the macro's from within PP itself. Simply go to Tools→Macro→Macros and you can choose either RelinkMoviesToDefaultLocation or RelinkMoviesAndAskForLocation to run.
Code
Copy and paste this code inside the VBA module.
Option Explicit
Public Const DefaultMovieSubFolder As String = ""
'relinks all movies to the default subdirectory beneath the presentations location
'the name of the subdirectory is set in the DefaultMovieSubFolder constant
Public Sub RelinkMoviesToDefaultLocation()
Dim folder As String
folder = GetDir(ActivePresentation.FullName) & DefaultMovieSubFolder
RelinkMovies folder
End Sub
'Ask the user for a directory and relinks all movie objects to that location
Public Sub RelinkMoviesAndAskForLocation()
Dim folder As String
folder = InputBox("Please enter target directory", , GetDir(ActivePresentation.FullName))
If Len(folder) = 0 Then Exit Sub
RelinkMovies folder
End Sub
Public Sub RelinkMovies(Target As String)
If Len(Dir(Target, vbDirectory)) = 0 Then
MsgBox "The target directory (" + Target + ") does not exist. Relinking cancelled"
Exit Sub
End If
Dim sl As Slide, sh As Shape, count As Integer, relinked As Integer
If Not Right$(Target, 1) = "\" Then Target = Target & "\"
For Each sl In ActivePresentation.Slides
For Each sh In sl.Shapes
If IsMovie(sh) Then
If Relink(sh, Target) Then relinked = relinked + 1
count = count + 1
End If
Next
Next
MsgBox "Finished: " & count & " movie objects were checked and " & relinked & " were relinked"
End Sub
Private Function IsMovie(sh As Shape)
On Error Resume Next
IsMovie = sh.MediaType = ppMediaTypeMovie
End Function
Function Relink(sh As Shape, TargetDir As String) As Boolean
Dim File As String, Current As String, ProposedFile As String
File = sh.LinkFormat.SourceFullName
Current = GetDir(File)
ProposedFile = TargetDir & Mid$(File, Len(Current) + 1)
ProposedFile = GetBestMatchingFile(TargetDir, File)
If File = ProposedFile Then
Exit Function 'no change made
End If
sh.LinkFormat.SourceFullName = ProposedFile
Relink = True
End Function
Private Function GetDir(File As String) As String
Dim i As Integer
i = InStrRev(File, "\")
If i = 0 Then
GetDir = ""
Else
GetDir = Left$(File, i)
End If
End Function
Private Function FillDir(colDirList As Collection, ByVal strFolder As String, strFileSpec As String, _
bIncludeSubfolders As Boolean)
'Build up a list of files, and then add add to this list, any additional folders
Dim strTemp As String
Dim colFolders As New Collection
Dim vFolderName As Variant
'Add the files to the folder.
strFolder = TrailingSlash(strFolder)
strTemp = Dir(strFolder & strFileSpec)
Do While strTemp <> vbNullString
colDirList.Add strFolder & strTemp
strTemp = Dir
Loop
If bIncludeSubfolders Then
'Build collection of additional subfolders.
strTemp = Dir(strFolder, vbDirectory)
Do While strTemp <> vbNullString
If (strTemp <> ".") And (strTemp <> "..") Then
If (GetAttr(strFolder & strTemp) And vbDirectory) <> 0& Then
colFolders.Add strTemp
End If
End If
strTemp = Dir
Loop
'Call function recursively for each subfolder.
For Each vFolderName In colFolders
Call FillDir(colDirList, strFolder & TrailingSlash(vFolderName), strFileSpec, True)
Next vFolderName
End If
End Function
Public Function TrailingSlash(varIn As Variant) As String
If Len(varIn) > 0& Then
If Right(varIn, 1&) = "\" Then
TrailingSlash = varIn
Else
TrailingSlash = varIn & "\"
End If
End If
End Function
Private Function GetBestMatchingFile(SearchDir As String, Filename As String) As String
Dim colDirList As New Collection
Dim varItem As Variant
Call FillDir(colDirList, SearchDir, "*.*", True)
Dim CurrentDir, FilenameOnly As String
CurrentDir = GetDir(Filename)
FilenameOnly = Mid$(Filename, Len(CurrentDir) + 1)
Dim bestMatchingChars As Integer
Dim bestMatchedString As String
bestMatchingChars = 0
bestMatchedString = Filename
For Each varItem In colDirList
Dim matchingChars As Integer
Dim matchedString As String
matchingChars = 0
Dim lenVar As Integer
Dim lenFile As Integer
lenVar = Len(varItem)
lenFile = Len(Filename)
Do While (Mid$(Filename, Len(Filename) - matchingChars - 1) = Mid$(varItem, Len(varItem) - matchingChars - 1))
matchingChars = matchingChars + 1
If matchingChars >= lenVar - 1 Then Exit Do
If matchingChars >= lenFile - 1 Then Exit Do
Loop
matchedString = varItem
If (matchingChars > bestMatchingChars) And (matchingChars >= Len(FilenameOnly)) Then
bestMatchingChars = matchingChars
bestMatchedString = matchedString
End If
' Debug.Print varItem
Next
' Debug.Print "org: " & Filename
' Debug.Print "best:" & bestMatchedString
If bestMatchingChars = 0 Then
MsgBox "Not found: " & Filename
Else
' make path relative?
bestMatchedString = Replace(bestMatchedString, SearchDir, "")
End If
GetBestMatchingFile = bestMatchedString
End Function
last modified on 2009/02/19 15:50
