Insert 10000+ rows in an Excel sheet - vba

I am creating an Excel macro while pulls data from an Excel sheet (containing more than 10 thousand rows) and populates another Excel sheet.
I have to insert data row-wise since for every row I need to fetch data from 2-3 different sheets based on a column value (say, EMP_ID).
e.g. Excel file - 1 has
Emp_ID | Emp_Name | Age
Now based on each employee ID I need to fetch employee related data from 3 other Excel sheets. So I have to loop through 10k records.
When I execute the code the Excel application just hangs. I think this is because I try to insert data row-wise.
Can someone suggest a faster way to insert/update large number of rows.
I have already tried using Variant/Array to store data and then populate the sheets. But it still doesn't seem to work.
NOTE: I am reading records from the Source file into a RecordSet.
I have already added:
Application.DisplayAlerts = False,
Application.ScreenUpdating = False,
Application.Calculation = xlCalculationManual
And then set it back to default.

I know this is not a direct answer, but sometimes it's better to teach how the work has to be done, intead of simply reply.
Your work needs to be done with Access (or any other dbms). You have to define three tables, each indexed by Emp_ID, and all the staff become simple.

I tend to agree with Sergio.
If using a database is totally not an option, using an array is the way to go.
I have already tried using Variant/Array to store data and then populate the sheets. But it still doesn't seem to work.
Can you show the code you tried?
This works for me:
Dim arData() As Variant
' ... calculate number of rows and columns ...
ReDim arData(1 To numRows, 1 To numCols)
' ... populate arData ...
' Define range with identical dimensions as arData, e.g. insert in second row
Set rng = sh.Range(sh.Cells(2, 1), sh.Cells(numRows + 1, numCols))
' Transfer array to range (this is fast!)
rng.Value = arData

Also agree, Excel isn't really the tool for this.
If you're stuck with it then try the following:
Read all lookup sheets just once into collections using class objects as your data structures. For example, create a class called Employee and add the appropriate properties.
Public ID As Long
Public Age As Integer
Public Name As String
To read them, you'd code it like this...
Private mEmployeeCol As Collection
Dim ws As Worksheet
Dim empData As Employee
Dim v As Variant
Dim r As Long
Set ws = ThisWorkbook.Worksheets("employee stuff")
v = ws.UsedRange.Value2
Set mEmployeeCol = New Collection
For r = LBound(v, 1) To UBound(v, 1)
Set empData = New Employee
empData.ID = v(r, 1)
empData.Name = v(r, 2)
empData.Age = v(r, 3)
mEmployeeCol.Add empData, Key:=CStr(empData.ID)
Next
To look up the values, do it so ...
Set empData = mEmployeeCol(CStr(ID))
v(r, [your col]) = empData.ID
Then, definitely, DEFINITELY populate the final sheet with an array of variants. It's pretty straight forward ...
Dim v(1 To 10000, 1 To 50) As Variant
ws.Range("A1").Resize(UBound(v, 1), UBound(v, 2)).Value = v

Related

Excel Change Columns Based On Another One

I'm currently working on 6 Excel workbooks all with same format. Basicly i have a table which includes product codes with their amount needs to be used. I have around 200 worksheets in every Excel file with same format. I want to update these product amount based on multiplier table i made. Here an example of data below;
Sample of data
Multiplier table
So the new values of sample codes should be 4,15 3,5 7,84 and 88,62.
Because the high amount of pages with workbooks, probably changing or inserting some kind of formula one by one would take very long time. I wonder how can I get the job done with few easy steps.
Thanks!
All you need to do is to use VLookup function or array formula. Then you'll be able to fill down or copy formula for every single record.
In your case i'd suggest to use array formula. Assuming, if MultiplierTable is the name of worksheet and that worksheet contains data (as you provided) in a range C4:D7, you can copy below formula and paste it into E4 cell:
=D4*SUM(IF(C4=MultiplierTable!C$4:C$7,MultiplierTable!D$4:D$7,0))
Fill down the formula. Select entire column and paste as values in the same column. Repeat this step for each worksheet.
Follow the links for further details.
In case, you want to use VBA, please let me know. I'll try to improve my answer.
I checked some guides for basics of VBA and created my own VBA script. It became a little hardcoded but because this is one time job, it get the job done.
Sub degistir()
Dim WS_Count As Integer
Dim I As Integer
Dim val As Double
WS_Count = ActiveWorkbook.Worksheets.Count
For I = 1 To WS_Count
Worksheets(I).Activate
For R = 8 To 14
val = ActiveSheet.Cells(R, 4)
If ActiveSheet.Cells(R, 2) Like "P001" Then
val = val * 1
ElseIf ActiveSheet.Cells(R, 2) Like "P002" Then
val = val * 0.533333333
'and goes...
End If
ActiveSheet.Cells(R, 4).Value = val
Next R
Next I
End Sub

Incrementing the numeric part of an alphanumeric criteria to search multiple columns and print records with Excel VBA

I should note that there are related solutions to my question online but I've been unable to implement them into my own situation.
We have an .mdb database of all the products that we make. I've managed to take two criteria (Order type and Box), and print all records containing those two criteria to Excel. What I need in addition to that now is to print 30 boxes in one go as a basis for a bigger template. The labeling of these boxes usually increment (e.g. P1, P2...P30), and I'm struggling to see how I can increment the numeric portion of it to fit it into my code. Ideally, I'd like for the user to input the first and last box numbers in excel to represent the entire range (P1 and P30) and use those two values.
Sub Dan()
Dim order As String
Dim title As String 'initialize title
Dim palette As String 'intialize comment
Dim finalpalette As String
Dim finalrow As Integer 'initialize bottom-most row
Dim i As Integer
Dim Cntr As Integer
Dim LR As Integer
'Clears the contents of the last macro run
With Sheets("ALL.txt")
.Range(.Cells(6, 2), .Cells(725, 8)).ClearContents 'equates to (D2:F26)/ row, column ;Erase Columns for next macro
End With
title = Sheets("Sheet2").Range("B1").Value
palette = Sheets("Sheet2").Range("B2").Value
finalrow = Sheets("Sheet1").Range("A2").End(xlDown).Row
For i = 3 To finalrow
If Cells(i, 1) = title And Cells(i, 2) = palette Then
Cells(i, 5).Copy 'Copy ID
Sheets("ALL.txt").Range("B734").End(xlUp).Offset(1, 0).PasteSpecial
Range(Cells(i, 11), Cells(i, 14)).Copy
Sheets("ALL.txt").Range("C734").End(xlUp).Offset(1, 0).PasteSpecial
Range(Cells(i, 9), Cells(i, 10)).Copy
Sheets("ALL.txt").Range("G734").End(xlUp).Offset(1, 0).PasteSpecial
End If
Next i
End Sub
The variable I'm looking to adjust is 'palette'. I originally used it to match records to one Box (P1). What I need is to able to match records from 30 boxes (P1 to P30) in the loop. The variable 'palette' is just taking the static value of whatever is in cell B2 at the moment. I'm thinking there should be some way to type the first and last box into two cells to establish a range for the macro to iterate, or to write all the box numbers into a column and have 'palette' move down a cell each loop to take in a new Box value.
In an attempt to grab data from a column that has all 30 boxes written into 30 cells, I tried the following line of code
End If
palette = Sheets("Sheet2").Range("B2").Offset(, 1)
Next i
but it does not seem to be grabbing any value. It should be grabbing values from cells B2 to B31.
Here is some code that I changed (still no clue as to why you're breaking this up into 3 parts, seems like excel VBA is an extra step that complicates it).
thisworkbook.worksheets(1).cells(i,5) Use full references when learning VBA
let me know if this works, I don't know enough about your situation to know exactly what you need, other than what I can see you're trying to do.
Sub Dan()
Dim Order As String
Dim Title As String 'initialize title
Dim Palette As String 'intialize comment
Dim Fpalette As String
Dim Frow As Integer 'initialize bottom-most row
Dim i As Integer
Dim Cntr As Integer
Dim LR As Integer
Dim wsALL As Worksheet
'Clears the contents of the last macro run
With Sheets("ALL.txt")
.Range(.Cells(6, 2), .Cells(725, 8)).ClearContents 'equates to (D2:F26)/ row, column ;Erase Columns for next macro
End With
Title = Sheets("Sheet2").Range("B1").Value
Palette = Sheets("Sheet2").Range("B2").Value
Frow = Sheets("Sheet1").Range("A2").End(xlDown).Row
Set wsALL = Sheets("ALL.txt")
i = 2
Do While i < Frow
i = i + 1
If ThisWorkbook.Worksheets("Sheet1").Cells(i, 1) = Title And ThisWorkbook.Worksheets("Sheet1").Cells(i, 2) = Palette Then
Sheets("Sheet1").Cells(i, 5).Copy Destination:=wsALL.Range("B734").End(xlUp).Offset(1, 0)
'wsALL.Range("B734").End(xlUp).Offset(1, 0).PasteSpecial
Sheets("Sheet1").Range(Cells(i, 11), Cells(i, 14)).Copy Destination:=wsALL.Range("C734").End(xlUp).Offset(1, 0)
'wsALL.Range("C734").End(xlUp).Offset(1, 0).PasteSpecial
Sheets("Sheet1").Range(Cells(i, 9), Cells(i, 10)).Copy Destination:=wsALL.Range("G734").End(xlUp).Offset(1, 0)
'wsALL.Range("G734").End(xlUp).Offset(1, 0).PasteSpecial
End If
Loop
End Sub
Ignore the Below, I was going to make this way more complicated than necessary. Looking at your code, be sure to reference using
Hi Joshua,
I'm not sure I completely understand what you're trying to accomplish, adding in more details such as the first macro may help in getting you a specific answer. I think possibly VBA in Excel may not be the best way. A VBA in Access sounds possible solution. But this may be of help to you.
I know you said for an end user, It would be much more complicated on your part but I've had great success using microsoft query to import data, with the correct ODBC driver "Access Database Engine" http://www.microsoft.com/en-us/download/details.aspx?id=13255 it works great now and I use it to get data from flat files then send it to SQL based on a query, but I fought with it to get it to work you will rip your hair out and it wouldn't be portable to an end user
Having a user enter a value into a specific cell could work, i.e. put a value in A1 and VBA can check that value using:
Alpha = Cells(1,1).Value
pStart = Cells(2,1).Value 'A2
pEnd = pStart + 30
In order to prevent any issues with spaces this could be done as:
set pStart = Trim(ActiveCell(2,1).Value)
Or another way is to use data validation and give users a drop down list. https://support.office.com/en-ca/article/Create-or-remove-a-drop-down-list-5a598f31-68f9-4db7-b65e-58bb342132f7
Here is the code if for either way. Notice I've made some edits, most are not essential changes, just how I write VBA. When you use the copy -> paste command it avoids the clipboard if you say .Copy Destination:= Another comment, this would be so easy in Access simply write an SQL statement and use the append feature. You say that you have a macro before this, and after this, I would say make it one (very powerful and nice) SQL statement what is run through a user form.

Excel Overflow Error

Here is my code :
Dim i As Integer, a As Integer, rowsInThere As Integer, rowsInI As Integer
Dim ws As Worksheet, b As Integer
Dim x As Integer, z As Integer
Dim total As Integer
Dim value As String
rowsInProjects = Sheets("Projects").UsedRange.Rows.Count
z = 3
Worksheets("Summary_Sheet (2)").Range("b5:b50").ClearContents
Worksheets("Summary_Sheet (2)").Range("c5:c50").ClearContents
Worksheets("Summary_Sheet (2)").Range("d5:d50").ClearContents
Worksheets("Summary_Sheet (2)").Range("e5:e50").ClearContents
Worksheets("Summary_Sheet (2)").Range("F5:F50").ClearContents
Worksheets("Summary_Sheet (2)").Range("G5:G50").ClearContents
Worksheets("Summary_Sheet (2)").Range("H5:H50").ClearContents
For a = 1 To rowsInProjects
value = Worksheets("Projects").Cells(a, 1).value
Worksheets("Summary_Sheet (2)").Cells(a + 4, 2).value = value
For i = 5 To Worksheets.Count
rowsInI = Worksheets(i).UsedRange.Rows.Count
For x = 1 To rowsInI
If Worksheets(i).Cells(x + 8, 3).value = value Then
total = total + Worksheets(i).Cells(x + 8, 6).value
End If
Worksheets("Summary_Sheet (2)").Cells(i, z).value = total
Next x
z = z + 1
Next i
z = 3
Next a
There error arises on the total = total + ... line. What my code is doing is copying a list of projects from a worksheet into a new one.
It then has to search through the other worksheets for each of the project names added. Each of the other worksheets will have 2-3 records with the project name. I want to get the total cost of the project from each worksheet and then insert it back into the orginal file.
Steps:
1. Create list of projects
Iterate through List
iterate through each worksheet
totaling values from matching projects
Insert value back into project list
J O'Brien, Choate and Townsend are the 3 worksheets
This is the Choate worksheet
Is this approach right for what I am trying to achieve?
you're probably overflowing the max size of an Integer, which is 32767. Try using a long for your range loop counter instead.
This would apply to a, x, z and rowsInI
You also asked if this (your method) was the right approach, Yours works so yes it is. However, it could possibly be optimised.
For every item in your project list, you're iterating over every row in your data sheet in all of your data sheets.
Which, depending on the number of rows in each sheet, is a fair few! (its at least Projects * Rows * 3)
I dont know if your "projects" list is one you generate per-run, so you only get a few projects or if its just everything you've got.
Hopefully the code below makes some sense, if you decide to give it a go please make sure you run it on a copy of your data! It's an example and it only dumps the result to the debug window.
The code below (which may not function perfectly as I might have got the columns and rows wrong) will loop over each sheet once and calculate a per-sheet total for each project (allowing for multiple instances of the same project in a single sheet, if this is possible in your data)
Sub Main()
Dim Projects As Object
'Dim Projects As Scripting.Dictionary
Set Projects = CreateObject("Scripting.Dictionary")
'Set Projects = New Scripting.Dictionary
Dim Project As String
Dim Sheets() As String
Dim Name As String
Dim Sheet As Worksheet
Dim SheetIndex As Integer
Dim ProjectColumn As Variant
Dim TotalColumn As Variant
Dim Index As Integer
Dim Max As Long
Dim MaxRow As Long
' You'll need to put your sheet names below
' not very nice, just a way to predefine an array containing sheet names
Sheets = Split("Sheet1,Sheet2,Sheet3", ",")
' loop over all the sheets
For SheetIndex = 0 To UBound(Sheets)
' get a reference to the sheet were looking at
Set Sheet = ThisWorkbook.Worksheets(Sheets(SheetIndex))
' calculate the last row in the workbook (as using UsedRange isnt always right)
MaxRow = Sheet.Cells(Sheet.Rows.Count, 3).End(xlUp).Row
' get the data were looking for
' the 9 in the next 2 lines might be wrong, it should be the row# for the first data row
Set ProjectColumn = Sheet.Range(Sheet.Cells(9, 3), Sheet.Cells(MaxRow, 3)) ' the 9 here might be wrong!
Set TotalColumn = Sheet.Range(Sheet.Cells(9, 6), Sheet.Cells(MaxRow, 6)) ' again, 9
Max = MaxRow - 8 ' adjust the max row to account for the +8 header cells above the data
For Index = 1 To Max
' loop over all the projects in the current sheet
Project = ProjectColumn(Index, 1)
' this allows for multiple instances of the same project per sheet (no idea if this occurs in your data)
If Projects.Exists(Project) Then
If Projects(Project).Exists(Sheets(SheetIndex)) Then
' update the total
Projects(Project)(Sheets(SheetIndex)) = Projects(Project)(Sheets(SheetIndex)) + TotalColumn(Index, 1)
Else
' inclue the total for the sheet
Projects(Project).Add Sheets(SheetIndex), CLng(TotalColumn(Index, 1))
End If
Else
' new project, add it and the total value for the current sheet
'Projects.Add Project, New Scripting.Dictionary
Projects.Add Project, CreateObject("Scripting.Dictionary")
Projects(Project).Add Sheets(SheetIndex), CLng(TotalColumn(Index, 1))
End If
Next Index
Set ProjectColumn = Nothing
Set TotalColumn = Nothing
Next SheetIndex
' Projects now contains a list of all projects, and the totals for your sheets.
' Projects
' - Project Name
' - - Sheet Name - Sheet Total
' dump the data to the immediate window in the vba editor
For Each Key In Projects.Keys
For Each SubKey In Projects(Key).Keys
Debug.Print Key & ", " & SubKey & " = " & Projects(Key)(SubKey)
Next SubKey
Next Key
End Sub
Using this you'd only need to iterate over each sheet once and then one further iteration over the projects sheet to extract the required totals from the result.
My normal approach is to hold all the available data in one worksheet so I can analyse it using pivot tables. If I then need to create a non-pivot table worksheet, I then use VBA to copy and PasteSpecial the pivot table as a regular range.
If there's a really good reason to hold this data in 3 separate worksheets, I would amalgamate the 3 sheets using VBA (basically copying and pasting all the data into a single worksheet with one set of column headers), adding an extra column that contains either "Choate", "OBrien" or "Townsend" during the copy/paste process, then creating a pivot table from the resulting amalgamation.
I use this approach a lot - all my data is standardised and I can filter the pivot table as required - by date, project, manager/salesperson/creator (Choate, Townsend and O'Brien), currency, or whatever.
I'm afraid this isn't strictly speaking an answer to your question, more a suggestion of a different approach. Of course, I don't know the circumstances of how you get this data, so it may not be feasible for you.

Add new row to excel Table (VBA)

I have an excel which serves to record the food you ingest for a specific day and meal. I hav a grid in which each line represent a food you ate, how much sugar it has, etc.
Then i've added an save button to save all the data to a table in another sheet.
This is what i have tried
Public Sub addDataToTable(ByVal strTableName As String, ByRef arrData As Variant)
Dim lLastRow As Long
Dim iHeader As Integer
Dim iCount As Integer
With Worksheets(4).ListObjects(strTableName)
'find the last row of the list
lLastRow = Worksheets(4).ListObjects(strTableName).ListRows.Count
'shift from an extra row if list has header
If .Sort.Header = xlYes Then
iHeader = 1
Else
iHeader = 0
End If
End With
'Cycle the array to add each value
For iCount = LBound(arrData) To UBound(arrData)
**Worksheets(4).Cells(lLastRow + 1, iCount).Value = arrData(iCount)**
Next iCount
End Sub
but i keep getting the same error on the highlighted line:
Application-defined or object-defined error
What i am doing wrong?
Thanks in advance!
You don't say which version of Excel you are using. This is written for 2007/2010 (a different apprach is required for Excel 2003 )
You also don't say how you are calling addDataToTable and what you are passing into arrData.
I'm guessing you are passing a 0 based array. If this is the case (and the Table starts in Column A) then iCount will count from 0 and .Cells(lLastRow + 1, iCount) will try to reference column 0 which is invalid.
You are also not taking advantage of the ListObject. Your code assumes the ListObject1 is located starting at row 1. If this is not the case your code will place the data in the wrong row.
Here's an alternative that utilised the ListObject
Sub MyAdd(ByVal strTableName As String, ByRef arrData As Variant)
Dim Tbl As ListObject
Dim NewRow As ListRow
' Based on OP
' Set Tbl = Worksheets(4).ListObjects(strTableName)
' Or better, get list on any sheet in workbook
Set Tbl = Range(strTableName).ListObject
Set NewRow = Tbl.ListRows.Add(AlwaysInsert:=True)
' Handle Arrays and Ranges
If TypeName(arrData) = "Range" Then
NewRow.Range = arrData.Value
Else
NewRow.Range = arrData
End If
End Sub
Can be called in a variety of ways:
Sub zx()
' Pass a variant array copied from a range
MyAdd "MyTable", [G1:J1].Value
' Pass a range
MyAdd "MyTable", [G1:J1]
' Pass an array
MyAdd "MyTable", Array(1, 2, 3, 4)
End Sub
Tbl.ListRows.Add doesn't work for me and I believe lot others are facing the same problem. I use the following workaround:
'First check if the last row is empty; if not, add a row
If table.ListRows.count > 0 Then
Set lastRow = table.ListRows(table.ListRows.count).Range
For col = 1 To lastRow.Columns.count
If Trim(CStr(lastRow.Cells(1, col).Value)) <> "" Then
lastRow.Cells(1, col).EntireRow.Insert
'Cut last row and paste to second last
lastRow.Cut Destination:=table.ListRows(table.ListRows.count - 1).Range
Exit For
End If
Next col
End If
'Populate last row with the form data
Set lastRow = table.ListRows(table.ListRows.count).Range
Range("E7:E10").Copy
lastRow.PasteSpecial Transpose:=True
Range("E7").Select
Application.CutCopyMode = False
Hope it helps someone out there.
I had the same error message and after lots of trial and error found out that it was caused by an advanced filter which was set on the ListObject.
After clearing the advanced filter .listrows.add worked fine again.
To clear the filter I use this - no idea how one could clear the filter only for the specific listobject instead of the complete worksheet.
Worksheets("mysheet").ShowAllData
I actually just found that if you want to add multiple rows below the selection in your table
Selection.ListObject.ListRows.Add AlwaysInsert:=True works really well. I just duplicated the code five times to add five rows to my table
I had the same problem before and i fixed it by creating the same table in a new sheet and deleting all the name ranges associated to the table, i believe whene you're using listobjects you're not alowed to have name ranges contained within your table hope that helps thanks
Ran into this issue today (Excel crashes on adding rows using .ListRows.Add).
After reading this post and checking my table, I realized the calculations of the formula's in some of the cells in the row depend on a value in other cells.
In my case of cells in a higher column AND even cells with a formula!
The solution was to fill the new added row from back to front, so calculations would not go wrong.
Excel normally can deal with formula's in different cells, but it seems adding a row in a table kicks of a recalculation in order of the columns (A,B,C,etc..).
Hope this helps clearing issues with .ListRows.Add
As using ListRow.Add can be a huge bottle neck, we should only use it if it can’t be avoided.
If performance is important to you, use this function here to resize the table, which is quite faster than adding rows the recommended way.
Be aware that this will overwrite data below your table if there is any!
This function is based on the accepted answer of Chris Neilsen
Public Sub AddRowToTable(ByRef tableName As String, ByRef data As Variant)
Dim tableLO As ListObject
Dim tableRange As Range
Dim newRow As Range
Set tableLO = Range(tableName).ListObject
tableLO.AutoFilter.ShowAllData
If (tableLO.ListRows.Count = 0) Then
Set newRow = tableLO.ListRows.Add(AlwaysInsert:=True).Range
Else
Set tableRange = tableLO.Range
tableLO.Resize tableRange.Resize(tableRange.Rows.Count + 1, tableRange.Columns.Count)
Set newRow = tableLO.ListRows(tableLO.ListRows.Count).Range
End If
If TypeName(data) = "Range" Then
newRow = data.Value
Else
newRow = data
End If
End Sub
Just delete the table and create a new table with a different name. Also Don't delete entire row for that table. It seems when entire row containing table row is delete it damages the DataBodyRange is damaged

Excel VBA - Compare worksheet rows based off of value

Similar issue to these:
Find the differences between 2 Excel worksheets?
Compare two excel sheets
My issue specifically, I have a monthly employee listing with a unique ID and around 30 columns of other data for around 900 employees.
I'm trying to accomplish two things:
Compare if employees were added or dropped between the lists.
Between the sheets for each employee compare what other data for that employee changed. i.e. Job Title changed.
Most compare add-ins/modules I find only compare the specific ranges in order, thus once once difference if found every subsequent row will be different.
First, I'm wondering if there are any existing tools that can do this. If not I was thinking of building my own. I was thinking of doing this by looping through each employee and using vlookup to verify matches. I'm concerned doing this many loops will make the macro difficult to use. Any guidance on how I should go about this? Thanks.
Untested, but will give you a place to start from...
This does not find ex-employees which are on the "old" sheet but not on the "current" sheet.
Sub CompareEmployeeInfo()
Const ID_COL As Integer = 1 ' ID is in the first column
Const NUM_COLS As Integer = 30 'how many columns are being compared?
Dim shtNew As Excel.Worksheet, shtOld As Excel.Worksheet
Dim rwNew As Range, rwOld As Range, f As Range
Dim x As Integer, Id
Dim valOld, valNew
Set shtNew = ActiveWorkbook.Sheets("Employees")
Set shtOld = ActiveWorkbook.Sheets("Employees")
Set rwNew = shtNew.Rows(2) 'first employee on "current" sheet
Do While rwNew.Cells(ID_COL).Value <> ""
Id = rwNew.Cells(ID_COL).Value
Set f = shtOld.UsedRange.Columns(ID_COL).Find(Id, , xlValues, xlWhole)
If Not f Is Nothing Then
Set rwOld = f.EntireRow
For x = 1 To NUM_COLS
If rwNew.Cells(x).Value <> rwOld.Cells(x).Value Then
rwNew.Cells.Interior.Color = vbYellow
Else
rwNew.Cells.Interior.ColorIndex = xlNone
End If
Next x
Else
rwNew.Cells(ID_COL).Interior.Color = vbGreen 'new employee
End If
Set rwNew = rwNew.Offset(1, 0) 'next row to compare
Loop
End Sub
Don't know if there is anything that does that for you or not. But, you can use the Dictionary Object to make this comparison task much easier. You can also take examples from this answer that uses Dictionaries which checked for uniques and is optimized for speed, change it to what you need. Then you can use this fast method to color the cells or whatever you want to do with it.
I know I'm not providing code for you but these pointers will get you started, and if you have more questions I can help you out.