Unique list based on two cells - vba

I am using the following code to extract a list of unique customers, I would like to extract a list based on a combination of two columns, column F and column K. Is there a way to update this code, that would be effective?
Sub FilterUniqueCustomer()
Application.ScreenUpdating = False
'Advance Filter
Range("F1").Select
Application.CutCopyMode = False
Application.CutCopyMode = False
Range("F1:F100").AdvancedFilter Action:=xlFilterCopy, CopyToRange:=Range( _
"S1"), Unique:=True
ActiveWindow.SmallScroll Down:=-6
'Copy Values
Range("T2:T100").Select
Selection.copy
Range("U2").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
'Clear Formatting
Range("N4").Select
Selection.copy
Columns("S:S").Select
Selection.PasteSpecial Paste:=xlPasteFormats, Operation:=xlNone, _
SkipBlanks:=False, Transpose:=False
Application.CutCopyMode = False 'Clears clipboard
Call DeleteZerosCustomer
Application.ScreenUpdating = True
End Sub

Like this using a dictionary to get unique combinations and array to work faster than in sheet.
Option Explicit
Sub TEST()
Application.ScreenUpdating = False
Dim arr(), i As Long, dict As Object
Set dict = CreateObject("Scripting.Dictionary")
With Worksheets("Sheet3") '<==Change as required
arr = .Range("F1:K6").Value
For i = LBound(arr, 1) To UBound(arr, 1)
dict(arr(i, 1) & "," & arr(i, 6)) = 1
Next
End With
Dim key As Variant, rowCounter As Long
For Each key In dict.keys
rowCounter = rowCounter + 1
Worksheets("Sheet2").Cells(rowCounter + 1, 1).Resize(1, 2) = Split(key, ",") '<== Change output sheet as required
Next
Application.ScreenUpdating = True
End Sub

Related

Excel VBA - Do Until Blank Cell

I'm recording a macro and need some help. I'd like copy and paste the values from the column G of the "SalesData" worksheet into cells A2, A12, A22 etc of the "Results" worksheet until there's no more values in the column G.
VBA is pretty new to me, I've tried using Do/Until, but everything crashed. Could you please help me? Please see the code I've recorded below. Thank you!
Sub(x)
Sheets("SalesData").Select
Range("G2").Select
Selection.Copy
Sheets("Results").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Range("A12").Select
Sheets("SalesData").Select
Range("G3").Select
Application.CutCopyMode = False
Selection.Copy
Sheets("Results").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Range("A22").Select
Sheets("SalesData").Select
Range("G4").Select
Application.CutCopyMode = False
Selection.Copy
Sheets("Results").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Range("A32").Select
Sheets("SalesData").Select
Range("G5").Select
Application.CutCopyMode = False
Selection.Copy
Sheets("Results").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
End Sub
I prefer to find the last cell in the column first then use a For loop.
Since you are only doing the values we can avoid the clipboard and assign the values directly.
Since you paste is every 10 cells we can use a separate counter to move down 10 each loop.
Sub x()
Dim ws As Worksheet
Dim lst As Long
Dim i As Long, j As Long
'use variable to limit the number of times we type the same thing
Set ws = Worksheets("Results")
'First row of the output
j = 2
'using with and the "." in front of those items that belong to it also limits the typing.
With Worksheets("SalesData")
'Find the last row with values in Column G
lst = .Cells(.Rows.Count, 7).End(xlUp).Row
'Loop from the second row to the last row.
For i = 2 To lst
'Assign the value
ws.Cells(j, 1).Value = .Cells(i, 7).Value
'Move down 10 rows on the output
j = j + 10
Next i
End With
End Sub
here is the same thing but using range variables
Sub x()
Dim src As Range
Dim dst As Range
Set dst = Worksheets("Results").Range("a2") ' point to top cell of destination
With Worksheets("SalesData")
For Each src In Range(.Cells(2, "g"), .Cells(.Rows.Count, "g").End(xlUp)) ' loop through used cell range in column G
dst.Value = src.Value
Set dst = dst.Offset(10) ' move destination pointer down 10 rows
Next src
End With
End Sub
This is just for fun/practice for another way to do it:
Sub copyFromG()
Dim copyRng As Range, cel As Range
Dim salesWS As Worksheet, resultsWS As Worksheet
Set salesWS = Sheets("SalesData")
Set resultsWS = Sheets("Results")
Set copyRng = salesWS.Range("G2:G" & salesWS.Range("G2").End(xlDown).Row) ' assuming you have a header in G1
For Each cel In copyRng
resultsWS.Range("A" & 2 + 10 * copyRng.Rows(cel.Row).Row - 30).Value = cel.Value
Next cel
End Sub

Stack Three Macros into One VBA Command

I have three macros (below) that work separately, but when I sandwich them together, only the first macro executes properly. I'm not getting an error; the other two macros just don't seem to run. Any advice on how to link them together so I can execute all at once?
Macro 1
Sub Update_Workbook()
Dim QryStr As String, cell As String
Dim a As Integer, b As Integer
Dim cellv As Variant
'Pause spreadsheet calculations until end of sub
Application.Calculation = xlManual
ActiveWorkbook.Sheets("Raw Data").Select
'Clear cells to import query
With Range("A1:O1").EntireColumn
.ClearContents
.NumberFormat = "General"
.Validation.Delete
End With
'Process SQL query string
QryStr = ActiveSheet.TextBox1.Value
Do While InStr(QryStr, "{&")
a = InStr(QryStr, "{&")
b = InStr(a, QryStr, "}")
cell = Mid(QryStr, a + 2, b - a - 2)
cellv = Range(cell).Value
If IsDate(cellv) Then
cellv = Format(cellv, "dd-mmm-yy")
End If
QryStr = Replace(QryStr, "{&" & cell & "}", cellv)
Loop
'Import data from query
With ActiveSheet.QueryTables.Add(Connection:="ODBC;DRIVER={Oracle in OraClient11g_home1};UID=xx;PWD=xx;SERVER=xx;DBQ=xx", _
Destination:=Range("A1"), Sql:=QryStr)
.MaintainConnection = False
.BackgroundQuery = False
.RefreshStyle = xlOverwriteCells
.Refresh
.Delete
End With
Finish_Sub:
Call ClearUnneededNames
Application.Calculation = xlCalculationAutomatic
End Sub
Sub ClearUnneededNames()
Dim savedNames As Integer
savedNames = 0
Do While ActiveSheet.Names.Count > savedNames
If InStr(ActiveSheet.Names(savedNames + 1).Name, "ExternalData") = 0 Then
savedNames = savedNames + 1
Else
ActiveSheet.Names(savedNames + 1).Delete
End If
Loop
End Sub
Macro 2
Sub Five_Felicia_for_MFG()
'
' Macro3 Macro
'
'
Range("A3:M3").Select
Range(Selection, Selection.End(xlDown)).Select
Range(Selection, Selection.End(xlDown)).Select
Range(Selection, Selection.End(xlUp)).Select
Range(Selection, Selection.End(xlDown)).Select
ActiveWindow.SmallScroll Down:=-18
Range(Selection, Selection.End(xlUp)).Select
Range("A3:M1010").Select
Selection.Delete Shift:=xlUp
Sheets("5Felicia").Select
Range("A3:M34").Select
Selection.Copy
Sheets("5Felicia for MFG").Select
Range("A3").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Selection.PasteSpecial Paste:=xlPasteFormats, Operation:=xlNone, _
SkipBlanks:=False, Transpose:=False
Sheets("5Felicia").Select
Range("A37:M37").Select
Range(Selection, Selection.End(xlDown)).Select
Range("A37:M692").Select
Application.CutCopyMode = False
Selection.Copy
Sheets("5Felicia for MFG").Select
ActiveWindow.SmallScroll Down:=18
Range("A36").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Selection.PasteSpecial Paste:=xlPasteFormats, Operation:=xlNone, _
SkipBlanks:=False, Transpose:=False
ActiveWindow.SmallScroll Down:=-48
Columns("A:M").Select
Application.CutCopyMode = False
ActiveSheet.Range("$A$1:$M$691").RemoveDuplicates Columns:=Array(1, 2, 3, 4, 5, 6, _
7, 8, 9, 10, 11, 12, 13), Header:=xlNo
End Sub
Macro 3
Sub DUMMY_ITEMS()
'
' DUMMY_ITEMS Macro
Dim LastRow As Long
Sheets("Operations").Range("H2:V73").Copy
With Sheets("Raw Data")
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
.Range("A" & LastRow + 1).PasteSpecial xlPasteValues
End With
End Sub
In VBA a Module can have several macros (or, more accurately, subroutines) in it.
But, when you call one of those macros, execution stops at the End Sub statement. Nothing else in the module will run regardless of how you "sandwich" them together within the module.
But subroutines can call other subroutines. So code like this will run all three of your macros:
Sub RunAllThree()
Update_Workbook
Five_Felicia_for_MFG
DUMMY_ITEMS
End Sub

Trying to copy specific columns in a row to another excel sheet based on it meeting certain criteria

Im very new to excel/vba and trying to use a macro to check a column for the value true, when it sees that value I'd like it to copy parts of that row to another sheet in my column. Then I need it to iterate through the other rows and perform the same checks. Here is my code currently.
Sub Macro3()
'
' Macro3 Macro
'
'
Sheets("Aspen Data").Select
Dim tfCol As Range, Cell As Object
Set tfCol = Range("G26:G56")
Sheets("Code").Select
ActiveSheet.Calculate
Sheets("Aspen Data").Select
ActiveSheet.Calculate
For Each Cell In tfCol
If IsEmpty(Cell) Then
Exit Sub
End If
If Cell.Value = "True" Then
Range("I26:Q26").Select
Selection.Copy
Sheets("AspenHist").Select
Range("B" & Rows.Count).End(xlUp).Offset(1).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
End If
Next
End Sub
The issue appears to be in getting my Range("I26:Q26) to increment by one as it goes through the loop.
Try this
Sheets("Aspen Data").Select
Dim i As Integer
Sheets("Code").Calculate
Sheets("Aspen Data").Calculate
For i = 26 To 56
If IsEmpty(Cells(i, 7)) Then
Exit Sub
ElseIf Cells(i, 7).Value = "True" Then
Range(Cells(i, 9), Cells(i, 12)).Copy
Sheets("AspenHist").Activate
Range("B" & Rows.Count).End(xlUp).Offset(1).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Sheets("Aspen Data").Activate
End If
Next i
There's no need to use .Select/.Activate/ActiveSheet (see this) to accomplish your goals, and you can definitely use For Each. Try this:
Option Explicit
Sub Macro1()
'
' Macro1 Macro
'
'
Dim tfCol As Range, Cell As Object
Set tfCol = Sheets("Aspen Data").Range("G26:G56")
Application.ScreenUpdating = False
Sheets("Code").Calculate
Sheets("Aspen Data").Calculate
For Each Cell In tfCol
If IsEmpty(Cell) Then
Exit For
End If
If Cell.Value = "True" Then
Sheets("Aspen Data").Range("I" & Cell.Row & ":Q" & Cell.Row).Copy
Sheets("AspenHist").Range("B" & Rows.Count).End(xlUp).Offset(1).PasteSpecial _
Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
End If
Next
Application.ScreenUpdating = True
End Sub

Loop to copy results of filtered table

I'm working on a work schedule, where I have a list of employees name and a flat table with everyone schedule per day. My macro should for each employee filter the data, copy it and paste it in a new sheet with his/her name.
Sub EnvoiPlanning()
'Sheets("People").Range("B:B").RemoveDuplicates Columns:=1, Header:= _
xlYes
Dim i As Integer
i = 2
While Sheets("People").Cells(i, 1) <> ""
Sheets("Data").Range("A:O").AutoFilter Field:=2, Criteria1:=Sheets("People").Cells(i, 1).Value
Sheets("Data").Range("A:F").Select
Selection.Copy
Sheets.Add After:=Sheets(Sheets.Count)
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Sheets(Sheets.Count).Name = Sheets("People").Cells(2, 1).Value
i = i + 1
Wend
End Sub
There is error:
Run-time error '1004': Select method of Range class failed
on the second instruction of the loop after the first iteration.
Try this :
Sub EnvoiPlanning()
'Sheets("People").Range("B:B").RemoveDuplicates Columns:=1, Header:= _
xlYes
Dim i As Integer, _
Ws As Worksheet
i = 2
While Sheets("People").Cells(i, 1) <> ""
Sheets("Data").Range("A:O").AutoFilter Field:=2, Criteria1:=Sheets("People").Cells(i, 1).Value
Sheets("Data").Range("A:F").Copy
Set Ws = Sheets.Add(After:=Sheets(Sheets.Count))
Ws.Range("A1").PasteSpecial Paste:=xlPasteValues, _
Operation:=xlNone, _
SkipBlanks:=False, _
Transpose:=False
Ws.Name = Sheets("People").Cells(2, 1).Value
i = i + 1
Wend
End Sub

copy row in vba - add the same autonumber to few rows

I try to copy in the excel few rows to a table, and give the same auto number to the rowa I add in each opparation.
I have a macro that copy the rows and gives the first line (of the new lines I just added) the next auto number. I want to add the same number to the other rows. (and each time there can be different numbers of rows, but not more then 16).
my macro is:
Sub copy_order()
'
'
Sheets("orders").Select
Application.Goto Reference:="product"
ActiveCell.Range("A1:D16").Select
Selection.Copy
Application.Goto Reference:="orders_table"
Selection.End(xlDown).Select
ActiveCell.Offset(1, 1).Range("A1").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
ActiveCell.Offset(0, -1).Range("A1").Select
Application.CutCopyMode = False
ActiveCell.FormulaR1C1 = "=R[-1]C+1"
ActiveCell.Offset(1, 0).Range("A1").Select
Application.Goto Reference:="product"
ActiveCell.Offset(0, 0).Range("A1:C1").Select
Selection.ClearContents
Application.Goto Reference:="orders_table"
End Sub
thank you, Keren.
Not sure I followed all your offsets correctly, but this should get you close...
Sub copy_order()
Dim rngDest As Range, rngCopy As Range, sht As Worksheet, num
Dim c As Range
Set sht = Sheets("orders")
Set rngCopy = sht.Range("product").Range("A1:D16")
Set rngDest = sht.Range("orders_table").Cells(1).End(xlDown).Offset(1, 0)
rngDest.Resize(rngCopy.Rows.Count, rngCopy.Columns.Count).Value = rngCopy.Value
num = rngDest.Offset(-1, -1).Value + 1
Do While Application.CountA(rngDest.Resize(1, rngCopy.Columns.Count)) > 0
rngDest.Offset(0, -1).Value = num
Set rngDest = rngDest.Offset(1, 0)
Loop
End Sub