VBA/Excel: Flow Chart Formula - excel

I'm sorry if this question is vague or answer exists, but struggling to find what I'm looking for.
I have created a sheet (VBA generated) where the user is required to fill in certain cells in a table. As multiple users are going to be editing the document, I want to automate a 'flow chart' type answer to standardize the document.
I.e. if in the first cell the user input is "No", then the remaining cells in the table default to "N/A". If the input is "Yes", then the user moves on to filling out the next box in the table. I was also going to use a drop down list to ensure the correct user input.
Does anyone have any suggestions of what I can research for a method to achieve this? Was thinking of having the cell formula, but this will delete after user input so wanted a method where the formula would remain even if the user input is deleted.
Thanks for any help.

The answer would be to use the worksheet_change event. However your problem is you are creating the sheet programatically. If you are using a template for your sheet you can just attach the code to the template, other wise you will have to create the code in your workbook and use the Workbook_sheetchange event
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
If Sh.Name = "sheet1" Then
If Target.Address = "$A$5" Then 'I'm assuming cell A5 is your first cell, change as required
If UCase(Sh.Range("a5")) = "NO" Then
Sh.Range("a10") = "#N/A" 'repeat for all cells you want to be NA
End If
End If
End If
End Sub

Related

Filling a range of cells with the same value using drop-down list

We all know that Excel has some counter-intuitive behaviours and it is, I believe, one of them:
When you select a range of few cells, starting your selection with the cell with data validation list and choose value from drop-down list: only one cell changes (the one containing drop-down list) instead of all selected.
Sometimes a few magic keyboard shortcuts such as CTRL+d, or combination of CTRL+' and CTRL+ENTER can fix this behaviour, but from my experience clients doesn't like to learn some new hacks, they just want to work everything in as simple way as possible.
I found even similar questions on SO e.g. here:
Adding same drop-down value to multiple cells simultaneously
I know that this is very simple code, but following few lines of code make my life easier, and I am sure this will help somebody too. Code in Worksheet module of course:
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
' MACRO FILLS THE WHOLE SELECTED RANGE
' WITH THE SAME VALUE USING DROP-DOWN LIST
' IN JUST ONE ACTIVE CELL
' change to false if all selected cells should be filled with value
Const FILL_VISIBLE_CELLS_ONLY As Boolean = True
' detecting if dropdown list was used
'
' I am using very clever solution by JvdV from SO
' ~~~~> stackoverflow.com/questions/56942551/
'
' If after edit we're in the same cell - drop-down list was used
' I know that may be also drag&drop or copy-paste
' but it seems no matters here.
' Warning! Should be add one more check if someone used
' 'accept OK character' next to formula bar, not implemented here.
'
If ActiveCell.Address <> Target.Address Then Exit Sub
' preventing error which sometimes occurs
If IsEmpty(ActiveCell.Value) Then Exit Sub
' fill a range or visible range with activeCell value
If FILL_VISIBLE_CELLS_ONLY Then
Selection.Cells.SpecialCells(xlCellTypeVisible) _
.Value = ActiveCell.Value
Else
Selection.Value = ActiveCell.Value
End If
End Sub
When you select a Range of more than one Cell, is is important to distinguish between the Active Cell (the single highlighted cell) and the Selection (the entire selected range, including the Active Cell).
Then:
Any Content (such as Values or Formulas) that you enter into the Formula bar is input into the Active Cell only, not the entire Selection.
Any Formatting changes you make are applied to the entire Selection, not just the Active Cell.
An exception is when entering an Array formula which applies to the Selection.
Since in this case you are making a change to content not formatting, it is applied to only the Active Cell.
When considering the above, it is not counterintuitive but entirely consistent with the design and operation of the software.
However, from a UX experience this may seem counterintuitive simply because it defies your expectation. This is kind of like a "customer is always right" type situation, which can be very frustrating for programmers, but is essential that it be understood. You can read more about the concept in a series of well-written articles on the topic at https://www.joelonsoftware.com/2000/04/10/controlling-your-environment-makes-you-happy/ (disclosure: the author of these articles happens to be integral to the development history of both Excel and SO, but it is linked here on merit). It was written more than 20 years ago and is still every bit as relevant today.

Hiding rows using a macro

I've got this project I'm working on where I have a "Data" sheet and am pulling the data in to "Sheet 2". I want a row on "Sheet 2" to automatically hide/unhide if there is no data within a specific cell in that row.
I am very new to macros and coding in general. I have tried looking this up but and following the tutorials on YouTube but none of them go too in-depth as to why you select certain things and I haven't had any luck getting them to work.
My question are.:
Would a macro that is effecting "Sheet 2" while I am on "Data", be placed within "Sheet 2" or within "ThisWorkbook"?
Before you write the macro, you need to select the drop downs "Workbook" and then I would assume you are detecting a change so would "SheetChange" be correct?
Will a macro detect a change within a cell that is hidden and then can that cell's row be unhidden?
Lastly, What the heck do I even write for the to detect a 0 and hide/unhide cells, I haven't gotten any of them to do anything so far?
Thank you for any help you guys can give.
To answer your questions:
Would a macro that is effecting "Sheet 2" while I am on "Data", be placed within "Sheet 2" or within "ThisWorkbook"?
It doesn't matter where you place the code unless the code is triggered by a built in event like Worksheet_Change(). In that case then it must reside within the worksheet that you are wanting to detect changes in. If it's not event driven then I would place the code in it's own module. To each their own though.
Before you write the macro, you need to select the drop downs "Workbook" and then I would assume you are detecting a change so would "SheetChange" be correct?
It would be appropriate if you wanted the code contained in that subroutine to be executed whenever there is a change to that worksheet. You could also trigger code through a user action like a button click or a double click or sheet activation, etc.
Will a macro detect a change within a cell that is hidden and then can that cell's row be unhidden?
Sure! Why not? As an example:
Private Sub Worksheet_Change(ByVal Target As Range)
'Detect if the change was in a cell we care about (it can be hidden, VBA don't care)
If Not Intersect(Target, Column(3)) Is Nothing Then
'Something changed in Column C! Unhide whatever row had the change
Target.EntireRow.Hidden = False
End If
End Sub
Lastly, What the heck do I even write for the to detect a 0 and hide/unhide cells, I haven't gotten any of them to do anything so far?
Using that last example to detect if a particular column experienced a change, detect if it was just a single cell, detect if that single cell is now a 0 and hide it's row:
Private Sub Worksheet_Change(ByVal Target As Range)
'Detect if the change was in a cell we care about (it can be hidden, VBA don't care)
If Not Intersect(Target, Column(3)) Is Nothing Then
'Something changed in Column C!
If Target.Cells.Count = 1 Then
If Target.Value = "0" Then
Target.EntireRow.Hidden = True
End If
End If
End If
End Sub
Stick that in whatever worksheet you wanting to detect the change. Change that first If so that you are only detecting changes in whatever range you anticipate that change to happen in (I chose Column C as an example).

Linking cells to each other; having cells update linked cells and vice versa

I have two ideas that could lead to more or less the same result.
I am trying to have similar cells or tables update themselves to whatever the most recent entry was in the linked system. For example, cell A1 is linked to cell B2 (in this system that I am trying to create). I would enter something like "1" or "Text" or whatever in A1 and the system would update cell B2 to whatever I entered in cell A1. However the opposite must work in the same manner. If I changed whatever in cell B2 to, say, "5", cell A1 would also display "5". Also, note that I have Excel 2013.
I need this to work with a cell or a table. So, getting to the possible solutions...
A subroutine in VBA that automatically updates all the linked cells or tables.
Some sort of mechanic unknown to me that uses VBA or another Excel aspect to do this, like a function or tool.
In your answer or solution, please be mindful to my inexperience with VBA. Thanks in advance.
You can try a worksheet change function:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = Range("A1").Address then
ActiveSheet.Range("B1").Value = ActiveSheet.Range("A1").Value
ElseIf Target.Address = Range("B1").Address then
ActiveSheet.Range("A1").Value = ActiveSheet.Range("B1").Value
End If
End Sub
Although this seems like it might create an infinite loop (the update from the change causes another change) it DOES work for me in Excel 2010..
There are other Worksheet functions you can try as well (e.g. Worksheet_SelectionChange)
This macro needs to be placed/entered as a WORKSHEET macro on the sheet where you desire to use it..it will not work in a Module.
To install:
1) Save your workbook as a macro-enabled file.
2) Close Excel, reopen file, and enable macro security
3) Type Alt-F11
4) In the project explorer view on the left, look for your sheet name. Double click it
5) In the code entry area on right (big window) paste the example code above
6) Return to your worksheet and try it.

How to detect if filter(s) changed on a worksheet?

In excel workbook project, how could we detect if the filters on some worksheet are updated?
Make sure that you have a formula (e.g. COUNT) that includes an entire column of the data. In the case of a Table, turn on the Total row.
When the filter is changed, the Excel calculation event will fire because of the formula and you can pick this up by inserting the following code into the sheet.
Private Sub Worksheet_Calculate()
MsgBox "Calculation"
End Sub
Your sheet will need to be designed to only have data, otherwise code will be needed to determine if the calculation event on the sheet did not originate due to a change in filter.
You will need to add code to pick up the filter values. Focus on the Filter class members like Citeria1, Criteria2, Operator, On, etc.
My case was an Excel database. I created a label indicating "number of filtered items" or "number of meeting instances", so that when you filter using dropdown filters this label will update. I didn't find any "filter change" event. I tried the method described above like the following:
Select a cell in your sheet that you are not willing to use
Set the formula of the cell to "=count(B:B)" or "=counta(C:C)" or any formula that depends on the entire column. Make sure that the cell is not in the same column
Set the format type of this auxiliary cell to "custom" and set the format to ";;;" so the cell contents will be invisible
In VBA, use the "worksheet calculate" event to execute your code
Private Sub Worksheet_Calculate()
' The commands and actions you want to execute when filter changes
End Sub
Now, you are done

MS-Excel: How to show the value of a combo box inside a locked cell

Background Details
I have an excel spreadsheet with Activex dropdown (combobox) objects which help the user to know what options are available. I did this because the data validation list dropdowns are way too small in font size, and were gathering a lot of complaints.
So my solution was to add combobox objects which allow the user to select from a range of options. However, I have to link the comboboxes to a cell with the linkedcell property, so that both the user and various formulas can see what has been chosen. I also set up the combobox to disappear when it's not in use (much in the same way as the data validation dropdown button only appears when you select the relevant cell).
Here is the problem:
I don't want the users to edit the value in the linked cell, so I make sure the linked cell is locked whenever the combobox is not selected:
Private Sub comboBox1_GotFocus()
Call unlockComboBoxTargetCell(comboBox1)
End Sub
the procedure above does this:
If (targetComboBox.LinkedCell <> "") Then
Dim targetCell As Variant
Set targetCell = Range(targetComboBox.LinkedCell)
If Not targetCell Is Nothing And targetCell.Locked <> False Then
unlockSheet (activesheet.Name)
targetCell.MergeArea.Locked = False
lockSheet (activesheet.Name)
End If
End If
Equivalent procedures exist to lock the target cell.
However, whenever you do a "Save As" action on the workbook, it seems that the linked and locked cells create a problem: Excel gives this error out of the blue:
"The cell or chart you are trying to change is protected and therefore read-only..."
This error comes up about twice or three times for each cell that is locked and is the linkedcell for a combobox.
Is there a good way to overcome this problem? Right now my best solution is to leave the cells unlocked and place data validation on the cell, so that if the user edits the cell they will at least be refused when they type something invalid. I could make sure that the combobox covers up the linked cell whenever it is selected, but sometimes that means having a very large, annoying combo box with a very tiny dropdown button on its right side.
Perhaps I am being a bit too particular about the user interface?
Thanks in advance for reading this long and involved post.
In the "lockSheet" procedure you have created, the code to 'protect' the worksheet needs an additional parameter, UserInterfaceOnly, set to true.
I imagine the LockSheet sub is something like this;
sub lockSheet(strSheetName as string)
thisworkbook.sheets(strSheetName).Protect
end sub
Try this:
sub lockSheet(strSheetName as string)
thisworkbook.sheets(strSheetName).Protect, UserInterfaceOnly=True
end sub
UserInterfaceOnly allows programmatic changes to the protected sheet.
Bill

Resources