在脚本控制下的 Google Docs 中,能否以编程方式解决插入 table 后自动插入的段落?

In Google Docs under script control, can a paragraph inserted automatically after the insertion of a table be addressed programmatically?

我有一个 Google Docs 文档,其中有一个 PARAGRAPH,后跟一个 TABLE,然后是一个 TABLE。从视觉上看,两个 TABLE 之间有一个 PARAGRAPH。但是,以编程方式,使用以下代码,运行 日志表明没有 PARAGRAPH,即

[1] PARAGRAPH {'LEFT_TO_RIGHT' : true, 'LINE_SPACING' : 1.15, 'SPACING_AFTER' : 0, 'SPACING_BEFORE' : 0, 'INDENT_FIRST_LINE' : 0, 'INDENT_END' : 0, 'INDENT_START' : 0} 
[1/1] TEXT {} perth influencer
[2] TABLE {'BORDER_WIDTH' : 1, 'BORDER_COLOR' : '#000000'} 
[3] TABLE {'BORDER_WIDTH' : 1, 'BORDER_COLOR' : '#000000'} Keyword Research Volume
...

根据 appendTable 的 Google Apps 脚本文档:

This method will also append an empty paragraph after the table, since Google Docs documents cannot end with a table.

这一段是肉眼可以看到的,但现在的剧本是看不到的。也就是说,遍历文档正文的子元素无法检测到自动插入的段落的存在。这是一个问题,因为我想减少该段落的点数。

这可能是 Google Docs 通过 Google Apps 脚本的已知限制。或者它可能是我的错误代码,所以下面是我断言的基础函数。他们除了报告他们发现的东西外什么都不做,但即便如此,也许我遗漏了什么。

上面的输出是通过使用类型 GoogleAppsScript.Document.Body 的参数编码 LogChildren 并引用生成文档的正文生成的。

String.prototype.quoted = function () {
  return  "'" + this.replace(/'/g,"\'") + "'";
}

Number.prototype.quoted = function () {
  return String(this);
}

Boolean.prototype.quoted = function () {
    return this ? "true" : "false";
}

function getInnerText(child) {
    switch (child.getType().toString()) {
        case "BODY_SECTION":
            return child.asBody().getText();
            break;
        case "EQUATION":
            return child.asEquation().getText();
            break;
        case "EQUATION_FUNCTION":
            return child.asEquationFunction().getText();
            break;
        case "FOOTER_SECTION":
            return child.asFooterSection().getText();
            break;
        case "FOOTNOTE_SECTION":
            return child.asFootnoteSection().getText();
            break;
        case "HEADER_SECTION":
            return child.asHeaderSection().getText();
            break;
        case "LIST_ITEM":
            return child.asListItem().getText();
            break;
        case "PARAGRAPH":
            return "";
            break;
        case "TABLE":
            return child.asTable().getText();
            break;
        case "TABLE_CELL":
            return child.asTableCell().getText();
            break;
        case "TABLE_OF_CONTENTS":
            return child.asTableOfContents().getText();
            break;
        case "TABLE_ROW":
            return child.asTableRow().getText();
            break;
        case "TEXT":
            return child.asText().getText();
            break;
        case "PAGE_BREAK":
            return "";
            break;
        case "INLINE_IMAGE":
            return child.asInlineImage().getLinkUrl();
            break;
        default:
            return child.asText().getText();
            break;
    }
}
function getStyles(child) {
    const attribs = child.getAttributes();
    const attribList = [];
    for (let att in attribs) {
        try {
            if (null !== attribs[att])
                attribList.push(att.quoted() + " : " + attribs[att].quoted());
        }
        catch (E) { }
    }
    return "{" + attribList.join(", ") + "}";
}
function LogChild(index, child) {
    Logger.log("[%s] %s %s %s", index, child.getType().toString(), getStyles(child), getInnerText(child));
}
function LogChildren(body) {
    function LogDeeper(cc, child) {
        const childCount = child.getNumChildren();
        for (let c = 0; c < childCount; c++) {
            LogChild(String(cc) + "/" + String(c + 1), child.getChild(c));
        }
    }
    const childCount = body.getNumChildren();
    for (let c = 0; c < childCount; c++) {
        const child = body.getChild(c);
        LogChild(String(c + 1), child);
        if (isParagraph(child)) {
            LogDeeper(c + 1, child.asParagraph());
        }
        else if (isListItem(child)) {
            LogDeeper(c + 1, child.asListItem());
        }
    }
}
function isPageBreak(elem) {
    return elem.getType() === DocumentApp.ElementType.PAGE_BREAK;
}
function isText(elem) {
    return elem.getType() === DocumentApp.ElementType.TEXT;
}
function isParagraph(elem) {
    return elem.getType() === DocumentApp.ElementType.PARAGRAPH;
}
function isListItem(elem) {
    return elem.getType() === DocumentApp.ElementType.LIST_ITEM;
}
function isTable(elem) {
    return elem.getType() === DocumentApp.ElementType.TABLE;
}

使用 's Document#get to retrieve the document structure and if there is a intervening paragraph recorded between the two tables, issue UpdateParagraphStyleRequest修改该段落。

您可以通过 Advanced Google services

从应用脚本访问 api