Excel failling to recognize type of chart - vba

I have following code to copy all charts on one sheet into another.
Problem is that in spite of the fact that my charts have numeric(timeseries) data for horizontal axis Excel treats it as categorical. I can tell that is does that because it tries to display every single date on the axis( in spite of my code swtiching it to once a month), and once select "Format Axis" I only see fields for Categorical data( I am missing fields like Maximim, Major Unit etc.).
This is the code I am using, to be hones I copeid most of it of some forum but I cannot recall where if I do find it again I'll post a link:
Sub CopyCharts(Source As Worksheet, Target As Worksheet)
Dim SChart As ChartObject
Dim NChart As ChartObject
Dim NewSheetNChart As ChartObjects
Dim ChartTop As Single
Dim ChartLeft As Single
Dim ChartIndex As Integer
Dim ChartSeries As Series
Dim XAxis As Axis
For Each SChart In Source.ChartObjects
'Save chart's current position
ChartTop = SChart.Top
ChartLeft = SChart.Left
'Copy and paste the chart
SChart.Copy
Target.Paste
'Find the chart in a new spreadsheet
ChartIndex = ChartIndex + 1
Set NewSheetNChart = Target.ChartObjects
Set NChart = NewSheetNChart(ChartIndex)
'Align the charts
NChart.Top = ChartTop
NChart.Left = ChartLeft
'Delink sereis from source
For Each ChartSeries In NChart.Chart.SeriesCollection
ChartSeries.XValues = ChartSeries.XValues
ChartSeries.Values = ChartSeries.Values
ChartSeries.Name = ChartSeries.Name
Next ChartSeries
'Set the X axis to correct values
Set XAxis = NChart.Chart.Axes(xlCategory, xlPrimary)
With XAxis
.CategoryType = xlTimeScale
.BaseUnit = xlMonths
.MajorUnit = 1
End With
Next SChart
End Sub

Related

Using named ranges with embedded formulas for excel chart data

I have two drop-down menus that list a range of dates. One date identifies the beginning of the range and the other the end. I also created two named ranges as follows:
chart_Dates=INDEX(Dates,MATCH(Home!$A$7,Dates,0)):INDEX(Dates,MATCH(Home!$A$9,Dates,0))
chart_Frequency=INDEX(Frequency,MATCH(Home!$A$7,Dates,0)):INDEX(Frequency,MATCH(Home!$A$9,Dates,0))
Dates, and Frequency from those formulas are named ranges with set boundaries. If I manually enter the y-values as "Home!chart_Frequency" and the horizontal values as Home!chart_Dates the macro works just fine. I can adjust the start and end dates using the drop-down menus and the graph updates accordingly.
However, the macro recorder doesn't translate those action into code. I've attempted the following code without success (there is no error generated but the graph only references the first cell in my range).
ActiveChart.SeriesCollection(1).Values = Range("chart_Frequency")
ActiveChart.SeriesCollection(1).XValues = Range("chart_Dates")
How do I get the code to replicate what I can do manually? Any advice is greatly appreciated!
Try this:
Sub testing()
Dim freqRange As String
Dim datesRange As String
Dim Name As Variant
For Each Name In ThisWorkbook.Names
If Name.Name = "chart_Frequency" Then
freqRange = Name.Value
ElseIf Name.Name = "chart_Dates" Then
datesRange = Name.Value
End If
Next Name
ActiveSheet.ChartObjects("Chart 1").Activate
ActiveChart.SeriesCollection.NewSeries
ActiveChart.FullSeriesCollection(1).Name = "=Sheet1!$B$1"
ActiveChart.FullSeriesCollection(1).Values = datesRange
ActiveChart.FullSeriesCollection(1).XValues = freqRange
End Sub
My chart didnt have any series so it adds a new series and it updates the Name, Values and XValues with no issues.
Here is the code I have right now. After it runs when I check the y-values and horizontal values on the graph itself and they are both blank.
'Create chart
Dim rng As Range
Dim cht As ChartObject
'Data range for the chart
Set rng = ActiveSheet.Range("$E$7:$F$501")
'Designates which cell to place the top left corner of the graph in
ActiveSheet.Range("N5").Select
'Create a chart
Set cht = ActiveSheet.ChartObjects.Add( _
Left:=ActiveCell.Left, _
Width:=360, _
Top:=ActiveCell.Top, _
Height:=216)
'Give chart some data
'I was using the line below to set the range but comment blocked it out and entered the suggested code
' cht.Chart.SetSourceData Source:=rng
Dim freqRange As String
Dim datesRange As String
Dim Name As Variant
For Each Name In ThisWorkbook.Names
If Name.Name = "chart_Frequency" Then
freqRange = Name.Value
ElseIf Name.Name = "chart_Dates" Then
datesRange = Name.Value
End If
Next Name
ActiveSheet.ChartObjects("Chart 1").Activate
ActiveChart.SeriesCollection.NewSeries
ActiveChart.FullSeriesCollection(1).Name = "=Home!$A$5"
ActiveChart.FullSeriesCollection(1).Values = datesRange
ActiveChart.FullSeriesCollection(1).XValues = freqRange
'Determine the chart type
cht.Chart.ChartType = xlLineMarkersStacked
'Remove Major Gridlines
cht.Chart.Axes(xlValue).MajorGridlines.Delete
'Sets the legend to the bottom of the graph
cht.Chart.SetElement (msoElementLegendBottom)
cht.Name = "Frequency_Chart"
'Add title and reference A5 for name
ActiveSheet.ChartObjects("Frequency_Chart").Activate
ActiveChart.SetElement (msoElementChartTitleAboveChart)
Application.CutCopyMode = False
Selection.Caption = "=Home!R5C1"

Power Point VBA - Change color of each bar

I need to change color of bar to red or green based on value.
Code works fine on Column chart but does not work on waterfall chart. It says "This action is not supported."
Please help making below code waterfall chart compatible:
Sub UpdateBarColor()
Dim p As Point
Dim s As Series
Dim c As Chart
Set c = ActiveWindow.Selection.ShapeRange(1).Chart
Set s = c.SeriesCollection(1)
For Each p In s.Points
Debug.Print p.Format.Fill.ForeColor.RGB
Next
End Sub
This changes the bars in a waterfall chart to be gray (that's the RGB)
You should be able to modify it to suit your needs
Set c = ActivePresentation.Slides(1).Shapes(1).Chart.SeriesCollection(1)
For Each p In c.Points
p.Format.Fill.ForeColor.RGB = RGB(169, 169, 169)
Next
Getting xvalues from the chart, try this
Dim arr As Variant
Dim i As Integer
With ActivePresentation.Slides(1).Shapes(1).Chart.SeriesCollection(1)
arr = .XValues
For i = LBound(arr) To UBound(arr)
Debug.Print arr(i)
Next
End With

How to set the XValues of a series in excel using VB.Net

I am trying to create a XY-Scatter chart with two col of data. The first col is X from cell A2 to A30, the second col is Y from cell B2 to B30 in the excel sheet.
I am able to create the chart but it is plotting with two series of data, it is taking col X as one series, and col Y as another series. Because I don't know how the syntax works in vb.net and I could not find documents on how to do this in vb.net, I got some ideas from vba documentations( it can be defined like this in vba :
Charts("Chart1").SeriesCollection(1).XValues =_Worksheets("Sheet1").Range("B1:B5")
and generated the following lines.
So I tried to set the XValues of the series with the line
xlApp.ActiveChart.SeriesCollection(1).XValues = xlWorkSheet.Range("$A$2", "$A$30")
xlApp.ActiveChart.SeriesCollection(1).Values = xlWorkSheet.Range("$B$2", "$B$30")
But it is throwing errors at me: COMException was unhandled on the above lines. I am not sure what I did wrong, so please help.
Here is the code block to generate the chart. basically, it's reading in a excel file and then creating a chart using the data in the file.
Private Sub Create_Chart_Click(sender As Object, e As EventArgs) Handles Create_Chart.Click
Dim xlApp As Excel.Application
Dim xlWorkBook As Excel.Workbook
Dim xlWorkSheet As Excel.Worksheet
xlApp = New Excel.ApplicationClass
'~~> Add a New Workbook
xlWorkBook = xlApp.Workbooks.Open("C:\Test_data.xlsx")
'Display Excel
xlApp.Visible = True
'~~> Set the relebant sheet that we want to work with
xlWorkSheet = xlWorkBook.Sheets("Sheet1")
With xlWorkSheet
'~~> Inserting a Graph
.Shapes.AddChart.Select()
'~~> Formatting the chart
With xlApp.ActiveChart
'~~> Make it a Line Chart
.ApplyCustomType(Excel.XlChartType.xlXYScatterSmoothNoMarkers)
'~~> Set the data range
xlApp.ActiveChart.SeriesCollection(1).Name = "X-Y"
xlApp.ActiveChart.SeriesCollection(1).XValues = xlWorkSheet.Range("$A$2", "$A$30")
xlApp.ActiveChart.SeriesCollection(1).Values = xlWorkSheet.Range("$B$2", "$B$30")
'~~> Fill the background of the chart
xlApp.ActiveChart.ChartArea.Format.Fill.ForeColor.ObjectThemeColor = _
Microsoft.Office.Core.MsoThemeColorIndex.msoThemeColorBackground1 '<~~ Grey
xlApp.ActiveChart.ChartArea.Format.Fill.ForeColor.TintAndShade = 0
xlApp.ActiveChart.ChartArea.Format.Fill.ForeColor.Brightness = -0.150000006
xlApp.ActiveChart.ChartArea.Format.Fill.Transparency = 0
xlApp.ActiveChart.ChartArea.Format.Fill.Solid()
xlApp.ActiveChart.SeriesCollection(1).Trendlines.Add()
xlApp.ActiveChart.SeriesCollection(1).Trendlines(1).Type = Microsoft.Office.Interop.Excel.XlTrendlineType.xlPolynomial
xlApp.ActiveChart.SeriesCollection(1).Trendlines(1).Order = 2
'xlApp.ActiveChart.SeriesCollection(1).Format.Line.Visible = Microsoft.Office.Core.MsoTriState.msoFalse
'~~> Make the corners of the Chart Rount
'.Parent.RoundedCorners = True
'~~> Removing lines and the back color so plot area shows char's background color
With .PlotArea
.Format.Fill.Visible = Microsoft.Office.Core.MsoTriState.msoFalse
.Format.Line.Visible = Microsoft.Office.Core.MsoTriState.msoFalse
End With
'~~> Removing the major gridlines
'.Axes(Excel.XlAxisType.xlValue).MajorGridlines.Format.Line.Visible = Microsoft.Office.Core.MsoTriState.msoFalse
'~~> Making the series line smooth
'.SeriesCollection(1).Smooth = True
'~~> Formatting the legend
With .Legend
With .Format.TextFrame2.TextRange.Font.Fill
.Visible = Microsoft.Office.Core.MsoTriState.msoTrue
.ForeColor.RGB = RGB(0, 0, 0)
.Transparency = 0
.Solid()
End With
With .Format.Fill
.Visible = Microsoft.Office.Core.MsoTriState.msoTrue
.ForeColor.ObjectThemeColor = Microsoft.Office.Core.MsoThemeColorIndex.msoThemeColorBackground1
.ForeColor.TintAndShade = 0
.ForeColor.Brightness = -0.25
.Transparency = 0
.Solid()
End With
End With
'~~> Change the format of Y axis to show $ signs
'.Axes(Excel.XlAxisType.xlValue).TickLabels.NumberFormat = "#,##0.00"
'~~> Underline the Chart Title
' .ChartTitle.Format.TextFrame2.TextRange.Font.UnderlineStyle = _
' Microsoft.Office.Core.MsoLineStyle.msoLineSingle
End With
End With
End Sub
Thanks
Please Try like This
xlApp.ActiveChart.SeriesCollection(1).XValues = "={""tes1"",""Test2""}"
or
MyVal="{""" & xlWorkSheet.range("A2") & """"
MyVal=MyVal & ",""" & xlWorkSheet.range("A30") & """}"
xlApp.ActiveChart.SeriesCollection(1).XValues = MyVal
XValues actually can be an Array for example:
Dim MyXVal() as string={"123","345","567"}
xlApp.ActiveChart.SeriesCollection(1).XValues = MyXVal
Wrapping the cells in quotes making it an array like suggested by Jamil does the job. A routine like below can help you:
Private Function WrapUp(ByVal Cells As Range) As String
Dim TmpWrap As String = ""
For Each Cell As Range In Cells
TmpWrap &= """" & Cell.Value & ""","
Next
Return "{" & Left(TmpWrap, Len(TmpWrap) - 1) & "}"
End Function
Now you can use something like this:
xlApp.ActiveChart.SeriesCollection(1).XValues = WrapUp(_Worksheets("Sheet1").Range("B1:B5"))
xlApp.ActiveChart.SeriesCollection(1).XValues =WrapUp(Globals.ThisAddIn.Application.Selection)

Get Chart Axis Value

I realise you can set the axis of a graph in VBA using
.MaximumScale =
.MinimumScale =
Is there a way to get the axis value?
I ask this because it would make it easier to automate a process that gets the axis of a chart, then adds a month to it (without setting the graph axis to automatic).
P.S.
I recorded a macro of changing the axis dates and it set the date values as a number like 40148 or 41609. What is this?
Try to step through the following snippet of code. It shows how to find Y axis value and how to change it. See some comments inside.
1st attempt for chart embedded in worksheet
Sub test_chart()
'get the chart for activesheet
Dim myCHR As Chart
Set myCHR = ActiveSheet.ChartObjects(1).Chart
'get Y axis of the chart
Dim myYA As Axis
Set myYA = myCHR.Axes(XlAxisType.xlValue)
'get the value
Debug.Print myYA.MaximumScale
Debug.Print myYA.MinimumScale
'the same in almost one line
With ActiveSheet.ChartObjects(1).Chart.Axes(xlValue)
Debug.Print .MaximumScale
Debug.Print .MinimumScale
'change the value
.MaximumScale = 10
End With
End Sub
2nd attempt for chart being separate sheet
Sub test_sheet_chart()
'get the chart for activesheet
Dim myCHR As Chart
Set myCHR = Sheets("All SIN 10 Pubs - Unique Users")
'get Y axis of the chart
Dim myYA As Axis
Set myYA = myCHR.Axes(XlAxisType.xlValue)
'get the value
Debug.Print myYA.MaximumScale
Debug.Print myYA.MinimumScale
'the same in almost one line
With Sheets("All SIN 10 Pubs - Unique Users").Axes(xlValue)
Debug.Print .MaximumScale
Debug.Print .MinimumScale
'change the value
.MaximumScale = 10
End With
End Sub

Using dynamic named range in VBA for scatter chart labeling

I'm trying to make a macro that will change the data labels on a scatter chart to the title of each point. Eg:
(source: wiseowl.co.uk)
In this case I would like the data labels to show the movie title. The code I used comes from this website, but my scatter chart has two series of data. I would like to use dynamic named ranges to tell the macro the range of cells where the names are, in my code the dynamic named ranges are FONames & BONames. Here's my code:
Sub CreateDataLabels()
'holds the entire film data series in the chart
Dim FilmDataSeries As Series
Dim FilmDataSeries2 As Series
'holds one cell at a time
Dim SingleCell As Range
'holds the full list of cells containing film names
Dim FilmList As Range
Dim FilmList2 As Range
'keeps track of which datapoint we're labelling
Dim FilmCounter As Integer
Dim FilmCounter2 As Integer
'The sheet in which the graph is on
Dim ws As Worksheet
Set ws = Worksheets("Datos Gráfico")
'set the counter to start at 1
FilmCounter = 1
FilmCounter2 = 1
'set a reference to the cells containing the list of films
Set FilmList = Range("FONames")
Set FilmList2 = Range("BONames")
'set a reference to the chart data series
Set FilmDataSeries = ws.ChartObjects(1).Chart.SeriesCollection(1)
Set FilmDataSeries2 = ws.ChartObjects(1).Chart.SeriesCollection(2)
'make sure data labels are turned on
FilmDataSeries.HasDataLabels = True
FilmDataSeries2.HasDataLabels = True
'loop over the cells in the list of films
For Each SingleCell In FilmList
FilmDataSeries.Points(FilmCounter).DataLabel.Text = SingleCell.Value
FilmCounter = FilmCounter + 1
Next SingleCell
For Each SingleCell In FilmList2
FilmDataSeries2.Points(FilmCounter2).DataLabel.Text = SingleCell.Value
FilmCounter2 = FilmCounter2 + 1
Next SingleCell
End Sub
I'm getting a 1004 error saying the dimension specified is not valid. When I replace FONames or BONames with an actual range of cells, Eg. Range("A5","A11"), everything works perfectly. How do I use those dynamic named ranges in my code?
What is the definition of your dynamic named range? I defined a named range for column A like so:
=OFFSET(Sheet1!$A$1,1,0,COUNTA(Sheet1!$A:$A)-1,1)
and it worked just fine.
For example :
'---------------------------------------------------------------------------
' In order to add label at scatter graph. You must selected a graph before.
' #param void
'---------------------------------------------------------------------------
Sub add_label_on_graph()
Dim Counter As Integer
Dim xVals As String
Dim reponse As Integer
If ActiveChart Is Nothing Then
reponse = MsgBox("Attention, vous devez au préalable sélectionner un graphique avant de lancer cette commande.", vbExclamation, "Information")
Exit Sub
End If
Application.ScreenUpdating = False
' Récupération de la range des données que l'on stocke dans la variable xVals.
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)
Do While Left(xVals, 1) = ","
xVals = Mid(xVals, 2)
Loop
' Ajoute un label à chaque point du graphique
For Counter = 1 To Range(xVals).Cells.Count
ActiveChart.SeriesCollection(1).Points(Counter).HasDataLabel = True
ActiveChart.SeriesCollection(1).Points(Counter).DataLabel.text = Range(xVals).Cells(Counter, 1).Offset(0, -1).Value
Next Counter
Application.ScreenUpdating = True
End Sub