Macro to copy and paste based on column headings - excel

I'm very new to writing Macros in Excel, and have done a bit of looking around to try and solve my problem, but I haven't found a solution yet that works.
I'm trying to write a Macro to do the following:
I'm trying to copy data from Sheet 1, Workbook 1 based on column headings (so for example, I want to copy all the data under the column name "Sort"). The number of rows of data in this row may increase/decrease. I then want to paste this data into Sheet 2, Workbook 2 under the column name "Name". Columns may be added/removed from both workbooks, which is why I want to write the macro to copy based on the column name rather than a column number.
I have been using the below code, which I've tried putting together based on similar but slightly different requests I've found online, but when I run the macro, nothing much happens - I've written the Macro in Workbook 2 and it just opens Workbook 1.
If anyone can see something wrong with my code or suggest an alternative, I'd be extremely grateful for any help. Thanks!!!
Sub CopyProjectName()
Dim CurrentWS As Worksheet
Set CurrentWS = ActiveSheet
Dim SourceWS As Worksheet
Set SourceWS = Workbooks("Workbook1.xlsx").Worksheets("Sheet1")
Dim SourceHeaderRow As Integer: SourceHeaderRow = 1
Dim SourceCell As Range, sRange As Range, Rng As Range
Dim TargetWS As Worksheet
Set TargetWS = Workbooks("Workbook2.xlsm").Worksheets("Sheet2")
Dim TargetHeader As Range
Set TargetHeader = TargetWS.Range("A1:AX1")
Dim RealLastRow As Long
Dim SourceCol As Integer
Range("B2").Select
SourceWS.Activate
LastCol = Sheets("Sheet1").Cells(1, Columns.Count).End(xlToLeft).Column
Set sRange = Sheets("Sheet1").Range("A1", Cells(1, LastCol))
With sRange
Set Rng = .Find(What:="Sort", _
After:=.Cells(1), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False)
If Not Rng Is Nothing Then
LastRow = Sheets("Sheet1").Cells(Rows.Count, Rng.Column).End(xlUp).Row
Sheets("Sheet1").Range(Rng, Cells(LastRow, Rng.Column)).Copy
TargetWS.Activate
Sheets("Sheet2").Range("B1").Paste
End If
End With
End Sub

Workbook1.xlsx and Workbook2.xlsm have to be open for the code bellow
Option Explicit
Public Sub CopyProjectName()
Dim sourceWS As Worksheet, targetWS As Worksheet
Dim lastCol As Long, lastRow As Long, srcRow As Range
Dim found1 As Range, found2 As Range
Set sourceWS = Workbooks("Workbook1.xlsx").Worksheets("Sheet1") 'Needs to be open
Set targetWS = Workbooks("Workbook2.xlsm").Worksheets("Sheet2") 'Needs to be open
With sourceWS
lastCol = .Cells(1, Columns.Count).End(xlToLeft).Column
Set srcRow = .Range("A1", .Cells(1, lastCol))
Set found1 = srcRow.Find(What:="Sort", LookAt:=xlWhole, MatchCase:=False)
If Not found1 Is Nothing Then
lastCol = targetWS.Cells(1, Columns.Count).End(xlToLeft).Column
Set srcRow = targetWS.Range("A1", targetWS.Cells(1, lastCol))
Set found2 = srcRow.Find(What:="Name", LookAt:=xlWhole, MatchCase:=False)
If Not found2 Is Nothing Then
lastRow = .Cells(Rows.Count, found1.Column).End(xlUp).Row
.Range(.Cells(2, found1.Column), .Cells(lastRow, found1.Column)).Copy
found2.Offset(1, 0).PasteSpecial xlPasteAll
End If
End If
End With
End Sub

Related

Copy paste date value to last row in nested loop

Got a bunch of worksheets in the same workbook that have a specific range of interest that starts with finding string 'Green'. Let's call this Range (A) that I'm interested in copying and pasting into a master sheet to form a database in same workbook. I found some useful code and got this part to work gr8!
There is a date value in each worksheet in cell(3,3). What's missing is adding this date value from each worksheet and past it to column B in the master sheet 'Main' such that the date value extends to match the length of the pasted Range (A).
all help is appreciated
Sub FindRangeHistory()
'// in MainDB workbook for each trade sheet, copy and paste specific range into 'Main' sheet
Dim fnd As String, faddr As String
Dim rng As Range, foundCell As Range
Dim ws As Worksheet
Dim ws_count As Integer, i As Integer
ws_count = ThisWorkbook.Worksheets.Count
For i = 1 To ws_count
With ThisWorkbook
'initialize main sheet and keyword search
Set ws = .Worksheets("Main")
fnd = "New Life"
'Search for keyword in sheet
With .Worksheets(i)
Set foundCell = .Cells.Find(What:=fnd, after:=.Cells.SpecialCells(xlCellTypeLastCell), _
LookIn:=xlFormulas, LookAt:=xlWhole, _
SearchOrder:=xlByRows, SearchDirection:=xlNext)
'Test to see if anything was found
If Not foundCell Is Nothing Then
faddr = foundCell.Address
Set rng = .Range(foundCell, foundCell.End(xlDown))
Do
Set rng = Union(rng, .Range(foundCell, foundCell.End(xlDown)).Resize(, 7))
Set foundCell = .Cells.FindNext(after:=foundCell)
Loop Until foundCell.Address = faddr
Set rng = rng.Offset(1, 0)
rng.Copy
ws.Cells(Rows.Count, "C").End(xlUp).PasteSpecial Paste:=xlPasteValues
Worksheets(i).Cells(3, 3).Copy
ws.Cells(Rows.Count, "B").End(xlUp).PasteSpecial Paste:=xlPasteValuesAndNumberFormats
End If
End With
End With
Next i
End Sub
You could do it like this:
'...
'...
Dim nextRowC As Long, lastRowC As Long
nextRowC = ws.Cells(Rows.Count, "C").End(xlUp).Row + 1 'first empty row in ColC before paste
rng.Copy
ws.Cells(nextRowC, "C").PasteSpecial Paste:=xlPasteValues
lastRowC = ws.Cells(Rows.Count, "C").End(xlUp).Row 'last used row in ColC after paste
.Worksheets(i).Cells(3, 3).Copy
ws.Range(ws.Cells(nextRowC, "B"), ws.Cells(lastRowC, "B")). _
PasteSpecial Paste:=xlPasteValuesAndNumberFormats
'...
'...

Copy and Paste Selected Columns to End of Table in Excel with VBA

Within the same worksheet I have a single table, and each time I add new data I need to copy the last 4 columns of this table to the right end of that same table so I can add new data. The main reason being I always want to keep the same format and some columns have dropdown lists and formulas.
I found the next code in the website below. It works really well for copy/pasting
rows, so I tried to modify the code to do it for columns but I couldn´t manage.
I´m new to VBA and just starting to learn how to program macros, so any feedback on what I could do would be appreciated.
https://www.contextures.com/exceltablemacrocopyitems.html
Sub CopySelectionVisibleRowsEnd()
Dim ws As Worksheet
Dim mySel As Range
Dim lRow As Long
Dim lRowNew As Long
Dim lRowsAdd As Long
Dim myList As ListObject
Dim myListRows As Long
Dim myListCols As Long
Set ws = ActiveSheet
Set mySel = Selection.EntireRow
Set myList = ActiveCell.ListObject
myListRows = myList.Range.Rows.Count
myListCols = myList.Range.Columns.Count
lRow = ws.Cells.Find(What:="*", _
SearchOrder:=xlRows, _
SearchDirection:=xlPrevious, _
LookIn:=xlValues).Row + 1
mySel.SpecialCells(xlCellTypeVisible).Copy
ws.Cells(lRow, 1).PasteSpecial Paste:=xlPasteAll
lRowNew = ws.Cells.Find(What:="*", _
SearchOrder:=xlRows, _
SearchDirection:=xlPrevious, _
LookIn:=xlValues).Row + 1
lRowsAdd = lRowNew - lRow
With myList
.Resize ws.Range(.Range.Resize(myListRows + lRowsAdd, myListCols).Address)
End With
Application.CutCopyMode = False
End Sub
If you always want to copy just the last 4 columns, try this. Adjust table name as necessary.
Sub CopySelectionVisibleRowsEnd()
Dim myList As ListObject
Dim rng As Range
Dim myListCols As Long
Set myList = ActiveSheet.ListObjects("Table1")
myListCols = myList.Range.Columns.Count
Set rng = Range("Table1[#All]").Resize(, myListCols + 4)
myList.Resize rng
myList.ListColumns(myListCols - 3).Range.Resize(, 4).Copy myList.ListColumns(myListCols + 1).Range
End Sub

Finding multiple cell values from list

I have a workbook with 2 sheets.
Sheet1 contains a list of Product Codes in column A and Column R is Current Stock Level.
Sheet2 contains a list of Product Codes in column A and Column B contains the New Stock Level.
What I want to do is replace the Current Stock Levels in Sheet1 with the New Stock Level from Sheet2.
I found some code on this site already (below) which I have adapted slightly for my purpose and it works fine but only for one Product Code (as it references A1 and B1). What I would like to do is add a Loop so it works down all products in Sheet2 but I'm not sure how to and haven't been able to adapt any similar loops I've found online for this purpose.
Any help would be appreciated, my backup plan is to just do a v-lookup in Sheet1 to bring in the Sheet2 New Stock Level values and then replace the original column but I would like to get this other way working if possible.
Private Sub CommandButton1_Click()
Dim search_range As Range, search_value As Range, _
lastcell As Range, foundcell As Range
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("Sheet1")
Set search_range = ws.Range("A1", ws.Range("A" & Rows.Count).End(xlUp))
Set lastcell = search_range.Cells(search_range.Cells.Count)
Set search_value = ThisWorkbook.Sheets("Sheet2").Range("A1")
Set foundcell = search_range.Find(What:=search_value, After:=lastcell,
LookIn:=xlValues, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not foundcell Is Nothing Then foundcell.Activate Else MsgBox "Not Found"
ActiveCell.Offset(0, 17).Value = Sheets("Sheet2").Range("B1").Value
End Sub
How about the following:
Private Sub CommandButton1_Click()
Dim search_range As Range, search_value As Range, lastcell As Range, foundcell As Range
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("Sheet1")
Set search_range = ws.Range("A1", ws.Range("A" & Rows.Count).End(xlUp))
Set lastcell = search_range.Cells(search_range.Cells.Count)
For i = 1 To lastcell.Row
Set search_value = ThisWorkbook.Sheets("Sheet2").Range("A" & i)
Set foundcell = search_range.Find(What:=search_value, After:=lastcell, LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext)
If Not foundcell Is Nothing Then foundcell.Activate Else MsgBox "Not Found"
ActiveCell.Offset(0, 17).Value = Sheets("Sheet2").Range("B" & i).Value
Next i
End Sub
The idea is the following - you have two types of ranges - ranges where you search and ranges where your value should be. They are called Target and Search.
In the code below you loop through all cells in column A of the first worksheets and you look for their value in column A of the second worksheet. If you find the value, you write the value in column B of the second worksheet to the 17. column in the first worksheet:
Private Sub CommandButton1_Click()
Dim targetRange As Range
Dim targetValue As Range
Dim searchRange As Range
Dim lastSearchCell As Range
Dim foundCell As Range
Dim wsTarget As Worksheet
Dim wsSearch As Worksheet
Dim myCell As Range
Set wsTarget = ThisWorkbook.Worksheets(1)
Set wsSearch = ThisWorkbook.Worksheets(2)
With wsTarget
Set targetRange = .Range("A1", .Range("A" & .Rows.Count).End(xlUp))
End With
With wsSearch
Set searchRange = .Range("A1", .Range("A" & .Rows.Count).End(xlUp))
End With
Set lastSearchCell = searchRange.Cells(searchRange.Cells.Count)
For Each myCell In targetRange
Set foundCell = searchRange.Find(What:=myCell, After:=lastSearchCell).Offset(0, 1)
If Not foundCell Is Nothing Then
myCell.Offset(0, 17) = foundCell
Else
MsgBox "Not Found"
End If
Next myCell
End Sub

Filtering Excel Data by Row and Copying a Specific Column

I've been having a bit of trouble with my Excel code. What I want to do is to search the rows by text criteria, filter/sort those rows with the specific criteria by column, and be able to copy and hold all of the values in the clipboard for an automation software to take over from that point.
So far, I have been able to sort the rows by the specified criteria (text string), but I cannot seem to figure out the code to copy only the column range (to the end of the row). I can copy the rows, but I'm not sure what the code is to copy an individual column (in this case these are all web addresses, and the column to be copied would be C). I am using Excel 2010.
Sub USPS_Select2()
Dim wb1 As Workbook, wb2 As Workbook
Dim ws1 As Worksheet, ws2 As Worksheet
Dim copyFrom As Range
Dim lRow As Long
Dim strSearch As String
Dim rng As Range
Dim cl As Object
Dim strMatch As String
Dim filterRange As Range
Dim copyRange As Range
Dim lastRow As Long
Set wb1 = Application.Workbooks.Open("\\S51\CompanyFolder\Employee Folders\Jason\TrackingDeliveryStatus.xls")
Set ws1 = wb1.Worksheets("TrackingDeliveryStatusResults")
strSearch = "usps.com"
With ws1
.AutoFilterMode = False
lRow = .Range("C" & .Rows.Count).End(xlUp).Row
With .Range("C2:C" & lRow)
.AutoFilter field:=1, Criteria1:="=*" & strSearch & "*"
Set copyFrom = .Offset(1, 0).SpecialCells(xlCellTypeVisible).EntireRow
End With
.AutoFilterMode = False
End With
Set wb2 = Application.Workbooks.Open("C:\Users\CompanyFolder\Desktop\Excel_Test.xls")
Set ws2 = wb2.Worksheets("Sheet1")
With ws2
If Application.WorksheetFunction.CountA(.Cells) <> 0 Then
lRow = .Cells.Find(What:="*", _
After:=.Range("A1"), _
LookAt:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
Else
lRow = 1
End If
copyFrom.Copy .Rows(lRow)
End With
'wb2.Save
'wb2.close
End Sub
Since you are already working only with column C in this statement:
With .Range("C2:C" & lRow)
You can just eliminate the EntireRow property from this statement
Set copyFrom = .Offset(1, 0).SpecialCells(xlCellTypeVisible).EntireRow
And it will set the range to visible cells in column C only, like this:
Set copyFrom = .Offset(1, 0).SpecialCells(xlCellTypeVisible)
EDIT (to address issue in comment)
The line:
copyFrom.Copy .Rows(lRow)
Is going to paste the data into every column of that row. So make the line this to copy only into Column A.
copyFrom.Copy .Cells(lRow,1)

Special copy&paste-script for .csv files

I have a partial solution for a former question I asked, I hope it's okay to open a new question.
What I have:
.csv-file 1
00|G1|G2|
K4|__|X_|
K5|X_|X_|
.csv-file 2
00|G3|G7|G9|G12
K6|X_|__|X_|__|
K7|__|X_|X_|__|
K8|__|__|__|X_|
What I want:
final .csv (or .xls) file
00|G1|G2|G3|G7|G9|G12
K4|__|X_|__|__|__|__|
K5|X_|X_|__|__|__|__|
K6|__|__|X_|__|X_|__|
K7|__|__|__|X_|X_|__|
K8|__|__|__|__|__|X_|
So the top row of file 2 -- shall be added to the right -- of the top row of file 1.
The first column to the left of file 2 -- shall be added underneath -- the first column of file 1.
The corresponding Xes shall then be just copy and pasted -- to the down right corner -- of the Xes of file 1.
I have a lot of .csv-files and no idea how to use VBA.
I'd very much appreciate your help!
Regards,
Tom
Try this it's a bit convoluted but I think this is what you want. I've put it so they are in the same workbook but that is easily changed to opening the files with setting a workbook with Workbooks.Open()
Edit to show how I do to an open csv. (there are many ways you can do all the below)
Sub simplePaste()
Dim lastRow0 As Long
Dim lastColumn0 As Long
Dim lastColumn1
Dim ws0 As Worksheet
Dim ws1 As Worksheet
Dim wb1 As Workbook
Dim CopyRange As Range
Dim pasteRange As Range
Set ws0 = ThisWorkbook.Sheets("Sheet1")
Set wb1 = Workbooks.Open("C:\Users\james\Desktop\source.csv")
Set ws1 = wb1.Sheets(1)
lastRow0 = ws1.Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
lastColumn0 = ws1.Cells.Find(What:="*", SearchDirection:=xlPrevious, SearchOrder:=xlByColumns).Column
lastColumn1 = ws0.Cells.Find(What:="*", SearchDirection:=xlPrevious, SearchOrder:=xlByColumns).Column
Set CopyRange = ws1.Range(ws1.Cells(1, 1), ws1.Cells(lastRow0, lastColumn0))
Set pasteRange = ws0.Cells(1, lastColumn1 + 1)
CopyRange.Copy
pasteRange.PasteSpecial
wb1.Close
End Sub
So this code should do the trick, it only misses some kind of function to crawl through your directory and open the files one by one. But that doesnt seem to hard to write.
Sub simplePaste()
Dim lastRow0 As Long
Dim lastColumn0 As Long
Dim lastColumn1
Dim ws0 As Worksheet
Dim ws1 As Worksheet
Dim CopyRange As Range
Dim pasteRange As Range
Set ws0 = ThisWorkbook.Sheets("Sheet1")
Set ws1 = ThisWorkbook.Sheets("Sheet2")
lastRow0 = ws0.Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
lastColumn0 = ws0.Cells.Find(What:="*", SearchDirection:=xlPrevious, SearchOrder:=xlByColumns).Column
lastRow1 = ws1.Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
vlastColumn1 = ws1.Cells.Find(What:="*", SearchDirection:=xlPrevious, SearchOrder:=xlByColumns).Column
Set CopyRange = ws1.Range(ws1.Cells(1, 2), ws1.Cells(1, lastColumn1))
Set pasteRange = ws0.Cells(1, lastColumn0 + 1)
CopyRange.Copy
pasteRange.PasteSpecial
Set CopyRange = ws1.Range(ws1.Cells(2, 1), ws1.Cells(lastRow1, 1))
Set pasteRange = ws0.Cells(lastRow0 + 1, 1)
CopyRange.Copy
pasteRange.PasteSpecial
Set CopyRange = ws1.Range(ws1.Cells(2, 2), ws1.Cells(lastRow1 - 1, lastColumn1))
Set pasteRange = ws0.Cells(lastRow0 + 1, lastColumn0 + 1)
CopyRange.Copy
pasteRange.PasteSpecial
End Sub
What it does:
get the count of rows and columns in each sheet
set the copy range for the first row in sheet 2
set the paste cell in sheet 1 (first cell with no content in row 1)
paste
set the copy range to the first column in sheet 2
set the paste cell in sheet 1 (first cell with no content in column 1)
paste
set the copy range in sheet 2 from B2 to the cell with the coordinates (lastColumn|lastRow) ((That's where all the Xes are)
set the paste cell in sheet 1. This is the cell after the block of Xes in Sheet 1
paste
Job is done!
Thanks for your help!
Tom

Resources