Change horizontal axis labels in XY Scatter chart with VBA - excel

I have plotted a XY Scatter plot with VBA code. But I'm unable to change the horizontal axis labels. Can the horizontal axis labels be changed to text? If yes, how can I change it with arrays.
This is the XY Scatter chart I have created with VBA:XY Scatter chart
I would like to change the horizontal labels from 1,2,3,4 (as marked in the chart) to A,B,C,D using arrays. Thank you very much!
Edit:
My data table:
Data table
VBA macro code:
Sub plot_test3()
Dim ws2 As Worksheet
Dim i, j, c, m, n, a, lrow As Long
Dim frist_code, frist_value, frist_name, frist_date As Variant
Dim xychart As Chart
Set ws2 = Worksheets("Sheet3")
i = 1: j = 1: a = 1: k = 1: p = 2
c = 4: lrow = 6: m = 2: n = 2
ws2.Activate
ReDim frist_code(1 To lrow - 1)
ReDim frist_value(1 To lrow - 1)
ReDim frist_name(0)
ReDim frist_date(1 To lrow - 1)
Set xychart = ws2.Shapes.AddChart2(Left:=0, Top:=0, Width:=400, Height:=300).Chart
For j = 1 To c
For i = 1 To lrow - 1
frist_value(i) = ws2.Cells(m, n)
frist_code(i) = k
frist_name(0) = ws2.Cells(1, n)
frist_date(i) = ws2.Cells(m, 1).Value2
m = m + 1
Next i
xychart.SeriesCollection.NewSeries
xychart.ChartType = xlXYScatter
With xychart.SeriesCollection(a)
.Name = frist_name(0)
.Values = frist_value
.XValues = frist_code
.MarkerSize = 15
.MarkerStyle = 2
End With
a = a + 1
n = n + 1
m = 2
k = k + 1
Next j
xychart.Axes(xlCategory).TickLabelPosition = xlLow
xychart.SetElement (msoElementLegendBottom)
End Sub

XY Scatter is not adequate to such. XY expects continuous values over X axis and, as so, isn't compatible with named values.
To achieve desired labels, a discrete type chart must be used, like Line.
But for such, you can't have multiple values in same X value. You may:
consider using transposed data:
if color grouping required, using a serie by each point and then format every serie as required:
EDIT: Code for 2nd option:
Following code will produce desired chart. Note chart isn't interactive, ie, changing values in spreadsheet won't change chart!
Sub Plot_Chart()
Dim v(), r As Long, c As Long
'Create and use chart
With ActiveSheet.Shapes.AddChart(xlLineMarkers).Chart
'Clear all series and legend
While .SeriesCollection.Count
.SeriesCollection(1).Delete
Wend
.Legend.Delete
'Iterate through rows and columns of data
For r = 2 To Selection.Rows.Count
For c = 1 To Selection.Columns.Count
'Create series and use it
With .SeriesCollection.NewSeries 'chart.SeriesCollection
'Create data with single valid point
ReDim v(1 To Selection.Columns.Count)
v(c) = Selection(r, c)
.Values = v
End With
Next
Next
'Set and format X-Axis
.SeriesCollection(1).XValues = Selection.Rows(1).Value
With .Axes(xlCategory)
.MajorTickMark = xlNone
.TickLabelPosition = xlLow
End With
'Format series
For c = 1 To .SeriesCollection.Count
.SeriesCollection(c).MarkerStyle = xlMarkerStyleDiamond
.SeriesCollection(c).MarkerSize = 7
Set dbg = .SeriesCollection(c).Format.Fill
.SeriesCollection(c).Format.Fill.ForeColor.ObjectThemeColor = (c - 1) Mod Selection.Columns.Count + 5
.SeriesCollection(c).Format.Line.ForeColor.ObjectThemeColor = (c - 1) Mod Selection.Columns.Count + 5
Next
End With
End Sub

Related

Increase Chart Data Series By Two Rows with VBA

I am working on a chart that I want to change data series every few seconds. After ten seconds, I want the data series to move from SERIES(Input!$A$4:$D$4,Input!$E$3:$F$3,Input!$E$4:$F$4,1) to SERIES(Input!$A$6:$D$6,Input!$E$3:$F$3,Input!$E$6:$F$6,1).
I have tried adapting the below code, but so far am only able to add a series, and not the data series row.
Sub ChangeChartRange()
Dim i As Integer, r As Integer, n As Integer, p1 As Integer, p2 As Integer, p3 As Integer
Dim rng As Range
Dim ax As Range
'Cycles through each series
Sheets("Dashboard").ChartObjects("Chart 1").Activate
'For n = 1 To ActiveChart.SeriesCollection.Count Step 1
r = 0
'Finds the current range of the series and the axis
For i = 1 To Len(ActiveChart.SeriesCollection(1).Formula) Step 1
If Mid(ActiveChart.SeriesCollection(1).Formula, i, 1) = "," Then
r = r + 1
If r = 1 Then p1 = i + 1
If r = 2 Then p2 = i
If r = 3 Then p3 = i
End If
Next i
MsgBox ActiveChart.SeriesCollection(1).Formula
'Defines new range
Set rng = Range(Mid(ActiveChart.SeriesCollection(1).Formula, p2 + 1, p3 - p2 - 1))
Set rng = Range(rng, rng.Offset(0, 1))
'Sets new range for each series
ActiveChart.SeriesCollection(1).Values = rng
'Updates axis
'Set ax = Range(Mid(ActiveChart.SeriesCollection(1).Formula, p1, p2 - p1))
'Set ax = Range(ax, ax.Offset(0,1))
'ActiveChart.SeriesCollection(1).XValues = ax
End Sub

Creating an Array From Criteria

I have the following code, that is doing some if's, but with the values I am struggling to see how I create, and add the values to an array. At the moment, I am just adding the values to a listbox
List(lC, 0) = sh1.Cells(row, 23)
I tried creating an integer and, and then used something like
var = var & List(lC, 0) = sh1.Cells(row, 23)
But I am not sure if that's the correct way?
Private Sub CommandButton3_Click()
Dim sh1
Dim LR
Dim lC
Dim row
Me.lstUsedRooms.Clear
Set sh1 = ThisWorkbook.Worksheets(4) 'room order from sheets
With sh1
LR = .Range("A" & .Rows.Count).End(xlUp).row
End With
lC = 0
With Me.lstUsedRooms
.ColumnCount = 1 'there is 8 columns
.RowSource = ""
.ColumnWidths = 40
For row = 2 To LR
NewIVTime = Format("14:00", "h:mm:ss")
If Left(sh1.Cells(row, 6), 10) = "24/05/2019" Then ' Gets all interviews for the date specified
Dim LTime As Date
Dim LTime1 As Date
LTime = Format(sh1.Cells(row, 7), "h:mm:ss") 'Gets the times from all the rooms from the date stated above
LTime1 = CDate(LTime) + 3 / 24 ' Adds 3 hours to the time above
If LTime1 < NewIVTime Then ' Check which interviews display three hours after the new interview
.AddItem
.List(lC, 0) = sh1.Cells(row, 23)
lC = lC + 1
End If
End If
Next
If .ListCount = 0 Then
Me.lstUsedRooms.ColumnWidths = 100
Me.lstUsedRooms.AddItem "No Rooms"
End If
End With
End Sub
First see what you are going to be inputting, if you only need a 1 dimensional array then the best option is a collection:
Dim newCollection as New Collection
For each r in Range
newCollection.Add Value 'Add value here
Next r
If you are needing a multidimensional array then the array function is the best way:
Dim zArray() as variant
Redim zArray(x, y, ...) 'x and y are size of array
Or
Redim Preserve zArray(x, y, ...) 'If you loop through the Redim
For i = 1 to x
For j = 1 to y
zArray(x,y)
Next j
Next i

Data-labels not displaying in proper order with excel scattered chart using vba

i have an excel sheet with master data with the following information
Row number | candidate | X Value | Y value
I need to plot a scattered chart with X and Y value plotted with row number as data label. Created a VBA to do so, and it worked but datalabel was overlapping. It was fixed with the help of one of our member. But the issue now is, some of the datapoint is showing in different points.
Error picture here, please click
Code as follows
Dim Counter As Integer, ChartName As String, xVals As String, yVals As String
Application.ScreenUpdating = False
Dim c As ChartObject
Set c = Sheets("IImpactchart").ChartObjects("Chart 1")
c.Activate
'Find address of the X values
xVals = ActiveChart.SeriesCollection(1).Formula
xVals = Mid(xVals, InStr(InStr(xVals, ","), xVals, _
Mid(Left(xVals, InStr(xVals, "!") - 1), 9)))
xVals = Left(xVals, InStr(InStr(xVals, "!"), xVals, ",") - 1)
'Not sure why this loop from your code is useful, but let's leave it.
Do While Left(xVals, 1) = ","
xVals = Mid(xVals, 2)
Loop
'Find address of the Y values
yVals = ActiveChart.SeriesCollection(1).Formula
yVals = Mid(yVals, InStr(InStr(yVals, ","), yVals, _
Mid(Left(yVals, InStr(yVals, "!") - 1), 9)))
yVals = Right(yVals, Len(yVals) - InStr(yVals, ","))
yVals = Left(yVals, InStr(InStr(yVals, "!"), yVals, ",") - 1)
'Again, not sure why this loop from your code is useful, but let's leave it.
Do While Left(yVals, 1) = ","
yVals = Mid(yVals, 2)
Loop
Dim DimY As Long, DimX As Long
DimY = 250
DimX = 250
Dim LabelArray() As Long
ReDim LabelArray(1 To DimX, 1 To DimY)
Dim src As Series, pts As Points
Set src = ActiveChart.SeriesCollection(1)
Set pts = src.Points
'Clear labels
src.HasDataLabels = False
For Counter = 1 To Range(xVals).Cells.Count
If (Range(xVals).Cells(Counter, 1).Offset(0, -1).Value = 0) Then
Exit Sub
End If
Dim xCoord As Long, yCoord As Long
xCoord = Range(xVals).Cells(Counter, 1).Value2
yCoord = Range(yVals).Cells(Counter, 1).Value2
If LabelArray(xCoord, yCoord) = 0 Then 'No overlap
LabelArray(xCoord, yCoord) = Counter
pts(Counter).HasDataLabel = True
pts(Counter).DataLabel.Text = Counter + 5
Else 'Overlap
pts(LabelArray(xCoord, yCoord)).DataLabel.Text = _
pts(LabelArray(xCoord, yCoord)).DataLabel.Text & "," & Counter + 5
End If
Next Counter
Application.ScreenUpdating = True
The above issue was solved by changing
yCoord = Range(yVals).Cells(Counter, 1).Value2
to
yCoord = Range(yVals).Cells(Counter, 2).Value2

How to loop through a matrix in VBA Excel?

I am trying to make a macro that will create a matrix based upon an equation in an VBA.
For example:
If I have the following 3x3 matrix:
3 5 7
6 3 4
1 2 3
I want to create a 3x3 matrix that takes the value 1st value and divides it by the sum of the row, and so on.
0.2 0.3 0.5
0.5 0.2 0.3
0.2 0.3 0.5
I tried the following code:
Sheets("sheet1").Select
Range("C2").Select
Selection.End(xlDown).Select
ActiveCell.Offset(2, 0).Range("A1").Select 'So the new matrix starts underneath the old matrix
Dim i As Integer
Dim n As Integer
i = 4
n = 1
Do While Cells(i, 3).Value <> ""
ActiveCell.FormulaRnC1 = "=RiC3/SUM(RiC3:RiC52)*100"
i = i + 1
ActiveCell.Offset(1, 0).Range("A1").Select
The number or rows will vary.
I have limited experience with this platform, please let me know how to improve framing this question.
I will recommend you put your first matrix on Sheet1 starting in cell A1. This will output the other Matrix to the new workbook, Sheet1, starting in cell A1.
Sub example()
Dim x As Variant, y As Variant
Dim row_sum As Double
Dim i As Integer, j As Integer
Dim wbk As Workbook
With ThisWorkbook.Sheets(1)
x = .Range("a1:" & .Cells(.Range("a" & .Rows.Count).End(xlUp).Row, .Cells(1, .Columns.Count).End(xlToLeft).Column).Address).Value2
End With
y = x
With Application.WorksheetFunction
For i = LBound(x, 1) To UBound(x, 1)
row_sum = .Sum(.Index(x, i))
For j = LBound(x, 2) To UBound(x, 2)
y(i, j) = x(i, j) / row_sum
Next j
Next i
End With
Set wbk = Workbooks.Add
wbk.Sheets(1).Range("a1").Resize(UBound(y, 1), UBound(y, 2)) = y
End Sub

Charts with variable series in Excel VBA

I am new to VBA and to this forum. I have a table with dates as the first column (x column) and 12 columns of data pertaining to the data (y values). I am trying to plot the data in a simple xlLine chart. Only few selected columns are to be plotted for y values. The columns are selected using a combo box at the top of the column. The number of rows are variable.
I am using this code but this is not working. Can someone kindly let me know what is wrong and fix it? Appreciate any help. Thanks in advance.
Sub drawchart1()
'
' drawchart1 Macro
'
'
Dim i As Integer
Dim j As Integer
Dim n As Integer
' finding the number of rows
j = Range("Charts!A1").Offset(Sheet1.Rows.Count - 1, 0).End(xlUp).Row
' selecting some range and adding a chart which is then modified.(not sure this is the correct method.)
Range("A10:C15").Select
ActiveSheet.Shapes.AddChart.Select
ActiveChart.ChartType = xlLine
i = 2
n = 2
' Cells (9,1) contains the value "Date". Defining the X Axis values
ActiveChart.SeriesCollection(1).Name = Sheets("Charts").Cells(9, 1).Value
ActiveChart.SeriesCollection(1).XValues = "=Charts!R10C1:R" & j & "C1"
Do While i < 14
' Cells(8,i) contain the results of combo box - true or false.
' Cells(9,i) contain the names of the series
If Cells(8, i).Value = True Then
ActiveChart.SeriesCollection(n).Name = Sheets("Charts").Cells(9, i).Value
ActiveChart.SeriesCollection(n).Values = "=Charts!R10C" & i & ":R" & j & "C" & i
n = n + 1
i = i + 1
Else
i = i + 1
End If
Loop
End Sub
Hi Again,
Since my columns would not exceed 14 (i.e. not large), I used the following "brute force" technique and it worked fine. I would still love to learn how to do it without using the "brute force" technique. Thanks in advance.
Sub drawchart()
Dim j As Integer
Dim Chartstring As String
j = Range("Charts!A1").Offset(Sheet1.Rows.Count - 1, 0).End(xlUp).Row
Chartstring = "A9:A" & j
If Cells(8, 2).Value = True Then
Chartstring = Chartstring & ", B9:B" & j
Else
Chartstring = Chartstring
End If
If Cells(8, 3).Value = True Then
Chartstring = Chartstring & ", C9:C" & j
Else
Chartstring = Chartstring
End If
' And similarly added code for each of the 14 columns
' And finally fed the chartstring into the "Source"
ActiveSheet.Shapes.AddChart.Select
ActiveChart.ChartType = xlLine
ActiveChart.SetSourceData Source:=Range(Chartstring)
End Sub
Probably you're not watching any more. Here's an alternative approach.
Sub DrawChart1()
Dim i As Long
Dim j As Long
Dim ws As Worksheet
Dim rCht As Range, rYVals As Range
Dim cht As Chart
' finding the number of rows
Set ws = Worksheets("Charts")
j = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
' start with X values (row 10 to j), include header row (row 9)
Set rCht = ws.Range(ws.Cells(9, 1), ws.Cells(j, 1))
' add column of Y values if row 8 of column is TRUE
For i = 2 To 14
If ws.Cells(8, i).Value Then
Set rYVals = ws.Range(ws.Cells(9, i), ws.Cells(j, i))
Set rCht = Union(rCht, rYVals)
End If
Next
' if we've had any Y values, insert chart, using range we've built up
If Not rYVals Is Nothing Then
Set cht = ws.Shapes.AddChart(xlLine).Chart
cht.SetSourceData Source:=rCht, PlotBy:=xlColumns
End If
End Sub

Resources