I have some data that will always be 8 columns (A-H) the number of rows could be different every time (Dynamic).
If the string in column A ends with:
"IT", "LN" or "SJ" then the row value in Column G needs to be divided by 100.
If the string ends in "KK" the value in Column G needs to be
divided by 1000.
Otherwise no math operation to the row needs to be performed.
The data also needs to be sorted alphabetically by column C then by column H.
After this is done the header row (1). Can be deleted.
What I have so far "works" but it results in a very long list of 0.0000 values in column G that makes copying out the cleaned data difficult.
Would anyone be able to show me a more efficient solution?
Sub Clean()
Dim wkb As Workbook
Set wkb = ActiveWorkbook
Dim ws As Worksheet
Set ws = ActiveSheet
Range("A1").Select
Range(Selection, Selection.End(xlToRight)).Select
Range(Selection, Selection.End(xlDown)).Select
ws.Sort.SortFields.Clear
ws.Sort.SortFields.Add2 Key:=Range("H2:H2500" _
), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With ws.Sort
.SetRange Range("A1:H2500")
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Range("I2").Select
ActiveCell.FormulaR1C1 = _
"=IF(OR(RIGHT(RC[-8],2) = ""SJ"", RIGHT(RC[-8],2) = ""LN"", RIGHT(RC[-8],2) = ""IT"", RIGHT(RC[-8],2) = ""KK""),IF(RIGHT(RC[-8],2) = ""KK"",RC[-2]/1000,RC[-2]/100),RC[-2])"
Range("I2").Select
Selection.Copy
Selection.End(xlToLeft).Select
Selection.End(xlDown).Select
Range("I2500").Select
Range(Selection, Selection.End(xlUp)).Select
Range("I3:I2500").Select
Range("I2500").Activate
ActiveSheet.Paste
Selection.End(xlUp).Select
Range(Selection, Selection.End(xlDown)).Select
Application.CutCopyMode = False
Selection.Copy
Range("G2").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Selection.NumberFormat = "0.0000"
Columns("I").Delete
Dim strDataRange As Range
Dim keyRange As Range
Set strDataRange = Range("A:H")
Set keyRange = Range("C1")
strDataRange.Sort Key1:=keyRange, Header:=xlYes
Rows(1).Delete
End sub
Sample Input Data
Codes
Population
Animal
Type
Size
Housing Qty
Average Cost
Country
SHIB IT
4,504
DOGE
Standard
SMALL
15,019
9.5557
JP
CORG LN
33,052
DOGE
Standard
SMALL
8,816
31,404.9100
FR
SOG SJ
1,417
CAT
Standard
BIG
90
247.2508
ZM
CHOW KK
873
DOGE
Standard
BIG
9,192
177.2797
CN
FLOP AG
991
CAT
Standard
BIG
7
597.0650
BZ
Desired Output Data:
Please, try the next compact and fast code. It will place the range to be processed in an array and drop down the processed result at the end. Now it returns overwriting the existing range. It can be easily adapted to return in another sheet:
Sub processRangeAH()
Dim sh As Worksheet, lastR As Long, rng As Range, arr, i As Long
Set sh = ActiveSheet
lastR = sh.Range("A" & sh.rows.count).End(xlUp).row
Set rng = sh.Range("A1:H" & lastR)
rng.Sort Key1:=sh.Range("H1"), Order1:=xlAscending, Header:=xlYes
arr = rng.Value2
For i = 2 To UBound(arr)
Select Case UCase(Right(arr(i, 1), 2))
Case "IT", "LN", "SJ": arr(i, 7) = arr(i, 7) / 100
Case "KK": arr(i, 7) = arr(i, 7) / 1000
End Select
Next i
rng.Value2 = arr
rng.Sort Key1:=sh.Range("C1"), Order1:=xlAscending, Header:=xlYes
sh.Range("G2:G" & lastR).NumberFormat = "0.0000"
sh.rows(1).Delete
End Sub
I posted this answer some hours before, when I left my office, but by mistake, in another thread...
Just to see how an array can be used, in order to increase the speed for larger range.
Try this. It copies everything to a new sheet so you don't lose the original data. Could be sped up if you have lots of data.
Sub x()
Dim ws As Worksheet, r As Long
Set ws = Worksheets.Add
Sheet1.Range("A1").CurrentRegion.Copy ws.Range("A1") 'assumes data on sheet1 (code name, change to suit)
For r = 2 To ws.Range("A" & Rows.Count).End(xlUp).Row
Select Case Right(ws.Cells(r, 1), 2)
Case "IT", "LN", "SJ": ws.Cells(r, "G").Value = ws.Cells(r, "G").Value / 100
Case "KK": ws.Cells(r, "G").Value = ws.Cells(r, "G").Value / 1000
End Select
Next r
With ws.Sort
.SortFields.Clear
.SortFields.Add2 Key:=ws.Range("C2:C" & ws.Range("A" & Rows.Count).End(xlUp).Row), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
.SortFields.Add2 Key:=Range("H2:H" & ws.Range("A" & Rows.Count).End(xlUp).Row), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
.SetRange Range("A1:H" & ws.Range("A" & Rows.Count).End(xlUp).Row)
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End Sub
Related
New workbook opens fine with transposed data copied from original, but executable sorting code does not sort.
Tried various code strings from others based on extensive searches - no examples found that are similar to this effort
Private Sub CommandButton1_Click()
'clear any thing on clipboard to maximize available memory
Application.CutCopyMode = False
Application.ScreenUpdating = False
'unfreeze all panes
ActiveWindow.FreezePanes = False
'copy the data, create new workbook, and paste transposed data into worksheet
Dim newWB As Workbook, currentWB As Workbook
Dim newS As Worksheet, currentS As Worksheet
Dim LastRow As Long, LastColumn As Long
Dim SortRange As Range
'Copy the data you need
Set currentWB = ThisWorkbook
Set currentS = currentWB.Sheets("Sheet1")
LastRow = currentS.Cells(currentS.Rows.Count, "A").End(xlUp).Row
LastColumn = currentS.Cells(2, currentS.Columns.Count).End(xlToLeft).Column
Range(Cells(2, 1), Cells(LastRow, LastColumn)).Copy
'Create a new file that will receive the data and paste it
Set newWB = Workbooks.Add
With newWB
Set newS = newWB.Sheets("Sheet1")
newS.Activate
newS.Range("A1").PasteSpecial Paste:=xlPasteAll, Operation:=xlNone, SkipBlanks:=False, Transpose:=True
'reselect the range to sort and sort
LastRow = newS.Cells(newS.Rows.Count, "A").End(xlUp).Row
LastColumn = newS.Cells(1, newS.Columns.Count).End(xlToLeft).Column
ActiveSheet.Range(Cells(2, 1), Cells(LastRow, LastColumn)).Select
'newS.Range("A1").Select
'Apply sort
With ActiveSheet.Sort
.SortFields.Clear
.SortFields.Add Key:=Range("A1"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
.SetRange Range(Cells(2, 1), Cells(LastRow, LastColumn))
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End With
'CODE RUNS TO HERE BUT DOES NOT SORT
'move back to cell C2 and freeze row and column headings
Cells(2, 3).Select
ActiveWindow.FreezePanes = True
'select all columns and adjust width and height
ActiveCell.Columns("A:DV").EntireColumn.Select
Selection.ColumnWidth = 13
Selection.Rows.AutoFit
Application.ScreenUpdating = True
End Sub
runs fine through the sort then get a
Error 1004 "Application-defined or Object-defined error"
on the freezepane code. However, the new transposed data window DOES NOT SORT.
I have made some changes to your code and this should work:
Private Sub CommandButton1_Click()
'clear any thing on clipboard to maximize available memory
Application.CutCopyMode = False
Application.ScreenUpdating = False
'unfreeze all panes
ActiveWindow.FreezePanes = False
'copy the data, create new workbook, and paste transposed data into worksheet
Dim newWB As Workbook, currentWB As Workbook
Dim newS As Worksheet, currentS As Worksheet
Dim LastRow As Long, LastColumn As Long
Dim SortRange As Range
Set currentWB = ThisWorkbook
Set currentS = currentWB.Sheets("Sheet1")
'Create a new file that will receive the data
Set newWB = Workbooks.Add
Set newS = newWB.Sheets("Sheet1")
'Copy the data you need
With currentS
LastRow = .Cells(.Rows.Count, 1).End(xlUp).Row
LastColumn = .Cells(2, .Columns.Count).End(xlToLeft).Column
.Range(.Cells(2, 1), .Cells(LastRow, LastColumn)).Copy
End With
'Paste it asap
With newS
.Range("A1").PasteSpecial Paste:=xlPasteAll, SkipBlanks:=False, Transpose:=True
Application.CutCopyMode = False
'We know we copied LastRow-1 rows, and LastColumn columns
'So our pasted data is just the other way round. So we just use that info.
'Apply sort
With .Sort
.SortFields.Clear
.SortFields.Add Key:=newS.Range("A1"), _
SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
.SetRange newS.Range(newS.Cells(1, 1), newS.Cells(LastColumn, LastRow-1))
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End With
'move back to cell C2 (of newS, I assume) and freeze row and column headings
' Let us do it without Select :)
newS.Activate
With ActiveWindow
If .FreezePanes Then .FreezePanes = False
.SplitColumn = 2
.SplitRow = 1
.FreezePanes = True
End With
'adjust width and height of all columns, the right way (with our range)
With newS.Range(newS.Cells(1, 1), newS.Cells(LastColumn, LastRow-1))
.ColumnWidth = 13
.Rows.AutoFit
End With
Application.ScreenUpdating = True
End Sub
With below code I could sort data (marked with blue background) from 2 columns based on "B" column. Similarly I want to repeat the same for each blue block. I've highlighted cells manually just for illustration. Any help will be appreciated.
Code:
Sub SortRanges()
Dim firstcell As String
With Columns("B")
.Find(what:="*", after:=.Cells(1, 1), LookIn:=xlValues).Activate
firstcell = ActiveCell.Row
End With
Range(Selection, Selection.End(xlDown)).Select
Range(Selection, Selection.End(xlToLeft)).Select
ActiveWorkbook.Worksheets("Sheet4").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Sheet4").Sort.SortFields.Add Key:=Range("B" & firstcell & ":B" & firstcell + 5), _
SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Sheet4").Sort
.SetRange Range("A" & firstcell & ":B" & firstcell + 5)
.Header = xlGuess
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End Sub
Try a loop down your column and, as it looks like everything is blocks of 5, do something like:
lr = cells(rows.count,1).end(xlup).row
For i = 1 to lr
if cells(i,1).interior.color = Blue Then `FIX THIS TO MATCH THE BLUE YOU WANT
Range(Cells(i,1),Cells(i+5,2)).Sort key1:=Range(Cells(i,2),Cells(i+5,2)), order1:=xlAscending, Header:=xlNo
i=i+5
End if
next i
I may have not understood the part about your highlighting... if that blue is the "highlight" then you can modify the above such that:
lr = cells(rows.count,1).end(xlup).row
For i = 1 to lr
if not isempty(cells(i,2)) Then
Range(Cells(i,1),Cells(i+5,2)).Sort key1:=Range(Cells(i,2),Cells(i+5,2)), order1:=xlAscending, Header:=xlNo
i=i+5
End if
next i
One more thing... if you can just run 2 sorts in sequence, second should be your final sort, like:
lr = cells(rows.count,1).end(xlup).row
For i = 1 to lr
if not isempty(cells(i,2)) Then
Range(Cells(i,1),Cells(i+5,2)).Sort key1:=Range(Cells(i,1),Cells(i+5,1)), order1:=xlAscending, Header:=xlNo
Range(Cells(i,1),Cells(i+5,2)).Sort key1:=Range(Cells(i,2),Cells(i+5,2)), order1:=xlAscending, Header:=xlNo
i=i+5
End if
next i
I have an Excel VBA macro that works successfully the first two times I run it, but the third time it gives this error:
Run-Time Error '1004'
The sort reference is not valid. Make sure that it's within the data you want to sort, and the first Sort By box isn't the same or blank.
If I restart Excel it works the first two times, then gives the error again. Why would this happen? Here's my code:
Dim rawData As Object
Dim report As Object
Dim areaCodes As Object
Set rawData = Sheets("RawData")
Set report = Sheets("Report")
Set areaCodes = Sheets("AreaCodes")
report.Cells.Clear
report.Cells.ClearFormats
stateCol = rawData.Cells(1, 1).EntireRow.Find(What:="state", LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByColumns, SearchDirection:=xlNext, MatchCase:=False).Column
Dim MyRange As Range
Set MyRange = rawData.Cells(1, stateCol)
With rawData
lastRow = .Cells(Rows.Count, MyRange.Column).End(xlUp).Row
.Range(.Cells(2, stateCol), .Cells(lastRow, stateCol)).Copy
End With
With report
.Range("A3").PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
.Range(.Cells(3, 1), .Cells(lastRow + 1, 1)).RemoveDuplicates Columns:=1, Header:=xlNo
End With
lastRow = report.Cells(Rows.Count, Range("A1").Column).End(xlUp).Row
report.Range("B3").Select
ActiveCell.FormulaR1C1 = "=COUNTIF(rawData!C[" & stateCol - 2 & "],report!RC[-1])"
Range("B3").AutoFill Destination:=Range("B3:B" & lastRow)
Range("B" & lastRow + 1).Select
ActiveCell.FormulaR1C1 = "=SUM(R[-" & lastRow - 2 & "]C:R[-1]C)"
Range("C3").Select
ActiveCell.FormulaR1C1 = "=RC[-1]/R" & lastRow + 1 & "C[-1]"
Range("C3").AutoFill Destination:=Range("C3:C" & lastRow)
Range("C" & lastRow + 1).Select
ActiveCell.FormulaR1C1 = "=SUM(R[-" & lastRow - 2 & "]C:R[-1]C)"
Range("C:C").NumberFormat = "0.0%"
Range("A2:A" & lastRow + 1).Select
Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
report.Range("A2").Value = "State"
report.Range("A2").Font.Bold = True
report.Range("A:A").HorizontalAlignment = xlCenter
report.Range("A3").FormulaR1C1 = "=INDEX(areaCodes!R2C5:R52C5,MATCH(report!RC[1],AreaCodes!R2C6:R52C6,0))"
Range("A3").Select
ActiveCell.AutoFill Destination:=Range("A3:A" & lastRow)
With report
newLastRow = .Cells(Rows.Count, Range("C1").Column).End(xlUp).Row - 1
.Range(.Cells(3, 3), .Cells(newLastRow, 3)).Copy
.Range("C3").PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
End With
With report
.Sort.SortFields.Add Key:=Range("C2"), SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
newLastRow = .Cells(Rows.Count, Range("C1").Column).End(xlUp).Row - 1
With .Sort
.SetRange Range("A2:D" & newLastRow)
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End With
you should qualify the range in your sort instruction, this will produce an error if the sheet report is not activated
With report
.Sort.SortFields.Add Key:=.Range("C2"), SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
newLastRow = .Cells(Rows.Count, .Range("C1").Column).End(xlUp).Row - 1
With .Sort
.SetRange report.Range("A2:D" & newLastRow)
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End With
I'm trying to clean up a bit of code and I was hoping SO could come to my rescue once again. I need to copy a range, open a new workbook with only one tab called "project code - Labels" (project code found in labels sheet cell A2 or A2 of new workbook). After pasting values and source formatting, I'd like to propmt the user to choose a save location, save the new file, close new workbook and return to the original workbook.
I have added comments for what I'd like to do in the code below
Sub GenLabels()
Application.ScreenUpdating = False
Worksheets("HR-Cal").Activate
Range("u100000").End(xlUp).Select
Range("ap2") = ActiveCell.Row
Worksheets("Labels").Activate
Dim rng As Range
Dim lab As String
Rows("3:" & Range("as1")).Select
Selection.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
Range("A2:AP2").AutoFill Destination:=Range("A2:AP" & Range("as1")), Type:=xlFillDefault
Range("A2:AP32").End(xlDown).Select
Range("a100000").End(xlUp).Activate
Range("at1") = ActiveCell.Row
lab = ("A2:AP" & Range("at1"))
Set rng = Range(lab)
rng.Select
ActiveWorkbook.Worksheets("Labels").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Labels").Sort.SortFields.Add Key:=Range("X2:X" & Range("at1")) _
, SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Labels").Sort
.SetRange Range("a1:ap" & Range("at1"))
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
For lrow = Cells(Cells.Rows.Count, "X").End(xlUp).Row To 1 Step -1
If Cells(lrow, "X") = 0 Then
Rows(lrow).EntireRow.Delete
End If
Next lrow
For lrow = Cells(Cells.Rows.Count, "D").End(xlUp).Row To 1 Step -1
If Cells(lrow, "D") = 0 Then
Rows(lrow).EntireRow.Delete
End If
Next lrow
Range("A1:AP1").End(xlDown).Copy
Application.ScreenUpdating = True
' msgbox that allows user to check filtered data and only runs the rest of the macro
' if they click OK
msgbox("If Label data looks correct please press OK to continue, or CANCEL to stop",vbOKCancel)
If vbCancel Then
End Sub
Else
'Code to paste only values and formatting into new workbook
Worksheets("Labels").Activate
Range("A1:AP1").End(xlDown).Copy
Sheets("Labels").Select
' create new workbook with only one sheet
Workbooks.Add
'paste label data
Selection.PasteSpecial Paste:=xlPasteAllUsingSourceTheme, Operation:=xlNone _
, SkipBlanks:=False, Transpose:=False
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
' prompt user to choose file save location, with file name PROJECT CODE - Labels
ActiveWorkbook.SaveAs Filename:="v:\Users\lies\NotReal\J31 Labels.xlsx", _
FileFormat:=xlOpenXMLWorkbook, CreateBackup:=False
' save and close new workbook
'return to orginal workbook
Worksheets("Labels").Activate
Range("A2").Select
End Sub
After lots of hair pulling and desk punching I figure this out please see code. granted this may not be the most efficient way but its fairly fast and without errors
Sub GenLabels()
Application.ScreenUpdating = False
Worksheets("HR-Cal").Activate
Range("u100000").End(xlUp).Select
Range("ap2") = ActiveCell.Row
Worksheets("Labels").Activate
Dim rng As Range
Dim lab As String
Rows("3:" & Range("as1")).Select
Selection.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
Range("A2:AP2").Select
Selection.AutoFill Destination:=Range("A2:AP" & Range("as1")), Type:=xlFillDefault
Range("A2:AP32").End(xlDown).Select
Range("a100000").End(xlUp).Activate
Range("at1") = ActiveCell.Row
lab = ("A2:AP" & Range("at1"))
Set rng = Range(lab)
rng.Select
ActiveWorkbook.Worksheets("Labels").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Labels").Sort.SortFields.Add Key:=Range("X2:X" & Range("at1")) _
, SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Labels").Sort
.SetRange Range("a1:ap" & Range("at1"))
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
For lrow = Cells(Cells.Rows.Count, "X").End(xlUp).Row To 1 Step -1
If Cells(lrow, "X") = 0 Then
Rows(lrow).EntireRow.Delete
End If
Next lrow
For lrow = Cells(Cells.Rows.Count, "D").End(xlUp).Row To 1 Step -1
If Cells(lrow, "D") = 0 Then
Rows(lrow).EntireRow.Delete
End If
Next lrow
Dim last As String
Range("a100000").End(xlUp).Activate
last = ActiveCell.Row
Range("A1:AP" & last).Copy
'Application.ScreenUpdating = True
Sheets.Add After:=Sheets(Sheets.Count)
ActiveSheet.Name = ActiveSheet.Range("A2") & " " & Range("Z2") & " - Labels"
'Range("A1").Select
Selection.PasteSpecial Paste:=xlPasteAllUsingSourceTheme, Operation:=xlNone _
, SkipBlanks:=False, Transpose:=False
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Selection.Columns.AutoFit
ActiveWindow.Zoom = 80
Range("A1").Select
ActiveSheet.Select
Application.CutCopyMode = False
ActiveSheet.Move
'
ActiveSheet.Name = ActiveSheet.Range("A2") & " " & Range("Z2") & " - Labels"
Application.ScreenUpdating = True
Dim bFileSaveAs As Boolean
bFileSaveAs = Application.Dialogs(xlDialogSaveAs).Show
End Sub
I created this macro to search through two spreadsheets and update one from the other based on unique keys that each row has. It will copy the first sheet to a temp sheet then unfilter and unhide everything. Next it will sort them by key so that they are all in order. after that it will move two columns to be excluded from the update to the front and update the rest. To update it will search through using the match function and if it comes up as an error (which means the row isn't there) it will add it to the end of the update sheet. Otherwise, it will copy and paste each row from the source to the update sheet. It all works but for some reason it won't update past line 24 and I have no idea why. I've stepped through it and it doesn't break, it just doesn't update. I am new to vba so any help would be greatly appreciated.
Sub crossUpdate()
Dim rng1 As Range, rng2 As Range, rng1Row As Range, rng2Row As Range, Key As Range, match As Variant
Dim wb1 As Workbook
Dim wb2 As Workbook
Dim endRng2 As Long
Set wb2 = Workbooks("011 High Level Task List v2.xlsm")
Set wb1 = Workbooks("011 High Level Task List v2 ESI.xlsm")
'Unfilter and Unhide both sheets
With wb1.Sheets("Development Priority List")
.Cells.EntireColumn.Hidden = False
.Cells.EntireRow.Hidden = False
.AutoFilterMode = False
End With
With wb2.Sheets("Development Priority List")
.Cells.EntireColumn.Hidden = False
.Cells.EntireRow.Hidden = False
.AutoFilterMode = False
End With
'Copy and paste original sheet to new temp sheet
wb1.Sheets("Development Priority List").Activate
wb1.Sheets("Development Priority List").Cells.Select
Selection.Copy
Sheets.Add.Name = "SourceData"
wb1.Sheets("SourceData").Paste
N = Cells(Rows.Count, "A").End(xlUp).Row
Set rng1 = wb1.Sheets("SourceData").Cells.Range("A2:A" & N)
Set rng1Row = rng1.EntireRow
'Sort temp sheet by key
wb1.Worksheets("SourceData").Sort.SortFields.Clear
wb1.Worksheets("SourceData").Sort.SortFields.Add Key:=wb1.Sheets("SourceData").Cells.Range("A2:A" & N), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= _
xlSortNormal
With wb1.Worksheets("SourceData").Sort
.SetRange Range("A1:Z1000")
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
'Sort update sheet by key
wb2.Activate
wb2.Worksheets("Development Priority List").Sort.SortFields.Clear
wb2.Worksheets("Development Priority List").Sort.SortFields.Add Key:=wb2.Sheets("Development Priority List").Cells.Range("A2:A" & N), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= _
xlSortNormal
With wb2.Worksheets("Development Priority List").Sort
.SetRange Range("A1:Z1000")
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
'Dev columns moved on SourceData sheet
wb1.Sheets("SourceData").Activate
Columns("F:G").Select
Selection.Cut
Columns("A:A").Select
Selection.Insert Shift:=xlToRight
'Dev columns moved on update sheet
wb2.Sheets("Development Priority List").Activate
Columns("F:G").Select
Selection.Cut
Columns("A:A").Select
Selection.Insert Shift:=xlToRight
'Update sheet searched and updated from SourceData
Set rng2 = wb2.Sheets("Development Priority List").Cells.Range("C2:C" & N)
endRng2 = rng2.Rows.Count
For i = 2 To rng1.Rows.Count + 1
Set Key = wb1.Sheets("SourceData").Range("C" & i)
match = Application.match(Key, rng2, 0)
'Rows that don't exsist in update sheet are added
If IsError(match) Then
wb1.Sheets("SourceData").Range("C" & i, "Z" & i).Copy
wb2.Sheets("Development Priority List").Range("C" & endRng2, "Z" & endRng2).Select
wb2.Sheets("Development Priority List").Paste
endRng2 = endRng2 + 1
'All other rows are scanned for changes
Else
For j = 3 To wb1.Sheets("SourceData").Range("C" & i, "Z" & i).Columns.Count
wb2.Sheets("Development Priority List").Cells(j, i).Value = wb1.Sheets("SourceData").Cells(j, i)
Next j
End If
Next i
'SourceData sheet deleted
Application.DisplayAlerts = False
wb1.Sheets("SourceData").Delete
Application.DisplayAlerts = True
'Dev columns moved back on update sheet
wb2.Sheets("Development Priority List").Activate
Columns("A:B").Select
Selection.Cut
Columns("H:H").Select
Selection.Insert Shift:=xlToRight
wb1.Activate
It took me a few times coming back to this to figure out what was wrong. Here is what I believe is happening:
This code:
For j = 3 To wb1.Sheets("SourceData").Range("C" & i, "Z" & i).Columns.Count
wb2.Sheets("Development Priority List").Cells(j, i).Value = wb1.Sheets("SourceData").Cells(j, i)
Next j
Is looping from 3 to the number of columns between "C" and "Z" (ALWAYS 24). The bit inside the FOR loop is using Cells(<row>, <column>) syntax to copy from one cell to another. Because J is always looping from 3 to 24 then ROWS 3 through 24 are the only ones that will be updated. Perhaps you meant Cells(i,j)?