简体   繁体   English

Excel VBA使用其他表中的查找/替换来更新单元格

[英]Excel VBA updating cells with Find/Replace from a different sheet

Hey i have a sheet1 containing a list of search patterns in column A, and a corresponding list of category names in column B. I have a sheet2 which has a list of various descriptions of my bank transactions. 嘿,我的sheet1包含A列中的搜索模式列表,而列B则包含相应的类别名称列表。我有一个sheet2,其中包含我的银行交易的各种描述列表。

Eg in sheet1 i have groceries, fuel, entertainment, savings, and in sheet2 i have "Shell service station, abc road", "Coles supermarket" etc.. 例如,在工作表1中,我有杂货,燃料,娱乐,储蓄,在工作表2中,我有“ Shell服务站,abc路”,“ Coles超市”等。

I want to find words in the transactions columns, and then replace the found line with a category.. 我想在“交易”列中找到单词,然后将找到的行替换为类别。

Eg. 例如。 If i find the word "Shell" in Sheet2 i want to replace that line with the word "Fuel" 如果我在Sheet2中找到单词“ Shell”,我想用单词“ Fuel”替换该行。

So far i have got this working, but i dont believe that it is the most efficient or effective way of doing it. 到目前为止,我已经完成了这项工作,但是我不认为这是最有效的方法。 Below is my code. 下面是我的代码。

Sub UpdateCats()
Dim x As Integer
Dim FindString As String
Dim ReplaceString As String
Dim NumRows As Integer
'Replace and update Categories
With Sheets("Categories")
    .Activate
  ' Set numrows = number of rows of data.
  NumRows = Range("A2", Range("A2").End(xlDown)).Rows.Count
  ' Select cell a1.
  Range("A2").Select
  ' Establish "For" loop to loop "numrows" number of times.
  For x = 1 To NumRows
     FindString = ActiveCell.Value
     ActiveCell.Offset(0, 1).Select
     ReplaceString = ActiveCell.Value
     ActiveCell.Offset(1, -1).Select

     With Sheets("Data")
        .Activate
        'With Columns(2)
        Cells.Replace What:=FindString, Replacement:=ReplaceString, LookAt:=xlWhole, SearchOrder:=xlByRows, MatchCase:=False
        'End With
     End With
     Sheets("Categories").Activate
  Next
End With
End Sub

The reason i dont like my code so far is because it has to continually switching (activating) between sheets as it runs through the loop. 到目前为止,我不喜欢我的代码的原因是因为它必须在运行循环时不断在工作表之间切换(激活)。 Is there a way to do this better? 有办法更好地做到这一点吗?

In general, I don't believe that this a very good way to go. 总的来说,我不认为这是一个很好的方法。 Using "ActiveCell" and ".Activate" is a rather dangerous habit because whatever changes will screw your entire piece of code. 使用“ ActiveCell”和“ .Activate”是一个非常危险的习惯,因为任何更改都将破坏您的整个代码。 Try using a named hierarchy (name application - name workbook - name sheet - dynamic ranges such as named ranges as much as possible). 尝试使用命名层次结构(名称应用程序-名称工作簿-名称表-动态范围,例如尽可能多的命名范围)。 Personally I am also not too fond of the offset function, I don't know why everyone is so crazy about it, to revise this type of code is rather untransparent and you seldomly really need it. 我个人也不喜欢偏移函数,我不知道为什么每个人都对它如此着迷,修改这种类型的代码是不透明的,您很少真正需要它。 You could just load the entire thing in an array of strings and loop through it. 您可以将整个内容加载到字符串数组中并循环遍历。 It's brief and easy to read. 它简短且易于阅读。

使用这段代码:

Application.ScreenUpdating=false

This should substantially improve processing time. 这将大大改善处理时间。

Sub UpdateCats()
    Dim v As Long, vFSRSs As Variant

    On Error GoTo bm_Safe_Exit
    Application.EnableEvents = False
    Application.ScreenUpdating = False

    'Replace and update Categories
    With Sheets("Categories")
        vFSRSs = .Range(.Cells(2, 1), .Cells(Rows.Count, 1).End(xlUp).Offset(0, 1)).Value2
    End With

    With Sheets("Data")
        With .Columns(2)
            For v = LBound(vFSRSs, 1) To UBound(vFSRSs, 1)
                'Debug.Print vFSRSs(v, 1) & " to " & vFSRSs(v, 2)
                .Replace What:=vFSRSs(v, 1), Replacement:=vFSRSs(v, 2), _
                         LookAt:=xlWhole, MatchCase:=False
            Next v
         End With
    End With

bm_Safe_Exit:
    Application.EnableEvents = True
    Application.ScreenUpdating = True

End Sub

By storing the search-for and replacement terms in a two dimensional array, the loop through the worksheet cells is discarded. 通过将搜索项和替换项存储在二维数组中,遍历工作表单元格的循环将被丢弃。 Additionally, any form of Worksheet.Activate method or range .Select has been avoided. 此外,避免了任何形式的Worksheet.Activate方法或range .Select

See How to avoid using Select in Excel VBA macros for more methods on getting away from relying on select and activate to accomplish your goals. 有关摆脱依赖于选择和激活来实现目标的更多方法,请参见如何避免在Excel VBA宏中使用“选择”

I would use built in app functions to your advantage. 我会使用内置的应用程序功能来为您带来好处。 In my code I have implemented the "TypeName" and "Search" methods to essentially do the same thing as Ctrl+F & Ctrl+replace, it just became a little more readable. 在我的代码中,我已经实现了“ TypeName”和“ Search”方法,它们实际上执行与Ctrl + F和Ctrl + replace相同的操作,只是变得更具可读性。 I think it is important to be mindful of how powerful VBA methods are and to use those first before resorting to more unorthodox methods. 我认为重要的是要牢记VBA方法的功能强大,并在诉诸更非传统的方法之前先使用它们。

Sub Cats()

With ThisWorkbook
For i = 1 To Sheets(1).Cells(Rows.Count, 1).End(xlUp).Row

    Dim lookupvalue As String

    lookupvalue = Sheets(1).Cells(i, 1).Value

    For n = 1 To Sheets(2).Cells(Rows.Count, 1).End(xlUp).Row

        If TypeName(Application.Search(lookupvalue, Sheets(2).Cells(n, 1))) = "Double" Then
                Sheets(2).Cells(n, 1).Value = Sheets(1).Cells(i, 2).Value
                GoTo exitloop
        End If
    Next n
exitloop:
Next i

End With

End Sub

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM