【问题标题】:How to count up elements in excel如何计算excel中的元素
【发布时间】:2014-10-14 10:11:01
【问题描述】:

所以我有一个名为化学式的列,包含大约 40,000 个条目,我想要做的是计算化学式中包含多少元素。例如:-

EXACT_MASS  FORMULA
626.491026  C40H66O5
275.173274  C13H25NO5

为此,我需要某种返回结果的公式

C  H  O
40 66 5
13 25 5

所有作为不同元素的单独列和不同条目的行。有没有公​​式可以做到这一点?

【问题讨论】:

  • 字符串是否固定,我的意思是,每个条目都有一个字母然后两个数字,一个字母然后两个数字,一个字母和其余数字?
  • 所以每个条目都有一个字母表,但数字可能会有所不同。因此,例如,您可以获得 C10H60,或者您可以获得 CH4,它应该将 C 计为 1,甚至 CH3O,它应该将 C 和 O 计为 1,H 计为 3
  • K,但一切都是标准的,因为总是以 C 开头,然后是 H,然后是 O。对吗?
  • 所以基本上它必须计算化学式中可能存在的 C、H、O 或任何化学元素。例如,H2CO3 会以 H - 2、C - 1 和 O - 3 的形式出现
  • 处理此问题时,请注意区分大小写。 CO2(二氧化碳)是C-1,O-2。 Co2(钴)是 Co-2。

标签: excel count


【解决方案1】:

你可以自己制定公式。

使用 ALTF11 打开 VBA 编辑器并插入一个新模块。

单击工具,然后单击引用,添加对Microsoft VBScript Regular Expressions 5.5 的引用。

现在添加以下代码:

Public Function FormulaSplit(theFormula As String, theLetter As String) As String

    Dim RE As Object
    Set RE = CreateObject("VBScript.RegExp")
    With RE
        .Global = True
        .MultiLine = False
        .IgnoreCase = False
        .Pattern = "[A-Z]{1}[a-z]?"
    End With

    Dim Matches As Object
    Set Matches = RE.Execute(theFormula)

    Dim TheCollection As Collection
    Set TheCollection = New Collection

    Dim i As Integer
    Dim Match As Object
    For i = (Matches.Count - 1) To 0 Step -1
        Set Match = Matches.Item(i)
        TheCollection.Add Mid(theFormula, Match.FirstIndex + (Len(Match.Value) + 1)), UCase(Trim(Match.Value))
        theFormula = Left(theFormula, Match.FirstIndex)
    Next

    FormulaSplit = "Not found"
    On Error Resume Next
    FormulaSplit = TheCollection.Item(UCase(Trim(theLetter)))
    On Error GoTo 0

    If FormulaSplit = "" Then
        FormulaSplit = "1"
    End If

    Set RE = Nothing
    Set Matches = Nothing
    Set Match = Nothing
    Set TheCollection = Nothing

End Function

用法:

  • FormulaSplit("C40H66O5", "H") 将返回 66。
  • FormulaSplit("C40H66O5", "O") 将返回 5。
  • FormulaSplit("C40H66O5", "blah") 将返回“未找到”。

您可以直接在工作簿中使用此公式。

【讨论】:

  • 感谢您的帮助!我刚刚试了一下,基本上是复制粘贴进去了,但我一直收到以下回复:- 未定义用户定义的类型
  • @user2062207 - 您是否添加了对Microsoft VBScript Regular Expressions 5.5 库的引用?在 VBA 编辑器中,单击工具,然后单击引用。然后在列表中找到Microsoft VBScript Regular Expressions 5.5。勾选它,然后按 OK。
  • @user2062207 我已将 Jamie 的代码更新为后期绑定。我相信当 Jamie 批准它时,您应该能够看到更新的代码,然后您可以检查它。
  • @JurPertin - 感谢您的帮助。我无法直接接受您的编辑,但我已采纳您的想法并编辑了答案。谢谢!
  • 为迟到的回复道歉,我们实验室的网络中断了。现在就做!
【解决方案2】:

我已经在一个公式中尝试了这样做,并提出了以下内容:

=IFERROR((MID($C18,FIND(D17,$C18)+1,2))*1,IFERROR((MID($C18,FIND(D17,$C18)+1,1))*1,IFERROR(IF(FIND(D17,$C18)>0,1),0)))

它不是很整洁,如果您的任何元素出现超过 99 次,则必须进一步扩展 - 我还在工作表上使用了随机放置,因此标题 H、C 和 O 位于第 17 行。我个人会接受 Jamie 的回答,但只是想试试这个,看看我是否可以用一个可能的公式来做到这一点,并认为它值得分享,就像另一个视角一样。

【讨论】:

  • 感谢您的帮助!我会试一试,看看进展如何
  • 这对这两个例子非常有效,所以它得到了我的投票。请注意,如果一个元素有两个字符,它将不起作用。对于 CO2,它正确地为碳返回 1,为氧返回 2。但是对于 Co2,它错误地为碳返回 1,为钴返回 1。我不认为你可以在不使用数组公式的情况下使用函数来做到这一点。
【解决方案3】:

尽管这有一个出色的(并且被接受的)VBA 解决方案,但我无法抗拒不使用 VBA 的挑战。

我之前发布了一个解决方案,但并非在所有情况下都有效。这段新代码应该始终有效:

=MAX(
   IFERROR(IF(FIND(C$1&ROW($1:$99),$B2),ROW($1:$99),0),0),
   IFERROR(IF(FIND(C$1&CHAR(ROW($65:$90)),$B2&"Z"),1,0),0)
 )

作为数组公式输入:Ctrl + Shift + Enter

输出:

公式在找不到时输出 0,我只是使用条件格式将零变成灰色。

工作原理

这部分公式查找元素,后跟 1 到 99 之间的数字。如果找到,则返回原子数。否则,返回 0。结果存储在一个数组中:

IFERROR(IF(FIND(C$1&ROW($1:$99),$B2),ROW($1:$99),0),0)

对于 C13H25NO5,搜索“C”会返回此数组:

{1,0,0,0,0,0,0,0,0,0,0,0,13,0,0,0,...,0}

1 是第一个数组元素,因为 C1 是匹配项。 13 是第十三个数组元素,这就是我们感兴趣的。

公式的下一部分查找元素,后跟一个大写字母,表示一个新元素。 (字母 A 到 Z 是字符 65 到 90。)如果找到,则返回数字 1。否则,返回 0。结果存储在一个数组中:

IFERROR(IF(FIND(C$1&CHAR(ROW($65:$90)),$B2&"Z"),1,0),0)

“Z”附加到化学式后,以便在其最后一个元素没有数字时找到匹配项。 (例如,“H2O”。)元素周期表中没有元素“Z”,所以这不会造成问题。

对于 C13H25NO5,搜索“N”会返回此数组:

{0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0}

1 是数组中的第 15 个元素。那是因为它找到了字母“NO”,而 O 是字母表的第 15 个字母。

从每个数组中取最大值可以得到所需的原子数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-12
    • 2017-08-23
    • 2017-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-05
    相关资源
    最近更新 更多