VBA Macro to delete unchecked rows using marlett check - excel

I don't really have much of a background in VBA, but I'm trying to create a macro where, on the push of a button all rows that do not have a check mark in them in a certain range are deleted. I browsed some forums, and learned about a "marlett" check, where the character "a" in that font is displayed as a check mark. Here is the code I have to generate the "marlett check" automatically when clicking a cell in the A column in the appropriate range:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Cells.Count > 1 Then Exit Sub
If Not Intersect(Target, Range("A10:A111")) Is Nothing Then
Target.Font.Name = "Marlett"
If Target = vbNullString Then
Target = "a"
Else
Target = vbNullString
End If
End If
End Sub
I then have another macro (assigned to a button) that actually deletes the rows without a check mark in the "A" column when the button is pressed:
Sub delete_rows()
Dim c As Range
On Error Resume Next
For Each c in Range("A10:A111")
If c.Value <> "a" Then
c.EntireRow.Delete
End If
Next c
End Sub
Everything works, but the only problem is that I have to press the button multiple times before all of the unchecked rows are deleted!! It seems like my loop is not working properly -- can anyone please help??
Thanks!

I think this may be due to how you're deleting the rows, you might be skipping a row after every delete.
You might want to change your for-each for a regular for loop. so you can control the index you'r working on. see this answer or the other answers to the question to see how to do it.
Heres a modified version that should suit your (possible) problem.
Sub Main()
Dim Row As Long
Dim Sheet As Worksheet
Row = 10
Set Sheet = Worksheets("Sheet1")
Application.ScreenUpdating = False
Do
If Sheet.Cells(Row, 1).Value = "a" Then
'Sheet.Rows(Row).Delete xlShiftUp
Row = Row + 1
Else
'Row = Row + 1
Sheet.Rows(Row).Delete xlShiftUp
End If
Loop While Row <= 111
Application.ScreenUpdating = True
End Sub
Update
Try the edit I've made to the if block, bit of a guess. Will look at it when I have excel.
It does go into an infinite loop regardless of the suggested change.
The problem was when it got near the end of your data it continually found empty rows (as theres no more data!) so it kept deleting them.
The code below should work though.
Sub Main()
Dim Row As Long: Row = 10
Dim Count As Long: Count = 0
Dim Sheet As Worksheet
Set Sheet = Worksheets("Sheet1")
Application.ScreenUpdating = False
Do
If Sheet.Cells(Row, 1).Value = "a" Then
Row = Row + 1
Else
Count = Count + 1
Sheet.Rows(Row).Delete xlShiftUp
End If
Loop While Row <= 111 And Row + Count <= 111
Application.ScreenUpdating = True
End Sub

Related

Delete Empty Columns VBA

I would like to delete all of the empty columns in my worksheet. I found some code online, but it is not working as I wish.
Sub deleteEmptyColumns()
' Set variables
Dim i As Long
Dim lngLastColumn As Long
' Get last column
lngLastColumn = ActiveSheet.Cells.SpecialCells(xlCellTypeLastCell).Column
' Turn off screen updating
Application.ScreenUpdating = False
' Loop from last column cell to 1
For i = lngLastColumn To 1 Step -1
' Check if column has any values
If Application.WorksheetFunction.CountA(Columns(i)) = 0 Then
' Delete column
Columns(i).Delete
End If
Next i
' Turn on screen updating
Application.ScreenUpdating = True
End Sub
Here is a screenshot of my workbook. There are lots of empty columns, and I would like to delete them.
Any help would be greatly appreciated!
Assuming missing data is missing uniformly and last row is data and not totals or something else the following solution should work even if there are formulas but the formulas will not work after this solution so back things up:
Sub Delete_Empty_Columns()
Dim Last_Column_No As Long
Dim Last_Row_No As Long
Dim i As Long
Last_Column_No = Columns(ActiveSheet.UsedRange.Column + ActiveSheet.UsedRange.Columns.Count - 1).Column
Last_Row_No = ActiveSheet.UsedRange.Rows.Count + ActiveSheet.UsedRange.Rows(1).Row - 1
'Coppy everything in used range and paste only values back
'This will clear all formulas
ActiveSheet.Range("A1", Cells(Last_Row_No, Last_Column_No)).Copy
ActiveSheet.Range("A1").PasteSpecial xlPasteValues
For i = 1 To Last_Column_No
If Cells(Last_Row_No, i) = "" Then
Columns(i).Delete
End If
Next i
End Sub

Hiding/unhiding excel sheets based of a matrix

I have a macro that works, but it's not very effective and could be done a lot better.
I simply have a list with all sheet names(they could change so it needs to be dynamic) in one row and in the next row I have a "yes/no" answer that displays if the sheet should be hidden or not.
Example:
Sheet 1, sheet2, sheet3, sheet4,
yes, yes, no, yes
My code so far:
Sub HidingSheets()
'Checking the first sheet
'-------------------------------------------------------------------------------------------
Sheets(Worksheets("Sheet1").Range("E9").Value).Visible = True
Sheets(Worksheets("Sheet1").Range("E9").Value).Activate
If ActiveSheet.Range("A1") = "NO" Then
ActiveSheet.Visible = False
End If
'-------------------------------------------------------------------------------------------
'Checking the second sheet
'-------------------------------------------------------------------------------------------
Sheets(Worksheets("Sheet1").Range("F9").Value).Visible = True
Sheets(Worksheets("Sheet1").Range("F9").Value).Activate
If ActiveSheet.Range("A1") = "NO" Then
ActiveSheet.Visible = False
End If
'-------------------------------------------------------------------------------------------
End Sub
I basically do it manually per every sheet instead of a loop, and this also requires that I need the "yes/no" displayed in every sheet(the "if" formula checking if A1 = "no"). The "yes/no" that s displayed in cell A1 is taken from the matrix that I explained before.
Note: The matrix could be "tranposed", the direction of it doesn't matter.
Thank you in advance if you can help me.
My second attempt is this:
Sub Hiding2()
Dim i As interger
For i = 1 To 10
a = ActiveSheet.Range("E9").Value
If Offset(a(1, 0)) = YES Then
Sheets(a).Visible = True
Else
Sheets(a).Visible = False
End If
Next i
End Sub
But I dont know how to reference the cells that I need, and then get them to move over for every "i".
Sub HideWorksheets()
Dim Cell As Range
Dim Data As Range: Set Data = Worksheets("Sheet1").Range("E9:N9")
On Error Resume Next
For Each Cell In Data
Worksheets(Cell.value).Visible = IIf(Cell.Offset(1, 0) = "YES", xlSheetHidden, xlSheetVisible)
Next Cell
End Sub
You can use Cells instead of Range. With it, you can use column numbers to iterate over some range of columns. There is also other possibilities to exit the code... it depends on the data in your worksheet.
Sub Hiding()
Dim sh as Worksheet, col as Integer
For col = 5 to 100
shName = Worksheets("Sheet1").Cells(9, col).Value
On Error GoTo TheEnd ' in case there is no such sheet
Set sh = Worksheets(shName)
If UCase(sh.Range("A1").Value) = "YES" Then
sh.Visible = xlSheetVisible
Else
sh.Visible = xlSheetHidden
End If
Next col
TheEnd:
End Sub

Deleting worksheet row based on value tied to a table

I have a worksheet with two tables on it located starting in column B. In Column A I have a COUNTA formula that is tied to a delete blank rows button. My code works great to delete the table row but i need it to delete the entire worksheet row so that it also deletes the formula in column A instead of it continuously shifting down as rows are added or deleted.
The trouble is that I have two tables on the sheet so I need the deletion row action to refer only to the Local_1 table and the loop to stop when it reaches the end of that table.
Any suggestions on how to delete the entire row and not just the table row?
Dim i As Long
Application.ScreenUpdating = False
ActiveSheet.Unprotect Password:=pswStr
Rows.EntireRow.Hidden = False
With ActiveSheet.ListObjects("Local_1")
For i = .ListRows.Count To 1 Step -1
If .ListRows(i).Range.Cells(0) <= 0 Then
.ListRows(i).Delete
End If
Next i
End With
List Entire Row
To not cramp your style, just replace
If .ListRows(i).Range.Cells(0) <= 0 Then
.ListRows(i).Delete
End If
with
If .ListRows(i).Range.Cells(1) <= 0 Then 'as Tim Williams mentioned
'.ListRows(i).Delete
ActiveSheet.Rows(Range(.DataBodyRange.Address).Row + i - 1).Delete
End If
But (to cramp your style) I would strongly suggest you use (declare) variables like this:
Sub ListEntireRow()
Dim i As Long
Dim oWs As Worksheet
Dim oList As ListObject
Application.ScreenUpdating = False
Set oWs = ActiveSheet
Set oList = oWs.ListObjects("Local_1")
oWs.Unprotect Password:=pswStr
Rows.EntireRow.Hidden = False
With oList
For i = .ListRows.Count To 1 Step -1
If .ListRows(i).Range.Cells(1) <= 0 Then
' .ListRows(i).Delete
oWs.Rows(Range(.DataBodyRange.Address).Row + i - 1).Delete
End If
Next i
End With
Application.ScreenUpdating = True
End Sub
Now you have the Intellisense for the Worksheet (oWs) and the ListObject (oList) working for you i.e. you can see their properties and methods.

Excel VBA strip string into another cell

I´m trying to create an Excelsheet that runs multiple VBA scripts after writing anything in A Column.
One part I would like some help with is that the character 2,3 and 4 written in A column (any row) should be written i D column same row.
I also would like to remove any information i D Column if I remove the text from A Column.
I have manage to create a script that calls modules after writing information i a cell in A Column
Private Sub Worksheet_Change(ByVal Target As Range)
If Intersect(Target, Me.Range("A:A")) Is Nothing Then Exit Sub
Application.EnableEvents = False 'to prevent endless loop
On Error GoTo Finalize 'to re-enable the events
Call Modul1.Module
Finalize:
Application.EnableEvents = True
End Sub
Any help would be much appriciated.
This is what I have for now.
It doesn´t work to clear value on all rows only some of them?!
Sub Lokation()
Dim n As Long, i As Long, j As Long
n = Cells(Rows.Count, "A").End(xlUp).Row
j = 2
For i = 2 To n
If Cells(i, "A").Value = vbNullString Then
Cells(j, "D").Value = ("")
Else
Cells(j, "D").Value = Mid(Cells(j, "A").Value, 2, 3)
End If
j = j + 1
Next i
End Sub
You can wrap this whole piece up in just the Worksheet_Change event if you use the following:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim columnAcell As Range
If Intersect(Target, Me.Range("A:A")) Is Nothing Then Exit Sub
Application.EnableEvents = False
For Each columnAcell In Target.Cells
columnAcell.Offset(0, 3) = Mid(columnAcell, 2, 3)
Next
Application.EnableEvents = True
End Sub
Instead of specifically writing to column D, I've used a cell offset of 3 columns from Target. As this code only looks at column A currently, it will always offset to column D.
Things to watch out for though -
Altering cell(A1) which contains the header would result in cell(D1) being altered. You can prevent this by changing the Intersect range from A:A to something like A2:Axxxx
Deleting the entirety of column A would result in the loop running for a very long time, not to mention causing column D to move to column C. You may want to prevent users from being able to do this.

Rearrange Row data based on cells values automatically

Sheet1 Have 90 columns and 288 rows. Some cells of each row have value and some are blank (containing formula). I want to rearrange each row data in Sheet2 as value contain cells come to left and blank goes to right. I don’t want to remove the blank cells so, if a row doesn’t have any data will not got removed. Row order is very important in my case.
Sheet1 got updated each 5 minutes, if there is any possibility to update Sheet2 each 5 minute that will be really great.
Example:
Sheet1
Sheet1
Sheet2Sheet2
NB: My VBA or Macro knowledge is very basic. If I’m not asking too much, explanation to apply the solutions will be great.
Using office 365 latest version
If you are having a hard time finding a place to start, you could try this Worksheet_Change event macro for Sheet1.
Option Explicit
Private dALL As Double
Private Sub Worksheet_Change(ByVal Target As Range)
If Application.Sum(Target.Parent.UsedRange.Cells) <> dALL Then
dALL = Application.Sum(Target.Parent.UsedRange.Cells)
On Error GoTo bm_Safe_Exit
'suspend events so nothing on Sheet2 gets triggered
Application.EnableEvents = False
Dim a As Long, i As Long, j As Long, aVALs As Variant
aVALs = Target.Parent.UsedRange.Cells.Value2
For i = LBound(aVALs, 1) To UBound(aVALs, 1)
For j = LBound(aVALs, 2) To UBound(aVALs, 2) - 1
If Not CBool(Len(aVALs(i, j))) Then
For a = j + 1 To UBound(aVALs, 2)
If CBool(Len(aVALs(i, a))) Then
aVALs(i, j) = aVALs(i, a)
aVALs(i, a) = vbNullString
Exit For
End If
Next a
End If
Next j
Next i
With ThisWorkbook.Worksheets("Sheet2")
.UsedRange.Clear
.Cells(1, 1).Resize(UBound(aVALs, 1), UBound(aVALs, 2)) = aVALs
End With
End If
bm_Safe_Exit:
Application.EnableEvents = True
End Sub

Resources