My spreadsheet hides and shows multiple rows by clicking buttons. As the spreadsheet is password protected any macro should apply password, then runs hide/show and finally set password again. This is how its look like.
Sub Macro1()
ActiveSheet.Unprotect Password:="abc"
Rows("12:16").EntireRow.Hidden = True
ActiveSheet.Protect Password:="abc"
End Sub
Sub Macro2()
ActiveSheet.Unprotect Password:="abc"
Rows("12:16").EntireRow.Hidden = False
ActiveSheet.Protect Password:="abc"
End Sub
Sub Macro3()
ActiveSheet.Unprotect Password:="abc"
Rows("20:24").EntireRow.Hidden = True
ActiveSheet.Protect Password:="abc"
End Sub
Sub Macro4()
ActiveSheet.Unprotect Password:="abc"
Rows("20:24").EntireRow.Hidden = False
ActiveSheet.Protect Password:="abc"
End Sub
Script works fine, but I have 16 sections which require 32 macro's. It still works fine but I wonder if there would be an easier way, requiring only 1 line for applying and 1x for setting the password.
Thank you for your comments.
Dennis
The Netherlands
Sub Macro1
HideIt Rows("12:16"), True
End Sub
Sub Macro2()
HideIt Rows("12:16"), False
End Sub
Sub HideRows(rng As Range, HideIt as Boolean)
ActiveSheet.Unprotect Password:="abc"
rng.EntireRow.Hidden = HideIt
ActiveSheet.Protect Password:="abc"
End Sub
If you could name your buttons with something which would enable to to translate the names to a range and true/False, you could link them all to a single Sub and use Application.Caller to get the name of the calling button and extract the parameters from that.
EDIT:
OK here's a very simple example: add two "forms" buttons to your worksheet and name one "btn_12_5_H" and the other "btn_12_5_S".
Here's how you name each button:
Select the button via a right-click
Enter the name in the "name" box in the formula bar and press Enter
Link both buttons to the Sub below (right-click button >> Assign macro):
Sub ShowHideRows()
Dim arr
'split the calling button name into an array
' (array will be zero-based)
arr = Split(Application.Caller, "_")
'**EDIT** check array is expected size...
If UBound(arr) <> 3 Then Exit Sub
If IsNumeric(arr(1)) and IsNumeric(arr(2)) Then
With Me 'if the code is in the sheet module, else "ActiveSheet"
.Unprotect Password:="abc"
'arr(1) determines start row
'arr(2) determines # of rows
'arr(3) determines if rows are hidden or not
.Cells(arr(1), 1).Resize(arr(2), 1).EntireRow.Hidden = (arr(3) = "H")
.Protect Password:="abc"
End With
End If
End Sub
EDIT#2:
Just for completeness, note that you can also add arguments directly to the OnAction (i.e. when you right-click the button an select "Assign macro")
For example you can use something like:
Book1!'ShowHideRows2 12,TRUE'
Note use of single quotes around the whole thing. The called sub might look something like (very basic example to demonstrate that the arguments were properly passed):
Sub ShowHideRows2(rownum, HideIt)
Debug.Print rownum, HideIt
End Sub
Note that because the Sub has parameters it won't show up in the "Assign macro" list and you have to type it in.
Related
Very Basic I am sure but I can't figure it out for the life of me.
I have a set of radio buttons that changes the value of cell("L37") between 1 and 2.
I have tried to write the VBA code several different ways without luck. Please advise.
Sub hide_sheet()
If Worksheets("Feedback").Range("L37").Value = 1 Then
Rows("63:93").EntireRow.Hidden = True
Else Worksheets("Feedback").Range("L37").Value = 2 Then
Worksheets("Feedback").Rows("63:93").EntireRow.Hidden = False
End If
End Sub
I had it working perfectly fine via a Macro tied to the radio buttons; however, due to me needing to protect the sheet I needed to change it.
I am using a protect/unprotect VBA code and would like to include it into the code so it won't set off the macro/sheet protected warning.
Here is my protect/unprotect code I am using for everything.
Sub unprotect()
Worksheets("Feedback").unprotect
End Sub
Sub protect()
Worksheets("Feedback").protect , _
AllowFormattingCells:=True, _
AllowFormattingRows:=True
End Sub
Any advice would be greatly appreciated. I Thank You in Advance of your assistance.
Show/Hide Rows
Issues
The Feedback worksheet is not qualified so if the wrong workbook is active, it will fail. To reference the workbook containing this code, you can use ThisWorkbook:
ThisWorkbook.Worksheets("Feedback")...
You are using Rows("63:93") instead of Worksheets("Feedback").Rows("63:93") in the If clause. If the wrong worksheet is active (selected), it will fail.
You are using Else instead of ElseIf.
You can use the With statement to reduce typing as illustrated in the following code.
If you convert the cell value to a string, then if the cell accidentally contains an error value, the code will not fail.
The Code
Sub ShowHideRowsFix()
With ThisWorkbook.Worksheets("Feedback")
.Unprotect
Select Case CStr(.Range("L37").Value)
Case "1"
.Rows("63:93").Hidden = True
Case "2"
.Rows("63:93").Hidden = False
Case Else
End Select
.Protect AllowFormattingCells:=True, AllowFormattingRows:=True
End With
End Sub
An Improvement
To automate this operation (no need for buttons), in the sheet module of the Feedback worksheet identified in the VBE Project explorer window by e.g. Sheet1(FeedBack) (double-click to open), you could use the following code.
Private Sub Worksheet_Change(ByVal Target As Range)
Const CellAddress As String = "L37"
Dim Cell As Range: Set Cell = Me.Range(CellAddress)
If Intersect(Cell, Target) Is Nothing Then Exit Sub
ShowHideRows Cell
End Sub
Sub ShowHideRows(ByVal Cell As Range)
With Cell.Worksheet
.Unprotect
Select Case CStr(Cell.Value)
Case "1"
.Rows("63:93").Hidden = True
Case "2"
.Rows("63:93").Hidden = False
Case Else
End Select
.Protect AllowFormattingCells:=True, AllowFormattingRows:=True
End With
End Sub
I prefer the simplest approach where possible. This is the approach I use to hide columns re-written for your needs.
The following code may exist on the UserForm or in a standard Code Module:
Sub rwControl(ByRef hType As String)
Dim rwVis As Boolean
If hType = "hRW" Then rwVis = True
If hType = "uRW" Then rwVis = False
With ThisWorkbook.Worksheets("Feedback")
.Unprotect
.Rows("63:93").Hidden = rwVis
.Protect
End With
End Sub
You may call this code directly from you RadioButton_Change() Event vy including the following code:
IF RadioButton1.Value = True then 'Assuming the value is 1
rwControl "hRW" 'This hides the Rows
ELSE
rwControl "uRW" 'This unhides the Rows
End If
OR, to keep it really simple:
in your RadioButton_Change() event simply add:
Private Sub RadioButton1 Change()
With ThisWorkBook.Worksheets("Feedback")
.Unprotect
If RadioButton1.Value = True Then
.Rows("63:93").Hidden = True
Else
.Rows("63:93").Hidden = False
End If
.Protect
End With
End Sub
Using this approach negates the need for Worksheet Module Coding and Case Coding and allows you to keep the RadioButtons if you deem them important to the functionality.
I have created a macro that allows a user to select an option from a dropdown list which unhides selected rows that corresponds with their selection. The problem is when I protect the sheet I get the following error "Run-time error '1004'" when I select an option for the drop down list. I need this sheet to be protected so the user cannot touch the data sets shown. Here is a sample code (original version is very long):
Private Sub Worksheet_Change(ByVal Target As Range)
ActiveSheet.Activate
If Not Application.Intersect(Range("C15"), Range(Target.Address)) Is Nothing Then
Select Case Target.Value
Case Is ="Option 1"
Rows("17:75").EntireRow.Hidden = True
Case Is ="Option 2"
Rows("17:28").EntireRow.Hidden = False
End Select
End If
End Sub
I've been reading other threads and I've come across a few options that said I need to Unprotect and Protect my sheet but I'm not to sure how to add this to the code above. And if this is the best option for what I am trying to accomplish
Option 1
Sub UnprotectAll()
Dim sh As Worksheet
For Each sh In ActiveWorkbook.Worksheets
sh.Unprotect Password:=yourPassword
Next sh
End Sub
Sub ProtectAll()
Dim sh As Worksheet
For Each sh In ActiveWorkbook.Worksheets
sh.Protect Password:=yourPassword
Next sh
End Sub
Option 2 - Adding this code somewhere below
UserInterFaceOnly:=True
Any suggestions in how I can accomplish this? And what the full code would look like?
Thanks so much!
#ExcelNoob I’ve made the following assumptions based on your question:
Only the active sheet is relevant
You formatted cell C15 as not Locked (when the sheet is unprotected, right click C15 /format/protection and uncheck ‘locked’ & ‘hidden’
You have indicated the correct rows you want hidden or not (seem a bit odd?)
There are only 2 options
That being the case, the minimum code below will do what you ask. If you want to use a specific password, just put it between the double quotation marks.
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Range("C15"), Target) Is Nothing Then
ActiveSheet.Unprotect Password:=""
If Range("C15").Value = "Option 1" Then
Rows("17:75").Hidden = True
ElseIf Range("C15").Value = "Option 2" Then
Rows("17:28").Hidden = False
End If
ActiveSheet.Protect Password:=""
End If
End Sub
As per above, but if you don't want to protect/unprotect, put your drop down in a form and use :
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Sheet1.Protect "Password", UserInterfaceOnly:=True
End Sub
Where "password" is changed to whatever password you want.
I have a userform which has multiple RefEdit controls. I need the user to select ranges from multiple sheets and the userform has to be complete before the rest of the code can run.
Issue: The activesheet is "Sheet1" when the userform is initiated. Each time I select a range on "Sheet2" and click into the next RefEdit the visible Excel sheet returns to "Sheet1". I'd like the sheet to remain on "Sheet2", since clicking between the sheets significantly increases the time it takes to select the data.
Because I need the userform to be completed before continuing with my code, using "vbModeless" doesn't appear to work.
I've tried to step through the userform events which appeared to be relevant but none were activated when I entered the RefEdit, selected the data, or left the RefEdit.
Thanks in advance for any help!
Edit: Using some input from the responses and doing some more research I think I've figured out the problem and a work around.
RefEdit events such as Change or Exit (I tried all of them I think) don't appear to trigger when a change occurs in the control. So I couldn't write code to manipulate the activesheet when I changed the control. A workaround found here: http://peltiertech.com/refedit-control-alternative/ uses a textbox and inputbox to simulate a RefEdit control and will actually trigger when changes are made! Code is below. To add other "RefEdit" controls you should repeat the code in the Userform_Initialize event for each control, then add another TextBox1_DropButtonClick and update TextBox1 to the name of the new control. In use when the control updates the workbook jumps to the previous activesheet and then returns the desired activesheet. Not as smooth as I'd like but much better than it was.
Code:
Private Sub CancelButton_Click()
Unload Me
End
End Sub
Private Sub OKButton_Click()
UserForm1.Hide
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
End
End Sub
Private Sub UserForm_Initialize()
Me.TextBox1.DropButtonStyle = fmDropButtonStyleReduce
Me.TextBox1.ShowDropButtonWhen = fmShowDropButtonWhenAlways
End Sub
Private Sub TextBox1_DropButtonClick()
Dim ASheet As String ' Active sheet
Me.Hide
'Use input box to allow user to select a range
On Error Resume Next
Me.TextBox1.Value = Application.InputBox("Select the range containing your data", _
"Select Chart Data", Me.TextBox1.Text, Me.Left + 2, _
Me.Top - 86, , , 0)
On Error GoTo 0
'Check if there is a sheet name - if the range selected is on the activesheet the output of the inputbox doesn't have a sheet name.
If InStr(1, Me.TextBox1.Value, "!", vbTextCompare) > 0 Then ' there is a sheet name
ASheet = Replace(Split(Me.TextBox1.Value, "!")(0), "=", "") ' extract sheet name
Else ' there is no sheet name
Me.TextBox1.Value = "=" & ActiveSheet.Name & "!" & Replace(Me.TextBox1.Value, "=", "") ' add active sheet name to inputbox output
ASheet = ActiveSheet.Name
End If
Worksheets(ASheet).Activate ' set the active sheet
Me.Show
End Sub
Have you tried something as simple as:
Sheets("Sheet2").Select
somewhere in the beginning of your form code ?
Since you haven't posted your code, it's hard to provide a good answer.
Hope this helps a little :)
This form module worked for me.
Private Sub CommandButton1_Click() 'Cancel Button
Unload Me
End Sub
Private Sub CommandButton2_Click() 'GO Button
Dim newSheet As Worksheet
abc = Split(RefEdit1.Value, "!")
cbn = abc(0)
Unload Me
Set newSheet = Worksheets(abc(0))
newSheet.Activate
End Sub
I want to increment the value of a cell by 1 when I input a specific key combination.
I used Record Macro but when I edit that code it doesn't show how it binds the macro to the keystroke.
Here's the code I have that does not work:
Sub IncTest2()
ActiveCell.Value = ActiveCell.Value + 1
End Sub
Sub KeyTest()
Application.OnKey "^a", "IncTest2"
End Sub
It should increment the active cell by 1 with "Control+a", but instead it does the standard "Control+a" keyboard shortcut.
Try this and see if it works for you. In the ThisWorkBook code, add the sub below.
Sub Workbook_Activate()
Application.OnKey "^a", "IncrementByeOne"
End Sub
In a module in ThisWorkBook, add the macro below.
Sub IncrementByeOne()
With ThisWorkbook.ActiveSheet
ActiveCell.Value = ActiveCell.Value + 1
End With
End Sub
We have a trivial problem regarding how to run a simple macro button. The purpose of this button is two-fold: expanding a row and collapsing a row.
1 on pressing the button this VBA command is initiated:
Sub Macro7()
Rows(7).ShowDetail = True
End Sub
This command expands row 7.
2 on pressing the button again (whilst the row is expanded), this VBA is initiated:
Sub Macro7()
Rows(7).ShowDetail = False
End Sub
This collapses the row.
Is there a way to link a button to two macros?
Thanks in advance!!!
M
Sub Macro7()
With Rows(7)
.ShowDetail = Not .ShowDetail
End With
End Sub
No need to. Just adjust your macro to check the current state of your row (collapsed or expanded) and act accordingly:
Sub ExpandOrCollapse()
Rows(7).ShowDetail=IIF(Rows(7).ShowDetail,False,true)
End Sub
I tried above answers and it didn't work for me. Below is the code that works:
Sub rowExpanded()
Rows("7:7").Select
Selection.EntireRow.Hidden = IIf(Selection.EntireRow.Hidden, False, True)
End Sub
Try this
Dim rowExpanded As Boolean
rowExpanded = Rows(7).ShowDetail
If rowExpanded = True Then
Rows(7).ShowDetail = False
Else
Rows(7).ShowDetail = True
End If
Try using a Command Button (ActiveX Control). Use the button caption to identify the toggle state.
Private Sub CommandButton1_Click()
If CommandButton1.Caption = "-" Then
ActiveSheet.Outline.ShowLevels Rowlevels:=1, ColumnLevels:=1
JobDescriptionToggleButton.Caption = "+"
Else
ActiveSheet.Outline.ShowLevels Rowlevels:=8, ColumnLevels:=8
JobDescriptionToggleButton.Caption = "-"
End If
End Sub