我是VBA的新手,在使用我想写的宏中的If语句时遇到了一些困难。每个月我都会在Excel中收到一份报告,其中列出了我们公司的哪些员工执行了某些任务。我正在编写的宏旨在将每个员工的数据复制并粘贴到主工作簿中。
我遇到的问题是定义我需要复制的范围。正如您在代码中看到的那样,员工列在B列中。我首先在B列中搜索员工。如果它们不存在,宏将在主工作簿中的名称下复制并粘贴(无) 。如果找到了自己的名字,则会将其名称下方的行设置为第一个变量。
这是我遇到问题的地方。下一步是找到列出的下一个员工,并将上面的行设置为第二个变量。然后我使用第一个和第二个变量来复制和粘贴该行范围。我正在使用If语句循环查找下一个列出的员工。但是,我的嵌套If语句在我的第二个Else if语句之后结束。有谁知道我可以写得更好吗?我尝试使用Select Case语句,但无法正确使用语法。
Sub EmployeeActivity()
Dim Employee1 As Integer, Employee2 As Integer, Employee3 As Integer, Employee4 As Integer
Dim EmployeeRange As Range, rngSelectFind As Range, rngPasteFind As Range
Windows("Activities Report.xlsm").Activate
Set rngSelectFind = Columns("B:B").Find(What:="Employee 1", After:=Range("B1"), LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext)
If Not rngSelectFind Is Nothing Then
Employee1 = rngSelectFind.Row + 1
ElseIf rngSelectFind Is Nothing Then
Set rngSelectFind = Columns("B:B").Find(What:="(none)", After:=Range("B1"), LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext)
Consultant3 = rngSelectFind.Row
End If
Set rngSelectFind = Columns("B:B").Find(What:="Employee 2", After:=Range("B1"), LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext)
If Not rngSelectFind Is Nothing Then
Employee2 = rngSelectFind.Row - 1
ElseIf rngSelectFind Is Nothing Then
Set rngSelectFind = Columns("B:B").Find(What:="Employee 3", After:=Range("B1"), LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext)
If Not rngSelectFind Is Nothing Then
Employee2 = rngSelectFind.Row - 1
End If
ElseIf rngSelectFind Is Nothing Then
Set rngSelectFind = Columns("B:B").Find(What:="(none)", After:=Range("B1"), LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext)
If Not rngSelectFind Is Nothing Then
Employee2 = rngSelectFind.Row - 1
End If
End If
If Employee1 > 0 And Employee2 > 0 Then
Set EmployeeRange = Range(Cells(Employee1, 2), Cells(Employee2, 7))
ElseIf Employee3 > 0 Then
Set EmployeeRange = Range(Cells(Employee3, 2), Cells(Employee3, 7))
End If
EmployeeRange.Select
Selection.Copy
Windows("Monthly Activity Report.xlsm").Activate
Sheets("April '13").Activate
Set rngPasteFind = Columns("A:A").Find(What:="Employee Activities", After:=Range("A1"), LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext)
If Not rngPasteFind Is Nothing Then
Employee4 = rngPasteFind.Row + 1
End If
Range(Cells(Employee4, 1), Cells(Employee4, 6)).Select
Selection.Insert (xlShiftDown)
End Sub
提前感谢您的帮助。如果我能提供更多背景信息,请告诉我。
答案 0 :(得分:1)
我注意到的事情很少。
请不要使用.Activate
和Selection
。直接使用该对象。您可能希望看到THIS
如果您使用的是.Find
,那么当您找不到匹配项时,请提供实例。你已经在几个地方做过这件事,但后来又错过了一些。
请勿将Employee1
,Employee2
等声明为Integer
。在Excel 2007+中,这可能会给您一个错误,因为Excel 2007+支持1048576行。请改用Long
。
我不确定为什么你不打算将它粘贴到任何地方时复制范围EmployeeRange
?我看到你宣布Paste
范围虽然......
请参阅此代码。这是你在尝试什么? (的 UNTESTED 强>)
Sub EmployeeActivity()
Dim Employee1 As Long, Employee2 As Long, Employee3 As Long, Employee4 As Long
Dim EmployeeRange As Range, rngSelectFind As Range, rngPasteFind As Range
Dim wb As Workbook, ws As Worksheet
Dim wb1 As Workbook, ws1 As Workbook
'~~> Change path as applicable
Set wb = Workbooks.Open("C:\Activities Report.xlsm")
'~~> Change this to the relevant sheet
Set ws = wb.Sheets("Sheet1")
'~~> Change path as applicable
Set wb1 = Workbooks.Open("C:\Monthly Activity Report.xlsm")
Set ws1 = wb.Sheets("April '13")
With ws
Set rngSelectFind = .Columns("B:B").Find(What:="Employee 1", _
LookIn:=xlValues, LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext)
If Not rngSelectFind Is Nothing Then
Employee1 = rngSelectFind.Row + 1
Else
Set rngSelectFind = .Columns("B:B").Find(What:="(none)", _
LookIn:=xlValues, LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext)
If Not rngSelectFind Is Nothing Then
Consultant3 = rngSelectFind.Row
End If
End If
Set rngSelectFind = Nothing
Set rngSelectFind = .Columns("B:B").Find(What:="Employee 2", _
LookIn:=xlValues, LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext)
If Not rngSelectFind Is Nothing Then
Employee2 = rngSelectFind.Row - 1
Else
Set rngSelectFind = .Columns("B:B").Find(What:="Employee 3", _
LookIn:=xlValues, LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext)
If Not rngSelectFind Is Nothing Then
Employee2 = rngSelectFind.Row - 1
Else
Set rngSelectFind = .Columns("B:B").Find(What:="(none)", _
LookIn:=xlValues, LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext)
If Not rngSelectFind Is Nothing Then
Employee2 = rngSelectFind.Row - 1
End If
End If
End If
If Employee1 > 0 And Employee2 > 0 Then
Set EmployeeRange = .Range(.Cells(Employee1, 2), _
.Cells(Employee2, 7))
ElseIf Employee3 > 0 Then
Set EmployeeRange = .Range(.Cells(Employee3, 2), _
.Cells(Employee3, 7))
End If
End With
'~~> I am not sure why are you copying this range???
If Not EmployeeRange Is Nothing Then EmployeeRange.Copy
With ws1
Set rngPasteFind = .Columns("A:A").Find(What:="Employee Activities", _
LookIn:=xlValues, LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext)
If Not rngPasteFind Is Nothing Then
Employee4 = rngPasteFind.Row + 1
.Range(.Cells(Employee4, 1), .Cells(Employee4, 6)).Insert (xlShiftDown)
End If
End With
End Sub
提示:您可以创建一个可以接受参数的公共.Find
函数。这样你可以大大减少上面的代码;)
修改强>
请参阅此示例( UNTESTED )以演示上述提示。这样您就不需要在代码中反复使用.Find
。
Sub EmployeeActivity()
Dim Employee1 As Long, Employee2 As Long
Dim Employee3 As Long, Employee4 As Long
Dim EmployeeRange As Range, rngSelectFind As Range, rngPasteFind As Range
Dim wb As Workbook, ws As Worksheet
Dim wb1 As Workbook, ws1 As Workbook
'~~> Change path as applicable
Set wb = Workbooks.Open("C:\Activities Report.xlsm")
'~~> Change this to the relevant sheet
Set ws = wb.Sheets("Sheet1")
'~~> Change path as applicable
Set wb1 = Workbooks.Open("C:\Monthly Activity Report.xlsm")
Set ws1 = wb.Sheets("April '13")
With ws
Employee1 = GetRow(ws, 2, "Employee 1")
If Employee1 <> 0 Then
Employee1 = Employee1 + 1
Else
Consultant3 = GetRow(ws, 2, "(none)")
End If
'
'And So on
'
End Sub
Function GetRow(wks As Worksheet, ColNo As Long, SearchString As String) As Long
Dim rng As Range
Set rng = wks.Columns(ColNo).Find(What:=SearchString, _
LookIn:=xlValues, LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext)
If rng Is Nothing Then
GetRow = 0
Else
GetRow = rng.Row
End If
End Function