VBA Macro Loop only copies one cell of data instead of many - vba

all
I'm a VBA novice here, and I'm being tasked with developing some macros in my new job. Currently, I am working on a macro that goes though a text file, applies some formatting, isolates required numerical data, copies it, and then outputs the copied information into a new Worksheet.
Here's the code for the formatting, just to make sure I post it:
`Perform Text-To-Columns on Column A. Delimited by the character "#"
Columns("A:A").Select
Selection.TextToColumns Destination:=Range("A1"), DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=False, _
Semicolon:=False, Comma:=False, Space:=False, Other:=True, OtherChar _
:="#", FieldInfo:=Array(1, 1), TrailingMinusNumbers:=True
`Perform Text-To-Columns on Column B. Delimited by the character ")"
Columns("B:B").Select
Selection.TextToColumns Destination:=Range("B1"), DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=False, _
Semicolon:=False, Comma:=False, Space:=False, Other:=True, OtherChar _
:=")", FieldInfo:=Array(1, 1), TrailingMinusNumbers:=True
`Format Column B for Numbers to have zero decimal places
Selection.NumberFormat = "0"
`Filter Column B for all numbers greater than 500
Selection.AutoFilter
ActiveSheet.Range("$B$1:$B$1720").AutoFilter Field:=1, Criteria1:=">500", _
Operator:=xlAnd
`Sort Filtered numbers from lowest to highest
ActiveWorkbook.Worksheets(1).Sort.SortFields.Clear
ActiveWorkbook.Worksheets(1).Sort.SortFields.Add Key:=Range( _
"B1"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= _
xlSortNormal
With ActiveWorkbook.Worksheets(1).Sort
.SetRange Range("B1").EntireColumn
.Header = xlNo
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
At this point, I now have column B with an amount of 12 digit numbers that varies from file to file. This next part of the macro is a loop that should now look at this Column B, and begin to inspect the cells of Column B to see if they contain 12 digit numbers, and if they do, begin to copy them as a range. Once all the 12 digit numbers in B are found, it should copy them all, open a new tab, and paste the results:
' Declare loop variables
Dim myLastRow As Long
Dim myRow As Long
Dim i As Long
Dim myValue As String
Dim myStartRow As Long
Dim myEndRow As Long
' Find last row with data in column B
myLastRow = Cells(Rows.Count, "B").End(xlUp).Row
' Loop through all data in column B until you find a 12 order number Number
For myRow = 1 To myLastRow
' If 12 digit entry is found, capture the row number,
' then go down until you find the first entry not 12 digits long
If (Len(Cells(myRow, "B")) = 12) And (IsNumeric(Cells(myRow, "B"))) Then
myStartRow = myRow
i = 1
Do
If Len(Cells(myRow + i, "B")) <> 12 Then
' If found, capture row number of the last 13 digit cell
myEndRow = myRow + i - 1
' Copy the selected data
Range(Cells(myStartRow, "B"), Cells(myEndRow, "B")).Copy
' Add "Results" as a new sheet for the copied Card Numbers to be pasted into
Sheets.Add.Name = "Results"
Sheets("Results").Activate
' Paste clipboard to "Results" and format the results for viewing
Range("A1").Select
ActiveSheet.Paste
Columns("A:A").EntireColumn.AutoFit
Application.CutCopyMode = False
Exit Do
Else
' Otherwise, move row counter down one and continue
i = i + 1
End If
Loop
Exit For
End If
Next myRow
For whatever reason, when I go through the macro, all it does is capture the first value in B1 and then put that into the Results sheet. I cannot for the life of me figure out why. Could it be due to the filtering I've applied? If anyone could give me some insight, I'd be all ears. Thanks very much for any help you can offer.

This is a fairly simple code that seems to work. Hopefully it meets your needs:
Sub test1()
Dim ws As Worksheet
Dim res As Worksheet
Dim val As String
Set ws = ActiveSheet
Sheets.Add
Set res = ActiveSheet
res.Name = "Results"
ws.Select
Range("B1").Select
While ActiveCell.Value <> ""
If Len(ActiveCell.Value) = 12 Then
val = ActiveCell.Value
res.Select
ActiveCell.Value = val
ActiveCell.Offset(1, 0).Select
ws.Select
ActiveCell.Offset(1, 0).Select
Else
ActiveCell.Offset(1, 0).Select
End If
Wend
res.Select
Columns("A:A").EntireColumn.AutoFit
Range("A1").Select
End Sub

I am not sure to understand, but you can try this:
Option Explicit
Sub CopyNumber()
Dim ws1 As Worksheet: Set ws1 = ThisWorkbook.Sheets("Sheet1") 'Change the name of the sheet
Dim Result As Worksheet
Dim ws1Lastrow As Long, LastrowResult As Long
Dim i As Long, Rng As Range
Dim TestLenght, Arr
Sheets.Add.Name = "Results" ' Add your new sheet
Set Result = ThisWorkbook.Sheets("Results")
With ws1
ws1Lastrow = .Range("B" & Rows.Count).End(xlUp).Row 'Find the lastrow in the Source Data Sheet
Set Rng = .Range("B1:B" & ws1Lastrow) 'Set your range to put into your Array
Arr = Rng.Value
For i = LBound(Arr) To UBound(Arr)
TestLenght = Arr(i, 1)
If Len(Trim(TestLenght)) = 12 And IsNumeric(TestLenght) Then ' Test your data
LastrowResult = Result.Range("A" & Rows.Count).End(xlUp).Row + 1
Result.Cells(LastrowResult, "A") = TestLenght ' Past your data from your array to the Result Sheet
End If
Next ' next data of the Array
End With
End Sub

I think the problem may be that formatting the numbers to display 0 decimal places is not the same as truncating them. The Len() function will operate on the actual contents (or true value) of the cell, not the displayed value. So if you do have decimals on those numbers, Len() will return a value greater than 12, as it'll count the decimal place and the decimals.
If that is the issue, you'll need to round to 0 decimal places (or truncate to integer) in order to force the actual cell contents to a length of 12.

Related

Each row in a column and copy/paste result in first free cell in another column

I need to take a list of strings in a sheet and transform them into a list in a new sheet, the strings in Sheet 1 look like:
B87YTDF,ENG,22;B54TRDX,ITA,23
B99REDT,FRA,25;B46TEST,GER,29;B94FRDE,GBT,21
and what I need to obtain in Sheet 2 is:
B87YTDF ENG 22
B54TRDX ITA 23
B99REDT FRA 25
B46TEST GER 29
B94FRDE GBT 21
so what I need to do is, for each string (all in the same column):
copy string from Sheet 1 and paste in the first row of Sheet 2
in Sheet 2 perform a txt to column separating by ;
copy the full row, paste it one row below it and transpose
txt to column separating by ,
clear the first row that still contains the full string
and repeat this for all non-empty rows in Sheet 1, copying and pasting the string each time in the first free row of Sheet 2.
At this point I am stuck with this, but have no idea of how to loop this for each row in Sheet 1 and have it done in each first free row in Sheet 2.
Rows("1:1").Select
Selection.Copy
Sheets("Sheet5").Select
ActiveSheet.Paste
Application.CutCopyMode = False
Range("A1").Select
Selection.TextToColumns Destination:=Range("A1"), DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=True, _
Semicolon:=False, Comma:=False, Space:=False, Other:=True, OtherChar _
:=";", FieldInfo:=Array(Array(1, 1), Array(2, 1), Array(3, 1), Array(4, 1), Array(5, _
1), Array(6, 1), Array(7, 1), Array(8, 1), Array(9, 1), Array(10, 1), Array(11, 1), Array(12 _
, 1)), TrailingMinusNumbers:=True
Rows("1:1").Select
Selection.Copy
Range("A2").Select
Selection.PasteSpecial Paste:=xlPasteAll, Operation:=xlNone, SkipBlanks:= _
False, Transpose:=True
Rows("1:1").Select
Application.CutCopyMode = False
Selection.Delete Shift:=xlUp
Thanks for any help!
a no-loop code:
Option Explicit
Sub main()
Dim vals As Variant
With Worksheets("Sheet1")
vals = Split(Join(Application.Transpose(.Range("A1", .Cells(.Rows.Count, 1).End(xlUp)).Value), ";"), ";")
End With
With Worksheets("Sheet2").Range("A1").Resize(UBound(vals))
.Value = Application.Transpose(vals)
.TextToColumns comma:=True
End With
End Sub
Below code assumes that you store those trings in column A of Sheet1 and it pastes parsed values in Sheet2 starting with A1 cell.
Try this code:
Sub CopyStrings()
Dim i As Long, ws1 As Worksheet, ws2 As Worksheet, currRow As Long, lastRow As Long, rowsToPaste() As String, rowToPaste() As String, j As Long, k As Long
currRow = 1
Set ws1 = Worksheets("Sheet1")
Set ws2 = Worksheets("Sheet2")
'here you determine how many rows there are in Sheet1 to copy and parse
lastRow = ws1.Cells(ws1.rows.Count, 1).End(xlUp).Row
For i = 1 To lastRow
'split current string into rows
rowsToPaste = Split(Cells(i, 1).Value, ";")
For j = LBound(rowsToPaste) To UBound(rowsToPaste)
'split current row and iterate through values and paste then in Sheet2
rowToPaste = Split(rowsToPaste(j), ",")
For k = LBound(rowToPaste) To UBound(rowToPaste)
ws2.Cells(currRow, k + 1).Value = rowToPaste(k)
Next
currRow = currRow + 1
Next
Next
End Sub
Sub test()
Dim S
Dim vS, v, vR(),mys,Myv
Dim n as Long, i as Long
S = Sheet1.range ("a1").currentregion
'vS = Split(S,Char(10))
For each v in S
Myv = Split (v,";")
For each mys in Myv
n= n+1
Redim preserve vR (1 to 3,1 to n)
For i= 0 to 2
vR (i+1,n) = Split (mys,",")(i)
Next i
Next mys
Next v
Sheet2.range ("a1").resize (n,3)= application.Transpose (vR)
End sub

sort data left to right in excel vba

I want to sort complete sheet data by column header alphabetically.
Below code works fine but i have to manually enter data range in variables(keyrange and datarange) every time, Since number of columns/rows varies in every file. I tried different ways in below code. Can you advise Is there a way that the last column automatically selected ??like in below W is last column with data in file and code should pick up last column.
Similarly last row of columns should pick up into range (like 485 is last row of file in below code), IS it possible ?
Sub sortfile2()
Dim keyrange As String
Dim DataRange As String
keyrange = "A1:W1"
DataRange = "A1:W485"
Range("A1").Select
Range(Selection, Selection.End(xlToRight)).Select
Range(Selection, Selection.End(xlDown)).Select
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Add Key:=Range(keyrange), _
SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Sheet1").Sort
.SetRange Range(DataRange)
.Header = xlYes
.MatchCase = False
.Orientation = xlLeftToRight
.SortMethod = xlPinYin
.Apply
End With
End Sub
If the source rane is dynamic, you can go with
bottom= Range("A1").End(xlDown).Row
Set DataRange = Range("A1").CurrentRegion.Resize(bottom - 1).Offset(1)
Note that CurrentRegion itself is not enough. you should combine it with Resize and Offset. İf you try with only CurrentRegion and go with F8, you can see why.
Yes, determining last column and last row is possible.
If you want to determine last column in first (1) row, use the code:
Cells(1, Columns.Count).End(xlToLeft).Column
If you want to get last row in first column, use following:
Cells(Rows.Count, 1).End(xlUp).Row
This is for the first column / row, so you can change it as you want.
This is range of data.
Sub test()
Dim rngDB As Range
Dim Ws As Worksheet
Dim r As Long, c As Long
Set Ws = ActiveSheet
With Ws
r = .Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
c = .Cells.Find("*", SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column
Set rngDB = .Range("a1", .Cells(r, c))
rngDB.Select
End With
End Sub
Or
range("a1").CurrentRegion
yes, Michal answer and other source helped to find exact required output
'Find the last non-blank cell in row 1
lCol = Cells(1, Columns.Count).End(xlToLeft).Column
d = Replace(Cells(1, lCol).Address(True, False), "$1", "")
'Find the last non-blank cell in column 1
lRow = Cells(rows.Count, 1).End(xlUp).row
keyrange = "A1:" & d & 1
DataRange = "A1:" & d & lRow
'below line is to print (for debugging) the calculated range
MsgBox (keyrange)
MsgBox (DataRange)

Excel 2013: Sorting columns based on first row value using VBA

I would like to implement an Excel macro that sorts all columns from column "C" to the last column containing data (columns A and B shall not be affected).
The columns shall be sorted from A->Z based on the cell value of their first row (which is a string).
So far, I came up with the following code which I do not like that much because it contains hardcoded numbers for the Sort range making the code not really robust.
Sub SortAllColumns()
Application.ScreenUpdating = False
'Sort columns
With ActiveWorkbook.Worksheets("mySheet").Sort
.SetRange Range("C1:ZZ1000")
.Header = xlYes
.MatchCase = False
.Orientation = xlLeftToRight
.Apply
End With
Application.ScreenUpdating = True
End Sub
Searching the internet, one may find tons of suggestions getting the last used column or row. However most of them will blow up the code more than I expected.
I am not a VBA expert and it would be great if someone could make a suggestion how this problem can be solved in an elegant and efficient way.
If this is important: We will definitely not have more that 1000 rows and 1000 columns.
Any suggestion is highly appreciated.
edited:
changed temporary sheet adding statement to have it always as the last one
revised its deletion statement accordingly
should your need be to sort columns by moving them so as to have their headers sorted from left to right, then try this code
Option Explicit
Sub main()
Dim lastCol As Long
With Sheets("mySheet")
lastCol = .cells(1, .Columns.Count).End(xlToLeft).Column
Call OrderColumns(Range(.Columns(3), Columns(lastCol)))
End With
End Sub
Sub OrderColumns(columnsRng As Range)
Dim LastRow As Long
With columnsRng
LastRow = GetColumnsLastRow(columnsRng)
With .Resize(LastRow)
.Copy
With Worksheets.Add(after:=Worksheets(Worksheets.Count)).cells(1, 1).Resize(.Columns.Count, .Rows.Count) 'this will add a "helper" sheet: it'll be removed
.PasteSpecial Paste:=xlPasteAll, Transpose:=True
.Sort key1:=.Columns(1), Order1:=xlAscending, Orientation:=xlTopToBottom, Header:=xlNo
.Copy
End With
.PasteSpecial Paste:=xlPasteAll, Transpose:=True
Application.DisplayAlerts = False: Worksheets(Worksheets.Count).Delete: Application.DisplayAlerts = True 'remove the "helper" sheet (it's the (n-1)th sheet)
End With
End With
End Sub
Function GetColumnsLastRow(rng As Range) As Long
Dim i As Long
'gets last row of the given columns range
GetColumnsLastRow = -1
With rng
For i = 1 To .Columns.Count
GetColumnsLastRow = WorksheetFunction.Max(GetColumnsLastRow, .Parent.cells(.Parent.Rows.Count, .Columns(i).Column).End(xlUp).row)
Next i
End With
End Function
it makes use of a "helper" temporary (it gets deleted by the end) sheet.
Thanks to the suggestions and revisions of #SiddharthRout I got this:
Sub SortAllColumns()
Application.ScreenUpdating = False
Dim ws As Worksheet
Dim LastRow As Long
Dim LastColumn As Long
Dim LastColumnLetter As String
Set ws = ThisWorkbook.Sheets("mySheet")
'Get range
With ws
LastRow = .Range("A" & .Rows.Count).End(xlUp).Row
LastColumn = .Cells(1, .Columns.Count).End(xlToLeft).Column
LastColumnLetter = Split(.Cells(, LastColumn).Address, "$")(1)
'Sort columns
Range("C1:" & LastColumnLetter & LastRow).Select
.Sort.SortFields.Clear
.Sort.SortFields.Add Key:=Range("C1:" & LastColumnLetter & 1), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With .Sort
.SetRange ws.Range("C1:" & LastColumnLetter & LastRow)
.Header = xlYes
.MatchCase = False
.Orientation = xlLeftToRight
.Apply
End With
End With
Application.ScreenUpdating = True
End Sub

VBA for searching string in a column and copy entire rows depending on the presence of certain string at adjacent cell

I am completely new for VBA.
I have excel data sheet containing numbers and strings. I want to search for certain string say 'CYP' in column I then look for a cell of its row at column C and copy entire rows containing the string of cell C. I want to paste in sheet 2 of the same workbook and loop it again to look for remaining CYPs in column.
Would you help me on this please?
After the suggestion from pnuts, here is my macro code
Sub Macro1()
'
' Macro1 Macro
'
'
Columns("I:I").Select
Range("I729").Activate
Selection.Find(What:="cyp", After:=ActiveCell, LookIn:=xlValues, LookAt _
:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
False, SearchFormat:=False).Activate
ActiveWindow.SmallScroll Down:=5
Range("C749").Select
Selection.Copy
Columns("C:C").Select
Range("C734").Activate
Selection.Find(What:="EPT001TT0601C000151", After:=ActiveCell, LookIn:= _
xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext _
, MatchCase:=False, SearchFormat:=False).Activate
Rows("746:750").Select
Application.CutCopyMode = False
Selection.Copy
Sheets("Sheet2").Select
ActiveSheet.Paste
End Sub
In this code the CYP was found in I749, cell C749 was copied as string and first row in column C containing the same string was searched followed by copying of the entire row and 4 more followed by it then pasting in sheet2 of the same workbook.
What I wanted was to loop this action again and again upto the end of column I and repeat the same action.
Thank you!
I managed to solve the problem with the help of Trebor76 at Excelforum. Here I am giving solution in that way it might be helpful for some newbies like myself with similar problem.
Option Explicit
Sub Macro1()
'Written and assisted by Trebor76
'Copy an entire row from Sheet1 to Sheet2 for each unique matching item in Col. C if the text in Col. I contains the text 'CYP' (case sensitive)
'http://www.excelforum.com/excel-programming-vba-macros/962511-vba-for-searching-string-in-a-column-and-copy-rows-depending-on-string-in-adjacent-cell.html
Dim rngCell As Range
Dim objMyUniqueArray As Object
Dim lngMyArrayCounter As Long
Dim lngMyRow As Long
Dim varMyItem As Variant
Application.ScreenUpdating = False
Set objMyUniqueArray = CreateObject("Scripting.Dictionary")
For Each rngCell In Sheets("Sheet1").Range("I1:I" & Sheets("Sheet1").Range("I" & Rows.Count).End(xlUp).Row)
If InStr(rngCell, "CYP") > 0 Then
If Not objMyUniqueArray.Exists(Trim(Cells(rngCell.Row, "C"))) Then
lngMyArrayCounter = lngMyArrayCounter + 1
objMyUniqueArray.Add (Trim(Cells(rngCell.Row, "C"))), lngMyArrayCounter
varMyItem = Sheets("Sheet1").Cells(rngCell.Row, "C")
For lngMyRow = 1 To Sheets("Sheet1").Cells(Rows.Count, "C").End(xlUp).Row
If Sheets("Sheet1").Cells(lngMyRow, "C") = varMyItem Then
Rows(lngMyRow).Copy Destination:=Sheets("Sheet2").Range("A" & Sheets("Sheet2").Range("A" & Rows.Count).End(xlUp).Row + 1)
End If
Next lngMyRow
End If
End If
Next rngCell
Set objMyUniqueArray = Nothing
Application.ScreenUpdating = True
MsgBox "All applicable rows have been copied.", vbInformation
End Sub
Cheers!

Finding Numerical Value Pairs With Conditionals and Nested If-Then Statements - VBA Excel 2007

I am attempting to sort data imported via an excel macro from a Mainframe system, in order to search for potential patterns, especially for duplicates and the like. Suffice to say, the macro works fine and just serves as background to the question.
I checked for question duplicates and have not found an exact match to the language+ subject focus/specifics as yet. This stackoverflow question appeared to bear a resemblance, but I do not feel it is the same: Need to find a way to loop this macro through every other column
I have examined the AND conditional, but to be honest I feel stumped as to how to use it to help me loop through, run the comparisons and find all possible permutations of Decimal type value-based pairs.
I am sorting data based on three conditionals, with two serving as preconditions to the third, such that:
[pseudocode/thought process]
----------
IF String Comparison 1 (Cell Col 1 R 1) == (Cell Col 1 R 2) AND
IF String Comparison 2 (Cell Col 2 R 1) == (Cell Col 2 R 2) AND
IF Value of DECIMAL (Cell Col 3 R1) == DECIMAL (Cell Col 3 R2)
CHANGE CELLCOLOR to 'SomeColor'
----------
LOOP Through and run all value pair checks given String Compare 1,2 == TRUE for all
comparisons of String Comparison 1 & String Comparison 2
I feel certain that there is a simple OOP-focused solution that just recursively loops through the cells, but I do not see it.
What follows is my example foobar data (post worksheet migration):
Category1ID Category2ID Values
CCC400 219S2 400
CCC400 219S2 400
BBB300 87F34 300
BBB300 87F34 300
ABA250 987M9 500
600DDD 0432QV 700
500ABA 01W29 600
200AAA 867B2 200
100AAA 5756A 100
100AAA 5756A 100
100AAA 5756A 100
100AAA 5756A 100
100AAA 5756A 100
Here is my current solution set --
First, I sort the data into the three columns I will use for the loop. The data is sorted by column 1 A-Z, column 2 A-Z and then column 3 smallest values to largest:
Code Block 1
Sub DataCopy()
'
' DataCopy Macro
' Move some data and sort.
'
'
Range("B:B,D:D,F:F").Select
Range("F1").Activate
Selection.Copy
Sheets("Worksheet2").Select
Range("A1").Select
ActiveSheet.Paste
Application.CutCopyMode = False
ActiveWorkbook.Worksheets("Worksheet2").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Worksheet2").Sort.SortFields.Add Key:=Range( _
"A2:A14"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= _
xlSortNormal
ActiveWorkbook.Worksheets("Worksheet2").Sort.SortFields.Add Key:=Range( _
"B2:B14"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= _
xlSortNormal
ActiveWorkbook.Worksheets("Worksheet2").Sort.SortFields.Add Key:=Range( _
"C2:C14"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= _
xlSortNormal
With ActiveWorkbook.Worksheets("Worksheet2").Sort
.SetRange Range("A1:C14")
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End Sub
I then attempt to loop through and "tag" the matching values based on the conditionals:
Code Block 2
Private Sub CommandButton1_Click()
'Trying to set variable in type RANGE and set variable alias rng.
Dim c As Range, rng
'Trying to set variable in type RANGE and set variable alias rng2.
Dim c2 As Range, rng2
'Trying to set variable in type RANGE and set variable alias rng3.
Dim c3 As Range, rng3
Dim LASTROW As Long
LASTROW = Cells(Rows.Count, 1).End(xlUp).Row
Set rng = Range("A2:A" & LASTROW)
Set rng2 = Range("B2:B" & LASTROW)
Set rng3 = Range("C2:C" & LASTROW)
For Each c In rng
'If category1ID cell Ax = Ax+1, Then go to next if
If StrComp(c, c.Offset(1, 0)) = 0 Then
'If category2ID cell Bx = Bx+1, Then go to next if
If StrComp(c2, c2.Offset(1, 0)) = 0 Then
'If the value contained of cell Cx = C, Then highlight the value cell
If Round(c3, 2) = Round(c3.Offset(1, 0), 2) Then
c3.Interior.ColorIndex = 4
End If
End If
End If
Next c
End Sub
Unfortunately, Code Block 2 results in the error "Run-time error '91': Object variable or With block variable not set."
The errors on line 29:
If StrComp(c2, c2.Offset(1, 0)) = 0 Then
I have attempted to resolve this error a number of ways, but I have only served to increase the number of errors I trip.
In theory, if the color tagging process functioned, I would attempt to execute this block of code, perhaps in the same execution button. This code is very similar to Code Block 1, except that it simply sorts by colored cells in the value column (column 3) and then by the criteria of column 1 A-Z, column 2 A-Z and column 3 smallest to largest values:
Code Block 3
Sub ColorSort()
'
' ColorSort Macro
' Sorts by Color and then by various data criteria.
'
'
Columns("A:C").Select
ActiveWorkbook.Worksheets("Worksheet3").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Worksheet3").Sort.SortFields.Add(Range("C2:C14"), _
xlSortOnCellColor, xlAscending, , xlSortNormal).SortOnValue.Color = RGB(0, 255 _
, 0)
ActiveWorkbook.Worksheets("Worksheet3").Sort.SortFields.Add Key:=Range( _
"A2:A14"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= _
xlSortNormal
ActiveWorkbook.Worksheets("Worksheet3").Sort.SortFields.Add Key:=Range( _
"B2:B14"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= _
xlSortNormal
ActiveWorkbook.Worksheets("Worksheet3").Sort.SortFields.Add Key:=Range( _
"C2:C14"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= _
xlSortNormal
With ActiveWorkbook.Worksheets("Worksheet3").Sort
.SetRange Range("A1:C14")
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End Sub
Code Block 3 is never executed, however, due to the Run-Time 91 error.
I am hopeful for an elegant recursive/iterative method or set of methods to fix the error and optimize performance, but any fix will do, if possible/feasible.
Much Thanks,
JackOrangeLantern
This should work if I understand your logic correctly:
Private Sub CommandButton1_Click()
Dim c As Range, rng As Range
Dim c2 As Range
Dim c3 As Range
Dim LASTROW As Long
With ActiveSheet
LASTROW = .Cells(Rows.Count, 1).End(xlUp).Row
Set rng = .Range("A2:A" & LASTROW)
End With
For Each c In rng.Cells
Set c2 = c.Offset(0, 1)
Set c3 = c.Offset(0, 2)
If StrComp(c.Value, c.Offset(1, 0).Value) = 0 Then
If StrComp(c2.Value, c2.Offset(1, 0).Value) = 0 Then
If Round(c3.Value, 2) = Round(c3.Offset(1, 0).Value, 2) Then
'EDIT: highlight the original and the duplicate
c3.Resize(2,1).Interior.ColorIndex = 4
End If
End If
End If
Next c
End Sub
EDIT: this should be better (also works on unsorted data)
Private Sub HighlightDups()
Const CLR_HILITE As Integer = 4
Dim rw As Range, rng As Range
Dim LASTROW As Long, r As Long
Dim dict As Object, tmp
With ActiveSheet
LASTROW = .Cells(Rows.Count, 1).End(xlUp).Row
Set rng = .Range("A2:C" & LASTROW)
End With
Set dict = CreateObject("scripting.dictionary")
For Each rw In rng.Rows
tmp = rw.Cells(1).Value & "~~" & rw.Cells(2).Value & _
"~~" & CStr(Round(rw.Cells(3).Value, 1))
If Not dict.exists(tmp) Then
dict.Add tmp, rw.Cells(3)
Else
If Not dict(tmp) Is Nothing Then
dict(tmp).Interior.ColorIndex = CLR_HILITE
Set dict(tmp) = Nothing
End If
rw.Cells(3).Interior.ColorIndex = CLR_HILITE
End If
Next rw
End Sub