Vba macro excel: How to hide rows if cell equal FALSE - vba

I have a project which requires Excel to hide rows on a separate sheet(within the same workbook) after user selects specific options on the activesheet. The macro is linked to a button, when clicked rows will be hidden on the separate sheet, and the whole process occurs in the background. If the user want to check the table with hidden rows they'd need to navigate to that separate sheet to see the result.
Image explanation:
http://postimg.org/image/ek6981vg1/
Worksheets("Input- Select Pens") --> active sheet where has the button
Worksheets("Input- Pen") --> separate sheet where has the hidden rows
I have tried several methods, but none of them worked:
Method 1:
Sub selectPens()
Dim c As Range
Application.EnableEvents = False
On Error Resume Next
For Each c In Range("E6:E35")
If c.Value = "FALSE" Then
Worksheets("Input- Pen").c.EntireRow.Hidden = True
ElseIf c.Value = "TRUE" Then
Worksheets("Input- Pen").c.EntireRow.Hidden = False
End If
Next c
On Error GoTo 0
Application.EnableEvents = True
End Sub
Method 2:
Sub selectPens()
Dim i As Long
Set wselect = Sheet11
With wselect
For i = 6 To 35
If ActiveSheet.Cells(i, 5).Value = "FALSE" Then
.Range("i:i").EntireRow.Hidden = True
' .Rows(i).EntireRow.Hidden = True
ElseIf ActiveSheet.Cells(i, 5).Value = "TRUE" Then
' .Rows(i).EntireRow.Hidden = False
.Range("i:i").EntireRow.Hidden = False
End If
Next i
End With
End Sub
I would be greatly appreciated for any help.
Many thanks!

Sub selectPens()
Dim i As Long, wsselect
Set wselect = Sheet11
For i = 6 To 35
'EDIT
wselect.Rows(i).Hidden = (ActiveSheet.Cells(i, 5).Value = False)
Next i
End Sub

Related

Excel keeps crashing with Worksheet_selectionChange

I am running two VBA formulas.
The first hides all cells with empty information the first column.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim c As Range
On Error Resume Next
Application.ScreenUpdating = False
For Each c In Range("A3:A49")
If c.Value = vbNullString Then
c.EntireRow.Hidden = True
End If
Next c
For Each c In Range("A3:A47")
If c.Value <> vbNullString Then
c.EntireRow.Hidden = False
End If
Next c
Application.ScreenUpdating = True
End Sub
The second Formula strings data together and placeses this information in the next cell that is empty (aka the first hidden cell) when the button is clicked.
Option Explicit
Dim iwsh As Worksheet
Dim owsh As Worksheet
Dim output As String
Dim i As Integer
Sub Copy()
Set iwsh = Worksheets("Budget")
Set owsh = Worksheets("Release Burnup")
i = 3
While owsh.Cells(i, 1) <> ""
i = i + 1
Wend
output = "R" & iwsh.Cells(13, 2).Value & "-S" & iwsh.Cells(14, 2).Value
owsh.Cells(i, 1) = output
ActiveSheet.EnableCalculation = False
ActiveSheet.EnableCalculation = True
End Sub
Previously, this has been causing no problem... Something has happened that is causing the workbook to crash anytime I try to delete information out of one of the cells with the new data.
PS: This is the list of my other formulas. maybe there is something in these that is interacting with the formentioned code?
Private Sub NewMemberBut_Click()
'causes userform to appear
NewMember.Show
'reformats button because button kept changing size and font
NewMemberBut.AutoSize = False
NewMemberBut.AutoSize = True
NewMemberBut.Height = 40.25
NewMemberBut.Left = 303.75
NewMemberBut.Width = 150
End Sub
'Similar code to the problematic code in question, but this one works fine
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim c As Range
On Error Resume Next
Application.ScreenUpdating = False
For Each c In Range("A3:A35,A41:A80")
If c.Value = vbNullString Then
c.EntireRow.Hidden = True
End If
Next c
For Each c In Range("A3:A35,A41:A80")
If c.Value <> vbNullString Then
c.EntireRow.Hidden = False
End If
Next c
Application.ScreenUpdating = True
End Sub
'Code for UserForm
Option Explicit
Dim mName As String
Dim cName As String
Dim mRole As String
Dim cRole As String
Dim i As Integer
Dim x As Integer
Dim Perc As Integer
Dim Vac As Integer
Dim Prj As Worksheet
Dim Bud As Worksheet
Private Sub NewMember_Initialize()
txtName.Value = ""
cboRoleList.Clear
Scrum.Value = False
txtPercent.Value = ""
txtVacation.Value = ""
txtName.SetFocus
End Sub
Private Sub AddMember_Click()
If Me.txtName.Value = "" Then
MsgBox "Please enter a Member name.", vbExclamation, "New Member"
Me.txtName.SetFocus
Exit Sub
End If
If Me.cboRoleList = "Other" And Me.txtCustomRole = "" Then
MsgBox "Please provide a role name.", vbExclamation, "Other Role"
Exit Sub
End If
If Me.cboRoleList.Value = "" Then
MsgBox "Please select a Role.", vbExclamation, "Member Role"
Me.cboRoleList.SetFocus
Exit Sub
End If
If Me.cboRoleList <> "Other" And Me.txtPercent = "" Then
MsgBox "Please select a valid percentage to be applied to this sprint.", vbExclamation, "Sprint Percent"
Me.txtPercent.SetFocus
Exit Sub
End If
If Me.txtPercent.Value > 100 And Me.txtPercent <> "" Then
MsgBox "Please select a valid percentage to be applied to this sprint.", vbExclamation, "Sprint Percent"
Me.txtPercent.SetFocus
Exit Sub
End If
If Me.txtVacation.Value = "" Then
Me.txtVacation.Value = 0
End If
Dim i As Long
Set Prj = Worksheets("Project Team")
Set Bud = Worksheets("Budget")
Prj.Activate
i = 5
x = 1
If Me.cboRoleList.Value = "Other" Then
i = 46
End If
While Prj.Cells(i, 1) <> ""
i = i + 1
Wend
If cboRoleList = "Other" Then
Cells(i, x).Value = txtCustomRole.Value
End If
If cboRoleList <> "Other" Then
Cells(i, x).Value = cboRoleList.Value
End If
x = x + 1
Cells(i, x).Value = txtName.Value
x = x + 1
If Me.cboRoleList.Value <> "Other" Then
Cells(i, x).Value = txtPercent.Value
End If
Unload Me
End Sub
Private Sub CloseBut_Click()
Unload Me
End Sub
Change the event driven Worksheet_SelectionChange to Worksheet_Change and isolate further by only processing when something changes in A3:A49.
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("A3:A49")) Is Nothing Then
On Error GoTo safe_exit
Application.EnableEvents = False
Application.ScreenUpdating = False
Dim c As Range
For Each c In Intersect(Target, Range("A3:A49"))
c.EntireRow.Hidden = CBool(c.Value = vbNullString)
Next c
End If
safe_exit:
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
Caveat: A Worksheet_Change is not triggered on the change in a cell from the cell's formula. Only by typing, deleting or dragging a cell's contents. Adding or removing a formula will trigger it but not when a formula's result changes from another value somewhere in the workbook changing. This should not affect you as no formula can return vbNullString but it is worth mentioning for others.

Excel VBA: update cell based on previous cells change

I'm working on an Excel worksheet and using VBA to complete and update information on the cells.
There are seven columns in the Excel table. Three of them are drop-down lists with Data Validation, which I used the following VBA code to fill them.
Private Sub TempCombo_KeyDown(ByVal _KeyCode As MSForms.ReturnInteger, _ ByVal Shift As Integer)
'Ocultar caixa de combinação e mover a próxima célula com Enter e Tab
Select Case KeyCode
Case 9
ActiveCell.Offset(0, 1).Activate
Case 13
ActiveCell.Offset(1, 0).Activate
Case Else
'Nada
End Select
End Sub
These columns also work with autocomplete, using the code below:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim str As String
Dim cboTemp As OLEObject
Dim ws As Worksheet
Dim wsList As Worksheet
Set ws = ActiveSheet
Set wsList = Sheets(Me.Name)
Application.EnableEvents = False
Application.ScreenUpdating = False
If Application.CutCopyMode Then
'Permite copiar e colar na planilha
GoTo errHandler
End If
Set cboTemp = ws.OLEObjects("TempCombo")
On Error Resume Next
With cboTemp
.Top = 10
.Left = 10
.Width = 0
.ListFillRange = ""
.LinkedCell = ""
.Visible = False
.Value = ""
End With
On Error GoTo errHandler
If Target.Validation.Type = 3 Then
Application.EnableEvents = False
str = Target.Validation.Formula1
str = Right(str, Len(str) - 1)
With cboTemp
.Visible = True
.Left = Target.Left
.Top = Target.Top
.Width = Target.Width + 15
.Height = Target.Height + 5
.ListFillRange = str
.LinkedCell = Target.Address
End With
cboTemp.Activate
'Abrir a lista suspensa automaticamente
Me.TempCombo.DropDown
End If
errHandler:
Application.ScreenUpdating = True
Application.EnableEvents = True
Exit Sub
End Sub
Anytime I update any cell on a row, I want that the content of the seventh column of this row is updated with the current date.
I tried using the following code, but it only works with common cells, the ones that I manually type its content. I want the seventh column to be updated when I change the drop-down list selection also.
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Row = 1 Then Exit Sub
Application.EnableEvents = False
Cells(Target.Row, "U").Value = Date
End Sub
Is there any way to update the content of the column as I said before? Even when I change the option selected in the drop-down list?
Your code is fine except that you need to turn events back on. You have stopped events from firing with this line: Application.EnableEvents = False but you never turn the event firings back on again. So your code will work the first time you change a cell, the Worksheet_Change event will fire as expected. However, within this sub you have set EnableEvents to false and then never set it back to true. So you have stopped all future events, including this one, from firing again in the future. Here is the solution:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Row = 1 Then Exit Sub
Application.EnableEvents = False
Cells(Target.Row, "U").Value = Date
Application.EnableEvents = True
End Sub

Change properties to several merged cells using "for each" takes too long VBA

I finally got able to program a code to do several operations in merged cells, however it takes too long and I need the cells to be merged.
The macro activates when someone clicks on a button and it's intended to block the some cells if a checkbox is activated, and block another set of cells when is not.
The first "If" is the evaluation of the checkbox. Then it does some operations to some merged cells. Tho code works bur the problems comes with the use of the "For each" statements because it makes the macro run really slow.
An alternative is just select each merged cell and apply the changes one by one to avoid the loops, but that will take some a lot of time (this is just a part of the code).
dim rng as Range
...
with some_worksheet
If .Shapes("checkbox1").ControlFormat.Value = xlOn Then
For Each rng In .Range("K20:X33")
rng.MergeArea.Locked = False
Next rng
.Range("U29").MergeArea.ClearContents
For Each rng In .Range("K32:X33")
rng.MergeArea.ClearContents
Next rng
For Each rng In .Range("L26:X33")
rng.MergeArea.Locked = True
Next rng
Else
For Each rng In .Range("K20:X33")
rng.MergeArea.Locked = False
Next rng
For Each rng In .Range("K20:U25")
rng.MergeArea.ClearContents
Next rng
For Each rng In .Range("K28:T31")
rng.Locked = True
Next rng
For Each rng In .Range("K20:AC27")
rng.Locked = True
Next rng
.Range("K28").MergeArea.Locked = True
.Range("K29").MergeArea.Locked = True
For Each rng In .Range("K30:AC31")
rng.Locked = True
Next rng
End If
End With
...
End Sub
Here's the Excel Screen Display(it also needs to be like that).
The program takes too long because it loops through a LOT of ranges due to the Display.
I'll help to further explain what the macros does.
The grey are the ranges that need to be locked and cleared.
When I click "selection1":
It should unlock all the grey areas, clear the grey fields below the "selection2" selection button, the lock those cells and leave the fields "K20:U25" free to edit.
When I click "selection2" should do the opposite.
Thanks for the quick responses!
Try using
Application.ScreenUpdating = False
In the beginning of your Function, and
On Error GoTo HERE
: HERE
Application.ScreenUpdating = True
Before End Sub
It basically freeze any update in excel window before the code finish running. It will significantly speed up the running time, especially if there is many cell formatting in the code.
On Error make sure that Excel will unfreeze even if your code stops midway
Thanks for the replies.
Application.ScreenUpdating helped but the time was still huge.
What I did was to do little loops between the cells instead of using a "For Each" statement and go through all those cells.
Dim intloop as integer
...
'Unblock
if ("checkbox1").ControlFormat.Value = xlOn then
For intLoop = 0 To 4
.Range("K2" & intLoop).MergeArea.Locked = False
.Range("U2" & intLoop).MergeArea.Locked = False
Next intLoop
For intLoop = 2 To 3
.Range("K3" & intLoop).MergeArea.Locked = False
.Range("U3" & intLoop).MergeArea.Locked = False
Next intLoop
.Range("U28").MergeArea.Locked = False
.Range("U29").MergeArea.Locked = False
'Data delete
.Range("U28").Font.Color = RGB(255, 255, 255)
.Range("U29").MergeArea.ClearContents
For intLoop = 2 To 3
.Range("K3" & intLoop).MergeArea.ClearContents
.Range("U3" & intLoop).MergeArea.ClearContents
Next intLoop
'Block
For intLoop = 2 To 3
.Range("K3" & intLoop).MergeArea.Locked = True
.Range("U3" & intLoop).MergeArea.Locked = True
Next intLoop
.Range("U28").MergeArea.Locked = True
.Range("U29").MergeArea.Locked = True
Else
'Unblock
For intLoop = 0 To 4
.Range("K2" & intLoop).MergeArea.Locked = False
.Range("U2" & intLoop).MergeArea.Locked = False
Next intLoop
For intLoop = 2 To 3
.Range("K3" & intLoop).MergeArea.Locked = False
.Range("U3" & intLoop).MergeArea.Locked = False
Next intLoop
.Range("U28").MergeArea.Locked = False
.Range("U29").MergeArea.Locked = False
'Data delete
.Range("U28").Font.Color = RGB(0, 0, 0)
For intLoop = 0 To 4
.Range("K2" & intLoop).MergeArea.ClearContents
.Range("U2" & intLoop).MergeArea.ClearContents
Next intLoop
'Block
For intLoop = 0 To 4
.Range("K2" & intLoop).MergeArea.Locked = True
.Range("U2" & intLoop).MergeArea.Locked = True
Next intLoop
End if
...
End sub
As you see the code is longer but is way faster.

Excel Macro works slow, how to make it faster?

Stackovwerflow community.
I do believe that this question was asked x1000 times here, but i just wasn not able to find a solution for my slow macro.
This macro serves for unhiding certain areas on worksheets if correct password was entered. What area to unhide depends on cell value. On Sheet1 i have a table that relates certain cell values to passwords.
Here's the code that i use.
1st. Part (starts on userform named "Pass" OK button click)
Private Sub CommandButton1_Click()
Dim ws As Worksheet
DoNotInclude = "PassDB"
For Each ws In ActiveWorkbook.Worksheets
If InStr(DoNotInclude, ws.Name) = 0 Then
Application.ScreenUpdating = False
Call Module1.Hide(ws)
Application.ScreenUpdating = True
End If
Next ws
End Sub
2nd Part.
Sub Hide(ws As Worksheet)
Application.Cursor = xlWait
Dim EntPass As String: EntPass = Pass.TextBox1.Value
If EntPass = Sheet1.Range("G1").Value Then ' Master-Pass, opens all
Sheet1.Visible = xlSheetVisible
ws.Unprotect Password:="Test"
ws.Cells.EntireRow.Hidden = False
Pass.Hide
Else
Dim Last As Integer: Last = Sheet1.Range("A1000").End(xlUp).Row
Dim i As Integer
For i = 2 To Last
Dim region As String: region = Sheet1.Range("A" & i).Value
Dim pswd As String: pswd = Sheet1.Range("B" & i).Value
If EntPass = pswd Then
ws.Unprotect Password:="Test"
ws.Cells.EntireRow.Hidden = False
Dim b As Integer
Dim Last2 As Integer: Last2 = ws.Range("A1000").End(xlUp).Row
For b = 2 To Last2
ws.Unprotect Password:="Test"
If ws.Range("A" & b).Value <> region Then
ws.Range("A" & b).EntireRow.Hidden = True
End If
If ws.Range("A" & b).Value = "HEADER" Then
ws.Range("A" & b).EntireRow.Hidden = False
End If
ws.Protect Password:="Test"
Next b
End If
Next i
End If
Application.Cursor = xlDefault
Sheet2.Activate
Sheet2.Select
Pass.Hide
End Sub
It works fast enough if I enter master-pass to get access to every hidden area, but if i enter cell.value related password, it takes about 5-6 minutes before macro will unhide required areas on every worksheet.
I'd be really grateful if someone could point out the reasons of slow performance and advise changes to be made in code. Just in case, i've uploaded my excel file here for your convenience.
http://www.datafilehost.com/d/d46e2817
Master-Pass is OPENALL, other passwords are "1" to "15".
Thank you in advance and best regards.
Try batching up your changes:
Dim rngShow as Range, c as range
ws.Unprotect Password:="Test" 'move this outside your loop !
For b = 2 To Last2
Set c = ws.Range("A" & b)
If c.Value = "HEADER" Then
c.EntireRow.Hidden = False
Else
If c.Value <> region Then
If rngShow is nothing then
Set rngShow = c
Else
Set rngShow=application.union(c, rngShow)
End If
End If
End If
Next b
If Not rngShow is Nothing Then rngShow.EntireRow.Hidden = False
ws.Protect Password:="Test" 'reprotect...
You might also want to toggle Application.Calculation = xlCalculationManual and Application.Calculation = xlCalculationAutomatic
You can also try moving your Application.Screenupdating code out of the loop, it's going to update for every sheet as written.
Private Sub CommandButton1_Click()
Dim ws As Worksheet
Application.ScreenUpdating = False ''<- Here
DoNotInclude = "PassDB"
For Each ws In ActiveWorkbook.Worksheets
If InStr(DoNotInclude, ws.Name) = 0 Then
Call Module1.Hide(ws)
End If
Next ws
Application.ScreenUpdating = True ''<- Here
End Sub

Excel VB Script Issue - Hide/Show Sheets

I found the below code which I have modified slightly for my needs. The issue I'm having is it doesn't do exactly what I'd like. Specifically, I have a drop down menu in A1 of each sheet with the names of the three sheets, Shipping, Orders, and Inventory in my workbook. What I'm trying to accomplish is whenever a user selects a drop down menu item regardless of the sheet they are working in, the relevant sheet is shown and the other two are hidden.
The below code works, but only if all three sheets have the same sheet name in the drop down selected, which becomes untenable when two sheets get hidden. I'm not exactly sure how to overcome this, but hopefully someone here who is much better at this than I am will have some advice.
Current VB Code:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Value = "Shipping" Then
Sheets("Shipping").Visible = True
Sheets("Orders").Visible = False
Sheets("Inventory").Visible = False
ElseIf Target.Value = "Orders" Then
Sheets("Orders").Visible = True
Sheets("Shipping").Visible = False
Sheets("Inventory").Visible = False
ElseIf Target.Value = "Inventory" Then
Sheets("Inventory").Visible = True
Sheets("Shipping").Visible = False
Sheets("Orders").Visible = False
End If
End Sub
Here is your code adapted for flexibility. This will hide any sheet that does not equal your target value, and unhide the sheet that DOES equal your target value.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim ws As Worksheet
Dim x As Worksheet
Set x = Excel.ActiveSheet
For Each ws In Excel.ActiveWorkbook.Worksheets
If Trim(ws.Name) <> Trim(Target.Value) and ws.Name <> x.Name Then
ws.Visible = xlSheetHidden
Else
ws.Visible = xlSheetVisible
End If
Next ws
End Sub
If you are wondering about the Trim() command, it removes leading and trailing spaces from the string value. Those are sometimes hard to spot in sheet names :)
Edit
I added the ws.Name <> x.Name part of the if statement to make sure the current sheet (aka the sheet on which the drop-down control is located) remains visible.
Start with all three sheets visible and use this code in all three sheets:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Value = "Shipping" Then
Sheets("Shipping").Visible = True
Sheets("Shipping").Select
Sheets("Orders").Visible = False
Sheets("Inventory").Visible = False
ElseIf Target.Value = "Orders" Then
Sheets("Orders").Visible = True
Sheets("Orders").Select
Sheets("Shipping").Visible = False
Sheets("Inventory").Visible = False
ElseIf Target.Value = "Inventory" Then
Sheets("Inventory").Visible = True
Sheets("Inventory").Select
Sheets("Shipping").Visible = False
Sheets("Orders").Visible = False
End If
End Sub