【问题标题】:Using VBA Find function to check whether a range already exists on Excel worksheet使用 VBA Find 函数检查 Excel 工作表上是否已存在范围
【发布时间】:2018-05-14 16:09:32
【问题描述】:

对 VBA 非常陌生(和一般的编码),试图用我可以在网上找到的信息自学。

编写一个宏,将在 MAIN 表中输入的员工绩效数据逐行复制到工作簿的 LOG 表中。

到目前为止,我已经设法让它正常工作。但是现在我想添加一个FIND函数来判断LOG表上是否已经存在一行数据,这样我就可以使用IF... THEN语句:

  • 如果特定员工和日期的数据不存在,则该行将复制到日志表的第一个空行。
  • 如果它确实已经存在,则日志表上的现有数据行将被覆盖。

这就是我所拥有的:

Sub CopyToLog()

Dim RowCount As Integer

    Sheets("MAIN").Select

    For RowCount = 1 To Range("WeeklyData").Rows.Count

        With Sheets("LOG").Range("A:B")
        Set Dupe = .Find(Sheets("MAIN").Range("B5:C5").Offset(RowCount - 1, 0), LookIn:=xlValues)

        Range("B5:F5").Offset(RowCount - 1, 0).Select
        Selection.Copy

        Sheets("LOG").Select

            If Dupe Is Nothing Then

            Range("A" & Rows.Count).End(xlUp).Offset(1).Select
            Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
            :=False, Transpose:=False

            Else

            Dupe.Select
            Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
            :=False, Transpose:=False

            End If
        End With

    Sheets("MAIN").Select

    Next RowCount

End Sub

但这不起作用。看起来问题出在 Find 函数中:

With Sheets("LOG").Range("A:B")       
Set Dupe = .Find(Sheets("MAIN").Range("B5:C5").Offset(RowCount - 1, 0), LookIn:=xlValues)

需要检查 both 日期 员工(主工作表上的 B 和 C 列与 LOG 上的 A 和 B 列表),但是这里的公式似乎只是比较第一列(日期)。因此,如果下一位员工的数据为同一日期,则该员工的数据现在会被下一位员工覆盖。

您是否只能使用 Find 来查找单个单元格的值,而不是两个相邻单元格的范围?如果是这样,有关如何解决此问题的任何提示?

【问题讨论】:

    标签: excel vba find range


    【解决方案1】:

    听起来辅助细胞可以完成您的任务。我假设您在Sheets("MAIN").Range("B5:C5") 旁边的单元格D5 中有空间。将公式=B5&C5 输入到D5。这样做将为您提供两者的组合,并允许您实现所需的查找。您还需要一个帮助列用于日志表上的查找范围。如果您的信息从单元格 C10 的第 10 行开始,请输入 =A10&B10,根据需要向下复制。有了这些,您现在可以使用它们进行检查。我更改了您的代码以使用辅助单元格。

    Sub CopyToLog()
        Dim main As Worksheet
        Set main = ThisWorkbook.Worksheet("MAIN")
    
        Dim log As Worksheet
        Set log = ThisWorkbook.Worksheets("LOG")
    
        Dim searchRange As Range
        Set searchRange = log.Range("C:C") 'Helper Column
    
        Dim RowCount As Integer
        For RowCount = 1 To main.Range("WeeklyData").Rows.Count
            Dim lookFor As String
            lookFor = main.Range("D5").Offset(RowCount - 1, 0).Value2 'Uses helper cells
    
            Dim dupe As Range
            Set dupe = searchRange.Find(lookFor, LookIn:=xlValues)
    
            Dim copyInfo As Range
            Set copyInfo = searchRange.Range("B5:F5").Offset(RowCount - 1, 0)
    
            Dim destination As Range
            If dupe Is Nothing Then
                Set destination = log.Range("A" & Rows.Count).End(xlUp).Offset(1)
            Else
                Set destination = dupe
            End If
    
            destination.Resize(ColumnSize:=copyInfo.Columns.Count).Value2 = copyInfo.Value2
        Next
    
        main.Select
    End Sub
    

    使用对象本身。我删除了 .SelectSelection. 对。不使用它们将使您的代码更具可读性和更快。首先,宏记录器将使用它们,但请注意,您可以将它们夹在中间(IE Range("M10").Select 后跟 Selection.Copy 最好写成 Range("M10").Copy)。

    我用合格的变量替换了所有不合格的Range 变量。 Range 隐含使用ActiveSheet,本质上是ActiveSheet.Range。使用main.Range("A5") 之类的工作表对象对其进行限定可以让您确切知道它来自哪个工作表。这样可以避免您稍后拉扯头发。

    destination.Resize(ColumnSize:=copyInfo.Columns.Count).Value2 = copyInfo.Value2 与直接复制值相同。调整大小用于使两个范围的大小相同。

    【讨论】:

    • 哇!这是非常非常有教育意义的,非常感谢!它不仅解决了我目前的问题,而且您的解释和建议确实有助于更好地理解未来的事情。我确实必须使用 '=CONCATENATE(TEXT(C5, "dd-mm-yyyy")," ", D5)' 而不仅仅是 '&' 来组合日期和字符串数据,并更改您的 CopyInfo 建议以参考MAIN 而不是 SearchRange,但现在它工作得非常漂亮。更重要的是:很高兴地意识到我真的理解你在这里所说的以及为什么你的代码比我的更好!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-15
    • 1970-01-01
    • 2023-03-25
    • 2023-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多