3

I am creating a macro but I am stuck at this cut paste statement and not able to proceed since yesterday.

Here is the problem: I am selecting all the rows in column "D2 to F2" and pasting it at "A1". Here is the code for it :

Range("D2:F2").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Cut

Range("A1").Select
Selection.End(xlDown).Select
ActiveCell.Offset(1, 0).Select
ActiveSheet.Paste    

Getting this Error:
Error

Here's what I have tried :

  1. Code Change: Using PasteSpecial instead of simple Paste.

    Range("D2:F2").Select
    Range(Selection, Selection.End(xlDown)).Select
    Selection.Cut
    
    Range("A1").Select
    Selection.End(xlDown).Select
    ActiveCell.Offset(1, 0).Select
    'ActiveSheet.Paste  ' insted of this using paste special.
    ActiveSheet.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
    

Getting the following error:
enter image description here

  1. Code Change: Resized the selection to 3 columns.

    Range("D2:F2").Select
    Range(Selection, Selection.End(xlDown)).Select
    Selection.Cut
    
    Range("A1").Select
    Selection.End(xlDown).Select
    ActiveCell.Offset(1, 0).Resize(1, 3).Select
    'ActiveSheet.Paste
    

Getting this error:
enter image description here

  1. Tried On Error Resume Next statement. It is ignoring the error message but not pasting the data as well.

I am looking for a way to ignore this error message and proceed with paste. We normally get this error when we manually copy-paste or cut-paste in excel sheet, there we have option to ignore and paste data. Similarly is there any method to ignore it within a macro?

Sandeep Kushwah
  • 590
  • 1
  • 18
  • 35
  • 4
    Don't use `Select`. – David Zemens Sep 28 '16 at 14:21
  • 5
    I'm pretty sure your original selection to copy goes all the way to teh bottom of the worksheet. Because of this, the copied cells are too large to fit into the target. . See [How to avoid using Select in Excel VBA macros](http://stackoverflow.com/questions/10714251/how-to-avoid-using-select-in-excel-vba-macros) for more on getting away from relying on select and activate to accomplish your goals. –  Sep 28 '16 at 14:22
  • 2
    Use only the single top-left cell to designate a target paste area for the copied cells. –  Sep 28 '16 at 14:23
  • giving it a try, will keep you updated. – Sandeep Kushwah Sep 28 '16 at 14:26

3 Answers3

6

Avoid Select at all costs. Try something like this instead

Sub foo()
Dim rng
Set rng = Range("D2:F" & GetLastRow(4))

rng.Cut
Application.Goto Range("A1").Offset(GetLastRow(1))
ActiveSheet.Paste

End Sub

Function GetLastRow(col As Long)
' modified from:
' https://stackoverflow.com/questions/11169445/error-in-finding-last-used-cell-in-vba

If Application.WorksheetFunction.CountA(Columns(col)) <> 0 Then
    GetLastRow = Columns(col).Find(What:="*", _
                  After:=Cells(Rows.Count, col), _
                  Lookat:=xlPart, _
                  LookIn:=xlFormulas, _
                  SearchOrder:=xlByRows, _
                  SearchDirection:=xlPrevious, _
                  MatchCase:=False).Row
Else
    GetLastRow = 1
End If

End Function
Community
  • 1
  • 1
David Zemens
  • 53,033
  • 11
  • 81
  • 130
  • 1
    I am getting "Object doesn't support this property or method." error (I have data in `D2:F10`) in `Range("A1").Paste`. Any guess what is wrong? – RCaetano Sep 28 '16 at 14:48
  • Try `Set rng = Range(rng.Address, rng.End(xlDown).Address)` – David Zemens Sep 28 '16 at 14:49
  • @RCaetano I am also getting the same but was trying to figure. Thanks you asked it. I will try david 's suggestion – Sandeep Kushwah Sep 28 '16 at 14:55
  • the assignment to `rng` object works correctly, which line is raising the error? – David Zemens Sep 28 '16 at 14:57
  • @DavidZemens Range("A1").Paste is causing the error. – Sandeep Kushwah Sep 28 '16 at 14:58
  • 1
    What is below range D2:F2 in the sheet? Do you have any merged cells? – Excel Developers Sep 28 '16 at 15:03
  • @ExcelDevelopers its very high 1048576. – Sandeep Kushwah Sep 28 '16 at 15:08
  • Try another revision, though I don't think that would make a difference if you select the single cell "A2" , etc., you should still be able to paste 3 columns there. However, if there are merged cells in column A, or if part of column A is locked/protected, then you may get a 1004. – David Zemens Sep 28 '16 at 15:12
  • @DavidZemens The problem is I don't want to paste on `Range("A1")`, I want to come end blank row or `A1` and then paste the selected data. Your selection thing is perfect. Even paste is perfect only if i want to paste to `A1` but as soon as I apply `End(xlDown)` and `Offset` its beaks :( – Sandeep Kushwah Sep 28 '16 at 15:22
  • Then the problem would seem to be that the range you're *cutting* is too big to fit in the destination. Too many rows, will exceed the limit of the worksheet, and raise the 1004 error. – David Zemens Sep 28 '16 at 15:29
  • I made a revision to get the last row more appropriately, however this can still fail if the sheet cannot accommodate the pasted data (i.e., if the cut range, when pasted, would overflow the available rows in the worksheet). – David Zemens Sep 28 '16 at 15:47
  • Yeah! This one worked :). Just changed `GetLastRow = 2` in `GetLastRow` function as I need results starting from 2nd row. Thank you very much :). Could you please tell me what exactly `Application.WorksheetFunction.CountA(Columns(col))` does? – Sandeep Kushwah Sep 28 '16 at 16:48
  • @SandeepKushwah the [COUNTA](https://support.office.com/en-us/article/COUNTA-function-7dc98875-d5c1-46f1-9a82-53f3219e2509) function counts the number of non-empty cells in a range. – David Zemens Sep 28 '16 at 16:55
  • @DavidZemens : Why you passed `4` in the function argument? Should it be `6` for F right? – Sandeep Kushwah Sep 28 '16 at 17:40
  • @SandeepKushwah For my testing, I assumed that columns D, E and F all contained the same number of data rows in which case the choice of column number won't matter. If you need to scan from Column F (maybe Column D has not as much data?) then yes, you'll need to use 6 as the argument.. – David Zemens Sep 28 '16 at 17:56
  • 1
    @DavidZemens Thanks! got the concept. – Sandeep Kushwah Sep 28 '16 at 18:44
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/124459/discussion-between-sandeep-kushwah-and-david-zemens). – Sandeep Kushwah Sep 28 '16 at 19:06
1

As mentioned in other answers and comments avoid the use of .Select at all costs. It is the source of many common errors. The next solution finds the last row with data by using a simple function.

Option Explicit

Function lastrow(rng_str As String)

    ' Adapted from http://www.rondebruin.nl/win/s9/win005.htm
    Dim rng As Range: Set rng = Range(rng_str)
    Dim r As Range
    lastrow = rng.Column

    With ActiveSheet
        For Each r In rng.Columns
            lastrow = Application.Max(lastrow, .Cells(.Rows.Count, r.Column).End(xlUp).Row)
        Next
    End With

End Function

Sub test()

    Dim source_rng As Range
    Dim dest_rng As Range
    Dim nr_rows As Long

    ' Maximum number of rows from D to F
    nr_rows = lastrow("D2:F2")

    Set source_rng = Range("D2:F" & nr_rows)
    Set dest_rng = Range("A1")

    source_rng.Cut
    dest_rng.Activate
    ActiveSheet.Paste

End Sub

HTH ;)

RCaetano
  • 642
  • 1
  • 8
  • 23
  • Thanks for your efforts! The approach was correct just implementing the same in paste selection would have resulted in the SOLUTION. Thanks!!! – Sandeep Kushwah Sep 28 '16 at 16:50
0

The problem is that you are trying to select a cell, which is one cell below the end of the table. After the stop, you have an offset, which gives you one cell lower. Check this out:

Option Explicit
Sub test()
    Range("D2:F2").Select
    Range(Selection, Selection.End(xlDown)).Select
    Selection.Cut

    Range("A1").Select
    Selection.End(xlDown).Select

    Debug.Print ActiveCell.Address
    Stop

    ActiveCell.Offset(1, 0).Select
    ActiveSheet.Paste

End Sub

And, as already said, try to avoid select.

Vityata
  • 42,633
  • 8
  • 55
  • 100