Perform calculation on cells if they have data - excel

I am a bit new to the macro's in excel and I am trying to find a way to adjust one of the macros I currently have in an excel file. I have a calculation that takes the columns D and E then subtracts D from E and adds it to the value of column B. here is the current code and also the sheet being used.
Sub InvAdj()
'
' InvAdj Macro
'
' Keyboard Shortcut: Ctrl+Shift+I
'
Columns("C:C").Select
Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
Range("C1").Select
ActiveCell.FormulaR1C1 = "Quality"
Range("C2").Select
ActiveCell.FormulaR1C1 = "=RC[-1]-RC[2]+RC[3]"
Range("C2").Select
Selection.AutoFill Destination:=Range("C2:C33")
Range("C2:C33").Select
Columns("C:C").Select
Selection.Copy
Columns("B:B").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=True, Transpose:=False
Columns("C:C").Select
Application.CutCopyMode = False
Selection.Delete Shift:=xlToLeft
Range("D2:E33").Select
Selection.ClearContents
Range("F1").Select
End Sub

Not sure if this is what you are trying?
Sub InvAdj()
Dim ws As Worksheet
'~~> Change this to the relevant sheet
Set ws = ThisWorkbook.Sheets("Sheet1")
With ws
.Range("B1").Value = "Quality"
For i = 2 To 33
'~~> Check if all cells have data
If Len(Trim(.Range("B" & i).Value)) <> 0 And _
en(Trim(.Range("D" & i).Value)) <> 0 And _
en(Trim(.Range("E" & i).Value)) <> 0 Then
'B = B + (E - D)
.Range("B" & i).Value = .Range("B" & i).Value + _
(.Range("E" & i).Value - .Range("D" & i).Value)
End If
Next i
End With
End Sub

Related

Grouping records in an Excel sheet which have the same values in one column but only one unique record in other columns

Dummy data of a tournament
Above is the example of the dummy data. My goal is to use VBA to group the data so that there is only one name displayed and the 3 Games populated with the Results so there would only be one line for the name as well as the 3 Games' results in the same line.
Example of the output data
Well, this is not as easy as first appears, however, this works:
So, the country is returned with classic index & match. The results are built by finding the result against each player and round. This expects blanks in the other cells for each player.
Try this:
Sub mSummarise()
'
' Macro1 Macro
'
'
Dim lData, lSummary, lFilter As String
Dim lRow1, lRow2, lRow3, lCol1, lCount As Long
lData = ActiveSheet.Name
Range("A1").Select
Selection.End(xlToRight).Select
lCol1 = ActiveCell.Column
Range("A1").Select
Selection.End(xlDown).Select
lRow1 = ActiveCell.Row
Sheets.Add After:=ActiveSheet
ActiveSheet.Name = "Summary"
Sheets(lData).Activate
Range("A1:B" & lRow1).Select
Selection.Copy
Sheets("Summary").Select
ActiveSheet.Paste
Application.CutCopyMode = False
ActiveSheet.Range("$A$1:$B$" & lRow1).RemoveDuplicates Columns:=Array(1, 2), Header _
:=xlNo
Range("A1").Select
Selection.End(xlDown).Select
lRow2 = ActiveCell.Row
Sheets(lData).Select
Range(Cells(1, 3), Cells(1, lCol1)).Select
Selection.Copy
Sheets("Summary").Select
Range("C1").Select
ActiveSheet.Paste
Sheets(lData).Select
For lCount = 3 To lCol1
Range(Cells(1, 1), Cells(lRow1, lCol1)).Select
Selection.AutoFilter
ActiveSheet.Range(Cells(1, 1), Cells(lRow1, lCol1)).AutoFilter Field:=lCount, Criteria1:="<>", Operator:=xlAnd
Range(Cells(1, 1), Cells(lRow1, lCount)).Select
Selection.SpecialCells(xlCellTypeVisible).Select
Selection.Copy
Sheets.Add After:=ActiveSheet
lFilter = ActiveSheet.Name
ActiveSheet.Paste
Range("A1").Select
Selection.End(xlDown).Select
lRow3 = ActiveCell.Row
Sheets("Summary").Select
Application.CutCopyMode = False
Cells(2, lCount).Select
ActiveCell.Formula = "=VLOOKUP(A2," & lFilter & "!$A$2:" & Cells(lRow3, lCount).Address & "," & lCount & ",0)"
Range(Cells(2, lCount), Cells(2, lCount)).Copy
Range(Cells(2, lCount), Cells(lRow3, lCount)).Select
ActiveSheet.Paste
Range(Cells(2, lCount), Cells(lRow3, lCount)).Select
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Sheets(lFilter).Select
Application.DisplayAlerts = False
ActiveWindow.SelectedSheets.Delete
Application.DisplayAlerts = True
Sheets(lData).Select
Next
Selection.AutoFilter
Range("A1").Select
Sheets("Summary").Select
Range("A1").Select
End Sub

Select.Autofill Destination:=Range NOT autofilling

I have been working with VBA for about two years now, and I am having a problem I haven't had before. I am trying to autofill columns A, B, D, E and G with formulas based on the number of cells that are populated in column L. In the example shown below, cells L2-L5 are populated. With my autofill formulas, this should mean that cells A2-A5 populate, cells B2-B5 populate etc. But they don't. Only column G populates correctly, and I am stumped as to why this is happening. Any brilliant ideas?
Here is my code:
Application.DisplayAlerts = False
Sheets("QBTimecard").Select
Range("DP2").Select
ActiveCell.FormulaR1C1 = _
"=RC[-119]&""_""&RC[-107]&""_""&IF(RC[-2]<>""Client Transportation"",""Z"",""XY"")"
Range("DQ2").Select
ActiveCell.FormulaR1C1 = "=IF(RC[-13]<=RC[-8],""Pass"",""MMV"")"
On Error Resume Next
Selection.Autofill Destination:=Range("dp2:ds" & Cells(Rows.Count, "A").End(xlUp).Row)
Sheets("QBTimecard").Select
Columns("DP:DP").Select
Selection.Copy
Sheets("PunchEntryImport").Select
Columns("L:L").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Range("L1").Select
Application.CutCopyMode = False
ActiveCell.FormulaR1C1 = "Blank"
Range("L2").Select
Sheets("PunchEntryImport").Select
Range("A2").Select
ActiveCell.FormulaR1C1 = _
"=INDEX(QBTimecard!C,MATCH(PunchEntryImport!RC[11],QBTimecard!C[119],0))"
Range("B2").Select
ActiveCell.FormulaR1C1 = _
"=SUMIF(QBTimecard!C[118],PunchEntryImport!RC[10],QBTimecard!C[13])/COUNTIF(QBTimecard!C[118],PunchEntryImport!RC[10])"
Range("D2").Select
ActiveCell.FormulaR1C1 = _
"=INDEX(Lookup!C[-2],MATCH(INDEX(QBTimecard!C[9],MATCH(PunchEntryImport!RC[8],QBTimecard!C[116],0)),Lookup!C[-3],0))&""/1/""&INDEX(QBTimecard!C[10],MATCH(PunchEntryImport!RC[8],QBTimecard!C[116],0))&"" ""&TEXT(INDEX(QBTimecard!C[12],MATCH(PunchEntryImport!RC[8],QBTimecard!C[116],0)),""HHMM"")"
Range("E2").Select
ActiveCell.FormulaR1C1 = _
"=INDEX(Lookup!C[-3],MATCH(INDEX(QBTimecard!C[8],MATCH(PunchEntryImport!RC[7],QBTimecard!C[115],0)),Lookup!C[-4],0))&""/1/""&INDEX(QBTimecard!C[9],MATCH(PunchEntryImport!RC[7],QBTimecard!C[115],0))&"" ""&TEXT(INDEX(QBTimecard!C[12],MATCH(PunchEntryImport!RC[7],QBTimecard!C[115],0)),""HHMM"")"
Range("G2").Select
ActiveCell.FormulaR1C1 = _
"=INDEX(QBTimecard!C[103],MATCH(PunchEntryImport!RC[5],QBTimecard!C[113],0))"
On Error Resume Next
'This is the portion that is not autofilling
Selection.Autofill Destination:=Range("a2:a" & Cells(Rows.Count, "L").End(xlUp).Row)
Selection.Autofill Destination:=Range("b2:b" & Cells(Rows.Count, "L").End(xlUp).Row)
Selection.Autofill Destination:=Range("d2:d" & Cells(Rows.Count, "L").End(xlUp).Row)
Selection.Autofill Destination:=Range("e2:e" & Cells(Rows.Count, "L").End(xlUp).Row)
Selection.Autofill Destination:=Range("g2:g" & Cells(Rows.Count, "L").End(xlUp).Row)
Without re-writing the whole thing, this is a more-approachable way to handle this, without the Select/ Activate/ Autofill:
Dim wsQBTC As Worksheet, wsPE As Worksheet, lr As Long
Set wsQBTC = Worksheets("QBTimecard")
Set wsPEI = Worksheets("PunchEntryImport")
lr = wsQBTC.Cells(Rows.Count, "A").End(xlUp).Row
With wsQBTC
.Range("DP2:DP" & lr).FormulaR1C1 = "=RC[-119]&""_""&RC[-107]&""_""&IF(RC[-2]<>""Client Transportation"",""Z"",""XY"")"
.Range("DQ2:DQ" & lr).FormulaR1C1 = "=IF(RC[-13]<=RC[-8],""Pass"",""MMV"")"
End With
From the help for Range.AutoFill
The destination must include the source range.
Because you are using Selection.AutoFill and G2 is the active cell, the autofill will only work when G2 is part of the range being autofilled.
To fix this, replace Selection.AutoFill with Range("A2").AutoFill, Range("B2").AutoFill and so on

Trying to Copy rows selected with checkboxes to another workbook

I am a bit stuck: I have the below code for a spreadsheet which copies rows, selected with a checkbox, into a second sheet.
I now need to amend this code so that the copied rows are pasted into another workbook on a specific sheet.
I have tried Workbooks("").Worksheets("") and also using the whole C drive path but always get a run-time 9, subscript out of range error. I haven't had any luck in finding a solution online.
Both workbooks are saved on my desktop currently for ease:
Sub CopyRows()
For Each chkbx In ActiveSheet.CheckBoxes
If chkbx.Value = 1 Then
For r = 1 To Rows.Count
If Cells(r, 1).Top = chkbx.Top Then
With Worksheets("Sheet2")
LRow = .Range("A" & Rows.Count).End(xlUp).Row + 1
.Range("A" & LRow & ":R" & LRow) = _
Worksheets("Sheet1").Range("A" & r & ":R" & r).Value
End With
Exit For
End If
Next r
End If
Next
End Sub
This recorded macro takes the data to where it needs to go:
Sub Transfer()
'
' Transfer Macro
'
'
Range("K2").Select
Selection.Copy
Windows("Destination.xls").Activate
Range("E7:E8").Select
ActiveSheet.Paste
Windows("WIP - Live.xlsm").Activate
Range("B2").Select
Application.CutCopyMode = False
Selection.Copy
Windows("Destination.xls").Activate
Range("E9").Select
ActiveSheet.Paste
Windows("WIP - Live.xlsm").Activate
Range("M2").Select
Application.CutCopyMode = False
Selection.Copy
Windows("Destination.xls").Activate
Range("E10").Select
ActiveSheet.Paste
Windows("WIP - Live.xlsm").Activate
Range("G2").Select
Application.CutCopyMode = False
Selection.Copy
Windows("Destination.xls").Activate
Range("E11").Select
ActiveSheet.Paste
Windows("WIP - Live.xlsm").Activate
Range("N2").Select
Application.CutCopyMode = False
Selection.Copy
Windows("Destination.xls").Activate
Range("E12").Select
ActiveSheet.Paste
Windows("WIP - Live.xlsm").Activate
Range("E2").Select
Application.CutCopyMode = False
Selection.Copy
Windows("Destination.xls").Activate
Range("E13").Select
ActiveSheet.Paste
Windows("WIP - Live.xlsm").Activate
Range("A2").Select
Application.CutCopyMode = False
Selection.Copy
Windows("Destination.xls").Activate
Range("E14").Select
ActiveSheet.Paste
Windows("WIP - Live.xlsm").Activate
Range("S2").Select
Application.CutCopyMode = False
Selection.Copy
Windows("Destination.xls").Activate
Range("E15").Select
ActiveSheet.Paste
Windows("WIP - Live.xlsm").Activate
Range("J2").Select
Application.CutCopyMode = False
Selection.Copy
Windows("Destination.xls").Activate
Range("E16").Select
ActiveSheet.Paste
Windows("WIP - Live.xlsm").Activate
Range("I2").Select
Application.CutCopyMode = False
Selection.Copy
Windows("Destination.xls").Activate
Range("E17").Select
ActiveSheet.Paste
Windows("WIP - Live.xlsm").Activate
Range("C2").Select
Application.CutCopyMode = False
Selection.Copy
Windows("Destination.xls").Activate
Range("E20").Select
ActiveSheet.Paste
Windows("WIP - Live.xlsm").Activate
Range("D2").Select
Application.CutCopyMode = False
Selection.Copy
Windows("Destination.xls").Activate
Range("E21").Select
ActiveSheet.Paste
Windows("WIP - Live.xlsm").Activate
End Sub
Code with error at destination workbook:
Sub CopyRows()
For Each chkbx In ActiveSheet.CheckBoxes
If chkbx.Value = 1 Then
For r = 1 To Rows.Count
If Cells(r, 1).Top = chkbx.Top Then
With Workbooks("Destination").Sheets("Sheet2")
LRow = .Range("A" & Rows.Count).End(xlUp).Row + 1
.Range("A" & LRow & ":R" & LRow) = _
Worksheets("Sheet1").Range("A" & r & ":R" & r).Value
End With
Exit For
End If
Next r
End If
Next
End Sub
Solved: I have managed to get it working with the below code:
Sub CopyRows()
For Each chkbx In ActiveSheet.CheckBoxes
If chkbx.Value = 1 Then
For r = 1 To Rows.Count
If Cells(r, 1).Top = chkbx.Top Then
With Workbooks("Destination.xlsm").Sheets("Details")
LRow = .Range("A" & Rows.Count).End(xlUp).Row + 1
.Range("A" & LRow & ":U" & LRow) = _
Worksheets("Sheet2").Range("A" & r & ":U" & r).Value
End With
Exit For
End If
Next r
End If
Next
End Sub
The error was being caused by the Sheet 2 name in the destination workbook. I had to amend the name to details and it started working. Frustratingly simple for how long I spent on it!
Many Thanks to ed2 and norie for the replies and help. It is much appreciated.
Try this:
First:
Change
Worksheets("Sheet1").Range("A" & r & ":R" & r).Value
to
Workbooks("WIP - Live.xlsm").Sheets("Sheet1").Range("A" & r & ":R" & r).Value
Then:
Change
With Worksheets("Sheet2")
to
Workbooks("Destination.xls").Sheets("Sheet2")
This assumes that both workbooks are already open when the macro is run. If not, you will need code to open one or both of them.

how to calculate average for multiple tables of filtered data dynamically - VBA

I have a table where I need to find the elements present in different samples.
For every sample, the no of iterations is a variable - I can have two rows of sample 1 and 3 rows of sample2 or 5 rows of sample4. the number of columns which are the elements can also be different. I have considered 3 samples and 17 elements in this case.
I need to filter based on the sample. say sample 1. Then the average needs to be calculated for all the entries of sample 1. Then below that sample 2 values need to be displayed and the average for all the entries of sample 2 should be calculated.
I am a beginner in vba and hence the code I used is not able to do it for dynamic range of values. Also, I can only calculate the average using macro recorder. I am not aware how to combine these two codes into one. I tried to search a lot on this topic
I have included my codes as well.
Any help would be much appreciated!!! Thank you
Sub sorttable()
Dim j As Long 'row variable
On Error GoTo Err_Execute
Dim i As Long
'Start search in row 1 in sheet1
j = 1
'Column counter for sheet2
i = 1
While Len(Range("A" & CStr(j)).Value) > 0
If Range("A" & CStr(j)).Value = "Sample1" Then
Range(Range("A" & CStr(j)), Range("A" & CStr(j)).End(xlToRight)).Select
Selection.Copy
Sheets("Sheet2").Select
Sheet2.Cells(i, 1).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
'Cells(j + 1, 1) = "=AVERAGE(A1:C" & j - 1 & ")" 'used to calculate avg
i = i + 1
Sheets("Sheet1").Select
ElseIf Range("A" & CStr(j)).Value = "Sample2" Then
Range(Range("A" & CStr(j)), Range("A" & CStr(j)).End(xlToRight)).Select
Selection.Copy
Sheets("Sheet2").Select
Sheet2.Cells(i, 1).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
i = i + 1
Sheets("Sheet1").Select
ElseIf Range("A" & CStr(j)).Value = "Sample3" Then
Range(Range("A" & CStr(j)), Range("A" & CStr(j)).End(xlToRight)).Select
Selection.Copy
Sheets("Sheet2").Select
Sheet2.Cells(i, 1).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
i = i + 1
Sheets("Sheet1").Select
End If
j = j + 1
Wend
Application.CutCopyMode = False
MsgBox "the values have been extracted"
Exit Sub
Err_Execute:
MsgBox "Error Occured"
End Sub
'code- part of it for calculating the average
Application.CutCopyMode = False
Selection.AutoFill Destination:=Range("A9:B9"), Type:=xlFillDefault
Range("A9:B9").Select
Range("B9").Select
Selection.ClearContents
ActiveCell.FormulaR1C1 = "= AVERAGE(R[-2]C,R[-1]C)"
Range("B9").Select
Selection.AutoFill Destination:=Range("B9:R9"), Type:=xlFillDefault
Range("B9:R9").Select
Range("A11").Select
Sheets("Sheet2").Select
Range("A27").Select
Sheets("Sheet1").Select
Range("A8:R10").Select
Selection.Copy
Sheets("Sheet2").Select
Range("A11").Select
ActiveSheet.Paste
Range("A14").Select
Application.CutCopyMode = False
Selection.Style = "Normal 2"
ActiveCell.FormulaR1C1 = "Average"
Range("B14").Select
ActiveCell.FormulaR1C1 = "= AVERAGE(R[-3]C:R[-1]C)"
Range("B14").Select
Selection.AutoFill Destination:=Range("B14:R14"), Type:=xlFillDefault
Range("B14:R14").Select
Range("A16").Select
End Sub
It looks like you've recorded your macro as a start, then tried to modify it from there. This is an excellent first step, so now there are things to be aware of:
The macro recorder captures many, many things that are unnecessary, so don't use Select or Activate.
Since your data may not be the same for each sample group, your code has to take that into account. Review the sample code below and notice that it loops to figure out how many rows are in a sample group, then dynamically fills in the formula for the columns of that group.
Option Explicit
Sub SortTable()
Dim ws As Worksheet
Set ws = ActiveSheet
Dim numSampleRows As Long
numSampleRows = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row - 1
Dim sampleRow As Range
Set sampleRow = ws.Range("A2")
Dim i As Long
Dim numSamplesInGroup As Long
Dim currentSampleLabel As String
Dim numSampleColumns As Long
Dim avgRow As Long
Dim avgCol As Long
For i = 1 To (numSampleRows + 1)
'--- look at the sample labels to determine how
' many are in this group
If numSamplesInGroup = 0 Then
'--- this is the start of a sample group
currentSampleLabel = sampleRow.Offset(0, 0)
numSamplesInGroup = 1
ElseIf currentSampleLabel = sampleRow.Offset(0, 0) Then
'--- continue to count the samples in the group
numSamplesInGroup = numSamplesInGroup + 1
Else
'--- we've reached the end of the sample group
' so insert two empty rows here
sampleRow.EntireRow.Insert
sampleRow.EntireRow.Insert
Debug.Print sampleRow.Address
'--- create the AVERAGE formula for each populated column
' ASSUMES all the columns are consistent for each sample group
avgRow = sampleRow.Offset(-2, 0).Row
ws.Cells(avgRow, 1) = "Average"
numSampleColumns = ws.Cells(avgRow - 1, ws.Columns.Count).End(xlToLeft).Column
For avgCol = 1 To (numSampleColumns - 1)
sampleRow.Offset(-2, avgCol).FormulaR1C1 = _
"=AVERAGE(R" & _
avgRow - numSamplesInGroup & _
"C" & avgCol + 1 & _
":R" & avgRow - 1 & "C" & avgCol + 1 & ")"
Next avgCol
'--- reset for the next loop
currentSampleLabel = sampleRow.Offset(0, 0)
numSamplesInGroup = 0
End If
'--- move down one row
Set sampleRow = sampleRow.Offset(1, 0)
Next i
End Sub

Excel 2010 Macros

I work with excel 2010 and have created a macro to copy a row of text data, transpose it into a column and then add commas after each value. Now I want the same macro to also find a pre-determined value in the column and replace it with another pre-determined value. Here is what I have so far...
Sub Macro2()
'
' Macro2 Macro
'
' Keyboard Shortcut: Ctrl+q
'
Range("E2:CL6").Select
Selection.Copy
Range("A11").Select
Selection.PasteSpecial Paste:=xlPasteAll, Operation:=xlNone, SkipBlanks:= _
False, Transpose:=True
x = 1
Do While Cells(11, x) <> ""
Cells(11, x).Select
Set Rng = Range(Selection, Selection.End(xlDown))
For Each cell In Rng
cell.Value = cell.Value + ","
Next
x = x + 1
Loop
Application.CutCopyMode = False
Columns("B:B").Select
Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
Cells.Select
Cells.EntireColumn.AutoFit
Range("B1").Select
ActiveCell.FormulaR1C1 = "user id"
Range("C1").Select
ActiveCell.FormulaR1C1 = "Pin"
Range("B2").Select
End Sub
Here is your code (a bit more cleaner without the .Select) :
Sub Macro2()
'
' Macro2 Macro
'
' Keyboard Shortcut: Ctrl+q
'
Range("E2:CL6").Copy
Range("A11").PasteSpecial Paste:=xlPasteAll, _
Operation:=xlNone, _
SkipBlanks:=False, _
Transpose:=True
x = 1
Do While Cells(11, x) <> ""
Set Rng = Range(Cells(11, x), Cells(11, x).End(xlDown))
For Each cell In Rng
cell.Value = CStr(cell.Value & ",")
cell.Value = Replace(cell.Value, "Fixed Income Research Group", "SS FixedIncomeResearch")
cell.Value = Replace(cell.Value, "Fixed Income Trading Group", "SS FixedIncomeTrading")
Next
x = x + 1
Loop
Application.CutCopyMode = False
Columns("B:B").Insert Shift:=xlToRight, _
CopyOrigin:=xlFormatFromLeftOrAbove
Columns("B:B").Insert Shift:=xlToRight, _
CopyOrigin:=xlFormatFromLeftOrAbove
Cells.EntireColumn.AutoFit
Range("B1").FormulaR1C1 = "user id"
Range("C1").FormulaR1C1 = "Pin"
End Sub

Resources