TL; DR:使用代码下面的代码段。
看起来Google Docs在选择“插入”>“表格”时会执行的操作是将当前段落分成两段,然后在两段之间插入一个新表格。
困难的部分是将段落分成两部分。我试图通过几种方式来实现这一点。我无法从Google Apps脚本文档找到任何API调用(电子表格API在Range
对象上有moveTo()
方法,但这不能帮助我们)。我希望能够将段落中给定位置的元素复制到另一段中,并删除原稿。但是,由于Document Service does not allow explicit insertion of several element types只能在原地进行操作,如Equation
元素,因此无法一一复制这些元素。
幸运的是,Paragraph
有一个copy()
方法执行深度复制。因此,我接下来要复制整个段落,从原始段落中的光标位置向前移除所有内容,并删除光标所在段落副本中的所有内容。这样,你就可以在中间分割段落,并且可以在需要的位置插入一个表格。它的作用方式与ListItem
相同。
下面是函数splitParagraphAt()
的代码,该函数返回新创建的段落(或列表项,它是原始段的下一个兄弟元素)。我在代码中进行了一些额外的检查,以确定它所做的是您认为正在做什么。接下来,我添加了一个简短代码摘录,说明如何在当前光标位置插入一张表。有人可能会使用splitParagraphAt()
类似于在光标位置插入任何元素。我没有彻底测试过,所以任何输入都是可以接受的。
/**
* Splits the contents of the paragraph (or list item) at the given position,
* producing two adjacent paragraphs (or list items). This function may be used
* to insert any kind of element at an arbitrary document position, but placing
* it immediately before the second paragraph (or list item).
*
* @param {Position} pos The position where the paragraph (or list item) should
* be split. `pos.getElement()` should be either a Text, Paragraph or
* ListItem object.
*
* @returns {ContainerElement} The second (newly created) Paragraph or ListItem
* object.
*
*/
function splitParagraphAt(pos) {
var el = pos.getElement(), offset = pos.getOffset();
var inParagraph = (el.getType() == DocumentApp.ElementType.PARAGRAPH || el.getType() == DocumentApp.ElementType.LIST_ITEM);
if (!inParagraph && (el.getType() != DocumentApp.ElementType.TEXT)) {
throw new Error("Position must be inside text or paragraph.");
}
var par;
if (inParagraph) {
// in this case, `offset` is the number of child elements before this
// Position within the same container element
par = el;
if (offset == par.getNumChildren()) {
// we're at the end of the paragraph
return par.getParent().insertParagraph(
par.getParent().getChildIndex(par) + 1, "");
}
el = par.getChild(offset);
}
else {
par = el.getParent();
if (par == null || (par.getType() != DocumentApp.ElementType.PARAGRAPH && par.getType() != DocumentApp.ElementType.LIST_ITEM)) {
throw new Error("Parent of text is not a paragraph or a list item.");
}
}
var parContainer = par.getParent();
if (!("insertParagraph" in parContainer)) {
throw new Error("Cannot insert another paragraph in this container.");
}
// This assumes the given position is in the current document.
// alternatively, one may traverse through parents of par until document
// root is reached.
var doc = DocumentApp.getActiveDocument();
var elIndex = par.getChildIndex(el);
var newPar = par.copy();
var newEl = newPar.getChild(elIndex);
// remove everything up to position from the new element
if (!inParagraph && (offset != 0)) {
newEl.deleteText(0, offset-1);
}
newEl = newEl.getPreviousSibling();
while (newEl != null) {
// get the previous sibling before we remove the element.
var prevEl = newEl.getPreviousSibling();
newEl.removeFromParent();
newEl = prevEl;
}
// since we might remove el itself, we get the next sibling here already
var nextEl = el.getNextSibling();
// remove everything from position onwards in the original element
if (!inParagraph && (offset != 0)) {
el.deleteText(offset, el.getText().length-1);
}
else {
// we're at the beginning of the text (or just before a paragraph
// subelement) and need to remove the entire text/subelement.
el.removeFromParent();
}
el = nextEl;
while (el != null) {
// get the next sibling before we remove the element.
nextEl = el.getNextSibling();
el.removeFromParent();
el = nextEl;
}
// actually insert the newly created paragraph into the document tree.
switch (par.getType()) {
case DocumentApp.ElementType.PARAGRAPH:
parContainer.insertParagraph(parContainer.getChildIndex(par)+1, newPar);
break;
case DocumentApp.ElementType.LIST_ITEM:
parContainer.insertListItem(parContainer.getChildIndex(par)+1, newPar);
break;
}
return newPar;
}
下面是在光标位置插入一个表格并设置在表中的第一个单元格中的光标位置的代码摘录:
var doc = DocumentApp.getActiveDocument();
var cursor = doc.getCursor();
var el = (cursor.getOffset() == 0? cursor.getElement() : splitParagraphAt(cursor));
var parentEl = el.getParent();
var table = parentEl.insertTable(parentEl.getChildIndex(el), [['ಠ‿ಠ']]);
doc.setCursor(doc.newPosition(table.getCell(0, 0), 0));
注意,这里仍然需要一些额外的检查看看有没有选择,等等。具体来说,这个假设cursor
不会是null
。