【问题标题】:Replace text marker with column text用列文本替换文本标记
【发布时间】:2016-09-15 20:53:26
【问题描述】:

我有几列文字。此外,我还有一个名为Replacement text 的专栏。此列包含带有标记的字符串,例如 [1], [2], etc.

我想用标记所在行中的文本替换标记。

例如,Here you can find [5] 变为 Here you can find b,因为[5] 是标记列,而字符串行中的b 是标记的值。

我正在考虑创建一个大的if-else 构造和substitute 文本,这非常容易出错。

但是,请问您是否有更简单的解决方案?

感谢您的意见!

【问题讨论】:

  • 是的,VBA 可以轻松处理这个问题。您确实需要提供到目前为止您已经尝试过的内容。请记住,SO 不是一个代码编写服务,而是一个获取有关编码问题的尖锐问题的论坛。首先,您可以创建一个循环,该循环贯穿您在 K 列上的范围,拉动每个单元格的标记并替换适当的字符串。获得代码后,如果仍有问题,您可以在 SO 上分享代码以获得有关问题的帮助。问候,

标签: excel excel-formula excel-2010 vba


【解决方案1】:

此答案高度抄袭 Thomas Inzina 的第一版答案,但执行替换的一种非常简单的方法是:

Sub ReplaceText()
    Dim r As Long
    Dim c As Long
    With ActiveSheet
        For r = 3 To .Range("K" & .Rows.Count).End(xlUp).Row
            For c = 1 To 10
                .Cells(r, "K").Replace "[" & c & "]", .Cells(r, c).Value
            Next
        Next
    End With
End Sub

以上代码将尝试使用所有十个列进行替换。

正如 Thomas 所指出的,以下代码仅在需要替换时才会执行替换,因此速度可能会快一个数量级,因此无疑是一个更好的解决方案:

Sub ReplaceText()
    Dim r As Long
    Dim c As Long
    With ActiveSheet
        For r = 3 To .Range("K" & .Rows.Count).End(xlUp).Row
            For c = 1 To 10
                If Instr(.Cells(r, "K").Value, "[" & c & "]") > 0 Then
                    .Cells(r, "K").Replace "[" & c & "]", .Cells(r, c).Value
                End If
            Next
        Next
    End With
End Sub

(非常感谢 Thomas 为对两种不同方法进行速度测试所做的努力。)

【讨论】:

  • 我进行了速度测试,原来处理 100K 记录需要 78 秒,但使用 Instr 避免额外替换时只需 18 秒。显然,无论是否有任何更改,Excel 都会写入单元格。
  • 谢谢@ThomasInzina - 我会相应地更新答案。
【解决方案2】:

ReplaceBrackets1:使用 RegEx 提取列号。处理 10 万条记录需要 15.03 秒。


Sub ReplaceBrackets1()
    'http://analystcave.com/excel-regex-tutorial/
    Dim c As Range
    Dim Match As Object, Matches As Object, regex As Object
    Set regex = CreateObject("VBScript.RegExp")

    With regex
        .Global = True
        .Pattern = "\[(.*?)\]"
    End With

    For Each c In Range("K3", Range("K" & Rows.Count).End(xlUp))
        If regex.Test(c.Text) Then
            Set Matches = regex.Execute(c.Text)
            For Each Match In Matches
                c.Replace Match, c.EntireRow.Columns(CInt(Match.SubMatches(0)))
            Next Match

        End If
    Next
End Sub

ReplaceBrackets2:将数据加载到数组中,使用 RegEx 提取列号,并且只写入工作表 1 次。处理 10 万条记录需要 1.27 秒。


Sub ReplaceBrackets2()
'http://analystcave.com/excel-regex-tutorial/
    Dim x As Long, column As Long
    Dim arData, values
    Dim Match As Object, Matches As Object, regex As Object
    Set regex = CreateObject("VBScript.RegExp")

    With regex
        .Global = True
        .Pattern = "\[(.*?)\]"
    End With

    values = Range("K3", Range("K" & Rows.Count).End(xlUp))
    arData = Range("A3", "L" & UBound(values, 1) + 2)

    For x = 1 To UBound(values, 1)
        If regex.Test(values(x, 1)) Then
            Set Matches = regex.Execute(values(x, 1))
            For Each Match In Matches
                column = Match.SubMatches(0)
                values(x, 1) = arData(x, column)
            Next Match
        End If
    Next

    Range("K3", Range("K" & Rows.Count).End(xlUp)) = values

End Sub

在将ReplaceBrackets1 转换为UDF (getReplacedText) 后,我惊讶地发现只需 2.53 秒即可为 10 万条记录填写公式。我不确定这会比原来的更快。但是有这么多公式确实会减慢电子表格的速度。

getReplacedText:使用静态正则表达式解析数据。

Function getReplacedText(ReplacementText As String, Source As Range)
'http://analystcave.com/excel-regex-tutorial/
    Dim Match As Object, Matches As Object
    Static regex As Object
    If regex Is Nothing Then
        Set regex = CreateObject("VBScript.RegExp")

        With regex
            .Global = True
            .Pattern = "\[(.*?)\]"
        End With
    End If

    If regex.Test(ReplacementText) Then
        Set Matches = regex.Execute(ReplacementText)
        For Each Match In Matches
            ReplacementText = Replace(ReplacementText, Match, Source.Columns(CInt(Match.SubMatches(0))))
        Next Match

    End If

    getReplacedText = ReplacementText
End Function

【讨论】:

  • 您可能会将column = ... 更改为For column = 1 To 10,因此将处理每个单元格的多组括号。
  • 这样做我将不得不更改每个Instr() 的起点。正则表达式会更好或拆分。
  • 您的 Instr 仅用于计算 column 的值,如果您遍历 column 的所有可能值,则不需要。 (您的解决方案的核心是Cells(x, "k").Replace "[" & column & "]", Cells(x, column),它只需要知道行号和column 的值。)
  • Columns 将字母作为字符串,将数字作为数字。这是一个示例公式=getReplacedText(K5,A5:J5)。你的公式是什么?
  • 这与您的示例完全不同。它需要引用列标题和WorksheetFunction.MatchRange().Find 来获取列号。我要上班了,可能要到下周才能修改它。
猜你喜欢
  • 2020-02-06
  • 1970-01-01
  • 2012-07-09
  • 1970-01-01
  • 2015-10-15
  • 2012-03-13
  • 1970-01-01
  • 1970-01-01
  • 2020-10-07
相关资源
最近更新 更多