Excel VBA - Change tab colours based on user - excel

I'm setting up a spreadsheet for multiple users on my team for testing purposes.
The idea is that a spreadsheet gets passed around and any feedback whether it be a pass or fail is noted on the spreadsheet.
I've currently added validation on certain cells which are red until something is filled in by, let's call them the primary tester.
I've added further validation via VBA to check that all red cells have something entered, otherwise the tab colour will turn red.
My problem is that the spreadsheet then gets accessed by the secondary tester then I want the tab to stay red until they have passed or failed the work (again based on cell validation).
So I think I've found a solution whereby the
In a module I've got:
Public Function UserName()
UserName = Environ$("UserName")
End Function
Range("M5").Value = Environ("username")
In another worksheet I've got:
Set myRange3 = ActiveSheet.Range("P21")
If UserName <> Range("M5").Value Then
If UserName = Range("E15").Value Then
If Application.WorksheetFunction.CountA(myRange3) = 0 Then
ActiveWorkbook.ActiveSheet.Tab.Color = vbRed
Else
ActiveWorkbook.ActiveSheet.Tab.Color = xlColorIndexNone
End If
End If
End If
'M5 = Primary tester
'E15 = Secondary tester
I expect the primary tester to have filled in all their requirements, making the tab turn from Red to neutral.
I would then expect the secondary tester to open up the spreadsheet and notice that a tab has been flagged as Red, meaning they need to add their validation of pass/fail for the tab to go neutral.

Related

Repopulate Excel data to report specific information whenever a validation list option is switched

I'm working on an Excel financial template that calculates Standard Costs of Manufacturing, and on one tab I need to select from a list (Current, Increase/Decrease, NPI) to tell the calculator to use either a "standard value" or "manual entry", but coming from the same cell.
The Docs saved so that a new WB its set to 'Current' and displays the current 'List Price', 'Bulk Price', and 'Materials Cost' that are called from the 'ROI - Current' to the 'ROI - Target' tab where gross margin is calculated.
However, when you changes through the options, you need to rewrite the called values to whatever it needs to be. When you're doing process improvement, you doing this this a lot just to see how the numbers are moving. So I'm looking for a way to repopulate data a specific way every time a list option is switched.
What I'd like to accomplish is when 'Current' gets selected, the *List Price $(75), Bulk Price $(60), Materials Costs $(18), are called back from the ROI - C tab. (Preferable, nothing would be modifiable unless you changed options, like when using the Validation's error message; but not essential).
Then if Increase/Decrease is selected, List Price and Material Costs populates with the Current $ (but are modifiable fields). Here, Bulk Price is calculated as (CurTabBulk/CurTabList)xIncDecList then used to find the gross margin.
Then when 'NPI' is selected, if only List Price is modified, it calculates bulk price as 0.7 x List Price to assume Material Costs to get gross margin. So as an example of all this:
$75 List x 0.8 = $60 Wholesale X 0.3 = $18 Materials / $60 Wholesale * 100 = 70% Gross Margin (which is the NPI Market Forecast from the ROI - Current Tab building the ROI - Target Tab.)
I can code all this into the cells directly, but whenever you enter your own value, the code that exists in that cell is overwritten. So, I'm looking for a fast 'n dirty way to repopulate it a specific way every time the option is switched.
Thanks all!
UPDATE: So I made it this far at work today using Alt-F11:
I found this code that I put into the VBA:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$G$4" Then
Range("H4:I7").Value = "Select"
End If
End Sub
That will set all validation boxes H4:I7 to "Select" after choosing the Category, but I want each cell to update with the value rather than having to keep selecting them since it's the only value in the list.
I then found this VBA that will reset as I need, but have no idea how to make it work at all...
Sub ResetDropDowns()
Dim rngLists As Range
Dim ListCell As Range
On Error Resume Next
Set rngLists = Sheets("Entry Sheet").UsedRange.SpecialCells(xlCellTypeAllValidation)
On Error GoTo 0
If Not rngLists Is Nothing Then
For Each ListCell In rngLists.Cells
ListCell.Value = Range(Trim(Mid(Replace(ListCell.Validation.Formula1, ":", String(99, " ")), 2, 99))).Value
Next ListCell
End If
End Sub
Also, After the independent Category is chosen, I will need to enter values into the white boxes under Product 1 and 2. These boxes move around depending on what ROI category is selected: Current = No white; Adj/ Price =- List & Costs, NPI = List & GM. So, I'm hoping I can just reassign the code to accomplish calling the 'dependent recalculated Values' to the correct cells as changes are made.
Follow the URL for pictures of the spread sheet. This is the dependent list code that I put into the Validation Source (the result numbers in the image) for Product 1 List Price: =INDEX($E$43:$G$43,,MATCH($G$4,$E$42:$G$42,0))
Thanks all for the help.
https://www.excelforum.com/excel-programming-vba-macros/1387101-auto-populate-dependent-validation-list-with-fist-values-from-list.html
This solves it. Right click the tab to open the Code editor. Copy and past below to the window. Change Sheet1 and the Cells to what ever you need. Create a Macro button using an inserted Icon and right click it and select make macro.
Sub ResetDropDowns()
Dim rngLists As Range
Dim ListCell As Range
On Error Resume Next
Set rngLists = Sheets("Sheet1").Range("G21,H21")
On Error GoTo 0
If Not rngLists Is Nothing Then
For Each ListCell In rngLists.Cells
ListCell.Value = Range(Trim(Mid(Replace(ListCell.Validation.Formula1, ":", String(99, " ")), 2, 99))).Value
Next ListCell
End If
End Sub

Listbox value from userform intermittently not updating a cell

I have a userform in Excel. On loading, the form pulls data from the last row of a spreadsheet. There is a button on the form to print the form.
Prior to printing the form, it updates the selection in a list box for work order status to "Assigned" and then copies this status to the spreadsheet.
Sometimes the work order status in the spreadsheet is updated to "". It is like the selection of the list box is not being recognized. It is intermittent and I have not been able to determine a pattern.
This is the code
PrintWOForm.LB_WOStatus.value = "Assigned" 'Updates WO status to Assigned
To write this to the spreadsheet I have this code
'Update WO Status to Complete if there is a date in Date Completed
'Else update Status based on Selection in WO Status list box
If PrintWOForm.TB_DateComplete = "" Then
ws.Cells(cRow, 4) = PrintWOForm.LB_WOStatus.value
Else
ws.Cells(cRow, 4) = "Complete"
ws.Cells(cRow, 23) = PrintWOForm.LB_RepairCode.value
End If
It appears when I first open the form and use the print button, which updates the selection in the list box LB_WOStatus to "Assigned", it copies a blank into cRow 4.
If I manually select a status in the list box, that time and every time forward it will work correctly even when the status is selected by the code.
I am not sure this is best the fix for my issue, but so far it appears to work well. I added the below first line of code in front the prexesting second line of code.
Me.LB_WOStatus.SetFocus 'Must SetFocus to the WOStatus list box for the application to realize the next line of code
Me.LB_WOStatus.value = "Assigned" 'Updates WO status to Assigned
I did not try using the SetFocus method previously because I read on one of these websites that this was only used to set the focus to the object for the user of the form.

How to use Match (and replace) function when the source you are matching with is a dynamic (textbox) value (in userforms)?

I am extremely new to vba code/coding of any sort, and am trying to develop a loaning system for equipment within my discipline using excel sheets and forms.
Essentially, I want a cmdbutton_click to update the availability status of the specific piece of equipment to "On Loan" within the inventory list spreadsheet. The problem I am having however, is with the fact that the form user will enter the ItemID (number) which obviously will always be different. The item ID is the value of which I am looking to use the Match function with.
I have tried to refer to the form's ItemID text box using the match function, but it does not work whatsoever - I understand this is probably completely incorrect.
Set ws2 = Worksheets("MajorInventoryList")
ws2.Cells(WorksheetFunction.Match(me.txtID.value), 10) = "On Loan"
This brings about the Compile error: 'Argument not optional'
Is there any way to ameliorate this?
Use Find like this:
Set ws2 = Worksheets("MajorInventoryList")
Set fnd = ws2.Range("A:A").Find(Me.txtID.Value)
If Not fnd Is Nothing Then ws2.Cells(fnd.Row,10).Value = "On Loan"
This will look for Text Input in Column A and if found, will place "On Loan" in column J of that row in which the value exists.

Excel-VBA combo box value on form load

I have a VBA form which is used to enter data on a sheet. I am currently coding the form so as it will load any data already existing in the sheet back into the form.
For simple text strings it works perfectly.
e.g.
ReqSetup.ReqText = Application.Worksheets("Req Sheet").Range("F11").Value
However, I have some combo boxes, that on the form, when they are selected will enter a number in the corresponding cell.
Fail 1. - Run Time Error 380 - Invalid property value.
ReqSetup.MinPerKgCB = Application.Worksheets("Req Sheet").Range("C27").Value
Fail 2.
Dim MinPerKg As Range
Set MinPerKg = Application.Worksheets("Req Sheet").Range("C27")
ReqSetup.MinPerKgCB = MinPerKg
I'm obviously doing something really simple wrong but I can't work out what it is!!
Kind Regards!
I have some combo boxes, that on the form, when they are selected will
enter a number in the corresponding cell
Then you'd need to do the opposite of your code attempt, i.e.:
Worksheets("Req Sheet").Range("C27").Value = ReqSetup.MinPerKgCB.Value
That you'd better wrap inside a check that any combobox value is actually selected :
With ReqSetup.MinPerKgCB
If .ListIndex <> -1 Then Worksheets("Req Sheet").Range("C27").Value = .Value
End With

From a selected line in a chart, filter a table or pivot table

I am facing a challenge. In a chart with multiple lines, I would like to able when I click on a line or mouse over a line to see the corresponding datapoint in the the table or pivot table...So basically, filtering a table based on the element i click or select on a chart with my mouse.
Do you think that it is achievable ? What would be the methodology ? Is there a VBA code for this ? I have seen examples, but they are working on the oppiste way; click or mouse over an observation and the line is highlighted...
Thanks in advance
saskap
This is really complicated, you have to customize the code for each chart, this example code can be a starting point:
Dim p As Series
Dim pc As Long
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim ch As ChartObject: Set ch = Me.ChartObjects("Chart 1")
With ch
Dim s As Series: Set s = Nothing
On Error Resume Next: Set s = .Chart.SeriesCollection(Target.Value): On Error GoTo 0
If Not p Is Nothing And Not p Is s Then
p.Format.Fill.ForeColor.RGB = pc
End If
If Not s Is Nothing Then
Set p = s
pc = s.Format.Fill.ForeColor.RGB
With s
s.Format.Fill.ForeColor.RGB = RGB(255, 0, 0)
End With
End If
End With
End Sub
The first two rows are global variables that store which Series
object was highlighted last time and what was its original color,
this is needed to restore the original color when a different cell is
selected. Unfortunately global variables in VBA loose their value when the project is reset (e.g. the Stop button is pressed or an error occurs), so it is possible that this code colors a bar and then cannot color it back. If important, these information may be stored in invisible Cells or Chart data but that complicates the code.
The next line means that this is an event handler, a function that is called in response to a certain event, in this case when the selection changes on a certain worksheet (the one on which you insert this - you have to insert this into a worksheet module not a standard code module).
Next we look up the chart based on its name and assign it to a variable, which is of type ChartObject, so early binding will allows us to depend on the support of intellisense (if you type a . it shows members of interfaces).
Then we look up the Series inside the chart based on the name found in the newly selected cell's contents. Since we don't know if the new cell will have a valid name, we have to protect this line with disabling error handling and checking later if the s has a non-nothing value. - This part depends largly on the type of chart and how it represents data, it is possible that you will have to select data based on Series::XValues.
We check if there is a saved value for a previously highlighted bar and if it is different from the current selection, restore its original color.
Finally if the looking up the Series earlier was successful then s is non-null and we save the color of the current bar and highlight it with red fill.

Resources