从化学式中提取数字

Jul*_*ian 6 excel vba excel-vba excel-formula chemistry

如果已经提出并回答了这个问题,我很抱歉,但我找不到满意的答案.

我有一个化学公式列表,按顺序包括:C,H,N和O.我想在每个字母之后提取数字.问题是并非所有公式都包含N.但是,所有公式都包含C,H和O. 并且数字可以是单数,双数或(仅在H的情况下)三位数.

因此数据看起来像这样:

  • C20H37N1O5
  • C10H12O3
  • C20H19N3O4
  • C23H40O3
  • C9H13N1O3
  • C14H26O4
  • C58H100N2O9

我想在单独的列中列出列表的每个元素编号.所以在第一个例子中它将是:

20 37 1 5
Run Code Online (Sandbox Code Playgroud)

我一直在努力:

=IFERROR(MID(LEFT(A2,FIND("H",A2)-1),FIND("C",A2)+1,LEN(A2)),"") 
Run Code Online (Sandbox Code Playgroud)

分离出C#.然而,在此之后我被卡住了,因为H#侧面是O或N.

是否有excel公式或VBA可以做到这一点?

Pᴇʜ*_*Pᴇʜ 10

使用正则表达式

这对于正则表达式(正则表达式)来说是一个很好的任务.由于VBA不支持开箱即用的正则表达式,因此我们需要首先引用Windows库.

  1. 工具然后引用下添加对正则表达式的引用 在此输入图像描述

  2. 并选择Microsoft VBScript Regular Expression 5.5 在此输入图像描述

  3. 将此功能添加到模块

    Option Explicit 
    
    Public Function ChemRegex(ChemFormula As String, Element As String) As Long
        Dim strPattern As String
        strPattern = "([CNHO])([0-9]*)" 
                     'this pattern is limited to the elements C, N, H and O only.
        Dim regEx As New RegExp
    
        Dim Matches As MatchCollection, m As Match
    
        If strPattern <> "" Then
            With regEx
                .Global = True
                .MultiLine = True
                .IgnoreCase = False
                .Pattern = strPattern
            End With
    
            Set Matches = regEx.Execute(ChemFormula)
            For Each m In Matches
                If m.SubMatches(0) = Element Then
                    ChemRegex = IIf(Not m.SubMatches(1) = vbNullString, m.SubMatches(1), 1) 
                                'this IIF ensures that in CH4O the C and O are count as 1
                    Exit For
                End If
            Next m
        End If
    End Function
    
    Run Code Online (Sandbox Code Playgroud)
  4. 在单元格公式中使用这样的函数

    例如在单元格B2中:=ChemRegex($A2,B$1)并将其复制到其他单元格 在此输入图像描述


也识别出多次出现的元素的化学式,如CH3OHCH2COOH

请注意,上面的代码不能计算CH3OH元素出现多次的情况.然后只有第一个H3是计数,最后省略.

如果您还需要以类似CH3OHCH2COOH(并总结元素的出现)的格式识别公式,那么您需要更改代码以识别这些...

If m.SubMatches(0) = Element Then
    ChemRegex = ChemRegex + IIf(Not m.SubMatches(1) = vbNullString, m.SubMatches(1), 1)
    'Exit For needs to be removed.
End If
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

也识别含有2个字母元素的化学式,如NaOHCaCl2

除了多次出现的元素更改之外,还可以使用以下模式:

strPattern = "([A-Z][a-z]?)([0-9]*)"   'https://regex101.com/r/nNv8W6/2
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  1. 请注意,它们必须位于正确的大写/小写字母大小写中.CaCl2工作但不是cacl2CACL2.
  2. 请注意,这不能证明这些字母组合是否是元素周期表的现有元素.所以这也将承认例如.Xx2Zz5Q作为虚构的元素Xx = 2,Zz = 5Q = 1.

    要仅接受元素周期表中存在的组合,请使用以下模式:

    strPattern = "([A][cglmrstu]|[B][aehikr]?|[C][adeflmnorsu]?|[D][bsy]|[E][rsu]|[F][elmr]?|[G][ade]|[H][efgos]?|[I][nr]?|[K][r]?|[L][airuv]|[M][cdgnot]|[N][abdehiop]?|[O][gs]?|[P][abdmortu]?|[R][abefghnu]|[S][bcegimnr]?|[T][abcehilms]|[U]|[V]|[W]|[X][e]|[Y][b]?|[Z][nr])([0-9]*)"
    'https://regex101.com/r/Hlzta2/3
    'This pattern includes all 118 elements up to today. 
    'If new elements are found/generated by scientist they need to be added to the pattern.
    
    Run Code Online (Sandbox Code Playgroud)