替换Excel工作表中的多个单词

用户名
Sub xLator2()
Dim s1 As Worksheet, s2 As Worksheet
Dim N As Long, i As Long
Dim from(), too()
Set s1 = Sheets("Sheet1") '   contains the data
Set s2 = Sheets("Sheet2") '   contains the translation table

s2.Activate

N = Cells(Rows.Count, 1).End(xlUp).Row
ReDim from(1 To N)
ReDim too(1 To N)
For i = 1 To N
    from(i) = Cells(i, 1).Value
    too(i) = Cells(i, 2).Value
Next i

s1.Activate

' -------------- Modification starts here --------------------------
' Replace from from(i) to __MYREPLACEMENTi__  (where i is the counter)
For i = LBound(from) To UBound(from)
    Cells.Replace What:=from(i), Replacement:="__MYREPLACEMENT" + Str(i) + "__"
Next i
' Replace from __MYREPLACEMENTi__ to too(i)  (where i is the counter)
For i = LBound(from) To UBound(from)
    Cells.Replace What:="__MYREPLACEMENT" + Str(i) + "__", Replacement:=too(i)
Next i
' -------------- Modification ends here --------------------------
End Sub

我正在使用上面的代码在下面提到的工作表中查找和替换多个单词(“ Column A Sheet1”中的单词与“ Column B Sheet 2”中的单词):

https://docs.google.com/spreadsheets/d/14ba9pQDjMPWJd4YFpGffhtVcHxml0LdUUVQ0prrOEUY/edit?usp=sharing

但是,当我在另一个工作表(如下所述)中将其应用于另一个数据时,代码将失败,即,我在工作表1中得到了失真的单词:

https://docs.google.com/spreadsheets/d/1spvZAzxT1kB1bytCQaNQH7tl1DJSpLITYgW6P5dxbQE/edit?usp=sharing

请帮帮我,以便我可以将“ A列Sheet1”中的单词替换为“ B列Sheet2”中的单词

注意:上面的链接已经给出了Google电子表格,但是我在Excel 2007工作表中遇到了问题。

我要求您通过提供完整的修订代码来帮助我,因为我在VBA中表现不佳

托尼·达利摩(Tony Dallimore)

我同意sous2817的观点:解决自己的问题越多,您的发展就会越快。但是,我认为一些建议会有所帮助。

如果要使用VBA,则必须学习VBA。找到并尝试使用您不理解的一段代码永远都不会结束。当此代码的作者仅比您了解更多时,尤其如此。

在网上搜索“ Excel VBA教程”。有很多可供选择的内容,因此请尝试一些并完成与您的学习风格相匹配的内容。我更喜欢书。我参观了一个大型图书馆,审阅了他们的Excel VBA入门手册,并借用了我喜欢的那些。在家里试用之后,我买了最适合自己的那一款。

您从哪里获得此代码?它包含典型的初学者错误,即使使用第一个示例也不起作用。

Sheet1中的第一个单词是“ it”。Sheet2指示将“ it”替换为“ that”。该代码将“ it”正确替换为“ that”。不幸的是,它用“ that”替换了所有“ it”,因此“ with”被翻译为“ wthath”而不是“ having”。由于您抱怨第二张纸,所以我想您没有注意到翻译错误。这样的误译在第二对中必须更加明显,并且在“他们”,“那里”,“他们”,“他们”,“然后”和“这些”中出现第一个单词“ the”。

如果您查看Replace Method,您应该会看到此错误的快速更正。注意:Replace Method不能Replace Function

最后,我将给出一些示例,说明初级程序员可能是如何编写此例程的。


考虑:

s2.Activate

N = Cells(Rows.Count, 1).End(xlUp).Row
ReDim from(1 To N)
ReDim too(1 To N)
For i = 1 To N
    from(i) = Cells(i, 1).Value
    too(i) = Cells(i, 2).Value
Next i

开始学习VBA时要学习的第一件事是“不要激活工作表或选择单元格”。这些命令很慢,即使您使用ScreenUpdating = False,也会进行一些屏幕重写。更重要的是,您的代码可能会变得非常混乱。以下更好:

With s2

  N = .Cells(Rows.Count, 1).End(xlUp).Row
  ReDim from(1 To N)
  ReDim too(1 To N)
  For i = 1 To N
   from(i) = .Cells(i, 1).Value
   too(i) = .Cells(i, 2).Value
  Next i

End With

注1:前三个时期CellsCells在活动工作表上运行。.CellsWith语句中指定的工作表上运行

注2:我还没有放置过一段Rows.CountRows.Count返回活动工作表中的行数。.Rows.Count返回指定工作表中的行数。行数取决于Excel的版本,并且在工作表之间不会有所不同,因此大多数程序员都不会担心句点。


我将创建两个工作表参数:

Sub xLator2(s1 As Worksheet, s2 As Worksheet)

这使子例程更加灵活。我可能会走得更远,并将参数Ranges赋予更大的灵活性。


我可以继续,但是我认为这足以开始。祝您好运,欢迎您来享受编程的乐趣。


编辑:教程和完整的解决方案

第1部分-不使用激活的原因之一

请研究以下代码块,这些代码块说明为什么只有大多数初级VBA程序员在Activate没有充分理由的情况下才使用我不希望您因节省几秒钟或几毫秒而变得过于紧张。有些程序员会花半个小时来优化一次又一次运行的例程。只有每天要执行数百次例程,才能证明该时间是合理的。我希望您Application.ScreenUpdating = False 节省很多时间,所以请您自动使用它。Application.ScreenUpdating = False被包括在内,之间的区别Activate,并With就少了很多,但足以证明作出With的默认选择。

  For Count = 1 To 10000             ' This takes 148 seconds
    Worksheets("Sheet1").Activate
    Worksheets("Sheet2").Activate
  Next

  Application.ScreenUpdating = False ' This takes 11 seconds
  For Count = 1 To 10000
    Worksheets("Sheet1").Activate
    Worksheets("Sheet2").Activate
  Next

  Application.ScreenUpdating = False ' This takes .07 seconds
  For Count = 1 To 10000
    With Worksheets("Sheet1")
    End With
    With Worksheets("Sheet2")
    End With
  Next

  Application.ScreenUpdating = False ' This takes 12 seconds
  For Count = 1 To 10000
    Worksheets("Sheet1").Activate
    Cells(23, 1).Value = "A"
    Worksheets("Sheet2").Activate
    Cells(23, 1).Value = "A"
  Next

  Application.ScreenUpdating = False ' This takes 1.16 seconds
  For Count = 1 To 10000
    With Worksheets("Sheet1")
      .Cells(23, 1).Value = "A"
    End With
    With Worksheets("Sheet2")
      .Cells(23, 1).Value = "A"
    End With
  Next

  Application.ScreenUpdating = False ' This takes 0.96 seconds
  Set Wsht1 = Worksheets("Sheet1")
  Set Wsht2 = Worksheets("Sheet2")
  For Count = 1 To 10000
    With Wsht1
      .Cells(23, 1).Value = "A"
    End With
    With Wsht2
      .Cells(23, 1).Value = "A"
    End With
  Next

第2部分-将值从工作表复制到数组

LoadFromTo1()是基于其加载从太表宏开幕代码。因为我的测试数据略有不同,所以它略有不同。加载“从”和“太”表需要十分之六秒的时间

Sub LoadFromTo1()

  ' Takes about .594 seconds for 50,000 rows * 2 columns

  Dim s1 As Worksheet
  Dim N As Long, i As Long
  Dim From(), too()

  Dim InxFromTo As Long
  Dim TimeStart As Single

  TimeStart = Timer

  Set s1 = Sheets("Test1") '   contains the data

  s1.Activate

  N = Cells(Rows.Count, 3).End(xlUp).Row
  ReDim From(1 To N - 1)
  ReDim too(1 To N - 1)
  For i = 2 To N
    From(i - 1) = Cells(i, 3).Value
    too(i - 1) = Cells(i, 4).Value
  Next i

  Debug.Print "M1: " & Timer - TimeStart

  For InxFromTo = 1 To 20
    Debug.Print Right("    " & InxFromTo, 5) & " " & From(InxFromTo) & " " & too(InxFromTo)
  Next
  For InxFromTo = UBound(From) - 20 To UBound(From)
    Debug.Print Right("    " & InxFromTo, 5) & " " & From(InxFromTo) & " " & too(InxFromTo)
  Next

End Sub

LoadFromTo2()(未显示)With代替Activate只有一个Activate一个With,没有明显的性能变化。

LoadFromTo3()使用另一种技术来加载表。而不是一次导入一个单元格值,而是在单个语句中导入CellValue = .Range(.Cells(2, 3), .Cells(RowMax, 4)).Value这句话现在对您可能看起来很奇怪。但是,如果您学习和实践该技术,它将成为第二天性。我发现LoadFromTo3()LoadFromTo1()更容易编码和理解,并且它的速度是它的十倍。我已经读过,虽然我从未达到过那种性能提升的水平,但将范围作为一个单元而不是逐个单元导入的速度可以快五十倍。

Sub LoadFromTo3()

  ' Takes about .0625 seconds for 50,000 rows * 2 columns

  Const ColFrom As Long = 1
  Const ColTo As Long = 2

  Dim s1 As Worksheet
  Dim RowMax As Long, RowCrnt As Long

  Dim InxFromTo As Long
  Dim TimeStart As Single

  Dim CellValue As Variant

  TimeStart = Timer

  Set s1 = Sheets("Test1") '   contains the data

  With s1
    RowMax = .Cells(Rows.Count, 3).End(xlUp).Row
    CellValue = .Range(.Cells(2, 3), .Cells(RowMax, 4)).Value

    Debug.Print "M3: " & Timer - TimeStart

  End With

  For InxFromTo = 1 To 20
    Debug.Print Right("    " & InxFromTo, 5) & " " & CellValue(InxFromTo, ColFrom) & _
                                               " " & CellValue(InxFromTo, ColTo)
  Next
  For InxFromTo = UBound(CellValue, 1) - 20 To UBound(CellValue, 1)
    Debug.Print Right("    " & InxFromTo, 5) & " " & CellValue(InxFromTo, ColFrom) & _
                                               " " & CellValue(InxFromTo, ColTo)
  Next

End Sub

第3部分-原始代码分析

首先是一些定义。目标范围是字的列进行翻译。所述目标表是目标范围加载到存储器中。FromTo范围是From和To列。所述的FromTo表是加载到存储器中的所述的FromTo范围。

本节花费的时间比我最初计划的要长。最初,我只打算对我的代码进行适当的测试。鉴于较早答案中提供的代码中的错误,并且隐含着另一个错误,我特别小心。我编写了一个例程,生成了各种大小的测试数据。我使用该例程生成了用于第2部分中的计时的50,000行FromTo表。我对您发布的转换例程进行了一些细微更改,并针对我的测试数据运行了该例程,以提供以下持续时间:

FromTo  Target  Target  Duration  
  Rows    Rows    Cols   in secs
50,000      20       1       103
50,000  10,000       1       486
10,000   3,000       2        60

我修改后的代码的关键部分是:

With RngTgt
    For RowFromTo = 1 To UBound(FromToTable, 1)
      .Replace What:=FromToTable(RowFromTo, ColFrom), _
               Replacement:="__" + Str(RowFromTo), _
               LookAt:=xlWhole
    Next
    For RowFromTo = 1 To UBound(FromToTable, 1)
      .Replace What:="__" + Str(RowFromTo), _
               Replacement:=FromToTable(RowFromTo, ColTo), _
               LookAt:=xlWhole
    Next
  End With

我使用了一个范围,因此目标范围可以在任何工作表中并且可以是多列。我看不到具有如此大的前缀和后缀会导致时间损失的意义,因此我将前缀减少为两个下划线。我包括LookAt:=xlWhole更正。我使用从范围加载的ToFrom表。我已替换i为有意义的名称,RowFromTo以使代码更易于理解。

没有评论说这段代码做什么以及为什么这样做。必须在宏中包含足够的注释。您还记得此宏在六到十二个月内做什么吗?如果同事需要修改该怎么办?

在您的第一个FromTo表中,“ for”转换为“ on”,“ on”转换为“ upon”。如果没有两遍解决方案,“ for”可能会转换为“ upon”。这是我的猜测,这似乎很合理但是应该有一条评论,这样我就不必猜测了,负责此宏的新程序员可能无法猜测,并可能通过删除“不必要的”第二遍来“改进”代码。

Replace方法背后的代码将达到其作者可以管理的效率,但是仍然必须检查范围中的每个单元格。我通过搜索指定范围而不是整个工作表来改善了这种情况。但是,它仍然必须为FromTo表中的每一行两次搜索该范围。

研究此代码后,我看到了立即的改进。第一遍将目标表中的单词替换为“ __1”,“ __ 2”,“ __ n”,依此类推,其中1、2和n是FromTo表的索引。第二遍搜索“ __1”,“ __ 2”和“ __n”。更好的技术是提取1、2和n并使用它们访问FromTo表中的正确条目。使用这种更好的技术,持续时间为:

                           First    Second
FromTo  Target  Target  duration  duration
  Rows    Rows    Cols   in secs   in secs
50,000      20       1       103        52
50,000  10,000       1       486       257
10,000   3,000       2        60        32

也就是说,我通过将代码更改为以下方式将持续时间减半:

  With RngTgt
    For RowFromTo = 1 To UBound(ToFromTable, 1)
      .Replace What:=ToFromTable(RowFromTo, ColFrom), _
               Replacement:="__" + Str(RowFromTo), _
               LookAt:=xlWhole
    Next
  End With

  For Each Cell In RngTgt
    Test = Mid(Cell.Value, 3)
    If IsNumeric(Test) Then
      Cell.Value = ToFromTable(Val(Test), ColTo)
    End If
  Next

但是,我认为基本方法是错误的。如果在FromTo范围内有FT条目,而在Target范围内有T条目,则:

  • 在方法1中,有2个* FT替换需要搜索T细胞。
  • 对于方法2,有FT替换,需要搜索T细胞,然后再进行T替换。

由于相同的单词可能会在“目标”范围内重复出现,因此“目标”范围的搜索必须检查每个单元格。但是,如果我们在FromTo范围的From列中搜索Target范围内的每个条目怎么办?除非目标范围中的大量单词从FromTo范围中丢失,否则将在找到匹配项之前检查平均FT / 2条目。同样,也不需要第二遍。我们期望基于这种逻辑的第三种方法,是方法2持续时间的一半。

我重新编码了例程的主要部分并重复了测试

                           First    Second      Third
FromTo  Target  Target  duration  duration   duration
  Rows    Rows    Cols   in secs   in secs    in secs
50,000      20       1       103        52        .13
50,000  10,000       1       486       257      61.51 
10,000   3,000       2        60        32       7.54

与我预期的相比,持续时间的减少要大得多。我对原因有一些猜测,但我没有进一步调查。我相信最后的期限是可以接受的。我还有一个主意,但我认为不值得花时间进行研究。

上面的主要课程是:在实施之前先考虑一下实施策略。对我来说,技术3显然优于技术1和2,我本来应该从该技术开始的。花一些时间在初始设计上可以使自己获得丰厚的回报。

第4部分-最终解决方案

您发布了两个工作簿,每个工作簿在Sheet1中都有Target范围,在Sheet2中有FromTo范围。我创建了一个工作簿,并将第二个工作簿中的数据复制到Sheet3和Sheet3。

我修改了您的宏以调用我的宏:

Option Explicit
Sub xLator2()

  Dim RngTgt As Range
  Dim RngFromTo As Range
  Dim RowMax As Long
  Dim TimeStart  As Single

  With Worksheets("Sheet1")
    RowMax = .Cells(Rows.Count, "A").End(xlUp).Row
    Set RngTgt = .Range(.Cells(1, "A"), .Cells(RowMax, "A"))
  End With

  With Worksheets("Sheet2")
    RowMax = .Cells(Rows.Count, "A").End(xlUp).Row
    Set RngFromTo = .Range(.Cells(1, "A"), .Cells(RowMax, "B"))
  End With

  TimeStart = Timer
  Call Translate3(RngTgt, RngFromTo)
  Debug.Print "Sheet1 technique 3 duration: " & Timer - TimeStart

  With Worksheets("Sheet3")
    RowMax = .Cells(Rows.Count, "A").End(xlUp).Row
    Set RngTgt = .Range(.Cells(1, "A"), .Cells(RowMax, "A"))
  End With

  With Worksheets("Sheet4")
    RowMax = .Cells(Rows.Count, "A").End(xlUp).Row
    Set RngFromTo = .Range(.Cells(1, "A"), .Cells(RowMax, "B"))
  End With

  TimeStart = Timer
  Call Translate3(RngTgt, RngFromTo)
  Debug.Print "Sheet3 technique 3 duration: " & Timer - TimeStart

End Sub

我针对技术3的宏将两个范围作为其参数,因此可以将多个Target和FromTo范围放置在方便的地方:

Sub Translate3(ByVal RngTgt As Range, ByVal RngFromTo As Range)

  ' RngTgt     A rectangle containing words to be translated
  ' RngFromTo  Two columns with the left column containing the original values
  '            for words and the right column containing the values to replace
  '            the original values.

  ' Constants numbering the From and To columns within RngFromTo.  This makes the
  ' code easier to understand than if 1 and 2 had been used.
  Const ColFrom As Long = 1
  Const ColTo As Long = 2

  Dim ColTgtCrnt As Long
  Dim Test As String
  Dim RngFindStart As Range
  Dim RngFrom As Range
  Dim RngTemp As Range
  Dim RowFromTo As Long
  Dim RowTgtCrnt As Long
  Dim TgtTable As Variant

  ' Check FromTo range has two columns
  If RngFromTo.Columns.Count <> 2 Then
    Call MsgBox("ToFrom table must have two columns", vbOKOnly)
    Exit Sub
  End If

  ' Load Target range to array
  TgtTable = RngTgt.Value

  ' Set RngFrom to the From column of RngFromTo
  Set RngFrom = RngFromTo.Columns(ColFrom)
  ' Set RngFindStart to first cell of RngFrom
  Set RngFindStart = RngFrom.Rows(1)

  ' Loop for every entry in Target table
  For RowTgtCrnt = 1 To UBound(TgtTable, 1)
    For ColTgtCrnt = 1 To UBound(TgtTable, 2)
      Set RngTemp = RngFrom.Find(What:=TgtTable(RowTgtCrnt, ColTgtCrnt), _
                                 After:=RngFindStart, _
                                 LookAt:=xlWhole)
      If Not RngTemp Is Nothing Then
        ' This target cell is to be translated
        ' Replace value in Target table with value for To column of FromTo table
        TgtTable(RowTgtCrnt, ColTgtCrnt) = RngTemp.Offset(0, ColTo - ColFrom).Value
      End If
    Next
  Next

  ' Upload updated array back to Target range
  RngTgt.Value = TgtTable

End Sub

这里有很多东西要学习。慢慢来,查找您不理解的任何陈述。如有必要,请回答一些问题,但是您对自己的了解越多,您的发展就会越快。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

循环以在多个Excel工作簿中创建多个工作表

来自分类Dev

多个工作表中的Excel图表

来自分类Dev

VLOOKUP和IF在多个Excel工作表中

来自分类Dev

从 Excel 中的多个工作表返回数据

来自分类Dev

Excel:使用查找矩阵替换多个单词

来自分类Dev

连接Excel中多个工作表中的单元格

来自分类Dev

计算Excel中多个工作表中的值

来自分类Dev

在文件夹中的多个 Excel 工作表上附加单个(和多个)工作表

来自分类Dev

Excel PageSetup多个工作表

来自分类Dev

参考多个Excel工作表

来自分类Dev

循环读取和合并R中的多个Excel工作表

来自分类Dev

无法在PHP Excel中创建多个工作表

来自分类Dev

Excel宏可隐藏多个工作表中的行

来自分类Dev

Excel-汇总多个工作表中的值的公式?

来自分类Dev

在Excel中跨多个工作表进行拼写检查

来自分类Dev

循环读取和合并R中的多个Excel工作表

来自分类Dev

使用ByteScout Spreadsheet在Excel文件中写入多个工作表

来自分类Dev

比较多个工作表中的多列Excel

来自分类Dev

如何在Excel中搜索和合并多个工作表?

来自分类Dev

Excel:合并多个工作表中包含值的行

来自分类Dev

jQuery替换div中的多个单词

来自分类Dev

在Word中查找并替换多个单词

来自分类Dev

匹配和替换多个工作表上多个范围内的列中的字符串

来自分类Dev

Excel:在多个列中搜索多个单词

来自分类Dev

在excel中替换相同的因此出现的单词

来自分类Dev

用R中的部分匹配替换整个单词或多个单词

来自分类Dev

从多个Excel工作表中复制数据,然后使用VBScript将其追加到单个Excel工作表中

来自分类Dev

通过Python在Excel工作簿中的多个工作表中添加单元格值

来自分类Dev

使用openpyxl在Excel工作表的文本字符串中搜索单词

Related 相关文章

  1. 1

    循环以在多个Excel工作簿中创建多个工作表

  2. 2

    多个工作表中的Excel图表

  3. 3

    VLOOKUP和IF在多个Excel工作表中

  4. 4

    从 Excel 中的多个工作表返回数据

  5. 5

    Excel:使用查找矩阵替换多个单词

  6. 6

    连接Excel中多个工作表中的单元格

  7. 7

    计算Excel中多个工作表中的值

  8. 8

    在文件夹中的多个 Excel 工作表上附加单个(和多个)工作表

  9. 9

    Excel PageSetup多个工作表

  10. 10

    参考多个Excel工作表

  11. 11

    循环读取和合并R中的多个Excel工作表

  12. 12

    无法在PHP Excel中创建多个工作表

  13. 13

    Excel宏可隐藏多个工作表中的行

  14. 14

    Excel-汇总多个工作表中的值的公式?

  15. 15

    在Excel中跨多个工作表进行拼写检查

  16. 16

    循环读取和合并R中的多个Excel工作表

  17. 17

    使用ByteScout Spreadsheet在Excel文件中写入多个工作表

  18. 18

    比较多个工作表中的多列Excel

  19. 19

    如何在Excel中搜索和合并多个工作表?

  20. 20

    Excel:合并多个工作表中包含值的行

  21. 21

    jQuery替换div中的多个单词

  22. 22

    在Word中查找并替换多个单词

  23. 23

    匹配和替换多个工作表上多个范围内的列中的字符串

  24. 24

    Excel:在多个列中搜索多个单词

  25. 25

    在excel中替换相同的因此出现的单词

  26. 26

    用R中的部分匹配替换整个单词或多个单词

  27. 27

    从多个Excel工作表中复制数据,然后使用VBScript将其追加到单个Excel工作表中

  28. 28

    通过Python在Excel工作簿中的多个工作表中添加单元格值

  29. 29

    使用openpyxl在Excel工作表的文本字符串中搜索单词

热门标签

归档