I have a list of 50000+ items in column A with their corresponding quantities in column B. There are duplicate items in A and I want to combine the quantities of the duplicate items then remove the duplicates rows.
Doing this in For-Next loops takes hours to complete. I am looking for a quicker method such as using the Find statement.
Thanks
can you try this experiment
keep the original file safe somewhere.
I presume that in sheet col A and B have column heading in row 1.
goto sheet2
selecst A1 in sheet2
click data(menu bar)-filter-advance filter
in teh advance filter window
against list ramge type
Sheet1!$A$1:$A$5000(row 5000 is the last row)
leave criteria range blank
choose "copy to another locations" at the top
click "unique records only" at the bottom
then in "copy to type
$A$1 (if it is not there already.
click Ok in the advance filter window.
you get unique values of column A of sheet 1 in column A of sheet 2
in cell B2 of sheet 2 type this formula
=SUMPRODUCT((Sheet1!$A$2:$A$5000=A2)*(Sheet1!$B$2:$B$5000))
copy this down to the last row.
will this take less time than a macro
Hello Matrex,
This macro is fast. It copies the cell data and the values into an array and uses the Dictionary Object to blank duplicates and sum the values. Lastly, the rows are that contain blanks are deleted. The default worksheet is "Sheet1" in the code. The default starting cell is "A2". Both of the values can be changed in the code to match what you using. They marked in red. Copy this code into a standard VBA module.
Adding the MacroSub MergeUniqueData() Dim Blanks As Range Dim Data As Variant Dim DSO As Object Dim I As Long Dim Item As Variant Dim Key As Variant Dim Rng As Range Dim RngEnd As Range StartTime = Timer Set Rng = Worksheets("Sheet1").Range("A2") Set RngEnd = Rng.Parent.Cells(Rows.Count, Rng.Column).End(xlUp) Set Rng = IIf(RngEnd.Row < Rng.Row, Rng, Rng.Parent.Range(Rng, RngEnd)) Application.ScreenUpdating = False Set DSO = CreateObject("Scripting.Dictionary") DSO.CompareMode = vbTextCompare Data = Rng.Resize(ColumnSize:=2).Value For I = 1 To UBound(Data, 1) Key = Trim(Data(I, 1)) If Key <> "" Then Item = Data(I, 2) If Not DSO.Exists(Key) Then DSO.Add Key, I Else Data(DSO(Key), 2) = Data(DSO(Key), 2) + Item Data(I, 1) = "" End If End If Next I Rng.Value = Data On Error Resume Next Set Blanks = Rng.SpecialCells(xlCellTypeBlanks) If Err = 0 Then Blanks.EntireRow.Delete Err.Clear On Error GoTo 0 Application.ScreenUpdating = True Set DSO = Nothing EndTime = Timer TotalTime = EndTime - StartTime '332.2813 End Sub
1. Copy the macro above pressing the keys CTRL+C
2. Open your workbook
3. Press the keys ALT+F11 to open the Visual Basic Editor
4. Press the keys ALT+I to activate the Insert menu
5. Press M to insert a Standard Module
6. Paste the code by pressing the keys CTRL+V
7. Make any custom changes to the macro if needed at this time.
8. Save the Macro by pressing the keys CTRL+S
9. Press the keys ALT+Q to exit the Editor, and return to Excel.
To Run the Macro...
To run the macro from Excel, open the workbook, and press ALT+F8 to display the Run Macro Dialog. Double Click the macro's name to Run it.
Last edited by Leith Ross; 07-05-2009 at 12:59 AM.
Sincerely,
Leith Ross
Remember To Do the Following....
1. Use code tags. Place [CODE] before the first line of code and [/CODE] after the last line of code.2. Thank those who have helped you by clicking the Starbelow the post.
3. Please mark your post [SOLVED] if it has been answered satisfactorily.
Old Scottish Proverb...
Luathaid gu deanamh maille! (Rushing causes delays!)
Try:
expression.Find(What, After, LookIn, LookAt, SearchOrder, SearchDirection, MatchCase, MatchByte, SearchFormat)
an good examplePlz see more detail at the link: http://www.ozgrid.com/VBA/find-method.htmSub FindCatOtherSheet() Dim rFound As Range On Error Resume Next With Sheet1 Set rFound = .Columns(1).Find(What:="Cat", After:=.Cells(1, 1), LookIn:=xlValues, LookAt:= _ xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False _ , SearchFormat:=False) On Error GoTo 0 If Not rFound Is Nothing Then Application.Goto rFound, True End With End Sub
Ref: http://www.ozgrid.com/VBA/find-method.htm
OR other example with loop:
ref: http://msdn.microsoft.com/en-us/libr...ffice.11).aspxExample This example finds all cells in the range A1:A500 on worksheet one that contain the value 2 and changes it to 5. With Worksheets(1).Range("a1:a500") Set c = .Find(2, lookin:=xlValues) If Not c Is Nothing Then firstAddress = c.Address Do c.Value = 5 Set c = .FindNext(c) Loop While Not c Is Nothing And c.Address <> firstAddress End If End With
or another way
no loops
will take about 2-3 minutesOption Explicit Sub ptest() Dim lRows As Long Application.ScreenUpdating = False With Sheet1.UsedRange lRows = .Rows.Count .Columns(2).Insert .Columns(2).FormulaR1C1 = "= SUMIF(R2C[-1]:R" & lRows & "C[-1],RC[-1],R2C[1]:R" & lRows & "C[1])" .Columns(2).Value = .Columns(2).Value .Resize(, 2).AdvancedFilter Action:=xlFilterCopy, CriteriaRange:=.Resize(, 2), copytorange:=Range("E1"), unique:=True .Columns(2).Delete End With End Sub
regards pike
If the solution helped please donate here to the RSPCA
Sites worth visiting;
J&R Solutions - royUK
AJP Excel Information - Andy Pope
Spreadsheet Toolbox
The Code Cage - Symond Lloyd
VBA for smarties - snb
venkat1926 - Copying a formula to 50,000 cells is not an effecient way to do this.
Leith Ross - Got an avtivex error on the DSO line. Besides this is not a FIND method
tigertiger - I already saw these codes online but none actually does the job correctly. The Find lines either miss the first match, or give unexpected results. Try them on a sample of 10 or so rows and see what I mean.
Any other ideas?
Pike - A great piece of code. Worked brilliantly in one workbook but gave an error on " With Sheet1.UsedRange" line on the another workbook. I'm still trying to figure out what's causing the error.
try changing
with Activesheet.used range
Last edited by pike; 07-05-2009 at 12:15 AM. Reason: tags
regards pike
If the solution helped please donate here to the RSPCA
Sites worth visiting;
J&R Solutions - royUK
AJP Excel Information - Andy Pope
Spreadsheet Toolbox
The Code Cage - Symond Lloyd
VBA for smarties - snb
Hello matrex,
What system are you using? I have never heard of "avtivex" error.
Did you mean "Acitve X" ?Got an avtivex error on the DSO line
"FIND" is not required to do this task. The method I presented works much faster than the Range.Find method. If you have some fondness for this method, a macro can be supplied. Just don't expect it to be fast.
Sincerely,
Leith Ross
Remember To Do the Following....
1. Use code tags. Place [CODE] before the first line of code and [/CODE] after the last line of code.2. Thank those who have helped you by clicking the Starbelow the post.
3. Please mark your post [SOLVED] if it has been answered satisfactorily.
Old Scottish Proverb...
Luathaid gu deanamh maille! (Rushing causes delays!)
try this SUB
Public Sub findx() Const StartRow = 2 Dim c, firstAddress, iR As Long, eR As Long, Q, Sh0 As Worksheet Set Sh0 = Application.ActiveSheet eR = Sh0.Range("A" & Rows.Count).End(xlUp).Row Dim aCo() As Byte: ReDim aCo(eR) As Byte: For iR = 0 To eR: aCo(iR) = 0: Next For iR = StartRow To eR If Sh0.Cells(iR, "A").Value2 = "" Then aCo(iR) = 2 Else If aCo(iR) = 0 Then firstAddress = Sh0.Cells(iR, "A").Address Q = Sh0.Cells(iR, "A").Offset(, 1).Value2 With Sh0.Range("a" & iR & ":a" & eR) Set c = .Find(Sh0.Cells(iR, "A").Value2, LookIn:=xlValues, LookAt:=xlWhole) Do While Not c Is Nothing And c.Address <> firstAddress aCo(c.Row) = 1 If Q = c.Offset(, 1).Value2 Then aCo(c.Row) = 2 Set c = .FindNext(c) Loop End With End If End If Next iR For iR = eR To StartRow Step -1 If aCo(iR) = 2 Then Sh0.Rows(iR).Delete Next iR End Sub
Leith Ross - Yes I meant mean "Acitve X". Sorry about the typo.
tigertiger - tried it on this sample list but nothing seems to happen!
AAA 2
BBB 2
AAA 1
AAA 4
FFF 3
GGG 2
GGG 1
RRR 4
AAA 3
BBB 1
Thanks so much everyone for all your help.
matrex
There are currently 1 users browsing this thread. (0 members and 1 guests)
Bookmarks