Macro Merge file with different header - vba

I am working on 2 different sheets which are Sheet1 and Sheet2.
Right now, I have managed to combined 2 sheet if the column header in both files is the same. So how to merge into a combined file which select specific column.
The problem I have right now is the header between 2 sheet is different so it is hard for me to merge 2 different header but it contains same type of data. For example Sheet1 use First Name as its column header and Sheet2 uses Nickname as its column header.
I also don't want it copy the entire column since it contain insignificant column to merged.
I attach the expected result for reference.
Sub Combine()
Dim J As Integer
On Error Resume Next
Sheets(1).Select
Worksheets.Add
Sheets(1).Name = "Combined"
Sheets(2).Activate
Range("A1").EntireRow.Select
Selection.Copy Destination:=Sheets(1).Range("A1")
For J = 2 To Sheets.Count
Sheets(J).Activate
Range("A1").Select
Selection.CurrentRegion.Select
Selection.Offset(1, 0).Resize(Selection.Rows.Count - 1).Select
Selection.Copy Destination:=Sheets(1).Range("A65536").End(xlUp)(2)
Next
End Sub

If you know what Columns your data is in then you can work with Sheets/Columns with simple Do Until Loop
See Example / and see comment on the code
Option Explicit
Public Sub Example()
Dim B As Range, _
C As Range, _
D As Range, _
E As Range, _
F As Range, _
G As Range ' Columns on Sheet1 & Sheet2
Dim i%, x% ' Dim as long
Dim Sht As Worksheet ' Every Sheet on This Workbook
Dim Comb As Worksheet ' Combine Sheet
Set Comb = ThisWorkbook.Worksheets("Combine")
i = 2 ' Start on row 2 - Sheet1 & Sheet2
x = 2 ' Start on row 2 - Combine sheet
'Looping through the worksheets in the workbook
For Each Sht In ThisWorkbook.Worksheets
' ignore Sheet "Combine"
If Sht.Name <> "Combine" Then
Debug.Print Sht.Name ' Print on Immediate Window
Set B = Sht.Columns(2)
Set C = Sht.Columns(3)
Set D = Sht.Columns(4)
Set E = Sht.Columns(5)
Set F = Sht.Columns(6)
Do Until IsEmpty(B.Cells(i))
Comb.Columns(1).Cells(x).Value = B.Cells(i).Value
Comb.Columns(2).Cells(x).Value = C.Cells(i).Value
Comb.Columns(3).Cells(x).Value = D.Cells(i).Value
Comb.Columns(4).Cells(x).Value = E.Cells(i).Value
Comb.Columns(5).Cells(x).Value = F.Cells(i).Value
i = i + 1
x = x + 1
Loop
End If
i = 2 ' Reset 1st Loop
Next
' Auto-Fit Rows & Columns
With Comb.Cells
.Rows.AutoFit
.Columns.AutoFit
End With
End Sub
See also examples on copy/paste - values = values - PasteSpecial method
Also see How to avoid using Select in Excel VBA macros

I have added to your code and commented it. I hope this helps.
Sub Combine()
Dim J As Integer
Dim Rng As Range ' specify a range to copy
Dim R As Long ' set a variable to calculate a row number
' On Error Resume Next ' You want to see the errors and fix them
' therefore don't suppress them
' Sheets(1).Select ' you don't need to "select" anything
' Worksheets.Add ' instead of adding a sheet I suggest you
' you create a copy of Shhet(1)
Sheets("Sheet1").Copy Before:=Sheets(1)
' the new sheet will now be the "ActiveSheet"
With ActiveSheet
.Name = "Combined"
' delete all the columns you don't want to keep, like:-
.Columns("C:K").Delete ' or .Columns("F").Delete
' if you delete individual columns, delete from right to left (!!)
End With
' this part is already done
' Sheets(2).Activate ' you don't need to select anything
' Range("A1").EntireRow.Select
' Selection.Copy Destination:=Sheets(1).Range("A1")
' Note that sheets are numbered 1 and up.
' Therefore the newly inserted sheet is now # 1
' and the previous #1 is now Sheet(2)
For J = 3 To Sheets.Count
' Sheets(J).Activate ' you don't need to activate anything
' Range("A1").Select ' you don't need to select anything either
' Selection.CurrentRegion.Select ' the Selection is already selected
With Sheets(J)
' Selection.Offset(1, 0).Resize(Selection.Rows.Count - 1).Select
' It appears that you want to select the range from A2 to lastrow in A -1
R = .Cells(.Rows.Count, "A").End(xlUp).Row
Set Rng = .Range(.Cells(2, "A"), .Cells(R - 1, "A"))
' avoid using the Selection object. Use Range object instead:-
' Selection.Copy Destination:=Sheets(1).Range("A65536").End(xlUp)(2)
Rng.Copy Destination:=Sheets(1).Range("A65536").End(xlUp)(2)
End With
Next J
End Sub
Note that you can copy a range comprising several columns in one operation. Just change the definition of the range you copy. This will copy columns A:E.
Set Rng = .Range(.Cells(2, "A"), .Cells(R - 1, "E"))
No other change is required.

Related

need vba macro to delete cells except first and last row in each column

I have a excel which has multiple rows and columns and range of column values differ for each row.
Need a macro which will delete all cells in a row except first and last in each row and paste the last value next to first value.
Tried the below script:
Sub test()
Dim sh As Worksheet
Dim IDS As range
Dim ID As range
Set sh = ThisWorkbook.Sheets("Sheet1")
Set IDS = ActiveSheet.range("A2", range("A1").End(xlDown))
For Each ID In IDS
Dim b As Integer
Dim k As Integer
k = sh.range("ID", sh.range("ID").End(xlToRight)).Columns.Count
b = k - 1
range(ID.Offset(0, 0), ID.Offset(0, "b")).Select
Selection.ClearContents
Next ID
End Sub
This is a little different approach but should help.
Also, it is generally not best to declare variables in a loop as you do with b & k just fyi
Sub test()
Dim sh As Worksheet
Dim row As Integer
Dim lastCol As Integer
Set sh = ThisWorkbook.Sheets("Sheet1")
For row = 2 To sh.Cells(Sheets(1).Rows.Count, "A").End(xlUp).row
lastCol = sh.Cells(row, Columns.Count).End(xlToLeft).Column
sh.Range("B" & row).Value = sh.Cells(row, lastCol).Value
sh.Range(sh.Cells(row, 3), sh.Cells(row, lastCol)).ClearContents
Next
End Sub
Best of luck
I'd go as follows:
Sub test()
Dim cell As Range
With ThisWorkbook.Sheets("Sheet1") ' reference relevant sheet
For Each cell In .Range("A2", .Cells(.Rows.Count, "A").End(xlUp)) ' loop through referenced sheet column A cells from row 2 down to last not empty one
With .Range(cell, .Cells(cell.Row, .Columns.Count).End(xlToLeft)) ' reference referenced sheet range spanning from current cell to last not empty one in the same row
If .Count > 2 Then ' if referenced range has more then 2 cells
cell.Offset(, 1).Value = .Cells(1, .Count).Value ' store last cell value next to the current one
.Offset(, 2).Resize(, .Columns.Count - 1).ClearContents 'clear all cells right of current one
End If
End With
Next
End With
End Sub
You can use Range.Delete Method (Excel)
range(ID.Offset(0, 0), ID.Offset(0, b)).Delete Shift:=xlToLeft

Integer not storing correct LastRow value after many loops: VBA Run-Time error

In the code below, my LastRow variable is not storing the right row number on the 27th loop (i = 27) causing the code to malfunction
I have used the F8 step through multiple times and noticed that the issue is on the 27th loop. The LastRow variable is meant to be +1204 rows from the previous LastRow value on each iteration of the loop, so I was expecting LastRow = 32509 instead of LastRow = 31316. For reference, on the 26th loop, LastRow = 31305. I'm not sure why the it is finding the wrong LastRow when the code has worked for the first 26 loops.
I am trying to get from my Source Table to my Desired Table:
Source Table
to
Desired Table
Also , the final error that shows is:
Run-Time error '1004': Application -defined or object- defined error
Sub Populate_entity()
Dim i As Integer
i = 1
Dim LastRow As Long
Dim SearchText As String
Do While i < 122 ' go across entity (columns wise)
If i = 1 Then
Range("E1").Select
Selection.Copy
SearchText = ActiveCell.Value
ActiveCell.End(xlToLeft).Select 'snap to left (cell A1)
ActiveCell.Offset(0, 2).Select 'move to cell C1
ActiveCell.Offset(1, 0).Select ' move to cell C2
Else
ActiveCell.Offset(0, i + 1).Select
Selection.Copy
SearchText = ActiveCell.Value
ActiveCell.End(xlToLeft).Select
ActiveCell.Offset(0, 2).Select
ActiveCell.End(xlDown).Select
ActiveCell.Offset(1, 0).Select
End If
ActiveSheet.Paste
ActiveCell.Offset(1203, 0).Select
ActiveSheet.Paste
ActiveCell.End(xlUp).Select
' ======== Error here ========
LastRow = Cells.Find(What:=SearchText, After:=ActiveCell, LookIn:=xlValues, SearchOrder:=xlByRows).Row
Range("C" & ActiveCell.Row & ":C" & LastRow).FillDown
ActiveCell.End(xlUp).Select
i = i + 1
Loop
End Sub
A summary of what you want, as you described in the comments:
Copy the values from cells E1:DU1, paste each cell 1204 times in column C.
1st loop it will paste cell E1 in C2:C1205
2nd loop it will paste cell F1 to C1206:C2409
etc.
This code achieves that:
Sub Populate_entity()
' Declare 2 range variables (top row to copy from and paste destination)
Dim RowRange As Range
Dim PasteCells As Range
' Use the With block to specify the sheet. If you want the destination
' to be another sheet, then you can specify that instead:
' ThisWorkbook.Sheets("SheetName").Range("...")
With ThisWorkbook.ActiveSheet
Set RowRange = .Range("E1:DU1") ' Set range to copy from
Set PasteCells = .Range("C2:C1205") ' Set paste cells, blocks of 1204 cells in column C
End With
' Loop through RowRange, copy each cell's value into PasteCells
' Then offset the PasteCells range by 1024 rows, so next RowRange cell
' is inserted underneath previously copied cells.
Dim ofst As Long
For ofst = 1 To RowRange.Cells.Count
' Use .Value to avoid the (comparably slow) copy/paste operation
PasteCells.Offset((ofst - 1) * 1204, 0).Value = RowRange.Cells(ofst).Value
Next ofst
End Sub
In my opinion you don't need any search because your code always places the SearchString in row 1205. Since you know that it is there you don't need to look for it. This thought brings me to the code below.
Sub Populate_Entity()
Dim C As Long ' Column
Dim Target As Range
Dim FirstRow As Long
Dim LastRow As Long
FirstRow = 2
LastRow = 7 '1205
C = 3
Range("C2").value = Range("E1").value
' Cells(2, C).Value = Cells(1, 5).Value
Do
Set Target = Range(Cells(FirstRow, C), Cells(LastRow, C))
Target.FillDown
C = C + 1
Cells(2, C).value = "Can't figure"
Loop While C < 3 ' 122
End Sub
I have cut the loop short to only 7 rows (instead of 1205) and 3 columns (instead of 122). I just couldn't figure out where the text in the FirstRow should come from. For column C it comes from E1, but where does it come from in the subsequent columns? You can fill this in using the method I showed you above, like, Cells(2, C).Value = Cells(1, 5).Value. I believe that the 5 can be replaced by a value derived from the current C, perhaps C + 2.
Note the Cells(2, C).Value doesn't refer to the value in cell C2. Instead if refers to the cell in Row 2, Column C.

Copy and Paste dynamic ranges to new sheet in Excel with VBA

I am new to macro writing and I need some help.
I have one sheet and need to copy the columns and reorder them to paste into a software program.
I want to copy A2 - the last data entry in column A and paste it into A1 on Sheet2
I want to copy B2 - the last data entry in column A and paste it into K1 on Sheet2
I want to copy C2 - the last data entry in column A and paste it into C1 on Sheet2
I want to copy D2 - the last data entry in column A and paste it into D1 on Sheet2
Then from Sheet 2, I want to copy A1:KXXXX (to the last entry in column A) and save it on the clipboard to paste into the other application
Here is my code, I have tried... (I know this is just for copying column A, but I got stuck there.)
Sub Copy()
aLastRow = ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Row
Range("A2" & aLastRow).Select
Selection.Copy
Sheets("Sheet2").Select
Range("A1").Select
ActiveSheet.Paste
End Sub
Thank you so much for your help!
Jess
Try this instead. Given that you said you got an error with the paste code and I am still using that, I think you'll still have an error there. Post the error message. Hopefully we can figure that out.
Sub copyStuff()
Dim wsIn As Worksheet
Set wsIn = Application.Worksheets("Sheet1")
Dim endRow As Long
wsIn.Activate
endRow = wsIn.Cells(wsIn.Rows.Count, "A").End(xlUp).Row
Dim r As Range
Dim wsOut As Worksheet
Set wsOut = Application.Worksheets("Sheet2")
' column a to column a
Set r = wsIn.Range(Cells(2, 1), Cells(endRow, 1))
r.Copy
wsOut.Range("A1").PasteSpecial xlPasteAll
' column b to column k
Set r = wsIn.Range(Cells(2, 2), Cells(endRow, 2))
r.Copy
wsOut.Range("K1").PasteSpecial xlPasteAll
' column c to column c
Set r = wsIn.Range(Cells(2, 3), Cells(endRow, 3))
r.Copy
wsOut.Range("C1").PasteSpecial xlPasteAll
' column d to column d
Set r = wsIn.Range(Cells(2, 4), Cells(endRow, 4))
r.Copy
wsOut.Range("D1").PasteSpecial xlPasteAll
' Copy data from sheet 2 into clipboard
wsOut.Activate
Set r = wsOut.Range(Cells(1, 1), Cells(endRow - 1, 11))
r.Copy
End Sub
My original answer is below here. You can disregard.
This should accomplish your first goal:
Sub copyStuff()
Dim wsIn As Worksheet
Set wsIn = Application.Worksheets("Sheet1")
Dim endRow As Long
endRow = wsIn.Cells(wsIn.Rows.Count, "A").End(xlUp).Row
Dim r As range
Set r = wsIn.range(Cells(2, 1), Cells(endRow, 4))
r.Copy
Dim wsOut As Worksheet
Set wsOut = Application.Worksheets("Sheet2")
wsOut.range("A1").PasteSpecial xlPasteAll
End Sub
I copied all 4 columns at once since that would be much faster but it assumes the columns are the same length. If that isn't true you would need to copy one at a time.
The data should be in the clipboard at the end of the macro.
Edit: I removed "wsIn.Activate" since it isn't really needed.
Edit 2: Oops! I just noticed you wanted the output in different columns. I'll work on it.
Generally you want to avoid .Select and .Paste when copying values and rather copy by .value = .value:
Sub Copy()
Dim aLastRow As Long
Dim clipboard As MSForms.DataObject
Set clipboard = New MSForms.DataObject
aLastRow = Sheets("Sheet1").Cells(Rows.Count, 1).End(xlUp).Row
Sheets("Sheet2").Range("A1:A" & aLastRow - 1).Value = Sheets("Sheet1").Range("A2:A" & aLastRow).Value
Sheets("Sheet2").Range("K1:K" & aLastRow - 1).Value = Sheets("Sheet1").Range("B2:B" & aLastRow).Value
Sheets("Sheet2").Range("C1:D" & aLastRow - 1).Value = Sheets("Sheet1").Range("C2:D" & aLastRow).Value
clipboard.SetText Sheets("Sheet2").Range("A1:K" & aLastRow - 1).Value
clipboard.PutInClipboard
End Sub

Add worksheet and combine data

I have a workbook with 2991 worksheets. Each sheet containing information on trucks. Each worksheet is named city,state. For example Juneau, AK. Each worksheet is also formatted exactly the same.
I have code that copies the data from each workbook (excluding the headers) and places it in a "combined" worksheet.
I would like to expand the code so that when a worksheet gets copied the city and state are placed in new separate columns. For example for Jeneau, AK when the data gets copied next to each truck the city Juneau is placed in column F and the state "AK" is placed in column G.
I have the code listed below as well as example screenshots.
Sub Combine()
Dim J As Integer
On Error Resume Next
Sheets(1).Select
Worksheets.Add
Sheets(1).Name = "Combined"
Sheets(2).Activate
Range("A1").EntireRow.Select
Selection.Copy Destination:=Sheets(1).Range("A1")
For J = 2 To Sheets.Count
Sheets(J).Activate
Range("A1").Select
Selection.CurrentRegion.Select
Selection.Offset(1, 0).Resize(Selection.Rows.Count - 1).Select
Selection.Copy Destination:=Sheets(1).Range("A65536").End(xlUp)(2)
Next
End Sub
Original Data
Combined Data
I think the following will do what you need:
Sub Combine()
Dim J As Integer
Dim ws1 As Worksheet
Dim wsCombined As Worksheet
Dim sheetName() As String
Dim pasteStartRow as Integer, pasteEndRow as Integer
On Error Resume Next
'Set ws1 to the first worksheet (I assume this has the header row in it)
Set ws1 = Sheets(1)
'Create wsCombined as the "Combined" worksheet
Set wsCombined = ThisWorkbook.Sheets.Add(ws1)
wsCombined.Name = "Combined"
'Copy the first row from ws1 to wsCombined
ws1.Rows(1).Copy Destination:=wsCombined.Range("A1")
'Loop through all sheets with data
For J = 2 To Sheets.Count
'Get the row on which we will start the paste
pasteStartRow = wsCombined.Range("A65536").End(xlUp).Row + 1
'Figure out the copy range
Sheets(J).Activate
Range("A1").Select
Selection.CurrentRegion.Select
'Copy/Paste
Selection.Offset(1, 0).Resize(Selection.Rows.Count - 1).Copy Destination:=wsCombined.Range("A" & pasteStartRow)
'Get the end row of the pasted data
pasteEndRow = wsCombined.Range("A65536").End(xlUp).Row
'Split the sheet name by comma and put it into an array
sheetName = Split(Sheets(J).Name, ",")
'write out the sheetname to the paste destination from above (using the start and end row that we grabbed)
'Added a trim() to the second item in the array (the state) in case the format of the name is <city>, <state>
wsCombined.Range("F" & pasteStartRow & ":" & "F" & pasteEndRow).Value = sheetName(0)
wsCombined.Range("G" & pasteStartRow & ":" & "G" & pasteEndRow).Value = Trim(sheetName(1))
Next
wsCombined.Activate
End Sub
I rewrote the bit before the for loop to remove all the selecting and activating and whatnot and also to get rid of the the ordinal sheet references and make everything more explicit. The rewrite also makes use of the Worksheets.Add() method to create the new worksheet.
The big change here is:
Grabbing the starting row of the paste destination into a variable
pasteStartRow so we can reuse it when we paste in the city and
state
Grabbing the ending row of the paste destination after we
paste into a variable pasteEndRow, again so we can reuse it with
City/State
Using an Array sheetName and Split() to grab the
comma delimited city, state value from the Sheets(J).name.
Writing the value of the city and state (sheetName(0) and
sheetName(1), respectively) into columns f and g on the
Combined worksheet.
I also added a wsCombined.activate at the end so that your combined worksheet is activate after everything is run.

Continue macro for 53 more rows

Sub attempt()
'
' attempt Macro
'
'
For i = 0 To 818
Sheets("hedz").Select
q = (i * 4) + 1
ActiveSheet.Range(Cells(1, q), Cells(1, q + 3)).Select
Selection.Copy
Sheets("Sheet1").Select
Range("A" & i + 1).Select
ActiveSheet.Paste
Sheets("hedz").Select
I need help repeating this for 53 rows and restart pasting every 818th row in column A on sheet1. I already accomplished this through repeating the macro 53 times but I am just a beginner and could not figure out how. A copy of my spreadsheet:
This should do it:
Sub attemp()
Dim i&, j&
Dim ows As Worksheet, tws As Worksheet
Set ows = Sheets("hedz") 'Change to the sheet that has the data
Set tws = Sheets("Sheet1") 'change to the sheet where the data goes
With ows
'this loop finds the extents of the rows and iterates
For i = 1 To .Cells(.Rows.Count, 1).End(xlUp).Row
'this loop finds the extents of the columns and iterates.
'the step 4 jumps to every forth.
For j = 1 To .Cells(1, .Columns.Count).End(xlToLeft).Column Step 4
'this takes assigns the value of the four cells to the new sheet.
tws.Cells(tws.Rows.Count, 1).End(xlUp).Offset(1).Resize(, 4).Value = .Cells(i, j).Resize(, 4).Value
Next j
Next i
End With
End Sub
You need two loops. This will find the total columns and total rows.