I am collating data of different worksheet.
The problem is when copying data into the destination file, all the data are placed into one column.
The code below is a snippet of the part where the problem occurs.
Workbooks.Open (Folderpath & Filename)
Lastrow = ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Row
Lastcolumn = ActiveSheet.Cells(2, Columns.Count).End(xlToLeft).Column
Range(Cells(2, 1), Cells(Lastrow, Lastcolumn)).Copy
Application.DisplayAlerts = False
ActiveWorkbook.Close
erow = ThisIsAWS.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
ThisIsAWS.Paste Destination:=ThisIsAWS.Range(Cells(erow, 1), Cells(erow, Lastcolumn))
Filename = Dir
This is how a file would look initially.
After going through the macro, it ends up like this.
When I do it manually where I copy (ctrl + c) and paste (ctrl + v) using the same data, it comes out fine.
For the source file, the data might have been placed in a table, so would this play a role to why it ends up in one column in the destination file?
EDIT: Source picture. I might have found the problem but still in need of a solution. The column B and C are merged together in this picture. Could this be it?
Your macro works fine for me. However, you could try to set the ranges equal using .value rather than .copy:
Dim to_rng as Range
Dim rng_loop as Range
Workbooks.Open (Folderpath & Filename)
Lastrow = ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Row
Lastcolumn = ActiveSheet.Cells(2, Columns.Count).End(xlToLeft).Column
Application.DisplayAlerts = False
erow = ThisIsAWS.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
Set to_rng = ThisIsAWS.Range(ThisIsAWS.Cells(erow, 1), ThisIsAWS.Cells(erow + Lastrow - 2, Lastcolumn))
to_rng.value = ActiveSheet.range(ActiveSheet.cells(2,1), ActiveSheet.cells(Lastrow, Lastcolumn)).value
For loop1 = Lastcolumn To 1 Step -1
Set rng_loop = ThisIsAWS.Range(ThisIsAWS.Cells(erow, loop1), ThisIsAWS.Cells((erow + Lastrow - 2), loop1))
If WorksheetFunction.CountA(rng_loop) = 0 Then
rng_loop.Delete shift:=xlToLeft
End If
Next loop1
ActiveWorkbook.Close
Filename = Dir
The loop moves backwards (step -1) through each column in the added range and if all cells in the range column are empty (CountA = 0), then it deletes the column by shifting the entire row to the left.
Original data:
Data added to other file:
Closed Too Early
With Workbooks.Open(Folderpath & Filename).ActiveSheet
Lastrow = .Cells(.Rows.Count, 1).End(xlUp).Row
Lastcolumn = .Cells(2, .Columns.Count).End(xlToLeft).Column
erow = ThisIsAWS.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
.Range(.Cells(2, 1), .Cells(Lastrow, Lastcolumn)).Copy _
Destination:=ThisIsAWS.Cells(erow, 1)
.Parent.Close False
End With
Filename = Dir
Related
I'm working on a excel document with multiple seperate data, all in a single column (A1 to A10160).
All the data begins in a cell with the text NC/xx/xxxx/x (x being variable) and ending in a cell containing different dates but the cell above it always has the text "Start Date". Some data covers 49 cells others cover 51 cells so it's not contained in a fixed number of cells in the column.
I need to copy the range from NC/xx/xxxx/x to Start Date plus one for each data "set", transpose it and paste all the data in the column in a new sheet.
Really haven't found anything useful so far but I am fumbling with this one:
Sub Find()
Dim Search, End, Start, i As Integer, j As Integer, L
Search = Cells(1, 1)
End = Cells(2, 1)
For i = 1 To 10160
If Left(Cells(i, 1), 3) = Search Then
Start = i - 0
End If
Next i
For j = 1 To 10160
If Cells(j, 1) = End Then
L = j + 1
End If
Sheet4.Select
Range(Cells(Start, 1), Cells(L + 2, 1)).Select
Selection.Copy
Sheet4.Range("BB23").PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=True
Application.CutCopyMode = False
End
Next j
End Sub
Would really appreciate any help I can get!
Thanks!
It looks like you haven't had much interest in your question, so I've taken a look at it. It's one of those fiddly jobs - not terribly technical but tricky to get the flow of logic right. The code below gives you what you've outlined in your question. You've said transpose it - so that's what the code does. Try it and let me know how you go.
Option Explicit
Sub Copy2Sheet2()
'Declare all your variables
Dim ws1 As Worksheet, ws2 As Worksheet
Dim topRow As Long, BottomRow As Long, LastRow As Long
Dim PasteToRow As Long, i As Long, c As Range
'Set the sheet variables
Set ws1 = Sheets(1)
Set ws2 = Sheets(2)
'Initial row settings
LastRow = ws1.Cells(Rows.Count, 1).End(xlUp).Row
PasteToRow = ws2.Cells(Rows.Count, 1).End(xlUp).Row + 1 '<~~ assumes headers on sheet2
'Start the loop
For i = 1 To LastRow
'Find the bottom row of the first block of data
Set c = ws1.Range("A" & i & ":A" & LastRow).Find(What:="Start Date", LookIn:=xlValues)
BottomRow = c.Row + 1
'Define and copy the range to sheet2
ws1.Range("A" & i & ":A" & BottomRow).Copy
ws2.Range("A" & PasteToRow).PasteSpecial Transpose:=True
Application.CutCopyMode = False
'Redefine the 'paste to' row
PasteToRow = ws2.Cells(Rows.Count, 1).End(xlUp).Row + 1
'Redefine the top row of the next block of data
i = BottomRow
'Repeat the process
Next i
End Sub
Sub copyNonblankData()
Dim erow As Long, lastrow As Long, i As Long
lastrow = Sheet1.Cells(Rows.Count, 1).End(xlUp).Row
For i = 2 To lastrow
If Sheet1.Cells(i, 1) <> "" Then
' i'm assuming the next line is the 8th line?
Sheets("Sheet1").Range(Cells(i, 1), Cells(i, 2)).Copy
Sheets("Sheet2").Activate
' error occurs here
erow = Sheet2.Cells(Rows.Count, 1).End(xlUp).Row.Offset(1, 0).Row
ActiveSheet.Paste Destination:=Sheets("Sheet2").Range(Cells(erow, 1), Cells(erow, 2))
Sheets("Sheet1").Activate
End If
Next i
Application.CutCopyMode = False
End Sub
The Offset property in Excel VBA takes the range which is a particular number of rows and columns away from a certain range.
Sheet2.Cells(Rows.Count, 1).End(xlUp).Row will give you Long and not a Range Object.
Your code can be written as
Dim rng As Range
Set rng = Sheet2.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0)
erow = rng.Row
Or simply as
erow = Sheet2.Cells(Rows.Count, 1).End(xlUp).Row + 1
Also your code will work if the relevant sheet is active. You need to fully qualify your cells as shown in Why does Range work, but not Cells?
TIP
If you are using CodeName then use CodeName and avoid using the Name of the sheet. And if you are using Name then avoid using Codename. You will end up getting confused. If you do not know the difference between them, then you may want to see Refer to sheet using codename
Remember you will get the same error (Object required) again if the Codename doesn't exist. BTW if the Name of the sheet doesn't exist then you will get a different error (Subscript Out Of Range).
so if erow = Sheet2.Cells(Rows.Count, 1).End(xlUp).Row + 1 gives the same error then that means Sheet2 doesn't exist. Try with
erow = Sheets("Sheet2").Cells(Rows.Count, 1).End(xlUp).Row + 1
I'm new with Macro and I want to create a simple copy and paste excel formula from one sheet to another. But the thing is the main data has a formula inside the cell and it wont let me copy and paste as values it to another cell.
Sub selectpasting()
Dim Lastrow As Long, erow As Long
Lastrow = Sheets("attendance").Cells(Rows.Count, 1).End(xlUp).Row
For i = 3 To Lastrow
If Sheets("attendance").Cells(i, 3) = "absent" Then
Sheets("attendance").Cells(i, 1).copy
erow = Sheets("forpasting").Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
Sheets("attendance").Paste Destination:=Sheets("forpasting").Cells(erow, 1)
Sheets("attendance").Cells(i, 3).copy
Sheets("attendance").Paste Destination:=Sheets("forpasting").Cells(erow, 2)
End If
Next i
Application.CutCopyMode = False
Sheets("forpasting").Columns.AutoFit
Range("A1").Select
End Sub
Change this row:
Sheets("attendance").Paste Destination:=Sheets("forpasting").Cells(erow, 1)
To:
Sheets("forpasting").Cells(erow, 1).PasteSpecial xlValues
The complete code would be:
Sub selectpasting()
Dim Lastrow As Long, erow As Long
Dim i As Long
Lastrow = Sheets("attendance").Cells(Rows.Count, 1).End(xlUp).Row
For i = 3 To Lastrow
If Sheets("attendance").Cells(i, 3) = "absent" Then
Sheets("attendance").Cells(i, 1).Copy
erow = Sheets("forpasting").Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
Sheets("forpasting").Cells(erow, 1).PasteSpecial xlValues
Sheets("attendance").Cells(i, 3).Copy
Sheets("forpasting").Cells(erow, 2).PasteSpecial xlValues
End If
Next i
Application.CutCopyMode = False
Sheets("forpasting").Columns.AutoFit
Range("A1").Select
End Sub
The code above is quite slow (try both the codes and you would notice that the below is way faster).. The reason is that in the above excel needs to determine/evaluate if the the cell properties needs to be pasted or not due to ".copy". It's one approach when you need to copy/paste cell formats etc.
In your case you only interested in the value the cells shows. So you could just pick the value and copy it.
I would therefore recommend you to change it to:
Sub selectpasting_2()
Dim Lastrow As Long, erow As Long
Dim i As Long
Lastrow = Sheets("attendance").Cells(Rows.Count, 1).End(xlUp).Row
For i = 3 To Lastrow
If Sheets("attendance").Cells(i, 3) = "absent" Then
erow = Sheets("forpasting").Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
Sheets("forpasting").Cells(erow, 1) = Sheets("attendance").Cells(i, 1)
Sheets("forpasting").Cells(erow, 2) = Sheets("attendance").Cells(i, 3)
End If
Next i
Application.CutCopyMode = False
Sheets("forpasting").Columns.AutoFit
Range("A1").Select
End Sub
I'm trying to copy data from columns AJ through AQ from one workbook and paste the values in a new workbook. The number of rows is variable (dependent on the user). I've tried implementing the following code, but it only pastes the first row into the new workbook:
Dim i, j, LastRow, LastRow2
Set OldBook = ActiveWorkbook
Set NewBook = Workbooks.Add(xlWBATWorksheet)
With NewBook
.ActiveSheet.Name = "GMD"
End With
OldBook.Activate
Sheets("Entry Sheet").Select
LastRow = ActiveSheet.Range("AJ" & Rows.Count).End(xlUp).Row ''Finds the last row of the column with text
LastRow2 = ActiveSheet.Range("AQ" & Rows.Count).End(xlUp).Row ''Finds the last row of the column with text
For i = 1 To LastRow ''Sets the range of rows to be copied including header
Range(Cells(i, 36), Cells(i, 43)).Select ''Selects relevant columns
Selection.Copy
NewBook.Activate
Range("A1").Select
Selection.PasteSpecial Paste:=xlPasteValues
OldBook.Activate
Sheets("Entry Sheet").Select
Next i
For j = 1 To LastRow ''Sets the range of Rows to be copied including header
Range(Cells(j, 43), Cells(j, 44)).Select ''Selects relevant columns
Selection.Copy
NewBook.Activate
Range("H1").Select
ActiveSheet.Paste
OldBook.Activate
Sheets("Entry Sheet").Select
Next j
Any observations on what I'm doing wrong?
The problem is that in you paste section you are only calling the first cell and it is in the loop so each time the loop will paste in cell A1.
Also if all you want is values, it is best to skip the clipboard and assign the values directly. With this you can avoid the loop all together.
Thirdly avoid using the select.
Edit: Removed loop and added the wrap text for the line breaks.
Dim i, LastRow
Dim ws As Worksheet
Set oldbook = ActiveWorkbook
Set ws = oldbook.Sheets("Entry Sheet")
Set newbook = Workbooks.Add(xlWBATWorksheet)
With newbook
.ActiveSheet.Name = "GMD"
End With
With ws
LastRow = .Range("AJ" & .Rows.Count).End(xlUp).Row ''Finds the last row of the column with text
newbook.Sheets("GMD").Range(newbook.Sheets("GMD").Cells(1, 1), newbook.Sheets("GMD").Cells(LastRow, 7)).Value = .Range(.Cells(1, 36), .Cells(LastRow, 43)).Value
End With
newbook.Sheets("GMD").Range("H:I").WrapText = True
The code I have placed below is a combination of what works and what i can't get to work.
The code that is not commented will copy cells to "sheet2" from "sheet1".
What I cannot get to work correctly is the code that I have disabled that would replace my Range Method of coping from "sheet1" to "sheet2".
Also my If Then Code is what will some up what I'm trying to accomplish. I'm trying to get the If statement to search all of column A and copy all Cars that are year 1991 to sheet2.
Mind my poor coding skills I'm Doing my best to show & explain so I can be helped.
Here is the Sheets 1 & 2
(hxxp://s15.postimg.org/orfw7tlaz/test.jpg)
OLD CODE
Sub Macro1()
Set a = Sheets("Sheet1")
Set b = Sheets("Sheet2")
Set c = Sheets("Sheet3")
Dim x
Dim z
Dim lastrow As Long, erow As Long
x = x + 1
z = 2
'lastrow = Sheet1.Cells(Rows.Count, 1).End(xlUp).Row
'lastrow = b.Cells(Rows.Count, 1).End(xlUp).Row
'For i = 2 To lastrow
lastrow = b.Range("A" & Rows.Count).End(xlUp).Row + x
'If a.Cells(i, 1) = “1991” Then
'a.Cells(i, 1).Copy
'erow = b.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
'b.Paste Destination:=b.Range.Cells(erow, 4)
Range("A" & z).Copy Destination:=b.Range("D" & lastrow)
'a.Cells(i, 1).Copy
'b.Paste Destination:=b.Range.Cells(erow, 1)
Range("B" & z).Copy Destination:=b.Range("A" & lastrow)
'a.Cells(i, 1).Copy
'b.Paste Destination:=b.Range.Cells(erow, 3)
Range("C" & z).Copy Destination:=b.Range("C" & lastrow)
'a.Cells(i, 1).Copy
'b.Paste Destination:=b.Range(erow, 2)
Range("D" & z).Copy Destination:=b.Range("B" & lastrow)
'End If
'Next i
Application.CutCopyMode = False
Sheet2.Columns().AutoFit
'b.Range("A1").Select
End Sub
So I added some Lines and Began changing the cell locations to reflect the format I need and now when I run the macro it only copys the very last line from Sheet1 to sheet2. I believe it has to do with the order of the way these cells are.
b.Cells(erow, 1) = a.Cells(i, 1)
b.Cells(erow, 2) = a.Cells(i, 2)
b.Cells(erow, 3) = a.Cells(i, 3)
b.Cells(erow, 4) = a.Cells(i, 4)
Changing these back fixes it so it copys all the cells but its not what I'm trying to do.
The Code I'm Trying to run is Below
NEW CODE Working Thanks to EntryLevel!
Sub TakeTwo()
Dim a As Worksheet
Dim b As Worksheet
Dim c As Worksheet
Set a = ThisWorkbook.Sheets("Sheet1")
Set b = ThisWorkbook.Sheets("Sheet2")
Set c = ThisWorkbook.Sheets("Sheet3")
Dim i As Long
Dim lastrowsheet1 As Long
Dim erow As Long
lastrowsheet1 = a.Cells(Rows.Count, 1).End(xlUp).Row
erow = b.Cells(b.Rows.Count, 1).End(xlUp).Offset(1, 0).Row
For i = 2 To lastrowsheet1
If a.Cells(i, 1).Value = "AEM" Then
b.Cells(erow, 31) = a.Cells(i, 1) '<------When I modify these
b.Cells(erow, 6) = a.Cells(i, 4) '<------The copied cells
b.Cells(erow, 28) = a.Cells(i, 5) '<------Don't show up
b.Cells(erow, 26) = a.Cells(i, 6) '<------In Sheet2
b.Cells(erow, 46) = a.Cells(i, 11) '<------Only the last
b.Cells(erow, 29) = a.Cells(i, 14) '<------Line found Is copied to sheet2
erow = erow + 1
End If
Next i
Application.CutCopyMode = False
b.Columns.AutoFit
'b.Range("A1").Select
End Sub
Now Using Same Working Code But Different function Not Working
Sub TakeThree()
Dim a As Worksheet
Dim b As Worksheet
Dim c As Worksheet
Set a = ThisWorkbook.Sheets("Sheet1")
Set b = ThisWorkbook.Sheets("Sheet2")
Set c = ThisWorkbook.Sheets("Sheet3")
Dim i As Long
Dim lastrowsheet1 As Long
Dim erow As Long
lastrowsheet1 = c.Cells(Rows.Count, 1).End(xlUp).Row
erow = b.Cells(b.Rows.Count, 1).End(xlUp).Offset(1, 0).Row
For i = 2 To lastrowsheet1
If c.Cells(i, 1).Value = b.Cells(erow, 6).Value Then 'If serial number is found from sheet2 column 6 in sheet3 Column 1
b.Cells(erow, 8) = c.Cells(i, 2) 'Then copy description from sheet3 cell row to Sheet2 cell row
erow = erow + 1
End If
Next i
Application.CutCopyMode = False
b.Columns.AutoFit
c.Columns.AutoFit
'b.Range("A1").Select
End Sub
So I added another For Loop with Dim r and added another Line erow = erow + r & now the code copys the first 2 rows needed but does not continue iterating down the list. which is confusing me. here is the code below i have added.
Dim r As Long
Dim i As Long
Dim lastrowsheet1 As Long
Dim erow As Long
lastrowsheet1 = c.Cells(Rows.Count, 1).End(xlUp).Row
erow = b.Cells(b.Rows.Count, 1).End(xlUp).Offset(1, 0).Row
For r = 1 To erow
For i = 2 To lastrowsheet1
If c.Cells(i, 1) = b.Cells(erow, 6) Then
b.Cells(erow, 8) = c.Cells(i, 2)
erow = erow + r
End If
Debug.Print i
Next i
Next r
Based on your statement that I'm trying to get the If statement to search all of column A and copy all Cars that are year 1991 to sheet2, it seems like Autofilter might be an easier solution than looping. You should be able to use something like this:
Sub TestyTestTest()
Dim lastrowsheet1 As Long
Dim lastrowsheet2 As Long
With ThisWorkbook.Sheets("Sheet1")
.AutoFilterMode = False
lastrowsheet1 = .Cells(.Rows.Count, 1).End(xlUp).Row
.Range(.Cells(1, 1), .Cells(lastrowsheet1, 4)).AutoFilter Field:=1, Criteria1:="1991"
.Range(.Cells(2, 1), .Cells(lastrowsheet1, 4)).SpecialCells(xlCellTypeVisible).Copy
.AutoFilterMode = False
End With
With ThisWorkbook.Sheets("Sheet2")
.AutoFilterMode = False
lastrowsheet2 = .Cells(.Rows.Count, 1).End(xlUp).Row
.Cells(lastrowsheet2 + 1, 1).PasteSpecial Paste:=xlPasteValues
.AutoFilterMode = False
End With
Application.CutCopyMode = False
End Sub
EDIT:
Trying to stick close to your original code, would something like this be more like what you are looking for?
Sub TakeTwo()
Dim a As Worksheet
Dim b As Worksheet
Dim c As Worksheet
Set a = ThisWorkbook.Sheets("Sheet1")
Set b = ThisWorkbook.Sheets("Sheet2")
Set c = ThisWorkbook.Sheets("Sheet3")
Dim i As Long
Dim lastrowsheet1 As Long
Dim erow As Long
lastrowsheet1 = a.Cells(Rows.Count, 1).End(xlUp).Row
For i = 2 To lastrowsheet1
If a.Cells(i, 1).Value = 1991 Then
erow = b.Cells(b.Rows.Count, 1).End(xlUp).Offset(1, 0).Row
b.Cells(erow, 1) = a.Cells(i, 1)
b.Cells(erow, 2) = a.Cells(i, 2)
b.Cells(erow, 3) = a.Cells(i, 3)
b.Cells(erow, 4) = a.Cells(i, 4)
End If
Next i
Application.CutCopyMode = False
b.Columns.AutoFit
End Sub
SECOND EDIT - OP's NEW PROBLEM:
It looks like your data is just pasting over itself because erow is defined as the row after the last row in column 1 that is not empty, but you are not actually putting any data into that column, so erow isn't moving down to the next line.
Basically, change the column number in this line:
erow = b.Cells(b.Rows.Count, 1).End(xlUp).Offset(1, 0).Row
The 1 in b.Cells(b.Rows.Count, 1) should be changed to a column number that you paste data into every time. Alternatively, you could use erow as a counter and increment it manually each time through the loop. In that case move the existing line that defines erow up underneath the line that defines lastrowsheet1 and then put erow = erow + 1 inside the loop after all the pasting has taken place but before End if. If you put it after End If, you'll end up with a bunch of blank lines between your data.