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
。