EntireRow.Delete似乎删除了错误的行

时间:2017-06-18 08:07:08

标签: excel vba excel-vba

我有以下代码:

Sub test()
    Dim ws1 As Worksheet
    Dim ws2 As Worksheet
    Dim r As Long
    Dim rng As Range

    Set ws1 = Worksheets("Sheet1")
    Set ws2 = Worksheets("Sheet2")

    'Set some dummy data
    For r = 1 To 20
        ws1.Cells(r, "A").Value = r + 100
        ws2.Cells(r, "A").Value = r + 200
    Next

    'Set a reference to Sheet1!A11
    Set rng = ws1.Range("A11")

    'Copy Sheet1 row 11 to Sheet2 row 5
    rng.EntireRow.Cut ws2.Range("A5")

    'Delete Sheet1 row 11
    rng.EntireRow.Delete

End Sub

我为“Sheet1”的第11行中的单元格指定了引用。使用该引用,我Cut行到“Sheet2”上的某个位置,然后我使用该引用从“Sheet1”中删除整行。

我的期望是“Sheet1”的第11行将被删除,在第1行到第10行的第A列101到110中留下值,在第11到19行留下112到120.

正在发生的事情是第11行被清除(由于Cut)而第5行正在被删除。

代码执行后的图纸图像: Image of sheets after code runs

删除第5行的事实似乎与第5行是Cut语句的“Sheet2”上的目标行有关。如果它删除了“Sheet2”上的第5行,我可以理解发生了什么 - 即引用被重新命名为另一个工作表作为Cut的一部分 - 但它删除了“Sheet1”上的第5行。

任何人都可以解释这种奇怪的行为吗?

注意:这个问题的灵感来自我尝试撰写this answer,我对该问题的OP发表的许多评论告诉他们“当然EntireRow.Delete会删除你的行 - 你为什么要告诉我它不起作用“。

4 个答案:

答案 0 :(得分:1)

使用“复制”代替“剪切”

rng.EntireRow.Copy ws2.Range(“A5”)

删除时,sheet1 A11的行不必为空

这是一个更简单的版本,显示了不良行为

Sub test()

    Dim rng As Range

    Set rng = Sheets("Sheet1").Range("A11")
    rng.Value = "cut and paste me"

    Sheets("Sheet1").Range("A11").Cut Sheets("Sheet2").Range("A5")  ' rng object not used in this line

    rng.Select     ' selects Sheet1 A5  ...  it should be Sheet2 A5

End Sub

它似乎是excel中的一个错误

由于剪切/粘贴有效地移动了剪切范围,因此excel将引用移动到新位置

excel将引用移动到正确的单元格,但无法移动到正确的工作表

如果您手动进行剪切/粘贴,则正确移动参考

例如:

如果,sheet1单元格A1包含“= B1”

然后切割sheet1单元格B1并将其粘贴到sheet2单元格C3

然后sheet1单元格A1将包含“= sheet2!C3”

答案 1 :(得分:0)

试试我的代码:

Sub test()
    Dim ws1 As Worksheet
    Dim ws2 As Worksheet
    Dim r As Long
    Dim rng As Range

    Set ws1 = Worksheets("Sheet1")
    Set ws2 = Worksheets("Sheet2")

    'Set some dummy data
    For r = 1 To 20
        ws1.Cells(r, "A").Value = r + 100
        ws2.Cells(r, "A").Value = r + 200
    Next

    'Set a reference to Sheet1!A11
    Set rng = ws1.Range("A11")

    'Copy Sheet1 row 11 to Sheet2 row 5
    rng.EntireRow.Cut ws2.Range("A5")

    'Delete Sheet1 row 11
    Range("A:A").SpecialCells(xlCellTypeBlanks).EntireRow.Delete


End Sub

答案 2 :(得分:0)

正如@ASH所提到的,Debug.Print rng.Address(external:=True)操作之前和之后的Cut将分别打印结果[workbookName.xlsm]Sheet1!$A$11[workbookName.xlsm]Sheet1!$A$5,原因是它会剪切对象和粘贴进入指定目的地并获取其地址。

作为Worksheet对象成员的Range Object无法更改其父级,因此它将继续保留为ws1的成员。因此,尝试ws2.rng.EntireRow.Delete将生成编译错误“未找到方法或数据成员”。

答案 3 :(得分:0)

可能的解释 - 但没有任何借口可以解决这个不明显的问题:

1)为什么不更换表格呢? -     .Cut方法仅覆盖 Range 定义,因为它是     通过Worksheet从属于ws1 = Worksheets("Sheet1")对象集,     因此ws1对象只获得一个新的目标范围$ A $ 5,但仍然是原始工作表

2)为什么要将源范围更改为目标? -     IMO在方法代码本身中的极简主义。

3)该怎么做 - 重置原始范围(参见下面的代码):

Sub test()
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Dim r As Long
Dim rng As Range

Set ws1 = Worksheets("Sheet1")
Set ws2 = Worksheets("Sheet2")

'Set some dummy data
For r = 1 To 20
    ws1.Cells(r, "A").Value = r + 100
    ws2.Cells(r, "A").Value = r + 200
Next


' Set a reference to Sheet1!A11
  Set rng = ws1.Range("A11")
' Copy Sheet1 row 11 to Sheet2 row 5
  rng.EntireRow.Cut ws2.Range("A5")

' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' Possible explication - but no excuse for this not obvious comportment:
' 1) Why not changing the sheet, too? -
'    The CUT method overwrites only the RANGE definition because it is
'    subordinated to the worksheet object set via ws1 = Worksheets("Sheet1"),
'    thus the ws1 object only gets a new target range $A$5 but remains the original sheet
' 2) Why changing the source range to target? -
'    IMO sort of minimalism within the method code itself.
' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' >> check range definition after executing CUT - rng definitively remains in sheet1
  MsgBox "Range rng: " & rng.Worksheet.Name & "!" & rng.Address & vbNewLine & _
         "Entire row: " & rng.EntireRow.Address & " ", vbInformation, "rng.Address"

' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' If you want to do something with the original range you have to reset it
' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 ' >> reset rng before further action as deleting source
  Set rng = ws1.Range("A11")      ' << resetting rng necessary

' Delete Sheet1 row 11
  rng.EntireRow.Delete

End Sub