如何使用 Google Apps 脚本获取列表项的值

How to get value of List Items using Google Apps Script

我有 google 个包含列表项的文档。现在我想获取这些列表项的值。例如,文档包含:

  1. 新文本
  2. 旧文本

如何获取列表项 (1,2)?

我使用了以下代码,但它只提供了一个列表项对象数组,而不是这些列表项的值。

function docFunction() {
  var doc = DocumentApp.getActiveDocument();
  var docBody = doc.getBody();
  var docText = docBody.getListItems();
 
   Logger.log(docText);
 
}

无法检索您需要的值。

此外,ListItem 指的是列表本身中的项目,而不是 Glyph

最接近获得所需信息的方法是使用 getGlyphType,它将 return 您正在使用的字形类型,在本例中为 NUMBER.

参考

我相信你的目标如下。

  • 您想通过搜索文本从列表项中检索字形。

  • 例如有如下列表时,

      1. Text New
      2. Text Old
    
  • 通过搜索 Text NewText Old,您想检索 1.2. 的字形。

问题和解决方法:

遗憾的是,在目前阶段,似乎无法直接检索字形。这已经在评论和现有答案中提到了。

幸运的是,可以通过 Google 文档服务检索字形类型。并且,可以检索字形格式 Google 文档 API。我认为当使用这些时,可能会提出一个解决方法。所以,这只是我的尝试。我不确定这种方法是否适用于所有情况。所以请注意这一点。

示例脚本:

此脚本使用文档 API。所以 please enable Docs API at Advanced Google services.

function myFunction() {
  // Please set the searching texts in the list.
  // const searchText = ["One One One", "Two Two Two", "ii ii ii ii ii", "C", "Factory Floor"];

  // In this case, all list itmes are retrieved.
  const searchText = DocumentApp.getActiveDocument().getBody().getListItems().map(e => e.getText().trim());

  // This is an object for the numbers with the GlyphType. When you want to use more numbers and GlyphTypes, please add them.
  const numObj = {
    "NUMBER": ["1", "2", "3", "4", "5", "6"],
    "LATIN_LOWER": ["a", "b", "c", "d", "e", "f"],
    "LATIN_UPPER": ["A", "B", "C", "D", "E", "F"],
    "ROMAN_LOWER": ["i", "ii", "iii", "iv", "v", "vi"],
    "ROMAN_UPPER": ["I", "II", "III", "IV", "V", "VI"],
    "GLYPH_TYPE_UNSPECIFIED": ["", "", "", "", "", ""],
    "noGlyphType": ["", "", "", "", "", ""],
  };

  // 1. Retrieve list object using Docs API.
  const doc = DocumentApp.getActiveDocument();
  const listObj = Docs.Documents.get(doc.getId(), { fields: "lists" }).lists;

  // 2. Retrieve list items using Document service and create an object for searching the texts.
  const listItems = doc.getBody().getListItems();
  const obj = listItems.reduce((o, e) => {
    const listId = e.getListId();
    const glyphType = e.getGlyphType() || "GLYPH_TYPE_UNSPECIFIED";
    const nestingLevel = e.getNestingLevel().toString();
    const text = e.getText();
    if (o[listId]) {
      if (o[listId][nestingLevel]) {
        if (o[listId][nestingLevel][glyphType]) {
          o[listId][nestingLevel][glyphType].text.push(text);
        } else {
          o[listId][nestingLevel] = { [glyphType]: { text: [text], glyphFormat: listObj[listId].listProperties.nestingLevels[nestingLevel].glyphFormat, nestingLevel } };
        }
      } else {
        o[listId][nestingLevel] = { [glyphType]: { text: [text], glyphFormat: listObj[listId].listProperties.nestingLevels[nestingLevel].glyphFormat, nestingLevel } };
      }
    } else {
      o[listId] = { [nestingLevel]: { [glyphType]: { text: [text], glyphFormat: listObj[listId].listProperties.nestingLevels[nestingLevel].glyphFormat, nestingLevel } } };
    }
    return o;
  }, {});

  // 3. Search text and output an object for retrieving glyphs.
  const getRes = (obj, search, res = [], parents = []) => {
    Object.entries(obj).forEach(([k, v]) => {
      if (Array.isArray(v)) {
        v = v.map(vv => vv.trim());
        const temp = search.filter(s => v.includes(s));
        if (temp.length > 0) {
          const parent = parents[parents.length - 1];
          res.push(temp.map(e => ({ search: e, k: parent.k == "null" ? "noGlyphType" : parent.k, idx: v.indexOf(e), glyphFormat: parent.v.glyphFormat, nestingLevel: parent.v.nestingLevel })));
        }
      } else if (typeof v == "object") {
        parents.push({ k, v });
        getRes(v, search, res, parents);
      }
    });
    return search.map(s => res.flat().filter(t => t.search == s)[0]);
  }
  const res = getRes(obj, searchText).map(e => {
    const count = [...e.glyphFormat].reduce((c, e) => e == "%" ? c + 1 : c, 0);
    return e ? e.glyphFormat.replace(/%([0-9]+)/g, (_, p, o) => count > 1 ? numObj[e.k][o == 0 ? Number(p) : e.idx] : numObj[e.k][e.idx]) : "Text was not found."
  });

  console.log(res);
}

测试:

当上述脚本为运行时,检索所有列表项并返回字形。并且,例如,当使用下图中显示的示例文档并将 const searchText = ["One One One", "Two Two Two", "ii ii ii ii ii", "C", "Factory Floor"]; 用作搜索文本时,

得到如下结果。

[ '1.', '2.', 'ii.', '(A)', '1.3' ]

不幸的是,我找不到识别I1.I2.I的方法。这样,Factory Floor 的字形就变成了 1.3.

注:

  • 现阶段,在我提议的脚本中,我找不到识别I1.I2.I的方法。当我找到方法时,我想更新我的示例脚本。

  • 这只是我的尝试。我不确定这种方法是否适用于所有情况。所以请注意这一点。

  • 当您要检索所有列表项的字形时,请按如下方式修改上述脚本。

    • 来自

        const searchText = ["One One One", "Two Two Two", "ii ii ii ii ii", "C", "Factory Floor"];
      
    •   const searchText = DocumentApp.getActiveDocument().getBody().getListItems().map(e => e.getText().trim());
      
  • 很遗憾,目前阶段,好像check box type的glyph type无法检索到

参考文献: