How to Export a Table (Shape) as JPG from Powerpoint - vba

I am able to export Charts as JPG files from Powerpoint, but haven't been able to do this with a table, which as far as I can tell is still a "Shape" which should be able to export.
This is a cleansed version of the code I use to export the Chart as JPG.
Const imgFilePath as String = "ChartImage.JPG"
Sub ExportChartJPG()
Dim cht as Variant 'this will hold the Chart/Shape object
Set cht = ActivePresentation.Slides(1).Shapes("Chart1").Chart
On Error Resume Next
Kill imgPath
On Error GoTo 0
cht.Export imgPath, "JPG"
End Sub
I figured this would be simple to modify, like:
Sub ExportChartJPG()
Dim cht as Variant 'this will hold the Chart/Shape object
Set cht = ActivePresentation.Slides(1).Shapes("Table1").Table
On Error Resume Next
Kill imgPath
On Error GoTo 0
cht.Export imgPath, "JPG"
End Sub
But this is throwing an error 13 Mismatch.
I have also tried dimensioning cht as a Shape instead of Variant, and setting cht = ActivePresentation.Slides(1).Shapes("Table1"), also unsuccessfully.

Although KazJaw's solution works, it was a bit cumbersome (copying takes additional time to process, I was getting errors I think as a result of not "waiting" long enough for the copy to complete, clipboard issues? etc.)
http://www.tech-archive.net/pdf/Archive/Office/microsoft.public.office.developer.vba/2006-10/msg00046.pdf
I open the object browser, right-click, and show hidden methods, which now allows me to use the Export method on a Shape.
Sub ExportShapeJPG()
Dim cht as Variant 'this will hold the Chart/Shape object
Set cht = ActivePresentation.Slides(1).Shapes("Table1") '<-- removed .Table and only pass the Shape itself
'Likewise, for charts, omit the .Chart:
' Set cht = ActivePresentation.Slides(1).Shapes("Chart1")
On Error Resume Next
Kill imgPath
On Error GoTo 0
cht.Export imgPath, ppShapeFormatJPG '<-- The export syntax is slightly different using ppShapeFormatJPG instead of "JPG"
End Sub

I have one quite weird idea. Look at the code where first part save a chart and second save table.
Sub ExportinChartAndTable()
Dim imgFilePath As String
imgFilePath = ActivePresentation.Path & "\chart"
Dim shp As Shape
Set shp = ActivePresentation.Slides(1).Shapes(1)
Dim shpChart As Chart
Set shpChart = shp.Chart
'exporting chart
On Error Resume Next
Kill imgFilePath
On Error GoTo 0
shpChart.Export imgFilePath & "chart.jpg", "JPG"
Stop
Dim chartPart As ChartData
Set chartPart = shpChart.ChartData
imgFilePath = ActivePresentation.Path & "\dataTable.jpg"
chartPart.Workbook.worksheets("arkusz1").Range("a1:c20").Copy
shpChart.Paste
shpChart.Shapes(1).Width = shp.Width
shpChart.Shapes(1).Height = shp.Height
On Error Resume Next
Kill imgFilePath
On Error GoTo 0
shpChart.Export imgFilePath, "JPG"
End Sub
You have to come up with idea how to check the range of the table. I hoped that CurrentRegion would work but it's not. You could use the possibility to count the amount of rows and columns in the table (it is possible). Or maybe you have fixed range so it would be easy. One more thing, you have to adjust dimension when table is resized.
EDIT due to David comment. I keep the above solution in place as could be useful for others (please refer to comments below)
Sub SolutionSecond()
Dim whereTo As String
whereTo = ActivePresentation.Path & "\table.jpg"
Dim shp As Shape
Set shp = ActivePresentation.Slides(1).Shapes(1)
Dim chrt As Shape
Set chrt = ActivePresentation.Slides(1).Shapes.AddChart
shp.Copy
'required due to excel opening proces
chrt.Select
chrt.Chart.Paste
'set dimensions here
chrt.Chart.Export whereTo, "JPG"
chrt.Delete
End Sub
This one base on the same logic. Copy table into chart which (the only kind of Shape) could be exported.

Related

Microsoft Word: Select and GoTo InlineShape

A macro in my Word document goes through all the graphs (inlineshapes) and updates links and values. At the moment the document freezes for the whole process behind a "Please wait" form dialog. Ideally I'd have the code move throughout the document to show the user that stuff is actually happening.
How can I select and GoTo the current inlineshape within my loop below?
Private Sub UpdateFields()
PleaseWait.bar.Width = 0
PleaseWait.Show
' This routine sets the new path for external links, pointing them to the current folder.
Dim Rng As Range, Fld As Field, Shp As Shape, iShp As InlineShape, i As Long
Dim no_of_steps As Integer
Dim single_step_width As Integer
no_of_steps = 0
With ThisDocument
' Create progress bar
' a) Count total number of steps
For Each Rng In .StoryRanges
For Each iShp In Rng.InlineShapes
no_of_steps = no_of_steps + 1
Next iShp
Next Rng
' b) Divide full width of progress frame by number of steps
single_step_width = PleaseWait.frame.Width \ no_of_steps
' Go through all story ranges in the document.
For Each Rng In .StoryRanges
' Go through the inlineshapes in the story range.
For Each iShp In Rng.InlineShapes
With iShp
' Skip over inlineshapes that don't have links to external files.
If Not .LinkFormat Is Nothing Then
With .LinkFormat
' Skip links already set to current folder
If Not .SourceFullName = ThisDocument.Path & "\datagrunnlag.xlsm" Then
' Replace the link to the external file
.SourceFullName = ThisDocument.Path & "\datagrunnlag.xlsm"
On Error Resume Next
.AutoUpdate = False
.Update
On Error GoTo 0
End If
End With
End If
' Update progress bar with completed step
PleaseWait.bar.Width = PleaseWait.bar.Width + single_step_width
DoEvents
End With
Next iShp
Next Rng
End With
End Sub
Edit 05.12.2020: added all code within the sub. ScreenUpdating = False and True are being set by separate subs for MacroEntry and MacroExit.
That would be a really bad idea. Using the Selection object will just slow the operation down even more, and leave the user cursing you.
As you already appear to have a progress indicator, you are doing all that you can to keep the user informed.
Anything that involves scrolling the document makes your code run more slowly, so the best you can do is ensure your code completes in as short a time as possible. This includes avoiding use of the Selection object and turning off ScreenUpdating.

VBA Code crashes PPT Application - unclear reason

I have a problem with the following Code. What happens is that my PPT application crashes while running the code. It does not always happen and it happens in different parts of the code.
I tried the application.wait-method, but it did not work.
help is appreciated since I am already working on this for days -.-. Thanks in advance.
Option Explicit
Public myfilename As String
Sub filepicker()
Dim i As Variant
MsgBox ("In the following dialog please choose the current file")
Dim myfilenamepicker As FileDialog
Set myfilenamepicker = Application.FileDialog(msoFileDialogFilePicker)
myfilenamepicker.InitialFileName = "C:\Users\Michael\Desktop\Test PPT"
myfilenamepicker.Show
If myfilenamepicker.SelectedItems.Count <> 0 Then
myfilename = myfilenamepicker.SelectedItems(1)
End If
End Sub
Sub Saveas_PPT_and_PDF()
Dim PP As PowerPoint.Presentation
Dim sh As Variant
Dim company, strPOTX, strPfad, pptVorlage, newpath, newpathpdf As String
Dim Cell As Range
Dim pptApp As Object
Call filepicker
Application.ScreenUpdating = False
' set the dropdown from which the company Is Selected
Set DropDown.ws_company = Tabelle2
' the company is the value selected in the dropdown, stored in "C2"
company = DropDown.ws_company.Range("C2").Value
On Error Resume Next
Set pptApp = GetObject(, "PowerPoint.Application")
On Error Resume Next
If pptApp Is Nothing Then
Set pptApp = CreateObject("PowerPoint.Application")
End If
On Error GoTo 0
'loop through the companies in the dropdown menu
For Each Cell In DropDown.ws_company.Range(DropDown.ws_company.Cells(5, 3), _
DropDown.ws_company.Cells(Rows.Count, 3).End(xlUp)).SpecialCells(xlCellTypeVisible)
DropDown.ws_company.Range("C2") = Cell
pptVorlage = myfilename
Debug.Print (myfilename)
Set PP = pptApp.Presentations.Open(pptVorlage)
newpath = Replace(myfilename, "AXO", "" & Cell & " AXO")
PP.UpdateLinks
PP.SaveAs newpath
newpathpdf = Replace(newpath, "pptx", "pdf")
Debug.Print (newpathpdf)
PP.ExportAsFixedFormat "" & newpathpdf & "", ppFixedFormatTypePDF, ppFixedFormatIntentPrint
pptApp.Presentations(newpath).Close
Set PP = Nothing
Next
' this part below closes PPT application if there are no other presentation
' object open. If there is at least 1, it leaves it open
If IsAppRunning("PowerPoint.Application") Then
If pptApp.Windows.Count = 0 Then
pptApp.Quit
End If
End If
Set pptApp = Nothing
Set PP = Nothing
End Sub
Function IsAppRunning(ByVal sAppName) As Boolean
Dim oApp As Object
On Error Resume Next
Set oApp = GetObject(, sAppName)
If Not oApp Is Nothing Then
Set oApp = Nothing
IsAppRunning = True
End If
End Function
I don't see anything obviously wrong but I can give you a strategy for debugging.
You will want to test all major manipulations seperately. You will want to run each test in the debugger and have screenupdating on so you can see what happens:
test the filepicker
test GetObject/CreateObject - do you really need it? You already have PowrPoint open it seems;
test your loop with a single hardcoded value. What happens with the focus when opening a presentation?
try without UpdateLinks; try without SaveAs and try without Export (i.e. just open a presentation and close it again).
check if the presentation really closes, otherwise you might end up with lots of open presentations.
test closing the application
test reading from a dropdown box
test the IsAppRunning function. Note that it sets On Error Resume Next but does not reset it. Note it does not set IsAppRunning = False anywhere.
try relevant parts of the above in a loop with and without debugging to see what happens and see if it crashes - there could be a timing problem in the Office application, e.g. trying to manipulate a presentation while it is not yet fully loaded.
Minimising your code can help isolate the area that causes the problem. I hope this helps.

How to clear Slide Master of all information in PowerPoint using VBA?

I would like to open every PowerPoint (*.pptx) in current folder and clear the Slide Master of all images and text boxes and then save.
(It says my post is mostly code so I need to add more detail, so here is a quote by George Washington, "Associate with men of good quality if you esteem your own reputation; for it is better to be alone than in bad company")
New code
Sub DeleteSlideMasterShapes()
Dim i As Long
Dim shp As Shape
With ActivePresentation
For i = .Designs.Count To 1 Step -1
For Each shp In .Designs(i).SlideMaster.Shapes
shp.Delete
Next
Next i
End With
End Sub
Sub loopFiles()
Dim fso As New FileSystemObject
Dim fil As File
Dim fold As Folder
Dim yourfolder As String
Set fold = fso.GetFolder(Application.ActivePresentation.Path)
For Each fil In fold.Files
If InStr(1, fil.Name, ".pptx") > 0 Then
Application.Presentations.Open fil.Path
Call DeleteSlideMasterShapes
ActivePresentation.Save
ActivePresentation.Close
End If
Next fil
End Sub
Another approach, in case you want to delete all the shapes from all Slide Masters AND the master's layouts:
Sub DeleteSlideMasterShapes()
' Including shapes on layouts
Dim oDes As Design
Dim oLay As CustomLayout
With ActivePresentation
' For each slide master:
For Each oDes In .Designs
' Delete the shapes on the master
oDes.SlideMaster.Shapes.Range.Delete
' Then delete the shapes from each layout under
' the slide master:
For Each oLay In oDes.SlideMaster.CustomLayouts
oLay.Shapes.Range.Delete
Next
Next
End With
End Sub
Further to my comments, if you want to delete the slide master then use this
Sub DeleteSlideMaster()
Dim i As Long
With ActivePresentation
On Error Resume Next
For i = .Designs.Count To 1 Step -1
.Designs(i).SlideMaster.Delete
Next i
On Error GoTo 0
End With
End Sub
To delete Shapes of a slidemaster, use this
Sub DeleteSlideMasterShapes()
Dim i As Long
Dim shp As Shape
With ActivePresentation
For i = .Designs.Count To 1 Step -1
For Each shp In .Designs(i).SlideMaster.Shapes
shp.Delete
Next
Next i
End With
End Sub
If I have not understood your query then please feel free to ask

Loop Through Charts on Selected (or Range of) Powerpoint Slides

I am currently using this code to update all links in my powerpoint presentation:
Sub UpdateLinks()
Dim ExcelFile
Dim exl As Object
Set exl = CreateObject("Excel.Application")
ExcelFile = "C:\Users\J\Documents\Reporting\Governance Physical Charts.xlsm"
Dim i As Integer
Dim k As Integer
'Go through every slide
For i = 1 To ActivePresentation.Slides.Count
With ActivePresentation.Slides(i)
'Go through every shape on every slide
For k = 1 To .Shapes.Count
On Error Resume Next
'Set the source to be the same as teh file chosen in the opening dialog box
.Shapes(k).LinkFormat.SourceFullName = ExcelFile
If .Shapes(k).LinkFormat.SourceFullName = ExcelFile Then
'If the change was successful then also set it to update automatically
.Shapes(k).LinkFormat.AutoUpdate = ppUpdateOptionAutomatic 'other option is ppUpdateOptionManual
End If
Next k
End With
Next i
End Sub
Instead of updating the link of every chart in the presentation, is it possible to have this code loop through only selected slides? Or if it's easier - is it possible to set a range? For example, only update charts on slides 15-30?
Thank you!
EDIT:
Resolution provided in comments - here is my revised code
Sub UpdateLinks()
Dim ExcelFile
Dim exl As Object
Set exl = CreateObject("Excel.Application")
Dim sld As Slide
ExcelFile = "C:\Users\J\Documents\Reporting\Governance Physical Charts.xlsm"
Dim i As Integer
Dim shp As Shape
For Each sld In ActivePresentation.Slides.Range(Array(11, 12, 13, 14, 15, 16, 17, 18))
For Each shp In sld.Shapes
On Error Resume Next
shp.LinkFormat.SourceFullName = ExcelFile
If shp.LinkFormat.SourceFullName = ExcelFile Then
shp.LinkFormat.AutoUpdate = ppUpdateOptionAutomatic 'other option is ppUpdateOptionManual
End If
Next shp
Next
End Sub
Yes you can compose custom ranges on Slides as well as on Shapes, using an Array as the index parameter. Try this:
Dim sld As Slide
For Each sld In ActivePresentation.Slides.Range(Array(1, 3, 5))
Debug.Print sld.Name
Next
Output:
Slide2
Slide4
Slide6
p.s. I had deleted a slide in the test presentation.
Since you also mentioned processing just selected slides, you can do that like so:
Sub SelectedSlides()
Dim osl As Slide
For Each osl In ActiveWindow.Selection.SlideRange
Debug.Print osl.SlideIndex
Next
End Sub
Note that this will give you the selected slides in REVERSE order of selection. That is, if you control-click slides 2,4,6, this will give you 6,4,2.

PowerPoint VBA search and delete paragraphs in Notes

I have several PowerPoints with a great deal of text in the notes. I need to search the note text and delete any paragraphs that start with "A."
Here is what I tried - but am getting type mismatch error
Dim curSlide As Slide
Dim curNotes As Shape
Dim x As Long
For Each curSlide In ActivePresentation.Slides
Set curNotes = curSlide.NotesPage.Shapes(2).TextFrame.TextRange
With curNotes.TextFrame.TextRange
For x = 1 To Len(curNotes.TextFrame.TextRange)
If Mid(curNotes.TextFrame.TextRange, x, 2) = "A." Then
curNotes.TextFrame.TextRange.Paragraphs = ""
End If
Next x
End With
Next curSlide
End Sub
Thanks for your help!!
You get a mismatch error whenever you try to assign data of a different type specified by your variable. This is happening in your code because you defined curNotes as type Shape and then tried to set that object variable to a different data type, TextRange. You are then trying to process the object TextRange as a string. You need to work on the .Text child of .TextRange The use of Mid is not checking the start of the string and finally, when you set the text to "", you are deleting all the text in the Note but that's not what you said you're trying to do.
This is the corrected code to delete only paragraphs starting with "A."
' PowerPoint VBA macro to delete all slide note paragraphs starting with the string "A."
' Rewritten by Jamie Garroch of youpresent.co.uk
Option Explicit
Sub DeleteNoteParagraphsStartingA()
Dim curSlide As Slide
Dim curNotes As TextRange
Dim iPara As Long
For Each curSlide In ActivePresentation.Slides
Set curNotes = curSlide.NotesPage.Shapes(2).TextFrame.TextRange
With curNotes
' Count backwards in any collection when deleting items from it
For iPara = .Paragraphs.Count To 1 Step -1
If Left(.Paragraphs(iPara), 2) = "A." Then
.Paragraphs(iPara).Delete
Debug.Print "Paragraph " & iPara & " deleted from notes pane on slide " & curSlide.SlideIndex
End If
Next
End With
Next curSlide
End Sub