Use formulas to select chart data - excel

I have a large data table with a number of different measurements and parameters. I am trying to create a number of charts that organize the data series based on the parameters. For example, if I had data like this:
Xval Yval ParA ParB
22 5 10 0.25
27 7 10 0.5
26 6 20 0.25
25 8 20 0.5
I might want to create two charts - one that has a series for each value of ParA, and one that has a series for each value of ParB. What I want to do is be able to define the series data forumlaicly, saying something like (sudocode)
Series1x = Xval, IF(ParA==10)
Series1y = Yval, IF(ParA==10)
Series2x = Xval, IF(ParA==20)
Series2y = Yval, IF(ParA==20)
This way I can continue to sort however I like, and no change to the chart. I know that I can F9 the selected data to convert to raw numbers, but I would like to be able to reuse the series selection on multiple data sets.
Does anyone know if this is even possible in Excel?

Here is something to get you started. You will have to run the macro "UpdateChart" each time you sort/re-sort the data, but this seems to be working for me.
I create some Names in the macro, and then set the series Values & XValues to those ranges, although that would not strictly be necessary.
Sub UpdateChart()
Dim cht As Chart
Dim srs As Series
Dim s1xVals As Range
Dim s1Vals As Range
Dim s1Test As Double
Dim s2Test As Double
Dim nmAddress As String
Dim nm1 As Name
Dim nm2 As Name
Dim parAVals As Range
Set parAVals = GetRange("Define the ParA range?")
Set s1xVals = GetRange("X Values?")
Set s1Vals = GetRange("Y Values?")
s1Test = Application.InputBox("What filter value for ParA?", "Series 1 Filter")
s2Test = Application.InputBox("What filter value for ParA?", "Series 2 Filter")
'Get the address of all cells matching the filter rule for series 1.'
nmAddress = GetAddress(s1xVals, parAVals, s1Test)
'Add the name to the workbook:'
ActiveWorkbook.Names.Add Name:="Srs1_XValues", RefersTo:=Range(nmAddress), Visible:=True
'Repeat for the Y Values'
nmAddress = GetAddress(s1Vals, parAVals, s1Test)
ActiveWorkbook.Names.Add Name:="Srs1_YValues", RefersTo:=Range(nmAddress), Visible:=True
'Repeat for series 2:'
nmAddress = GetAddress(s1xVals, parAVals, s2Test)
ActiveWorkbook.Names.Add Name:="Srs2_XValues", RefersTo:=Range(nmAddress), Visible:=True
nmAddress = GetAddress(s1Vals, parAVals, s2Test)
ActiveWorkbook.Names.Add Name:="Srs2_YValues", RefersTo:=Range(nmAddress), Visible:=True
Set cht = ActiveSheet.ChartObjects(1).Chart '## Modify as needed.'
'remove any existing data in the chart, or modify as needed.'
For Each srs In cht.SeriesCollection
srs.Delete
Next
'Add the first series:'
Set srs = cht.SeriesCollection.NewSeries
srs.XValues = Range("srs1_XValues")
srs.Values = Range("srs1_YValues")
srs.Name = "Series 1 Name" '## modify as needed.'
'Add the second series:'
Set srs = cht.SeriesCollection.NewSeries
srs.XValues = Range("srs2_xValues")
srs.Values = Range("srs2_YValues")
srs.Name = "Series 2 Name" '## modify as needed.'
End Sub
Function GetAddress(srsVals As Range, filterVals As Range, filterCriteria As Double)
Dim cl As Range
Dim c As Long: c = 1
Dim tmpAddress As String
For Each cl In filterVals
If cl.Value = filterCriteria Then
Debug.Print srsVals.Cells(c).Value
'Create a string value of cell address matching criteria'
If tmpAddress = vbNullString Then
tmpAddress = srsVals.Cells(c).Address
Else:
tmpAddress = tmpAddress & "," & srsVals.Cells(c).Address
End If
End If
c = c + 1
Next
GetAddress = tmpAddress
End Function
Private Function GetRange(msg As String) As Range
Set GetRange = Application.InputBox(msg, Type:=8)
End Function
REVISION
The above method fails when returning string longer than 255 characters, not able to assign the address to a Name or to a series.
Here is a modified version that does not use Names, it merely collects the filtered scores in to an array, and uses those values to define the series.
Like the above solution, you would have to run it any time you change the data.
Sub UpdateChartNoNames()
Dim cht As Chart
Dim srs As Series
Dim s1xVals As Range
Dim s1Vals As Range
Dim s1Test As Double
Dim s2Test As Double
Dim parAVals As Range
Set parAVals = GetRange("Define the ParA range?")
Set s1xVals = GetRange("X Values?")
Set s1Vals = GetRange("Y Values?")
'## Alternatively, you could set these ranges without using the inputbox:'
'Set parAvals = Range("C2:C300") '
'Set s1XVals = Range("A2:A300") '
'Set s1Vals = Range("B2:B300") '
s1Test = Application.InputBox("What filter value for ParA?", "Series 1 Filter")
s2Test = Application.InputBox("What filter value for ParA?", "Series 2 Filter")
Set cht = ActiveSheet.ChartObjects(1).Chart '## Modify as needed.'
'remove any existing data in the chart, or modify as needed.'
For Each srs In cht.SeriesCollection
srs.Delete
Next
'Add the first series:'
Set srs = cht.SeriesCollection.NewSeries
srs.XValues = GetValues(s1xVals, parAVals, s1Test)
srs.Values = GetValues(s1Vals, parAVals, s1Test)
srs.Name = "Series 1 Name" '## modify as needed.'
'Add the second series:'
Set srs = cht.SeriesCollection.NewSeries
srs.XValues = GetValues(s1xVals, parAVals, s2Test)
srs.Values = GetValues(s1Vals, parAVals, s2Test)
srs.Name = "Series 2 Name" '## modify as needed.'
End Sub
Function GetValues(srsVals As Range, filterVals As Range, filterCriteria As Double) As Variant
Dim cl As Range
Dim c As Long: c = 0
Dim tmpVar As Variant
ReDim tmpVar(0)
For Each cl In filterVals
If cl.Value = filterCriteria Then
'Debug.Print srsVals.Cells(c).Value'
'Create a string value of cell address matching criteria'
ReDim Preserve tmpVar(c)
tmpVar(c) = srsVals.Cells(c).Value
c = c + 1
End If
Next
GetValues = tmpVar
End Function
Private Function GetRange(msg As String) As Range
Set GetRange = Application.InputBox(msg, Type:=8)
End Function

Related

How can I create a chart from unique values in a range

I have items that are being populated on a worksheet via userform. When I open the workbook I'm trying to get the tool to go to the sheet grab the data and generate a chart/dashboard on the main landing sheet.
In the range of data contains statuses. I want VBA to look through one column of data and create a chart that counts each different status and put that in a bar chart.
yaxis = the different statuses
xaxis = count
my code so far
Sub populatecharts()
Dim ws As Worksheet
Dim ch As Chart
Dim tablerng As Range
Dim rng1 As Range
Dim rng2 As Range
Dim rng3 As Range
Dim sh As String
Set ws = ActiveSheet
'When the workbook opens it should always check the data and populate the BA Dashboard
'I need to check for sheets and if they exist generate a chart from the data
sh = "Action"
On Error Resume Next
Worksheets("Action").Visible = True
If CheckSheetExist(sh) = False Then
GoTo nextchart1
Else
Worksheets(sh).Activate
'Set ws = ActiveSheet
Set rng1 = Range("G4", Range("G4", "G4").End(xlDown))
rng1.Select
'Set rng2 = Range("B2")
'Set rng3 = Range("C3")
'Set tablerng = rng1 '& rng2 & rng3
Set ch = ws.Shapes.AddChart2(Width:=200, Height:=200, Left:=Range("B4").Left, Top:=Range("B4").Top).chart
With ch
.SetSourceData Source:=rng1
.ChartType = xlBarClustered
.ChartTitle.Text = "Action Items by Status"
End With
ws.Activate
Worksheets("Action").Visible = False
End If
Seems easy but I'm not able to think through it, also the location is hit or miss even though I define the top and bottom and size. Sometimes it's to the right of the cell I chose to be the left.
Try the next way, please. It uses a dictionary to extract the unique values and their count and array to feed the necessary series. Try running it on active sheet and adapt it to your situation only after having the confirmation that what it returns is what you need:
Sub populatecharts()
Dim shT As Worksheet, ch As Chart, lastRow As Long
Dim arrY, arrX, i As Long, dict As Object
Set shT = ActiveSheet 'use here the sheet you need
lastRow = shT.Range("G" & shT.Rows.count).End(xlUp).row
arrX = shT.Range("G4:G" & lastRow).Value 'put the range in a array
Set dict = CreateObject("Scripting.Dictionary") 'needed for the next step
On Error Resume Next
shT.ChartObjects("MyChartXY").Delete 'for the case of re running need
On Error GoTo 0
For i = 1 To UBound(arrX)
If Not dict.Exists(arrX(i, 1)) Then
dict(arrX(i, 1)) = 1 'create the unique keys
Else
dict(arrX(i, 1)) = dict(arrX(i, 1)) + 1 'increment the key next occurrrence
End If
Next i
arrX = dict.Keys: arrY = dict.Items 'extract the necessary arrays
Set ch = shT.ChartObjects.Add(left:=shT.Range("B4").left, _
top:=shT.Range("B4").top, width:=200, height:=200).Chart
With ch
.ChartType = xlBarClustered
.HasTitle = True
.ChartTitle.Text = "Action Items by Status"
.SeriesCollection.NewSeries.Values = arrY 'feed it with the array elements
.SeriesCollection(1).XValues = arrX 'feed it with the array elements
End With
End Sub
Please, test it and send some feedback.

How to extend the range that is included in a graph with a macro

I have some data in column A and am trying to write a macro to extend the data range to the next - column B, so that every time I add data in following columns, the macro will extend the border to include that data in the graph plot.
See image below where only column A is included in my graph -
What do I need to do in order to get it to also include the next column - column B
For example:
What do you think?
This works for me:
Sub ExpandChartSource()
Dim ObjChart As Object
Dim RngSource As Range
Set ObjChart = ActiveSheet.ChartObjects(1)
Set RngSource = Range(Split(ObjChart.Chart.SeriesCollection(1).Formula, ",")(2))
Set RngSource = RngSource.Resize(RngSource.Rows.Count, RngSource.Columns.Count + 1)
ObjChart.Chart.SetSourceData Source:=RngSource
End Sub
Here a more dynamic version, useful if you want to enlarge the data indefinitely:
Sub ExpandChartSource()
Dim ObjChart As Object
Dim RngSource As Range
Dim IntSeries As Integer
Dim StrAddress As String
Set ObjChart = ActiveSheet.ChartObjects(1)
Set RngSource = Range(Split(ObjChart.Chart.SeriesCollection(1).Formula, ",")(2))
StrAddress = RngSource.Cells(1, 1).Address
Set RngSource = Range(Split(ObjChart.Chart.SeriesCollection(ObjChart.Chart.SeriesCollection.Count).Formula, ",")(2))
StrAddress = StrAddress & ":" & RngSource.Cells(RngSource.Rows.Count, 1).Address
Set RngSource = Range(StrAddress)
Set RngSource = RngSource.Resize(RngSource.Rows.Count, RngSource.Columns.Count + 1)
ObjChart.Chart.SetSourceData Source:=RngSource
End Sub
It assumes that the first series is the one most on the left while the last series is assumed to be on the right.

Create multiple charts from dynamic columns in a table

I would like to create a macro that runs through a series of data in a table and is able to automatically create multiple formatted graphs from it.
Here is what I'm working with (below):
Sub MakeXYGraph()
'https://stackoverflow.com/questions/62285791/dynamically-select-cells-and-input-in-chart
Dim ws As Worksheet
Set ws = Sheet1 'This is the codename of the sheet where the data is
'For the test, deleting all the previous charts
Dim vChartObject As ChartObject
For Each vChartObject In ws.ChartObjects
vChartObject.Delete
Next vChartObject
'rngData is the range where the data are. It is assumed that nothing else is on the sheet than what you displ
Dim rngData As Range
Set rngData = ws.UsedRange.Offset(1).Resize(ws.UsedRange.Rows.Count - 1)
' Get the number of series
Dim iMaxSeries As Integer
iMaxSeries = Application.WorksheetFunction.Max(rngData.Columns(1))
' Is the actual Series, but in the sheet it called Point
Dim iPoint As Integer
'Used for setting the ranges for the series data
Dim lFirstRow As Long, lLastRow As Long, lFirstColumn As Long, lLastColumn As Long
lFirstColumn = rngData(1).Column
lLastColumn = rngData.Columns(rngData.Columns.Count).Column
'Creating the Chart
Dim cht As ChartObject
Set cht = ws.ChartObjects.Add(Left:=250, Width:=500, Top:=50, Height:=300)
With cht.Chart
.ChartType = xlXYScatterLines
'X axis name
.Axes(xlCategory, xlPrimary).HasTitle = True
.Axes(xlCategory, xlPrimary).AxisTitle.Characters.Text = "Vertical Displacement"
'Y-axis name
.Axes(xlValue, xlPrimary).HasTitle = True
.Axes(xlValue, xlPrimary).AxisTitle.Characters.Text = "Vertical Coordinate"
' deleting the unwanted series (Excel tries to find out the data, but no need for it.)
Do Until .SeriesCollection.Count = 0
.SeriesCollection(1).Delete
Loop
End With
For iPoint = 1 To iMaxSeries
'Search for the first occurence of the point
lFirstRow = rngData.Columns(1).Offset(-1).Find(what:=iPoint).Row
'Search for the first occurence of the second point -1 is the last of this point
If iPoint = iMaxSeries Then
lLastRow = rngData.Rows(rngData.Rows.Count).Row - 1
Else
lLastRow = rngData.Columns(1).Find(what:=iPoint + 1).Row - 1
End If
'Add the series
With cht.Chart.SeriesCollection.NewSeries
.XValues = ws.Range(Cells(lFirstRow, lFirstColumn + 1), Cells(lLastRow, lLastColumn - 1))
.Values = ws.Range(Cells(lFirstRow, lFirstColumn + 2), Cells(lLastRow, lLastColumn))
.Name = "Point " & CStr(iPoint)
End With
Next iPoint
End Sub
Which plots the vertical coordinate vs. vertical displacement columns from this table:
To create this graph:
However, as you can see from the image with the table, I have multiple columns, and I would like to like to make graphs for several columns, all with the same format as the vertical coordinate vs. vertical displacement chart above, without interfering with the previous charts created. For example, the second graph that I would like to create is vertical coordinate vs. vertical stress. There is additional data on this worksheet, so one cannot just assume that the rest of the worksheet is blank.
One issue is that as you can see there are four different point numbers (1,2,3,4) and each point number is iterated 9 times. However, these numbers can change (for example there could be 8 Point numbers with three iterations each, and thus the data is dynamic and shouldn't just consider 4 Point No.'s with 9 iterations). And the table data will always be located starting from cell "C8". The current code deals with this.
The reason why the current code doesn't satisfy this is because it assumes that there is no other data on the worksheet where the table is (but there is). I want to be able to add more columns and create more charts (all of them plotted against vertical coordinate column) without affecting the other charts. Please if there is any way to modify the code so then I could create charts for several sets of data on the same worksheet then that would be much appreciated! I'm not sure what the best way to approach this is. Thank you.
https://drive.google.com/file/d/1cuW2eWYwrkNeJ-TmatiC4-PFodflNbSN/view?usp=sharing
Here's one approach:
Sub MakeXYGraph()
Const PLOT_HEIGHT As Long = 200
Const PLOT_WIDTH As Long = 300
Dim ws As Worksheet
Dim cht As ChartObject
Dim rngData As Range, rngHeaders As Range
Dim col As Long, posTop As Long, posLeft As Long
Dim ptRanges As Object, pt, dataRows As Range, i As Long
Set ws = Sheet1 'This is the codename of the sheet where the data is
For i = ws.ChartObjects.Count To 1 Step -1
ws.ChartObjects(i).Delete
Next i
Set rngData = ws.Range("C7").CurrentRegion
Set rngHeaders = rngData.Rows(1) 'the header row
Set rngData = rngData.Offset(1, 0).Resize(rngData.Rows.Count - 1) 'just the data
Set ptRanges = PointRanges(rngData.Columns(1))
posTop = ws.Range("M2").Top
posLeft = ws.Range("M2").Left
For col = 3 To rngData.Columns.Count
'add the chart
Set cht = NewChart(ws, posLeft, PLOT_WIDTH, posTop, PLOT_HEIGHT, rngHeaders.Cells(col).Value)
'loop over the keys of the dictionary containing the point numbers and corresponding ranges
For Each pt In ptRanges
Set dataRows = ptRanges(pt).EntireRow
With cht.Chart.SeriesCollection.NewSeries
.XValues = dataRows.Columns(rngData.Columns(col).Column)
.Values = dataRows.Columns(rngData.Columns(2).Column)
.Name = "Point " & pt
End With
Next pt
posTop = posTop + PLOT_HEIGHT
Next col
End Sub
'Scan the "point No" column and collect unique values and
' corresponding ranges in a Scripting Dictionary object
' assumes data is sorted by point no
Function PointRanges(pointsRange As Range) As Object
Dim dict As Object, c As Range, p, rng As Range
Set dict = CreateObject("scripting.dictionary")
For Each c In pointsRange.Cells
p = c.Value
If Not dict.exists(p) Then
dict.Add p, c 'add the start cell
Else
Set dict(p) = dict(p).Resize(dict(p).Count + 1) 'resize to add this cell
End If
Next c
Set PointRanges = dict
End Function
'add a chart and do some initial configuration
Function NewChart(ws As Worksheet, L, W, T, H, yAxisName As String)
Dim cht As ChartObject
Set cht = ws.ChartObjects.Add(Left:=L, Width:=W, Top:=T, Height:=H)
With cht.Chart
.ChartType = xlXYScatterLines
.Axes(xlCategory, xlPrimary).HasTitle = True 'X axis name
.Axes(xlCategory, xlPrimary).AxisTitle.Characters.Text = yAxisName
.Axes(xlValue, xlPrimary).HasTitle = True 'Y-axis name
.Axes(xlValue, xlPrimary).AxisTitle.Characters.Text = "Vertical Coordinate"
.Axes(xlValue, xlPrimary).ReversePlotOrder = True
Do While .SeriesCollection.Count > 0
.SeriesCollection(1).Delete
Loop
End With
Set NewChart = cht
End Function

Add series to chart

I use Holebase for work and it would be very useful for me if excel knew how to differentiate the start of a new series since the macro we have so far only displays one series by making a gap between series.
So the macro I'm trying to manipulate was taken from here and has already been adjusted since the previous one suited a purpose slightly different.
What I want is: Everytime I find a new BH on column A plot a distinct series with the values from column C and column D (x and y respectively) till the next BH on column A.
I managed to sort it out. So the macro first deletes all series inside the chart, second everytime time there is a new value / text on column A it displays the data shown on column C (X) and column D (Y).
No I have only one more problem to sort it out. The x range needs to have a minimum date since excel always adopts 1900 by default
Sub MakeCharts()
Dim sh As Worksheet
Dim rAllData As Range
Dim rChartData As Range
Dim cl As Range
Dim rwStart As Long, rwCnt As Long
Dim s As Series
Dim SourceRangeColor As Long
Set sh = ActiveSheet
sh.ChartObjects(1).Activate
'Set chrt = sh.ChartObjects(1)
For Each s In ActiveChart.SeriesCollection
s.Delete
Next s
With sh
' Get reference to all data
Set rAllData = .Range(.[A1], .[A1].End(xlDown)).Resize(, 4)
' Get reference to first cell in data range
rwStart = 2
Set cl = rAllData.Cells(rwStart, 1)
Do While cl <> ""
'Capture the first cell in the source range then trap the color
Set SourceRange = rAllData.Cells(rwStart, 5)
SourceRangeColor = SourceRange.Interior.Color
' cl points to first cell in a station data set
' Count rows in current data set
rwCnt = Application.WorksheetFunction. _
CountIfs(rAllData.Columns(1), cl.Value)
' Get reference to current data set range
Set rChartData = rAllData.Cells(rwStart, 1).Resize(rwCnt, 4)
'ActiveChart.SeriesCollection.Add _
'Source:=rChartData
With ActiveChart.SeriesCollection.NewSeries
.ChartType = xlXYScatterLines
.XValues = rChartData.Offset(, 2).Resize(, 1)
.Values = rChartData.Offset(, 3).Resize(, 1)
.Name = rAllData.Cells(rwStart, 1)
.MarkerBackgroundColor = SourceRangeColor
.MarkerForegroundColor = SourceRangeColor
'.Format.Line.ForeColor.RGB = SourceRangeColor (line colour for workbook 2007-2010)
'.Format.Line.BackColor.RGB = SourceRangeColor (line colour for workbook 2007-2010)
'.Format.Fill.ForeColor.RGB = SourceRangeColor (line colour for workbook 2007-2010)
.Interior.Color = SourceRangeColor
.Border.Color = SourceRangeColor
'.Axes(xlCategory, xlPrimary).CategoryType = xlTimeScale
'.Axes(xlCategory, xlPrimary).TickLabels.NumberFormat = "dd-mm-yyyy"
'.Axes(xlCategory, xlPrimary).MinimumScale = Application.Min.Range("C:C")
'.Axes(xlCategory, xlPrimary).MaximumScale = Application.Max.Range("C:C")
' Get next data set
rwStart = rwStart + rwCnt
Set cl = rAllData.Cells(rwStart, 1)
End With
Loop
End With
End Sub
Thanks
enter image description here

Different colour between series VBA Scatter Graph

I have the following macro which plots a Scatter graph for three columns. One column (AL13, downwards) is on the x axis. How do I get it to plot the other two columns (AK and AM) onto the same scatter? Also in different colour to each other? Thank You
Sub Graphing()
Set rng4 = ActiveSheet.Range(Range("AP13"), Range("AV33"))
With ActiveSheet.ChartObjects.Add(Left:=rng4.Left, Width:=rng4.Width, Top:=rng4.Top, Height:=rng4.Height)
.Chart.ChartType = xlXYScatter
.Chart.HasLegend = False
.Chart.Axes(xlCategory).TickLabels.Font.Size = 18
.Chart.Axes(xlValue).TickLabels.Font.Size = 18
Set srs = .Chart.SeriesCollection.NewSeries
srs.Values = Range(Range("AK13"), Range("AK13").End(xlDown))
srs.XValues = Range(Range("AL13"), Range("AL13").End(xlDown))
srs.Values = Range(Range("AM13"), Range("AM13").End(xlDown))
End With
End Sub
I will repost the code that I revised for you above, thanks for crediting me :)
Sub Graphing()
'Declare all the variables to be used:'
Dim rng4 as Range
Dim srs as Series
Dim cht as Chart
Dim xVals as Range
Dim srsVals as Range
'Set the chart's data range:'
Set rng4 = ActiveSheet.Range(Range("AP13"), Range("AV33"))
'Set the range variable to contain the series values'
' You can later modify this to include any number of columns, and the '
' loop structure below will add each column as a series to the chart.'
Set srsVals = ActiveSheet.Range(Range("AL13"),Range("AM13").End(xlDown))
'Set the cht variable:'
Set cht= ActiveSheet.ChartObjects.Add(Left:=rng4.Left, Width:=rng4.Width, Top:=rng4.Top, Height:=rng4.Height).Chart
'Set the Range variable for xValues:
Set xVals = Range(Range("AK13"),Range("AK13").End(xlDown))
'Format the chart and add series to the chart by iterating over the columns in srsVals:'
With cht
.ChartType = xlXYScatter
.HasLegend = False
.Axes(xlCategory).TickLabels.Font.Size = 18
.Axes(xlValue).TickLabels.Font.Size = 18
'Create the series in a loop
For c = 1 to srsVal.Columns.Count
Set srs = .SeriesCollection.NewSeries
With srs
.Values = xVals
.XValues = Range(srsVals.Columns(c).Address)
.Name = "Series " & c '<-- Modify as needed.'
End With
Next
End With
End Sub
I found that if I set the series as two separate series then it will plot both and give them different colours. Not sure if it is the most efficient way of doing it but it works.
Sub Graphing()
'Declare all the variables to be used:'
Dim rng4 as Range
Dim srs as Series
Dim cht as Chart
Dim xVals as Range
Dim srsVals as Range
'Set the chart's data range:'
Set rng4 = ActiveSheet.Range(Range("AP13"), Range("AV33"))
'Set the range variable to contain the series values'
' You can later modify this to include any number of columns, and the '
' loop structure below will add each column as a series to the chart.'
Set srsVals = ActiveSheet.Range(Range("AL13"),Range("AM13").End(xlDown))
'Set the cht variable:'
Set cht= ActiveSheet.ChartObjects.Add(Left:=rng4.Left, Width:=rng4.Width, Top:=rng4.Top, Height:=rng4.Height).Chart
'Set the Range variable for xValues:
Set xVals = Range(Range("AK13"),Range("AK13").End(xlDown))
'Format the chart and add series to the chart by iterating over the columns in srsVals:'
With cht
.ChartType = xlXYScatter
.HasLegend = False
.Axes(xlCategory).TickLabels.Font.Size = 18
.Axes(xlValue).TickLabels.Font.Size = 18
'Create the series in a loop
For c = 1 to srsVal.Columns.Count
Set srs = .SeriesCollection.NewSeries
With srs
.Values = xVals
.XValues = Range(srsVals.Columns(c).Address)
.Name = "Series " & c '<-- Modify as needed.'
End With
Next
End With
End Sub

Resources