I have some data, which I have charted as a scatter plot. And I would like to iterate over the points on the chart, and programmatically using VBA determine their
cluster
budget
actual
varaince values
I know I can get (4) variance using the following code, but I am not sure how to get values 1: cluster, 2: budget, 3: actual
Sub t3()
Dim chart As chart
Dim series As series
Dim values As Long
Dim p As Double
Set chart = ActiveChart
Set series = chart.SeriesCollection(1)
p = series.Points.Count
For i = 1 To p
values = series.values(i)
Debug.Print " ", i, values,
Debug.Print ""
Next i
End Sub
Using this information for 1, 2, 3, 4, I will check the cluster, and color the point accordingly A: blue, B, Red, C Green
Then I need to put a legend on the left of the chart with the 3 cluster values and their colors: A: blue, B, Red, C Green
chart
What I want
I chart, colored according to cluster: A, B, or C, where each of A, B, C only appear once in the legend. However the cluster is appearing for each point instead :(
Getting the other values
I'd like to do calculations on each point on the scatter chart, however I am not sure how to get access to the other values (budget and actual), as I am only showing cluster and variance on my chart now.
I simply offset from the start position and stored the values in variables, but I feel there must be a better way of accessing other data in a worksheet to use in a chart? Instead of removing it from the data (when you Select Data >> for the chart, can you hide it and then use it in calculations?
To get the chart only to show each cluster ID once, use this approach. I've added three columns to the data range, one headed by each cluster ID. Select E2:G7, enter this formula
=IF(E$1=$A2,$D2,NA())
and press Ctrl+Enter to fill the selected range with the formula.
Select the shaded range (select one region, then hold CTRL while selecting another) and insert a scatter chart.
Each cluster has a unique legend entry and a distinct format in the chart.
For your other calculations, use formulas in the worksheet.
I don't know why you're calculating your life with VBA when what you need is built right into Excel.
Related
I have a chart with xvalues Green, Blue, and Red and I want to only add Data Labels to the Red Values. But the colors aren't always in the same order, so I cant use some thing like: Chart.SeriesCollection(n).Points(j).DataLabel.Delete
I want to be able to do something like this: If Chart.SeriesCollection(n).Points(j).DataLabel.XValues = "Red" Then Chart.SeriesCollection(n).Points(j).DataLabel.Delete
But the .XValues command in vba doesnt work like that. Any suggestions? Thanks in advance.
In your description, you say that you want to add data labels to the Red XValues, yet your code deletes them. So I am going to assume that you want to delete the data labels for the Red XValues. Change the chart reference accordingly.
Dim sr As Series
Dim n As Long
Dim j As Long
With Worksheets("Sheet1").ChartObjects("Chart 1").Chart
For n = 1 To .SeriesCollection.Count
Set sr = .SeriesCollection(n)
sr.HasDataLabels = True
For j = 1 To sr.Points.Count
If sr.XValues()(j) = "Red" Then
sr.Points(j).DataLabel.Delete
End If
Next j
Next n
End With
No need for VBA.
Here's my setup. Categories, including maybe "Red" in column A, Values in column B, and chart labels in column C. In cell C2 I'm using a formula like this:
=IF(A2="Red","Label Text Here","")
so there is only text in that column if the X value is "Red".
My chart plots columns A and B of the data range. I added data labels, then formatted the data labels to use Values from Cells, and selected C2:C7 for the cells with labels.
The nice thing is it's dynamic. If the data changes, the labels update without having to add the labels back and rerunning any code.
I have a line chart in excel with data already set; I need to add a vertical line that moves according to the X values (month dates). For example for this month the line will move on the X value of "Jul-20"
Below I have attached the screenshot of the chart and the chart data. I have never had my hands on excel chart up until now and this chart has not been made by myself. Any help would be appreciated.
UPDATE 1
Thanks to #Steven Pomponio
when I try to add the new series for the vertical line, I do not have the "Y" values; see screenshot
UPDATE 2
added a new data source with values as 01/072020 and /01/07/2020 in cells J182 and K182; now I see a black dot on the left between the £10.0m and £ 20.0m Y values. If I change the verttical line data source chart type to be "Scatter with straight lines" then I do not even see the point.
If I change teh entire chart to be of Scatter with straight lines then I do see the Series Y Values but the whole chart change design and I do not want to do this.
UPDATE 3
Thanks to #Steven Pomponio I did it
Choose two cells in which you will have your target x value where the vertical line will appear, for this example I'll be using cells (E1) and (E2). Within cell (E1) you'll want to type in the formula =TODAY()-DAY(TODAY())+1 in order to get the first date of the current month. Cell (E2) can just be =E1.
In two cells, preferably next to them you will need to enter in the minimum and maximum bounds of one of your axes (Since you are already using a dual axes). It is important that these numbers are the same as what you set for the axis min & max bounds as this allows for you the line to properly span across the entire chart. Don't leave them on Auto.
Next, right click on your chart and click Select Data -> Add -> and add in the two dates (cells (E1) and (E2)) into the Series X Values, and the min and max bounds into the Series Y Values.
The final step is to make sure that the Chart type for this newly added series is selected as Scatter with Straight Lines and plotted on whichever axis you set the bounds equal to.
So I got Sheet1 with a table containing some data. To simplify let's say there's a column 'x' with some data and a column 'y' with some data. Every now and then more values are manually added to the table.
On Sheet2 I need Excel to automatically plot a graph only using the last 10 values in the table. So when more values are added the graph changes automatically to the new last 10 values. Is this possible?
Furthermore, let's say there's a third column 'z' that's always a constant value (for example to show some kind of a maximum for 'y' in the graph). How to make Excel automatically fill the cell with the number when the according 'x' and 'y' cells are filled? I know I could manually fill the 'z' column all the way down but I suspect that would screw up with plotting the last 10 values.
I'm using MS Excel 2013.
Thank you very much!
You'll need to create a chart using dynamic named ranges as the series data.
Start by setting up the data table with headings x, y and z.
Select x heading and click Insert > Table, make sure "My table has headers"
is checked then click OK
In column z, to set 20 as the autofilled value, add formula =20
Put your data in columns x and y
Create your chart based on columns x and y. This example creates a XY Plot.
Assuming you've only got one table in your workbook, it will be named "Table1".
Go to Formulas > Name Manager > New
xPlot: =OFFSET(Table1[[#Headers],[x]],COUNTA(Table1[z])-9,0,10,1)
Also create:
yPlot: =OFFSET(Table1[[#Headers],[y]],COUNTA(Table1[z])-9,0,10,1)
Right click on your chart and click Select Data...
Remove the Series that is there
Create a new Series
If your workbook was called Chart Example.xlsx, then set:
Series X values: 'Chart Example.xlsx'!xPlot
Series Y values: 'Chart Example.xlsx'!yPlot
Click OK and try adding more data.
A bit of background: I have a table which by using a combination of vlookup and index, goes through my main dataset and pulls out each row of data for a given month (in this case March). Each month will have a maximum of 15 entries, but may have less.
The image below is an example of the table for the month of March, which currently has 4 entries.
I want to create a column graph which is sourced from this table, that formats in a way such that if there is:
4 entries, it shows 4 evenly spaced columns
5 entries, it shows 5 evenly spaced columns
etc...
However, when I create this graph using the two yellow highlighted columns of data, I get 4 columns (in the graph) squashed over to the left side, and a whole bunch of blank space, as seen below:
Is there a way that I can create a graph that looks like the graph on the left, and that will add in new columns automatically as data appears in the table, without looking like the graph on the right?
Thanks
You could automatically updated your graph data ranges using VBA.
For example if your data range is in columns A and B of Sheet2 and your graph is Sheet1 you could use the following code:
Sub UpdateRange()
Dim LastRow As Long
Dim RngCount as Range
Set RngCount = Sheets("Sheet2").Range("A1:A10")
LastRow = Application.WorksheetFunction.CountA(RngCount)
Sheets("Sheet1").ChartObjects("Chart 1").Chart.SetSourceData Source:=Sheets("Sheet2").Range("A1:B" & LastRow)
End Sub
Graph with old data:
After data was added and the macro was run:
Starting with screenshot:
http://i.imgur.com/Isj9MER.png
(I'm a new user, can't post images)
Working for a call center. We have a program that tracks our time spent in various phone states (so when we're on calls, out to lunch, etc) that can export data for a given team and date range as a CSV.
I'm working on automating this report. The way it works is that the team lead will pull the CSV, copy-paste into another tab, and then I've got a bunch of array formula If functions and Indirect references to pull all the data as shown. The data analysis and everything is working great.
My problem is the graph. Right now, I've got column B with an If function that either outputs the agent's email (which is how the system tracks it) or "" if all emails have been used. The rest of the columns have If(B2="","", [relevant formula]). That way, we can have all the team leads with various (and fluctuating) team sizes use the same report with a simple copy-paste.
My problem is the stupid bar chart. It pulls data from rows 2-32 (A2:A32). Our current largest team is 28, and I left room for new hires showing up soon. My problem happens when I use data from one of our smaller teams. As you can see, even though the blank rows are filled with "" in every cell, it's still displaying those rows. In the chart. This means that with the smallest team (shown), the chart is half wasted whitespace.
Is there a way to make the column chart only show rows that have actual data in them?
One thing I tried was putting an Indirect reference for Series Values. So I had a cell (AA1) with {=MAX(IF(B2:B31="","",ROW(B2:B31)))}. That outputs the row number of the last non-blank row. Then for the Series Values I put =Indirect("Report!A2:A"&AA1), but Excel gave me an error saying the function was not valid. I guess you can only have an actual range (and not a formula) in the data input for a chart.
Excel 2016, by the way.
I come up with three possible solutions for this problem.
Convert your data table to a pivot table and use a pivot chart (currently only available in Windows version, sorry if you are using a Mac).
Use a bit of VBA to hide the empty rows.
Use a bit of VBA to modify the data displayed on the chart.
Sample Data Setup
Although you provided a screen shot of your data, it is not simple to convert that into a test case to demonstrate the three solutions. Therefore, I threw together this very simple set up.
Column A contains a list of possible "users".
Cell D1 is a user entry to change the contents of column B and C.
Column B contains the actual "users". It is calculated with =IF(A2<=$D$1,A2,"")
Column C contains the data that goes with the "users". It is calculated with =IF(B2<>"",10,"")
A chart is added to the sheet.
Below is a screenshot of the sample setup, where all potential users are included. (Note: It is Sheet1)
Below is a screenshot of the sample setup, where only potential users A through E are included.
The white space in the second image is the problem we are trying to address.
SOLUTION 1: Make a pivot table of the data
Select all of the pertinent data, in this case B1:C12.
Select Insert -> Pivot Table
In the Create Pivot Table dialog, make sure "New Worksheet" is selected, and click OK.
On the Pivot Table, place "User" field in Rows, and "Total" field in Values. Select the Value Field Settings... for the "Total" field and make sure it uses Sum.
In the Pivot Table, select the Row Labels drop down, Label Filters, Greater Than... . Type "" into the dialog and select OK.
From Pivot Table Tools -> Analyze, select PivotChart. Choose Bar Chart from the dialog.
Below is a screen shot of the Pivot Table.
On the tab with the data, change the last potential user from E to G. On the Pivot Table, refresh the data.
Below is a screen shot of the refreshed pivot table.
SOLUTION 2: Use VBA to hide empty rows
The below code is attached to a button made visible on the worksheet. (n.b. There are other ways to activate the code such as change events, but this will depend on a number of factors outside the scope of this answer).
Sub HideRows()
Dim AllCatRange As Range
Set AllCatRange = Worksheets("Sheet1").Range("B2:B12")
Dim iLoop As Long
For iLoop = 1 To AllCatRange.Rows.Count
If AllCatRange.Cells(iLoop, 1) = "" Then
AllCatRange.Cells(iLoop, 1).EntireRow.Hidden = True
Else
AllCatRange.Cells(iLoop, 1).EntireRow.Hidden = False
End If
Next iLoop
Set AllCatRange = Nothing
End Sub
Below is a screen shot of the data tab with the button added.
After clicking the button, it now looks like this ...
This code will expand rows when they contain data, and collapse rows when they do not.
A potential problem with this approach is that expanding/collapsing rows will change the size of the chart, if the chart lays over those rows.
SOLUTION 3: Use VBA to modify the chart
The below code is attached to a button, and used to modify the chart after the source data is changed.
Sub ModifyChart()
Dim AllCatRange As Range
Set AllCatRange = Worksheets("Sheet1").Range("B2:B12")
Dim lastRow As Long
lastRow = 1
Dim iLoop As Long
For iLoop = 1 To 11
If AllCatRange.Cells(iLoop, 1) <> "" Then
lastRow = lastRow + 1
End If
Next iLoop
Dim PlotCatRange As Range
Set PlotCatRange = Worksheets("Sheet1").Range("B2:B" & lastRow)
Dim PlotSerRange As Range
Set PlotSerRange = Worksheets("Sheet1").Range("C2:C" & lastRow)
Worksheets("Sheet1").ChartObjects(1).Chart.FullSeriesCollection(1).XValues = "=Sheet1!" & PlotCatRange.Address
Worksheets("Sheet1").ChartObjects(1).Chart.FullSeriesCollection(1).Values = "=Sheet1!" & PlotSerRange.Address
Set AllCatRange = Nothing
Set PlotCatRange = Nothing
Set PlotSerRange = Nothing
End Sub
Below is a screenshot of the data tab with the new button in place.
Below is a screenshot of the tab after clicking the button.
Wrap up
My personal preference is to use VBA to modify the chart after the data is modified, as this reflects what you would do manually.
I found a solution! Thanks largely to this page. Here's what I did:
I created made a named range using this formula: =OFFSET(Report!$B$1,1,0,COUNTIF(Report!$B$2:$B$30,"<>-"),1)
For that to work, I had to change all the empty cells to output "-" when empty in stead of "". I couldn't get COUNTIF to accept "<>""" or "<>" or any other weird tricks I tried. Using "-" was easier.
That makes a dynamic named range that changes size as I put data into the sheet. I named a similar range for everything I'm trying to chart (Approved Status, Call Ready, Not Ready). The chart was able to accept those names and now it's dynamically sized. If I only have three agents on the sheet, it shows three huge bars. With twenty, it shows twenty bars (exactly what I was looking for).
One other tip: I changed my first row to output "" when empty, so that COUNTIF(Report!$B$2:$B$30,"<>-") always returns at least 1 (otherwise you get annoying errors because you have a named range referencing a 0-length array).