searching for matches between two sheets and copying specific values from specific column - excel

i have 2 sheets , in sheet1 i have a column with article names(im geeting my names from sheet1) , in sheet 2 i have a column like that two "Nom de l'entité" (doing a search by header in sheet 2), if i find a match in sheet 2 , i look for a column called "longueur" and copy the value and put it in the offset(0,1) of the article name in sheet 1 . Im a beginner but this is what i did so far.I need to loop through all the article names hoping to fin them all in sheet 2 . Here's a link of photo to see what im trying to do exactly : https://postimg.cc/pmLY9dXc
Sub longueur()
Dim ws As Worksheet: Set ws = ThisWorkbook.Sheets("Lecture") '<== Sheet that has raw data
Dim wss As Worksheet: Set wss = ThisWorkbook.Sheets("Feuil1") 'sheet that we re gonna paste longueur into
Dim FoundName As Range, FoundLongueur As Range
Dim c As Range
Set FoundName = ws.Range("A1:DS1").Find("NOM DE L'ENTITÉ") '<== Header name to search for
Set FoundLongueur = ws.Range("A1:DS1").Find("LONGUEUR") '<== Header name to search for in case we already found name match
If Not FoundName Is Nothing And Not FoundLongueur Is Nothing Then
For Each c In Range(wss.Cells.Range("D:D")) 'go back to sheet1 to get the names to search for
If c.value = FoundName Then
FoundLongueur.Offset(0, 1).value
End If
Next c
End If
End Sub

Try
Option Explicit
Sub longueur()
Dim wb As Workbook, ws1 As Worksheet, ws2 As Worksheet
Dim rngName As Range, rng As Range, c As Range
Dim colLongueur As Integer, iLastRow As Long
Set wb = ThisWorkbook
Set ws1 = wb.Sheets("Feuil1") 'sheet that we re gonna paste longueur into
Set ws2 = wb.Sheets("Lecture") '<== Sheet that has raw data
' find column NOM DE L'ENTITÉ on sheet 2
Set rng = ws2.Range("A1:DS1").Find("NOM DE L'ENTITÉ")
If rng Is Nothing Then
MsgBox "Could not find 'NOM DE L'ENTITÉ' on " & ws2.Name, vbCritical
Exit Sub
End If
' expand to end of column
Set rngName = ws2.Range(rng, ws2.Cells(Rows.Count, rng.Column).End(xlUp))
' find column LONGUEUR on sheet 2
Set rng = ws2.Range("A1:DS1").Find("LONGUEUR")
If rng Is Nothing Then
MsgBox "Could not find 'LONGUEUR' on " & ws2.Name, vbCritical
Exit Sub
End If
colLongueur = rng.Column
' scan sheet 1 col D
iLastRow = ws1.Cells(Rows.Count, "D").End(xlUp).Row
For Each c In ws1.Range("D1:D" & iLastRow)
' find name on sheet 2
Set rng = rngName.Find(c.Value, LookIn:=xlValues, LookAt:=xlWhole)
If rng Is Nothing Then
c.Offset(0, 1).Value = "No Match"
Else
' copy value from column LONGUEUR
c.Offset(0, 1).Value = ws2.Cells(rng.Row, colLongueur)
End If
Next
MsgBox "Ended"
End Sub

Related

Find column based on header and remove first 3 characters starting from 2 row

I need help to remove character from a column with particular header.
I have a spreadsheet with headers (IP, hostname, Asset Group). I need to remove the first 3 characters from each row of the column called "Asset Group" (excluding header name (row 1)). Basically, I want to get rid of the "VM " from that column. I have a problem how to refer to that particular column "Asset Group". Thank you in advance!
Dim SelRange As Range
Dim ColNum As Integer
Dim CWS As Worksheet
'Find the column number where the column header is Asset Group
Set CWS = ActiveSheet
ColNum = Application.WorksheetFunction.Match("Asset Group", CWS.Rows(1), 0)
LastColumn = Cells(1, CWS.Columns.Count).End(xlToLeft).Column
For i = 2 To LastColumn
...
Next i
End With
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
You can try something like the following
Dim CWS As Worksheet
Dim AssetHdr as Range
Dim tmp as Variant
Dim i as Long
Set CWS = ActiveSheet
' Find Header Column
Set AssetHdr = CWS.Rows(1).Find(what:="Asset Group")
' Test if Header was found
If Not AssetHdr is Nothing Then
With CWS
' Get Last Row in Column
NoRow = .Cells(.Rows.Count, AssetHdr.Column).End(xlUp).Row
' Store in array
tmp = Application.Transpose(.Range(.Cells(2, AssetHdr.Column), .Cells(NoRow, AssetHdr.Column))).Value2
' Remove first 3 characters
For i = LBound(tmp) to UBound(tmp)
tmp(i) = Right(tmp(i), Len(tmp(i))-3)
Next i
' Write back to sheet
.Cells(2, AssetHdr.Column).Resize(ubound(tmp)-1).Value2 = tmp
End With
End If
Replace Partial Strings in a Range
Application.Match allows you to test its result with IsError or IsNumeric, while WorksheetFunction.Match raises an error if no match.
With the Range.Replace method you can replace values in a range in one go.
Option Explicit
Sub ReplacePartialString()
Dim cws As Worksheet: Set cws = ActiveSheet
Dim ColNum As Variant
ColNum = Application.Match("Asset Group", cws.Rows(1), 0)
If IsError(ColNum) Then
MsgBox "Column 'Asset Group' not found.", vbCritical
Exit Sub
End If
Dim LastCell As Range
Set LastCell = cws.Cells(cws.Rows.Count, ColNum).End(xlUp)
If LastCell.Row < 2 Then
MsgBox "No data found.", vbCritical
Exit Sub
End If
Dim crg As Range: Set crg = cws.Range(cws.Cells(2, ColNum), LastCell)
crg.Replace "VM ", "", xlPart, , True
End Sub
I was able to figure it out how to do it, the way I started. Thanks for the answer #VBasic2008, you created a better one with catching errors.
Dim CWS As Worksheet
Set CWS = ActiveSheet
ColNum = Application.WorksheetFunction.Match("Asset Group", CWS.Rows(1), 0)
With CWS
LR = .Cells(.Rows.Count, ColNum).End(xlUp).Row
End With
For i = 2 To LR
CWS.Cells(i, ColNum) = Right(CWS.Cells(i, ColNum).Value, Len(CWS.Cells(i, ColNum).Value) - 3)
Next i

Selectively copy and paste rows with given criteria

I am trying to select rows in a table based on the word "Yes" being present in column J.
I have a table going from column A to J, and I want to select the rows where there is a "Yes" in column J and paste only those rows into a new sheet.
Once selected, I need to copy these rows to a new sheet or word document.
I have tried a range of forumulas, this is for Windows MS Excel software, using a VBA Macro.
I am using the following VBA, but having issues:
Sub Macro1()
Dim rngJ As Range
Dim cell As Range
Set rngJ = Range("J1", Range("J65536").End(xlUp))
Set wsNew = ThisWorkbook.Worksheets.Add
For Each cell In rngJ
If cell.Value = "Yes" Then
cell.EntireRow.Copy
wsNew.Sheets("Sheet1").Range("J65536").End(xlUp).Offset(1, 0).Select
ActiveSheet.Paste
End If
Next cell
End Sub
Any help would be very much appreciated!
Rather than finding, copying and pasting for each cell, why not find all, then copy and paste once like this:
Sub Macro1()
Dim rngJ As Range
Dim MySel As Range
Set rngJ = Range("J1", Range("J" & Rows.Count).End(xlUp))
Set wsNew = ThisWorkbook.Worksheets.Add
For Each cell In rngJ
If cell.Value = "Yes" Then
If MySel Is Nothing Then
Set MySel = cell.EntireRow
Else
Set MySel = Union(MySel, cell.EntireRow)
End If
End If
Next cell
If Not MySel Is Nothing Then MySel.Copy Destination:= wsNew.Range("A1")
End Sub
It's better to avoid using Select as much as possible; see this link.
Use something like this
Option Explicit
Public Sub CopyYesRowsToNewWorksheet()
Dim wsSource As Worksheet
Set wsSource = ThisWorkbook.ActiveSheet 'better define sheet by name ThisWorkbook.Worksheets("SourceSheet")
Dim DataRangeJ As Variant 'read "yes" data into array for faster access
DataRangeJ = wsSource.Range("J1", wsSource.Range("J" & wsSource.Rows.Count).End(xlUp)).Value
Dim wsNew As Worksheet
Set wsNew = ThisWorkbook.Worksheets.Add
Dim NextFreeRow As Long
NextFreeRow = 1 'start pasting in this row in the new sheet
If IsArray(DataRangeJ) Then
Dim iRow As Long
For iRow = LBound(DataRangeJ) To UBound(DataRangeJ) 'loop through data array
If DataRangeJ(iRow, 1) = "yes" Then
wsNew.Rows(NextFreeRow).Value = wsSource.Rows(iRow).Value 'copy the values of the row
NextFreeRow = NextFreeRow + 1
End If
Next iRow
ElseIf DataRangeJ = "yes" Then 'if only the first row has data
wsNew.Rows(NextFreeRow).Value = wsSource.Rows(1).Value
End If
End Sub
The line
wsNew.Rows(NextFreeRow).Value = wsSource.Rows(iRow).Value
only copys the value without formatting. If you also want to copy the formatting replace it with
wsSource.Rows(iRow).Copy Destination:=wsNew.Rows(NextFreeRow)

Copying data from selection of rows to different sheet based on cell string start and end

I have my data in columns A:L in Sheet2 and wish to copy each block based on the starting point, as certain cell text and the end point, again as certain cell text!
So in the example the cell start text should be "Tank Engine" and the cell end text would be "INFORMATION: Tank Engine". Therefore, column A:L, rows 1:18 should be copied into Sheet3 at cell A1, but only where the cell text exists as this can be dynamic. I need to reference column A to paste to in Sheet3, and copy only the rows that begin with "Tank Engine" and end with "INFORMATION: Tank Engine", which are rows 1:18. The next block would be Columns A:L, rows 25:41 based on the string "Weatherman" and this being pasted into Sheet3 Cell M:X etc.....
The rows are dynamic the columns are static..... I have tried many many snippets of VBA but this is quite particular so cannot find a good match!!
Sub Mike4()
Dim i As Long
lastcolumn = Cells(1, Columns.Count).End(xlToLeft).Column
For i = 1 To lastcolumn
If Cells(1, i) = "Tank Engine" Then
'lastrow = Columns(i).SpecialCells(xlLastCell).Row
lastRow = Columns(i).Find("INFORMATION: Tank Engine").Row
Range(Cells(2, i), Cells(lastRow, i)).Copy Sheet3.Range("A" & Sheet3.Range("A" & Rows.Count).End(xlUp).Row + 1)
End If
Next i
End Sub
I am trying to get the above to then paste the columns with the rows affected into a specific cell then to search for Weatherman as described above but need a starting point that something is working then be able to build on that...As stated previously I have lots of snippets of code but none accumulatively work for what I want to achieve if at all. Any help would be greatly appreciated!! Thanks in advance...Many Thanks!!
Look at this example:
Option Explicit
Sub CopyMyStuff()
Dim wsSrc As Worksheet
Set wsSrc = ThisWorkbook.Worksheets("SourceSheet")
Dim wsDest As Worksheet
Set wsDest = ThisWorkbook.Worksheets("Sheet3")
'find start
Dim FoundStart As Range
Set FoundStart = wsSrc.Range("A:L").Find(What:="Tank Engine", LookAt:=xlWhole)
If FoundStart Is Nothing Then
MsgBox "start not found"
Exit Sub
End If
'find end
Dim FoundEnd As Range
Set FoundEnd = wsSrc.Range("A:L").Find(What:="INFORMATION: Tank Engine", LookAt:=xlWhole, After:=FoundStart)
If FoundEnd Is Nothing Then
MsgBox "start not found"
Exit Sub
End If
wsSrc.Range(FoundStart, FoundEnd).Resize(ColumnSize:=12).Copy wsDest.Range("A1")
End Sub
Or more elegant with a function:
Option Explicit
Sub CopyMyStuff2()
Dim wsSrc As Worksheet 'define source
Set wsSrc = ThisWorkbook.Worksheets("SourceSheet")
Dim wsDest As Worksheet 'define destination
Set wsDest = ThisWorkbook.Worksheets("Sheet3")
Dim FindList As Variant 'defind search words
FindList = Array("Tank Engine", "Weatherman")
Dim i As Long
Dim FindItm As Variant
For Each FindItm In FindList
Dim CopyRange As Range
Set CopyRange = FindMyRange(wsSrc.Range("A:L"), FindItm, "INFORMATION: " & FindItm)
If Not CopyRange Is Nothing Then
CopyRange.Copy wsDest.Range("A1").Offset(ColumnOffset:=i) 'note that if the first column uses merged cells the ColumnOffset:=i otherwise it is ColumnOffset:=i*12
i = i + 1
End If
Next FindItm
End Sub
Function FindMyRange(SearchInRange As Range, ByVal StartString As String, ByVal EndString As String) As Range
'find start
Dim FoundStart As Range
Set FoundStart = SearchInRange.Find(What:=StartString, LookAt:=xlWhole)
If FoundStart Is Nothing Then GoTo ERR_NOTHING_FOUND
'find end
Dim FoundEnd As Range
Set FoundEnd = SearchInRange.Find(What:=EndString, LookAt:=xlWhole, After:=FoundStart)
If FoundEnd Is Nothing Then GoTo ERR_NOTHING_FOUND
Set FindMyRange = SearchInRange.Parent.Range(FoundStart, FoundEnd).Resize(ColumnSize:=12)
Exit Function
ERR_NOTHING_FOUND:
FindMyRange = Nothing
End Function

Loop through worksheets, paste data in another worksheet in columns with matching name

I want to merge tables from multiple Excel sheets with uncommon and common column names.
I can't get the loop to go to sheets in my workbook and paste in the combine worksheet.
For example I have the following tables:
Sheet1:
name surname color
Eva x
steven y black
Mark z white
Sheet2:
Surname color name code
L Green Pim 030
O yellow Xander 34
S Rihanna 567
My third sheet (the combine sheet) has all the possible column names of all sheets so it looks like:
name surname color code
The macro should read Sheet1 and Sheet2 then paste data in the combine sheet under the correct column name.
The combine sheet should looks like this, with the elements of Sheet2 under the elements of Sheet1:
name surname color code
Eva x
steven y black
Mark z white
Pim L Green 030
Xander O yellow 34
Rihanna S 567
I couldn't get the loop to read then paste data in the right column.
Sub CopyDataBlocks_test2()
'VARIABLE NAME 'DEFINITION
Dim SourceSheet As Worksheet 'The data to be copied is here
Dim CombineSheet As Worksheet 'The data will be copied here
Dim ColHeaders As Range 'Column headers on Combine sheet
Dim MyDataHeaders As Range 'Column headers on Source sheet
Dim DataBlock As Range 'A single column of data
Dim c As Range 'a single cell
Dim Rng As Range
'The data will be copied here (="Place holder" for the first data cell)
Dim i As Integer
'Dim WS_Count As Integer 'for all sheets in active workbook
'Dim j As Integer 'Worksheets count
'Change the names to match your sheetnames:
Set SourceSheet = Sheets(2)
Set CombineSheet = Sheets("Combine")
With CombineSheet
Set ColHeaders = .Range(.Cells(1, 1), .Cells(1, .Columns.Count).End (xlToLeft))
Set Rng = .Cells(.Rows.Count, 1).End(xlUp).Offset(1)
End With
With SourceSheet
Set MyDataHeaders = .Range(.Cells(1, 1), .Cells(1, .Columns.Count).End(xlToLeft))
For Each c In MyDataHeaders
If Application.WorksheetFunction.CountIf(ColHeaders, c.Value) = 0 Then
MsgBox "Can't find a matching header name for " & c.Value & _
vbNewLine & "Make sure the column names are the same and try again."
Exit Sub
End If
Next c
'A2:A & the last cell with something on it on column A
Set DataBlock = .Range(.Cells(2, 1), .Cells(.Rows.Count, 1).End(xlUp))
Set Rng = Rng.Resize(DataBlock.Rows.Count, 1)
For Each c In MyDataHeaders
i = Application.WorksheetFunction.Match(c.Value, ColHeaders, 0)
'Writes the values
Rng.Offset(, i - 1).Value = Intersect(DataBlock.EntireRow, c.EntireColumn).Value
Next c
End With
End Sub
you just wrap your With SourceSheet - End With block code into a For each sourceSheet in Worksheets - Next loop checking not to process "Combine" sheet itself
it'd be cleaner to move that into a helper Sub like follows:
Option Explicit
Sub CopyDataBlocks_test2()
'VARIABLE NAME 'DEFINITION
Dim sourceSheet As Worksheet 'The data to be copied is here
Dim ColHeaders As Range 'Column headers on Combine sheet
With Worksheets("Combine") '<--| data will be copied here
Set ColHeaders = .Range(.Cells(1, 1), .Cells(1, .Columns.Count).End(xlToLeft))
For Each sourceSheet In Worksheets '<--| loop through all worksheets
If sourceSheet.Name <> .Name Then ProcessSheet sourceSheet, ColHeaders, .Cells(.Rows.Count, 1).End(xlUp).Offset(1) '<--| process data if not "Combine" sheet
Next
End With
End Sub
Sub ProcessSheet(sht As Worksheet, ColHeaders As Range, rng As Range)
Dim MyDataHeaders As Range 'Column headers on Source sheet
Dim c As Range 'a single cell
Dim i As Integer
Dim DataBlock As Range 'A single column of data
With sht
Set MyDataHeaders = .Range(.Cells(1, 1), .Cells(1, .Columns.Count).End(xlToLeft))
For Each c In MyDataHeaders
If Application.WorksheetFunction.CountIf(ColHeaders, c.Value) = 0 Then
MsgBox "In worksheet " & .Name & " can't find a matching header name for " & c.Value & vbNewLine & "Make sure the column names are the same and try again."
Exit Sub
End If
Next c
Set DataBlock = .Range(.Cells(2, 1), .Cells(.Rows.Count, 1).End(xlUp)) 'A2:A & the last cell with something on it on column A
For Each c In MyDataHeaders
i = Application.WorksheetFunction.Match(c.Value, ColHeaders, 0)
rng.Offset(, i - 1).Resize(DataBlock.Rows.Count, 1).Value = DataBlock.Columns(c.Column).Value 'Writes the values
Next c
End With
End Sub

Extracting Data from Excel Database

I've got a database with a long list of names, and unique values associated with the names. What I want to do is create one worksheet for each individual, and then copy only their data to a specified range in their worksheet, then proceed to the next individual, copy their data to their worksheet etc.
Here is a link to an example worksheet (in google docs form, note - I am actually using Excel 2010, not google docs).
I've been able to create all the worksheets through using the following code in a new sheet I called "Employee". All I did to this sheet was remove the duplicate name values so I could have a list of all the names for the worksheets.
Any help is much appreciated. Thanks in advance.
Sub CreateSheetsFromAList()
Dim nameSource As String 'sheet name where to read names
Dim nameColumn As String 'column where the names are located
Dim nameStartRow As Long 'row from where name starts
Dim nameEndRow As Long 'row where name ends
Dim employeeName As String 'employee name
Dim newSheet As Worksheet
nameSource = "Employee"
nameColumn = "A"
nameStartRow = 1
'find the last cell in use
nameEndRow = Sheets(nameSource).Cells(Rows.Count, nameColumn).End(xlUp).Row
'loop till last row
Do While (nameStartRow <= nameEndRow)
'get the name
employeeName = Sheets(nameSource).Cells(nameStartRow, nameColumn)
'remove any white space
employeeName = Trim(employeeName)
' if name is not equal to ""
If (employeeName <> vbNullString) Then
On Error Resume Next 'do not throw error
Err.Clear 'clear any existing error
'if sheet name is not present this will cause error that we are going to leverage
Sheets(employeeName).Name = employeeName
If (Err.Number > 0) Then
'sheet was not there, so it create error, so we can create this sheet
Err.Clear
On Error GoTo -1 'disable exception so to reuse in loop
'add new sheet
Set newSheet = Sheets.Add(After:=Sheets(Sheets.Count))
'rename sheet
newSheet.Name = employeeName
'paste training material
Sheets(employeeName).Cells(1, "A").PasteSpecial
Application.CutCopyMode = False
End If
End If
nameStartRow = nameStartRow + 1 'increment row
Loop
End Sub
Bare bones approach - could be optimized for better performance, but it will do the job.
Sub SplitToSheets()
Dim c As Range, ws As Worksheet, rngNames
With ThisWorkbook.Sheets("EmployeeData")
Set rngNames = .Range(.Range("A1"), .Cells(Rows.Count, 1).End(xlUp))
End With
For Each c In rngNames.Cells
Set ws = GetSheet(ThisWorkbook, c.Value)
c.EntireRow.Copy ws.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0)
Next c
End Sub
Function GetSheet(wb As Workbook, wsName As String, _
Optional CreateIfMissing As Boolean = True) As Worksheet
Dim ws As Worksheet
On Error Resume Next
Set ws = wb.Sheets(wsName)
On Error GoTo 0
If ws Is Nothing And CreateIfMissing Then
Set ws = wb.Sheets.Add(after:=wb.Sheets(wb.Sheets.Count))
ws.Name = wsName
End If
Set GetSheet = ws
End Function

Resources