Formatting Chart Legends Using With (Syntax) - excel

I have a macro which adds and removes (filterseries) set data series of a chart (in its own sheet) by looping through checkboxes in a separate sheet. When I add and remove them, I want to cycle the legend off then back on so that it resizes itself automatically.
I think this is just a syntax error of how I'm using the with statement.
I have a separate macro which does this for a different purpose, but it loops through chart-sheets and treats them as variables and, for some reason, it works there.
Sub ISurfSeries1Checklist()
Application.ScreenUpdating = False
Application.EnableEvents = False
Dim i As Integer
Dim c As Integer
For i = 1 To 56
If ActiveWorkbook.Sheets("Range").Cells(3 + i, 12).Value = True Then
ActiveWorkbook.Charts("I. Surf (1)").FullSeriesCollection(i).IsFiltered = False
Else 'ActiveWorkbook.Sheets("Range").Cells(3 + i, 12) = False Then
ActiveWorkbook.Charts("I. Surf (1)").FullSeriesCollection(i).IsFiltered = True
End If
Next i
For c = 51 To 56 'ActiveWorkbook.Charts("I. Surf (1)").FullSeriesCollection.Count
ActiveWorkbook.Charts("I. Surf (1)").FullSeriesCollection(c).Format.Line.Visible = msoTrue
ActiveWorkbook.Charts("I. Surf (1)").FullSeriesCollection(c).Format.Line.ForeColor.RGB = RGB(255, 0, 0)
ActiveWorkbook.Charts("I. Surf (1)").FullSeriesCollection(c).Format.Line.Transparency = 0
Next c
ActiveWorkbook.Charts("I. Surf (1)").HasLegend = False
ActiveWorkbook.Charts("I. Surf (1)").HasLegend = True
'***Below is where it stops working.***
With ActiveWorkbook.Charts("I.Surf (1)").Legend
.Font.Size = 8
.Border.Weight = xlHairline
.Border.Color = RGB(89, 89, 89)
.Interior.Color = RGB(255, 255, 255)
.Left = Cht_Sht.PlotArea.InsideLeft - Cht_Sht.Axes(xlValue).Format.Line.Weight
.Top = Cht_Sht.PlotArea.InsideTop
End With

Runtime Error '9'. Subscript out of range
on the With statement: With ActiveWorkbook.Charts("I.Surf (1)").Legend
That means a chart named "I.Surf (1)" does not exist you are probably missing the space between the dot and Surf. It should be "I. Surf (1)".
I recommend to reference the chart by a variable so you only have to use its name once. Coding rule number 1: Don't repeat yourself.
Dim ActChart As Chart
Set ActChart = ActiveWorkbook.Charts("I. Surf (1)")
This prevents typos and if you have to change it you only need to change it in one position:
Sub ISurfSeries1Checklist()
Application.ScreenUpdating = False
Application.EnableEvents = False
Dim ActChart As Chart
Set ActChart = ActiveWorkbook.Charts("I. Surf (1)")
Dim i As Long
For i = 1 To 56
'Note that you can shorten this to:
ActChart.FullSeriesCollection(i).IsFiltered = Not (ActiveWorkbook.Sheets("Range").Cells(3 + i, 12).Value = True)
Next i
Dim c As Long
For c = 51 To 56 'ActiveWorkbook.Charts("I. Surf (1)").FullSeriesCollection.Count
With ActChart.FullSeriesCollection(c).Format.Line
.Visible = msoTrue
.ForeColor.RGB = RGB(255, 0, 0)
.Transparency = 0
End With
Next c
ActChart.HasLegend = False
ActChart.HasLegend = True
With ActChart.Legend
.Font.Size = 8
.Border.Weight = xlHairline
.Border.Color = RGB(89, 89, 89)
.Interior.Color = RGB(255, 255, 255)
.Left = Cht_Sht.PlotArea.InsideLeft - Cht_Sht.Axes(xlValue).Format.Line.Weight
.Top = Cht_Sht.PlotArea.InsideTop
End With
End Sub

Related

PowerPoint O365 - v16 Prevent Screen Updating

I am creating shapes on a PowerPoint slide from Excel but it is incredibly slow because each shape is drawn and the screen is updating very slowly. I'm using office 365.
I have seen various posts pointing to the link below - but it appears to be for older versions. Even adding in another line for version 16 isn't doing anything
Case "16"
hWnd = FindWindow("PPTFrameClass", 0&)
PowerPoint VBA Equivalent of Application.ScreenUpdating
Has anyone managed to get this working so I can run Excel VBA, updating PowerPoint without any screen flicker and fast speeds.
Hope there is a solution to this.
Edit: Here is some sample code to run that shows the sort of thing I'm doing. Just need to add reference to Microsoft PowerPoint 16.0 Object Library
Option Explicit
Public PPT As PowerPoint.Application
Public PRES As PowerPoint.presentation
Public SLIDE As PowerPoint.SLIDE
Public CANV As PowerPoint.Shape
Public SHP As PowerPoint.Shape
Sub OpenPowerPoint()
Set PPT = CreateObject("Powerpoint.Application")
Set PRES = PPT.Presentations.Add
PPT.Visible = True
Set SLIDE = PRES.Slides.Add(PPT.ActivePresentation.Slides.Count + 1, ppLayoutText)
End Sub
Sub CreatePPTShapes()
If PRES Is Nothing Then OpenPowerPoint
Dim l As Long, t As Long, w As Long, h As Long, x As Long
Dim size As Long, m As Long, nm As String
Dim startDate As Long
startDate = DateSerial(2021, 4, 1)
l = 5
t = 70
w = PRES.PageSetup.SlideWidth - 10
h = PRES.PageSetup.SlideHeight - 75
Set CANV = SLIDE.Shapes.AddShape(msoShapeRectangle, l, t, w, h)
With CANV
.Name = "ta_canvas"
With .Fill
.Visible = msoTrue
.ForeColor.RGB = RGB(240, 240, 240)
.Transparency = 0
.Solid
End With
With .Line
.Visible = msoTrue
.ForeColor.RGB = RGB(0, 0, 0)
.Transparency = 0.5
.Weight = 0.25
End With
End With
t = t + 5
w = (w) / 12
h = 20
For x = 0 To 2
For m = 0 To 11
nm = MonthName(Month(DateAdd("m", m, startDate)), True)
t = 70 + 7 + (x * 25)
l = 10 + (w * m)
Dim newPos As Long
Set SHP = SLIDE.Shapes.AddShape(msoShapeRoundedRectangle, l, t, w, h)
With SHP
.Name = "ta_" & nm
.Adjustments(1) = 0.25
.Line.Visible = msoFalse
.Fill.Visible = True
.Fill.ForeColor.RGB = RGB(0, 0, 0)
With .TextFrame2
.TextRange.Characters.Text = nm
.MarginLeft = 2.8346456693
.MarginRight = 2.8346456693
.MarginTop = 0
.MarginBottom = 0
.WordWrap = msoFalse
.AutoSize = msoAutoSizeShapeToFitText
With .TextRange.ParagraphFormat
.FirstLineIndent = 0
.Alignment = msoAlignCenter
End With
.VerticalAnchor = msoAnchorMiddle
With .TextRange.Font
.size = 12
With .Fill
.Visible = msoTrue
.ForeColor.RGB = RGB(255, 255, 255)
End With
End With
End With
End With
Next m
Next x
End Sub
I've found that if I switch the view in code to the handout master then the code runs much much quicker. It looks like the screen updating is suspended.
ppt.activewindow.viewtype = ppviewhandoutmaster
then switch it back at the end to ppViewNormal or whichever your preferred default view.

Excel VBA - Copy pictures from on sheet to another in specified location

I'be built a code for a calendar-type plan with textboxes and pictures. I've managed to make a code so the shapes are all placed on the right spot. However, I'm struggling to copy some pictures from one sheet to another.
Sub AddEvent2()
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Application.EnableEvents = False
Dim i As Integer, shp As Shape, s, s2, v, t1, t2, t3, h, p, w, rgb1, rgbULP, rgbPULP, rgbSPULP, rgbXLSD, rgbALPINE, rgbJET, rgbSLOPS As String
For Each shp In Sheets("Calendar").Shapes
shp.Delete
Next shp
For i = 4 To 21
t1 = Sheets("AdminSheet").Cells(i, 30).Value 'Cell location on Calendar
s = Sheets("AdminSheet").Cells(i, 29).Value 'Naming the shapebox
w = Sheets("AdminSheet").Cells(i, 28).Value 'Supplier
p = Sheets("AdminSheet").Cells(i, 27).Value 'Product
t2 = Sheets("AdminSheet").Cells(i - 1, 30).Value 'Next Cell location on Calendar
v = Application.WorksheetFunction.Text(Sheets("AdminSheet").Cells(i, 24).Value, "hh:mm") & " " & _
Sheets("AdminSheet").Cells(i, 25).Value & Sheets("AdminSheet").Cells(i, 26).Value & " " & Sheets("AdminSheet").Cells(i, 27).Value 'Text in shapebox
rgbULP = rgb(177, 160, 199)
rgbPULP = rgb(255, 192, 0)
rgbSPULP = rgb(0, 112, 192)
rgbXLSD = rgb(196, 189, 151)
rgbALPINE = rgb(196, 215, 155)
rgbJET = rgb(255, 255, 255)
rgbSLOPS = rgb(255, 0, 0)
If s <> "" Then
Sheets("Calendar").Select
If i > 4 And t2 = t1 Then
s2 = Sheets("AdminSheet").Cells(i - 1, 29).Value 'Name of the added shapebox
h = Sheets("Calendar").Shapes.Range(Array(s2)).Height 'Height of the added shapebox
t3 = Sheets("Calendar").Shapes.Range(Array(s2)).Top 'Top of the added shapebox
ActiveSheet.Shapes.AddTextbox(msoTextOrientationHorizontal, Sheets("Calendar").Range(t1).Left + 1.5, 3 + t3 + h, 209, 36.6).Select
Else
ActiveSheet.Shapes.AddTextbox(msoTextOrientationHorizontal, Sheets("Calendar").Range(t1).Left + 1.5, Sheets("Calendar").Range(t1).Top + 3, 209, 36.6).Select
End If
With Selection
.Name = s
With .ShapeRange
.IncrementLeft 0
.IncrementTop 0
With .Fill
.Visible = msoTrue
If p = "ULP" Then
.ForeColor.rgb = rgbULP
ElseIf p = "PULP" Then
.ForeColor.rgb = rgbPULP
ElseIf p = "SPULP" Then
.ForeColor.rgb = rgbSPULP
ElseIf p = "XLSD" Then
.ForeColor.rgb = rgbXLSD
ElseIf p = "ALPINE" Then
.ForeColor.rgb = rgbALPINE
ElseIf p = "JET" Then
.ForeColor.rgb = rgbJET
ElseIf p = "SLOPS" Then
.ForeColor.rgb = rgbSLOPS
End If
.Transparency = 0
.Solid
End With
With .TextFrame2
.MarginLeft = 5.7
.MarginRight = 38.6
.AutoSize = msoAutoSizeShapeToFitText
With .TextRange.Font
.NameComplexScript = "Lucida Console"
.NameFarEast = "Lucida Console"
.Name = "Lucida Console"
.Size = 14
End With
.TextRange.Characters.Text = v
End With
End With
End With
Sheets("AdminSheet").Select
ActiveSheet.Shapes.Range(Array(w)).Select
Selection.Copy
Sheets("Calendar").Select
ActiveSheet.Paste
Selection.ShapeRange.Name = w & s
Selection.Name = w & s
Sheets("Calendar").Shapes(w & s).Top = Sheets("Calendar").Shapes(s).Top + (Sheets("Calendar").Shapes(s).Height / 2) - (Sheets("Calendar").Shapes(w & s).Height / 2)
Sheets("Calendar").Shapes(w & s).Left = Sheets("Calendar").Shapes(s).Left + Sheets("Calendar").Shapes(s).Width - Sheets("Calendar").Shapes(w & s).Width
End If
Next i
Application.Calculation = xlCalculationAutomatic
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
As you can see I'm very new to coding... Anyway, what I'm trying to do is to copy a pic named after "w" and paste it to the right side of the added Textbox (within the box - I guess the location would be textbox.left + textbox.width - pic.width but it doesn't work). I've tried recording it but it doesn't work for me. Any ideas?
*Edit - I updated the with the code I use for that task and the error I get. The location is wrong as well - they go outside the textbox...
I also struggle to understand how to change the fillcolor.RGB of the shape dynamically. I made it work with "if" statement but looks ugly. Any ideas how to sort the code there? Why .ForeColor.RGB = "rgb" & p not working?
Thanks in advance
I found the problem.
On the initial code, the name of the picture I was copying was not changing, hence not unique on the Sheet. So, when I was tying to move the Shape("example"), I was moving all with the same name.
Anyway, code updated with name change variable!

Suggestions for codes format to set the chart coordinates,title and added text in excel macro

Wrote a macro to draw line with markers plot with excel, it works well in a single macro xlsm file. But when I tried to convert it to a excel addin (xlam file) , it got a lot of bugs. All the bugs are related to the format of both X and Y coordinates, position, font type and size of chart title, and position, font type and sizeof added text. Not sure what is the reason, need to know the correct format of them. Any debug suggestions or help, really appreciated. Please see the error message and my full macro codes as the following. Thanks.
The error message is run time error '-21474627161 (800004003)': the object is no longer valid.
After you clicked the debug, the code " .left=358" was highlighted with yellow.
But you checked with excel, the plot was drawn without chart title and the add text (that I want) and the format of coordinate was not that I tried to set. Again all these errors only happen with the xlam file, the macro works well with xlms fie.
Sub strain_plot()
sh_rows = ActiveWorkbook.ActiveSheet.Range("B65535").End(xlUp).Row
For i = 1 To sh_rows
If ActiveSheet.Cells(i, 1).Value < 0.000001 Then
ActiveSheet.Cells(i, 1).Value = 1000000000# * ActiveSheet.Cells(i, 1).Value
End If
Next i
ii = sh_rows
c_name = "chart1"
On Error GoTo err:
ActiveWorkbook.ActiveSheet.ChartObjects(c_name).Delete
err:
Set ch = ActiveWorkbook.ActiveSheet.ChartObjects.Add(330, 120, 480, 270) 'set graph position and size
ch.Name = c_name
With ch.Chart
For iii = 1 To 2
.SeriesCollection.NewSeries
.SeriesCollection(iii).Values = Range(ActiveWorkbook.ActiveSheet.Cells(1, iii + 1), ActiveWorkbook.ActiveSheet.Cells(ii, iii + 1))
.SeriesCollection(iii).XValues = Range(ActiveWorkbook.ActiveSheet.Cells(1, 1), ActiveWorkbook.ActiveSheet.Cells(ii, 1))
.SeriesCollection(iii).ChartType = xlLineMarkers
Next iii
.SeriesCollection(1).Name = "[110]"
.SeriesCollection(1).MarkerStyle = 2
.SeriesCollection(1).MarkerSize = 12
.SeriesCollection(1).MarkerForegroundColor = RGB(255, 0, 0)
.SeriesCollection(1).MarkerBackgroundColor = RGB(255, 0, 0)
.SeriesCollection(1).Format.Fill.ForeColor.RGB = RGB(255, 0, 0)
.SeriesCollection(2).Name = "[001]"
.SeriesCollection(2).MarkerStyle = 2
.SeriesCollection(2).MarkerSize = 12
.SeriesCollection(2).MarkerForegroundColor = RGB(96, 96, 96)
.SeriesCollection(2).MarkerBackgroundColor = RGB(96, 96, 96)
.SeriesCollection(2).Format.Fill.ForeColor.RGB = RGB(96, 96, 96)
With .Legend
.IncludeInLayout = False
.Position = xlLegendPositionRight
.AutoScaleFont = False
.Font.Size = 14
.Top = 25
.Left = 392
.Width = 72
.Height = 40
End With
With .ChartArea.Fill
.Visible = msoTrue
.ForeColor.SchemeColor = 33
.Solid
End With
With .SeriesCollection(1).Format.Line
.Visible = msoTrue
.ForeColor.RGB = RGB(255, 0, 0) 'red
.Transparency = 0
End With
With .SeriesCollection(2).Format.Line
.Visible = msoTrue
.ForeColor.RGB = RGB(96, 96, 96) 'grey
.Transparency = 0
End With
.HasTitle = True
With .ChartTitle
.Text = ActiveWorkbook.ActiveSheet.Cells(5, 8)
.Left = 358
.Top = 236
With .Font
.Name = "Tahoma"
.Size = 10
End With
End With
With .Axes(xlCategory)
.HasTitle = True
.AxisTitle.Text = "Position(nm)" 'X-axis title
.TickLabels.Font.Size = 10 'X-axis coordinate number size
.AxisTitle.Font.Size = 14 'X-axis title word font size
.TickMarkSpacing = 3
.TickLabelSpacing = 5
.TickLabels.NumberFormatLocal = "#,##0._);[red](#,##0.)"
.TickLabels.NumberFormatLocal = "#,##0_);[red](#,##0)"
.TickLabels.NumberFormatLocal = "0_);[red](0.)"
End With
With .Axes(xlValue)
.HasTitle = True
.AxisTitle.Text = "Strain" 'Y-aixs title
.AxisTitle.Font.Size = 14 'y-axis title word font size
'Minimum value of Y axis
.Axes(xlValue).MinimumScale = -0.005
.Axes(xlValue).TickLabels.NumberFormatLocal = "0.0%"
End With
End With
Dim thechartobj As ChartObject
Set thechartobj = ActiveWorkbook.ActiveSheet.ChartObjects(ch.Name)
Dim thechart As Chart
Set thechart = thechartobj.Chart
Dim thetextbox As Shape
Set thetextbox = thechart.Shapes.AddTextbox(msoTextOrientationHorizontal, 688, 372, 122, 20)
With thetextbox.TextFrame.Characters
.Text = ActiveSheet.Cells(6, 8)
With .Font
.Name = "tahoma"
.Size = 10
.Bold = msoTrue
End With
End With
End Sub

Changing colour of a chart series based on conditions using vba

I am trying to code using vba so that a series on a chart is formatted based on certain criteria. My coding is as follows
Sub CreateChart()
Dim NPOINTS As Integer
Dim NVAL(1000) As Range, XVAL(1000) As Range, YVAL(1000) As Range
Dim Score(1000) As Range
Sheets("Scenario").Select
Range("B4").Select
NPOINTS = Worksheets("Scenario").Range(Selection, Selection.End(xlDown)).Rows.Count
Set Scenario = Worksheets("Scenario")
ActiveSheet.Shapes.AddChart2(240, xlXYScatter).Select
NVAL0 = "B3"
XVAL0 = "C3"
YVAL0 = "D3"
SCORE0 = "E3"
For i = 1 To NPOINTS
Set Score(i) = Cells(Range(SCORE0).Offset(i, 0).Row, Range(SCORE0).Column)
Set NVAL(i) = Cells(Range(NVAL0).Offset(i, 0).Row, Range(NVAL0).Column)
Set XVAL(i) = Cells(Range(XVAL0).Offset(i, 0).Row, Range(XVAL0).Column)
Set YVAL(i) = Cells(Range(YVAL0).Offset(i, 0).Row, Range(YVAL0).Column)
Scorei = Score(i).Value
ActiveChart.SeriesCollection.NewSeries
ActiveChart.FullSeriesCollection(i).Name = NVAL(i)
ActiveChart.FullSeriesCollection(i).XValues = XVAL(i)
ActiveChart.FullSeriesCollection(i).Values = YVAL(i)
If Scorei <= 10 >= 0 Then
ActiveChart.SeriesCollection(i).Points.Interior.Colour = _
RGB(0, 255, 0) 'Green
ElseIf Scorei <= 30 >= 11 Then
ActiveChart.SeriesCollection(i).Points.Interior.Colour = _
RGB(0, 255, 0) 'Green
ElseIf Scorei <= 60 >= 31 Then
ActiveChart.SeriesCollection(i).Points.Interior.Colour = _
RGB(0, 255, 0) 'Green
ElseIf Scorei <= 100 >= 61 Then
ActiveChart.SeriesCollection(i).Points.Interior.Colour = _
RGB(0, 255, 0) 'Green
Else
MsgBox "ERROR :- Score out of range"
End If
Next
With ActiveChart
'chart name
.HasTitle = False
'X axis name
.Axes(xlCategory, xlPrimary).HasTitle = True
.Axes(xlCategory, xlPrimary).AxisTitle.Characters.Text = "INFLUENCE"
'y-axis name
.Axes(xlValue, xlPrimary).HasTitle = True
.Axes(xlValue, xlPrimary).AxisTitle.Characters.Text = "IMPORTANCE"
.SetElement (msoElementLegendRight)
.Location Where:=xlLocationAsNewSheet, Name:="Priority Chart"
End With
End Sub
Unfortunately when I run it, it fails with "Object doesn't support this property or method and then when I press Debug it highlights the following line
ActiveChart.SeriesCollection(i).Points.Interior.Colour = _
RGB(0, 255, 0) 'Green
Where am I going wrong?
I appreciate any help.
just
ActiveChart.SeriesCollection(i).format.Fill.ForeColor.RGB =RGB(0, 255, 0)
The .Points() is a collection.
You will need to cycle through all its elements and change the color one by one.
The left most point is .Points(1), the right most point is .Points.count
as per: Change the Point Color in chart excel VBA
Also there is no such thing as interior colour for points.
There are 4 relevant options as per: https://msdn.microsoft.com/en-us/vba/excel-vba/articles/point-object-excel
MarkerBackgroundColor
MarkerBackgroundColorIndex
MarkerForegroundColor
MarkerForegroundColorIndex
As per comment from Jon Peltier it is not recommended to make use of the colorindex as this is a legacy from excel <2003

VBA - Write values inside bar chart

So I've this chart that is made trought VBA
And now i want to put the data inside bars, so it will look like this:
Can you help?
The code that i've to get to this chart is:
Set rng = ActiveSheet.Range("A" & x & ":C" & (x + 4))
' in brackets (Left, Top, Widht, Height) >> modify according to your needs
Set cht = ActiveSheet.ChartObjects.Add(550, 100 * (i - 4), 300, 100)
With cht
.Chart.SetSourceData Source:=rng
.Chart.PlotBy = xlColumns
.Chart.ChartType = xlBarStacked
.Chart.HasAxis(xlValue) = False
.Chart.HasLegend = False
.Chart.HasTitle = True
.Chart.ChartTitle.Text = Application.Sheets(i).Name
.Chart.ChartTitle.Font.Size = 10
.Chart.Axes(xlValue).HasMajorGridlines = False
.Chart.Parent.Name = Application.Sheets(i).Name
End With
cht.Activate
ActiveChart.ChartGroups(1).GapWidth = 10
With ActiveChart.Axes(xlCategory).TickLabels.Font
.Bold = msoFalse
.Size = 8
End With
Set cht_Series = cht.Chart.SeriesCollection(1)
cht_Series.Format.Fill.ForeColor.RGB = RGB(255, 255, 255)
Set cht_Series = cht.Chart.SeriesCollection(2)
cht_Series.Format.Fill.ForeColor.RGB = RGB(134, 188, 37)
Thanks!
To get what you want, you would need to add this line at the end of your code:
ActiveChart.SeriesCollection(2).HasDataLabels = True
Since you have defined a seriescollection object, this would also work:
cht_Series.HasDataLabels = True
You need to set series.HasDataLabels = true and series.datalabels.Position = xlLabelPositionCenter (or very similar, can't check with Excel).

Resources