Right now I have the following code to display a line curve. The number of inputs can vary and I want the chart to clear and draw a new line curve every time the macro is run.
Sub addchart()
If ActiveSheet.ChartObjects.Count > 0 Then
ActiveSheet.ChartObjects.Delete
End If
Dim ws As Worksheet
Dim ch As chart
Dim ch1 As chart
Dim dt As Range
Dim i As Integer
i = Cells(Rows.Count, "I").End(xlUp).Row
Set ws = ActiveSheet
Set dt = Range(Cells(2, 10), Cells(i, 10))
Set ch = ws.Shapes.AddChart2(Width:=1300, Height:=300, Left:=Range("a13").Left, Top:=Range("a13").Top).chart
With ch
.SetSourceData Source:=dt
.ChartTitle.Text = "Deflection Curve"
.ChartType = xlLine
.SeriesCollection(1).Name = "Deflection"
End With
If Application.WorksheetFunction.Min(dt) > -50 Then
With ch.Axes(xlValue)
.MinimumScale = -50
.MaximumScale = 0
End With
End If
End Sub
The chart that is printed looks something like this
I'm trying to figure out how to add labels to arbitrary points to the chart. Two labels to be specific. One is at the minimum value. And one is the value at any arbitrary point on x-axis. Both x-values are known and will be taken as inputs from two cells on the sheet. Something like this.
The style of highlighting is unimportant. Thanks for the help!
P.S. - I'm new to VBA and I'm learning everything on the go. I look up what I need to do and then try and imitate whatever examples I see online. So it's possible the existing program I've written for the chart might have unnecessary steps or is inefficient in some way. I would appreciate it if someone had any tips to offer to improve it, even though it does the job. Thanks!
Try those for first steps making chart labels:
Dim chartname as string
chartname = "enter_a_name"
ActiveSheet.Shapes.AddChart2(227, xlLine).Name = chartname
With ActiveSheet.Shapes(chartname).Line
.Visible = msoTrue
.ForeColor.RGB = RGB(0, 0, 0)
.Transparency = 0
.Weight = 1.5
End With
Set my_chart = ActiveSheet.ChartObjects(chartname).Chart
'Delete all Autolabels
my_chart.SetElement (msoElementDataLabelNone)
'Enter format of axis (just if you want to)
'With my_chart.Axes(xlCategory) ' axis adjustment
'.CategoryType = xlCategoryScale ' not XlCategoryType.xlAutomaticScale | XlCategoryType.xlTimeScale
'.TickLabels.NumberFormat = "DD.MM.YYYY hh:mm"
'.TickLabels.Orientation = xlUpward
'End With
cols = Array("F", "L") ' columns containing labels
For j = 1 To my_chart.SeriesCollection.Count
Set sc = my_chart.SeriesCollection(j)
For i = 2 To sc.Points.Count
sc.Points(i).ApplyDataLabels
sc.Points(i).DataLabel.Text = Range(cols(j - 1) & i + x).Value ' x= starting row containing values /labels
Next i
Sub addchart()
If ActiveSheet.ChartObjects.Count > 0 Then
ActiveSheet.ChartObjects.Delete
End If
Dim ws As Worksheet
Dim ch As Chart
Dim dt As Range
Dim i As Integer
i = Cells(Rows.Count, "I").End(xlUp).Row
Set ws = ActiveSheet
Set dt = Range(Cells(2, 10), Cells(i, 11)) ' Added another column with the relevant values to highlight line chart
Set ch = ws.Shapes.AddChart2(Width:=1300, Height:=300, Left:=Range("a13").Left, Top:=Range("a13").Top).Chart
With ch
.SetSourceData Source:=dt
.ChartTitle.Text = "Deflection Curve"
.FullSeriesCollection(1).ChartType = xlLine
.SeriesCollection(1).Name = "Deflection"
.SeriesCollection(2).ChartType = xlColumnStacked 'the second column shows up as a bar chart along with the line chart
End With
If Application.WorksheetFunction.Min(Range(Cells(2, 10), Cells(i, 10))) > -30 Then
With ch.Axes(xlValue)
.MinimumScale = -30
.MaximumScale = 0
End With
End If
End Sub
Related
Good morning.
I created a VB.NET application for Energy Measurement. All is OK, only one thing is a problem. In app, is code to create an excel table and also a chart. Table and chart are generated right, but series names in the chart are with default series names (e.g.: Series1, Series2... etc.). Only the last series has the right name what I set in code (I set all, but they are changed).
My code for the chart is:
Private Sub AddChart(Row As Integer, Columns As Integer)
xlWorkSheet = xlWorkBook.Sheets(2)
xlCharts = xlWorkSheet.ChartObjects
myChart = xlCharts.Add(0, 0, 1000, 500)
EnergyChart = myChart.Chart
xlWorkSheet = xlWorkBook.Sheets(1)
For i As Integer = 1 To Columns - 1
ColValue = ConvertNumberToString(i + 1)
SeriesName(i) = xlWorkSheet.Range(ColValue & "3").Value
chartRange = xlWorkSheet.Range("A4", ColValue & Row - 1)
EnergyChart.SetSourceData(Source:=chartRange)
Series = CType(EnergyChart.SeriesCollection(i), Excel.Series)
Series.Name = SeriesName(i)
Next
With EnergyChart
.HasTitle = True
.ChartTitle.Font.Color = Color.SeaGreen
.ChartTitle.Font.Size = 11
.ChartTitle.Font.Name = "Calibri"
.ChartTitle.Text = ReportFileName
.ChartType = Excel.XlChartType.xlLine
End With
End Sub
Could you please someone tell me why series names are changed to default? Thank you all.
SOLVED:
After code modification it's working right.
Private Sub AddChart(Row As Integer, Columns As Integer)
xlWorkSheet = xlWorkBook.Sheets(2)
xlCharts = xlWorkSheet.ChartObjects
myChart = xlCharts.Add(0, 0, 1000, 500)
EnergyChart = myChart.Chart
xlWorkSheet = xlWorkBook.Sheets(1)
For i As Integer = 1 To Columns - 1
ColValue = ConvertNumberToString(i + 1)
chartRange = xlWorkSheet.Range("A3", ColValue & Row - 1)
EnergyChart.SetSourceData(chartRange)
Series = CType(EnergyChart.SeriesCollection(1), Excel.Series)
Next
With EnergyChart
.HasTitle = True
.ChartTitle.Font.Color = Color.SeaGreen
.ChartTitle.Font.Size = 11
.ChartTitle.Font.Name = "Calibri"
.ChartTitle.Text = ReportFileName
.ChartType = Excel.XlChartType.xlLine
End With
End Sub
Chart OK
I have a worksheet with about 30 charts I want to update dynamically with a VBA macro. I have some issues in handling the series, but I can't find out what's wrong.
The code should run through several charts (only 3 in the following code), clear old contents, and add 6 new series with data taken from the spreadsheet. On the contrary, it doesn't delete the old series and, at each run, adds them again with a new one, then quits with a "Parameter not valid" error on line 22. I have been struggling on this for a couple of weeks now, and the most frustrating part is that the code is basically a copy+paste from another project, which works fine.
Here's the code:
Public Sub Refresh_NB_Graphs()
Dim cht As Chart
Dim chtObj As ChartObject
Dim vi As Integer
Dim s As Object
Dim j As Integer
Dim k As Integer
Dim seriesIndex As Integer
Dim xRange As Range
Dim yRange As Range
'Application.ScreenUpdating = False
On Error GoTo Errorcatch
'Graph fetching and update cycle
For vi = 1 To 3
Set chtObj = Sh_NBGain.ChartObjects("Ch_Gain_Vs" & CStr(vi))
Set cht = chtObj.Chart
' Adding or removing this section makes no difference -------
For Each s In cht.SeriesCollection
s.Delete
Next s
' -----------------------------------------------------------
cht.ChartArea.ClearContents
'Format Font Type and Size
cht.ChartType = xlXYScatterLinesNoMarkers ' scatter plot
cht.ChartArea.Format.TextFrame2.TextRange.Font.Name = "Arial"
cht.ChartArea.Format.TextFrame2.TextRange.Font.Size = 14
cht.HasTitle = False ' No chart title
' Add series: data origin in Sh_NBGainProcess
seriesIndex = 0
For j = 0 To 5
seriesIndex = seriesIndex + 1
cht.SeriesCollection.NewSeries
1 cht.SeriesCollection(seriesIndex).Name = CStr(Sh_Vars.Range("A8").Offset(j, 0).Value)
Set xRange = Sh_NBGainProcess.Range("C42:C1642").Offset(1600 * (vi - 1), 20 * j)
Set yRange = Sh_NBGainProcess.Range("D42:D1642").Offset(1600 * (vi - 1), 20 * j)
10 cht.SeriesCollection(seriesIndex).XValues = "='" & Sh_NBGainProcess.Name & "'!" & xRange.Address
20 cht.SeriesCollection(seriesIndex).Values = "='" & Sh_NBGainProcess.Name & "'!" & yRange.Address
22 With cht.SeriesCollection(seriesIndex)
23 Debug.Print seriesIndex
30 .Format.Line.Weight = 2.25
40 .Format.Line.Visible = msoTrue
50 .Format.Line.ForeColor.RGB = ECOPalette(j) ' Array with defined colors
60 .MarkerStyle = xlMarkerStyleNone
End With
Next j
'.....................
Next vi
End Sub
Can anybody help?
Thanks!
Had to rework the code a bit, but now it's fine:
Dim cht As Chart
Dim s As Series
Dim vi As Integer
Dim j As Integer
Dim xRange As Range
Dim yRange As Range
'Application.ScreenUpdating = False
On Error GoTo Errorcatch
'Graph fetching and update cycle
For vi = 1 To 3
' Gain charts (Vs 1 to 3) ***********************************************************************************************************
Set cht = Sh_NBGain.ChartObjects("Ch_Gain_Vs" & CStr(vi)).Chart
' Clear existing data
For Each s In cht.SeriesCollection
s.Delete
Next s
cht.ChartArea.ClearContents
cht.ChartType = xlXYScatterLinesNoMarkers ' scatter plot
' Add series: data origin in Sh_NBGainProcess
For j = 0 To 5
If Not Sh_NBGainProcess.Range("C42").Offset(1601 * (vi - 1), 20 * j).Value = "" Then
10 Set s = cht.SeriesCollection.NewSeries
40 s.Name = CStr(Sh_Vars.Range("A8").Offset(j, 0).Value)
50 Set xRange = Sh_NBGainProcess.Range("C42:C1642").Offset(1601 * (vi - 1), 20 * j)
60 Set yRange = Sh_NBGainProcess.Range("D42:D1642").Offset(1601 * (vi - 1), 20 * j)
90 s.XValues = "='" & Sh_NBGainProcess.Name & "'!" & xRange.Address
100 s.Values = "='" & Sh_NBGainProcess.Name & "'!" & yRange.Address
110 With s
130 .Format.Line.Weight = 2.25
140 .Format.Line.Visible = msoTrue
150 .Format.Line.ForeColor.RGB = ECOPalette(j)
160 .MarkerStyle = xlMarkerStyleNone
End With
End If
Next j
I think that the main issue was due to the use of the series collection indexing, which was somehow misbehaving (I still don't understand why). By referring directly to the series object when created, with Set s = cht.SeriesCollection.NewSeries, things go fine.
I have created a chart using vba excel, then accidentally populate a graph that show the user and the counts which I prefer. But stupid of me I forgot to save, due to testing. Now I cant get the logic how to set it again. please help, thanks
Sample Data
Operator Counts Team
OPSHAF 123 A
OPSAJC 1245 B
OPSZAL 23 A
OPSJGY 162 C
OPSOSM 54 D
Sub CreateChart()
Dim rEmailRng As Range
Dim oEmailCht As Object
Dim cEmailCht As Chart
Dim coEmailCht As ChartObject
Dim iEmailRow As Integer
Dim sEmailSeries As Series
Dim scEmailSerCol As SeriesCollection
On Error Resume Next
Set wb = ThisWorkbook
Set wbsh2 = wb.Worksheets("Email")
Set coEmailCht = wbsh2.ChartObjects.Add(Range("E5").Left, Range("E5").Top, 500, 300)
coEmailCht = "Email Requests Processed" '& year
Set cEmailCht = coEmailCht.Chart
With cEmailCht
.HasLegend = False
.HasTitle = True
.Axes(xlValue).MinimumScale = 50
.Axes(xlValue).MaximumScale = 1500
.ChartTitle.Text = "Email Processed by Operator"
Set scEmailSerCol = .SeriesCollection
Set sEmailSeries = scEmailSerCol.NewSeries
With sEmailSeries
.Name = Range("A1").Offset(0, 1).Value
.XValues = Range(Range("A1").Offset(1, 0), Range("A1").End(xlDown))
.Values = Range(Range("A1").Offset(1, 1), Range("A1").Offset(1, 1).End(xlDown))
.ChartType = xl3DColumnClustered
End With
End With
Welcome To SO. If Your Objective is that axis label contain Count along with Operator then simply try
With sEmailSeries
'
.XValues = Range("A2:B" & Range("B2").End(xlDown).Row)
if you want team name also then
.XValues = Range("A2:C" & Range("C2").End(xlDown).Row)
I have a chart that is composed of two main things.
The first is a loop that creates a bunch of series based on values. Each of these series is an XY Scatter with Lines. Each of these Lines is coloured based on conditions using the Vlookup function in Excel. The first thing I need to correct is the Case part because it doesn't like the first instance of G. This only occurs when I have added the second chart.
The next thing I want is to create an XY Scatter with another Range, then apply Custom Data Labels to only those points. I can change the type of Chart the Series plots by using the answer below, which has been updated.
Dim age1 As Variant
Dim age2 As Variant
Dim per1 As Variant
Dim per2 As Variant
Dim id as Variant
Dim mp as Range
Dim yd as Range
id = Range(Range("A2"), Range("A2").End(xlDown)).Value2
age1 = Range(Range("C2"), Range("C2").End(xlDown)).Value2
age2 = Range(Range("D2"), Range("D2").End(xlDown)).Value2
per1 = Range(Range("E2"), Range("E2").End(xlDown)).Value2
per2 = Range(Range("E2"), Range("E2").End(xlDown)).Value2
Set mp = Range(Range("J2"), Range("J2").End(xlDown))
Set yd= Range(Range("E2"), Range("E2").End(xlDown))
ln = UBound(id) - LBound(id) + 1
Set cht = ws.ChartObjects(1).Chart
With cht
.ChartArea.ClearContents 'Clears the chart so a new one can be created
.ChartType = xlXYScatterLines 'Defines the Chart as a Scatter with Lines
For i = 1 To ln 'First Thing that creates many series
xdata = Array(age1(i, 1), age2(i, 1))
ydata = Array(per1(i, 1), per2(i, 1))
.SeriesCollection.NewSeries
.SeriesCollection(i).XValues = xdata
.SeriesCollection(i).Values = ydata
.SeriesCollection(i).Name = id(i, 1)
Next i
'Orginal method: .ChartType = xlXYScatter
.SeriesCollection.NewSeries
.SeriesCollection(.SeriesCollection.Count).XValues = mp
.SeriesCollection(.SeriesCollection.Count).Values = yd
.SeriesCollection(.SeriesCollection.Count).Name = "Series"
'New Method
.SeriesCollection(.SeriesCollection.Count).ChartType = xlXYScatter
End With
'end of creating charts
Set drng = Range(Range("A2"), Range("B2").End(xlDown) 'For the Vlookup
With ActiveSheet
For Each xycht In .ChartObjects
For Each mysrs In xycht.Chart.SeriesCollection
mysrs.MarkerStyle = xlMarkerStyleCircle
lnum = Application.VLookup(mysrs.Name, drng, 2, 0) 'This fails the first instance with G as a Type Mismatch Error.
' Select Case lnum
' Case "G"
' lColor = RGB(255, 0, 0)
' Case "D"
' lColor = RGB(0, 255, 0)
' Case "M"
' lColor = RGB(0, 0, 255)
' Case "A"
' lColor = RGB(0, 0, 0)
' Case Else
' lColor = RGB(255, 255, 255)
' End Select
' mysrs.MarkerBackgroundColor = lColor
' mysrs.Format.Line.Visible = msoFalse
' mysrs.Format.Line.Visible = msoTrue
' mysrs.Format.Line.ForeColor.RGB = lColor
Next
Set mypts = ws.ChartObjects(1).SeriesCollection(SeriesCollection.Count).Points(1).Apply 'This fails cause it needs an Object
mypts(mypts.Count).ApplyDataLabels
With mypts(mypts.Count).DataLabel
.ShowSeriesName = False
.ShowCategoryName = False
.ShowValue = False 'I need this tonot show Values, but my own Values.
' optional parameters
.Position = xlLabelPositionAbove
.Font.Name = "Helvetica"
.Font.Size = 10
.Font.Bold = False
End With
Next
End With
Use the ChartType property of the Series object...
.SeriesCollection(.SeriesCollection.Count).ChartType = xlXYScatter
I am in the middle of a problem: I need to use the combobox value as I key to search a data in other plan and when I find the same value, capture some some cells values in the same row and plot this. Could someone help me? I believe that my great problem is create some loop with charts, because I need to verify if this value is greater than 0.01 to capture it.
Attempts so far:
Private Sub ComboBox1_Click()
x = 751
y = 1
If Sheets("Data").Cells(x, 7).Value = Me.ComboBox1.Value Then
Sheets("AnĂ¡lises").ChartObjects("Chart 3").Activate
ChartObjects("Chart 3").SeriesCollection.NewSeries
ChartObjects("Chart 3").SeriesCollection(1).Name = Sheets("Data").Cells(x, 7).Value
If Sheets("Data").Cells(x, 7 + y).Value > 0.01 Then
ActiveChart.SeriesCollection(1).Values = "=Data!$L$752,Data!$N$752,Data!$R$752,Data!$T$752"
ActiveChart.SeriesCollection(1).XValues = "=Data!$H$10"
ActiveChart.SeriesCollection(1).XValues = "=Data!$H$10,Data!$J$10,Data!$L$10,Data!$N$10"
End If
Else
x = x + 1
End If
End Sub
I know this dont make much sense. I performed a macro to see how works with charts, but I realized this way I am trying to do, wont work. Somehow I need to pick up as value for my chart some cells (they are not sequencial) which will depend from ComboBox1 choose.
I already found how I capture the range with a loop, just need to put in chart now:
Sub ComboBox1_Change()
Dim rng As Range
Dim x As Integer
Dim y As Integer
y = 8
For x = 751 To 1000 Step 1
If Me.ComboBox1.Value = Worksheets("Data").Cells(x, y - 1).Text Then
Set rng = Worksheets("Data").Cells(x, y)
Do Until y > 36
y = y + 2
Set rng = Application.Union(rng, Worksheets("Data").Cells(x, y))
Loop
rng.Copy
End If
Next x
End Sub
I believe that my great problem is create some loop with charts
Use appropriate object variables:
Dim cObj as ChartObject
Dim cht as Chart
Then loop using For/Next:
For each cObj in ...
Set cht = cObj.Chart '## Chart is child of ChartObject
Next
Like this, maybe (I am not sure where you need to loop or what other logic you may require):
Dim cObj As ChartObject
Dim cht As Chart
Dim srs As Series
Dim x as Long
Dim y as Long
x = 751
y = 1
If Sheets("Data").Cells(x, 7).Value = Me.ComboBox1.Value Then
For each cht in Sheets("AnĂ¡lises").ChartObjects
Set srs = cht.SeriesCollection.NewSeries
srs.Name = Sheets("Data").Cells(x, 7).Value
If Sheets("Data").Cells(x, 7 + y).Value > 0.01 Then
'## NOTE: I suspect these ranges also need to change for each chart
' That is going to be better suited for a SEPARATE question.
srs.Values = "=Data!$L$752,Data!$N$752,Data!$R$752,Data!$T$752"
srs.XValues = "=Data!$H$10"
srs.XValues = "=Data!$H$10,Data!$J$10,Data!$L$10,Data!$N$10"
End If
Next
Else
x = x + 1
End If