如何使用 ONLYOFFICE 宏计算文本的预计阅读时间

2025年04月07日作者:Krystal

预估阅读时间是文本编辑器中一项实用的功能,它能帮助用户了解阅读文档大概需要耗费多长时间。我们的实习生 Vukasin 开发了一个别出心裁却切实有效的宏,可在 ONLYOFFICE 文档编辑器里计算预计阅读时间。在本文中,我们将对该宏进行剖析,解释每个功能的工作原理,以及它们是如何协同运作,从而给出准确的预估阅读时间的。

How to calculate the estimated reading time of your text using an ONLYOFFICE macro

构建宏

首先,我们使用 Api.GetDocument() 方法检索文档对象:

try {
        const document = Api.GetDocument();

定义常量

      // Constants for reading speed calculations
        const WORDS_PER_MINUTE = 238; // Average adult reading speed
        const COMPLEX_WORD_LENGTH = 7; // Words with this many chars or more are considered complex

此处定义了两个常量:

  • WORDS_PER_MINUTE:代表成年人的平均阅读速度,即每分钟 238 个单词。
  • COMPLEX_WORD_LENGTH:作为判断单词是否复杂的标准阈值。

单词计数

然后,countWords 函数根据空格将给定的文本拆分为单词,并统计非空单词的数量:

 function countWords(text) {
            if (!text) return 0;
            return text.split(/\s+/).filter((word) => word.length > 0).length;
        }

估计复杂度

为了估计文本复杂程度,我们采用 estimatedComplexity 函数:

   function estimateComplexity(text) {
            if (!text) return 0;
            const words = text.split(/\s+/).filter((word) => word.length > 0);
            if (words.length === 0) return 0;


            const complexWords = words.filter(
                (word) => word.length >= COMPLEX_WORD_LENGTH
            ).length;
            return complexWords / words.length;
        }

此函数通过以下方式确定文本的复杂度:

  1. 将文本拆分成单词。
  2. 将文本拆分成单词。
  3. 计算复杂单词在所有单词中所占的比例。

检索和处理段落

然后我们继续处理文本:

        const paragraphs = document.GetAllParagraphs();
        let totalWords = 0;
        let totalText = "";


        paragraphs.forEach((paragraph) => {
            const text = paragraph.GetText();
            totalWords += countWords(text);
            totalText += text + " ";
        });

在本部分中,我们将执行以下操作:

  1. 从文档中检索所有段落。
  2. 从文档中检索所有段落。
  3. 统计每个段落包含的单词数量,并累计总字数。
  4. 保存所有文本,以便后续进行复杂度评估。

调整复杂

这里,复杂度系数用于调整阅读速度。复杂度越高,有效阅读速度越低:

        const complexityFactor = estimateComplexity(totalText);
        const complexityAdjustment = 1 - complexityFactor * 0.3;
        const effectiveWPM = WORDS_PER_MINUTE * complexityAdjustment;

计算阅读时间

接下来,我们将总字数换算成阅读所需分钟数,再进一步转换为小时数:

        const readingTimeMinutes = totalWords / effectiveWPM;
        const readingTimeHours = readingTimeMinutes / 60;

格式化输出

之后,我们根据计算得出的时间,对阅读时间的输出结果进行格式化处理。

    let readingTimeText;
        if (readingTimeMinutes < 1) {
            readingTimeText = `less than 1 minute`;
        } else if (readingTimeMinutes < 60) {
            readingTimeText = `${Math.ceil(readingTimeMinutes)} minute${Math.ceil(readingTimeMinutes) !== 1 ? "s" : ""
                }`;
        } else {
            const hours = Math.floor(readingTimeHours);
            const remainingMinutes = Math.ceil((readingTimeHours - hours) * 60);
            readingTimeText = `${hours} hour${hours !== 1 ? "s" : ""}${remainingMinutes > 0
                    ? ` and ${remainingMinutes} minute${remainingMinutes !== 1 ? "s" : ""
                    }`
                    : ""
                }`;
        }

插入输出

然后我们插入格式化的输出:

      const infoText = `Reading Time: ${readingTimeText} (${totalWords} words at ${Math.round(
            effectiveWPM
        )} words per minute)`;


        const oParagraph = Api.CreateParagraph();
        oParagraph.AddText(infoText);
        oParagraph.SetBold(true);
        oParagraph.SetItalic(true);
        oParagraph.SetFontFamily("Arial");
        document.InsertContent([oParagraph], 0);
    } catch (error) {
        console.log("Error: " + error.message);
    }
})();

本部分:

  1. 生成包含阅读时间详细信息的格式化字符串。
  2. 创建一个新的段落对象,并向其中添加文本内容。
  3. 为文本应用样式(包括加粗、倾斜以及设置 Arial 字体)。
  4. 将该段落插入到文档的开头位置。

完整宏代码如下:

(function () {
    try {
        const document = Api.GetDocument();
        // Constants for reading speed calculations
        const WORDS_PER_MINUTE = 238; // Average adult reading speed
        const COMPLEX_WORD_LENGTH = 7; // Words with this many chars or more are considered complex


        function countWords(text) {
            if (!text) return 0;
            return text.split(/\s+/).filter((word) => word.length > 0).length;
        }


        function estimateComplexity(text) {
            if (!text) return 0;
            const words = text.split(/\s+/).filter((word) => word.length > 0);
            if (words.length === 0) return 0;


            const complexWords = words.filter(
                (word) => word.length >= COMPLEX_WORD_LENGTH
            ).length;
            return complexWords / words.length;
        }


        const paragraphs = document.GetAllParagraphs();
        let totalWords = 0;
        let totalText = "";


        paragraphs.forEach((paragraph) => {
            const text = paragraph.GetText();
            totalWords += countWords(text);
            totalText += text + " ";
        });


        const complexityFactor = estimateComplexity(totalText);


        const complexityAdjustment = 1 - complexityFactor * 0.3;
        const effectiveWPM = WORDS_PER_MINUTE * complexityAdjustment;


        const readingTimeMinutes = totalWords / effectiveWPM;
        const readingTimeHours = readingTimeMinutes / 60;


        let readingTimeText;
        if (readingTimeMinutes < 1) {
            readingTimeText = `less than 1 minute`;
        } else if (readingTimeMinutes < 60) {
            readingTimeText = `${Math.ceil(readingTimeMinutes)} minute${Math.ceil(readingTimeMinutes) !== 1 ? "s" : ""
                }`;
        } else {
            const hours = Math.floor(readingTimeHours);
            const remainingMinutes = Math.ceil((readingTimeHours - hours) * 60);
            readingTimeText = `${hours} hour${hours !== 1 ? "s" : ""}${remainingMinutes > 0
                    ? ` and ${remainingMinutes} minute${remainingMinutes !== 1 ? "s" : ""
                    }`
                    : ""
                }`;
        }


        const infoText = `Reading Time: ${readingTimeText} (${totalWords} words at ${Math.round(
            effectiveWPM
        )} words per minute)`;


        const oParagraph = Api.CreateParagraph();
        oParagraph.AddText(infoText);
        oParagraph.SetBold(true);
        oParagraph.SetItalic(true);
        oParagraph.SetFontFamily("Arial");
        document.InsertContent([oParagraph], 0);
    } catch (error) {
        console.log("Error: " + error.message);
    }
})();

现在,让我们在 Youtube 看看宏的运行效果:

此宏提供了一种在 ONLYOFFICE 中估算阅读时间的巧妙方法,我们相信它会成为您日常工作中的实用工具。ONLYOFFICE 宏功能多样,既能帮助增强软件的默认功能,又能编写出专为您需求量身打造的脚本。我们鼓励您探索我们的 API 方法库,开发属于自己的宏。如果您有任何问题或想法,欢迎随时与我们联系!我们始终欢迎反馈和合作。祝您在探索过程中一切顺利!

关于作者

How to calculate the estimated reading time of your text using an ONLYOFFICE macro.

创建免费的 ONLYOFFICE 账户

在线查看并协作编辑文本文档、电子表格、幻灯片、表单和 PDF 文件。