How to delete duplicate entries completely - vba

I have a column in excel, using vba I am trying to check if there is a duplicate entry in that column then delete duplicate and also main entry so there will be no value related to that entry anymore. What would be the way to do this ?
Input column=>
1
2
3
1
4
5
2
desired output column =>
3
4
5
Actually my entries are text but, I gave numerical example to make it clear
After answers my code became
Last_Row = ws1.Cells(Rows.Count, "G").End(xlUp).Row
Columns("G:H").Select
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Add Key:=Range("G2", "G" & Last_Row) _
, SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Sheet1").Sort
.SetRange Range("G1", "H" & Last_Row)
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Dim i As Integer
i = 2
While (i < Last_Row + 1 And Not IsEmpty(Cells(i, 7).Value))
If Cells(i, 7) = Cells(i + 1, 7) Then
Range("G" & i + 1, "H" & i + 1).Delete Shift:=xlUp
Range("G" & i, "H" & i).Delete Shift:=xlUp
End If
If Not Cells(i, 7) = Cells(i + 1, 7) Then
i = i + 1
End If
Wend

This works. I haven't tried to optimise it or anything.
Dim v As Variant
Dim vOut As Variant
Dim ditch() As Integer
Dim i As Long, j As Long, n As Long
'Read input column into 2D array
v = Range("A1:A7").Value
'Mark which inputs to ditch (mark as 1 if duplicate, keep at 0 if not)
ReDim ditch(LBound(v, 1) To UBound(v, 1))
For i = LBound(v, 1) To UBound(v, 1)
For j = i + 1 To UBound(v)
If ditch(j) = 0 And v(j, 1) = v(i, 1) Then
ditch(i) = 1
ditch(j) = 1
End If
Next j
Next i
'How many non-duplicates are there?
n = UBound(v, 1) - LBound(v, 1) + 1 - WorksheetFunction.Sum(ditch)
'Put non-duplicates in new 2D array
ReDim vOut(1 To n, 1 To 1)
j = 0
For i = LBound(v, 1) To UBound(v, 1)
If ditch(i) = 0 Then
j = j + 1
vOut(j, 1) = v(i, 1)
End If
Next i
'Write array to sheet
Range("B1").Resize(n).Value = vOut

Not using VBA, a 'helper' column with =COUNTIF(A:A,A1) copied down to suit,if your data starts in Row1, should identify duplicates. Filter on the helper column and delete rows showing values greater than 1 may be suitable for you.

Create a macro Excel. Your Data should be in the first column and the worksheet to be called "Sheet1"
Columns("A:A").Select
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Add Key:=Range("A2"), _
SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Sheet1").Sort
.SetRange Columns("A")
.Header = xlNo
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Dim i As Integer
Dim b As Boolean
i = 1
b = False
While Cells(i, 1) > 0
While Cells(i, 1) = Cells(i + 1, 1)
Rows(i + 1).Delete
b = True
Wend
If b = True Then
Rows(i).Delete
b = False
i = i - 1
End If
i = i + 1
Wend

In Excel 2007
click the "Data" Tab in the ribbon
Highlight your selection
click "Remove Duplicates"

Related

Copying values from a range with added header and sorting by size in Excel with vba

I have a table ranging from B5 to R20, every row has a header and not every cell in range (except headers) has values. Table looks like this:
John empty empty 2 5 300...
Steve empty 23 45 130...
Todd 100 123 150 170...
...
Names are headers and instead of zeros there are empty cells. I need to copy these values in a new column (column AJ) and I need to copy the appropriate header next to every value (header value goes in column AI). After the copy those two columns should be sorted descending by AJ column. I have this so far:
Sub Sorter()
Dim g As Integer
Dim sourceCol As Integer
Dim rowCount As Integer
Dim currentRow As Integer
Dim currentRowValue As String
Dim sourceCol1 As Integer
Dim rng1 As Range
Dim t As Integer
sourceCol = 35
sourceCol1 = sourceCol + 1
rowCount = 300
t = 5
For g = 1 To 16
Set rng1 = Range(Rows(t).Cells(3), Rows(t).Cells(18))
If rng1.Cells(g) > 0 Then
For currentRow = 1 To rowCount
currentRowValue = Cells(currentRow, sourceCol).Value
If IsEmpty(currentRowValue) Or currentRowValue = "" Then
Cells(t, 2).Select
Selection.Copy
Cells(currentRow, sourceCol).PasteSpecial xlPasteValues
Cells(t, g).Select
Selection.Copy
Cells(currentRow, sourceCol1).PasteSpecial xlPasteValues
End If
Next currentRow
End If
t = t + 1
Next g
' This part sorts the two columns
Columns("AI:AJ").Select
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Add Key:=Range( _
"AJ1:AJ300"), SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:= _
xlSortNormal
With ActiveWorkbook.Worksheets("Sheet1").Sort
.SetRange Range("AI1:AJ300")
.Header = xlGuess
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Kraj:
End Sub
So, the sorting part is working, but the copying part is giving me problems. I'm stuck so can you please help?
The result should be:
AI AJ
John 300
Todd 170
Todd 150
Steve 130
... etc
a possible solution to test.
Sub Sorter()
Dim g As Integer
Dim sourceCol As Integer
Dim rowCount As Integer
Dim currentRow As Integer
Dim targetrow As Long
Dim currentRowValue As String
Dim sourceCol1 As Integer
Dim rng1 As Range
Dim t As Integer
sourceCol = 35
sourceCol1 = sourceCol + 1
rowCount = 300
targetrow = 1
t = 5
With ActiveWorkbook.Worksheets("Sheet1")
While .Cells(t, 1) <> ""
For g = 2 To 17
If .Cells(t, g) > 0 Then
targetrow = targetrow + 1
.Cells(targetrow, sourceCol) = .Cells(t, 1)
.Cells(targetrow, sourceCol1) = .Cells(t, g)
End If
Next g
t = t + 1
Wend
' This part sorts the two columns
With .Sort
.SortFields.Clear
.SortFields.Add Key:=Range("AJ1:AJ300"), SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
.SetRange Range("AI1:AJ300")
.Header = xlGuess
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End With
End Sub

VBA script to copy adjacent cells on same row if duplicate found

I modified the code only at one point because it was what I needed but I need something extra and I can't figure out how to do it.
Here is the original code from this post :
Sub test()
Dim lastRow As Integer, i As Integer
Dim cel As Range, rng As Range, sortRng As Range
Dim curString As String, nextString As String
Dim haveHeaders As Boolean
haveHeaders = False ' Change this to TRUE if you have headers.
lastRow = Cells(1, 1).End(xlDown).Row
If haveHeaders Then 'If you have headers, we'll start the ranges in Row 2
Set rng = Range(Cells(2, 1), Cells(lastRow, 1))
Set sortRng = Range(Cells(2, 1), Cells(lastRow, 2))
Else
Set rng = Range(Cells(1, 1), Cells(lastRow, 1))
Set sortRng = Range(Cells(1, 1), Cells(lastRow, 2))
End If
' First, let's resort your data, to get all of the "Column A" values in order, which will group all duplicates together
With ActiveSheet
.Sort.SortFields.Clear
.Sort.SortFields.Add Key:=rng, SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With .Sort
.SetRange sortRng
.Header = xlGuess
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
' Now, let's move all "Column B" data for duplicates into Col. C
' We can check to see if the cell's value is a duplicate by simply counting how many times it appears in `rng`
Dim isDuplicate As Integer, firstInstanceRow As Integer, lastInstanceRow As Integer
If haveHeaders Then
curString = Cells(2, 1).Value
Else
curString = Cells(1, 1).Value
End If
Dim dupRng As Range 'set the range for the duplicates
Dim k As Integer
k = 0
For i = 1 To lastRow
If i > lastRow Then Exit For
Cells(i, 1).Select
curString = Cells(i, 1).Value
nextString = Cells(i + 1, 1).Value
isDuplicate = WorksheetFunction.CountIf(rng, Cells(i, 1).Value)
If isDuplicate > 1 Then
firstInstanceRow = i
Do While Cells(i, 1).Offset(k, 0).Value = nextString
'Cells(i, 1).Offset(k, 0).Select
lastInstanceRow = Cells(i, 1).Offset(k, 0).Row
k = k + 1
Loop
Range(Cells(firstInstanceRow + 1, 2), Cells(lastInstanceRow, 3)).Copy
Cells(firstInstanceRow, 5).PasteSpecial xlPasteValues
Application.CutCopyMode = False
Range(Rows(firstInstanceRow + 1), Rows(lastInstanceRow)).EntireRow.Delete
k = 0
lastRow = Cells(1, 1).End(xlDown).Row
End If
Next i
End With
End Sub
What I did is:
changed this:
Range(Cells(firstInstanceRow + 1, 2), Cells(lastInstanceRow, 2)).Copy
Cells(firstInstanceRow, 3).PasteSpecial Paste:=xlPasteAll, Operation:=xlNone, SkipBlanks:=False, Transpose:=True
Application.CutCopyMode = False
to
Range(Cells(firstInstanceRow + 1, 2), Cells(lastInstanceRow, 3)).Copy
Cells(firstInstanceRow, 5).PasteSpecial xlPasteValues
Application.CutCopyMode = False
What I have is:
Column A has duplicates.
Column B has unique value.
And column C has the qty for the unique values.
It works until the copy and paste part with the exception that it copies either column C under value from column B or the other way is that it copies each value from Column B with the qty from Column C but when it finishes, it deletes all the duplicates.
Example
Column A Column B column C
322 sku322 qty 20
322 322sku qty 25
it outputs like
Column D column E
sku322 qty 20
322sku qty 25
And when it's finished, it delete the second row. This means that i don't have the second unique value.
Or it outputs like:
Column D Column E
sku322 322sku
qty 20 qty 25
And then it delete the last row and I don't have the qty anymore.
From my way of thinking if there is no way to paste on the same line, that would mean that after each find it should retake the loop and not copy/paste in bulk. But I tried multiple ways and can't seem to find a way to make it work.
Hows this? Screenshot of the results:
Note: If you want the ENTIRE 'unique-sku' column instead of just the country code, change
country = Right(Cells(i, 2), 2)
to
country = Cells(i, 2).Value
Code:
Sub Macro1()
'
' Macro1 Macro
'
Dim country As String, qty As Integer
Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
' Headers
dict("country") = "sum"
' Loop through all rows starting on row 2; per Column A
For i = 2 To Sheets("Sheet1").Cells(1, 1).End(xlDown).Row
' Country = last 2 letters of Column B
country = Right(Cells(i, 2), 2)
qty = CInt(Cells(i, 3).Value)
' If it already exists, add the new amount to the sum.
If dict.Exists(country) Then
qty = dict(country) + qty
End If
' This will create it if it doesn't already exist. Otherwise, update.
dict(country) = qty
Next
' Here are some display options.
' Horizontal
Range("F2").Resize(1, UBound(dict.Keys()) + 1).Value = dict.Keys()
Range("F3").Resize(1, UBound(dict.Items()) + 1).Value = dict.Items()
' Vertical
Range("F5").Resize(UBound(dict.Keys()) + 1).Value = WorksheetFunction.Transpose(dict.Keys())
Range("G5").Resize(UBound(dict.Items()) + 1).Value = WorksheetFunction.Transpose(dict.Items())
Set dict = Nothing
'
End Sub
So i found a workaround, i don't know if it's the most feasable one but it works and for 10.000 rows it does it in 40 seconds to 1 minute max.
You need to create 3 modules and a function (i did not want to put the function in the on the modules.
Module 1
Sub Simplify()
Application.Run "Module9.RemovePart"
Application.Run "Module10.SameRowDuplicates"
End Sub
Module 2
Private Sub RemovePart()
Dim fndList As Variant
Dim fndRplc As Variant
With ActiveSheet
Range("B1").EntireColumn.Insert 'Here i inserted a new column so i can duplicate the first column
Range("A1", Range("A" & Rows.Count).End(xlUp)).Copy ' Copied the first column to the inserted one
Range("B1", Range("B" & Rows.Count).End(xlUp)).PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False
Application.CutCopyMode = False
lastRow = Cells(Rows.Count, "A").End(xlUp).Row ' selected first column to remove the end of the sku
fndList = Array("FR", "DE", "ES") ' here you can just change to whatevery you want to remove
fndRplc = "" ' here is what it replaces it with
For x = LBound(fndList) To UBound(fndList)
For i = lastRow To 1 Step -1
Range("A1").EntireColumn.Replace What:=fndList(x), Replacement:=fndRplc, _
LookAt:=xlPart, SearchOrder:=xlByColumns, MatchCase:=False, _
SearchFormat:=False, ReplaceFormat:=False
Next i
Next x
End With
End Sub
Module 3
Private Sub SameRowDuplicates()
Dim lastRow As Integer, i As Integer
Dim cel As Range, Rng As Range, sortRng As Range
Dim curString As String, nextString As String
Dim haveHeaders As Boolean
haveHeaders = True ' Change this to TRUE if you have headers.
lastRow = Cells(1, 1).End(xlDown).Row
If haveHeaders Then 'If you have headers, we'll start the ranges in Row 2
Set Rng = Range(Cells(2, 1), Cells(lastRow, 1))
Set sortRng = Range("A2").CurrentRegion
Else
Set Rng = Range(Cells(1, 1), Cells(lastRow, 1))
Set sortRng = Range("A1").CurrentRegion
End If
' First, let's resort your data, to get all of the "Column A" values in order, which will group all duplicates together
With ActiveSheet
.Sort.SortFields.Clear
.Sort.SortFields.Add Key:=Rng, SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With .Sort
.SetRange sortRng
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
' Now, let's move all "Column B" data for duplicates into Col. C
' We can check to see if the cell's value is a duplicate by simply counting how many times it appears in `rng`
Dim isDuplicate As Integer, firstInstanceRow As Integer, lastInstanceRow As Integer
If haveHeaders Then
curString = Cells(2, 1).Value
Else
curString = Cells(1, 1).Value
End If
Dim dupRng As Range 'set the range for the duplicates
Dim k As Integer
k = 0
For i = 1 To lastRow
If i > lastRow Then Exit For
Cells(i, 1).Select
curString = Cells(i, 1).Value
nextString = Cells(i + 1, 1).Value
isDuplicate = WorksheetFunction.CountIf(Rng, Cells(i, 1).Value)
If isDuplicate > 1 Then
firstInstanceRow = i
Do Until Cells(i, 1).Offset(k, 0).Value <> nextString
'Cells(i, 1).Offset(k, 0).Select
lastInstanceRow = Cells(i, 1).Offset(k, 0).Row
k = k + 1
Loop
Cells(firstInstanceRow, 5).Formula = "=Combine(" & Range(Cells(firstInstanceRow + 1, 2), Cells(lastInstanceRow, 3)).Address(False, False) & ")" ' combine the results in one row so you have all the duplicates one after another
Cells(firstInstanceRow, 5).Copy
Cells(firstInstanceRow, 5).PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False
Application.CutCopyMode = False
Selection.TextToColumns DataType:=xlDelimited, _ ' this is for converting comma delimited to columns
ConsecutiveDelimiter:=False, Semicolon:=True ' here you should change your delimiter to what you are using
Range(Rows(firstInstanceRow + 1), Rows(lastInstanceRow)).EntireRow.Delete
k = 0
lastRow = Cells(1, 1).End(xlDown).Row
End If
Next i
End With
End Sub
Function 1
Function Combine(WorkRng As Range, Optional Sign As String = ";") As String
'Update 20130815
Dim Rng As Range
Dim OutStr As String
For Each Rng In WorkRng
If Rng.Text <> ";" Then
OutStr = OutStr & Rng.Text & Sign
End If
Next
Combine = Left(OutStr, Len(OutStr) - 1)
End Function
So quick story:
Module 1 calls for the other modules, i did it this way to make things easier for the end-user so he doesn't see all the modules just needs to click one.
Module 2 removes any text from the selected cells
Module 3 finds the duplicates and puts them on one line delimited by what you select in the function module. And then deletes the duplicates row.
Function 1 takes the output of you selection and puts it on one row delimited.
That is all, thanks for everybody's help and i wish this will help others.

Excel Macro: Copy data into new worksheet and sort base on date and random number

For the following excel data:
1 Name Date Color_picked
2 John 8/1/2015 Red
3 Jason 8/13/2015 Blue
4 Kevin 8/12/2015 Yellow
5 Derek 8/13/2015 Blue
6 Cherry 8/1/2015 Red
I want to do the follow:
1) Generate a random number for each of row (Not including the title row)
2) Copy all the records into a new tab/worksheet base on the color(Red, Blue and Yellow tabs)
3) Within each new tabs (Red, Blue and Yellow tabs), first sort the record by the date, if deplicated date, then sort by the random number.
This is what I have so far:
Sub myFoo()
Application.CutCopyMode = False
On Error GoTo Err_Execute
Sheet1.Range("B1:F3").Copy
Red.Range("A1").Rows("1:1").Insert Shift:=xlDown
Err_Execute:
If Err.Number = 0 Then MsgBox "Transformation Done!" Else _
MsgBox Err.Description
End Sub
Should I be creating the copy first or sort first?
This should do the trick :
Sub test_Ryan_Fung()
Dim WsSrc As Worksheet, _
WsRed As Worksheet, _
WsBlue As Worksheet, _
WsYellow As Worksheet, _
Ws As Worksheet, _
DateFilterRange As String, _
RandomRange As String, _
TotalRange As String, _
LastRow As Long, _
WriteRow As Long, _
ShArr(), _
Arr()
Set WsSrc = Sheet1
Set WsRed = Sheets("Red")
Set WsBlue = Sheets("Blue")
Set WsYellow = Sheets("Yellow")
ReDim ShArr(1 To 3)
Set ShArr(1) = WsRed: Set ShArr(2) = WsBlue: Set ShArr(3) = WsYellow
Application.CutCopyMode = False
On Error GoTo Err_Execute
With WsSrc
LastRow = .Range("A" & .Rows.Count).End(xlUp).Row
For i = 2 To LastRow
.Cells(i, 5) = Application.WorksheetFunction.RandBetween(1, 10000)
Next i
Arr = .Range("A2:E" & LastRow).Value
End With
For i = LBound(Arr, 1) To UBound(Arr, 1)
Select Case LCase(Arr(i, 4))
Case Is = "red"
With WsRed
WriteRow = .Range("A" & .Rows.Count).End(xlUp).Row + 1
For j = LBound(Arr, 2) To UBound(Arr, 2)
.Cells(WriteRow, j) = Arr(i, j)
Next j
End With
Case Is = "blue"
With WsBlue
WriteRow = .Range("A" & .Rows.Count).End(xlUp).Row + 1
For j = LBound(Arr, 2) To UBound(Arr, 2)
.Cells(WriteRow, j) = Arr(i, j)
Next j
End With
Case Is = "yellow"
With WsYellow
WriteRow = .Range("A" & .Rows.Count).End(xlUp).Row + 1
For j = LBound(Arr, 2) To UBound(Arr, 2)
.Cells(WriteRow, j) = Arr(i, j)
Next j
End With
Case Else
MsgBox "Color not recognised : " & Arr(i, 4), vbCritical + vbOKOnly
End Select
Next i
For i = LBound(ShArr, 1) To UBound(ShArr, 1)
Set Ws = ShArr(i)
With Ws
LastRow = .Range("A" & .Rows.Count).End(xlUp).Row
DateFilterRange = "C2:C" & LastRow
RandomRange = "E2:E" & LastRow
TotalRange = "A1:E" & LastRow
With .Sort
With .SortFields
.Clear
.Add Key:=Range(DateFilterRange), _
SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
.Add Key:=Range(RandomRange), _
SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
End With
.SetRange Range(TotalRange)
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End With
Next i
Err_Execute:
If Err.Number = 0 Then
MsgBox "Transformation Done!"
Else
MsgBox Err.Description
End If
End Sub

Excel VBA: How to add cells in a rows based on matched values

I am trying to sum values in rows in column B, C, D and E and output the sum values in column k, l, m and n. The criteria is matching the value between column A and J.
The output is not getting the summation correctly for multiple row entries with the same number. For example, for a specific cell value in column A = 32605 that only has one line entry with the following values as input:
Pr Pl La Sc
0 1 0 0
Output is getting in column K, L, M and N:
Pr Pl La Sc
17 0 0 1
For the above example, the output should be:
Pr Pl La Sc
0 1 0 0
For multiple row entries example, Column A cell value = 35092 and the input:
Pr Pl La Sc
0 1 0 0
0 2 0 0
0 1 0 0
0 3 0 0
0 2 0 0
0 1 0 0
0 1 0 0
84 0 0 7
0 2 0 0
Output is showing as:
Pr Pl La Sc
0 4 0 0
The correct output should be:
Pr Pl La Sc
84 13 0 7
Here is the full code
Sub A1Report()
ActiveSheet.Name = "AccessImport"
' Get the start and end date from the user
Dim TheString1 As String, TheString2 As String, TheStartDate As Date, TheEndDate As Date
Dim TotalDaysEntered As Integer
TheString1 = Application.InputBox("Enter the start date:")
If IsDate(TheString1) Then
TheStartDate = DateValue(TheString1)
Else
MsgBox "Invalid date entered"
End If
TheString2 = Application.InputBox("Enter the end date:")
If IsDate(TheString2) Then
TheEndDate = DateValue(TheString2)
Else
MsgBox "Invalid date entered"
End If
' The following code extracts the data for a specific date range provided by the user.
ActiveSheet.ListObjects("Table_ARM_Activity_Tracker").Range.AutoFilter field:=7, Criteria1:=">=" & TheStartDate, Operator:=xlAnd, Criteria2:="<=" & TheEndDate
' The next block of code fills up all the blank cells found in column A with E4486 or 004486.
Dim c As Integer
For c = 1 To Range("A" & Rows.Count).End(xlUp).Row
If Range("A" & c).Value = vbNullString Then
Range("A" & c).Value = "004486"
End If
Next c
Columns("A:W").HorizontalAlignment = xlCenter
Dim LastRowFrom As Long
Dim LastRowTo As Long
Dim i As Long, j As Long
Dim temp As Long
Dim found As Boolean
'determines the last row that contains data in column A
LastRowFrom = Range("A" & Rows.Count).End(xlUp).Row
' Copy data from active sheet to another sheet
ActiveWorkbook.Worksheets.Add
ActiveSheet.Name = "DeanRoberts"
Worksheets("AccessImport").Activate
Dim mainworkBook As Workbook
Set mainworkBook = ActiveWorkbook
mainworkBook.Sheets("AccessImport").UsedRange.Copy
mainworkBook.Sheets("DeanRoberts").Select
mainworkBook.Sheets("DeanRoberts").Range("A1").Select
mainworkBook.Sheets("DeanRoberts").Paste
' Find the unique values and place these identified unique values from Column A into Column J
Worksheets("DeanRoberts").Activate
Dim d2 As Object, c2 As Variant, i2 As Long, lr2 As Long
Set d2 = CreateObject("Scripting.Dictionary")
lr2 = Cells(Rows.Count, 1).End(xlUp).Row
c2 = Range("A2:A" & lr2)
For i2 = 1 To UBound(c2, 1)
d2(c2(i2, 1)) = 1
Next i2
Range("J2").Resize(d2.Count) = Application.Transpose(d2.keys)
' Clear contents after the last rows with values in column J
Worksheets("DeanRoberts").Activate
' Sum values found in column B for each unique WR# in Column J, output the result on Column K, L, M, N
Dim rowIndex As Long
Dim calcFormula1 As Double
Dim calcFormula2 As Double
Dim calcFormula3 As Double
Dim calcFormula4 As Double
For rowIndex = 2 To lr2
calcFormula1 = Application.SumIf(Range("A:A"), "*" & Cells(rowIndex, "J").Value & "*", Range("B:B"))
calcFormula2 = Application.SumIf(Range("A:A"), "*" & Cells(rowIndex, "J").Value & "*", Range("C:C"))
calcFormula3 = Application.SumIf(Range("A:A"), "*" & Cells(rowIndex, "J").Value & "*", Range("D:D"))
calcFormula4 = Application.SumIf(Range("A:A"), "*" & Cells(rowIndex, "J").Value & "*", Range("E:E"))
Cells(rowIndex, "K").Value = calcFormula1
Cells(rowIndex, "L").Value = calcFormula2
Cells(rowIndex, "M").Value = calcFormula3
Cells(rowIndex, "N").Value = calcFormula4
Cells(rowIndex, "O").Value = calcFormula1 + calcFormula2 + calcFormula3 + calcFormula4
Next rowIndex
For rowIndex = 2 To lr2
Cells(rowIndex, "P").Value = (Cells(rowIndex, "O").Value * 0.008) + 0.08
Next rowIndex
' Sort values, lowest to highest number WR#
ActiveWorkbook.Worksheets("DeanRoberts").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("DeanRoberts").Sort.SortFields.Add Key:=Range( _
"J:J"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= _
xlSortNormal
With ActiveWorkbook.Worksheets("DeanRoberts").Sort
.SetRange Range("J:J")
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Columns("J:J").EntireColumn.AutoFit
Range("O1").Select
Columns("O:O").EntireColumn.AutoFit
Columns("P:P").EntireColumn.AutoFit
' Inserting title of the columns
Cells(1, "J").Value = "WR#"
Cells(1, "K").Value = "Prints"
Cells(1, "L").Value = "Plots"
Cells(1, "M").Value = "Laminate"
Cells(1, "N").Value = "Scans"
Cells(1, "O").Value = "Total Usage"
Cells(1, "P").Value = "Total Hours"
' Cells(1, "P").Value = "Grand Total"
'Cells(2, "P").Value = calcTotal
'avgNumber = calcTotal / TotalDaysEntered
'Cells(1, "Q").Value = "Average"
'Cells(2, "Q").Value = avgNumber
Cells(1, 10).Font.Bold = True
Cells(1, 11).Font.Bold = True
Cells(1, 12).Font.Bold = True
Cells(1, 13).Font.Bold = True
Cells(1, 14).Font.Bold = True
Cells(1, 15).Font.Bold = True
Cells(1, 16).Font.Bold = True
Cells(1, 17).Font.Bold = True
Cells(1, 18).Font.Bold = True
Columns("A:W").HorizontalAlignment = xlCenter
End Sub
Hoping to get your help. Let me know if more info is needed.
Thank you.
mk
From your example, it seems you are trying to use wildcarded 'pattern matches' on numerical values. The
Dim rowIndex As Long
Dim calcFormula1 As Double
Dim calcFormula2 As Double
Dim calcFormula3 As Double
Dim calcFormula4 As Double
For rowIndex = 2 To lr2
calcFormula1 = Application.SumIf(Range("A:A"), Cells(rowIndex, "J").Value, Range("B:B"))
calcFormula2 = Application.SumIf(Range("A:A"), Cells(rowIndex, "J").Value, Range("C:C"))
calcFormula3 = Application.SumIf(Range("A:A"), Cells(rowIndex, "J").Value, Range("D:D"))
calcFormula4 = Application.SumIf(Range("A:A"), Cells(rowIndex, "J").Value, Range("E:E"))
Cells(rowIndex, "K").Value = calcFormula1
Cells(rowIndex, "L").Value = calcFormula2
Cells(rowIndex, "M").Value = calcFormula3
Cells(rowIndex, "N").Value = calcFormula4
Cells(rowIndex, "O").Value = calcFormula1 + calcFormula2 + calcFormula3 + calcFormula4
Next rowIndex
Your original code was producing false positives by finding 123 inside 91234.
Your sort routine is taking column J out of synch wiht columns K:O. Substitute what you have for this,
' Sort values, lowest to highest number WR#
With ActiveWorkbook.Worksheets("DeanRoberts")
With .Cells(2, 10).CurrentRegion
.Cells.Sort Key1:=.Columns(1), Order1:=xlAscending, _
Orientation:=xlTopToBottom, Header:=xlNo
End With
End With
I would also use the Range.Text property property for the sumifs.
calcFormula1 = Application.SumIf(Range("A:A"), Cells(rowIndex, "J").Text, Range("B:B"))
calcFormula2 = Application.SumIf(Range("A:A"), Cells(rowIndex, "J").Text, Range("C:C"))
calcFormula3 = Application.SumIf(Range("A:A"), Cells(rowIndex, "J").Text, Range("D:D"))
calcFormula4 = Application.SumIf(Range("A:A"), Cells(rowIndex, "J").Text, Range("E:E"))
This should compensate for the leading zeroes found in the numbers-that-are-actually-text.

simple loop used to be fast, now it's slow

I have a simple piece of code that used to burn through 45,000 rows of data in the blink of an eye and now it takes a very long time (~15 minutes). I have read through some similar problems but wanted to post the code since it is so basic. This code sums the individual weights of each item (one item per row) of an order and then populates a cell for each item with the total amount. It goes from top to bottom to get the total and then from bottom to top filling in the blanks. What am I missing?
Sub FillInTotalWeight()
'
' sort whole file by process order
'
'this macro sums all the children weights in a process order
'and then puts that total in column E for every child of the process order
'
Dim nLastRow As Long
Dim nRow As Long
Dim wtTot As Long
Dim nStop As Long
'
'determine the last row
'
nLastRow = ActiveSheet.UsedRange.Rows.Count
'
'sort by process order
'
ActiveWorkbook.Worksheets("zpr2013b").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("zpr2013b").Sort.SortFields.Add _
Key:=Range(Cells(1, "D"), Cells(nLastRow, "D")), _
SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("zpr2013b").Sort
.SetRange Range(Cells(1, "A"), Cells(nLastRow, "q"))
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
wtTot = Cells(2, "B").Value
'
'go top to bottom and put the total weight of each process order
'in the row of the last coil produced
'
For nRow = 2 To nLastRow
If Cells(nRow, "D").Value = Cells(nRow + 1, "D").Value Then
wtTot = wtTot + Cells(nRow + 1, "B").Value
Else
Cells(nRow, "E").Value = wtTot
wtTot = Cells(nRow + 1, "B").Value
End If
Next nRow
'
'go bottom to top and fill in all the blanks of the other coils
'
For x = nLastRow To 2 Step -1
If Cells(x, "E").Value = "" Then
Cells(x, "E").Value = Cells(x + 1, "E").Value
End If
Next x
End Sub
I would recommend using this code instead. It should run much faster for you and will accomplish the same thing:
Sub FillInTotalWeight()
Dim ws As Worksheet
Set ws = ActiveWorkbook.Sheets("zpr2013b")
ws.UsedRange.Sort Intersect(ws.UsedRange, ws.Columns("D")), xlAscending, Header:=xlYes
With Range("E2", ws.Cells(Rows.Count, "D").End(xlUp).Offset(, 1))
.Formula = "=SUMIF(D:D,D" & .Row & ",B:B)"
.Value = .Value
End With
End Sub