Why my VBA code creates line plot instead of scatter plot? - excel

I'm trying to generate scatter plot from 2 data-columns, but instead I get a line plot where data of the first column is ignored (i.e.: if I have 1000 points, on x-axis I see values from 1 to 1000, regardless of the data stored in 1st column). I can't find the error in my code. What's wrong?
Public Sub Graph_Refresh()
Dim cht As Chart
Dim i As Integer
Dim seriesIndex As Integer
Set cht = Sheets("Graph").ChartObjects("Chart 1").Chart
seriesIndex = 0
' ***** CLEAR OLD CONTENT *****
cht.ChartArea.ClearContents
' ***** NON CHANGEABLE PARAMETERS *****
'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 = 12
cht.HasTitle = False ' No chart title
'cht.SetElement (msoElementPrimaryValueGridLinesMajor) 'Gridlines
'Adjust x-axis
cht.HasAxis(xlCategory, xlPrimary) = True
cht.Axes(xlCategory, xlPrimary).HasTitle = True
cht.Axes(xlCategory).AxisTitle.Text = "Frequency [MHz]"
cht.Axes(xlCategory).MinimumScale = Sheets("Graph").Range("AI7").Value
cht.Axes(xlCategory).MaximumScale = Sheets("Graph").Range("AI8").Value
'Adjust y-axis
cht.HasAxis(xlValue, xlPrimary) = True
cht.Axes(xlValue, xlPrimary).HasTitle = True
cht.Axes(xlValue).AxisTitle.Text = "S-Parameters [dB]"
cht.Axes(xlValue).MinimumScale = Sheets("Graph").Range("AI9").Value
cht.Axes(xlValue).MaximumScale = Sheets("Graph").Range("AI10").Value
cht.Axes(xlValue).CrossesAt = -100
' Data Series
For i = 1 To 5
seriesIndex = seriesIndex + 1
cht.SeriesCollection.NewSeries
With Sheets("Graph")
cht.SeriesCollection(seriesIndex).Name = .Cells(6 + (i - 1) * 4).Value & " S11"
End With
cht.SeriesCollection(seriesIndex).XValues = "='" & Sheets("Data" & CStr(i)).Name & "'!$K$4:$K$10004"
cht.SeriesCollection(seriesIndex).Values = "='" & Sheets("Data" & CStr(i)).Name & "'!$L$4:$L$10004"
' Set line size and color
With cht.SeriesCollection(seriesIndex)
.Format.Line.Weight = 2.25
.Format.Line.Visible = msoFalse
.Format.Line.Visible = msoTrue
.Format.Line.ForeColor.RGB = RGB(255,0,0)
.MarkerStyle = xlMarkerStyleNone
End With
Next i
' Legend
End Sub
Data are stored in sheets "Data1" - "Data5", and the range should be ok. Chart "Chart 1" already exists (that's why I don't create it).
Thanks in advance for help!

After some more investigation, I fund the answer. I leave it here for anyone who might be interested.
The problem was due to the fact that the data range that I provided included empty cells (or, to be more precise, cells with functions returning blanks).
Resizing XValues and Values to include only cells with data solved the problem.

Related

How to plot data imported from a csv?

I am trying to import CSV output data from a simulation into an Excel sheet to plot the data in a regular XY scatter chart.
I managed everything except the end result. The data is imported from csv to Excel, points are replaced by commas as a decimal separator.
It is plotting a straight horizontal line at 0 y-coordinates.
I noticed that the values in Excel are stored as texts, although I specified the format for numerical contents of csv as numbers like following:
DataSheet.Cells(Row, col).NumberFormat = "0.E+00"
When I test Isnumeric(cell.value), it turns out positive.
My complete code:
CsvFile = Application.GetOpenFilename()
Set DataSheet = Worksheets("CSV_Plot")
nrow = 10 'data starts at 10th row
Open CsvFile For Input As #1
Do Until EOF(1)
Line Input #1, CsvLine
CsvItem = Split(CsvLine, ",")
If Not CsvItem(0) <> "" Then GoTo 10 'ignores first line
ncol = UBound(CsvItem) 'ncol = number of data columns
If IsNumeric(CsvItem(0)) Then
For i = 0 To ncol
CsvItem(i) = Replace(CsvItem(i), ".", ",") 'replace point with comma in 'numerical values
Next i
End If
Add1 = DataSheet.Cells(nrow, LBound(CsvItem) + 1).Address
Add2 = DataSheet.Cells(nrow, ncol + 1).Address
DataSheet.Range(Add1 & ":" & Add2) = CsvItem
nrow = nrow + 1
10:
Loop
nrowlast = nrow
Close #1
For Row = 11 To nrowlast
For col = 1 To ncol
DataSheet.Cells(Row, col).Select
DataSheet.Cells(Row, col).NumberFormat = "0.E+00"
Next col
Next Row
Set ChtObj = DataSheet.ChartObjects.Add(50, 50, 500, 300)
Set Cht = ChtObj.Chart
With Cht
.ChartType = xlXYScatterLines
.SeriesCollection.NewSeries
.SeriesCollection(1).XValues = DataSheet.Range("A11:A35")
.SeriesCollection(1).Values = DataSheet.Range("N11:N35")
End With
EDIT: I think your problem is this line: CsvItem = Split(CsvLine, ","). The return type of Split should be a String. I don't know what your data looks like but you could try casting it as Double if decimal places are relevant. Otherwise cast it as Long: CsvItem = CLng(Split(CsvLine, ",")).
Original answer:
I updated the relevant parts of your code:
For Row = 11 To nrowlast
For col = 1 To ncol
DataSheet.Cells(Row, col).NumberFormat = "0.E+00"
Next col
Next Row
I took out the .Select statement as it is unnecessary and might lead to errors. Here is the main part part:
Dim ChtObj As Object
Set ChtObj = DataSheet.Shapes.AddChart2(, xlXYScatterLines, 50, 50, 500, 300)
With ChtObj.Chart
.SeriesCollection.NewSeries
.SeriesCollection(1).XValues = DataSheet.Range("A11:A35")
.SeriesCollection(1).Values = DataSheet.Range("N11:N35")
End With
This should work as intended.
After some effort, i was able to locate the source of problem: I had defined CsvItem() as string and that's why when I execute the statement DataSheet.Range(Add1 & ":" & Add2) = CsvItem, the values in excel were always text irrespective of the format.
The solution to this was to define a variable to hold numerical values of CsvItem and assign this value to excel cells:
Dim CsvVal() As Double
CsvVal(i) = CDbl(CsvItem(i))
DataSheet.Range(Add1 & ":" & Add2).Value = CsvVal
this eventually produced the result I wanted.

Unable to plot values on scatterplot using vba

I am relatively new to VBA. I am attempting to automate the generation of a graph containing Beta values using the following steps:
Step 1 - Generate a list of random numbers in Column A
Step 2 - Based on values in Column A, apply the Beta.Dist formula in Column B
Step 3 - Generate a scatterplot based on values in Column B, the scatterplot should look like a U-shaped distribution curve
I've tried using the following code but I am only seeing 1 value in the scatter plot (i.e., the scatterplot only has one dot).
Here's the code:
Option Explicit
Option Base 1
Sub Macro1()
Application.ScreenUpdating = False
Dim i%, j%
Range("A1").Select
Selection = "0.99"
Selection.Offset(0, 1) = "Beta(" & Selection & ", " & Selection & ") Density"
For i = 1 To 301
Selection.Offset(i, 0).Formula = "= rand()"
Selection.Offset(i, 1).Formula = "=BETA.DIST(A2:A302,0.99,0.99,False)"
Next i
j = ActiveSheet.ChartObjects.Count
ActiveSheet.Shapes.AddChart2(-1, xlXYScatter, 98 + j * 10, 16.5 + j * 10, 319, 296.5).Select
ActiveChart.SetSourceData Source:=Sheets("Sheet1").Range("B2:B302")
ActiveSheet.ChartObjects(j + 1).Activate
ActiveChart.SetElement (msoElementChartTitleAboveChart)
Selection.Caption = "="
ActiveChart.Axes(xlCategory).MaximumScale = 1
ActiveChart.Axes(xlCategory).Format.Line.Visible = msoFalse
ActiveChart.Axes(xlCategory).MajorGridlines.Delete
ActiveChart.Axes(xlValue).MaximumScale = 1.1
ActiveChart.Axes(xlValue).TickLabels.NumberFormat = "0.000#"
ActiveChart.Axes(xlValue).Format.Line.Visible = msoFalse
ActiveChart.Axes(xlValue).MajorGridlines.Delete
Range("E1") = ""
Range("I1") = ""
Range("B1").Select
Application.ScreenUpdating = True
End Sub
I'm hoping to get a U-shaped beta distribution curve in the scatter plot. Appreciate any form of help and thank you in advance!
You're not setting the chart data correctly:
ActiveChart.SetSourceData Source:=Sheets("Sheet1").Range("A2:B302")

How can I prevent excel from automatically creating series in my vba generated chart?

I am trying to create a very basic scatterplot of an x column and a y column.
Dim c As Chart
Set c = sht.Shapes.AddChart.Chart
With c
.ChartType = xlXYScatter
.SeriesCollection.NewSeries
.SeriesCollection(1).Name = "GPC Plot"
.SeriesCollection(1).XValues = Range("B6", Range("B6").End(xlDown))
.SeriesCollection(1).Values = Range("C6", Range("C6").End(xlDown))
.HasTitle = True
.ChartTitle.Characters.Text = sheetname
.Axes(xlCategory, xlPrimary).HasTitle = True
.Axes(xlCategory, xlPrimary).AxisTitle.Characters.Text = "Molecular Weight"
.Axes(xlCategory).MaximumScale = 10000
.Axes(xlCategory).MinimumScale = 10
.Axes(xlCategory).ScaleType = xlLogarithmic
.Axes(xlValue).MaximumScale = 225
.Axes(xlValue).MinimumScale = 0
End With
I just want the chart with the one data series, but Excel keeps generating a chart with 5 other series using random data from the sheet that I am creating the chart on. Is there a way I can prevent excel from automatically doing this?
You need to clear data out of the chart before you add the data you want. At the beginning of your With/End With block, insert this:
With c
Do Until c.SeriesCollection.Count = 0
c.SeriesCollection(1).Delete
Loop

Assigning a negative value to the DataLabel.Orientation property in Excel

I've written the below code to create an XY scatter chart and format the points to create a visual timeline of events/decisions.
Sub UpdateDecisionTimelineChart()
Dim scount As Integer
Dim labelrotation As Integer
Dim c As Range
ActiveSheet.ChartObjects("chtDecisionTimeline").Activate
scount = 0
For Each c In Range(Worksheets("Decision Record").Range("C7"), Worksheets("Decision Record").Range("C7").End(xlDown))
scount = scount + 1
ActiveChart.SeriesCollection.NewSeries
With ActiveChart.SeriesCollection(scount)
.Name = "='Decision Record'!" & c.Offset(0, 1).Address
.XValues = "='Decision Record'!" & c.Address
.Values = "='Decision Record'!" & c.Offset(0, -1).Address
.MarkerStyle = 8
.MarkerSize = 7
.MarkerBackgroundColor = RGB(228, 10, 56)
.MarkerForegroundColor = -2
.Format.Line.Visible = False
.ApplyDataLabels
.DataLabels.ShowValue = False
.DataLabels.ShowSeriesName = True
.DataLabels.Position = xlLabelPositionAbove
.DataLabels.Orientation = -45
End With
Next
End Sub
The data which I am using is set out as follows:
And the resultant timeline looks like this:
The code works fine (although I know it's not pretty) except for the bit where I try to assign a value of -45 to the .DataLabels.Orientation property; this actually sets a value of 45.
MSDN states: 'The value of this property can be set to an integer value from –90 to 90 degrees or to one of the following constants.', but any negative integer value I assign converts to a positive value.
Is it possible to assign a negative value to the .DataLabels.Orientation property and, if so, how?

how to add data label to bubble chart in excel

Hi I want to add customize data label to my bubble chart. my code is below. at the moment data label refer to XValues. I would like my data label fill with bubble size. would u mind help me how I can customize below code?
I tried to add .DataLabel.Text = "txt" but I received below
error:
Run-time error '438':Object doesn't support this property or method
Public Sub CreateMultiSeriesBubbleChart()
If (Selection.Columns.Count <> 4 Or Selection.Rows.Count < 3) Then
MsgBox "Selection must have 4 columns and at least 2 rows"
Exit Sub
End If
Dim red, green, blue As Integer
Dim bubbleChart As ChartObject
Set bubbleChart = ActiveSheet.ChartObjects.Add(Left:=Selection.Left, Width:=600, Top:=Selection.Top, Height:=400)
bubbleChart.Chart.ChartType = xlBubble
Dim r As Integer
For r = 2 To Selection.Rows.Count
With bubbleChart.Chart.SeriesCollection.NewSeries
.Name = "=" & Selection.Cells(r, 1).Address(External:=True)
.XValues = Selection.Cells(r, 2).Address(External:=True)
.Values = Selection.Cells(r, 3).Address(External:=True)
.BubbleSizes = Selection.Cells(r, 4).Address(External:=True)
.Format.Fill.Solid
.Format.Fill.ForeColor.RGB = RGB(61, 161, 161)
' .DataLabel.Text = "txt"
End With
Next
bubbleChart.Chart.SetElement (msoElementPrimaryCategoryAxisTitleAdjacentToAxis)
bubbleChart.Chart.Axes(xlCategory, xlPrimary).AxisTitle.Text = "=" & Selection.Cells(1, 2).Address(External:=True)
bubbleChart.Chart.SetElement (msoElementPrimaryValueAxisTitleRotated)
bubbleChart.Chart.Axes(xlValue, xlPrimary).AxisTitle.Text = "=" & Selection.Cells(1, 3).Address(External:=True)
bubbleChart.Chart.SetElement (msoElementPrimaryCategoryGridLinesMajor)
bubbleChart.Chart.Axes(xlCategory).MinimumScale = 0
End Sub
My input sample:
Label Hour Day count
01-SUNDAY 14 1 1
01-SUNDAY 19 1 1
02-MONDAY 12 2 1
02-MONDAY 13 2 1
02-MONDAY 14 2 2
02-MONDAY 16 2 2
Without using VBA, right click on the bubbles and select Add Data Labels. Then, right click on the data labels and click Format Data Labels. Under Label Options, select Value From Cells and specify the cells containing the labels you'd like to use.
DataLabel.Text is a method for a Point, not the NewSeries
This code:
For r = 2 To Selection.Rows.Count
With bubbleChart.Chart.SeriesCollection.NewSeries
[...]
.DataLabel.Text = "txt"
End With
Next
...attempts to label the series, and fails.
Recognizing this code as being from another famous example of "multi-series Bubble Charts", it is a logical assumption that we only need to handle 1 data point per series, which makes the following code the solution:
For r = 2 To Selection.Rows.Count
With bubbleChart.Chart.SeriesCollection.NewSeries
[...]
.Points(1).HasDataLabel = True
.Points(1).DataLabel.Text = "txt"
End With
Next

Resources