A faster alternative without using arrays:
- I have not used arrays but I expect that you may find that this solution is quicker than your current one
- You can test in the attached workbook with {CTRL} q
- I added lots of duplicate rows to Data Source to allow fuller testing
- headers not added in row 1
- total font has not been made bold
- no merged cells - avoid them when you want to use VBA - they cause too many problems
- TestNo duplicated from TestYes (I was too lazy to write a code to avoid the duplication
)
How it works:
- DataFilter used on sheet source - filter for YES or NO
- copy all filtered rows together to other sheet (copy ALL columns)
- then delete columns not required
- insert the 6 rows
- add totals etc
Sub test()
With Application
.ScreenUpdating = False
.Calculation = xlCalculationManual
End With
Call TestYes
Call TestNo
With Application
.ScreenUpdating = True
.Calculation = xlCalculationAutomatic
End With
End Sub
Sub TestYes()
Dim yes As Worksheet, no As Worksheet, source As Worksheet
Dim rng As Range, rngYes As Range, rngNo As Range
Dim lRow As Long, fRow As Long, rCount As Long, rMod As Integer
Dim i As Long, c As Integer, x As Integer
Dim cel As Range, cel1 As Range, cel2 As Range, addr1 As String, addr2 As String
Dim myFormula As String
Set yes = Sheets("YES"): Set no = Sheets("NO"): Set source = Sheets("Data Source")
With source
lRow = .Range("C" & .Cells.Rows.Count).End(xlUp).Row '
Set rng = .Range("A1:AN" & lRow)
rng.AutoFilter Field:=31, Criteria1:="YES", Operator:=xlFilterValues
rng.Copy
yes.Range("A1").PasteSpecial (xlPasteColumnWidths)
rng.Copy yes.Range("A1")
If .AutoFilterMode Then .AutoFilterMode = False
End With
With yes
.Range(.Cells(1, 37), .Cells(1, 40)).EntireColumn.Delete
.Range(.Cells(1, 6), .Cells(1, 32)).EntireColumn.Delete
'insert 6 rows every 30 rows
fRow = .Range("A" & .Cells.Rows.Count).End(xlUp).End(xlUp).Row
If fRow > 1 Then .Rows("1:" & fRow).Delete
lRow = .Range("A" & .Cells.Rows.Count).End(xlUp).Row
lRow = (30 - lRow Mod 30) + lRow
.Cells(lRow + 1, 1).Value = "Marker"
For i = lRow + 1 - 30 To 31 Step -30
.Cells(i, 1).Resize(6).EntireRow.Insert Shift:=xlDown
Next i
lRow = .Range("A" & .Cells.Rows.Count).End(xlUp).Row
'add trimmings and totals
For i = lRow To 1 Step -36
If i <> 31 Then
x = 31
Else
x = 30
End If
Set cel = .Cells(i, 5)
Set cel1 = cel.Offset(-x)
Set cel2 = cel.Offset(-1)
'totals
For c = 0 To 4
addr1 = cel1.Offset(, c).Address(0, 0)
addr2 = cel2.Offset(, c).Address(0, 0)
myFormula = "=sum(" & addr1 & ":" & addr2 & ")"
cel.Offset(, c).Formula = myFormula
If i > 60 Then
addr1 = .Cells(i - 36, 5).Offset(, c).Address(0, 0)
myFormula = "=" & addr1
.Cells(i - 31, 5).Offset(, c).Formula = myFormula
If c = 0 Then .Cells(i - 31, 2) = "Previous Total"
End If
Next c
.Cells(i, 2) = "TOTAL"
.Cells(i + 1, 2) = "Signature"
.Cells(i + 1, 4) = "Signature"
.Cells(i + 1, 8) = "Signature"
.Cells(i + 2, 2) = "Auditor"
.Cells(i + 2, 4) = "Head of Accounts"
.Cells(i + 2, 8) = "General Manager"
Next i
.Cells(1, 1).EntireRow.Insert Shift:=xlDown
End With
End Sub
Sub TestNo()
Dim yes As Worksheet, no As Worksheet, source As Worksheet
Dim rng As Range, rngYes As Range, rngNo As Range
Dim lRow As Long, fRow As Long, rCount As Long, rMod As Integer
Dim i As Long, c As Integer, x As Integer
Dim cel As Range, cel1 As Range, cel2 As Range, addr1 As String, addr2 As String
Dim myFormula As String
Set yes = Sheets("YES"): Set no = Sheets("NO"): Set source = Sheets("Data Source")
With source
lRow = .Range("C" & .Cells.Rows.Count).End(xlUp).Row '
Set rng = .Range("A1:AN" & lRow)
rng.AutoFilter Field:=32, Criteria1:="NO", Operator:=xlFilterValues
rng.Copy
no.Range("A1").PasteSpecial (xlPasteColumnWidths)
rng.Copy no.Range("A1")
source.Activate
If .AutoFilterMode Then .AutoFilterMode = False
End With
With no
.Range(.Cells(1, 6), .Cells(1, 36)).EntireColumn.Delete
'insert 6 rows every 30 rows
fRow = .Range("A" & .Cells.Rows.Count).End(xlUp).End(xlUp).Row
If fRow > 1 Then .Rows("1:" & fRow).Delete
lRow = .Range("A" & .Cells.Rows.Count).End(xlUp).Row
lRow = (30 - lRow Mod 30) + lRow
.Cells(lRow + 1, 1).Value = "Marker"
For i = lRow + 1 - 30 To 31 Step -30
.Cells(i, 1).Resize(6).EntireRow.Insert Shift:=xlDown
Next i
lRow = .Range("A" & .Cells.Rows.Count).End(xlUp).Row
'add trimmings and totals
For i = lRow To 1 Step -36
If i <> 31 Then
x = 31
Else
x = 30
End If
Set cel = .Cells(i, 5)
Set cel1 = cel.Offset(-x)
Set cel2 = cel.Offset(-1)
'totals
For c = 0 To 4
addr1 = cel1.Offset(, c).Address(0, 0)
addr2 = cel2.Offset(, c).Address(0, 0)
myFormula = "=sum(" & addr1 & ":" & addr2 & ")"
cel.Offset(, c).Formula = myFormula
If i > 60 Then
addr1 = .Cells(i - 36, 5).Offset(, c).Address(0, 0)
myFormula = "=" & addr1
.Cells(i - 31, 5).Offset(, c).Formula = myFormula
If c = 0 Then .Cells(i - 31, 2) = "Previous Total"
End If
Next c
.Cells(i, 2) = "TOTAL"
.Cells(i + 1, 2) = "Signature"
.Cells(i + 1, 4) = "Signature"
.Cells(i + 1, 8) = "Signature"
.Cells(i + 2, 2) = "Auditor"
.Cells(i + 2, 4) = "Head of Accounts"
.Cells(i + 2, 8) = "General Manager"
Next i
.Cells(1, 1).EntireRow.Insert Shift:=xlDown
End With
End Sub
Bookmarks