I currently have two sheets with six columns of data, both in the same format, except that Sheet 1 has historic data and sheet 2 has newer data with some additional rows. Both sheets are sorted in order of the contents in the 2nd column followed by the 4th column.
I want to prepare a macro that compares both sheets and looks down the 2nd and 4th columns to identify the new rows in Sheet 2 that are not in Sheet 1 and color highlight these rows in Sheet 2. In addition, I would like the new rows from sheet 2 to be inserted into Sheet 1 in the correct order.
For Example
The reason for doing all this as opposed to just copying the entire contents of Sheet 2 into Sheet 1 is because sheet 1 has a number of formulas beyond the 6 columns which reference certain blocks of cells and it is require that these references be preserved. I currently have to manually insert each new row and given the amount of data being processed, this takes quite some time. I have tried adapting other macros that I found across the internet to perform this task but they don’t quite work.
Step #1: identify rows that are in sheet2 and not in sheet1
Create a new column E in both sheets with this formula:
=B2&D2
(starting from row 2 and auto fill it to the entire column)
in sheet2 create column F with this formula
=ISERR(VLOOKUP(Sheet2!E2,Sheet1!E:E,1,FALSE))
Now column F would be TRUE only for rows that aren't in sheet1.
Next you'll need to add conditional formatting for F=TRUE
Step #2: Copy the missing data
Filter rows from sheet2 with F=TRUE
Copy them to the end of sheet1
Sort sheet1
If you copy the data (excluding the header) from Sheet2 underneath the data in Sheet1 and subsequently a) remove duplicates then b) sort on columns B and D, you should achieve the results you are looking for.
Sub collect_and_sort()
With Sheets("sheet1")
Sheets("sheet2").Cells(1, 1).CurrentRegion.Offset(1, 0).Copy _
Destination:=.Cells(Rows.Count, 2).End(xlUp).Offset(1, -1)
With .Cells(1, 1).CurrentRegion
.RemoveDuplicates Columns:=Array(2, 4), Header:=xlYes
.Cells.Sort Key1:=.Columns(2), Order1:=xlAscending, _
Key2:=.Columns(4), Order2:=xlAscending, _
Orientation:=xlTopToBottom, Header:=xlYes
End With
End With
End Sub
From the data on two sheets like this (shown on one sheet for space considerations),
You will have this after the macro has run.
I will admit I am unclear on whether the 3000/b in Sheet1!B11:D11 was a typo or an actual duplicate record. The macro does reproduce your desired results.
Related
I have two sheets in an Excel file and need to perform a COUNTIF formula from one sheet and paste the respective information in another sheet. The original sheet just has the type in 1st column with an empty 2nd column. I am trying to loop through the Type from Sheet 1, in each increment loop through the Type from Sheet 2, and past the Count of column 2 from Sheet 2 into Column 2 of sheet 1.
My current VBA code is as follows:
Sub TestOE()
'For loop to go until end of filled cells in 1st column of each sheet
a = Worksheets("Sheet1").Cells(Rows.Count, 1).End(xlUp).Row
b = Worksheets("Sheet2").Cells(Rows.Count, 1).End(xlUp).Row
'Loop
For i = 2 To a
For j = 2 To b
If Worksheets("Sheet1").Cells(i, 1).Value = Worksheets("Sheet2").Cells(j, 1).Value Then
Worksheets("Sheet1").Cells(i, 2).Value = Application.WorksheetFunction.CountIf(Range("B:B"), 1)
End If
Next j
Next i
End Sub
This code is only pasting 0's in the desired outcome on Sheet 1.
Sheet to extract information from
Sheet to paste information in
Desired Outcome in destination sheet
You can simply use sumif function to sum the values based on criteria.
here is the formula
=COUNTIF(Sheet1!$A$2:$A$20,Sheet2!A2)
if you want to sum the col B then
=SUMIF(Sheet1!$A$2:$A$20,Sheet2!A2,Sheet1!$B$2:$B$20)
In a few steps, you can accomplish what you want without VBA, and just use a pivot table. Just do as follows.
Select your data set, including the header.
Click on insert tab, then PivotTable. See example for Office 365
Since you want a different worksheet, set PivotTable to be "New Worksheet" See example.
You'll need to drag the TYPE field into the rows, and binary into the values. CountIF is the same as summing binary, so you can leave as sum. See Example
And you'll have an output nearly identical to what you're looking for:
New to VBA, and I'm trying to create multiple ranges or arrays based on a criteria in a column, then place those in a separate worksheet. The issue is that this code has to work for several different data sets. So one data sat will look something like
this, but with far more data points ( around 10,000 for each data set).
So what I'm trying to do is, for each group of 1's in the state column, create a range/array, then move the corresponding time and data in a new worksheet. So for the example I have, there would be 3 new worksheets, with the first new worksheet containing range("A2:B5"), the second one containing range("A10:B12"). With each data set, the state column changes and the number of new worksheets can also vary.
I have looked through this site, and the closest I have found to my needs is Creating Dynamic Range based on cell value, but it has a known number of ranges. I quite honestly have no idea how to accomplish what I need. I've been trying to make a while loop inside of a if then loop inside of a for each loop, but can't make it work.
Any help would be greatly appreciated! Been banging my head for hours now.
this should help you:
Option Explicit
Sub main()
Dim area As Range
With Sheets("myDataSheet") '<--| reference your sheet (change "myDataSheet") to your actual sheet name
With .Range("C1", .Cells(.Rows.Count, "A").End(xlUp)) '<--| reference its columns A:C range form row 1 down to last column A not empty row
.AutoFilter Field:=3, Criteria1:="1" '<--| filter referenced range on its 3rd column (i.e. "State") with 1
If Application.WorksheetFunction.Subtotal(103, .Resize(, 1)) > 1 Then '<--| if any filterd cells other than header
For Each area In .Resize(.Rows.Count - 1, 2).Offset(1).SpecialCells(xlCellTypeVisible).Areas '<--| loop through filtered range (skipping header) 'Areas'
area.Copy Sheets.Add(Sheets(Sheets.Count)).Range("A1") '<--| copy current 'Area' into new sheet
Next area
End If
End With
.AutoFilterMode = False
End With
End Sub
I have a current Sub that organizes data certain way for me and even enters a formula within the first row of the worksheet, but I am running into the issue of wanting it to be able to adjust how far down to fill the formula based on an adjacent column's empty/not empty status. For example, each time I run a report, I will get an unpredictable amount of returned records that will fill out rows in column A, however, since I want to extract strings from those returned records into different Columns, I have to enter formulas for each iteration within the next three columns (B, C, and D). Is there a way to insert a line that will evaluate the number of rows in Column A that are not blank, and then fill out the formulas in Columns B, C, and D to that final row? (I know that tables will do this automatically once information is entered in the first row, but for logistical reasons, I cannot use tables).
My current code that fills out the formula in Column B, Row 2 is:
Range("B2").Select
ActiveCell.FormulaR1C1 = "=MID(RC[-1],FIND(""By:"",RC[-1])+3,22)"
Thanks!
The formula that you actually need is
=IF(A2="","",MID(A2,FIND("By:",A2)+3,22))
instead of
=MID(A2,FIND("By:",A2)+3,22) '"=MID(RC[-1],FIND(""By:"",RC[-1])+3,22)"
This checks if there is anything in cell A and then act "accordingly"
Also Excel allows you to enter formula in a range in one go. So if you want the formula to go into cells say, A1:A10, then you can use this
Range("A1:A10").Formula = "=IF(A2="","",MID(A2,FIND("By:",A2)+3,22))"
Now how do we determine that 10? i.e the Last row. Simple
Sub Sample()
Dim ws As Worksheet
Dim lRow As Long
'~~> Change the name of the sheet as applicable
Set ws = ThisWorkbook.Sheets("Sheet1")
With ws
'~~> Find Last Row in Col A
lRow = .Range("A" & .Rows.Count).End(xlUp).Row
.Range("B2:B" & lRow).Formula = "=IF(A2="""","""",MID(A2,FIND(""By:"",A2)+3,22))"
End With
End Sub
More About How To Find Last Row
You can use this to populate columns B:D based on Column A
Range("B2:D" & Range("A" & Rows.Count).End(xlUp).Row).Formula = _
"=MID($A2,FIND(""By:"",$A2)+3,22)"
I have vba question I have been trying to find the answer for for a long time. I have numerous spreadsheets from numerous clients that I run macro's on, I'm new to coding and have been able to mostly figure out what I need to do. My clients send us data monthly and every month the number of rows change. The columns don't change but the amount of data does. My previous macro's I have just chosen the entire column to copy and paste onto our companies template. This worked fine for must things but has created some really long code and macros take a long time. I would like to write a code that counts how many rows are in a certain column and then from there copies and pastes that however many rows it counted in each column. Only a few columns contain data in every row, so I need it to count the rows in one specific column and apply to that every column. Any help would be appreciated.
Thanks
Tony
Hi Guys,
Still having issues with this, below I pasted the code I'm using if anyone can see why it won't run please help.
Windows("mmuworking2.xlsx").Activate
Workbooks.Open Filename:= _
"C:\Users\I53014\Desktop\QC DOCS\Sample_Data_Import_Template.xlsx"
Windows("mmuworking2.xlsx").Activate
Dim COL As Integer
COL = Range("A:DB").Columns.Select
**Range(Cells(2, COL), Cells(Range("E" & Rows.Count).End(xlUp).Row, COL)).Copy Destination:=Windows("Sample_Data_Import_Template.xlsx").Range("A2")**
Range("A2").Paste
Range("A5000").Formula = "='C:\Users\I53014\Desktop\[Import_Creator.xlsm]sheet1'!$B$2"
ActiveWorkbook.SaveAs Filename:="Range (A5000)", _
FileFormat:=xlOpenXMLWorkbook, CreateBackup:=False
I bolded where it keeps stopping.
This should give you the last row containing data:
ActiveSheet.UsedRange.Rows.Count
This will give you the last row in a specific column:
Range("B" & Rows.Count).End(xlUp).Row
here is an example of how I can copy every row in the first three columns of a worksheet
Sub Example()
Dim LastRow As Long
LastRow = ActiveSheet.UsedRange.Rows.Count
Range(Cells(1, 1), Cells(LastRow, 3)).Copy Destination:=Sheet2.Range("A1")
End Sub
You have to be careful as there are some caveats to both methods.
ActiveSheet.UsedRange may include cells that do not have any data if the cells were not cleaned up properly.
Range("A" & Rows.Count).End(xlUp).Row will only return the number of rows in the specified column.
Rows(Rows.Count).End(xlUp).Row will only return the number of rows in the first column.
Edit Added an example
Edit2 Changed the example to be a bit more clear
For this example lets say we have this data
You could copy any other column down to the number of rows in column A using this method:
Sub Example()
Dim Col as Integer
Col = Columns("C:C").Column
'This would copy all data from C1 to C5
'Cells(1, Col) = Cell C1, because C1 is row 1 column 3
Range(Cells(1, Col), Cells(Range("A" & Rows.Count).End(xlUp).Row, Col)).Copy Destination:=Sheet2.Range("A1")
End Sub
The end result would be this:
I am struggling with this macro. I have two sheets; One with a large set of data that is updated by a macro with respect to multiple dates.
I want to copy the data from that sheet ("rawdata1") to another sheet ("sheet1"), but only if the data isn't already present (don't want multiple entries of the same data on "sheet1"). I have no problem copying the data to the other sheet but how do you avoid duplicate entries when the macro is run multiple times?
The code I have so far:
Sub CopyData()
'Copy data if not present in other sheet
'???
Sheets("rawdata1").Select
Range("A4:AC10000").Select
Range("A4:AC10000").Copy
Sheets("Sheet1").Select
' Find the last row of data
FinalRow = Cells(Rows.Count, 1).End(xlUp).Row
ActiveSheet.Paste
Sheets("Sheet1").Select
Thanks for the help!
Your code can be simplified to:
Sheets("rawdata1").Range("A4:AC10000").Copy _
Sheets("Sheet1").Cells(Rows.Count, 1).End(xlUp).Offset(1,0)
Sheets("Sheet1").Select
As for preventing multiple copies of the same line, if you're in Excel 2007+ then you can use RemoveDuplicates after running the copy: this will reduce the range down to unique rows only. Note: you need to adjust the Columns parameter to include all relevant column numbers.
ActiveSheet.UsedRange("$A$1:$E$8").RemoveDuplicates _
Columns:=Array(1, 2, 3, 4, 5), Header:=xlYes 'or xlNo, depending on your data