VBA Picture Shadow Macro - vba

I have a bunch of images that I would like to apply a specific picture style to - the 4th one that is shown in Word 2010:
I have a macro that will loop through all images, but need to know the possibilities for the shadow.type .
What would be really helpful is a reference to the commands that would be used for each type of picture style, with a visual example.
I don't have VBA, so can't examine the elements of the picture. I have tried various msoShadowxx, but that didn't work.
Is there a good reference with visual examples, or a reference with the settings for each picture style? Or the settings to use for the 4th picture style (shown in the screenshot here)?
Here is the macro code that I use to loop through all the pictures.
Sub BorderMacroshadow()
Dim oInlineShp As InlineShape
For Each oInlineShp In ActiveDocument.InlineShapes
With oInlineShp
.Line.Weight = 1
.Line.ForeColor.RGB = vbBlack
.Shadow.Type = msoShadow14
End With
Next
End Sub
Added
A closer look at the reference for msoShadow shows that it is referring to Picture Effects, Shadows 'dialog', not the 'Picture Styles', which I assumes uses some elements of msoShadow in addition to other elements.
So, I am looking for the elements that are needed to duplicate the 4th 'Picture Style' (see the screenshot). Haven't found those yet.

The msoShadowType enumeration is a group of pre-sets. These aren't necessarily used in the gallery on the Ribbon.
In order to ascertain the settings of any Shadows formatting use the various properties available for Shape.Shadow, such as Transparency, Size, Blur. Inthe UI, these can be seen in Picture Effects, Shadow, Shadow Options of the Picture Style group on the Ribbon.
To determine/set them programmatically, see the following code sample. Note that Angle is not one property, but a combintation of OffsetX and OffsetY.
Sub ShadowProperties()
Dim shp As Word.Shape
Dim shw As Word.ShadowFormat
Set shp = Selection.ShapeRange(1)
Set shw = shp.Shadow
With shw
Debug.Print "Blur: " & .Blur, _
"size: " & .Size, _
"Transparency: " & .Transparency, _
"Offset x: " & .OffsetX, _
"Offset y: " & .OffsetY
End With
End Sub

Related

How change the style of a shape-text in vba?

I changed the size of text with the following line of code
shp.CellsSRC(visSectionCharacter, 0, visCharacterSize).FormulaU = " 3pt"
I'd like to change the style (to Bold) and color of the shape text with the same pattern of code ?
I didn't find the exact "formula", would you know how I could do that ?
Thank you very much in advance
Edit : I found this line for the color :
shp.CellsSRC(visSectionCharacter, 0, visCharacterColor).FormulaU = "THEMEGUARD(RGB(255,0,0))"
I'm not sure why there is no enumeration for setting the Style. In any case, it's Column 2 in the shape properties. So use
shp.CellsSRC(visSectionCharacter, 0, 2).FormulaU = 17
to set your text to Bold.
How do I know this you ask? Based on the Microsoft reference on Understanding the Shape Sheet, there is a helpful snippet of code to use.
First, select the shape in your drawing that you want to see information about the properties. Then open up the Shape Properties window in the Visio editor (not in the VBE) -- you can get there by viewing the Developer ribbon, then click on the Show ShapeSheet icon
In the shape properties window, scroll down until you see the Characters section. You MUST select one of the cells in the properties window. The example here has selected the Style column.
Once you have done this, then run the following code snippet below and you'll get the information you need in the Immediate Window of the VBE.
Public Sub DebugPrintCellProperties()
' Abort if ShapeSheet not selected in the Visio UI
If Not Visio.ActiveWindow.Type = Visio.VisWinTypes.visSheet Then
Exit Sub
End If
Dim cel As Visio.Cell
Set cel = Visio.ActiveWindow.SelectedCell
'Print out some of the cell properties
Debug.Print "Section", cel.Section
Debug.Print "Row", cel.Row
Debug.Print "Column", cel.Column
Debug.Print "Name", cel.Name
Debug.Print "FormulaU", cel.FormulaU
Debug.Print "ResultIU", cel.ResultIU
Debug.Print "ResultStr("""")", cel.ResultStr("")
Debug.Print "Dependents", UBound(cel.Dependents)
' cel.Precedents may cause an error
On Error Resume Next
Debug.Print "Precedents", UBound(cel.Precedents)
Debug.Print "--------------------------------------"
End Sub
This will tell you the Section, Row, and Column to use when you call CellsSRC. What I did was to figure out the property, then I manually set the text to BOLD and viewed the results of DebugPrintCellProperties again to see that the FormulaU = 17 for bold.

VBA code for giving slides a constant name

I am trying to reduce the effort needed to keep a certain slide (lets call it SlideXYZ) up to date. SlideXYZ is an important content slide that can be found in multiple slide decks. I initially created slide objects that updated automatically when a change was made in the "source slide". However, slide objects unfortunately don't contain animations (they are simply a snapshot of the actual slide). I am now trying to write a VBA script that will search and replace SlideXYZ in each deck with a newer version of SlideXYZ. However, the slide number is dynamic (it changes when a new slide is added above). I need a static, constant reference to SlideXYZ.
I thought of copying SlideXYZ into all presentations once and then using the Slide.Name property to find all instances of it once an update is needed.
However, it appears that the Slide.Name is reassigned by powerpoint each time the slide is pasted into a new presentation. I need a reference that will not change so that I can find and replace SlideXYZ.
#Asger's suggestion would work but a more consistent approach (IMO) would be to use tags. Any presentation, slide, or shape on a slide can have one or more bits of text attached in the form of a tag.
For example:
ActivePresentation.Slides(1).Tags.Add "SlideIdentifier", "Bob"
will create a tag named SlideIdentifier with a value of Bob on slide #1 in the current presentation. These tags will travel with the slide, wherever it goes.
This page on the PowerPoint FAQ that I maintain has more info on using tags:
http://www.pptfaq.com/FAQ00815_Working_with_Tags_-and_a_bit_about_Functions-.htm
As you already found out: Neither SlideIndex, SlideNumber, SlideID nor Name can be used to identify a copied slide.
You may work with the "alternative text" of a characteristic shape to identify a slide:
Just do a right mouseclick on the shape and edit its alternative text.
Also slide notes may help to identify a slide.
Following prints some slide information to your debug window:
Private Sub IdentifyMySlide()
Dim myslide As PowerPoint.Slide
For Each myslide In ActivePresentation.Slides
Debug.Print "Index: " & myslide.SlideIndex,
Debug.Print "Number: " & myslide.SlideNumber,
Debug.Print "ID: " & myslide.SlideID,
Debug.Print "Name: " & myslide.Name,
If myslide.Shapes.Count > 0 Then
Debug.Print "Alternative ShapeText: " & myslide.Shapes(1).AlternativeText,
End If
If myslide.HasNotesPage Then
If myslide.NotesPage(1).Shapes.Count > 0 Then
If myslide.NotesPage(1).Shapes(1).HasTextFrame Then
Debug.Print "Notes: " & Left(myslide.NotesPage(1).Shapes(1).TextFrame.TextRange.Text, 10)
Else
Debug.Print
End If
Else
Debug.Print
End If
Else
Debug.Print
End If
Next myslide
End Sub

Select a VBA Pasted Shape from Excel to Word so I can wrap text tight

I'm developing a spreadsheet to automatically generate quotes; this involves copying the correct diagram (a grouped Excel shape) from a sheet with a library of our possible diagrams, and pasting/inserting/[whatever will work best] that image into the VBA-assembled Word document.
So far, I am able to successfully identify, copy and paste special the correct diagram shape from Excel into Word. However, every technique I have found means that the shape either wraps text as inline or infront-- whereas I need the next portion of text to be directly aside the diagram-- thus "wdTight"
Below, you can see how I paste in the current shape. But I can't figure out how to make that shape into ".wrapFormat.Type = wdTight"
I am generally met with a series of Runtime 438 errors: object doesn't support this property or method.
I have a theory that this is because Word considers the selection to always be the blinking text cursor, and not the just pasted shape which is activated and has a hovering layout options tooltip (but that is just a theory).
Here is the code. Please help.
Sub export_excel_to_word()
Dim appWord
Dim quoteWord
Dim wordSelection
Set appWord = CreateObject("Word.Application")
appWord.Visible = True
Set quoteWord = appWord.Documents.Add
Set wordSelection = appWord.Selection
'This part works
Module1.ImagesRefresh
'Product 1 image insertion
Sheets("Quick Lookup").Shapes("QuoteProduct1Image").Copy
wordSelection.PasteSpecial Link:=False, _
DataType:=wdPasteShape, _
Placement:=wdInLine, _
DisplayAsIcon:=False
'This part does not work and is where I need help
With wordSelection
.WrapFormat.Type = wdWrapFront
End With
Try creating a variable to represent the newly pasted shape, it should be accessible by index, and should be the last index:
'Product 1 image insertion
ActiveSheet.Shapes(1).Copy
wordSelection.PasteSpecial Link:=False, _
DataType:=wdPasteShape, _
Placement:=wdInLine, _
DisplayAsIcon:=False
Dim wdShape As Word.Shape
Set wdShape = quoteWord.Shapes(quoteWord.Shapes.Count)
wdShape.WrapFormat.Type = wdWrapTight
Without using the shape variable, this might also work, but I have not tested against a document with several shapes (assuming you're adding shapes in sequence/iteration)
'Product 1 image insertion
ActiveSheet.Shapes(1).Copy
wordSelection.PasteSpecial Link:=False, _
DataType:=wdPasteShape, _
Placement:=wdInLine, _
DisplayAsIcon:=False
wordSelection.ShapeRange(1).WrapFormat.Type = wdWrapTight
If you're also inserting text (e.g., through the TypeText method of a Word.Range, try the code below. I'm not super-familar with Word automation, and the rule that you should avoid activate/select I think is less strict in Word (or has more exceptions) but as a rule of thumb, I'd still try to avoid reliance on the Selection object, and work with ranges instead.
What I'm doing here is pasting to the wordSelection.Range rather than the Selection itself. Then I do
ActiveSheet.Shapes(1).Copy
wordSelection.Range.PasteSpecial Link:=False, _
DataType:=wdPasteShape, _
Placement:=wdInLine, _
DisplayAsIcon:=False
Dim wdShape As Word.Shape
Set wdShape = quoteWord.Shapes(quoteWord.Shapes.Count)
wdShape.WrapFormat.Type = wdWrapTight
wordSelection.TypeText "some text"

How to change an existing Tabstop in PowerPoint by VBA?

I have a VBA Code to resize objects in PowerPoint including Font size, margins and everything else. But I haven’t found a solution to update/change an existing TapStop. There is a the Ruler Object with different levels und a default value. I double checked also the TextRange Object with Characters.
Are there any ideas to update the TabStop size?
Here is an example of a TextBox, i would like to resize:
TextBox Example
Shape.textframe.ruler.tabstops.count is always 0, if I "take" just the shape by For-Each-Loop. If I select it manual, it's also 0 at the sub menu TabStops of Paragraph menu.
If I click inside the shape (blinking cursor) and open the TabStops menu again, I see one TabStopPosition.
How can I access this information by VBA?
I tried it already by Line.Selection and nothing works.
Thanks!
Moe
PowerPoint used to allow only one set of paragraph settings per textframe (ie, per shape). That changed in PPT2007; now each paragraph can have its own tab and other settings. Have a go with this:
Sub ShowMeTabs()
Dim X As Long
Dim lTabCount As Long
With ActiveWindow.Selection.ShapeRange(1).TextFrame2.TextRange
For X = 1 To .Paragraphs.Count
Debug.Print X
With .Paragraphs(X).ParagraphFormat
For lTabCount = 1 To .TabStops.Count
Debug.Print .TabStops(lTabCount).Position
Next ' Tab
Debug.Print "Level:" & .IndentLevel & " Position:" & .LeftIndent 'etc
End With
Next ' paragraph x
End With
End Sub

Transferring text range from 1 power point to another to change template

I am very new with Powerpoint VBA and would like to know if there is a short way to transfer one text range from PowerPoint A to another text range located in Powerpoint B in a specific sequence.
Page a1 = b1
Page a2 = b2
Page a3 = b3
The template is changing and I need to adapt 5 powerpoints of 100 slides so I tought it would be easier with this solution.
Thank you in advance for your help.
PRECISION : I don't want to copy and paste the text range but to copy the text inside the range to put it inside the new range. Please find below the code I already have but It doesnt' Paste it inside my new range.
Sub copier_texte() 'je veux copier le contenu de la forme, et non pas la forme en entier
Dim nb_slide As Integer
nb_slide = ActivePresentation.Slides.Count
With ActivePresentation
.Slides(1).Shapes(2).TextFrame.TextRange.Copy 'je sélectionne uniquement le contenu de la forme
For i = 2 To .Slides.Count
.Slides(i).Select
ActiveWindow.View.Paste
Next i
End With
End Sub
Short Answer:
Is there're a short way to transfer one text range from PowerPoint A to another text range located in Powerpoint B?
I think that there's no short way to do it, but let's try something first!
Long Answer:
Note: This solution based not on your desired behaviour (since it's unclear for me and there're many and more "what if" cases), but on similar problem, so I think that it's legit. Anyway it's a good fundament to start of.
Input:
I dont know how exactly your presentations looks like, so I made a reference one (Presentation A) and a "broken" one (Presentation B). Let's take a look on them:
Presentation A (5 slides: 1x"Title slide" with 2 triangle shapes, 3x"Title and Content" slides, 1x"Section Header" slide):
Presentation B (5 slides: 1x"Title slide" missing triangle shapes, 3x"Title and Content" slides with empty/without shapes(placeholders), 1x"Blank" slide (wrong layout)):
Both presentations are in the same folder:
Desired behaviour:
Some sort of synchronisation, if we miss a shape - then create one and put desired text to it, if there's one - put desired text only (based on Presentations A's shape). There're some "what if" cases in logic:
"What if" the number of slides in each presentation isn't equal? In which order compare slides then? (In our case the number is equal, so in code we drop that part and compare slides pair by pair).
"What if" the compared slides have a different layout? (In our case difference in blank layout, so we can easily handle it, but what we should do in general?)
...and many other cases not considered in this solution
Logic:
Logic is plain and simple. The entry point to our routine is in the Presentation A, since it's an our reference file. From that point we acquire a reference to Presentation B (when opening it), and start iteration in two loops (thru each pair of slides and thru reference shapes).
If we found a "broken" (or not so, there's no check for that) shape by a reference one - we put text and some options in it or create a new one shape (or placeholder) otherwise.
Option Explicit
Sub Synch()
'define presentations
Dim ReferencePresentation As Presentation
Dim TargetPresentation As Presentation
'define reference objects
Dim ReferenceSlide As Slide
Dim ReferenceSlides As Slides
Dim ReferenceShape As Shape
'define target objects
Dim TargetSlide As Slide
Dim TargetSlides As Slides
Dim TargetShape As Shape
'define other variables
Dim i As Long
'Setting-up presentations and slide collections
Set ReferencePresentation = ActivePresentation
With ReferencePresentation
Set TargetPresentation = Presentations.Open(FileName:=.Path & "/Presentation B.pptm", _
WithWindow:=msoFalse)
Set ReferenceSlides = .Slides
End With
Set TargetSlides = TargetPresentation.Slides
'Check slide count
If ReferenceSlides.Count <> TargetSlides.Count Then
'What's a desired behaviour for this case?
'We can add slides to target presentation but it adds complexity
Debug.Print "ERROR!" & vbTab & "Reference And Target slides counts are not equal!"
Else
'"mainloop" for slides
For i = 1 To ReferenceSlides.Count
Set ReferenceSlide = ReferenceSlides(i)
Set TargetSlide = TargetSlides(i)
'Check slide layout
If ReferenceSlide.Layout <> TargetSlide.Layout Then
'What's a desired behaviourfor this case?
'We can change layout for target presentation but it adds complexity
'But let's try to change a layout too, since we have an easy case in our example!
Debug.Print "WARNING!" & vbTab & "Reference And Target slides layouts are not same!"
TargetSlide.Layout = ReferenceSlide.Layout
End If
'"innerloop" for shapes (for placeholders actually)
With ReferenceSlide
For Each ReferenceShape In .Shapes
Set TargetShape = AcquireShape(ReferenceShape, TargetSlide, True)
If TargetShape Is Nothing Then
Debug.Print "WARNING!" & vbTab & "There's no shape like " & ReferenceShape.Name
ElseIf TargetShape.HasTextFrame Then
With TargetShape.TextFrame.TextRange
'paste text
.Text = ReferenceShape.TextFrame.TextRange.Text
'and options
.Font.Size = ReferenceShape.TextFrame.TextRange.Font.Size
.Font.Name = ReferenceShape.TextFrame.TextRange.Font.Name
.Font.Color.RGB = ReferenceShape.TextFrame.TextRange.Font.Color.RGB
'...
End With
End If
Next
End With
Next
End If
'Save and close target presentation
Call TargetPresentation.Save
Call TargetPresentation.Close
End Sub
Function AcquireShape(ByRef ReferenceShape As Shape, ByRef TargetSlide As Slide, _
Optional ByVal CreateIfNotExists As Boolean) As Shape
Dim TargetShape As Shape
With ReferenceShape
'seek for existed shape
For Each TargetShape In TargetSlide.Shapes
If TargetShape.Width = .Width And TargetShape.Height = .Height And _
TargetShape.Top = .Top And TargetShape.Left = .Left And _
TargetShape.AutoShapeType = .AutoShapeType Then
Set AcquireShape = TargetShape
Exit Function
End If
Next
'create new
If CreateIfNotExists Then
If .Type = msoPlaceholder Then
Set AcquireShape = TargetSlide.Shapes.AddPlaceholder(.PlaceholderFormat.Type, .Left, .Top, .Width, .Height)
Else
Set AcquireShape = TargetSlide.Shapes.AddShape(.AutoShapeType, .Left, .Top, .Width, .Height)
End If
End If
End With
End Function
Output:
I know that it's hard to find any difference by a screenshot (it's can be even photoshoped, anyway there're a few difference for that purpose), but for a full answer, here it is:
Conclusion:
As you see, it isn't a hard task to achieve something similar to your desire, but complexity of solution depends on inputs and on "what if" cases, hence there's no short way to overcome this task in general (in my humble opinion). Cheers!
Your question has a number of different interpretations, below is my attempt to answer what I believe the question is. There are a number of stage to this solution.
1. Ensure we save the VBA we write
Firstly, we have to assume a master presentation, that is one that will hold the values to be copied into all others. This will need to be saved as a macro enabled presentation (pptm) to allow us to save our VBA. This is done via File > Save-As and while selecting the save location choose PowerPoint Macro-Enabled Presentation in the Save as type box.
2. Enable Windows scripting runtime
Within the pptm 'master' presentation that we now have, open the VBA IDE (Alt+F11). In the menu bar select Tools > References... and tick Microsoft Scripting Runtime from the list that is presented. Click OK to close the references dialog box with your tick remembered. This is needed for some error handling in the code, it checks to see if the presentation exists before trying to open it.
3. Insert the provided code
Right-click on VBAProject in the upper right area (the Project explorer) and select Insert > Module.
In the main editing area paste the below (I have added commenting to describe what is happening): -
Option Explicit
Public Sub Update()
Dim AryPresentations(4) As String
Dim LngPID As Long
Dim FSO As New FileSystemObject
Dim PP_Src As Presentation
Dim PP_Dest As Presentation
Dim Sld_Src As Slide
Dim Sld_Dest As Slide
Dim Shp_Src As Shape
Dim Shp_Dest As Shape
Dim LngFilesMissing As Long
Dim BlnWasOpen As Boolean
'If there is an error, this will handle it and stop the process
On Error GoTo ErrorHandle
'Increase the size of AryPresentations and and the paths as shown in the example below
AryPresentations(0) = "C:\Users\garye\Desktop\PP2.pptx"
AryPresentations(1) = "C:\Users\garye\Desktop\PP3.pptx"
AryPresentations(2) = "C:\Users\garye\Desktop\PP4.pptx"
AryPresentations(3) = "C:\Users\garye\Desktop\PP5.pptx"
AryPresentations(4) = "C:\Users\garye\Desktop\PP6.pptx"
'PP_Src is this, our 'master' presentation
Set PP_Src = ActivePresentation
'This loops through each item in AryPresentations
For LngPID = 0 To UBound(AryPresentations, 1)
'We rememeber if you had it open already as if you did, then we won't close it when we are done
BlnWasOpen = False
'Check all currently open presentations to see if one if the presentation we are due to update
For Each PP_Dest In PowerPoint.Presentations
If Trim(UCase(PP_Dest.FullName)) = Trim(UCase(AryPresentations(LngPID))) Then Exit For
Next
'If it was not already open, check it exists and if it does, then open in
If PP_Dest Is Nothing Then
If FSO.FileExists(AryPresentations(LngPID)) Then
Set PP_Dest = PowerPoint.Presentations.Open(AryPresentations(LngPID))
End If
Else
BlnWasOpen = True
End If
If PP_Dest Is Nothing Then
Debug.Print "File note found"
LngFilesMissing = LngFilesMissing + 1
Else
'The below connects to the slide (Sld_Src) you want to pick up from, the shape (Shp_Src) you want to pick up from and then
'places it in the slide (Sld_Dest) you want it to go to into the shape (Shp_Dest) you want it to go in to
Set Sld_Src = PP_Src.Slides(1)
Set Sld_Dest = PP_Dest.Slides(1)
Set Shp_Src = Sld_Src.Shapes(1)
Set Shp_Dest = Sld_Dest.Shapes(1)
Shp_Dest.TextFrame.TextRange.Text = Shp_Src.TextFrame.TextRange.Text
Set Shp_Dest = Nothing
Set Shp_Src = Nothing
Set Sld_Dest = Nothing
Set Sld_Src = Nothing
'Repeat the above for each piece of text to copy
'Finally save the changes
PP_Dest.Save
'Close the presentation if it was not already open
If Not BlnWasOpen Then PP_Dest.Close
End If
Next
MsgBox "Process complete. Number of missing files: " & LngFilesMissing, vbOKOnly + vbInformation, "Complete"
Exit Sub
ErrorHandle:
MsgBox "There was an error: - " & vbNewLine & vbNewLine & Err.Number & ": " & Err.Description, vbOKOnly + vbExclamation, "Error"
Err.Clear
End Sub
4. Customise code
You'll want to add the paths and location of the changes in and then it should run.