Copy three columns into one column in Excel VBA - excel

I need help to create a Excel VBA macro. I have a workbook contains 4 worksheets. Coulmn "A" in worksheet number 1, 2 and 3 are filled with data. I need to copy these data into Sheet 4 Column "A". I already done this by using this code but it dosn't work (it only copy the data by replacing ..).
EXAMPLE (I need to do following)
(Sheet 1 Col. A)
1
2
3
4
(Sheet 2 Col. A)
5
6
(Sheet 3 Col. A)
7
8
9
Need to copy all above in sheet 4 Col. A as follows
1
2
3
4
5
6
7
8
9
So, I wrote a code as follows
Sub CopyColumnToWorkbook()
Dim sourceColumn As Range, targetColumn As Range
Set sourceColumn = Worksheets("Sheet1").Columns("A")
Set targetColumn = Worksheets("Sheet4").Columns("A")
sourceColumn.Copy Destination:=targetColumn
End Sub
Sub CopyColumnToWorkbook2()
Dim sourceColumn As Range, targetColumn As Range
Set sourceColumn = Worksheets("Sheet2").Columns("A")
Set targetColumn = Worksheets("Sheet4").Columns("A")
sourceColumn.Copy Destination:=targetColumn
End Sub
Sub CopyColumnToWorkbook2()
Dim sourceColumn As Range, targetColumn As Range
Set sourceColumn = Worksheets("Sheet3").Columns("A")
Set targetColumn = Worksheets("Sheet4").Columns("A")
sourceColumn.Copy Destination:=targetColumn
End Sub
This above coding is not work as I need. Someone please help me to do as in above EXAMPLE.
Thank you very much.

This is quick code I threw together just to get you on the right track. It can be cleaned up. Basically you want to look through each sheet and see what the last column used is, then copy the entire used range for column A, and paste it onto the master sheet, starting from the last cell used in column A. You don't want to paste entire columns, so I used "End(xlUp)" which find the last cell used in column A.
Sub ColumnAMaster()
Dim lastRow As Long, lastRowMaster As Long
Dim ws As Worksheet
Dim Master As Worksheet
Application.ScreenUpdating = False
Set Master = Sheets.Add
Master.Name = "Master"
lastRowMaster = 1
For Each ws In ThisWorkbook.Sheets
If ws.Name <> "Master" Then
lastRow = ws.Range("A" & Rows.Count).End(xlUp).Row
ws.Range("A1:A" & lastRow).Copy Destination:=Master.Range("A" & lastRowMaster)
lastRowMaster = Master.Range("A" & Rows.Count).End(xlUp).Row + 1
End If
Next
Application.ScreenUpdating = True
MsgBox "Done!"
End Sub
Sorry StackOverflow is not indenting the code as it should...
Things you may want to do: check if there is any data at all inside each sheet before copying A over to the master, loop through worksheets in a specific order, check if a 'master' sheet exists or not already, etc.

Here is another way, very quick and basic but does the job
You could obviously combine all of those 3 do loops into one loop
Dim x As Integer
Dim y As Integer
x = 1
y = 1
Do Until Worksheets("Sheet1").Range("A" & x) = ""
Worksheets("Sheet4").Range("A" & y) = Worksheets("Sheet1").Range("A" & x)
y = y + 1
x = x + 1
Loop
x = 1
Do Until Worksheets("Sheet2").Range("A" & x) = ""
Worksheets("Sheet4").Range("A" & y) = Worksheets("Sheet2").Range("A" & x)
y = y + 1
x = x + 1
Loop
x = 1
Do Until Worksheets("Sheet3").Range("A" & x) = ""
Worksheets("Sheet4").Range("A" & y) = Worksheets("Sheet3").Range("A" & x)
y = y + 1
x = x + 1
Loop

Related

Hod to copy data from one sheet to another with limited selection of columns using VBA

I need to copy data from one sheet to another with a limited selection of columns using VBA, not continuous and transpose the copied data in a column while pasting to another sheet. Also, I want to skip the empty cells while doing so.
I want to apply a loop but I am not able to declare the ranges of cells exactly as they should be. I am very new to VBA and below is the code which I am using trying to achieve the goal.
Option Explicit
Sub CopyPasteLoop()
Dim X As Long
Dim Y As Long
Dim Col As Long
Dim row1 As Long
'Dim A As Long
Col = 1
Sheets("Copy").Activate
'For A = 1 To 10000
row1 = Sheets("Copy").Range(.Cells(.Rows.Count, Col)).End(xlUp).row
Sheets("Key Entry Data").Activate
X = Sheet2.Range("A" & Rows.Count).End(xlUp).row
'Y = Sheet1.Cells(1, Columns.Count).End(xlToLeft).Column
Sheets("Copy").Activate
Sheet1.Range("Col" & 2, "Col" & row1).Select
Selection.Copy
'X = X + 1
Sheets("Key Entry Data").Activate
Sheet2.Cells(X).Select
Sheet2.Range("A" & X).PasteSpecial xlPasteValues
Col = ActiveCell.Next.EntireColumn.Cells(1).Select
'Next X
End Sub
In general you should avoid using .Acitvate and .Select as described here. In your code you can completely leave out those parts. This and the unqualified ranges (as mentioned in the comments) are most likely the cause of your problems. Here is your corrected code:
Option Explicit
Sub CopyPasteLoop()
Dim X As Long
Dim Y As Long
Dim Col As Long
Dim row1 As Long
'Dim A As Long
Col = 1
'For A = 1 To 10000
row1 = Sheets("Copy").Cells(Rows.Count, Col).End(xlUp).Row
X = Sheet2.Range("A" & Rows.Count).End(xlUp).Row
'Y = Sheet1.Cells(1, Columns.Count).End(xlToLeft).Column
Sheet1.Range(Sheet1.Cells(2, Col), Sheet1.Cells(row1, Col)).Copy Sheet2.Range("A" & X)
'X = X + 1
'Next X
End Sub
Please note that the For loop you commented out will not work. As it's unclear from your question what that loop is supposed to achieve I'm not able to correct it to what exactly you're trying to do. In general, you don't need X = X + 1 inside a For loop (it will skip every second integer this way), as the For ... To statement takes care of that.
Thank you for sharing this M.Schalk, I am using the below code to copy the data to another sheet. Can you look at the code and share an effective one with me?
Option Explicit
Sub EmailIDCopy()
Dim X As Long 'X is the value of Row
Dim Y As Long
Dim Col As Long 'Col is used to column of Sheet2
Dim row1 As Long 'row1 is currently being used for defining the last row of column
Dim M As Long
Col = 1
Sheets("Copy").Activate
For M = 1 To 5
row1 = Sheets("Copy").Cells(Rows.Count, Col).End(xlUp).row
Sheets("Key Entry Data").Activate
X = Sheet2.Range("A" & Rows.Count).End(xlUp).row
Sheets("Copy").Activate
Sheet1.Range(Cells(2, Col), Cells(row1, Col)).SpecialCells(xlCellTypeVisible).SpecialCells(xlCellTypeConstants).Copy
X = X + 1
Sheets("Key Entry Data").Activate
Sheet2.Cells(X).Select
Sheet2.Range("A" & X).PasteSpecial xlPasteValues
Col = Col + 2
Next M
End Sub
thank you.

Excel VBA Error Doing Multiple Row Multiplication

Gettin a "Type Mismatch" error.
Trying to take one matrix of numbers on one worksheet "Sheet1", divide by another matrix of numbers on a second worksheet "Sheet2", then show each cell result on a matrix on the third worksheet "Sheet1"
Sub MacroTest()
Worksheets("Sheet3").Range("C5") = Worksheets("Sheet1").Range("C5:DR124") / Worksheets("Sheet2").Range("C5:DR124")
End Sub
With this code you can do what you need on specific range (that you can choose) on different sheet and also on the same sheet.
Sub RangeDiv()
Dim RngFrom As Range
Dim RngDiv As Range
Dim RngTo As Range
Dim R As Integer
Dim C As Integer
Set RngFrom = Sheets(1).Range("A1:E3")
Set RngDiv = Sheets(1).Range("B6:F8")
Set RngTo = Sheets(1).Range("C10:G12")
'Check if all Rngs have the same number of rows and columns
If RngFrom.Rows.Count <> RngDiv.Rows.Count Or RngFrom.Rows.Count <> RngTo.Rows.Count Then
MsgBox ("Rngs rows number aren't equal")
Exit Sub
End If
If RngFrom.Columns.Count <> RngDiv.Columns.Count Or RngFrom.Columns.Count <> RngTo.Columns.Count Then
MsgBox ("Rngs columns number aren't equal")
Exit Sub
End If
For C = 1 To RngFrom.Columns.Count
For R = 1 To RngFrom.Rows.Count
'check cell value to avoid errors coming from dividing by 0
If Val(RngDiv.Cells(R, C)) <> 0 Then
RngTo.Cells(R, C) = RngFrom.Cells(R, C) / RngDiv.Cells(R, C)
Else
'Insert something when division is impossible
RngTo.Cells(R, C) = 0 'Or what you want to insert
End If
Next R
Next C
End Sub
I create sheet1 like this
Please click to see Image
then sheet2
Please click to see Image2
then create blank sheet 3
and use this code
Sub divideRange()
Dim lastRow, lastColumn As Long
lastColumn = Sheets("Sheet1").Cells(1, Columns.Count).End(xlToLeft).Column
lastRow = Sheets("Sheet1").Cells(Rows.Count, 1).End(xlUp).Row
For i = 1 To lastRow
For j = 1 To lastColumn
Sheets("Sheet3").Cells(i, j).Value = Sheets("Sheet1").Cells(i, j).Value / Sheets("Sheet2").Cells(i, j).Value
Next j
Next i
End Sub
Is this what you want?
Sorry for my late reply.
You can solve your problem with a for-loop:
For i = 3 To 9
If IsNumeric(Worksheets("Tabelle2").Cells(5, i).Value) And IsNumeric(Worksheets("Tabelle3").Cells(5, i).Value) And Worksheets("Tabelle3").Cells(5, i).Value <> 0 Then
Worksheets("Tabelle1").Cells(5, i).Value = Worksheets("Tabelle2").Cells(5, i).Value / Worksheets("Tabelle3").Cells(5, i).Value
End If
Next
variable i is your column as a number. A = 1, B = 2, Z = 26, AA = 27 and so on..
number 5 is your row
For example
Cells(5,1) is the same like Range("A5") or Cells(3,9) = Range("I3")
In my code above, it starts with column C (3) and stops with column I (9). Replace the Number 9 with the number of the Column FX (your last column) and edit the table Names then it should work.

Lookup Value in Same Column on Multiple Worksheets

In column B on three (Bakery, Floral, Grocery) of the five sheets in my workbook, I want to find rows that have the word Flyer in column B. There will be multiple rows in each worksheet that have the word Flyer in column B. When it finds the word Flyer, it will paste the entire row into Sheet1.
I go this to work on one tab, but want the same code to search all three tabs (but NOT all five ... this is the issue) and paste all of the rows with the word Flyer in column B into Sheet1.
My code (works, but only on the Bakery tab):
Sub CopyRowsFlyer()
'This looks in the Bakery tab and moves everything that has "Flyer" in column B to Sheet 1
Dim bottomB As Integer
Dim x As Integer
bottomB = Sheets("Bakery").Range("B" & Rows.Count).End(xlUp).Row: x = 1
Dim c As Range
For Each c In Sheets("Bakery").Range("B3:B" & bottomB)
If c.Value = "Flyer" Then
c.EntireRow.Copy Worksheets("sheet1").Range("A" & x)
x = x + 1
End If
Next c
End Sub
Similar to other solutions posted. Pretty simple. Replaces bounding for range checking. Fewest variables. No mid-execution dimensioning.
Sub CopyRowsFlyer()
Dim strSh As Variant, c As Range, x As Integer
x = 1
For Each strSh In Array("Bakery", "Floral", "Grocery")
For Each c In Worksheets(strSh).Range("B:B")
If c = "" and c.Row > 2 Then
Exit For
ElseIf c = "Flyer" and c.Row > 2 Then
c.EntireRow.Copy Worksheets("Sheet1").Range("A" & x)
x = x + 1
End If
Next
Next
End Sub
You just want to loop through the three sheets you want. Try this:
Sub CopyRowsFlyer()
'This looks in the Bakery tab and moves everything that has "Flyer" in column B to Sheet 1
Dim bottomB As Integer
Dim x As Integer
Dim SheetsArray() As Variant
Dim ws As WorkSheet
Dim i As Integer
SheetsArray = Array("Bakery", "Sheet2Name", "Sheet3Name")
For i = LBound(SheetsArray) To UBound(SheetsArray)
Set ws = Sheets(SheetsArray(i))
bottomB = ws.Range("B" & Rows.Count).End(xlUp).Row: x = 1
Dim c As Range
For Each c In ws.Range("B3:B" & bottomB)
If c.Value = "Flyer" Then
c.EntireRow.Copy Worksheets("sheet1").Range("A" & x)
x = x + 1
End If
Next c
Next i
End Sub
You can substitute an element of a string array for the ID in Sheets.
Here is your code modified to reflect.
Sub CopyRowsFlyer()
Dim bottomB As Integer
Dim x As Integer
Dim sheetName(1 to 3) As String, i as Integer
sheetName(1) = "Bakery"
sheetName(2) = "Floral"
sheetName(3) = "Grocery"
x=1
For i = 1 to 3
bottomB = Sheets(sheetName(i)).Range("B" & Rows.Count).End(xlUp).Row
Dim c As Range
For Each c In Sheets(sheetName(i)).Range("B3:B" & bottomB)
If c.Value = "Flyer" Then
c.EntireRow.Copy Worksheets("sheet1").Range("A" & x)
x = x + 1
End If
Next c
Next i
End Sub
Store the desired worksheet names in an array and loop through them.
Sub CopyRowsFlyer()
Dim bottomB As Long, b As Long, x As Long
Dim w As Long, vWSs As Variant
vWSs = Array("Bakery", "Floral", "Grocery")
x = 1
For w = LBound(vWSs) To UBound(vWSs)
With Worksheets(vWSs(w))
bottomB = .Range("B" & Rows.Count).End(xlUp).Row
For b = 3 To bottomB
If LCase(.Cells(b, "B").Value) = "flyer" Then
.Rows(b).EntireRow.Copy Worksheets("sheet1").Range("A" & x)
x = x + 1
End If
Next b
End With
Next w
End Sub
While this method of looping through the cells in each worksheet's column B is considered inefficient compared to other methods like the .Range.Find method, it will not make a lot of difference on smaller sets of data. If you have a large number of rows on each worksheet to examine, you may wish to explore other more direct avenues of retrieving the information.

mapping column headers from one sheet to another

i wanted to map columns from one worksheet to another and this is the code i have tried:
Dim x As Integer
x = 2
Do Until Sheets("Sheet1").Range("A" & x).Value = ""
Sheets("Sheet2").Range("C" & x).Value = Sheets("Sheet1").Range("A" & x).Value
x = x + 1
Loop
x = 2
Do Until Sheets("Sheet1").Range("B" & x).Value = ""
Sheets("Sheet2").Range("A" & x).Value = Sheets("Sheet1").Range("B" & x).Value
x = x + 1
Loop
x = 2
Do Until Sheets("Sheet1").Range("C" & x).Value = ""
Sheets("Sheet2").Range("B" & x).Value = Sheets("Sheet1").Range("C" & x).Value
x = x + 1
Loop
in worksheet1 i have:
A B C
1 applicationname applicationid number
2 applcation1 1 123
3 applcation2 2 454
4 applcation3 3 897
in worksheet2 i got:
A B C
1 appid num appname
2 1 123 applcation1
3 2 454 applcation2
4 3 897 applcation3
the problem is there are many other columns and this code seems to be lengthy..i need to loop so that applicationid maps to appid and so on ..i want to know wether there is a way to map columns based on the headers(the data in first row) and can anyone please say what to do if i want to copy the empty cells also?
may i know wether i can have an worksheet like interface say sheet3 where i can fill the required mappings like
A B
1 Application Name App Name
2 Application ID AppID
3 Technology Tech
4 Business Criticality Bus Criticality
5 IT Owner IT Owner
6 Business Owner BusOwner and accordingly map them?thanks in advance
Try this:
Sub Map()
Dim Sh1 As Worksheet, Sh2 As Worksheet
Dim HeadersOne() As String
Dim HeadersTwo() As String
With ThisWorkbook
Set Sh1 = .Sheets("Sheet1") 'Modify as necessary.
Set Sh2 = .Sheets("Sheet2") 'Modify as necessary.
End With
HeadersOne() = Split("applicationname,applicationid,number", ",")
HeadersTwo() = Split("appname,appid,num", ",")
For HeaderIter = 1 To 3
SCol = GetColMatched(Sh1, HeadersOne(HeaderIter - 1))
TCol = GetColMatched(Sh2, HeadersTwo(HeaderIter - 1))
LRow = GetLastRowMatched(Sh1, HeadersOne(HeaderIter - 1))
For Iter = 2 To LRow
Sh2.Cells(Iter, TCol).Value = Sh1.Cells(Iter, SCol).Value
Next Iter
Next HeaderIter
End Sub
Function GetLastRowMatched(Sh As Worksheet, Header As String) As Long
ColIndex = Application.Match(Header, Sh.Rows(1), 0)
GetLastRowMatched = Sh.Cells(Rows.Count, ColIndex).End(xlUp).Row
End Function
Function GetColMatched(Sh As Worksheet, Header As String) As Long
ColIndex = Application.Match(Header, Sh.Rows(1), 0)
GetColMatched = ColIndex
End Function
Let us know if this helps.
Follow-up Edit:
Here's a way to set up an interface.
Assuming that your set-up is similar to mine...
Sheet1:
Sheet2 (I jumbled the headers on purpose):
Interface Sheet:
Result after running code:
Here's the code. Modify accordingly and make sure your headers are exact.
Sub ModdedMap()
Dim Sh1 As Worksheet, Sh2 As Worksheet, Sh3 As Worksheet
Dim HeadersOne As Range, HeadersTwo As Range
Dim hCell As Range
With ThisWorkbook
Set Sh1 = .Sheets("Sheet1") 'Modify as necessary.
Set Sh2 = .Sheets("Sheet2") 'Modify as necessary.
Set Sh3 = .Sheets("Interface") 'Modify as necessary.
End With
Set HeadersOne = Sh3.Range("A1:A" & Sh3.Range("A" & Rows.Count).End(xlUp).Row)
Application.ScreenUpdating = False
For Each hCell In HeadersOne
SCol = GetColMatched(Sh1, hCell.Value)
TCol = GetColMatched(Sh2, hCell.Offset(0, 1).Value)
LRow = GetLastRowMatched(Sh1, hCell.Value)
For Iter = 2 To LRow
Sh2.Cells(Iter, TCol).Value = Sh1.Cells(Iter, SCol).Value
Next Iter
Next hCell
Application.ScreenUpdating = True
End Sub
Function GetLastRowMatched(Sh As Worksheet, Header As String) As Long
ColIndex = Application.Match(Header, Sh.Rows(1), 0)
GetLastRowMatched = Sh.Cells(Rows.Count, ColIndex).End(xlUp).Row
End Function
Function GetColMatched(Sh As Worksheet, Header As String) As Long
ColIndex = Application.Match(Header, Sh.Rows(1), 0)
GetColMatched = ColIndex
End Function
There's no need in this situation to copy the cells one at a time. Not for any performance reason (unless you have tons and tons of data you probably wouldn't run into any performance issues) - it's just that the code would be simpler if you copied the columns directly from Sheet1 to Sheet2 in one operation per column.
The first step is to identify how many rows total are in Sheet1 that you want to copy. There are many schools of thought on how to obtain a used row count in Excel, but the simplest is probably to use the expression UsedRange.Rows.Count on the worksheet (we subtract 1 because we're not copying the header row):
Dim row_count As Long
row_count = Sheets("Sheet1").UsedRange.Rows.Count - 1
Range("Sheet1!A2").Resize(row_count).Copy Range("Sheet2!C2")
Range("Sheet1!B2").Resize(row_count).Copy Range("Sheet2!A2")
Range("Sheet1!C2").Resize(row_count).Copy Range("Sheet2!B2")
I would be satisfied doing it this way, with one line per column that you want to copy. There's still duplicated code, but it's manageable in my opinion.

Editing Excel Macro VBA to have it fill in Column C and right, instead of Column A

I am currently using the Macro below for excel to move data from one one sheet to another. It is set up to fill from Row 2 down, as long as the rows are empty. I not want to have it already contain data in Columns 2 & 3. I have tried a number of things and am not having a lot of luck. I am new to this and "fixing" someone else's macro.
Sub MergeSheets()
Sheets("New").Activate
LastRowNew = Application.WorksheetFunction.CountA(Columns(1))
For i = 2 To LastRowNew
OrderNumber = Cells(i, 3)
Sheets("PRIOrders").Activate
LastRowPRI = Application.WorksheetFunction.CountA(Columns(1))
For j = 2 To LastRowPRI
If Cells(j, 3) = OrderNumber Then
Exit For
ElseIf j = LastRowPRI Then
Sheets("New").Rows(i).Copy Destination:=Sheets("PRIOrders").Rows(LastRowPRI + 1)
Sheets("PRIOrders").Rows(2).Copy
Sheets("PRIOrders").PasteSpecial xlPasteFormats
End If
Next
Sheets("New").Activate
Next
Sub MergeSheets()
Dim shtNew As Worksheet, shtOrders As Worksheet
Dim rngOrder As Range, rngNewOrders As Range
Dim f As Range, lastRow As Long
Set shtNew = ActiveWorkbook.Sheets("New")
Set rngNewOrders = shtNew.Range(shtNew.Range("C2"), _
shtNew.Cells(Rows.Count, 3).End(xlUp))
Set shtOrders = ActiveWorkbook.Sheets("PRIOrders")
For Each rngOrder In rngNewOrders.Cells
Set f = shtOrders.Columns(3).Find(Trim(rngOrder.Value), , xlValues, xlWhole)
If f Is Nothing Then
'find the last occupied row in Col B or C
lastRow = Application.Max(shtOrders.Cells(Rows.Count, 2).End(xlUp).Row, _
shtOrders.Cells(Rows.Count, 3).End(xlUp).Row)
rngOrder.EntireRow.Copy shtOrders.Cells(lastRow + 1, 1)
End If
Next rngOrder
End Sub

Resources