【问题标题】:Is there a way to count the number of characters per word for a string, returning values separated by a comma?有没有办法计算字符串每个单词的字符数,返回用逗号分隔的值?
【发布时间】:2020-02-28 14:03:10
【问题描述】:

我在单元格中有一个字符串列表 - 其中有 1000 个 - 我需要计算出每个单词的字符,但按单词分隔 - 最好在 1 个快速公式中......

例如: 1.“带柄黑杯”>我需要的配方>5,3,4,6

  1. “巨熊雕像”> 我需要的公式 > 5,4,6

我需要它来执行一项重复性任务,该任务以非常低效的方式宏化以将单词计数到列中(我们需要使用最多 20 个用于刚刚封装的列),但这需要解决。

通常,我们计算空格和层嵌套的 serach() 公式以背负一个和另一个以分解结构,然后字符计算单个单词...

我也可以用宏来替换逗号的空格,并将文本用于列,但这仍然让我在寻找我要查找的内容时需要较长的计数过程

我们显然使用=LEN(A1)-LEN(SUBSTITUTE(A1," ","")) 来计算单词中的空格

我们目前使用=SEACRH() 函数结合=MID() 函数(以及一些奇怪的数字)将每个单词显示到其自己的单个单元格中

然后=LEN 再次对所有单个单词进行处理 - 非常啰嗦

我希望找到一种更短的方法来做到这一点,但感觉可能没有足够动态的方法来单独使用公式,希望有人能证明我错了!

【问题讨论】:

  • 结果需要在一列中?只是数字,就像你的例子一样?
  • 你想要一个 VBA 代码吗?

标签: excel vba excel-formula word-count charactercount


【解决方案1】:

根据您的 Excel 版本,您会有不同的选择。


选项 1:TEXTJOIN

我认为您正在寻找TEXTJOIN 函数。请记住,您只能在更高版本的 Excel 中使用它(请参阅文档链接),它可以像这样工作:

B1中的公式:

=TEXTJOIN(",",TRUE,LEN(FILTERXML("<t><s>"&SUBSTITUTE(A1," ","</s><s>")&"</s></t>","//s")))

注意: 这是一个数组公式,您需要使用 CtrlShiftEnter 输入

为了让您不需要使用上述组合键,我们可以添加一个INDEX

=TEXTJOIN(",",TRUE,INDEX(LEN(FILTERXML("<t><s>"&SUBSTITUTE(A1," ","</s><s>")&"</s></t>","//s")),))

其他信息:

FILTERXML

这个函数需要(根据文档)两个必需的参数:

  • 有效XML中的字符串
  • 有效XPath中的字符串

因为我们想从单元格中返回一个元素(单词)数组,我们需要 SUBSTITUTE 结束标签 (&lt;/..&gt;) 的空格并将其与开始标签 (&lt;..&gt;) 连接起来字符串的开头和结尾的另一个结束标记。

我将不得不依靠标签上的XML 解释来解释为什么&lt;?&gt;&lt;?&gt; 起作用及其含义,因为就我的测试而言,我可以交换字母或用另一个相同的字母替换只要最终的Xpath 与相同的字符相似,就会得到结果。如果有人能够对这个问题提供更好的解释来补充这个答案,那就太好了。

更多FILTERXML“技巧”,请看here


TEXTJOIN

如果您是 Office 365 订阅者或拥有 Excel 2019,则可以使用此功能。有(根据文档)至少 3 个必需的参数:

  • 必须是文本字符串的分隔符,可以是空的,也可以是一个或多个用双引号括起来的字符,或者是对有效文本字符串的引用。如果提供了一个数字,它将被视为文本。
  • 第二个参数可以包含TRUEFALSE,并确定是否要排除/包含空值
  • 第三个参数是要连接的文本项。文本字符串或字符串数​​组,例如单元格区域。

现在我们可以将这两个函数连接在一起,FILTERXML 返回一个数组,我们可以在TEXTJOIN 中使用该数组。


INDEX + LEN

我将不得不一起解释这些函数的用法。我不认为LENINDEX 需要单独介绍太多​​,但它们一起工作得很好。原生会有一种称为隐式交集的力,当您将值数组传递给函数时,它会阻止LEN 返回值数组,在本例中是通过我们的FILTERXML

通常,您可以使用以下组合键禁用此机制:CtrlShiftEnter,更广为人知的是CSE

现在INDEX 所做的是禁用此隐式交集,使LEN 能够返回一个数组,从而无需CSE 公式。 INDEX 是具有这种“权力”的功能之一。关于隐式交集的更深入的解释可以找到here


选项 2:UDF

如果无法访问TEXTJOIN,我认为您需要看看如何使用 UDF,可能如下所示:

Function TEXTJOIN(rng As Range) As String
    TEXTJOIN = Join(Application.Evaluate("LEN({""" & Join(Split(rng, " "), """,""") & """})"), ",")
End Function

您可以在B1 中调用它,如下所示:=TEXTJOIN(A1)


其他信息:

UDF 由三个协同工作的主要机制组成:

JOIN

这个函数有两个参数,其中第一个是必需的:

  • 第一个参数是一个包含子字符串的一维数组
  • 第二个(可选)参数是一个字符串字符,用于分隔返回字符串中的子字符串。如果省略,则使用空格字符 (" ")。如果 delimiter 是一个长度为零的字符串 (""),则列表中的所有项目都连接起来,没有分隔符。

函数返回一个字符串值


SPLIT

此函数接受一个字符串并用指定的字符/子字符串对其进行分隔。它采用以下参数:

  • 1st:包含子字符串和分隔符的必需字符串表达式。如果表达式是零长度字符串(""),则Split返回一个空数组,即一个没有元素也没有数据的数组。
  • 2nd:可选的分隔符,它是用于标识子字符串限制的字符串字符。如果省略,则假定空格字符 (" ") 是分隔符。如果 delimiter 是长度为零的字符串,则返回包含整个表达式字符串的单元素数组。
  • 3rd:可选限制,要返回的子串数量; -1 表示返回所有子字符串。
  • 4th:Compare,也是可选的,是一个数值,表示在评估子字符串时要使用的比较类型。有关值,请参阅设置部分。

在这种情况下,我们只需要前两个参数。


Application.Evaluate

这是 IMO 最方便的机制之一,您可以使用它来提取返回的值数组,而无需遍历项目/单元格。当你为函数提供一个大数组公式时,它可能会变慢,但在这种情况下它会很好。该函数将 Microsoft Excel 名称转换为对象或值,当我们将公式传递给它时,它将返回结果。在这种特殊情况下,它将返回一个数组。

【讨论】:

  • 我非常喜欢你巧妙的FILTERXML替换;也许值得进一步解释+:)
  • @JvdV - 非常感谢您,这将对我一直在做的一些分析工作进行重大改进!
  • @T.M.我已经尽力解释公式虽然FILTERXML 部分,我不是专家。很高兴有人解释为什么&lt;?&gt;&lt;?&gt; 作为开始标签和&lt;/?&gt;&lt;/?&gt; 作为结束标签可以分开工作将单词放入数组中。
  • 单词(即标签&lt;s&gt;…&lt;/s&gt;之间的节点内容)通过搜索的给定XPath表达式“//s”返回为NodeList内容任何节点标记在XML结构中的任何级别等于“s”(用“//”表示); VBA 将这些 list 视为一个数组。您可以搜索单个表达式,例如通过 "//s[2]" 仅返回第二个节点,甚至返回节点内的条件(或者 XPath "t/s" 仅在起始 &lt;t&gt; 标记之后的级别 2 = 1 级别搜索。您可以重命名trootsitem 以更有意义的方式为他们施洗。@Jvdv :-)
  • @JvdV,好的,确实立即理解了公式,只是建议给不那么先进的 XML 的人提供进一步的提示 :-);祝贺您向许多用户提供了丰富而有用的解释(点赞不言自明)。
【解决方案2】:

如果你想使用 VBA 代码,你可以试试这个:

Option Explicit

Sub test()

    Dim arr As Variant
    Dim str As String
    Dim i As Long, j As Long, LastRow As Long

    With ThisWorkbook.Worksheets("Sheet1")

        LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row

        For i = 1 To LastRow

            str = .Range("A" & i).Value

            arr = Split(str, " ")

            For j = LBound(arr) To UBound(arr)
                .Cells(i, j + 3).Value = Len(arr(j))
            Next j

        Next i

    End With

End Sub

结果:

【讨论】:

    【解决方案3】:

    我不完全清楚您要寻找什么最终结果,或者您是否接受 VBA 解决方案,但这是我的解释:

    Function lengths(txt As String) As String
      Dim wrd
      For Each wrd In Split(txt)
        If lengths <> "" Then lengths = lengths & ","
        lengths = lengths & Len(wrd)
      Next wrd
    End Function
    

    将代码粘贴到 VBA 模块中,然后,例如,如果 A1 包含 Black Cup With Handle,那么您可以在另一个单元格中使用 =length(A1),这将返回 5,3,4,6

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-14
      • 1970-01-01
      • 2021-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-30
      相关资源
      最近更新 更多