选择的化学式中的下标数字

Subscript numbers in chemical formulae from selection

我经常在我的文档中找到需要数字下标的化学式。例如H2O应该是H2O,H2SO4应该是H2SO4。我正在尝试编写一个宏,它将从突出显示的选择和下标数值中获取数字。我不太擅长编程。我尝试了以下变化:

Sub SubscriptNumbers()
    
    Dim Char As String
  
    For Each Char In Selection.Characters
             
            If Char >= "0" And Char <= "9" Then
                Char = Char.Font.Subscript
            End If
        
    Next Char
    
End Sub

但我遇到了令人困惑的错误(编译错误:For Each control variable must be Variant or Object;但如果我将 Char 更改为 variant,它运行时没有错误,但似乎没有执行任何操作)。我知道知情人士对使用 'Select' 感到厌恶,但我的文档可能包含许多不应作为下标的其他数字。

虽然文档中没有说明循环遍历 Characters,但您需要声明 Char As Range。然后你需要检查 Char.Text 是否是一个数字。有一个 built-in 函数可以执行此操作 - IsNumeric。最后,您需要将 .Font.Subscript 设置为 true 或 false。

Sub SubscriptNumbers()
   Dim Char As Range
  
   For Each Char In Selection.Characters
      If IsNumeric(Char.Text) Then
         Char.Font.Subscript = True
      End If
   Next Char
    
End Sub

以下宏将在活动文档(或只是 selected 范围)中搜索化学式(例如 H2O、C5H8(N2S)4、3(CaO)•2(SiO2)•4( H2O)(gel) + 3Ca(OH)2) 和功率表达式(例如 100m2),superscripting/subscripting 适当的数字。除非您使用的是同位素,否则结果应该是正确的 - 您需要自己应用同位素上标(如果数字已经上标,它们将保持不变)。

如果您的文档有其他字母数字字符串,其中 non-superscripted 数字跟在字母后面(例如 Table 单元格引用),您只需要 select 范围(s ) 包含要转换的文本并对提示回答“否”。

Sub Demo()
Application.ScreenUpdating = False
Dim RngSel As Range, RngNum As Range, RngTmp As Range, bState As Boolean
Select Case MsgBox("Do you want to process the whole document?", _
    vbYesNoCancel + vbQuestion, "Chemical/Power Formatter")
  Case vbYes
    bState = True
  Case vbNo
    bState = False
  Case vbCancel
    End
End Select
Set RngSel = Selection.Range
With ActiveDocument.Range
  If bState = False Then .Start = RngSel.Start
  With .Find
    .ClearFormatting
    .Text = "[A-Za-z)][0-9]{1,}"
    .MatchWildcards = True
    .Wrap = wdFindStop
    .Forward = True
  End With
  Do While .Find.Execute = True
    Set RngNum = .Characters.Last
    If bState = False Then
      If RngNum.InRange(RngSel) = False Then Exit Do
    End If
    Set RngTmp = .Words.Last
    RngTmp.MoveStartUntil " ", wdBackward
    If LCase(RngTmp.Text) = RngTmp.Text Then
      RngNum.Font.Superscript = True
    ElseIf RngNum.Font.Superscript = False Then
      RngNum.Font.Subscript = True
    End If
    .Collapse Direction:=wdCollapseEnd
  Loop
End With
RngSel.Select
Set RngTmp = Nothing: Set RngNum = Nothing: Set RngSel = Nothing
Application.ScreenUpdating = True
End Sub