You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Office Add-in JavaScript API查找段落中的下标/上标符号

问题描述

我的需求和查找选中内容中的加粗单词类似,但要找的不是空格分隔的单词,而是段落里格式为下标或上标的字母数字字符(比如words<sub>like</sub><sup>this</sup>这类),最终要把这些字符用<sub>和<sup>标签包裹,例如把404<sup>2</sup>转换为404&lt;sup&gt;2&lt;/sup&gt;。

以下是对应的Python COM实现代码:

def paragraph_to_html(doc, paragraph):
    rng = doc.Range(paragraph.Range.Start, paragraph.Range.End - 1)
    rng.Find.Text = ''
    rng.Find.Font.Superscript = True
    while rng.Find.Execute():
        rng.InsertBefore('&lt;sup&gt;')
        rng.InsertAfter('&lt;/sup&gt;')
        rng.Font.Superscript = False
        rng = doc.Range(rng.End, paragraph.Range.End - 1)

我想用JavaScript Office Add-in改写这段代码,请问:

  • 如何查找下标和上标字符?
  • 如果无法直接查找,如何遍历段落中的每个字符,检查其font.subscript是否为true?

解决方案

方法一:使用Office JavaScript API的Find功能

Office JS的Range.find接口支持通过字体属性匹配内容,逻辑和你Python COM的实现一致,以下是查找上标的示例代码:

async function wrapSuperscriptInTags() {
    await Word.run(async (context) => {
        const paragraph = context.document.selectedParagraphs.getFirst();
        let range = paragraph.getRange('Start', 'End');
        
        // 设置查找规则:匹配所有上标格式内容
        const findOptions = context.createFindOptions();
        findOptions.font.superscript = true;
        findOptions.matchWildcards = false;
        
        let foundRange = range.find.findFirst(findOptions);
        await context.sync();
        
        // 循环处理所有匹配项
        while (foundRange) {
            // 插入标签
            foundRange.insertText('&lt;sup&gt;', 'Before');
            foundRange.insertText('&lt;/sup&gt;', 'After');
            // 取消上标格式,避免重复匹配
            foundRange.font.superscript = false;
            
            // 更新查找范围,从当前匹配项末尾开始
            range = paragraph.getRange(foundRange.end, 'End');
            foundRange = range.find.findFirst(findOptions);
            await context.sync();
        }
    }).catch(error => {
        console.error(error);
    });
}

查找下标只需将findOptions.font.superscript = true改为findOptions.font.subscript = true即可。

方法二:遍历段落字符检查格式

如果Find功能无法满足需求,可以逐个遍历段落字符,检查字体格式:

async function wrapSubSupByTraversing() {
    await Word.run(async (context) => {
        const paragraph = context.document.selectedParagraphs.getFirst();
        const textRange = paragraph.getRange('Start', 'End');
        textRange.load('text, length');
        await context.sync();
        
        let currentTag = null; // 记录当前处理的标签类型(sub/sup)
        let startIndex = 0;
        
        // 遍历每个字符
        for (let i = 0; i < textRange.length; i++) {
            const charRange = textRange.getRange(i, i + 1);
            charRange.load('font/superscript, font/subscript');
            await context.sync();
            
            const isSup = charRange.font.superscript;
            const isSub = charRange.font.subscript;
            
            // 处理上标逻辑
            if (isSup) {
                if (!currentTag || currentTag !== 'sup') {
                    // 关闭之前的标签(如果有)
                    if (currentTag) {
                        textRange.getRange(startIndex, i).insertText(`&lt;/${currentTag}&gt;`, 'After');
                        await context.sync();
                    }
                    currentTag = 'sup';
                    startIndex = i;
                    // 插入起始标签
                    textRange.getRange(i, i).insertText('&lt;sup&gt;', 'Before');
                    await context.sync();
                    // 插入后段落长度变化,调整索引
                    i += '&lt;sup&gt;'.length;
                    textRange.load('length');
                    await context.sync();
                }
            } else if (isSub) {
                // 处理下标逻辑,和上标逻辑一致
                if (!currentTag || currentTag !== 'sub') {
                    if (currentTag) {
                        textRange.getRange(startIndex, i).insertText(`&lt;/${currentTag}&gt;`, 'After');
                        await context.sync();
                    }
                    currentTag = 'sub';
                    startIndex = i;
                    textRange.getRange(i, i).insertText('&lt;sub&gt;', 'Before');
                    await context.sync();
                    i += '&lt;sub&gt;'.length;
                    textRange.load('length');
                    await context.sync();
                }
            } else {
                // 当前字符不是下标/上标,关闭标签
                if (currentTag) {
                    textRange.getRange(startIndex, i).insertText(`&lt;/${currentTag}&gt;`, 'After');
                    await context.sync();
                    currentTag = null;
                }
            }
        }
        
        // 处理段落末尾未关闭的标签
        if (currentTag) {
            textRange.getRange(startIndex, textRange.length).insertText(`&lt;/${currentTag}&gt;`, 'After');
            await context.sync();
        }
        
        // 取消所有下标/上标格式
        textRange.font.superscript = false;
        textRange.font.subscript = false;
        await context.sync();
    }).catch(error => {
        console.error(error);
    });
}

注意事项

  • 所有操作需包裹在Word.run中,确保上下文同步
  • 插入标签后段落长度会变化,需重新加载长度并调整遍历索引
  • 连续的下标/上标字符要避免重复插入标签

内容的提问来源于stack exchange,提问作者NotAProgrammer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 19:35:19