I'm trying to define some variables (for row/column referencing) and use it in multiple subs but I'm having some issue:
Update - fixed earlier issue. Now I can get the columns to cycle. However , when the Column AE is visible and someone clicks next, I want the process to hide the current row, reset to Column E i.e. 5, and show the next row, then cycle through to column AE again. At the moment, when I click 'Next' when AE is showing, it just hides the current row and doesn't show the next row or hid the columns D:AE....
The code it's working from is:
If Columns("AE:AE").EntireColumn.Hidden = False Then
Columns("D:AE").EntireColumn.Hidden = True
Rows(Question).EntireRow.Hidden = True
Question = Question + 1
Rows(Question).EntireColumn.Hidden = False
Brand = 5
End If
Full code here:
Public Brand As Integer
' this will hold the current visible column
Public Question As Integer
' this will hold the current visible row
Sub StartQuestionnaire()
' this sends the user to two different questionnaire formats
If ThisWorkbook.Team = 1 Then Call BrandManager
If ThisWorkbook.Team = 0 Then Call CrossFunctionalTeam
End Sub
Sub BrandManager()
'Questionnaire format 1
Brand = 5
Question = 10
Columns(Brand).EntireColumn.Hidden = False
Rows(Question).EntireRow.Hidden = False
End Sub
Sub CrossFunctionalTeam()
'Questionnaire format 2
If ThisWorkbook.Team = 0 Then
Columns("E:AE").EntireColumn.Hidden = False
Rows("10:10").EntireRow.Hidden = False
ActiveSheet.Range("E10").Select
End If
End Sub
Sub NextButton()
'if a Brand Manager, cycle to the next column question until column AE is reached, then move to next row and show first question only
If ThisWorkbook.Team = 1 Then
If Columns("AE:AE").EntireColumn.Hidden = False Then
Columns("D:AE").EntireColumn.Hidden = True
Rows(Question).EntireRow.Hidden = True
Question = Question + 1
Rows(Question).EntireColumn.Hidden = False
Brand = 5
End If
If Columns("AE:AE").EntireColumn.Hidden = True Then
Columns(Brand).EntireColumn.Hidden = True
Brand = Brand + 1
Columns(Brand).EntireColumn.Hidden = False
End If
End If
'if a Cross Funtional team user, Next button should cycle to the next row of questions
If ThisWorkbook.Team = 0 Then
Question = 10
Rows(Question).EntireRow.Hidden = True
Question = Question + 1
Rows(Question).EntireRow.Hidden = False
End If
End Sub
What do you want to say with Range(Row)? Say, Range(25)?
If I'm not misunderstanding and according to your code it must look as:
Sub NextButton()
' ...
If Range("AE:AE").EntireColumn.Hidden = False Then
' ...
Rows(Row).Hidden = True ' Range(Row).EntireRow.Hidden
Row = Row + 1
Columns(Row).Hidden = False ' Range(Row).EntireColumn.Hidden
' ...
Related
I have a userform in which pages and then on one page contain a lot of comboboxes all of them have a pattern in their name as per their location for example in first row I have 3 comboboxes their names are:
AO11, AO12, AO13
Second row has 04 comboboxes with following names
AO21, AO22, AO23, AO24
Third row has 04 Comboboxes with following names
AO31, AO32, AO33, AO34
and so on till 12~15 Comboboxes
X represents row number when which will start with X=1 because first row will always be visible.
once user press AddNewCMD it should make visible the next row of comboboxes with the following code:
Private Sub AddNewCMD_Click()
If X = 2 Then
Me.AO21.Visible = True
Me.AO22.Visible = True
Me.AO23.Visible = True
Me.AO24.Visible = True
X = X + 1
ElseIf X = 3 Then
Me.AO31.Visible = True
Me.AO32.Visible = True
Me.AO33.Visible = True
Me.AO34.Visible = True
X = X + 1
End If
End Sub
in AO21
2 represents row number
1 represent first combo in row two
however I realize that it will be very long code as if I add further rows in therefore I am search for a way that can loop through each comboboxes and validate x with its name and make them visible?
same goes for hiding the comboboxes.
Please, copy the next code in the userForm code module:
Option Explicit
Private nextRow As Long
Private Sub AddNewCMD_Click()
Dim i As Long, ctrl As MSForms.Control, boolVis As Boolean
If nextRow = 0 Then
nextRow = 2
Else
nextRow = nextRow + 1
End If
Debug.Print nextRow
For i = 0 To Me.MultiPage1.Pages(0).Controls.count - 1
Set ctrl = Me.MultiPage1.Pages(0).Controls(i)
If TypeOf ctrl Is MSForms.ComboBox Then
If CLng(Right(ctrl.Name, Len(ctrl.Name) - 2)) > 13 Then
Debug.Print ctrl.Name, ctrl.Visible
If CLng(Mid(ctrl.Name, 3, 1)) = nextRow Then
ctrl.Visible = True: boolVis = True
End If
End If
End If
Next i
If Not boolVis Then MsgBox "The row " & nextRow & " does not exist..."
End Sub
ClickingAddNewCMD button will make the next combos row visible. When the existing rows are all made visible, a message stating that no any row available will be raised.
You did not answer my clarification questions... But if only one such combo row should be visible (except the first one, or including), I can make a function to determine it, but this can be done only if you supply a logic algorithm based on what to proceed.
I have more than 20 hidden columns with data. I want 4 columns to appear and then the next 4 columns on each click of a button.
I tried the below code. Instead of 4 columns at a time, it shows all 20 columns in a click.
Sub compare() '
'compare macro
'selects the button1 rows for the output tab
application.screenupdating=true
range("I10:AR62").entirecolumn/hidden=false
range("B1").select
application.screenupdating=false
End
you want something like:
range(columns(j),columns(j+k)).entirecolumn.hidden=true
range(columns(y),columns(y+z)).entirecolumn.hidden=false
but you need logic to determine what j is... first scenario is where nothing is hidden:
if not columns(9).entirecolumn.hidden and not columns(13).entirecolumn.hidden and not columns(17).entirecolumn.hidden and not columns(21).entirecolumn.hidden then
Then you will want to hide such that:
j = 13
k = 15
Where that scenario is not true (ELSE), you should have some logic embedded to determine what is hidden and unhide other sections:
if not columns(9).entirecolumn.hidden then
j = 9
k = 3
y = 13
z = 3
You would need the above for each of your column groupings to tell what isn't hidden, so you know what grouping is next.
You would have listed what sections will be visible and which sections would be hidden based on the column numbers.
I know it has been a few days since anyone has posted on this, but I figured I would post this part of a macro that I have built for another project. This should work as intended, and the variables are already setup according to the OP's question.
Sub DynHideColumns()
FirstColumn = 9 ' First Column that could be hidden
LastColumn = 200 ' Last Column that could be hidden
ColumnSteps = 4 ' Number of columns to hide per start
x = FirstColumn
Z = 1
ReDim y(1 To ColumnSteps)
Do Until x > LastColumn
If ActiveSheet.Range(Columns(x), Columns(x)).EntireColumn.Hidden = False Then
If Z <= ColumnSteps Then
y(Z) = x
Z = Z + 1
Else
y(1) = ""
End If
End If
x = x + 1
Loop
ActiveSheet.Range(Columns(FirstColumn), Columns(LastColumn)).EntireColumn.Hidden = True
If y(1) = "" Then
ActiveSheet.Range(Columns(FirstColumn), Columns(FirstColumn + ColumnSteps - 1)).EntireColumn.Hidden = False
Else
If y(ColumnSteps) = LastColumn Then
ActiveSheet.Range(Columns(FirstColumn), Columns(FirstColumn + ColumnSteps)).EntireColumn.Hidden = False
Else
ActiveSheet.Range(Columns(y(1) + ColumnSteps), Columns(y(ColumnSteps) + ColumnSteps)).EntireColumn.Hidden = False
End If
End If
End Sub
I want to build a survey using excel and vba. I have a table with questions and answers. As the survey starts, my code will list the answers by overwriting the checkboxes' labels on a form. I will fetch their answer and write them in a column by using True or False value of a checkbox.
Variable "aRow" is the number of the answers for each question. "lastAns" is the row number of the last answer. Depending on the number of the answer, some checkboxes will be hidden, shown. "CheckBox1" to "CheckBox4" are the names of the checkboxes.
The following code works, but it is too long and I want to have a better method to loop through the checkboxes and changing their labels each time. Please show me how to do it!
Thanks you so much!
`lastAns = Cells(qRow, 5).End(xlDown).Row + 1
aRow = lastAns - qRow
If aRow >= 1 Then
Me.CheckBox1.Visible = True
Me.CheckBox1.Caption = Cells(qRow, 5)
Else: Me.CheckBox1.Visible = False
End If
If aRow >= 2 Then
Me.CheckBox2.Visible = True
Me.CheckBox2.Caption = Cells(qRow + 1, 5)
Else: Me.CheckBox2.Visible = False
End If
If aRow >= 3 Then
Me.CheckBox3.Visible = True
Me.CheckBox3.Caption = Cells(qRow + 2, 5)
Else: Me.CheckBox3.Visible = False
End If
If aRow >= 4 Then
Me.CheckBox4.Visible = True
Me.CheckBox4.Caption = Cells(qRow + 3, 5)
Else: Me.CheckBox4.Visible = False
End If
.....SAME CODE CONTINUES TILL 7...`
As a follow up answer to my comment, here is what I think you are looking for:
arow = lastAns - qRow
Dim i As Long, ctl As Control
For i = 1 To 4
Set ctl = Me.Controls("CheckBox" & i)
If i <= arow Then
ctl.Visible = True
ctl.Caption = Cells(qRow + i - 1, 5)
Else
ctl.Visible = False
End If
Next i
I’m using a userform with 12 listboxes (numbered 2-13). Each list box could contain 0-8 items assigned by user from main listbox1. I run the following code to output the content of each list box (12 boxes) to sheet “Tray” when a button is pressed.
Each listbox is then output into corresponding columns of each tray from columns B-M. Listbox2 fills column 1 of each tray and so on. A maximum of 4 trays can be filled. The code checks the 1st well of each tray and if it contains a value it assumes the tray is full & begins filling the next tray.
Problem: If the first tray contains a blank column(listbox) and the second tray contains values in the same listbox, the code will fill blank column of the frist tray with values that should be in the second tray. Please see pictures below and updated code below:
Listboxes 2,3 and 4 for Tray 1 (note listbox3 is empty)
Listboxes 2,3 and 4 for tray 2 (note listbox3 has data)
Code ran two times: Listbox3 from tray2 appears in tray1 (erroneously!!!)
Expected output:
Sub Worklist()
'
Dim Var, VarName As Variant
Dim i, DblDashPos, FirstPeriodPos, lngColNum, lngRowNum As Long
Dim item As ListBox
Const cstrNames As String = "Listbox2,Listbox3,Listbox4,Listbox5,Listbox6,Listbox7,Listbox8,Listbox9,Listbox10,Listbox11,Listbox12,Listbox13"
Application.ScreenUpdating = False
lngColNum = 2
For Each VarName In Split(cstrNames, ",")
If UserForm2.Controls(VarName).ListIndex <> -1 Then 'if listbox is not blank
If Sheets("Tray").Cells(4, lngColNum).Value = 0 Then
'checks if value in row 3 column "lngColNum" is empty
lngRowNum = 4
ThisWorkbook.Sheets("Tray").Range("C2").Value = UserForm2.TextBox1.Value
ElseIf Sheets("Tray").Cells(15, lngColNum).Value = 0 Then 'checks if value in row 14 column "lngColNum" is empty
lngRowNum = 15
ThisWorkbook.Sheets("Tray").Range("C13").Value = UserForm2.TextBox1.Value
ElseIf Sheets("Tray").Cells(26, lngColNum).Value = 0 Then 'checks if value in row 14 column "lngColNum" is empty
lngRowNum = 26
ThisWorkbook.Sheets("Tray").Range("C24").Value = UserForm2.TextBox1.Value
Else 'otherwise assumes tray starts in row 5, column "lngColNum"
lngRowNum = 37
ThisWorkbook.Sheets("Tray").Range("C35").Value = UserForm2.TextBox1.Value
End If
For i = 0 To UserForm2.Controls(VarName).ListCount - 1
Var = UserForm2.Controls(VarName).List(i)
DblDashPos = InStr(1, Var, "--")
FirstPeriodPos = InStr(1, Var, ".")
Sheets("Tray").Select
ActiveSheet.Cells(lngRowNum, lngColNum) = Left(Var, DblDashPos - 1) & Right(Var, Len(Var) - FirstPeriodPos + 1)
lngRowNum = lngRowNum + 1
Next i
End If
lngColNum = lngColNum + 1
Next
Application.ScreenUpdating = True
End Sub
Thank you very much!
The problem is that you're only testing the column that corresponds to the ListBox to see if the cell is empty. If you want to test that all of the columns in a "tray" are empty, you need to test once for the entire sheet. Something like this (untested because I'm too lazy to rebuild your form):
Private Function FindFirstUnusedRow(sheet As Worksheet) As Long
Dim testColumn As Long, testRow As Long
Dim used As Boolean
For testRow = 4 To 37 Step 11
used = False
For testColumn = 2 To 13
If IsEmpty(sheet.Cells(testRow, testColumn)) = False Then
used = True
Exit For
End If
Next testColumn
If used = False Then
FindFirstUnusedRow = testRow
Exit For
End If
Next testRow
End Function
Then in your code, call it before your loop:
Sub Worklist()
Dim var As Variant
Dim i As Long, dashPos As Long, periodPos As Long, colNum As Long
Dim rowNum As Long, Dim sheet As Worksheet
Application.ScreenUpdating = False
Set sheet = ThisWorkbook.Sheets("Tray")
rowNum = FindFirstUnusedRow(sheet)
If rowNum = 0 Then
Debug.Print "All trays full."
Exit Sub
End If
Dim current As ListBox
For colNum = 2 To 13
Set current = UserForm2.Controls("Listbox" & colNum)
If current.ListIndex <> -1 Then 'if listbox is not blank
sheet.Cells(rowNum - 2, colNum).Value = UserForm2.TextBox1.Value
For i = 0 To current.ListCount - 1
var = current.List(i)
dashPos = InStr(1, var, "--")
periodPos = InStr(1, var, ".")
sheet.Cells(rowNum + i, colNum) = Left$(var, dashPos - 1) & _
Right$(var, Len(var) - periodPos + 1)
Next i
End If
Next colNum
Application.ScreenUpdating = True
End Sub
A couple other notes: You can ditch the Sheets("Tray").Select line entirely - you never use the selection object. Same thing with the mixed references to ActiveSheet and ThisWorkbook.Sheets("Tray"). Grab a reference and use it.
Also, these lines don't do what you think they do:
Dim Var, VarName As Variant
Dim i, DblDashPos, FirstPeriodPos, lngColNum, lngRowNum As Long
Of all the variables you declare, everything is a Variant except lngRowNum. If you want to combine declarations on one line like that, you still need to specify a type for each variable, or they'll default to Variant. See the example code above.
Multiple cells reference cell R1 for an indirect lookup to one of four other sheets. The sheets are named week1, week2, week3, and week4.
What I am looking to do, is when I click Button X, my reference cell changes from week1 to week2. and every time I click it should advance to the extent that week4 leads back to week1.
My current broken code reads:
'Change the week number in cell R1
week = Range("R1")
If week = week1 Then
Range("R1").Value = week2
Else
If week = week2 Then
Range("R1").Value = week3
Else
If week = week3 Then
Range("R1").Value = week4
Else
If week = week4 Then
Range("R1").Value = week1
End If
End If
End If
End If
Application.ScreenUpdating = True 'Turns viewing function back on so the spreadsheet is usable.
End Sub
Select Case week
Case Is = week1: vValue = week2
Case Is = week2: vValue = week3
Case Is = week3: vValue = week4
Case Is = week4: vValue = week1
End Select
Range("R1").Value = vValue
Application.ScreenUpdating = True
There is a simple way to solve it:
Range("R1") = Left(Range("R1"), 4) & Right(Range("R1"), 1) Mod 4 + 1
'number after Mod = max week
Mod x just sets the count to 0 if it is at its max (the + 1 sets it then to 1 again)
However, you may use this sub to avoid strange behavior:
Sub NewWeekMax()
Dim str As String, i As Byte
str = "Week1"
For i = 2 To 4 'last num = max weeks
str = str & ",week" & i
Next
With Range("R4").Validation
.Delete
.Add 3, 1, 1, str
.InCellDropdown = True
.ShowInput = True
.ShowError = True
End With
End Sub
This sub simply sets a data validation to disable wrong input in R1
You should be able to do this in a single code line.
Range("R1") = Format(InStr(1, "4123", Right(Range("R1").Value, 1)), "\W\e\ek0")
This will cycle through Week1, Week2, Week3, Week4, Week1, .... I've omitted the parent worksheet reference of R1 but it is never a bad idea to include that.