Autosum vba for each new sheet added to workbook - excel

My current VBA provides an sum function for pre-defined columns within worksheets which are specified and defined in the code. This works fine, however I am adding new worksheets to this workbook on a daily basis, and its therefore not feasible to edit the code everyday to add a new worksheet and range for it to sum.
Is there a way I can edit my current code in order for it to conduct the sum function for every single worksheet in the workbook? I have attached the current code for reference below.
Sub AutoSum()
Sheets("MASTER ACCOUNT REVENUE").Select
Range("D4").Select
Selection.End(xlDown).Select
ActiveCell.Offset(2, 0).Select
Dim cel1 As String, cel2 As String
cel1 = ActiveCell.Offset(-2, 0).End(xlUp).Address
cel2 = ActiveCell.Offset(-1).Address
ActiveCell.Value = "=sum(" & (cel1) & ":" & (cel2) & ")"
End Sub

Yes, just loop through the sheets. NOTE: It's best to avoid using .Select/.Activate
Sub autoSum_AllSheets()
Dim ws As Worksheet
Dim cel1 As String, cel2 As String
Dim firstCel As Range
For Each ws In ActiveWorkbook.Worksheets
With ws
Set firstCel = .Range("D4").End(xlDown).Offset(2, 0)
cel1 = firstCel.Offset(-2, 0).End(xlUp).Address
cel2 = firstCel.Offset(-1).Address
firstCel.Value = "=SUM(" & cel1 & ":" & cel2 & ")"
End With
Next ws
End Sub
Note: I'm aware of the redundencies in the Offset() parts, but just kept them in for OP to see how to more easily avoid .Select/.Activate.
Edit: To loop through a bunch of columns, one (albeit kludgy) way is to just add the column letters to an array:
Sub autoSum_AllSheets()
Dim ws As Worksheet
Dim cel1 As String, cel2 As String
Dim firstCel As Range
Dim cols() As Variant
cols = Array("D", "E", "F")
Dim i As Long
For Each ws In ActiveWorkbook.Worksheets
With ws
For i = LBound(cols) To UBound(cols)
Set firstCel = .Range(cols(i) & "4").End(xlDown).Offset(2, 0)
firstCel.Select
cel1 = firstCel.Offset(-2, 0).End(xlUp).Address
cel2 = firstCel.Offset(-1).Address
firstCel.Value = "=SUM(" & cel1 & ":" & cel2 & ")"
Next i
End With
Next ws
End Sub
Please note though, if the Column does not have any information in a cell after row 5, you will get an error (because the .XlDown goes to the very last row, and you can't then Offset(2,0) from there.)

Yes add:
Dim wscount as long
dim i as long
wscount = Activeworkbook.Worksheets.Count
for i = 1 to wscount
Sheets(i).Select
Range("D4").Select
Selection.End(xlDown).Select
ActiveCell.Offset(2, 0).Select
Dim cel1 As String, cel2 As String
cel1 = ActiveCell.Offset(-2, 0).End(xlUp).Address
cel2 = ActiveCell.Offset(-1).Address
ActiveCell.Value = "=sum(" & (cel1) & ":" & (cel2) & ")"
next i
End Sub

Related

Using active sheet instead of using sheet name Public / Private Sub code

I want to use the code below without having to write out the sheet name in Sheets("Sheet1").Activate in the Public Sub function, so I can just click on the sheet and run the code. I am unfamiliar with VBA language, and this should be a simple fix, but after an hour of trying things out, I can't get it working so I'm asking here now. Also, when I remove the Sheets("Sheet1").Activate, the abbrev sheet is then activated so the function does not run on that instead of my desired sheet. Any help would be appreciated!
Public gcolWords As New Collection
Public Sub ReplaceAllWrds()
Dim vWord, vAbv, itm
Dim i As Integer
Dim Lastrow As Integer
LoadAbbrevs
Sheets("Sheet1").Activate
Lastrow = ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Row
Range("F" & Lastrow).Select
For Each itm In gcolWords
i = InStr(itm, ":")
vWord = Left(itm, i - 1)
vAbv = Mid(itm, i + 1)
Replace1Wrd vWord, vAbv
Next
Set gcolWords = Nothing
End Sub
Private Sub Replace1Wrd(ByVal pvWrd, pvAbv)
On Error Resume Next
Selection.Replace What:=pvWrd, Replacement:=pvAbv, LookAt:=xlWhole, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
End Sub
Private Sub LoadAbbrevs()
Dim vWord, vAbv, vItm
Sheets("abbrevs").Activate
Range("A2").Select
While ActiveCell.Value <> ""
vWord = ActiveCell.Offset(0, 0).Value
vAbv = ActiveCell.Offset(0, 1).Value
vItm = vWord & ":" & vAbv
gcolWords.Add vItm
ActiveCell.Offset(1, 0).Select 'next row
Wend
End Sub
You should define a Excel.Worksheet that points to the ActiveSheet, and then use it to keep the reference:
Public Sub ReplaceAllWrds()
Dim vWord, vAbv, itm
Dim i As Integer
Dim Lastrow As Integer
Dim ws As Excel.Worksheet
Set ws = ActiveSheet
LoadAbbrevs
ws.Activate
'MsgBox "The name of the ws sheet is " & ws.Name
Lastrow = ws.Cells(Rows.Count, 1).End(xlUp).Row
Range("F" & Lastrow).Select
For Each itm In gcolWords
i = InStr(itm, ":")
vWord = Left(itm, i - 1)
vAbv = Mid(itm, i + 1)
Replace1Wrd vWord, vAbv
Next
Set gcolWords = Nothing
End Sub
As a note, you could review your code using worksheet objects; this way you can operate directly via Worksheet references, and you don't need to activate the sheets when you operate on them.
You do not need to activate the sheet if you're using worksheet objects.
Dim ws As Excel.Worksheet
Set ws = ThisWorkbook.Sheets("Sheet1")
ws.Cells(1,1).Value = "Example"
Using the worksheet objects can speed up your code and you don't need to worry about what sheet is active.
The following is a quick example of what your LoadAbbrevs could be.
Sub Example()
Dim WS as Worksheet
Set WS = ThisWorkbook.Sheets("abbrevs")
Dim RowIndex as Integer
RowIndex = 2
While WS.Cells(RowIndex, 2).Value <> ""
gcolWords.add WS.Cells(RowIndex, 2).Value + ":" + WS.Cells(RowIndex, 3).Value
RowIndex = RowIndex + 1
Wend
End Sub

Fill Down with linked values

I need to fill down a value in Sheet 1 Cell A2 with =Sheet 2 Cell A2 until the linked value is blank. I dont really know what to do.
I got so far so that I only need zeros in the fields:
Sub Test1()
Dim x As Integer
Dim i As Integer
Dim wsh As Worksheet
Set wsh = Worksheets("List with Weights")
Application.ScreenUpdating = False
i = 2
While (wsh.Cells(i, 1)) <> ""
wsh.Cells(i, 1).FormulaR1C1 = "='Sample Weight'!RC[0]"
wsh.Cells(i, 2).FormulaR1C1 = "='Sample Weight'!RC[0]"
wsh.Cells(i, 3).FormulaR1C1 = "='IS Weight'!RC[-1]"
i = i + 1
Wend
' Selects cell down 1 row from active cell.
ActiveCell.Offset(1, 0).Select
Columns("A:C").Select
Columns("A:C").EntireColumn.AutoFit
Application.ScreenUpdating = True
Range("A1").Select
End Sub
If I have understood you correctly, there is no need for a loop. Is this what you are trying?
Option Explicit
Sub Sample()
Dim wsThis As Worksheet
Dim wsThat As Worksheet
Dim wsOther As Worksheet
'~~> Set your relevant worksheets
Set wsThis = ThisWorkbook.Sheets("List with Weights")
Set wsThat = ThisWorkbook.Sheets("Sample Weight")
Set wsOther = ThisWorkbook.Sheets("IS Weight")
'~~> Find the last row in Col A of Sample Weight worksheet
Dim wsThatLRow As Long
wsThatLRow = wsThat.Range("A" & wsThat.Rows.Count).End(xlUp).Row
'~~> Insert the formula in 1 go in the relevant range
With wsThis
.Range("A2:A" & wsThatLRow).Formula = "='" & wsThat.Name & "'!A2"
.Range("B2:B" & wsThatLRow).Formula = "='" & wsThat.Name & "'!B2"
.Range("C2:C" & wsThatLRow).Formula = "='" & wsOther.Name & "'!B2"
End With
End Sub

How to apply multiple criteria to .Find?

I adapted code I found online.
It finds the string "car" in column A and returns the rows as an array
It assigns a variable to the length of the array (how many matches it found)
It assigns a variable to generate a random number between 0 and the length of the array
It then prints a random matching row's value into K3
Dim myArray() As Variant
Dim x As Long, y As Long
Dim msg As String
With ActiveSheet.Range("A1:A" & ActiveSheet.Range("A" & Rows.Count).End(xlUp).Row)
Set c = .find("Car", LookIn:=xlValues)
If Not c Is Nothing Then
firstAddress = c.Address
Do
ReDim Preserve myArray(y)
myArray(y) = c.Row
y = y + 1
Set c = .findNext(c)
If c Is Nothing Then
GoTo DoneFinding
End If
Loop While c.Address <> firstAddress
End If
DoneFinding:
End With
For x = LBound(myArray) To UBound(myArray)
msg = msg & myArray(x) & " "
Next x
ArrayLen = UBound(myArray) - LBound(myArray)
random_index = WorksheetFunction.RandBetween(0, ArrayLen)
MsgBox myArray(random_index)
Dim test As String
test = "B" & myArray(random_index)
Range("K3").Value = Range(test)
Example
I'm struggling with adapting the find code to allow for multiple criteria. So in my example, it finds "Car". What if I want to find matches that had "Car" in column A and "Red" in column D?
I tried
With ActiveSheet.Range("A1:A" & "D1:D" & ActiveSheet.Range("A" & Rows.Count).End(xlUp).Row & ActiveSheet.Range("D" & Rows.Count).End(xlUp).Row)
Set c = .find("Car", "Red", LookIn:=xlValues)
I get type mismatch on the Set line.
In case it is confusing, it currently looks for a string e.g. "Car" but I will eventually link this to the variable which will be assigned to a data validation list. So if the user chooses "car" from a drop down list, this is what it will search for.
Maybe Advancde Filter is something that fit your needs:
Example Code
Option Explicit
Public Sub FilterData()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("YourSheetName")
Dim LastRow As Long
LastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
Dim CriteriaRange As Range
Set CriteriaRange = ws.Range("A1", "E2")
Dim DataRange As Range
Set DataRange = ws.Range("A4", "E" & LastRow)
DataRange.AdvancedFilter Action:=xlFilterInPlace, CriteriaRange:=CriteriaRange, Unique:=False
End Sub
Public Sub ShowAll()
On Error Resume Next
ActiveSheet.ShowAllData
On Error GoTo 0
End Sub
Edit according comment:
You can use the advanced filter and then loop through the filter results:
Option Explicit
Public CurrentRow As Long
Public Sub FilterData()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("YourSheetName")
Dim LastRow As Long
LastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
Dim CriteriaRange As Range
Set CriteriaRange = ws.Range("A1", "E2")
Dim DataRange As Range
Set DataRange = ws.Range("A4", "E" & LastRow)
DataRange.AdvancedFilter Action:=xlFilterInPlace, CriteriaRange:=CriteriaRange, Unique:=False
End Sub
Public Sub ShowAll()
On Error Resume Next
ActiveSheet.ShowAllData
CurrentRow = 1
On Error GoTo 0
End Sub
Public Sub GetNextResult()
FilterData
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("YourSheetName")
Dim LastRow As Long
LastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
Dim DataRange As Range
Set DataRange = ws.Range("A4", "E" & LastRow)
Dim FilteredData As Range
Set FilteredData = DataRange.Resize(ColumnSize:=1).SpecialCells(xlCellTypeVisible)
If CurrentRow + 1 > FilteredData.Cells.Count Then
CurrentRow = 1
End If
CurrentRow = CurrentRow + 1
Dim i As Long
Dim Cell As Variant
For Each Cell In FilteredData
i = i + 1
If i = CurrentRow Then
Cell.EntireRow.Select
'or
'MsgBox Cell.Value & vbCrLf & Cell.Offset(0, 1) & vbCrLf & Cell.Offset(0, 2) & vbCrLf & Cell.Offset(0, 3) & vbCrLf & Cell.Offset(0, 4)
End If
Next Cell
End Sub

How can I optimize this macro I compiled in excel 2010 for 2016?

I have a Macro that searches for a string and when it finds it it copy and pastes values and formats with it.
It runs pretty slowly in 2016, certainly 2010. I haven't been able to figure out how to work around it.
Sub CommandButton1_Click()
Dim strsearch As String, lastline As Long, tocopy As Long
strsearch = CStr(InputBox("enter the string to search for"))
lastline = Range("A65536").End(xlUp).Row
J = 190
For i = 1 To lastline
For Each c In Range("G" & i & ":Z" & i)
If InStr(c.Text, strsearch) Then
tocopy = 1
End If
Next c
If tocopy = 1 Then
Range(Cells(i, 1), Cells(i, 6)).Copy
Sheets("Report").Range("A" & J).PasteSpecial (xlValues)
Sheets("Report").Range("A" & J).PasteSpecial (xlFormats)
J = J + 1
End If
tocopy = 0
Next i
End Sub
Perhaps something like this will work quickly for you:
Sub CommandButton1_Click()
Dim wb As Workbook
Dim wsData As Worksheet
Dim wsDest As Worksheet
Dim rFind As Range
Dim rCopy As Range
Dim sFind As String
Dim sFirst As String
sFind = InputBox("Enter the string to search for:")
If Len(sFind) = 0 Then Exit Sub 'Pressed cancel
Set wb = ActiveWorkbook
Set wsData = wb.ActiveSheet
Set wsDest = wb.Worksheets("Report")
With wsData.Range("G1:Z" & wsData.Cells(wsData.Rows.Count, "A").End(xlUp).Row)
Set rFind = .Find(sFind, .Cells(.Rows.Count, .Columns.Count), xlValues, xlPart)
If Not rFind Is Nothing Then
sFirst = rFind.Address
Set rCopy = rFind
Do
Set rCopy = Union(rCopy, rFind)
Set rFind = .FindNext(rFind)
Loop While rFind.Address <> sFirst
Intersect(rCopy.Parent.Range("A:F"), rCopy.EntireRow).Copy
wsDest.Range("A190").PasteSpecial xlPasteValues
wsDest.Range("A190").PasteSpecial xlPasteFormats
End If
End With
End Sub

Excel 2010 data validation to check if cell contain comma value

In excel 2010, how to do a validation if cell contain ',' then pop up a message to user ?
Please try to show your work ..
lets say Column A contains the data then below code work perfectly
this is what u wanted (TESTED)
Sub tested()
Dim erange As Range
Dim lrow As Integer
lrow = ActiveSheet.Range("A" & Rows.Count).End(xlUp).Row
For Each erange In Range("A2:A" & lrow)
If InStr(erange.Value, ",") > 0 Then
MsgBox (erange.Address & " contains Comma ")
erange.Interior.Color = vbRed
End If
Next erange
End Sub
Using normal data validation, you could try this
=(LEN(A1) = LEN(SUBSTITUTE(A1,",","")))
If you want to avoid unnecessary loop use below code.
Sub findComma()
Dim srcRng As Range, findRng As Range
Dim firstCell As String
Dim lrow As Integer
lrow = Range("A" & Rows.Count).End(xlUp).Row
Set srcRng = Range("A1:A" & lrow)
Set findRng = srcRng.Find(What:=",", LookIn:=xlValues, LookAt:=xlPart)
If Not findRng Is Nothing Then firstCell = findRng.Address
Do Until findRng Is Nothing
MsgBox (findRng.Address & " contains Comma ")
findRng.Interior.Color = vbRed
Set findRng = srcRng.FindNext(findRng)
If findRng.Address = firstCell Then Exit Sub
Loop
End Sub

Resources