Add Total Row To Each Worksheet in Workbook - vba

I have been using this syntax to add a total row to one worksheet
With ActiveSheet
If Application.WorksheetFunction.CountA(.Cells) <> 0 Then
LastRow = .Cells.Find(What:="*", _
After:=.Range("A1"), _
LookAt:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
Else
LastRow = 1
End If
End With
Range("C" & LastRow + 1).FormulaR1C1 = "=SUM(R[-" & LastRow & "]C:R[-1]C)"
Range("C" & LastRow + 1 & ":L" & LastRow + 1).FillRight
I thought to add it to all worksheets in the workbook, I would just need to add a foreach loop like so
Dim ws As Worksheet
For Each ws In ActiveWorkbook.Worksheets
'code above
Next
But that did not fit the bill as since I use With ActiveSheet it just adds multiple "Total" rows to the selected worksheet.
How can I add a total row to each worksheet in my workbook?

Try this. I did not tested it. you test the code and let me know if there are errors, i will then work on it -
Dim ws As Worksheet
For Each ws In ActiveWorkbook.Worksheets
With ws
If Application.WorksheetFunction.CountA(.Cells) <> 0 Then
LastRow = .Cells.Find(What:="*", _
After:=.Range("A1"), _
LookAt:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
Else
LastRow = 1
End If
End With
ws.Range("C" & LastRow + 1).FormulaR1C1 = "=SUM(R[-" & LastRow & "]C:R[-1]C)"
ws.Range("C" & LastRow + 1 & ":L" & LastRow + 1).FillRight
Next

You just need to make sure that you are activating each worksheet:
Dim ws As Worksheet
For Each ws In ActiveWorkbook.Worksheets
ws.activate
'code above
Next
should do it.

Related

VBA deleting rows based on cell vale

I've written the following code where i want to find the value "BEST Cards Raised:" in column B and where ever this value is delete this and all subsequent rows with data in column B.
I thought what i've written would work but its currently deleting all rows and I cant figure it out :(
Dim lastRow As Long, found As Range
With ActiveSheet
Set found = .Range("B1:B" & .Cells(.Rows.Count, "B").End(xlUp).Row).Find("BEST Cards Raised:")
If Not found Is Nothing Then
lastRow = .Cells.Find(What:="*", _
After:=.Cells(1, 1), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
If lastRow >= found.Row Then
Debug.Print .Rows(found.Row & ":" & lastRow).EntireRow.Delete
End If
End If
End With
If also deleting the row where found then perhaps try the following:
Option Explicit
Public Sub DeleteRows()
Dim lastRow As Long, found As Range
With ThisWorkbook.Worksheets("Sheet1") '<your sheet
Set found = .Range("B1:B" & .Cells(.Rows.Count, "B").End(xlUp).Row).Find("BEST Cards Raised:")
If Not found Is Nothing Then
lastRow = .Cells.Find(What:="*", _
After:=.Cells(1, 1), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
If lastRow >= found.Row Then
.Rows(found.Row & ":" & lastRow).EntireRow.Delete
End If
End If
End With
End Sub
Post debugging
Dim lastRow As Long, foundRow As Variant
With ThisWorkbook.Worksheets("Sheet8")
lastRow = .Cells(.Rows.Count, "B").End(xlUp).Row
foundRow = Application.Match("BEST Cards Raised:", .Range("B1:B" & lastRow), 0)
If IsError(foundRow) Then Exit Sub
If lastRow >= foundRow Then .Rows(foundRow & ":" & lastRow).EntireRow.Delete
End With
Try this (comments in code):
Sub DeleteRows()
Dim ws As Worksheet, lastRow As Long, i As Long, j As Long
Set ws = ThisWorkbook.Worksheets("Sheet1")
lastRow = ws.Cells(ws.Rows.Count, 2).End(xlUp).Row
'determine where to start deleting rows
For i = 1 To lastRow
If Trim(ws.Cells(i, 2).Value) = "BEST Cards Raised:" Then Exit For
Next
'delete all rows from last to found row, looping backwards
For j = lastRow To i Step -1
ws.Rows(j).Delete
Next
End Sub

Excel VBA file increasing

I have a shared excel file (xlsm) where about 10 users enter into the cells a2 - x2 and then click a button(macro) which copies the data to the last row down.
The macro works but the file size keeps increasing by a lot and I don't know why. Sorry but my vba is very beginner so I have looked up some code online.
Sub Submit()
Application.CommandBars("Reviewing").Controls("&Update File").Execute
'this should save the file and then copy the data and paste to last row
ActiveWorkbook.Save
With ThisWorkbook.Sheets("Sheet1")
If Application.WorksheetFunction.CountA(.Cells) <> 0 Then
LastRow = .Cells.Find(What:="*", _
After:=.Range("a5"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
Else
LastRow = 1
End If
.Cells(2, 25) = Environ("USERNAME")
.Range("A2:Y" & LastRow).Copy
End With
'sheet to paste too
With ThisWorkbook.Sheets("Sheet1")
If Application.WorksheetFunction.CountA(.Cells) <> 0 Then
LastRow = .Cells.Find(What:="*", _
After:=.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
Else
LastRow = 1
End If
.Range("A" & LastRow + 1).PasteSpecial xlPasteValues
End With
With Worksheets("Sheet1")
.Range("B2:F2").ClearContents
.Range("H2:Q2").ClearContents
.Range("S2:Y2").ClearContents
End With
ActiveWorkbook.Save
End Sub

What is making the Sub stop at row 12135 when "Lastrow" of data is row 19195?

The Sub written below is designed to open a workbook and copy the sheets into a template, then close the workbook leaving the template open. It works, but there is data until row 19195 but only 12135 rows of data get copied. What is my problem in the Sub?
Sub CopySheetsl()
Dim wb As Workbook, wb1 As Workbook
Dim CopySht As Worksheet
Dim LastRow As Long
Set wb = Workbooks.Open("L:\ABC\test\macro\test.xlsx")
Set wb1 = Workbooks("macro.xlsm")
LastRow = range("A:A").Find("", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
wb1.Sheets("Sheet1").range("A1", "N1" & LastRow) = wb.Sheets("Sheet1").range("A1", "N1" & LastRow).Value
wb1.Sheets("Sheet2").range("C1", "AN1" & LastRow) = wb.Sheets("Sheet2").range("A1", "AL1" & LastRow).Value
wb.Close
End Sub
This isn't finding the last row, it's finding an empty cell.
Dim ws as Worksheet : Set ws = wb1.Sheets("Sheet1")
LastRow = ws.Cells(ws.rows.count, 1).End(xlUp).Row ' last populated row in column A
You'll also need to recalculate it for Sheet2 unless you can be absolutely sure that both sheets have the same number of rows.
From Ron De Bruin's site
Public Function fndLast(choice As Long, rng As Range)
'Ron de Bruin, 5 May 2008
' 1 = last row
' 2 = last column
' 3 = last cell
Dim lrw As Long
Dim lcol As Long
Select Case choice
Case 1:
On Error Resume Next
fndLast = rng.Find(What:="*", _
After:=rng.Cells(1), _
LookAt:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
On Error GoTo 0
Case 2:
On Error Resume Next
fndLast = rng.Find(What:="*", _
After:=rng.Cells(1), _
LookAt:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Column
On Error GoTo 0
Case 3:
On Error Resume Next
lrw = rng.Find(What:="*", _
After:=rng.Cells(1), _
LookAt:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
On Error GoTo 0
On Error Resume Next
lcol = rng.Find(What:="*", _
After:=rng.Cells(1), _
LookAt:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Column
On Error GoTo 0
On Error Resume Next
fndLast = rng.Parent.Cells(lrw, lcol).Address(False, False)
If Err.Number > 0 Then
fndLast = rng.Cells(1).Address(False, False)
Err.Clear
End If
On Error GoTo 0
End Select
End Function

How to get column number for regex match using VBA/Macro in Excel

I want to get cell number like A:1 for every match found using regex and store it on sheet next to the current in same excel file. Is it possible to achieve in excel. As few of the examples I tried return match found true/false.
Sub Sample()
Dim ws As Worksheet
Dim aCell As Range
Set ws = ThisWorkbook.Sheets("Sheet1")
With ws
Set aCell = .Columns(2).Find(What:="Custom ", LookIn:=xlValues, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not aCell Is Nothing Then
aCell.Value = "Test"
Else
MsgBox "Not Found"
End If
End With
End Sub
This is the sample I tried!!
Try This
Sub Sample()
Dim ws As Worksheet
Dim aCell As Range
Set ws = ThisWorkbook.Sheets("Sheet1")
With ws
Set aCell = .Columns(2).Find(What:="Custom ", LookIn:=xlValues, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not aCell Is Nothing Then
Worksheets("Sheet2").Range("A" & Worksheets("Sheet2").Range("A" & Rows.Count).End(xlUp).Row + 1).Value = aCell.Address
Else
MsgBox "Not Found"
End If
End With
End Sub
if you want all the match try below
Sub Sample()
Dim ws As Worksheet
Dim aCell As Range
Set ws = ThisWorkbook.Sheets("Sheet1")
lastrow = Range("B" & Rows.Count).End(xlUp).Row
With ws
For i = 1 To lastrow
If InStr(Range("B" & i), "Custom ") > 0 Then
Worksheets("Sheet2").Range("A" & Worksheets("Sheet2").Range("A" & Rows.Count).End(xlUp).Row + 1).Value = Range("B" & i).Address
End If
Next i
End With
End Sub

Merge Data in Excel Range, Removing Blanks and Duplicates

I have a range of cells in Excel that is more than one column wide and more than one row long. Some of the cells are blank. I would like to merge (using VBA) the non-blank cells into a list, remove the duplicates, and sort alphabetically.
For example, given this input (where a dash designates an empty cell for the purpose of this question):
- - A D -
C - - A -
- - B - D
- - - - -
A - - E -
The following sorted output is produced:
A
B
C
D
E
As the example input shows, some of the rows and columns in the range may contain all empty cells.
Here is one way to do it.
CODE
Option Explicit
Sub Sample()
Dim ws As Worksheet
Dim LastRow As Long, lastCol As Long, i as Long
Dim Rng As Range, aCell As Range
Dim MyCol As New Collection
'~~> Change this to the relevant sheet name
Set ws = Sheets("Sheet21")
With ws
LastRow = .Cells.Find(What:="*", After:=.Range("A1"), _
Lookat:=xlPart, LookIn:=xlFormulas, SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, MatchCase:=False).Row
lastCol = .Cells.Find(What:="*", After:=.Range("A1"), _
Lookat:=xlPart, LookIn:=xlFormulas, SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, MatchCase:=False).Column
Set Rng = .Range("A1:" & Split(.Cells(, lastCol).Address, "$")(1) & LastRow)
'Debug.Print Rng.Address
For Each aCell In Rng
If Not Len(Trim(aCell.Value)) = 0 Then
On Error Resume Next
MyCol.Add aCell.Value, """" & aCell.Value & """"
On Error GoTo 0
End If
Next
.Cells.ClearContents
For i = 1 To MyCol.Count
.Range("A" & i).Value = MyCol.Item(i)
Next i
'~~> OPTIONAL (In Case you want to sort the data)
.Columns(1).Sort Key1:=.Range("A1"), Order1:=xlAscending, Header:=xlGuess, _
OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom, _
DataOption1:=xlSortNormal
End With
End Sub
SNAPSHOTS
FOLLOWUP
I just realized that adding 3 lines more makes this code even faster than the above code.
Option Explicit
Sub Sample()
Dim ws As Worksheet
Dim LastRow As Long, lastCol As Long, i As Long
Dim Rng As Range, aCell As Range, delRange As Range '<~~ Added This
Dim MyCol As New Collection
'~~> Change this to the relevant sheet name
Set ws = Sheets("Sheet1")
With ws
'~~> Get all the blank cells
Set delRange = .Cells.SpecialCells(xlCellTypeBlanks) '<~~ Added This
'~~> Delete the blank cells
If Not delRange Is Nothing Then delRange.Delete '<~~ Added This
LastRow = .Cells.Find(What:="*", After:=.Range("A1"), _
Lookat:=xlPart, LookIn:=xlFormulas, SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, MatchCase:=False).Row
lastCol = .Cells.Find(What:="*", After:=.Range("A1"), _
Lookat:=xlPart, LookIn:=xlFormulas, SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, MatchCase:=False).Column
Set Rng = .Range("A1:" & Split(.Cells(, lastCol).Address, "$")(1) & LastRow)
'Debug.Print Rng.Address
For Each aCell In Rng
If Not Len(Trim(aCell.Value)) = 0 Then
On Error Resume Next
MyCol.Add aCell.Value, """" & aCell.Value & """"
On Error GoTo 0
End If
Next
.Cells.ClearContents
For i = 1 To MyCol.Count
.Range("A" & i).Value = MyCol.Item(i)
Next i
'~~> OPTIONAL (In Case you want to sort the data)
.Columns(1).Sort Key1:=.Range("A1"), Order1:=xlAscending, Header:=xlGuess, _
OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom, _
DataOption1:=xlSortNormal
End With
End Sub