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

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

Related

How to copy specific ranges into a new worksheet in VBA?

I'm trying to create a macro that will compile specific columns from all worksheets in a workbook into a single new worksheet.
What I have so far creates the new sheet, and returns the correct headers for each column, but copies across all columns from the existing sheets rather than just the columns I have specified.
As can be seen with the column headings, I would like to only copy the values in columns A:I, K:M, R and W:Y from sheets 2 onwards, into columns B:O in the "MASTER" worksheet.
Does anyone have any suggestions as to how I can get this working?
Sub Combine2()
Dim J As Integer, wsNew As Worksheet
Dim rngCopy As Range, rngPaste As Range
Dim Location As String
On Error Resume Next
Set wsNew = Sheets("MASTER")
On Error GoTo 0
'if sheet does not already exist, create it
If wsNew Is Nothing Then
Set wsNew = Worksheets.Add(Before:=Sheets(1)) ' add a sheet in first place
wsNew.Name = "MASTER"
End If
'copy headings and paste to new sheet starting in B1
With Sheets(2)
.Range("A1:I1").Copy wsNew.Range("B1")
.Range("R1").Copy wsNew.Range("K1")
.Range("K1:M1").Copy wsNew.Range("L1")
.Range("W1:Y1").Copy wsNew.Range("O1")
End With
' work through sheets
For J = 2 To Sheets.Count ' from sheet 2 to last sheet
'save sheet name/location to string
Location = Sheets(J).Name
'set range to be copied
With Sheets(J).Range("A1").CurrentRegion
Set rngCopy = .Offset(1, 0).Resize(.Rows.Count - 1)
End With
'set range to paste to, beginning with column B
Set rngPaste = wsNew.Cells(Rows.Count, 2).End(xlUp).Offset(1, 0)
'copy range and paste to column *B* of combined sheet
rngCopy.Copy rngPaste
'enter the location name in column A for all copied entries
Range(rngPaste, rngPaste.End(xlDown)).Offset(0, -1) = Location
Next J
With Sheets(1)
Range("A1").Value = "Extract Date"
Range("A1").Font.Bold = True
Columns("A:T").AutoFit
End With
' wsNew.Visible = xlSheetHidden
End Sub
Copy/paste each range in turn in the same way as you have for the headings. (untested)
Dim ar(4), k as Integer
ar(1) = array("A1:I1","B")
ar(2) = array("R1","K")
ar(3) = array("K1:M1","L")
ar(4) = array("W1:Y1","O")
'copy headings and paste to new sheet
With Sheets(2)
For k = 1 to Ubound(ar)
.Range(ar(k)(0)).Copy wsNew.Range(ar(k)(1) & "1")
Next
End With
' work through sheets
Dim lr As Long
For J = 2 To Sheets.Count ' from sheet 2 to last sheet
'save sheet name/location to string
Location = Sheets(J).Name
'set range to be copied
With Sheets(J)
lr = .Cells(Rows.Count, 1).End(xlUp).Row
For k = 1 to Ubound(ar)
Set rngCopy = .Range(ar(k)(0)).Offset(1).Resize(lr-1)
'set range to paste to, beginning with column B
Set rngPaste = wsNew.Cells(Rows.Count, ar(k)(1)).End(xlUp).Offset(1, 0)
'copy range and paste to combined sheet
rngCopy.Copy rngPaste
If k = 1 Then
'enter the location name in column A for all copied entries
Range(rngPaste, rngPaste.End(xlDown)).Offset(0, -1) = Location
End If
Next
End With
Next J
Note this block is missing a dot on the ranges to use the With
With Sheets(1)
Range("A1").Value = "Extract Date"
Range("A1").Font.Bold = True
Columns("A:T").AutoFit
End With

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

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

How to reference last used column in a certain row and paste certain value in there

I am working on a macro that loops over a the used range in one sheet (which is the last sheet in the workbook) in a certain column ("H"). The macro should then copy the value, only if it is not 0, and paste it in a sheet called "Overview" in the original row, offset by 3 (e.g. first row becomes 4th row) and in the column behind the last used column in row 5. (I hope that makes sense?). I already worked on some code but I did not manage to reference the last used column correctly and am honestly close to a breakdown.
can someone explain to me what I am doing wrong?
This is what I already have:
Dim Cell As Range, cRange As Range, lrw As Long
Dim wsDestination As Worksheet, wsSource As Worksheet
'set worksheets
With ThisWorkbook
Set wsSource = .Worksheets(Sheets.Count)
Set wsDestination = .Worksheets("Overview")
End With
LastRow1 = wsSource.Cells(Rows.Count, "H").End(xlUp).Row
LastColumn1 = wsDestination.Cells(5, "A").End(xlRight).Column
Set cRange = wsSource.Range(wsSource.Cells(1, 8), wsSource.Cells(LastRow1, 8))
For Each Cell In cRange.Cells
If Cell.Value > 0 Then wsDestination.Cells(Cell.Row, LastColumn1).offset(3, 1) = Cell.Value
Next Cell
End Sub```
The Subtle Differences in Ways of Finding the 'Last Column'
To successfully test the first procedure, in a new worksheet you have to:
write a value in cell A1,
write ="" in cell B1,
write a value in cell C1,
hide column C
and use a fill color in cell D1.
The result of the test will be shown in the Immediate window CTRL+G.
The third procedure is an example of how to use the second procedure, the function for calculating the column of the last non-blank cell in a row using the Find method.
The Code
Option Explicit
Sub LastColumnSuptileDifferences()
Dim wb As Workbook
Set wb = ThisWorkbook ' The workbook containing this code.
Dim ws As Worksheet
Set ws = wb.Worksheets("Sheet1")
' Cell Value Comment
' A1: 1 Value
' B1: ="" Formula
' C1 1 Value: Hidden Column
' D1: Fill Color
Debug.Print ws.Rows(1).Find("*", , xlFormulas, , , xlPrevious).Column ' 3
Debug.Print ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column ' 2
Debug.Print ws.Rows(1).Find("*", , xlValues, , , xlPrevious).Column ' 1
Debug.Print ws.Rows(1).CurrentRegion.Columns.Count ' 3
Debug.Print ws.Rows(1).SpecialCells(xlCellTypeLastCell).Column ' 4
Debug.Print ws.UsedRange.Rows(1).Columns.Count ' 4
End Sub
' This will find the last column even if columns are hidden
' unless you set 'excludeEmpties' to 'True'.
' If you set 'excludeEmpties' to 'True', the right-most cells in the row,
' possibly containing a formula that evaluates to "", will be skipped.
' Additionally only the visible cells will be included, i.e. hidden
' right-most columns, possibly containing data in cells of the row,
' will not be considered (mimicking 'End(xlToLeft)' or CRTL+Left).
Function getLastColumnInRow(RowNumber As Variant, _
Optional Sheet As Worksheet = Nothing, _
Optional excludeEmpties As Boolean = False)
If Sheet Is Nothing Then
Set Sheet = ActiveSheet
End If
Dim FormVal As XlFindLookIn
If excludeEmpties Then
FormVal = xlValues
Else
FormVal = xlFormulas
End If
Dim rng As Range
Set rng = Sheet.Rows(RowNumber).Find(What:="*", _
LookIn:=FormVal, _
SearchDirection:=xlPrevious)
If Not rng Is Nothing Then
getLastColumnInRow = rng.Column
Else
getLastColumnInRow = 0
End If
End Function
Sub testgetLastColumnInRow()
'...
LastColumn1 = getLastColumnInRow(5, wsDestination)
If LastColumn1 = 0 Then
MsgBox "No Data.", vbExclamation, "Empty Row"
Exit Sub ' or whatever
End If
' Continue with code.
Debug.Print LastColumn1
'...
End Sub
So you didn't quite get the last column right. Here's it back.
Dim Cell As Range, cRange As Range, lrw As Long
Dim wsDestination As Worksheet, wsSource As Worksheet
'set worksheets
With ThisWorkbook
Set wsSource = .Worksheets(Sheets.Count)
Set wsDestination = .Worksheets("Overview")
End With
LastRow1 = wsSource.Cells(Rows.Count, "H").End(xlUp).Row
LastColumn1 = wsDestination.Cells(5, columns.count).End(xltoleft).Column
Set cRange = wsSource.Range(wsSource.Cells(1, 8), wsSource.Cells(LastRow1, 8))
For Each Cell In cRange.Cells
If Cell.Value > 0 Then wsDestination.Cells(Cell.Row, LastColumn1).offset(3, 1) = Cell.Value
Next Cell
End Sub```

VBA TextBox fill values in colunm to specific range

My workbook has two sheets: one "Data" and one "Kiert". I solved to copy rows by specific attributes from "data" to "Kiert" with UserForm, but I added ti user form four textboxes (TextBox1, TextBox2 etc.) and I want to fill the database with constant values added in textbox with one command button in blank colums after pasted data.
I have additional textbox5, which indicates if the copy was succefull ("SIKERES"), this part works fine...
Private Sub CommandButton1_Click()
Dim ws As Worksheet
Dim Drng As Range, c As Range
Dim i As Long
Dim lastRow As Long
Dim srcRange As Range, fillRange As Range
Set a = TextBox5
Set d = TextBox1
Set ws = Sheets("Data")
Set Drng = ws.Columns("A:A").SpecialCells(xlCellTypeConstants, 23)
For Each c In Drng.Cells
If c = ListBox1 Then
c.EntireRow.Copy
Sheets("Kiert").Range("A1000000").End(xlUp).Offset(1, 0)
Range("F:F" & lastRow).Formula = TextBox1.Value
If c.Value = ListBox1.Value Then
a.Value = "SIKERES"
End If
End If
Next c
End Sub
I insert here an example:
My main problem is I cannot describe a correct range and description of textboxes, and I don't know where I can put it in my code to run it properly.
I tried this:
For Each c In Drng.Cells
If c = ListBox1 Then
c.EntireRow.Copy Sheets("Summary").Range("A1048576").End(xlUp).Offset(1, 0)
Sheets("Kiert").Range("A:A" & lasrRow).Value = TextBox1.Text
If c.Value = ListBox1.Value Then
A.Value = "SIKERES"
End If
End If
Next c
...but its out of range.
It's not very clear what you are trying to do, but the code below will help you paste the values of your textboxes to the relevant column:
Private Sub CommandButton1_Click()
Dim ws As Worksheet
Dim Drng As Range, c As Range
Dim i As Long
Dim NextFreeRow As Long
Dim srcRange As Range, fillRange As Range
Set Drng = Sheets("Data").Columns("A:A").SpecialCells(xlCellTypeConstants, 23)
For Each c In Drng.Cells 'loop through Column A on Sheet Data
If c = ListBox1.Value Then 'If the cells in Column A Sheet Data matches the selection on your Listbox1 then
NextFreeRow = Sheets("Kiert").Cells(Rows.Count, "A").End(xlUp).Row + 1 'Check the next free row on Sheet Kiert
c.EntireRow.Copy Desination:=Sheets("Kiert").Range("A" & NextFreeRow) 'Paste the entire row from Sheet Data to Sheet Kiert
Range("F" & NextFreeRow).Value = TextBox1.Text 'Copy the contents of TextBox1 to column F
'Add more lines like the one above to copy the values from your Textboxes to the relevant column
TextBox5.Text = "SIKERES"
End If
Next c
End Sub

Need to get cell value and declare it to the row range automatically

Name manager using vba ...
I need to get the cell value from the column one by one and have to declare that name to that row range next to that column
Example
In column D I have the name list
I have to get that D1 value and declare that value to the row range ( E1:S1 )
Next
have to D2 ---> E2:S2
This is how it should be done for first 5 rows:
For i = 1 To 5
ThisWorkbook.Names.Add Name:=yourWorksheet.Cells(i, 4).Value, RefersTo:=yourWorksheet.Range(yourWorksheet.Cells(i, 5), yourWorksheet.Cells(i, 19))
Next
remember that the names must be unique
Try following code
Sub AddNamedRange()
Dim cel As Range
Dim ws As Worksheet
Dim lastRow As Long
Set ws = ThisWorkbook.Sheets("Sheet4") 'change Sheet4 to your sheet name
With ws
lastRow = .Cells(.Rows.Count, "D").End(xlUp).Row 'last row with data in Column D
For Each cel In .Range("D1:D" & lastRow) 'loop through all cell in Column D
ThisWorkbook.Names.Add cel, ws.Range(cel.Offset(, 1), cel.Offset(, 15)) 'adding named range
Next
End With
End Sub

Resources