1

我是 VBA 新手,基本上是在尝试编写我的第一个宏。它旨在将条目从一个工作簿复制到另一个忽略重复值的工作簿。我有以下代码:

Dim s As String

Do While IsEmpty(ActiveCell) = False

If ActiveCell.Value <> s Then
    s = ActiveCell.Value
    ActiveCell.Offset(1, 0).Select
    Windows("Main.xlsm").ActiveCell.Value = s
    Windows("Main.xlsm").ActiveCell.Offset(1, 1).Select


Else
    ActiveCell.Offset(1, 0).Select

End If
Loop

它给了我这一行的运行时错误 1004:

Windows("Main.xlsm").ActiveCell.Offset(1, 1).Select

这意味着方法 Select 无法正常工作。(我打开了“Main.xlsm”但未激活,并且选择了一个单元格。)我搜索了类似的问题,发现可能是因为我没有选择工作表。但不知何故,这条线有效:

  Windows("Main.xlsm").ActiveCell.Value = s

我可以看到工作簿“Main.xlsm”中的单元格发生了变化。所以,我假设Windows("Main.xlsm").ActiveCell确实创建了一个 Range 对象。

那么为什么会发生错误呢?写这个的正确方法是什么?

我也尝试将我的代码更改为:

    Windows("Main.xlsm").ActiveSheet.ActiveCell.Value = s
    Windows("Main.xlsm").ActiveSheet.ActiveCell.Offset(1, 1).Select

这给了我:“运行时错误 438 对象不支持此属性或方法”。这是为什么?这里有什么不正确的?

并:

 Windows("Main.xlsm").Sheets("Name").ActiveCell.Value = s
 Windows("Main.xlsm").Sheets("Name").ActiveCell.Offset(1, 1).Select

结果是一样的。而且我仍然不明白为什么最后两个不起作用。

这是我在这里的第一篇文章,所以如果我的编辑或其他任何错误,请纠正我。谢谢!

4

1 回答 1

1

使用ActiveCell, Selectetc 不是一个好主意。浏览 SO Excel 标签,您会发现许多反对它的答案,其中许多都很好地解释了原因。对于我的一个看到这个问题

相反,声明RangeWorksheet变量并将它们分配给您的范围和工作表

Dim wbSource as WorkBook
Dim wsSource as WorkSheet

Set wbSource = Application.Workbooks("Main.xlsm")
Set wsSource = wbSource.Worksheets("Name")

要使用 VBA 所在的工作簿,请使用ThisWorkbook对象

如果要从活动工作表开始,通常可以使用

Dim sh as Worksheet
Set sh = ActiveSheet

要使用范围,请使用类似

Dim rng as Range

' Set to a specific range
Set rng = Range sh.Range("A1:D10")
' or
With sh
    Set rng = .Range(.Cells(1,1), .Cells(10,4))
End With

' Set to all used cells in a column
With sh
    Set rng = .Range(.Cells(1,1), .Cells(.Rows.Count,1).End(xlUp))
End With

' Adjust rng
Set rng = rng.Offset(1,0)
Set rng = rng.Resize(10,1)

所以,重构你的代码片段

Dim s As String
Dim rng as Range, cl as Range
Dim shSource as Worksheet
Dim rngDestination as Range

Set shSource = Application.Workbooks("Main.xlsm").Worksheets("SheetName")
Set rngDestination = shSource.Range("A1") ' Change to whatever you need here

Set rng = ActiveCell ' if you must!

' Just in case only one cell entry exists, avoid selecting down to bottom of sheet
If Not IsEmpty(rng.Offset(1,0)) Then
    Set rng = Range(rng, rng.End(xlDown)) ' unqualified Range (ie no sh. part) refers to the active sheet
End IF

For Each cl In rng
    If cl.Value <> s Then
        s = cl.Value
        rngDestination.Value = s
        Set rngDestination = rngDestination.Offset(1, 1) ' should this be .Offset(1, 0) ?
    End If
Next
于 2012-09-14T11:11:53.757 回答