updating column and row values of the list which has duplicate values - vba

I have merged variable amount of worksheets which are called anything includes the word "data" through this code;
Dim masterSheet As Worksheet
Set masterSheet = Sheets("Komko")
'Variable to save the used Range of the master sheet
Dim usedRangeMaster As Integer
Dim ws As Worksheet
'loop through each worksheet in current workbook
For Each ws In Worksheets
'If sheetname contains "data" (UCase casts the Name to upper case letters)
If InStr(1, UCase(ws.Name), "DATA", vbTextCompare) > 0 Then
'calculate the used range of the master sheet
usedRangeMaster = masterSheet.UsedRange.SpecialCells(xlCellTypeLastCell).Row + 1
'Variable to save the used Range of the sub sheet
Dim usedRangeSub As Integer
'calculate the used range of the sub sheet
usedRangeSub = ws.UsedRange.SpecialCells(xlCellTypeLastCell).Row
'copy relevant range from the subsheet
ws.Range("C1:C" & usedRangeSub).Copy
'paste the copied range after the used range in column a
masterSheet.Range("A" & usedRangeMaster).PasteSpecial
End If
Next ws
This code copies the C column of the "data" including Sheets and then pastes it to my master Sheets( which is called "Komko") Column A. Now i would like identify the same values in Column C and delete the complete row of the previous matching value. (e.g if C1 has value "123" and if C7 has value "123" the whole row which includes C1 should automatically be deleted)
How can i do this ?

See http://analysistabs.com/vba/find-duplicate-values-column/ to find your duplicate entries and Delete a row in Excel VBA to get some ideas how to delete the row in a good way.
Start searching after you merged your column C. Use a Boolean variable to skip the first found entry if necessary. Replace the code Cells(iCntr, 2) = "Duplicate" from the first link and put your way of deleting the row there.

Related

Find a sheet based on a cell name, then find the entry based on a different cell name, and fill in the values from adjacent cells

I'm pretty new to VBA, I've got a spread sheet that has a list of vehicle ID's in a row of columns, and different identifiers (ID) in column A.
So far I'm able to search for the sheet with the vehicle name and copy a range of cells to the main sheet. I'm trying to make it so that once it finds the specific vehicle sheet, it looks for the specific ID and pulls that in, rather than copy a set range of cells. I'm having it return nothing now, and when I had it before excel would crash, so I assumed I was in some sort of endless loop.
Dim ws As Worksheet, sh As Worksheet
Dim Rng As Range, c As Range
Dim ECU_Ovv As Range, ECU_V As Range
Set ws = Sheets("Overview") 'main worksheet to copy everything to
Set Rng = ws.Cells(3, 3).Resize(3, LastColumn) ' I;ve calculated LastColumn earlier, it's defined as a Long
Set ECU_Ovv = ws.Cells(5, 2).Resize(LastRow, 2)
For Each sh In Sheets
For Each c In Rng.Cells
If sh.Name = c Then
'Find row range for specific vehicle
LastRow = sh.Cells(Rows.Count, 2).End(xlUp).Row
Set ECU_V = sh.Cells(5, 2).Resize(LastRow, 2) ' this is the only syntax I could figure out to get it to let me set a range with a calculated variable
For Each ECU_Ovv In ECU_V.Cells 'now look for the ID in the specific sheet
If ECU_Ovv.Cells = ECU_V.Cells Then
a = ECU_Ovv.Value 'Put this here to see if I am able to match ID's from the main sheet to the specific sheet
'sh.Range("D12:D47").Copy Destination:=ws.Cells(24, c.Column) 'this was working but it's hardcoded so any change in the sheets would break it
End If
Next ECU_Ovv
End If
Next c
Next sh
I'm planning on adding a copy cell, 2 columns over (from the found ID) to the column of the vehicle (Rng), but I'll cross that bridge when I get there!

A code which copies data from a range in one tab to another, however every time the code is run it copies the data the row below. Excel VBA question

My data range needs to be copied from one tab to another. The key to this is it needs to paste the information in the data range into a new row, even if the information is the same. So each time it is run a new row will be populated. Another key here is the row data range consists of criteria, depending on the value of criteria the code will decide which tab to copy into.
I was able to create the code to copy but without if statement and it copies into the same row each time
if Cell E3 = "Revenue" then copy into Revenue worksheet, if not then copy into Cost worksheet.
Each time code is run, the data will be copied into the last unoccupied row available in that worksheet
If I understood You right, this should work:
Sub copy2sheet()
Dim cond As String
Dim lastRow As Integer
With Sheets(ActiveSheet.Name)
'taking name of the sheet from "E3"
cond = .Range("E3").Value
'checking last filled row in sheet we gonna copy data
lastRow = Sheets(cond).Cells(Rows.Count, 1).End(xlUp).row
'copy data starting from "A1" to every cell is close to - CurrentRegion
'a paste it into first empty cell in column "A"
'.Range("A1").CurrentRegion.Copy Sheets(cond).Range("A" & lastRow + 1)
.Range("E3:H3").Copy Sheets(cond).Range("A" & lastRow + 1)
End With
End Sub

Copy/Paste rows to matching named sheet

I have a worksheet "List" which has rows of data that I need to copy to other worksheets. In column "J" of "List", there is a name (Matthew, Mark, Linda, etc.) that designates who's data that row is.
Each of those names (22 in all) has a matching spreadsheet with the same name. I want all rows that say "Linda" in column "J" to paste to worksheet "Linda", all rows with "Matthew" to paste to worksheet "Matthew", etc.
I have some code below, which mostly works, but I'd have to rewrite it for all 22 names/sheets.
Is there a way to loop through all the sheets, pasting the rows with matching names? Also, the code below works really slowly, and I'm using data sets with anywhere from 200 to 60,000 rows that need sorted and pasted, which means that if its slow on a small data set like the one I'm currently working on, and only for one sheet, it's going to be glacially slow for the big data sets.
Sub CopyMatch()
Dim c As Range
Dim j As Integer
Dim Source As Worksheet
Dim Target As Worksheet
Set Source = Worksheets("List")
Set Target = Worksheets("Linda")
j = 4 ' Start copying to row 1 in target sheet
For Each c In Source.Range("J4:J1000") ' Do 1000 rows
If c = "Linda" Then
Source.Rows(c.Row).Copy Target.Rows(j)
j = j + 1
End If
Next c
End Sub
Unless you've turned calculation off somewhere we can't see here, then every time you copy a row, Excel is recalculating - even if your sheets contain no formulas.
If you're not doing so already, simply putting:
application.calculation=xlcalculationmanual
before you start your loop and:
application.calculation=xlcalculationautomatic
after exiting the loop will massively speed up your loop. For extra swank, you can use a variable to store the calculation setting before you turn it off and restore that setting at the end, e.g.
dim lCalc as long
lCalc = application.calculation
application.calculation = xlcalculationmanual
for ... next goes here
application.calculation = lCalc
Also consider other settings, e.g.: application.screenupdating=False|True.
Sort the data by the name you're selecting on, then by any other sorts you want. That way you can skip through any size sheet in 22 steps (since you say you have 22 names).
How you copy the data depends on preference and how much data there is. Copying one row at a time is economical on memory and pretty much guaranteed to work, but is slower. Or you can identify the top and bottom rows of each person's data and copy the whole block as a single range, at the risk of exceeding the memory available on large blocks in large sheets.
Assuming the value in your name column, for the range you're checking, is always one of the 22 names, then if you've sorted first by that column you can use the value in that column to determine the destination, e.g.:
dim sTarget as string
dim rng as range
sTarget = ""
For Each c In Source.Range("J4:J1000") ' Do 1000 rows
if c <> "" then ' skip empty rows
if c <> sTarget then ' new name block
sTarget = c
Set Target = Worksheets(c)
set rng = Target.cells(Target.rows.count, 10).end(xlup) ' 10="J"
j = rng.row + 1 ' first row below last name pasted
end if
Source.Rows(c.Row).Copy Target.Rows(j)
j = j + 1
end if
Next
This is economical of memory because you're going row by row, but still reasonably fast because you're only recalculating Target and resetting j when the name changes.
you could use:
Dictionary object to quickly build the list of unique names out of column J names
AutoFilter() method of Range object for filtering on each name:
as follows
Option Explicit
Sub CopyMatch()
Dim c As Range, namesRng As Range
Dim name As Variant
With Worksheets("List") '<--| reference "List" worskheet
Set namesRng = .Range("J4", .Cells(.Rows.count, "J").End(xlUp)) '<--| set the range of "names" in column "J" starting from row 4 down to last not empty row
End With
With CreateObject("Scripting.Dictionary") '<--| instance a 'Dictionary' object
For Each c In namesRng.SpecialCells(xlCellTypeConstants, xlTextValues) '<--| loop through "names" range cells with text content only
.item(c.Value) = c.Value '<--| build the unique list of names using dictionary key
Next
Set namesRng = namesRng.Resize(namesRng.Rows.count + 1).Offset(-1) '<--| resize the range of "names" to have a "header" cell (not a name to filter on) in the first row
For Each name In .Keys '<--| loop through dictionary keys, i.e. the unique names list
FilterNameAndCopyToWorksheet namesRng, name '<--| filter on current name and copy to corresponding worksheet
Next
End With '<--| release the 'Dictionary' object
End Sub
Sub FilterNameAndCopyToWorksheet(rangeToFilter As Range, nameToFilter As Variant)
Dim destsht As Worksheet
Set destsht = Worksheets(nameToFilter) '<--| set the worksheet object corresponding to passed name
With rangeToFilter
.AutoFilter Field:=1, Criteria1:=nameToFilter
Intersect(.Parent.UsedRange, .Resize(.Rows.count - 1).Offset(1).SpecialCells(xlCellTypeVisible).EntireRow).Copy destsht.Cells(destsht.Rows.count, "J").End(xlUp)
.Parent.AutoFilterMode = False
End With
End Sub

VBA compare 2 worksheets and extract entire work if there is a match in a column

I receive a monthly aging report. I need to compare these 2 reports to find out what items appear on each of the reports. I need a VBA to look at Column B of both sheets and if there is a match, extract those rows only. In addition, I need a vba to find out if something has changed. For those that are not familiar with aging report, this reports tells me how far the customer is past due in paying me. So if customer 1, was in the Aging 0-30 (Column S) on report pulled on 20151023, then on the report pulled 20160223, this customer should be in Aging 90-120 (Column V). I'm thinking the best way to display this information is to display matched data with no changes in the No Changes Sheet. Then, in the sheet called Changes, I would like to display about 6 columns of information: Report Date, Dealr, Contract Number, Status, Aging History, & AR Amount. The Aging History will tell me what bucket this customer was on when the report was pulled. This information will come from the column headings (S-X). The AR Amount will be the amount appearing in that column. I will try to upload a sample.
The following gives you a way to compare the same column in two sheets. The first way looks for a matching value anywhere in the second sheet's column, the second method only returns a match if the matching cells are on the same row in both sheets
Sub CompareSheets(sheet1 As Worksheet, sheet2 As Worksheet, columnNumber As Long)
Dim ws1 As Worksheet, ws2 As Worksheet
Dim ws1Data As Range, ws2Data As Range
Dim col As Long
Dim i As Integer
Dim cell1 As Range, cell2 As Range
Set ws1 = sheet1
Set ws2 = sheet2
col = columnNumber
ws1Data = ws1.Columns(col).Cells
ws2Data = ws2.Columns(col).Cells
Find a match anywhere in either column
' XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
' This code will find any match between the two sheets
' XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
'Checks each cell in the target column of sheet 1
For Each cell1 In ws1Data
'Checks each cell in the target column of sheet 2
For Each cell2 In ws2Data
'If the cell from sheet 1 matches any cell in sheet 2 then do stuff
If cell1 = cell2 Then
'Do stuff with the data here
End If
Next cell2
Next cell1
' XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
' XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Find a match only if the matching cells are on the same row
' ////////////////////////////////////////////////////////
' This code will find a match ONLY if both entries are
' on the same row in their respective sheets
' ////////////////////////////////////////////////////////
'Checks each cell in the target column of sheet 1
For Each cell1 In ws1Data
'Checks each cell in the target column of sheet 2
For Each cell2 In ws2Data
'If the cell from sheet 1 matches any cell in sheet 2
'AND there are on the same row in both sheets then do stuff
If (cell1 = cell2) And (cell1.Row = cell2.Row) Then
'Do stuff with the data here
End If
Next cell2
Next cell1
' /////////////////////////////////////////////////////////
' /////////////////////////////////////////////////////////
End Sub
Then you can make a button or macro that calls the sub
Call CompareSheets(firstworksheet, secondworksheet, 2) '2 is the column number for B
A proper example
Call CompareSheets(Worksheets(1), Worksheets(2), 2)
As for what you want to do with the matches once they're located, that's really for another post.

How to copy entire row from one sheet with specific value to another sheet (in different workbook)using macros

As a beginner in field of macros, I need advise on how to copy/paste an entire row if column R has value = "YES", from sheet "database", to the next available blank row in sheet2.
Also Sheet2 is another file/workbook at location "C:\Users\Desktop\KPIs"
Example assumes the workbook you want to paste to is already open.
If R1 is "YES" then it copies row 3 to row 3 in the Target workbook
Sub CopyRow()
Dim copyRng As Range
If Worksheets("Database").Range("R1") = "YES" Then
Worksheets("Database").Range("A3").EntireRow.Copy Destination:=Workbooks("Target").Worksheets("Sheet1").Range("A3")
End If
End Sub