Ho do you hide / highlight rows based on the value cells - excel

I am new to excel and want to programmatically do two things.
Hide entire row if Code = 0
Set background and border to all cells in rows if columns I - O = 0
Any help would be appreciated. Thanks in advance.

Place the following code in a new module (VBA Editor, Insert->Module).
Public Sub ToggleRows()
Dim Sheet As Worksheet
Dim Row As Long
Set Sheet = ThisWorkbook.Worksheets("Sheet1") ' Replace with the name of your worksheet
' Get Row Number of last Row
Row = Sheet.UsedRange.Rows.Count + Sheet.UsedRange.Row - 1
Application.ScreenUpdating = False
While Row > 1 ' (exclude header row)
' Hide/Unhide Row depending on value in Column A
Sheet.Rows(Row).EntireRow.Hidden = IIf(Sheet.Cells(Row, "A").Value = 0, True, False)
Row = Row - 1
Wend
Application.ScreenUpdating = True
End Sub
After copying it you should have a "ToggleRows" macro in the list when you press the Macros button in the Developer tab.
If you wanted the macro to run automatically, you need to add a few more lines of code.
Open the code module for your worksheet and put the following
Private Sub Worksheet_Calculate()
ToggleRows
End Sub
For the second part of your question, you should be able to use Conditional Formatting.
There are many ways you can do it, one way is:
Select Columns I->O and select New Rule from the conditional formatting menu, and then select Use a formula to determine which cells to format
Enter a formula (example below) and then specify the formatting.
=IF(SUM(INDIRECT("I"&ROW()&":O"&ROW()))=0,TRUE,FALSE)
If Sum of Cells I-O equals 0, apply the formatting, otherwise dont.

Related

How to conditionally format a row in Excel VBA based on if first cell is empty?

What I'm trying to do is very simple, I just don't have much VBA / Excel experience to know how to do it.
I am working on a macro to do a few different things, I'm just stuck on this part.
What I want to do is go through all of my rows, and if the first cell in the row is empty, I want to select the entire row and UnMerge it. I know that if the first cell is empty, that row contains merged cells that I want unmerged.
I know that these two lines below will select row 2 and Unmerge it, but I need a way to loop through my data and find and unmerge the rows automatically, because the row numbers wont be the same every time.
Rows("2:2").Select
Selection.UnMerge
I want to do something like this:
For (each row) {
if (the first cell is empty) {
UnMerge all cells in that row;
}
}
I just don't know how to do that in VBA syntax.
Any help is appreciated!
This should do the job.
Sub UnmergeRows()
Dim R As Long ' loop counter: rows
With Worksheets("Sheet1") ' change tab name as required
' "B" should be the longest column in the worksheet
For R = 2 To .Cells(.Rows.Count, "B").End(xlUp).Row
If IsEmpty(.Cells(R, 1)) Then .Rows(R).MergeCells = False
Next R
End With
End Sub

Update formula when inserting or deleting rows

I have a spreadsheet for measuring costing. All the data is stored within a table. I want to add or delete rows from the table.
Columns A, B and C have data validation lists stored on another tab. Columns D and E are the number of units and number of workers. F, G and H are total rows. F is the unit cost without tax. That is all in a table but there is a formula out in cell M that the formula in cell F makes reference to.
The first row in the table is row 7 and the cell M formula is
=IF(OR(ISBLANK(A7),ISBLANK(B7),ISBLANK(C7)),0,VLOOKUP(CONCATENATE(A7," ",B7," ",C7),Service_Price_List,2,FALSE))
I can't code but I found some code to add and delete a row.
The formulas fill down within the table so it updates the formulas to the correct dynamic formulas in columns F, G and H. The cells within the table update correctly when I add a row but the first time I add a row after performing another action, the cell in column M is added but referencing is wrong.
You might be at row 8, 12 or 13 etc. (any row) but it will put this formula in the cell
=IF(OR(ISBLANK(A7),ISBLANK(B7),ISBLANK(C7)),0,VLOOKUP(CONCATENATE(A7," ",B7," ",C7),Service_Price_List,2,FALSE))
which is the formula from the first cell in the list. If I then try to add another row, (click the add row button twice), the cell will be blank.
As the insert and delete buttons work, I think I need a way to copy the formula from M7, which would be the top of the list. Or would it be better to have the formula inserted dynamically through VBA?
This is the code for my button to add a row:
Private Sub CommandButton3_Click()
Dim ws As Worksheet
Set ws = ActiveSheet
Dim tbl As ListObject
Set tbl = ws.ListObjects("table3")
'add a row at the end of the table
tbl.ListRows.Add
End Sub
This is the code for my button to delete a row:
Private Sub CommandButton4_Click()
Dim oLst As ListObject
Application.ScreenUpdating = False
ActiveSheet.Unprotect Password:=""
If ActiveSheet.ListObjects.Count > 1 Then
For Each oLst In ActiveSheet.ListObjects
With oLst
If .Name = "Table3" Then
If oLst.ListRows.Count > 1 Then
number_of_columns = .ListColumns.Count
oLst.ListRows(oLst.ListRows.Count).Delete
End If
End If
End With
Next
'ActiveSheet.Protect Password:=""
End If
End Sub

How to run a function at the end of pasted data in Excel?

I have an excel sheet where I paste some data and I want to run a function automatically on pasting data at the end of each column to count the number of cells that have some text and then give that row which contains formula a specific color.
For example, I paste the below data:
And now I want to run a function at the end of each column which will display the count of cells containing 'Error'.
The function for the first column would be =countif(A2:A9, "Error"), the function for the second column would be =countif(B2:B9, "Error") and so on.
Appreciate any help in advance.
Format a blank table and create a sum row(Click in table -> Tabletools -> Sum row):
Write in the sum row your formula like: =countif([Second],"Error")
Now you can simply copy in your data and it will calculates the occurence in the last row. On pasting the table in, it will move the sum row automaticly downwards.
Expanding on Doomenik's answer
Part 1 Set your data up as a table and insert a total row. Adjust the following table name as appropriate.
Then insert total row by going into the design tab, which appears when you are inside the table range, and checking the Total Row box
A total row will appear at the bottom of the table with a dropdown icon
Starting with column A you want to select the COUNTIF function to apply to the total row which means selecting More Functions from the drop down and then typing in COUNTIF.
In the box that appears enter the following:
Notice that the entire data area of column A in the table is referenced by [ID]. This will be automatically entered when you select the data area of the table A column range when specifying the range argument to COUNTIF i.e. when selecting as below:
The criteria argument is NA() for error.
You then drag the formula from column A, in the total row, across to column C and autofill will do the rest.
Part 2: Apply conditional formatting to the total row by using
=ISFORMULA(INDIRECT("Table1[#Totals]"))
in Excel 2016 or
=LEFT(FORMULATEXT(INDIRECT("Table1[#Totals]")),8) = "=COUNTIF"
in earlier versions.
Entering the formula:
Now, specifying the range to apply to:
I messed around with specifying the last row with
=INDIRECT("Table1[#Totals]")
Turns out, Excel still converts this to the current last row range e.g.
=$A$11:$C$11
And this updates even if i add rows to the table.
Part 3: Adding new rows by pasting
Now, how to handle the adding of rows by pasting? Insert the following code by Zak into the worksheet containing the table.
Then paste the new rows into the first column of the totals row and it will update and shift the totals down.
Option Explicit
Private Const SingleRowOnly As Boolean = False
Private Const MaxRowCount As Long = 100
Private Sub Worksheet_Change(ByVal Target As Range)
Dim ResizeRange As Range
Dim Table As ListObject
Dim TotalsShowing As Boolean
Dim ExpandTables As Boolean
Dim RowIndex As Long
Dim RowCount As Long
' Make sure sheet isn't protected
If Me.ProtectContents Then Exit Sub
' If already in a table, then exit
If Not Target.ListObject Is Nothing Then Exit Sub
' Make sure only one row is being changed
If Target.Rows.Count > 1 Then Exit Sub
' Make sure we're not in row 1
If Target.Row = 1 Then Exit Sub
' Make sure we're in the row right under the Totals row
If Target.Offset(-1, 0).ListObject Is Nothing Then Exit Sub
' Set table
Set Table = Target.Offset(-1, 0).ListObject
TotalsShowing = Table.ShowTotals
ExpandTables = Application.AutoCorrect.AutoExpandListRange
' If Totals not showing, exit
If Not TotalsShowing Then Exit Sub
' Make sure the selection is a contiguous range
If Target.Areas.Count > 1 Then Exit Sub
' Make sure Target range is within the table columns
If Target(1, 1).Column < Table.ListColumns(1).Range.Column Then Exit Sub
If Target(1, Target.Columns.Count).Column > Table.ListColumns(Table.ListColumns.Count).Range.Column Then Exit Sub
' Prepare to adjust table
Application.EnableEvents = False
Table.ShowTotals = False
Application.AutoCorrect.AutoExpandListRange = True
' Set the resize range
If WorksheetFunction.CountA(Table.Range(1, 1).Offset(Table.Range.Rows.Count + 1).Resize(1, Table.Range.Columns.Count)) > 0 Then
If Not SingleRowOnly Then
RowIndex = Target.Row
RowCount = RowIndex
Do Until WorksheetFunction.CountA(Me.Range(Me.Cells(RowCount, Table.Range(1, 1).Column), Me.Cells(RowCount, Table.Range(1, Table.ListColumns.Count).Column))) = 0 Or RowCount - RowIndex > MaxRowCount
RowCount = RowCount + 1
Loop
Set ResizeRange = Table.Range.Resize(Table.Range.Rows.Count + RowCount - RowIndex, Table.Range.Columns.Count)
Else
Set ResizeRange = Table.Range.Resize(Table.Range.Rows.Count + 1, Table.Range.Columns.Count)
End If
Else
Set ResizeRange = Table.Range.Resize(Table.Range.Rows.Count + 1, Table.Range.Columns.Count)
End If
' Make table adjustment
Table.Resize ResizeRange
' Put things back the way we found them
Application.AutoCorrect.AutoExpandListRange = ExpandTables
Table.ShowTotals = TotalsShowing
Application.EnableEvents = True
End Sub
Quoting from the link:
There are two constants declared at the top of this code.
SingleRowOnly. This specifies whether multiple rows should be included
in appending into the Table, or if only a single row should be.
MaxRowCount. As to not go crazy with appending rows to a Table
automatically, this is the maximum number of rows to include at any
one time. If SingleRowOnly is set to True, this constant is moot.
So you can adjust as appropriate.
With Autocomplete feature it should update column references automatically
EDIT
If you want to auto-do this, maybe you can try to paste the following formula at the end of your data:
=COUNTIF((INDIRECT(ADDRESS(ROW()-8;COLUMN()))):(INDIRECT(ADDRESS(ROW()-1;COLUMN()))); "Error")
Explanation
COUNTIF(range; pattern)
The range is specified with two INDIRECT functions. One pointing to the first row, and one pointing to the last one (those 8 and 1 respectively).
So the range looks like:
(INDIRECT(ADDRESS(ROW()-8;COLUMN()))) : (INDIRECT(ADDRESS(ROW()-1;COLUMN())))
NOTE that I assumed that you have 8 rows in total, but you can put any other number there

Highlighting rows where a cell contains a name from a list of names

How would I go about highlighting rows which contain a cell that contains a name from a list of names which I can specify?
I assume this is best done by a macro, but not sure where to start.
Place this code in a module
Option Explicit
Public Sub ApplyConditionalFormattingsFromAList()
'
' this code create multiple conditional formattings on current selected cells
' using a list of conditions along with its formattings defined in another worksheet.
' to use, just select the range and then run this code
'
Dim iRng As Range
Dim ApplyToRng As Range
Dim wsCondition As Worksheet
' determine the worksheet that define the conditions and formattings
' to do this, create a blank worksheet and name it "Names",
' then in the worksheet,
' column A of the worksheet should contain the names to highlight, start at [A1]
' column B of the worksheet should be filled with the highlight color to apply, working in pair with column A
Set wsCondition = Worksheets("Names")
' i make the Macro to apply to current selection.
' i made it this way so that you can reuse this code on different sheets multiple times
' anyway, you can change this to apply to a fixed range, which can then be turned into automatic running code.
' e.g. Set ApplyToRng = Columns("B")
Set ApplyToRng = Selection
' clear the conditional formattings of current selection. otherwise the list of conditional formatting will keep growing.
ApplyToRng.FormatConditions.Delete
' add the conditions
For Each iRng In wsCondition.Range([A1].Address, wsCondition.Cells(Rows.Count, 1).End(xlUp))
ApplyToRng.FormatConditions.Add Type:=xlTextString, String:=iRng.Value, TextOperator:=XlContainsOperator.xlContains
ApplyToRng.FormatConditions(ApplyToRng.FormatConditions.Count).SetFirstPriority
ApplyToRng.FormatConditions(1).Interior.Color = iRng.Offset(0, 1).Interior.Color
ApplyToRng.FormatConditions(1).StopIfTrue = False
Next iRng
End Sub
The worksheet "Names" would look like this
I would write it as a macro.
Begin with the first sheet.
Find the last used column and the last used row on that sheet.
Use these figures to iterate through each cell in each row.
For each cell you iterate through you need to go to the list and iterate through each item in the list. Compare the cell value and the list value, if they are the same then highlight the row and go the next row.
I hope that helps.

Excel vba copy row and paste one row down based on a number in cell

Hi guys need little help on VBA macro
I have data on sheet, in row 36 from A36 to Q36 that i need to copy one row down based on a number from cell S36. So if number in S36 is 5 that means that i need to copy row 36 five times from that row. Number in cell S36 goes from 0 if 0 do not copy.
This is method based upon ranges. You might want to use times_to_copy+1, I could not tell from your question. I have not tested if this works correctly with formulas, etc. The code assumes the active sheet is the one where you want the code to apply.
Sub copy_cat()
Dim main_range As Range
Dim times_to_copy As Integer
Dim copy_to_range As Range
If (times_to_copy > 0) Then
Set main_range = ActiveSheet.Range("A36:Q36")
times_to_copy = ActiveSheet.Range("S36").Value
Set copy_to_range = main_range.Resize(times_to_copy, main_range.Columns.Count)
' or Set copy_to_range = main_range.Resize(times_to_copy+1, main_range.Columns.Count) dunno
copy_to_range = main_range.Value
End If
End Sub

Resources