After setting the name of a series in an Excel chart sheet with
ActiveChart.SeriesCollection(1).Name = dat.Cells(1, 2)
the chart legend shows the current value of the referenced cell but the 'series name' field in the 'Edit series' dialog is empty. Changes to the cells value don't show up in the chart legend.
Any advice on how to set the series name properly?
Assuming that dat is a Worksheet-Variable pointing to your data sheet:
Dim nameFormula As String
nameFormula = = "=" & "'" & dat.Name & "'" & "!" & "$B$1"
ActiveChart.SeriesCollection(1).Name = nameFormula
nameFormula will now contain "='Daten UVNIR'!$B$1". With that, the name of the series is set to the cell B1 and not a fixed string (I always recommend to use intermediate variables, it helps debugging).
I would strongly recommend not to use ActiveChart. Instead, use something like
Dim co As ChartObject, ch As Chart, ser As Series
Set co = dat.ChartObjects(1)
Set ch = co.Chart
Set ser = ch.SeriesCollection(1)
(...)
ser.Name = nameFormula
(you can use the name of the ChartObject instead of 1 as index)
Update: Haven't noticed that you are working with a Chart Sheet. In that case, use
Dim ser As Series
set ser = Sheets("Chart1").SeriesCollection(1)
Try this code:
ThisWorkbook.Sheets("Chart1").SeriesCollection(1).Name = "=" & dat.Cells(1, 2).Address(External:=True)
Related
I am trying to program a vba code to draw a smooth curve among control points as showing in the figure below:
This is part of the code, is there any suggest how to curve fitting among control points (polynomial regression). I just want guide or advice how to make this code to work.
Public Sub TestLinest()
Dim x
Dim i As Long
Dim evalString As String
Dim sheetDisplayName As String
Dim polyOrder As String
' this is whatever the name of your sheet containing data:
sheetDisplayName = "Sheet1"
' this gets the index of the last cell in the data range
i = Range(sheetDisplayName & "!A17").End(xlDown).Row
' Obviously change this depending on how many polynomial terms you need
polyOrder = "{1,2,3}"
evalString = "=linest(" & sheetDisplayName & "!E6:E" & i & ", " & sheetDisplayName & "!D6:D" & i & "^" & polyOrder & ")"
x = Application.Evaluate(evalString)
Cells(3, 8) = x(1)
Cells(4, 8) = x(2)
Cells(5, 8) = x(3)
Cells(6, 8) = x(4)
End Sub
Just a suggestion; Not sure about VBA code (need to explore).
To get a polynomial curve in your chart, you can simply follow these steps;
Right click on data points on scatterplot
Click on "Format Trendline"
Under Trendline options, you will see "Polynomial" with order range
of 2 to 6.
I am writing a vlookup function and I want to reference the last tab in a another workbook, rather than the tab name as it changes daily.
To move to the last tab in the workbook I have
Sheets(Sheets.Count).Select
Is it possible to reference this in the a VLOOKUP? (left a blank where the worksheet should be)
"=VLOOKUP(RC[133],'[Unavista UTI Lookup December2019.xlsm]" "'!C4:C7,4,0)"
This is just off the top of my head (untested), but maybe something like this
Dim wbData as Workbook
Set wbData = Workbooks.Add("Unavista UTI Lookup December2019.xlsm")
ActiveWorkbook.Worksheets("Sheet1").Range("A1").Formula = "=VLOOKUP(RC[133],[" & wbData.Name & "]" & wbData.WorkSheets(wbData.WorkSheets.Count).Name & "!C4:C7,4,0)"
wbData.Close False
Alternatively, using the .Open method:
Dim wbData as Workbook
Set wbData = Workbooks.Open(Filename:="Unavista UTI Lookup December2019.xlsm", ReadOnly:=True)
ActiveWorkbook.Worksheets("Sheet1").Range("A1").Formula = "=VLOOKUP(RC[133],[" & wbData.Name & "]" & wbData.WorkSheets(wbData.WorkSheets.Count).Name & "!C4:C7,4,0)"
wbData.Close False
Adjust Sheet1 and A1 to your needs
But still, you would need to trigger this code on an event of some sort, which isn't clear to me yet.
The Function I am at is below;
Currently i am changing the date of the worksheet which the vlookup is referencing. So the below shows "Dec 9" from yesterday. Once the new tab gets created today in the file "Unavista UTI Lookup December2019" - It will show "Dec 10"
ActiveCell.FormulaR1C1 = _
"=VLOOKUP(RC[133],'[Unavista UTI Lookup December2019.xlsm]Dec 9'!C4:C7,4,0)"
What I am trying to do is find a way for the code to automatically change this to todays date. Speaking with someone at work we tried the below
Dim DayValue As String
Dim FormulaString As String
DayValue = Format(Date, "mmm d")
Range("E2").Select
FormulaString = "=VLOOKUP(EH2,'[Unavista UTI Lookup December2019.xlsm]" & DayValue & "' !$D:$G,4,0)"
The formula isn't bringing back any error, but unfortunately the lookup isn't doing anything, and just bringing back empty cells.
If anyone can resolve this, as i've tried numerous things and still not been able to get it to work.
I would assume that your were applying the formula with a line like this:
Range("E2").Formula = FormulaString
however when I tried that line, it returned an error as your line has one blank space in excess, as the syntax for a link with another workbook should be:
'[WorkbookName]WorksheetName'!Range
and your line has:
'[WorkbookName]WorksheetName' !Range
Therefore instead of this:
FormulaString = "=VLOOKUP(EH2,'[Unavista UTI Lookup December2019.xlsm]" & DayValue & "' !$D:$G,4,0)"
use this:
FormulaString = "=VLOOKUP(EH2,'[Unavista UTI Lookup December2019.xlsm]" & DayValue & "'!$D:$G,4,0)"
Range("E2").Formula = FormulaString
However, in order to ease the maintenance of the procedure I suggest to use a constant, try this procedure:
Sub Formula_Today()
Const kFml As String = "= VLOOKUP( RC[133]," & _
"'[Unavista UTI Lookup December2019.xlsm]#TODAY'!C4:C7, 4, 0 )"
Dim sFml As String
sFml = Replace(kFml, "#TODAY", Format(Date, "mmm d"))
With ThisWorkbook.Worksheets("DATA")
.Range("E2:E10").FormulaR1C1 = sFml
End With
End Sub
Before adding the new worksheet
After adding the new worksheet and applying the Formula_Today procedure
I made this code a year or so ago and it's been working fine. Recently, however, it broke. I am assuming there was a Windows update that changed the way Excel's macros worked with charts. The pertinent sections of my code perform the following:
Create an XY Scatter chart on a "prep" worksheet
Create a trendline for each data series on the XY Scatter
Parse each trendline text for slope and R^2, coping them as text onto another "summary" worksheet
What I've found is that Step 1 and 2 work fine, but when I try to parse the trendline text (expecting something like y = 0.0289x + 143), I get an empty string (see the commented out MsgBox, below). What's weirder is that when the Macro finishes (or fails) the chart updates and the text shows normally.
' Create the graph for the linear part of the data set
Worksheets(PrepSheetName).Activate
ActiveSheet.Shapes.AddChart.Select
ActiveChart.ChartType = xlXYScatterSmooth
ActiveChart.SetSourceData Source:=Range("$B$19:$G$38")
' ActiveChart.Name = "Linear"
'MsgBox "Past linear creation"
' Add each data set to the chart individually
ActiveChart.PlotArea.Select
For i = 1 To 5
' Construct a string like ='Data'!$C$19:$C$38
YValues = "='" & PrepSheetName & "'!$" & DSMeasCol(i) & "$"
YValues = YValues & CStr(PrepDataStart) & ":$" & DSMeasCol(i) & "$"
YValues = YValues & CStr(PrepDataEnd(i))
' Construct a string like ='Data'!$C$19:$C$38
XValues = "='" & PrepSheetName & "'!$" & DSCmdCol(i) & "$"
XValues = XValues & CStr(PrepDataStart) & ":$" & DSCmdCol(i) & "$"
XValues = XValues & CStr(PrepDataEnd(i))
' Give the chart values
ActiveChart.SeriesCollection(i).Values = YValues
ActiveChart.SeriesCollection(i).XValues = XValues
' Create a trendline for the chart
Dim TL As Trendline
Set TL = ActiveChart.SeriesCollection(i).Trendlines.Add(Type:=xlLinear, Forward:=0, _
Backward:=0, DisplayEquation:=1, DisplayRSquared:=0, _
Name:="LC" & CStr(i) & " Trend")
TL.DisplayEquation = True
TL.DisplayRSquared = False
' Exract the trendline formula
Dim Eqn As String
TL.Select
'MsgBox "Trendline Text: " + TL.DataLabel.Text
Eqn = Split(TL.DataLabel.Text, "=")(1)
' ... and place it on the coversheet ...
CoverSheet.Cells(CSResults(i), CSFitSlope).Value = Split(Eqn, "x")(0)
CoverSheet.Cells(CSResults(i), CSFitOffset).Value = Split(Eqn, "x")(1)
'Find the RSquared of the Trendline
TL.DisplayEquation = False
TL.DisplayRSquared = True
TL.Select
Eqn = TL.DataLabel.Text
Eqn = Split(TL.DataLabel.Text, "=")(1)
' ... and place it on the coversheet ...
'CoverSheet.Cells(CSResults(i), CSFitCorr).Value = Eqn
Next i
If I try to run diagnostic code to parse the tredline datalabel text after running the macro the first time, it sees the text. When running the diagnostic code, though, I can't change the type of trendline data that is shown. I would expect, for example, that if I run:
TL.DisplayEquation = True
TL.DisplayRSquared = False
MsgBox "Should show Equation."
TL.DisplayEquation = False
TL.DisplayRSquared = True
MsgBox "Should show R^2."
... that I should see the trendline data label only show the equation when the first message box appears and the second message box should freeze the screen such that only the the R^2 is showing. When I run code like this, though, I find that my assumption is not true: The datalabel stays frozen until the macro completes, even with ScreenUpdating = True It seems like my charts aren't updating when the macro runs, but only updates at the end.
I've tried putting DoEvents and Application.Recalculate after creating the trendline, but it just causes my Excel to crash. Adding Application.ScreenUpdating = True or False doesn't seem to help, either...
Any ideas? I'm at a total loss...
Please let me know if I haven't provided enough information or anything is unclear.
Thanks!
I ended up using chillin's suggestion and used LinEst. It seems this is a bug in how Excel handles Chart DataLabels during Macro execution, as per this thread. To summarize, my code is almost the same as above, but with the following change using LinEst instead of parsing the Trenline's DataLabel:
' Create a trendline for the chart
Dim TL As Trendline
Set TL = ActiveChart.SeriesCollection(i).Trendlines.Add(Type:=xlLinear, Forward:=0, _
Backward:=0, DisplayEquation:=1, DisplayRSquared:=0, _
Name:="LC" & CStr(i) & " Trend")
' Generate the trendline constants and place them on the summary sheet
CoverSheet.Cells(CSResults(i), CSFitSlope).Value = "=INDEX(LINEST(" & YValues & "," & XValues & ",TRUE, TRUE), 1)"
CoverSheet.Cells(CSResults(i), CSFitOffset).Value = "=INDEX(LINEST(" & YValues & "," & XValues & ",TRUE, TRUE), 1,2)"
CoverSheet.Cells(CSResults(i), CSFitCorr).Value = "=INDEX(LINEST(" & YValues & "," & XValues & ",TRUE, TRUE), 3)"
I have a spreadsheet that has several charts. I house the data for the charts on 3 other sheets. I am trying, so far without success, to update the charts to cover additional data as I add it.
I have tried several things based on what I've seen around on the web. I've tried setting a range like
Set SourceRange1 = Split(Join((GetArray(Sheets(1).Range("P6:" & GetLetterFromNumber(Sheets(1).Cells(6, Sheets(1).Columns.Count).End(xlToLeft).Column) & "6"))), "|"), "|")
Set SourceRange2 = GetArray(Sheets(2).Range("P6:" & GetLetterFromNumber(Sheets(2).Cells(6, Sheets(2).Columns.Count).End(xlToLeft).Column) & "6")))
Set SourceRange3 = Application.Union(Worksheets(3).Range("P5", Sheets(3).Cells(5, Sheets(1).Columns.Count).End(xlToLeft)), Sheets(3).Range("P6", Sheets(3).Cells(6, Sheets(3).Columns.Count).End(xlToLeft))).Value
and then assigning it to the chart like this:
ActiveChart.SeriesCollection(1).Values = SourceRange1
ActiveChart.SeriesCollection(2).Values = SourceRange2
ActiveChart.SeriesCollection(3).Values = SourceRange3
This gives me the range P5:x5 currently, but it doesn't set the chart series.
Just for reference, the GetArray is a function that I created:
Function GetArray(Range1 As Range)
Dim Test() As String, cell As Range, i As Integer
i = 0
ReDim Test(0)
For Each cell In Range1
ReDim Preserve Test(i)
Test(i) = cell.Value
i = i + 1
Next cell
GetArray = Test
End Function
And so it the GetLetterFromNumber:
Function GetLetterFromNumber(Number)
GetLetterFromNumber = Split(Cells(1, Number).Address(True, False), "$")(0)
End Function
With the current setup like the Set SourceRange1, I get a
Compile error: Can't assign to array
I get the same error with both of the others as well. I have SourceRange1-3 setup like Dim SourceRange1()
If I set them up like Dim SourceRange1 then I get:
Run-time error '13':
Type Mismatch
On all three.
If I assign the SeriesCollection directly like:
ActiveChart.SeriesCollection(1).Values = GetArray(Sheets(1).Range("P6:" & GetLetterFromNumber(Sheets(1).Cells(6, Sheets(1).Columns.Count).End(xlToLeft).Column) & "6"))
ActiveChart.SeriesCollection(2).Values = GetArray(Sheets(2).Range("P6:" & GetLetterFromNumber(Sheets(2).Cells(6, Sheets(2).Columns.Count).End(xlToLeft).Column) & "6"))
ActiveChart.SeriesCollection(3).Values = GetArray(Sheets(3).Range("P6:" & GetLetterFromNumber(Sheets(3).Cells(6, Sheets(3).Columns.Count).End(xlToLeft).Column) & "6"))
The it assigns 0 to all the values when for SeriesCollection(1) they should be:
(20,30,40,50,60,10,20,30,40)
I'm sure I'm missing something simple, I just don't know what. If I've missed putting something in my description let me know and I can add it.
Otherwise, all the help I can get will be appreciated.
In order for the Chart.SeriesCollection(1).Values to be connected dynamically with the Range use something like the line below (assuming your SourceRange1 range is defined correclty):
ActiveChart.SeriesCollection(1).Values = "=" & SourceRange1.Address(True, True, xlA1, xlExternal)
When working with Charts you might also consider using:
Dim Cht as Chart
Dim Ser as Series
Set Cht = ActiveChart
Set Ser = Cht.SeriesCollection(1)
With Ser
.Values = "=" & SourceRange1.Address(True, True, xlA1, xlExternal)
End With
I have dynamically changing table in Excel and need for a bubble chart to automatically be based off the table even when data changes. The key is that each ROW in the table represents a series to be in the bubble chart.
Series A 5 10 5%
Series B 4 8 3%
.
.
I understand how to use dynamic ranges without VBA for bubble but since I need to create/update dynamic series from my research I need to use VBA. I have written the following code but am getting error message that the chart can't be found even though I have checked 50 times I have the correct name
I need the VBA code, to reference the Existing chart on Sheet11, and update it (add/edit) based on table.
My code:
Public Sub CreateMultiSeriesBubbleChart()
Dim bubbleChart As ChartObject
Set bubbleChart = Sheet11.ChartObjects("Chart 13") ''verified i have chart 13 on sheet 11
Dim r As Integer
For r = 2 To 201
With bubbleChart.Chart.SeriesCollection.NewSeries
.Name = "=" & Sheet11.Cells(r, 1).Address(External:=True)
.XValues = Sheet11.Cells(r, 2).Address(External:=True)
.Values = Sheet11.Cells(r, 3).Address(External:=True)
.BubbleSizes = Sheet11.Cells(r, 4).Address(External:=True)
End With
Next
bubbleChart.Chart.SetElement (msoElementPrimaryCategoryAxisTitleAdjacentToAxis)
bubbleChart.Chart.Axes(xlCategory, xlPrimary).AxisTitle.Text = "=" & Sheet11.Cells(1, 2).Address(External:=True)
bubbleChart.Chart.SetElement (msoElementPrimaryValueAxisTitleRotated)
bubbleChart.Chart.Axes(xlValue, xlPrimary).AxisTitle.Text = "=" & Sheet11.Cells(1, 3).Address(External:=True)
''bubbleChart.Chart.Axes(xlValue).MinimumScaleIsAuto = True
''bubbleChart.Chart.Axes(xlValue).MaximumScaleIsAuto = True
''bubbleChart.Chart.SetElement (msoElementPrimaryCategoryGridLinesMajor)
End Sub
Unfortunately, this code provides error on Set bubbleChart line saying 'Application defined or Object defined error'. I can use very similar code to create a new chart so I figure the rest works properly but I can't reference existing chart which is what I need to be able to do
You need to change the way your referencing your sheet. Use Sheets("Sheet11") instead of Sheet11
Try this:
Set bubbleChart = Sheets("Sheet11").ChartObjects("Chart 13")
Note that you can call the name or the index this way. For example:
Sheets("MySheetName").select
or
Sheets(11).select