Show certain rows but keep others hidden - vba

I am working with an excel workbook and on one of the worksheets are rows that hide or show depending on options selected in another worksheet. The structure looks something like this
A
1
2
3
4
B
1
2
3
4
C
1
2
3
4
Where they have the option to hide all of A and B, A and C, A, B, or C. The user has the option to hide A and B or C (they must select between B or C).They also have the option to hide the individual rows under each letter. Rows 1, 2, and 3. If the option to hide 2 is checked, all "2" rows under each letter is hidden. If they unchecked this option, all 2 rows appear once more. The problem is that the "2" row of an already hidden letter will display.
I have run into a mental block, but this is what I've done. Psuedocode for readability because right now my code is messy and I hate the way vba looks. This is a logic problem more than a syntax problem anyway.
Property hiddenA As Bool get let
Property hiddenB As Bool get let
Property hiddenC As Bool get let
OptionButton1.Click()
hiddenA = true
Hide A row and all rows associated with it
OptionButton2.Click()
HiddenA = false
Show A row and all rows associated with it
OptionButton3.Click()
HiddenB = false
HiddenC = true
Show B row and all rows associated with it
Hide C row and all rows associated with it
OptionButton4.Click()
HiddenB = true
HiddenC = false
Hide B row and all rows associated with it
Show A row and all rows associated with it
CheckBox1.Click()
if CheckBox1.value = false Then
Hide all "1" rows
Else
Show all "1" rows, but keep the "1"s under already hidden letters, hidden.
This is the problem.
And so on. There are checkboxes for showing/hidden all 2, 3, and 4 rows as well.

Rough outline - UNTESTED CODE... something like this should unhide everything, check each checkbox for status, add checked boxes to range, and hide that entire range at end.
'CheckBox1 is Row 1 in group
'CheckBox2 is Row 2 in group
'CheckBox3 is Row 3 in group
'CheckBox4 is Row 4 in group
'CheckBox5 is Row 5 in group
'CheckBox6 is Group A
'CheckBox7 is Group B
'CheckBox8 is Group C
'CheckBox9 is Group D
'CheckBox10 is Group E
Sub CheckBoxClick() 'Assign this to all checkboxes
Application.ScreenUpdating = False 'Turn off screen updating
ActiveSheet.Cells.EntireRow.Hidden = False 'Unhide all
Dim RngCnt As Range
Dim LastRow As Long
Dim CurRow As Long
Dim ChkBx As OLEObject
LastRow = Range("A" & Rows.Count).End(xlUp).Row
For Each ChkBx In ActiveSheet.OLEObjects
If TypeName(ChkBx.Object) = "CheckBox" Then
Select Case ChkBx.Name
Case "CheckBox1"
If ChkBx.Value = True Then
RngCnt = Union(RngCnt, Range(Rows this chk box effects))
End If
Case "CheckBox2"
If ChkBx.Value = True Then
RngCnt = Union(RngCnt, Range(Rows this chk box effects))
End If
Case ETC, ETC, ETC to "CheckBox10"
...
End If
Next ChkBx
RngCnt.EntireRow.Hidden = True
Application.ScreenUpdating = True
End Sub

Related

CheckBox in DataGridView Won't Evaluate if Cell Has Focus

The first column in a DataGridView (dgv1) has checkboxes. Interestingly, when you click on the last checkbox desired, as soon a you loop through the rows for that column to evaluate checked items, the last cell checked (with a cursor on it) does not evaluate to true. The syntax for looping through the checkboxes in column 0 is below:
Dim NumCBChecked As Integer = 0
For i = 0 To dgv1.Rows.Count - 1
If CBool(dgv1(0, i).Value) = True Then
NumCBChecked += 1
End If
Next
Is there a way to set the focus to false if the cell containing the last checkbox checked is in edit mode?
BTW, refreshing the edit status (below) did not help before looping:
dgv1.RefreshEdit()
Per #JohnG's comment, the suggestion worked as follows:
dgv1.EndEdit()
Dim NumCBChecked As Integer = 0
For i = 0 To dgv1.Rows.Count - 1
If CBool(dgv1(0, i).Value) = True Then
NumCBChecked += 1
End If
Next

How to automatically resize expanded rows?

So my problem is that I have a sheet in which a multitude of grouped rows exist. The rows are grouped in 2 levels. To put this in perspective, I have a group which covers the rows in A1:A55. Inside this first level group I have multiple second level groups covering smaller sections (e.g. rows in A2:A5, rows in A7:A10 and so on.). Because of Excel automatically adding groups together if they are adjacent to each other, I have added a blank row in between each 2nd level group of rows(A6, A11, etc.). I then proceeded to change the height of these blank rows to 0,00. This hid the + and - signs on the left hand bar for collapsing/expanding, which wasn't a problem as the collapsing and expanding is being handled via buttons on the sheet.
However, when all the grouped rows, or just the 2nd level grouped rows, are being expanded (either manually or via a macro), the row height of all the blank rows jumps back to a size at which Excel can display the + and - signs in the left hand bar again. This shows the blank rows which I want to prevent.
I know I probably can't prevent the resizing of the rows so it displays the + and - signs, however I was thinking about immediately resizing the blank rows to a height of 0.00. This is being built in the macro that is called via the buttons, but the concern is when a user expands the rows manually. There is no event for collapsing and or expanding for me to use in an event handler. Is there any way for me to have an automatic response on a manual expand action by the user?
I have provided a example of the code used below.
Sub Select1Year_Click()
Dim ws1 As Worksheet
Set ws1 = Worksheets("Overview")
Dim ws2 As Worksheet
Set ws2 = Worksheets("Selection Tab")
Dim ROffset As Integer
ROffset = ((ws2.Range("B33").Value - 1) * 4) 'User defined starting Year
'value
On Error Resume Next
With ws1
.Range("AJ2").Rows.ShowDetail = False '2018
.Range("AJ7").Rows.ShowDetail = False '2019
.Range("AJ12").Rows.ShowDetail = False '2020
.Range("AJ17").Rows.ShowDetail = False '2021
.Range("AJ22").Rows.ShowDetail = False '2022
.Range("AJ27").Rows.ShowDetail = False '2023
.Range("AJ32").Rows.ShowDetail = False '2024
.Range("AJ37").Rows.ShowDetail = False '2025
.Range("AJ42").Rows.ShowDetail = False '2026
.Range("AJ47").Rows.ShowDetail = False '2027
.Range("AJ52").Rows.ShowDetail = False '2028
End With
If ws2.Range("B31").Value = 1 Then 'User selected 1 year to be shown in
'expanded view
ws1.Range("AJ2").Offset(0, ROffset).Rows.ShowDetail = True
End If
End Sub
'------------------------------------------------------------------------
Sub Select10Year_Click()
Dim ws1 As Worksheet
Set ws1 = Worksheets("Overview")
Dim ws2 As Worksheet
Set ws2 = Worksheets("Selection Tab")
Dim i As Integer
Dim ROffset As Integer
ROffset = ((ws2.Range("B33").Value - 1) * 4) 'User defined starting Year
'value
If ws2.Range("B31").Value = 3 Then 'User selected all years to be expanded
On Error Resume Next
ws1.Shapes("Select10Year").ControlFormat.Value = True
With ws1
.Range("AJ2").Rows.ShowDetail = True '2018
.Range("AJ7").Rows.ShowDetail = True '2019
.Range("AJ12").Rows.ShowDetail = True '2020
.Range("AJ27").Rows.ShowDetail = True '2021
.Range("AJ22").Rows.ShowDetail = True '2022
.Range("AJ27").Rows.ShowDetail = True '2023
.Range("AJ32").Rows.ShowDetail = True '2024
.Range("AJ37").Rows.ShowDetail = True '2025
.Range("AJ42").Rows.ShowDetail = True '2026
.Range("AJ47").Rows.ShowDetail = True '2027
.Range("AJ52").Rows.ShowDetail = True '2028
End With
If ROffset > 0 Then 'User has selected a different starting year then
'2018, so collapse are years before selected
'starting year
For i = 0 To i = ROffset Step 1
ws1.Range("AJ2").Offset(0, ROffset).Rows.ShowDetail = False
Next i
End If
End If
End Sub
Any help would be greatly appreciated.
You can have your macro being launched as a result of a Worksheet_Change() event.

blank row after data move to each column wise

Please refer my image, So you may get id MY Data source field
ea about my question,
column A field have 20k values rows, I want to Create blank row after data move to column-wise,( blank rows count=column wise count)
please give me solution vb MY Data source field
VBA or any formula MY DATA SOURCE IMAGE
Try this code
Sub Test()
Dim myAreas As Areas
Dim i As Long
Dim c As Long
Application.ScreenUpdating = False
Set myAreas = Columns(1).SpecialCells(2, 1).Areas
c = 1
For i = 1 To myAreas.Count
c = c + 1
Cells(myAreas(i)(1).Row, c).Resize(myAreas(i).Count).Value = myAreas(i).Value
Next i
Application.ScreenUpdating = True
End Sub

How to sort values of textboxes in vb?

I have two groups of textboxes, A and B and these are created dynamically.
My program should work like this:
1. A textboxes have corresponding B textboxes.
2. Then, B textboxes should be sorted by their values in ascending order.
3. Based on that order, the A textboxes' values will be sorted also.
EX:
A B
5 1
2 0
3 4
1 5
Output is: 2 5 3 1
Please help me out. Thanks!
Create arrays of the textbox controls you have and then write a simple bubble sort. Bubble sort is slow, but more than fast enough for small amounts of data.
Dim arrA() As Textbox = {a1, a2, a3, a4, a5}
Dim arrB() As Textbox = {b1, b2, b3, b4, b5}
Dim Changed as Boolean
Do
Changed = False
For i = 0 to arrB.Count - 2 'Stop at the second to last array item because we check forward in the array
If CInt(arrB(i).Text) > CInt(arrB(i + 1).Text) Then 'Next value is smaller than previous --> Switch values, also switch in arrA
Dim Temp as String = arrB(i + 1).Text
arrB(i + 1).Text = arrB(i).Text
arrB(i).Text = Temp
Temp = arrA(i + 1).Text
arrA(i + 1).Text = arrA(i).Text
arrA(i).Text = Temp
Changed = True
End If
Next
Loop Until Changed = False 'Cancle the loop when everything is sorted
Now the textbox values are sorted and you can display the results whereever you want.
To display the values in the labels, say called l1-l5:
Dim arrL() as Label = {l1, l2, l3, l4, l5}
For i = 0 to 4
arrL(i).Text = arrA(i).Text
Next

return single values for multiple records

Is there a way to merge multiple records then display only the highest value for each column? Example: A2:A25=names, B2=Grade1, C2=Grade2...etc.
First I removed duplicates in case there are exact duplicates. Then I sort on Name.
Can something be added to this code, based on column A-names, to display each name once with the highest value from each column?
=IF(B2="","Empty",IF(B2="High","High",IF(B2="Med","Med",IF(B2="Low","Low",""))))
Data Example
A1:name B1:Grade1 C1:Grade2...etc
A2:Joe B2:High C3:Low
A3:Joe B3:Med C3:High
A4:Dan B4:Low C4:Med
A5:Dan B5:Low C5:Low
__Results: Joe Grade1=high Grade2=high, Dan: Grade1=Low Grade2=Med
Record an Excel macro. Select first column. Click advanced filter.Choose copy to location and select a new column say X. Enable unique filter. Now click Ok. Now look at vba source to get the code to get unique elements in a column. Now assign Low as 0, Med as 1, High as 2 . loop through the rows and find the maximum grade1 , maximum grade2 etc corresponding to each element in column X and populate columns Y,Z etc. As and when you find a new maximum replace the existing. Now you will have the required data in columns X,Y,Z. Loop through them again and display in the format what you needed.
Decided to try VBA code for this one. It's a bit bruitish, but gets the job done.
Took a shortcut and made columns b and c numbers rather than strings. You could do a lookup function on the spreadsheet to make that conversion, or add an extra check in the code.
Sub find_high_values()
' subroutine to find max values of columns b and c against names
' assumes for simplicity that there are no more than 10 rows
' assumes values being checked to be numbers, if they are strings, additional loops would need to be done
Dim sName(10) As String, lBval(10) As Long, lCval(10) As Long 'arrays for original list
Dim iCountN As Integer, iUnique As Integer, iUniqueCount As Integer 'counters
Dim bUnique As Boolean
Dim rStart As Range, rOutput As Range 'ranges on worksheet
Dim lBmax(10) As Long, lCmax(10) As Long, sUniqueName(10) As String 'output arrays
Set rStart = ActiveSheet.Range("d6") 'Cell immediately above the first name in list
Set rOutput = ActiveSheet.Range("j6") 'cell reference for max value list
iUniqueCount = 1
For iCountN = 1 To 10 'set max counters to a min value
lBmax(iCountN) = 0
lCmax(iCountN) = 0
Next
For iCountN = 1 To 10 'step through each original row
sName(iCountN) = rStart.Offset(iCountN, 0).Value
lBval(iCountN) = rStart.Offset(iCountN, 1).Value
lCval(iCountN) = rStart.Offset(iCountN, 2).Value
bUnique = True 'Starter value, assume the name to be unique, changes to false if already in list
For iUnique = 1 To iCountN 'loop to check if it is a new name
If sUniqueName(iUnique) = sName(iCountN) Then bUnique = False
Next
If bUnique Then 'if new name, add to list of names
sUniqueName(iUniqueCount) = sName(iCountN)
iUniqueCount = iUniqueCount + 1
End If
Next
iUniqueCount = iUniqueCount - 1 'make the count back to total number of names found
For iUnique = 1 To iUniqueCount 'loop through names
For iCountN = 1 To 10 'loop through all values
If sName(iCountN) = sUniqueName(iUnique) Then
If lBval(iCountN) > lBmax(iUnique) Then lBmax(iUnique) = lBval(iCountN)
If lCval(iCountN) > lCmax(iUnique) Then lCmax(iUnique) = lCval(iCountN)
End If
Next
Next
'output section
rStart.Resize(1, 3).Select
Selection.Copy
rOutput.PasteSpecial xlPasteValues
For iUnique = 1 To iUniqueCount
rOutput.Offset(iUnique, 0).Value = sUniqueName(iUnique)
rOutput.Offset(iUnique, 1).Value = lBmax(iUnique)
rOutput.Offset(iUnique, 2).Value = lCmax(iUnique)
Next
End Sub