This question already has answers here:
Copy Non Blank Cells From Range to Range
(2 answers)
Closed 2 years ago.
I am having difficulty having this macro copy and paste only the cells that have data in them. I would like the macro to only select and copy the cells in the columns that have data, ignore the empty cells. what I currently have is this
Sub testest()
Sheet4.Activate
'Dim lrow As Long
'lrow = Sheet4.Range("A", Rows.Count).End(xlUp).Row
Sheet4.Range("A2:A40").Select
Selection.Copy
Sheet5.Activate
Sheet5.Range("A2").PasteSpecial
Sheet4.Activate
Sheet4.Range("B2:B40").Select
Selection.Copy
Sheet5.Activate
Sheet5.Range("B2").PasteSpecial
End Sub
If you want them to paste only the cells with data by shifting the other cells up to fill in the blank ones, you should try the following commands after you select your desired copy range:
Selection.SpecialCells(xlCellTypeBlanks).Select
Selection.Delete Shift:=xlUp
This logic mirrors going to "Find and Select" > "Blanks" > "Delete"
This is not an answer to your question, merely a way to show you how to reduce your code, by eliminating the obsolete activation and selection actions:
Sub testest()
Sheet4.Range("A2:A40").Copy
Sheet5.Range("A2").PasteSpecial
Sheet4.Range("B2:B40").Copy
Sheet5.Range("B2").PasteSpecial
End Sub
In fact, why don't you simply do this:
Sheet4.Range("A2:B40").Copy
Sheet5.Range("A2").PasteSpecial
(Ranges can go over different columns)
There are ways to avoid the usage of the clipboard, but then the complexity of the macro increases, which, I believe, is not what you're looking for.
Similar to the answer by #Dominique, but addressing the empty cells and assuming you gave up on the last row method:
Sub testest()
Dim lrow As Long
lrow = Sheet4.Range("A", Rows.Count).End(xlUp).Row
Sheet4.Range("A2:A" & lrow).SpecialCells(xlCellTypeVisible).Copy
Sheet5.Range("A2").PasteSpecial
Sheet4.Range("B2:B" & lrow).SpecialCells(xlCellTypeVisible).Copy
Sheet5.Range("B2").PasteSpecial
End Sub
Related
This question already has answers here:
Excel VBA Delete Rows
(1 answer)
Faster way to delete rows 40k+ rows at once
(2 answers)
Closed 3 years ago.
The below code only seems to work on the first result. I have to re-run it for the other results to be removed. Could anyone take a look and tell me why please? Thanks
I've tried copy and pasting the code several times to compensate but it gives me an error about duplicate code
Dim cell As Range
For Each cell In [AE1:AE2000]
If cell.Value = "REMOVE" Then Range(cell.Offset(0, -5).Address & ":" & cell.Offset(0, 0).Address).Delete Shift:=xlUp
Next cell
One thing you must do when deleting rows is loop backwards; otherwise you may skip rows, which is what is happening to you by the sounds of it. You have to use a counter when looping backwards, such as
Sub x()
Dim r As Long, cell As Range
Set cell = Range("AE1:AE2000")
For r = cell.Count To 1 Step -1
If UCase(cell(r).Value) = "REMOVE" Then
Range(cell(r).Offset(0, -5), cell(r)).Delete Shift:=xlUp
End If
Next r
End Sub
I'm attempting to make a macro which will autofill a number of pages based on how many is actually needed. Each item, imported from another workbook, would receive its own 'page'. These pages are on one sheet, separated by print area. Currently I have a counter which counts the number of items that need pages (11 in my example), then I have a value for number of rows per page (34). Those are multiplied together to determine how many rows to autofill to (374). The issue is getting the macro to replace the range variable with the number (374).
I've tried to use the Indirect function but receive a compile error: "Expected: List separator or )"
I've also attempted the Offset function but receive the same error.
This is my Macro so far:
Sub Sheet_Fill()
Sheet_Fill Macro
ActiveCell.Range("A1:I34").Select
Selection.AutoFill Destination:=ActiveCell.Range("A1:I68"), Type:= _
xlFillDefault
ActiveCell.Range("A1:I68").Select
End Sub
Essentially, I want to replace the "I68" with something that will autofill the row number of the I column with my formula mentioned earlier. In the example case of 11 parts, the number would be autofilled with "374"
The raw version of your macro should be something like this:
Sub Sheet_Fill()
'Sheet_Fill Macro
Dim rownum As Long
rownum = 374 'Or a range? Where is this number located?
ActiveCell.Range("A1:I34").Select
Selection.AutoFill Destination:=ActiveCell.Range("A1:I" & rownum), Type:= _
xlFillDefault
ActiveCell.Range("A1:I" & rownum).Select
End Sub
Cleaned up a bit (this should work):
Sub Sheet_Fill()
Dim rownum As Long
rownum = 374 'Or a range? Where is this number located?
Range("A1:I34").AutoFill Destination:=ActiveCell.Range("A1:I" & rownum), Type:=xlFillDefault
End Sub
Need some more details from you on where you're storing this 374 - is it in a cell? Can it be calculated from your table setup? Until those answers are given, this is the best I can do.
Try:
Selection.AutoFill Destination:=ActiveCell.Range("A1:I" & lr), Type:= xlFillDefault
Where lr is last row... you would either want to determine this dynamically, or you could assign the to pull a value from a cell, e.g.:
'dynamic
lr = sheets(1).cells(sheets(1).rows.count,1).end(xlup).row
'from a cell
lr = sheets(1).range("A1").value
General comment... avoid using select/activate!
I am working with multiple sheets within a workbook. Each sheet has an identical header row. I would like to write a macro to copy a range of data from each sheet (A2:L2 to the last row of data on a sheet) and paste it into the first empty cell in Column A of master sheet.
What I have below doesn't seem to work. Any assistance is appreciated.
Dim Lastrow As Integer
Lastrow = ActiveSheet.Cells(Rows.Count,1).End(xlUp).Row
Sheets("Master Sheet").Range("A2:L10000).Clear
Sheets("Sheet1").Activate
Range("A2:L" & Lastrow).Select
Selection.Copy
Sheets("Master Sheet").Select
Range("A30000").Select
Selection.End(xlUp).Select
ActiveCell.Offset(1,0).Range("A1").Select
ActiveSheet.Paste
Sheets("Sheet2").Activate
Range("A2:L" & Lastrow).Select
Selection.Copy
Sheets("Master Sheet").Select
Range("A30000").Select
Selection.End(xlUp).Select
ActiveCell.Offset(1, 0).Range("A1").Select
ActiveSheet.Paste
You're almost there from the looks of it. It looks like you've recorded a macro which is a good place to start. The reason your specific code might not work is because of Sheets("Master Sheet").Range("A2:L10000).Clear. You're missing the end quote inside of the range. In any case though, I've chosen to leave that out so you don't accidentally clear your sheet when you're moving data across
So generally it's good to avoid using select and activate, but with a recorder you don't have much say in the matter. Below you can see how I can do operations directly with the range.
It's important to find the last row of the master sheet as well as your current sheet each time so you know the range you want to copy and where you can paste it. It's important to remember that you're always finding the last filled cell, so in the case of a paste destination, you need to add one more to the row value so you don't accidentally overwrite some data.
For loops are pretty useful, I'm not sure what names you have for the rest of your sheets, but luckily in VBA you can use For each. so what this does is it cycles through every single item that you specify. In this case I've specified worksheets. The only problem now though, is we don't want to try copying and pasting into the same Master Sheet, so we need to do a quick check to make sure we're not on the master sheet. I've done this simply by comparing the name of the worksheet to what you've put as the name of the master sheet.
Interestingly when you copy something, you only need to specify the top left cell and it'll fill in the rest of it. It makes life a little easier because you don't need to figure out the exact dimensions of the array you're pasting. The Copy function in VBA has an optional parameter called Destination which you can use to tell it where you want to paste it right away.
It's also good to fully specify ranges when you're using them so instead of Range, you can see how I use ThisWorkbook.Worksheets("Master Sheet").Range. This tells the computer exactly where you want to reference; whereas Range makes the computer sort of guess, so it assumes you mean the active sheet, which might not be what you want.
Sub Paster()
Dim LastRowCurr As Long
Dim LastRowMaster As Long
Dim wksht As Worksheet
For Each wksht In ThisWorkbook.Worksheets
If Not wksht.Name = "Master Sheet" Then
LastRowCurr = wksht.Cells(wksht.Rows.Count, 1).End(xlUp).Row
LastRowMaster = Worksheets("Master Sheet").Cells(Worksheets("Master Sheet").Rows.Count, 1).End(xlUp).Row + 1
Range("A2:L" & LastRowCurr).Copy Destination:=ThisWorkbook.Worksheets("Master Sheet").Cells(LastRowMaster, "A")
End If
Next wksht
End Sub
I am attempting to select a dynamic range of filtered data that spans from col. A: col. J without selecting the header (in row 1). From there I need to copy and paste it into a new sheet where I will manipulate it further, but I cannot come up with an efficient or functional way to do this. Based on some code I found on another forum I was able to select all of the "visable cells" in a single column, but I am running into issues trying to select the whole range. I am still very new to vba so forgive my syntax, but my code posted below was an attempt to itterate through Rows.Count and i which was an integer 1-10. If you have any advice on how to do this better and more efficiently I would really appreciate it.
Sub SelectVisibleInColD()
Dim lRow As Long, i As Integer
Set i = 1
Do While i <= 10
With ActiveSheet
lRow = .Cells(.Rows.Count, i).End(xlUp).Row
If lRow < 3 Then Exit Sub
.Cells(1, 1).Offset(1, 0).Resize(lRow - 1).SpecialCells(xlCellTypeVisible).Select
End With
i = i + 1
Loop
End Sub
You can select a range by using Range property of ActiveSheet. You already have the last row and you know that the header is in the first row, so your range starts from position A2 and goes to the last row of column J
ActiveSheet.Range("A2:J"&lRow).SpecialCells(xlCellTypeVisible)
If you want to copy this range, use Copy function like
yourRangeAsAbove.Copy
This function only moves the selection to memory, to paste it, build your destination range and call PasteSpecial function.
I came across this answer googling my issue for: deleting of filtered selection in vba.
However trying your answer &lRow gives me an runtime error 1004, application-defineed or object-defined error
I got around it with this
ActiveSheet.Range("A2:G" & Range("A" & Rows.Count).End(xlUp).Row).SpecialCells(xlCellTypeVisible).Delete
For those that may also get the same issue.
I've found this Macro on another post:
Sub DelBlankRows()
Columns("A:A").Select
Selection.SpecialCells(xlCellTypeBlanks).Select
Selection.EntireRow.Delete
End Sub
Can this be modified so that it only deletes rows after row x (row 14 on the spreadsheet that I'm currently working on)?
Thanks!
this is fairly straightforward.
Rows(x & ":" & y).EntireRow.Delete
Just swap x and y for the rows you want.
As an aside, it is best to avoid selecting ranges unnecessarily as it only slows things down. Any time you select a range then do something with the selection, you can just perform that action directly on the range instead.
EDIT: Just re-read the question - so try this one:
Range("A14:A" & Cells.SpecialCells(xlCellTypeLastCell).Row).SpecialCells(xlCellTypeBlanks).EntireRow.Delete