Excel VBA - hiding rows if other rows are hidden - excel

Sorry, I have searched but have only found solutions similar to mine that I think should work! I have a button set up in a financial worksheet to hide rows that have value=0 in each of four colums. This is working fine except then I have a seperation row that I also want to hide if a subtotal row itself is hidden. It is hiding that row that I am having problems with:
Private Sub CommandButton1_Click()
'macro hides rows if all four columns contain zero values
'declare and initialize variables
Dim Col1 As String 'stores the column letter for the first column to examine
Col1 = "C"
Dim Col2 As String 'stores the column letter for the second column to examine
Col2 = "D"
Dim Col3 As String 'stores the column letter for the third column to examine
Col3 = "E"
Dim Col4 As String 'stores the column letter for the fourth column to examine
Col4 = "F"
Dim ListBottom As String 'stores the cell reference of the column that is populated for each record
ListBottom = "A65536"
Dim FirstRow As Long 'first row with data to inspect
FirstRow = 3
'declare and initialize system variables
Dim LastRow As Long 'store the last row with data
LastRow = 300 'Range(ListBottom).End(xlUp).Row 'moves up to the last row with data
Application.ScreenUpdating = False
For x = FirstRow To LastRow
If Cells(x, Col1).Value = "0" And Cells(x, Col2).Value = "0" And Cells(x, Col3).Value = "0" And Cells(x, Col4).Value = "0" Then
Cells(x, Col1).EntireRow.Hidden = True
'Expenses section tenant, utilites and maint - hides spacing and underlines if data rows are hidden'
If Cells("C73").Value = 0 And Cells("D73").Value = 0 And Cells("E73").Value = 0 And Cells("F73").Value = 0 Then
Rows("72").EntireRow.Hidden = True
End If
If Rows("82").EntireRow.Hidden = True Then
Rows("81").EntireRow.Hidden = True And Rows("83").EntireRow.Hidden = True
End If
End If
Next x
Application.ScreenUpdating = True
End Sub
The top part hiding the 0 rows works fine, it is in the bottom section that I can't get to work. I have included the two different ways (starting in line 29) I have tried and neither one works.
If there is a more elegant way to do this, I am certainly open to it. Thank you very much for your help!

Don't panic, the solution should be quite simple (and I'll try to provide some "elegance" to your code) :D
Private Sub CommandButton1_Click()
' You don't need to Dim all those variables. Also they were constants not variables :)
' In case you need to declare a constant use "Const x As yourType = value"
Dim ListBottom As String 'stores the cell reference of the column that is populated for each record
Dim FirstRow As Long 'first row with data to inspect
Dim LastRow As Long 'store the last row with data
ListBottom = "A65536" ' You can address the last cell with some commands like .SpecialCells or .End. I strongly suggest googling them up ;)
FirstRow = 3
LastRow = 300 'moves up to the last row with data
Application.ScreenUpdating = False
For x = FirstRow To LastRow
If Cells(x, 3).Value = "0" And Cells(x, 4).Value = "0" And Cells(x, 5).Value = "0" _
And Cells(x, 6).Value = "0" Then ' WARNING: "0" indicates a STRING in which
' you find a Chr 0. When you (like below) say = 0 without the "", it means
' that you're comparing to a NUMERIC value. In this case, it would do good
' storing your values in some variables with a numeric type (Integer, Long,
' Double) or a string and then compare them as fail-safe!
Cells(x, 3).EntireRow.Hidden = True
'Expenses section tenant, utilites and maint - hides spacing and underlines if data rows are hidden'
If Cells("C73").Value = 0 And Cells("D73").Value = 0 And Cells("E73").Value = 0 And Cells("F73").Value = 0 Then
Rows("72").EntireRow.Hidden = True
End If
If Rows("82").EntireRow.Hidden = True Then
Rows("81").EntireRow.Hidden = True ' DANGER: for multiple commands you
' can't simply give "command" AND "command. All things that are between
' "Then" and "End If" are executed sequentially
Rows("83").EntireRow.Hidden = True
End If
End If
Next x
Application.ScreenUpdating = True
End Sub
Didn't test it but should work. I recommend doing some test with those things I said back in the code, they could help you a lot in the future!

What about this?
Private Sub CommandButton1_Click()
'macro hides rows if all four columns contain zero values
'declare and initialize variables
Dim Col1 As String 'stores the column letter for the first column to examine
Col1 = "C"
Dim Col2 As String 'stores the column letter for the second column to examine
Col2 = "D"
Dim Col3 As String 'stores the column letter for the third column to examine
Col3 = "E"
Dim Col4 As String 'stores the column letter for the fourth column to examine
Col4 = "F"
Dim ListBottom As String 'stores the cell reference of the column that is populated for each record
ListBottom = "A65536"
Dim FirstRow As Long 'first row with data to inspect
FirstRow = 3
'declare and initialize system variables
Dim LastRow As Long 'store the last row with data
LastRow = 300 'Range(ListBottom).End(xlUp).Row 'moves up to the last row with data
Application.ScreenUpdating = False
For x = FirstRow To LastRow
If Cells(x, Col1).Value = "0" And Cells(x, Col2).Value = "0" And Cells(x, Col3).Value = "0" And Cells(x, Col4).Value = "0" Then
Cells(x, Col1).EntireRow.Hidden = True
'Expenses section tenant, utilites and maint - hides spacing and underlines if data rows are hidden'
Cells(x+1, Col1).EntireRow.Hidden = True
End If
Next x
Application.ScreenUpdating = True
End Sub
Instead of veryfing if a row is hidden, hide the secondary row at the same time as you hide the main one.

Related

Split array and compare values to separate columns

Im trying to create a function which scans a column (job-trav-seq) and splits the values in each cell within a given range. It then compares these values to comparable cells in separate columns (so for instance job-trav-seq would have a cell 58546-05-10; this function would remove the dashes and compare the 58546 to job number, 05 to traveller ID and 07 to sequence No.
Basically, the function needs to first takes the A column (JobTravSeq) and breaks it apart into individual variables. (variable 1 should be compared with values in column B, values in variable 2 should be compared with column C and values in variable 3 should be compared with column D)
A loop should go up through the column cells as long as variable 1 = values in column B and variable 2 = values in column C (this is rowStart); this should be stored as a variable
A second loop should occur (rowEnd); which should loop down though the column cells as long as variable 1 = values in column B and variable 2 = values in column C; this should be stored as a variable
The code should then traverse between rowStart and rowEnd and check if variable 3 = values in column D, if it does then place an asterisk (or something similar) in front of the value to mark it as a current task
What im starting with: Sample Doc
What im trying to achieve: SampleDocOutput
any help would be most appreciated
heres my code for reference:
Sub SampleDocOrganise()
Dim i As Integer
Dim LastRow, rowCompare As Long
Dim variArr, rowStart, rowEnd, rangeID As Variant
Dim JobTravSeqRng As Range, jobNoRng As Range, TravellerRng As Range,
opSeqRng As Range, _
rng_JobTravSeq As Range, rng_JobNo As Range, rng_Traveller As Range,
rng_opSeq As Range
Set JobTravSeqRng = Range("A:A")
Set jobNoRng = Range("B:B")
Set TravellerRng = Range("C:C")
Set opSeqRng = Range("D:D")
For Each JobTravSeq In Selection
Str_Array = Split(JobTravSeq, "-")
For h = 0 To UBound(Str_Array)
Range("A:A").Find (Str_Array)
Range.Offset(, h + 1) = Str_Array(h)
For rowStart = 4 To Rows.Count
If Worksheets("Sheet1").Cells(Str_Array, 1).Value = jobNoRng.Value Then
If Cells(Str_Array, 2).Value = jobNoRng.Value Then
Cells.Value = rowStart
End If
End If
Next rowStart
For rowEnd = LastRow To 4 Step -1
If Cells(Str_Array, 1).Value = Range("B:B").Value Then
If Cells(Str_Array, 2).Value = Range("C:C").Value Then
Cells.Value = rowEnd
End If
End If
Next rowEnd
For rowCompare = rowStart To rowEnd
For Each opSeqArr In Str_Array
If Cells(Str_Array, 3).Value = Range("D:D").Value Then
If Cells(Str_Array, 1).Value = Range("B:B") Then
ActiveCell.Characters(0, 0).Insert (" P ")
With ActiveCell.Characters(0, Len(" P ")).Font
.Name = "OpSeq_Equals"
.Bold = True
.Color = -16776961
End With
MsgBox cell.Value = "*" & ""
' if cell changes then go to next loop
Else
' if cell changes then go to next loop
End If
End If
Next
Next
Next h
Next
End Sub
Sub MsgboxTasks() 'should display all rows that contain an asterisk in opSeq (current tasks)
End Sub

Is it possible to generate multiple copies of a value based on count data for that value?

Didn't know how to phrase my problem into a simple question, sorry!
I have a spreadsheet that is in the incorrect format for what I need to do.
As you can see, each row is a species of fish, while the column is a unique transect, composed of (a) year, (b) site, (c) reef zone and finally (d) replicate number. The number on the overlap is the number of times this species was recorded in that specific transect.
What I would like to do, is generate a new sheet where each record of a fish on the original spreadsheet is an entire row. This would give a spreadsheet where each individual fish that was recorded now gets its own line, and it would look like this:
I have very little understanding of anything more than basic Excel, so any help with this would be gratefully appreciated!
Depending on how big your data set is, code might not be necessary. It looks like you could flash fill most of the columns, then sort and paste in your specific transects and species. If you felt you still needed code, then a simple For Next loop would suffice to write your required unique values.
i.e.:
For i = 2 to LastRow
If
'code
Then
Next i
Const startRow As Integer = 5
Const newSheet As String = "TransposedData"
Sub makeDownwards()
Dim row As Integer, ws As Worksheet, ows As Worksheet
Dim oRow As Integer, col As Integer, repNumber As Integer, i As Integer
Dim fName As String, sName As String, year As String, site As String, none As String, transect As String
row = startRow
Set ws = ActiveSheet
Set ows = ThisWorkbook.Worksheets.Add(after:=ActiveSheet)
ows.Name = newSheet
oRow = 2
ows.Range("A1").Resize(1, 6) = Split("Fish Name ,Fish Spicies ,Year ,Site ,None ,Transect", ",")
ows.Range("A1:F1").Font.Bold = True
ows.Range("A1:F1").BorderAround xlContinuous, xlThin
ows.Range("A1:F1").HorizontalAlignment = xlCenter
Do While (ws.Cells(row, 1) <> "")
row = row + 1
col = 3
fName = ws.Cells(row, 1)
sName = ws.Cells(row, 2)
Do While ws.Cells(1, col) <> ""
repNumber = ws.Cells(row, col).Value
year = ws.Cells(1, col)
side = ws.Cells(2, col)
none = ws.Cells(3, col)
transect = ws.Cells(4, col)
For i = 1 To repNumber
ows.Range("A" & oRow).Resize(1, 6) = Array(fName, sName, year, side, none, transect)
oRow = oRow + 1
Next
col = col + 1
Loop
Loop
End Sub

How to count a pair of texts in one column that are few rows apart using vba?

In workbook A, I'm trying to count when a text, "Dr" occurs then within 5 rows after it, how many cells are blank or the cell is either a text, "Nr" or "Cr".
In another word, I'm trying to count the numbers of pairs of "DR-blank(within 5 rows after DR)", "DR-NF(within 5 rows after DR)", and "DR-CR(within 5 rows after DR)". The data set looks like this:
Column A 0 1 2 3 4 5 6 7 8
Column B Dr Cr Dr Nr
And then I want to copy the result to workbook B.
I've been tried to use offset:
If Range("B2:B901").Value = "D" Then
'V3 = Application.WorksheetFunction.CountBlank(.Range("B2:B901").Offset(5, 0))
Wb.Worksheets("Sheet1").Cells(Rows.Count, "M").End(xlUp).Offset(1, 0).Value = V3
But I always got a "0" in return, meaning the logic wasn't quite right to capture what I intended to do.
Could someone help with the codes? Really appreciated!
This code will iterate through every cell in the range you provide (in this case B1:B901 in sheet1) and if it contains the vale Dr it will then iterate through the subsequent 5 cells to check if they contain the values you are looking for.
It will output the contents of column A and column B to a new workbook, together with your count of nr, cr and blank in columns c, d and e respectively.
Option Compare Text 'this tells VBA that you want you string comparisons to NOT be
'case sesitive. If you want case to be taken into account, then leave
'this line out.
Sub test()
Dim cll As Range
Dim vCellValue As Variant
Dim iterator As Integer
Dim vCountBlank As Integer
Dim vCountCr As Integer
Dim vCountNr As Integer
Dim wb2 As Workbook
Set wb2 = Workbooks.Add
For Each cll In Sheet1.Range("B2:B901")
vCountBlank = 0
vCountCr = 0
vCountNr = 0
If cll.Value = "Dr" Then
For iterator = 1 To 5
vCellValue = cll.Offset(iterator, 0).Value
If vCellValue = "Nr" Then vCountNr = vCountNr + 1
If vCellValue = "Cr" Then vCountCr = vCountCr + 1
If vCellValue = "" Then vCountBlank = vCountBlank + 1
Next iterator
End If
wb2.Sheets(1).Cells(cll.Row, 1).Value = cll.Offset(0, -1).Value
wb2.Sheets(1).Cells(cll.Row, 2).Value = cll.Value
wb2.Sheets(1).Cells(cll.Row, 3).Value = vCountNr
wb2.Sheets(1).Cells(cll.Row, 4).Value = vCountCr
wb2.Sheets(1).Cells(cll.Row, 5).Value = vCountBlank
Next cll
Set wb2 = Nothing
End Sub

Coloring Excel rows

So i found this script on this site to color rows with the same cell-data and change the color when the celldata changes and it seems to work just fine, but i have two minor issues
It seems to only apply to the first 900 rows (I have an excel list with 8000+ rows)
It colors the entire row, is there a way to make it only color a certain part of the row?
Thanks in advance! here's the script:
Public Sub HighLightRows()
Dim i As Integer
i = 2 'start at 2, cause there's nothing to compare the first row with
Dim c As Integer
c = 2 'Color 1. Check http://dmcritchie.mvps.org/excel/colors.htm for color indexes
Do While (Cells(i, 1) <> "")
If (Cells(i, 1) <> Cells(i - 1, 1)) Then 'check for different value in cell A (index=1)
If c = 2 Then
c = 37 'color 2
Else
c = 2 'color 1
End If
End If
Rows(Trim(Str(i)) + ":" + Trim(Str(i))).Interior.ColorIndex = c
i = i + 1
Loop
End Sub
Try this:
Public Sub HighLightRows()
Const START_ROW As Long = 2 '<< use a Constant for fixed values
Const VALUE_COL As Long = 1
Dim rw As Range, emptyCells As Long, i As Long, currentValue, tmp
Dim arrColors
arrColors = Array(37, 2)
Set rw = ActiveSheet.Rows(START_ROW)
currentValue = Chr(0) 'dummy "current value"
Do While emptyCells < 10 'quit after 10 consecutive empty cells
tmp = rw.Cells(VALUE_COL).Value
If Len(tmp) > 0 Then
If tmp <> currentValue Then
i = i + 1
currentValue = tmp 'save the new value
End If
'assign the color to a specific set of cells in the row
' starting at cell 1 and 5 columns wide
rw.Cells(1).Resize(1, 5).Interior.ColorIndex = arrColors(i Mod 2)
emptyCells = 0 'reset empty row counter
Else
emptyCells = emptyCells + 1 'increment empty row counter
End If
Set rw = rw.Offset(1, 0) 'next row
Loop
End Sub
It looks like the code only evaluates if the cell is the same as the cell above it. Conditional formatting, as John Coleman said, would be more effective. With it values in the whole column can be evaluated instead of just adjacent ones. And, if I'm not mistaken, there's a setting to look for dup values since Excel 2007, so there doesn't have to be some kind of formula kung-fu to do it.
Unless I'm missing something, it's as simple as Conditional Formatting -> Highlight Cell Rules -> Duplicate Values.

Hide the cells with the value of "0" and then shift all cells up

I have data in range -D2:G61 and i am checking if the column F has zero value in it then i hide that row and cells below it will shift up.
Tried this but it's deleting the entire rows-
Sub Hide_rows()
Dim Col1 As String
Col1 = "F"
Dim ListBottom As String
ListBottom = "A61"
Dim FirstRow As Long
FirstRow = 2
Dim HideOrGroup As String
HideOrGroup = "Group"
Dim LastRow As Long
LastRow = Range(ListBottom).End(xlUp).Row
Application.ScreenUpdating = False
For x = FirstRow To LastRow
If Cells(x, Col1).Value = "0" Then
If HideOrGroup = "Group" Then
Rows(x).Group
End If
Cells(x, Col1).EntireRow.Hidden = True
End If
Next x
Application.ScreenUpdating = True
End Sub
We cannot hide individual cells rather we can delete them on the cost of losing them forever and shift the following cell up. This can be done in two line of code.
Range("D15:G15").Select
Selection.Delete Shift:=xlUp
If the date you are hiding is not going to be referenced in the future, you may follow this approach else there doesn't seems to be another way expect taking a back of original data.
HAPPY VBA :)

Resources