I am looking to format multiple selected charts on Excel 2010 using VBA. The code below works when only one chart is selected but when multiple charts are selected, I get a "run-time error '91' Object variable or With Block variable not set". Any idea how to run the macro for number of selected charts?
Sub ChartFormat5_Click()
''Adjust chart area
'Size
Selection.Width = 631.9
Selection.Height = 290.1
'Border
With Selection.Format.Line
.Visible = msoTrue
.ForeColor.ObjectThemeColor = msoThemeColorText1
.ForeColor.TintAndShade = 0
.ForeColor.Brightness = 0
.Transparency = 0
.Weight = 1
.DashStyle = msoLineSolid
End With
'Font
With Selection.Format.TextFrame2.TextRange.Font
.Name = "Calibri"
.Size = 10
.Fill.Visible = msoTrue
.Fill.ForeColor.ObjectThemeColor = msoThemeColorText1
.Fill.ForeColor.TintAndShade = 0
.Fill.ForeColor.Brightness = 0
.Fill.Transparency = 0
.Fill.Solid
End With
End Sub
Thanks!
This will process the active chart or all selected charts. The first routine determines what to process (active chart or selected charts) and the second processes each.
Sub FormatCharts()
Dim obj As Object
If Not ActiveChart Is Nothing Then
FormatOneChart ActiveChart
Else
For Each obj In Selection
If TypeName(obj) = "ChartObject" Then
FormatOneChart obj.Chart
End If
Next
End If
End Sub
Sub FormatOneChart(cht As Chart)
' do all your formatting here, based on cht not on ActiveChart
End Sub
Don't select parts of the chart, just fully reference them. Instead of
ActiveChart.ChartArea.Select
With Selection.Format.Line
use this
With cht.ChartArea.Format.Line
etc.
Note: this is a duplicate of VBA: Formatting Multiple Selected Charts (Chart, Plot, Legend, etc.)
After some trial-n-error, I figured out how to make it work if you have just one or multiple charts selected. It was straightforward, but this worked when I tested it.
Note that I broke the actual Chart Area formatting into a separate sub.
Sub ChartFormat5_Click()
Select Case TypeName(Selection)
Case Is = "ChartArea" `only 1 selected
FormatChart Selection
Case Is = "DrawingObjects" 'more than 1 selected
Dim cht As ChartObject
For Each cht In Selection
FormatChart cht.Chart.ChartArea
Next
End Select
End Sub
Sub FormatChart(chtArea As ChartArea)
With chtArea
'size
.Width = 631.9
.Height = 290.1
With .Format
'Border
With .Line
.Visible = msoTrue
.ForeColor.ObjectThemeColor = msoThemeColorText1
.ForeColor.TintAndShade = 0
.ForeColor.Brightness = 0
.Transparency = 0
.Weight = 1
.DashStyle = msoLineSolid
End With
'Font
With .TextFrame2.TextRange.Font
.Name = "Calibri"
.Size = 10
With .Fill
.Visible = msoTrue
With .ForeColor
.ObjectThemeColor = msoThemeColorText1
.TintAndShade = 0
.Brightness = 0
End With
.Transparency = 0
.Solid
End With
End With
End With
End With
End Sub
Hy try:
Sub ChartFormat5_Click_v02()
For i = 1 To Application.Sheets.Count
Application.Sheets(i).Activate
For j = 1 To ActiveSheet.ChartObjects.Count
ActiveSheet.ChartObjects(j).Activate
'your code here
Next j
Next i
End Sub
Related
I have some vsto add-in to PowerPoint.
I need to know which part of chart is selected by user (series, title, charta area, plot area, legend etc.). Is it possible to get such information?
I know, of course, how to get selected chart.
My add-in is written in VBA, but I think the below will help you. The PPT object model doesn't support this, so my hacky solution was to apply Strikethrough font as an ExecuteMSO command (i.e., Strikethrough is applied to whatever is selected), then I go through every element of the chart and look for Strikethrough. When we find it, we can tell what the user had selected, apply whatever rules we want, and remove the Strikethrough.
In my case, I wanted to rewrite the Bold command so that we could apply a different font weight to the user's selection, rather than using the native faux-bolding. Here is part of my solution:
First, this is the sub that's called when the selection contains shapes. Note how we handle the chart scenario:
Private Sub commandBoldSelectedShapes(mySelection As Selection)
Debug.Print "IN_commandBoldSelectedShapes"
Dim oShp As Shape
Dim oSmrtArt As SmartArt
Dim oTable As Table
Dim oChart As Chart
Dim oCell As Cell
Dim i As Long
Dim j As Long
Dim ctr As Long
Dim oFont As Font
For ctr = 1 To mySelection.ShapeRange.Count
Set oShp = mySelection.ShapeRange(ctr)
If oShp.Type = msoGroup Then
RefontTypoGroup oShp, mySelection
ElseIf oShp.HasSmartArt Then
Set oSmrtArt = oShp.SmartArt
DoEvents
Application.CommandBars.ExecuteMso ("Strikethrough")
DoEvents
RefontTypoSmartArt oSmrtArt
ElseIf oShp.HasTable Then
Debug.Print "Seeing a table!"
Set oTable = oShp.Table
If ctr = 1 And mySelection.ShapeRange.Count = 1 Then
With oTable
For i = 1 To oTable.Rows.Count
For j = 1 To oTable.Columns.Count
Set oCell = oTable.Rows(i).Cells(j)
If oCell.Selected Then
Set oFont = oCell.Shape.TextFrame.TextRange.Font
checkBoldsNoStrikethrough oFont
End If
Next
Next
End With
Else
For i = 1 To oTable.Rows.Count
For j = 1 To oTable.Columns.Count
Set oCell = oTable.Rows(i).Cells(j)
Set oFont = oCell.Shape.TextFrame.TextRange.Font
checkBoldsNoStrikethrough oFont
Next
Next
End If
' Charts are highly problematic because the VBA Selection object
' doesn't allow you to figure out which element(s) in a chart the user
' may have selected. You can only see that the full shape containing a chart
' has been selected. So my solution was to run an
' ExecuteMso - Strikethrough command. Then, separate macros
' go through the whole chart looking for strikethoughs and replace them
' with bolded/unbolded text and the correct font weight.
ElseIf oShp.HasChart Then
Debug.Print "Seeing a chart!"
Set oChart = oShp.Chart
If ctr = 1 And mySelection.ShapeRange.Count = 1 Then
DoEvents
Application.CommandBars.ExecuteMso ("Strikethrough")
DoEvents
RefontTypoChart oChart
Exit Sub
' If there is more than one shape selected, including a chart,
' and that chart is not the first shape selected, we know that
' the whole chart has been selected. As a result, we can simply
' apply bolding to the whole chart.
Else
With oChart.ChartArea.Format.TextFrame2.TextRange.Font
If GlobalSettings.IsBoldPressed = False Then
.Bold = False
.Name = FontsSettings.ActiveFonts.bodyFont
Else
.Bold = True
.Name = FontsSettings.ActiveFonts.headingFont
End If
End With
End If
ElseIf oShp.HasTextFrame Then
If oShp.TextFrame.HasText Then
Set oFont = oShp.TextFrame.TextRange.Font
checkBoldsNoStrikethrough oFont
End If
End If
Next
End Sub
And there is the sub that starts going through the chart elements. Most checks are outsourcing the Strikethrough hunt to yet another sub:
Sub RefontTypoChart(chrt As Chart)
On Error GoTo Errhandler
' Dim s As Series
Dim A As axis
' Dim scnt As Integer
Dim i As Integer
Dim oShp As Shape
Dim oTxtRange2 As TextRange2
Dim oTickLabels As TickLabels
Dim oLegendEntries As LegendEntries
Set oTxtRange2 = chrt.Format.TextFrame2.TextRange
If oTxtRange2.Font.Strikethrough = msoTrue Then
RefontTypoChartShapeRange oTxtRange2
Exit Sub
End If
If chrt.HasLegend Then
Set oLegendEntries = chrt.Legend.LegendEntries
For i = 1 To oLegendEntries.Count
With oLegendEntries(i).Font
If GlobalSettings.IsBoldPressed = False Then
If .Strikethrough = True Then
.Bold = False
.Name = FontsSettings.ActiveFonts.bodyFont
.Strikethrough = False
End If
Else
If .Strikethrough = True Then
.Bold = True
.Name = FontsSettings.ActiveFonts.headingFont
.Strikethrough = False
End If
End If
End With
Next
With chrt.Legend.Format.TextFrame2.TextRange.Font
If GlobalSettings.IsBoldPressed = False Then
If .Strikethrough = True Then
.Bold = False
.Name = FontsSettings.ActiveFonts.bodyFont
.Strikethrough = False
End If
Else
If .Strikethrough = True Then
.Bold = True
.Name = FontsSettings.ActiveFonts.headingFont
.Strikethrough = False
End If
End If
End With
End If
If chrt.HasTitle Then
Set oTxtRange2 = chrt.ChartTitle.Format.TextFrame2.TextRange
RefontTypoShapeRange oTxtRange2
End If
If chrt.HasAxis(xlCategory, xlPrimary) Then
Set A = chrt.Axes(xlCategory, xlPrimary)
If A.HasTitle = True Then
Set oTxtRange2 = A.AxisTitle.Format.TextFrame2.TextRange
RefontTypoShapeRange oTxtRange2
End If
Set oTickLabels = A.TickLabels
RefontTypoTickLabels oTickLabels
End If
If chrt.HasAxis(xlCategory, xlSecondary) Then
Set A = chrt.Axes(xlCategory, xlSecondary)
If A.HasTitle = True Then
Set oTxtRange2 = A.AxisTitle.Format.TextFrame2.TextRange
RefontTypoShapeRange oTxtRange2
End If
Set oTickLabels = A.TickLabels
RefontTypoTickLabels oTickLabels
End If
If chrt.HasAxis(xlValue, xlPrimary) Then
Set A = chrt.Axes(xlValue, xlPrimary)
If A.HasTitle = True Then
Set oTxtRange2 = A.AxisTitle.Format.TextFrame2.TextRange
RefontTypoShapeRange oTxtRange2
End If
Set oTickLabels = A.TickLabels
RefontTypoTickLabels oTickLabels
End If
If chrt.HasAxis(xlValue, xlSecondary) Then
Set A = chrt.Axes(xlValue, xlSecondary)
If A.HasTitle = True Then
Set oTxtRange2 = A.AxisTitle.Format.TextFrame2.TextRange
RefontTypoShapeRange oTxtRange2
End If
Set oTickLabels = A.TickLabels
RefontTypoTickLabels oTickLabels
End If
RefontTypoChartLabels chrt
If chrt.Shapes.Count > 0 Then
For Each oShp In chrt.Shapes
If oShp.HasTextFrame Then
If oShp.TextFrame.HasText Then
Set oTxtRange2 = oShp.TextFrame2.TextRange
RefontTypoShapeRange oTxtRange2
End If
End If
Next
End If
Exit Sub
Errhandler:
Debug.Print "Error: " & Err.Description
End Sub
Here is the sub that looks for most of the Strikethroughs:
Public Sub RefontTypoShapeRange(oTxtRange2 As TextRange2)
Dim i As Long
With oTxtRange2
For i = .Runs.Count To 1 Step -1
With .Runs(i).Font
If GlobalSettings.IsBoldPressed = False Then
If .Strikethrough = True Then
.Bold = False
.Name = FontsSettings.ActiveFonts.bodyFont
End If
Else
If .Strikethrough = True Then
.Bold = True
.Name = FontsSettings.ActiveFonts.headingFont
End If
End If
End With
Next
.Font.Strikethrough = False
End With
End Sub
You may notice that in the second sub posted, there are references to a few different subs that are specialized for certain chart elements. This is because TickLabels don't have a TextRange2 object and therefore need their own checker sub (one which passes along a TickLabels object). Also, there's a distinction made between chart elements that can have more than one formatting Run, and those that can't -- looking for Runs in the TextRange2 object of chart elements that don't support more than 1 run will cause a crash.
Public Sub RefontTypoChartShapeRange(oTxtRange2 As TextRange2)
Debug.Print "IN_RefontTypoChartShapeRange"
With oTxtRange2.Font
If GlobalSettings.IsBoldPressed = False Then
If .Strikethrough <> msoFalse Then
.Bold = False
.Name = FontsSettings.ActiveFonts.bodyFont
End If
Else
If .Strikethrough <> msoFalse Then
.Bold = True
.Name = FontsSettings.ActiveFonts.headingFont
End If
End If
.Strikethrough = False
End With
End Sub
Chart data labels are a small nightmare too, as they will become disconnected from the data if we don't massage the .Autotext property as seen below.
Sub RefontTypoChartLabels(oChrt As Chart)
Dim i As Integer
Dim j As Integer
Dim seriesVar As Series
Dim dataLabelsVar As DataLabels
Dim dataLabelVar As DataLabel
Dim pointVar As Point
Dim oTxtRange2 As TextRange2
Dim isAutoText As Boolean
For i = 1 To oChrt.SeriesCollection.Count
Set seriesVar = oChrt.SeriesCollection(i)
If seriesVar.HasDataLabels = True Then
Set dataLabelsVar = seriesVar.DataLabels
If dataLabelsVar.Format.TextFrame2.TextRange.Font.Strikethrough <> msoFalse Then
Set oTxtRange2 = dataLabelsVar.Format.TextFrame2.TextRange
RefontTypoChartShapeRange oTxtRange2
Else
For j = 1 To seriesVar.Points.Count
Set pointVar = seriesVar.Points(j)
If pointVar.HasDataLabel = True Then
Set dataLabelVar = seriesVar.DataLabels(j)
isAutoText = dataLabelVar.AutoText
Set oTxtRange2 = dataLabelVar.Format.TextFrame2.TextRange
RefontTypoChartShapeRange oTxtRange2
dataLabelVar.AutoText = isAutoText
End If
Next
End If
End If
Next
End Sub
Hopefully you're able to adapt some of this to your needs and avoid pulling out your hair. You can also use Shadow instead of Strikethrough if you think someone somewhere might need to use Strikethrough font inside a chart.
The PowerPoint object model doesn't provide any property or method for that.
For internal communication purposes in a group of people I have created a macro adding comment fields to a slide - not those of PPT itself.
Dim shp As Shape
Dim sld As Slide
'Comment field
On Error GoTo ErrMsg
If ActiveWindow.Selection.SlideRange.Count <> 1 Then
MsgBox "This function cannot be used for several slides at the same time"
Exit Sub
Else
Set sld = Application.ActiveWindow.View.Slide
Set shp = sld.Shapes.AddShape(Type:=msoShapeRectangle, Left:=0, Top:=104.88182, Width:=198.42507, Height:=28.913368)
shp.Fill.Visible = msoTrue
shp.Fill.Transparency = 0
shp.Fill.ForeColor.RGB = RGB(211, 61, 95)
shp.Line.Visible = msoTrue
shp.Line.ForeColor.RGB = RGB(255, 255, 255)
shp.Line.Weight = 0.75
shp.Tags.Add "COMMENT", "YES"
shp.Select
shp.TextFrame.TextRange.Font.Color.RGB = RGB(255, 255, 255)
shp.TextFrame.TextRange.Characters.Text = "Comment: "
shp.TextFrame.TextRange.Paragraphs.ParagraphFormat.Alignment = ppAlignLeft
shp.TextFrame.VerticalAnchor = msoAnchorTop
shp.TextFrame.TextRange.Font.Size = 12
shp.TextFrame.TextRange.Font.Name = "Arial"
shp.TextFrame.TextRange.Font.Bold = msoTrue
shp.TextFrame.TextRange.Font.Italic = msoFalse
shp.TextFrame.TextRange.Font.Underline = msoFalse
shp.TextFrame.Orientation = msoTextOrientationHorizontal
shp.TextFrame.MarginBottom = 7.0866097
shp.TextFrame.MarginLeft = 7.0866097
shp.TextFrame.MarginRight = 7.0866097
shp.TextFrame.MarginTop = 7.0866097
shp.TextFrame.WordWrap = msoTrue
shp.TextFrame.AutoSize = ppAutoSizeShapeToFitText
shp.TextFrame.TextRange.Select
End If
Exit Sub
ErrMsg:
MsgBox "Please select a slide"
End Sub
Works well.
I have tagged them, because I want it to be easy to delete all of them at once, e.g., in case you find comments 5 minutes before you have to present. Here's my way to delete them:
Sub CommDel()
Dim sld As Slide
Dim L As Long
If MsgBox("Do you want to delete ALL comments from the entire presentation?", vbYesNo) <> vbYes Then Exit Sub
On Error Resume Next
For Each sld In ActivePresentation.Slides
For L = sld.Shapes.Count To 1 Step -1
If sld.Shapes(L).Tags("COMMENT") = "YES" Then sld.Shapes(L).Delete
Next L
Next sld
End Sub
Works fine, too.
Third step I would like to do, is creating a third macro, called "find next comment". On every click it jumps to the next shape tagged with the tag "COMMENT", no matter if that shape is on the same slide or the next or somewhere else in the presentation. Just the next one, where ever it is. And now I'm completely lost. I am able to do something to all tagged shapes on one slide or inthe entire presentation - as you can see in the function to delete. But what I'm looking for is not selecting all shapes at the same time. In another try I was able to find the first one - but after clicking the macro again nothing seemed to happen, because the macro started searching at the same point and selected the same shape again and again, never jumping to the next one, except I deleted the first one.
Would be great to read your ideas. Thank you in advance. But be careful, I'm far from being a good programmer. ;-)
This starts at the current slide and works toward the end, dropping out of the Sub as soon as the first comment is found:
Sub FindNextComment()
Dim oSlide As Slide
Dim oShape As Shape
Set oSlide = ActiveWindow.View.Slide
For Each oShape In oSlide.Shapes
If oShape.Tags.Count > 0 Then
For y = 1 To oShape.Tags.Count
If oShape.Tags.Name(y) = "COMMENT" Then
oShape.Select
Exit Sub
End If
Next y
End If
Next oShape
For x = oSlide.SlideIndex + 1 To ActivePresentation.Slides.Count
For Each oShape In ActivePresentation.Slides(x).Shapes
If oShape.Tags.Count > 0 Then
For y = 1 To oShape.Tags.Count
If oShape.Tags.Name(y) = "COMMENT" Then
ActivePresentation.Slides(x).Select
oShape.Select
Exit Sub
End If
Next y
End If
Next oShape
Next x
End Sub
Bonus VBA Tip: You can make your code run a little faster by using With statements:
With shp.TextFrame
.MarginBottom = 7.0866097
.MarginLeft = 7.0866097
.MarginRight = 7.0866097
.MarginTop = 7.0866097
.WordWrap = msoTrue
.AutoSize = ppAutoSizeShapeToFitText
.Orientation = msoTextOrientationHorizontal
.VerticalAnchor = msoAnchorTop
With .TextRange
.Characters.Text = "Comment: "
.Paragraphs.ParagraphFormat.Alignment = ppAlignLeft
With .Font
.Size = 12
.Name = "Arial"
.Bold = msoTrue
.Italic = msoFalse
.Underline = msoFalse
End With
End With
End With
I hope you are doing well.
I am a little stuck on a macro scripting, I would like to perform the following
Once the macro is launch ; create a form rectangle with attributes (see below)
If a rectangle already exist within the active slide the delete it.
Here is the little macro code written to insert the shape
Sub TBU()
Dim oSh As Shape
Set oSh = ActiveWindow.Selection.SlideRange.Shapes.AddShape(msoShapeRectangle, 902, 5, 47, 27)
With oSh
With .TextFrame.TextRange
.Text = "[TBU]"
With .Font
.name = "Arial"
.Size = 12
.Bold = msoFalse
.Italic = msoFalse
.Underline = msoFalse
.Shadow = msoFalse
.Emboss = msoFalse
.BaselineOffset = 0
.AutoRotateNumbers = msoFalse
.Color = RGB(255, 0, 0)
End With
End With
With oSh
.Fill.Visible = msoTrue
.Fill.ForeColor.RGB = RGB(255, 255, 0)
.Fill.Solid
End With
End With
End Sub
I tried to delete the shape within the active slide only if a rectangle with the same attributes already existed but got stuck on that.
Does anyone has an idea?
Kind regards,
Naxos
I think the best way to find any shapes that you want to delete is to iterate over all the shapes in the current slide, and call a function that checks if the shape given matches your criteria.
It would look something like the code below. Basically, any one condition not matching is sufficient to say that the shape shouldn't be deleted. Therefore the function starts off by assuming that the shape should be deleted until it finds any condition that indicates otherwise, at which point it changes the return value to false and ceases checking for the given shape.
Dim i as Long
Dim sh as Shape
For i = ActiveWindow.View.Slide.Shapes.Count to 1 Step -1
Set sh = ActiveWindow.View.Slide.Shapes(I)
If ShouldBeDeleted(sh) Then
sh.Delete
End If
Next
'...
Function ShouldBeDeleted(sh as Shape) as Boolean
ShouldBeDeleted = True
'Repeat this IF structure for each criteria.
If sh.Fill.Visible <> msoTrue Then
ShouldBeDeleted = False
Exit Function
End If
If Not sh.HasTextFrame Then
ShouldBeDeleted = False
Exit Function
End If
'... keep repeating these if structures.
End Function
I want to create a program that will:
cycle through all my slides and find slides that contain Chart(s), these charts are not linked to any worksheet.
Chart must contain data and will be of ChartType = xlColumnClustered or ChartType(51) Like in the bellow picture.
If it has data then look at the numbers and change the colors of each bar according to the graph below (>=6.0 then Red, <=8.0 then Blue, 6.0<= x >=8.0 then Purple)
I have tried searching through every Expression in the Locals window of the debugger to see if I could find any difference between a graph with data and a graph that has no data. I found nothing. I'm not sure how I would be able to differentiate between a slide with data and one without.
I also don't know how I would be able to access the data in the Chart to apply the colors.
Any help would be appreciated in how to handle this.
Thank you!
i recorded a macro in excel of changing bar colors and tweaked it
there actually is a spreadsheet in powerpoint that feeds data to each chart in powerpoint
Application.ActivePresentation.Slides(1).Shapes(1).Chart.ChartData.Workbook.activesheet
you will have to read data from the worksheet to decide the colors for the bars, i think
here is the color changer
Option Explicit
Sub Macro1()
' recorded in excel and modified
Dim chrt As Chart
' Set chrt = ActiveSheet.ChartObjects("Chart 1").Chart ' excel object
Set chrt = Application.ActivePresentation.Slides(1).Shapes(1).Chart
chrt.ClearToMatchStyle
chrt.ChartStyle = 203
chrt.ChartStyle = 340
chrt.ChartStyle = 333
chrt.ChartStyle = 399
chrt.ChartType = xlColumnClustered
Dim fsc As FullSeriesCollection
Set fsc = chrt.FullSeriesCollection
With fsc(1).Format.Fill
.Visible = msoTrue
.ForeColor.RGB = RGB(255, 192, 0)
.Transparency = 0.5
.Solid
End With
With fsc(1).Format.Line
.Visible = msoTrue
.ForeColor.RGB = RGB(255, 0, 0)
.Transparency = 0
End With
With fsc(2).Format.Fill
.Visible = msoTrue
.ForeColor.ObjectThemeColor = msoThemeColorAccent1
.ForeColor.TintAndShade = 0
.ForeColor.Brightness = -0.25
.Transparency = 0
.Solid
End With
With fsc(3).Format.Fill
.Visible = msoTrue
.ForeColor.RGB = RGB(146, 208, 80)
.Transparency = 0
.Solid
End With
With fsc(3).Format.Line
.Visible = msoTrue
.ForeColor.RGB = RGB(255, 0, 0)
.Transparency = 0
End With
With fsc(1).Points(1).Format.Fill
.Visible = msoTrue
.ForeColor.RGB = RGB(255, 0, 0)
.Transparency = 0.6299999952
.Solid
End With
With fsc(1).Points(1).Format.Line
.Visible = msoTrue
.ForeColor.RGB = RGB(0, 176, 80)
.Transparency = 0.0500000119
.Weight = 5
.Style = msoLineThickBetweenThin
End With
End Sub
This post helped me figure out what I needed to do, coupled with some of the logic posted here by #jsotola. This is the PowerPoint version of those two and does exactly what was needed in the original question.
Option Explicit
Public Sub colorGraph()
Dim sld As Slide
Dim shpe As Shape
Dim pres As Object
Dim nPoint As Long
Dim iPoint As Long
Dim c As Chart
Dim s As Series
Set pres = ActivePresentation
For Each sld In pres.Slides
For Each shpe In sld.Shapes
Set s = shpe.Chart.SeriesCollection(1)
If Not shpe.HasChart Then GoTo nxtShpe
If Not shpe.Chart.ChartType = xlColumnClustered Then GoTo nxtShpe
If s.DataLabels.NumberFormat = "0%" Or s.DataLabels.NumberFormat = "0.0%" Or s.DataLabels.NumberFormat = "0.00%" Then GoTo nxtShpe
nPoint = s.Points.Count
For iPoint = 1 To nPoint
If s.Values(iPoint) >= 8 Then
s.Points(iPoint).Interior.Color = RGB(0, 255, 0)
ElseIf s.Values(iPoint) < 8 And s.Values(iPoint) >= 2 Then
s.Points(iPoint).Interior.Color = RGB(255, 0, 0)
ElseIf s.Values(iPoint) < 2 And s.Values(iPoint) > 0 Then
s.Points(iPoint).Interior.Color = RGB(0, 0, 255)
End If
Next iPoint
nxtShpe:
Next shpe
Next sld
End Sub
Is there an easy way to pro-actively or retro-actively apply a 'Picture Style' to all images stored in a word document?
I want to apply the 'Center Shadow Rectangle' picture style to all images that I add to a document without changing them 1 by 1.
The picture style concept only exists at the UI level. To apply it to an image, you will have to check the properties of the style in the UI and apply them one by one using VBA:
Sub FormatPictures()
Dim oInlineShape As inlineShape
For Each oInlineShape In ActiveDocument.InlineShapes
ApplyPictureStyleToInlineShape oInlineShape
Next
Dim oShape As Shape
For Each oShape In ActiveDocument.Shapes
ApplyPictureStyleToShape oShape
Next
End Sub
Sub ApplyPictureStyleToInlineShape(shape As inlineShape)
' borders
shape.Borders.Enable = False
' fill
shape.Fill.Visible = msoFalse
' line
shape.Line.Visible = msoFalse
' shadow
shape.Shadow.Style = msoShadowStyleOuterShadow
shape.Shadow.Type = msoShadow21
shape.Shadow.ForeColor = WdColor.wdColorBlack
shape.Shadow.Transparency = 0.3
shape.Shadow.Size = 100
shape.Shadow.Blur = 15
shape.Shadow.OffsetX = 0
shape.Shadow.OffsetY = 0
' reflection
shape.Reflection.Type = msoReflectionTypeNone
' glow
shape.Glow.Radius = 0
shape.SoftEdge.Radius = 0
End Sub
Sub ApplyPictureStyleToShape(shape As shape)
' fill
shape.Fill.Visible = msoFalse
' line
shape.Line.Visible = msoFalse
' shadow
shape.Shadow.Style = msoShadowStyleOuterShadow
shape.Shadow.Type = msoShadow21
shape.Shadow.ForeColor = WdColor.wdColorBlack
shape.Shadow.Transparency = 0.3
shape.Shadow.Size = 100
shape.Shadow.Blur = 15
shape.Shadow.OffsetX = 0
shape.Shadow.OffsetY = 0
' reflection
shape.Reflection.Type = msoReflectionTypeNone
' glow
shape.Glow.Radius = 0
shape.SoftEdge.Radius = 0
End Sub
Just got inspired by you guys (and others, so Thanks all!), and made my own macro to format a selected pasted picture with a single border (0.75 pt width) and simple shadow offset by 3 pts...
I assigned that macro to an icon, and voila!
Once I paste my image (most of them are screenshot for procedures and documentation of systems).
Works well in Word 2010.
I did not tested other versions ...
Sub FormatPictureWithLineAndShadow()
Dim oInlineShp As InlineShape
For Each oInlineShp In Selection.InlineShapes
With oInlineShp
'Line border
With .Borders(wdBorderLeft)
.LineStyle = wdLineStyleSingle
.LineWidth = wdLineWidth075pt
.Color = wdColorAutomatic
End With
With .Borders(wdBorderRight)
.LineStyle = wdLineStyleSingle
.LineWidth = wdLineWidth075pt
.Color = wdColorAutomatic
End With
With .Borders(wdBorderTop)
.LineStyle = wdLineStyleSingle
.LineWidth = wdLineWidth075pt
.Color = wdColorAutomatic
End With
With .Borders(wdBorderBottom)
.LineStyle = wdLineStyleSingle
.LineWidth = wdLineWidth075pt
.Color = wdColorAutomatic
End With
' shadow
.Shadow.Style = msoShadowStyleOuterShadow
.Shadow.Type = msoShadow21
.Shadow.ForeColor = WdColor.wdColorBlack
.Shadow.Transparency = 0.6
.Shadow.Size = 100
.Shadow.Blur = 5
.Shadow.OffsetX = 3
.Shadow.OffsetY = 3
' reflection
.Reflection.Type = msoReflectionTypeNone
' glow
.Glow.Radius = 0
.SoftEdge.Radius = 0
End With
Next
End Sub