excelvbadebuggingpowerpointole-object

PowerPoint VBA code is inconsistent when running in attempt to export OLE objects as high resolution JPG files


I have linked macro-enabled worksheet objects from excel to 25 different powerpoint slides in my powerpoint deck. Some slides have up to three linked objects and others have only one. For the slides that have multiple linked objects, I need the jpg output to contain all three objects / images. The VBA script that I am using sometimes works for every slide, sometimes works on 10 slides, 15 slides, or none. I need to be able to make the vba code bulletproof so that this can be reliable moving forward.

I expect this VBA code to have the same result time and time again... but when I run it constantly (5 times) I receive different results. Shape (unknown member) Object does not exist. When I receive this error, I look at my powerpoint deck and see that a blank slide has been created but obviously the code has failed. Here is a list of all of my objects when I open the immediate window: Below this list is my script which provided inconsistent result.

    Slide 1: Linked OLE Object - Excel.SheetMacroEnabled.12
    Slide 2: Linked OLE Object - Excel.SheetMacroEnabled.12
    Slide 2: Linked OLE Object - Excel.SheetMacroEnabled.12
    Slide 2: Linked OLE Object - Excel.SheetMacroEnabled.12
    Slide 3: Linked OLE Object - Excel.SheetMacroEnabled.12
    Slide 4: Linked OLE Object - Excel.SheetMacroEnabled.12
    Slide 5: Linked OLE Object - Excel.SheetMacroEnabled.12
    Slide 6: Linked OLE Object - Excel.SheetMacroEnabled.12
    Slide 6: Linked OLE Object - Excel.SheetMacroEnabled.12
    Slide 6: Linked OLE Object - Excel.SheetMacroEnabled.12
    Slide 7: Linked OLE Object - Excel.SheetMacroEnabled.12
    Slide 8: Linked OLE Object - Excel.SheetMacroEnabled.12
    Slide 9: Linked OLE Object - Excel.SheetMacroEnabled.12
    Slide 10: Linked OLE Object - Excel.SheetMacroEnabled.12
    Slide 10: Linked OLE Object - Excel.SheetMacroEnabled.12
    Slide 10: Linked OLE Object - Excel.SheetMacroEnabled.12
    Slide 11: Linked OLE Object - Excel.SheetMacroEnabled.12
    Slide 12: Linked OLE Object - Excel.SheetMacroEnabled.12
    Slide 13: Linked OLE Object - Excel.SheetMacroEnabled.12
    Slide 14: Linked OLE Object - Excel.SheetMacroEnabled.12
    Slide 14: Linked OLE Object - Excel.SheetMacroEnabled.12
    Slide 14: Linked OLE Object - Excel.SheetMacroEnabled.12
    Slide 15: Linked OLE Object - Excel.SheetMacroEnabled.12
    Slide 16: Linked OLE Object - Excel.SheetMacroEnabled.12
    Slide 17: Linked OLE Object - Excel.SheetMacroEnabled.12
    Slide 18: Linked OLE Object - Excel.SheetMacroEnabled.12
    Slide 18: Linked OLE Object - Excel.SheetMacroEnabled.12
    Slide 18: Linked OLE Object - Excel.SheetMacroEnabled.12
    Slide 19: Linked OLE Object - Excel.SheetMacroEnabled.12
    Slide 20: Linked OLE Object - Excel.SheetMacroEnabled.12
    Slide 21: Linked OLE Object - Excel.SheetMacroEnabled.12
    Slide 22: Linked OLE Object - Excel.SheetMacroEnabled.12
    Slide 22: Linked OLE Object - Excel.SheetMacroEnabled.12
    Slide 22: Linked OLE Object - Excel.SheetMacroEnabled.12
    Slide 23: Linked OLE Object - Excel.SheetMacroEnabled.12
    Slide 24: Linked OLE Object - Excel.SheetMacroEnabled.12
    Slide 25: Linked OLE Object - Excel.SheetMacroEnabled.12

Current Script:

Sub CaptureAndSaveAllOLEObjectsAsHighResJPG()
       Dim slide As slide
       Dim shape As shape
       Dim pic As shape
       Dim picPath As String
       Dim picName As String
       Dim slideIndex As Integer
       Dim scaleFactor As Double
       Dim originalWidth As Single
       Dim originalHeight As Single
       Dim saveFolder As String
       Dim positionX As Single  ' Position tracking variable for spacing
   
       ' Define the folder to save the screenshots
       saveFolder = "C:\Users\KWP863\Desktop\Testing\" ' Change this 
        to your desired path
   
       ' Create the folder if it doesn't exist
       If Dir(saveFolder, vbDirectory) = "" Then
           MkDir saveFolder
       Debug.Print "Created folder: " & saveFolder
       End If
   
       ' Set the scaling factor to increase resolution
       scaleFactor = 3#  ' Increase this factor for higher resolution
   
       ' Loop through each slide in the presentation
       For Each slide In ActivePresentation.Slides
       slideIndex = slide.slideIndex
       
       ' Create a blank slide to combine all pictures
       Dim combinedSlide As slide
       Set combinedSlide = 
       ActivePresentation.Slides.Add(ActivePresentation.Slides.Count + 
       1, ppLayoutBlank)
       
       ' Reset position tracking variable
       positionX = 0
       
       ' Loop through each shape in the slide
       For Each shape In slide.Shapes
           ' Check if the shape is a linked or embedded OLE object
           If shape.Type = msoLinkedOLEObject Or shape.Type = 
              msoEmbeddedOLEObject Then
               ' Copy the OLE object
               shape.Copy
               
               ' Paste the OLE object as a picture (Enhanced Metafile)
               On Error Resume Next
               Set pic = 
  combinedSlide.Shapes.PasteSpecial(DataType:=ppPasteEnhancedMetafile)(1)
               On Error GoTo 0
               
               If Not pic Is Nothing Then
                   ' Store the original dimensions
                   originalWidth = pic.Width
                   originalHeight = pic.Height
                   
                   ' Scale the picture up
                   pic.Width = originalWidth * scaleFactor
                   pic.Height = originalHeight * scaleFactor
                   
                   ' Position the picture on the combined slide
                   pic.Left = positionX
                   pic.Top = 0  ' Fixed top position for all pictures
                   
                   ' Update position for the next picture (add the 
                    original width for spacing)
                   positionX = positionX + (originalWidth * 
                   scaleFactor) + 10 ' Adding 10 for spacing between 
                   objects
                   Else
                   Debug.Print "Error: Could not paste shape on Slide 
                   " & slideIndex
               End If
           End If
           Next shape
       
       ' Save the combined picture as a high-resolution JPG file
       picName = "Slide" & slideIndex & "_OLEObjects.jpg"
       picPath = saveFolder & picName
       
       ' Debug print statements to check paths
       Debug.Print "Saving to: " & picPath
       
       ' Export the combined slide as a picture
       combinedSlide.Shapes.Range.Export picPath, ppShapeFormatJPG
       
       ' Delete the combined slide
       combinedSlide.Delete
       Next slide
   
       MsgBox "High-resolution screenshots taken and saved for all 
       linked objects.", vbInformation
End Sub

Solution

  • Following from comments above:

    Sub CaptureAndSaveAllOLEObjectsAsHighResJPG()
        
        'use Const for fixed values
        Const SAVE_FOLDER As String = "C:\Temp\PPT_test\" ' Change this to your desired path
        Const SCALE_FACTOR As Long = 3 ' Increase this factor for higher resolution
        
        '### avoid using a type name like "slide", "shape" as a variable name...
        Dim sld As Slide, pres As Presentation, combinedSlide As Slide
        Dim shp As Shape, pic As Shape
        
        Dim picPath As String, picName As String
        Dim slideIndex As Integer
        Dim originalWidth As Single, originalHeight As Single
        Dim positionX As Single  ' Position tracking variable for spacing
        
        If Dir(SAVE_FOLDER, vbDirectory) = "" Then ' Create the folder if it doesn't exist
            MkDir SAVE_FOLDER
            Debug.Print "Created folder: " & SAVE_FOLDER
        End If
        
        Set pres = ActivePresentation
        For Each sld In pres.Slides
            slideIndex = sld.slideIndex
            
            ' Create a blank slide to combine all pictures
            Set combinedSlide = pres.Slides.Add(pres.Slides.Count + 1, ppLayoutBlank)
            
            ' Reset position tracking variable
            positionX = 0
        
            ' Loop through each shape in the slide
            For Each shp In sld.Shapes
                ' Check if the shape is a linked or embedded OLE object
                If shp.Type = msoLinkedOLEObject Or shp.Type = msoEmbeddedOLEObject Then
                
                    shp.Copy ' Copy the OLE object
                    DoEvents
                    Set pic = PastePicRetry(combinedSlide) 'retries if needed
                    If Not pic Is Nothing Then
                        
                        originalWidth = pic.Width ' Store the original dimensions
                        originalHeight = pic.Height
                        
                        pic.Width = originalWidth * SCALE_FACTOR ' Scale the picture up
                        pic.Height = originalHeight * SCALE_FACTOR
                        
                        pic.Left = positionX ' Position the picture on the combined slide
                        pic.Top = 0  ' Fixed top position for all pictures
                        
                        ' Update position for the next picture (add the original width for spacing)
                        positionX = positionX + (originalWidth * SCALE_FACTOR) + 10 ' Adding 10 for spacing between objects
                    End If
                End If
            Next shp
           
            picName = "Slide" & slideIndex & "_OLEObjects.jpg"
            picPath = SAVE_FOLDER & picName
            Debug.Print "Saving to: " & picPath                         ' Debug print statements to check paths
            combinedSlide.Shapes.Range.Export picPath, ppShapeFormatPNG ' Export the combined slide as a picture
            combinedSlide.Delete
        Next sld
       
        MsgBox "High-resolution screenshots taken and saved for all linked objects.", vbInformation
    End Sub
    
    
    'Try to paste on slide `sld` - retry up to 20 times
    '  Return the pasted shape if paste succeeds
    Function PastePicRetry(sld As Slide) As Shape
        Dim i As Long, pic As Shape
        Do While i < 20
            On Error Resume Next
            Set pic = sld.Shapes.PasteSpecial(DataType:=ppPasteEnhancedMetafile)(1)
            On Error GoTo 0
            
            If pic Is Nothing Then
                Debug.Print "### Paste #" & i & " failed for slide# " & sld.slideIndex
                DoEvents
                i = i + 1
            Else
                Debug.Print "Paste #" & i & " succeeded for slide# " & sld.slideIndex
                Set PastePicRetry = pic
                Exit Function
            End If
        Loop
    End Function