Excel VBA triggering multiple events independently with dynamic scroll bars - excel

I have an excel workbook with three dynamic scroll bars in one tab of a workbook. I need to dynamically adjust the "max" value of the scroll bar based on the total lines of data in the source table. I have tried using the following code to achieve this; however this is adjusting the Max for all three scroll bars based on the value in cell S49, rather than separately adjusting Scrollbar 1, 2, and 3, based on the values in S49, S66, and S83, respectively:
Private Sub ScrollBar1_Change()
ActiveSheet.ScrollBar1.Max = Range("S49").Value
ActiveSheet.ScrollBar2.Max = Range("S66").Value
ActiveSheet.ScrollBar3.Max = Range("S83").Value
End Sub
How would I go about modifying this code in order to independently trigger the max value of each scroll bar based on a change in these cells?

Related

Excel Bar/Column graph showing blank cells

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).

Cannot apply filter on whole columns in Excel of exported DevExpress grid

I've exported a DevExpress grid in Excel. I want to be able to apply Excel filters on exported Excel sheet. Right now, the Excel export only allows me to apply filters on values between dark grey rows (rows that already have sums in them). See pics.
(Could this be because of the cell merge that happened in the formatting?)
I'm using a the following method to export:
Using link As New PrintableComponentLink(New PrintingSystem())
Dim options As New XlsxExportOptionsEx
options.ExportType = DevExpress.Export.ExportType.DataAware
options.TextExportMode = TextExportMode.Value 'Should set to Value to be able to have the numbers displayed as numbers instead of text.
options.AllowCellMerge = DefaultBoolean.False
link.Component = gcInvisibleDetail
link.CreateDocument(link.PrintingSystem)
link.ExportToXlsx(tbRepertoire.Text & "\Charges.xlsx", options)
End Using
The filter Cannot be apply to whole columns because there is a small indents on the top and at the bottom within the group footer row 7,9,15 and 17 in your example, empty rows in Excel emulate these indents.
These rows are added to support the WYSIWYG principe of the grid export.
You can review this topic:
Problem with XtraGrid Group Footer rending when exporting to excel

Is it possible to display a value based on presence of a cell border?

We are looking at doing some data import. There is a very large complex sheet which has some items grouped together using borders around cells in one column. The only indication that the items are grouped is the fact the group is surrounded by a border. Items ungrouped have no left and right border on the cell (may have top and bottom border as items above and below maybe grouped). As an initial exercise we want to add a column that displays true if an item is grouped. So if there is a border display a value like one. Does anyone know if this possible?
Use this custom VBA function:
Public Function GetBorder(ByVal Rng As Range, Idx As Integer) As Boolean
GetBorder = Rng.Borders(Idx).LineStyle <> xlNone
End Function
It takes two arguments: cell and index of border (7=left, 8=bottom, 9=top, 10=right). Returns TRUE or FALSE.
Now if you want to get info about bottom border of cell A1 you should:
=GetBorder(A1,8)

Create progress line using VBA excel

I try to create progress line by using VBA Excel command
I have all of data to define what progress is but
I don't know how to use VBA for creating progress line
for an example I tried to use connector line but It's seem not work
ActiveSheet.Shapes.AddConnector(msoConnectorStraight, 60, 405,800, 477).Select
Range("Z20").Select
ActiveSheet.Shapes.Range(Array("Straight Connector 11671")).Select
I would not use a shape for a progress bar, instead use the data bars conditional formatting on a cell where the cell value is updated by the code
Create a named range on one cell on the worksheet as, for example, "ProgressBar"
Adjust the width to suit your needs
Format the cell as a Percentage
Choose Conditional Formatting -> New Rule -> Format all cells based on their values
In the "Format Style" drop down, choose "Data Bar"
Select the "Show Bar Only" checkbox
In the "Type" drop downs, for Minimum and Maximum, choose "Number"
In the "Value" text boxes, enter 0 for Minimum, 1 for Maximum
Set the formatting as you wish
In the VB Editor, enter the code below
Sub UpdateProgressBar()
Dim Rows As Integer
Dim RowItem As Integer
Rows = 1000
For RowItem = 0 To Rows
Sheet1.Range("ProgressBar").Value = RowItem / Rows
Next RowItem
MsgBox "Done!"
Sheet1.Range("ProgressBar").Value = 0
End Sub
This will then update the value in the cell and the data bar will grow as the value increases.
You will need to adapt to your own code, but this should be a starting point.
some ways of doing a progress bar:
use the application.statusbar
or, use a userform, in wich you change the width property of any rectangle type (i use a button with nice picture font)
use a shape, from wich you change the size by altering its width property.
the hard part is more making it fast enough so it doesn't affect performance, and sometimes
when adding application.screenupdating=false in conjonction to doevents, it might blink... (or not)
if you need some code i can provide you a sample, and you can change it according to your needs

getting the values from the activechart using excel vba

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.

Resources