2015-11-26 3 views
5

Я работаю над добавлением Google Docs, которое превращает текст в таблицу. Это позволяет пользователю либо 1) выбрать некоторый текст или 2) поместить их курсор внутри текста они хотят, и когда пользовательские кнопки на боковой панели нажата, скрипт:Вставьте таблицу в документ google в позиции курсора

  1. Вставьте одну строку, холостой ячейка таблицы в позиции курсора или startIndex выбранного текста,
  2. Поместите внутри этой ячейки либо текст, выбранный пользователем, либо полный текст элемента, в котором находится курсор,
  3. Удалить исходный выделенный текст/элемент, так что остается только таблица

(По существу, это просто «рисование» таблицы вокруг выбранного текста или элемента).

Обзор documentation показывает, что текст можно вставить через var element = cursor.insertText('ಠ‿ಠ');, но аналогичного метода для вставки других элементов не существует. Таким образом, я пытался использовать insertTable(childIndex, cells) с разной степенью успеха. Сосредоточив внимание на том обстоятельстве, в котором пользователь просто помещает курсор внутри элемента, я могу вставить таблицу с правильным текстом и удалить исходный текст, но я не могу найти способ вставить таблицу в нужную позицию. Я попытался следующие, но безрезультатно:

  1. var newTable = body.insertTable(cursor.getOffset(), [['Test Text']]); - Это создает таблицу, но вставляет его в неправильном положении, казалось бы, на основе которой в тексте помещается курсор, как правило, к началу документа ,

  2. var el = cursor.getElement().asBody(); var newTable = el.insertTable(0, [['Test Text']]); - Это ничего не делает

  3. var el = cursor.getElement().getParent().asBody(); var newTable = el.insertTable(0, [['Test Text']]); - это не делает ничего

  4. var el = cursor.getElement(); var parent = el.getParent().getChildIndex(el); var newTable = body.insertTable(parent, [['Test Text']]); - Это вставляет таблицу в самом начале документа.

Обыск Stack Overflow дает this very similar question с предложением вставить некоторый текст-заполнитель в позиции курсора, а затем искать документ для этой вставленной строки и размещения таблицы. У меня есть две основные проблемы с этим подходом:

  1. Мне нужно изменить текст непосредственно окружающей точку вставки и вставки дополнительного текст, кажется, что это может сделать это более трудным, и
  2. Что еще более важно, я до сих пор не знаю, как получить правильное положение для точки вставки таблицы.

Если кто-то может расширить текст-метод-заполнитель или предоставить новое решение, это будет очень полезно. Благодаря!

ответ

3

Я использовал следующий код GAS для вставки таблицы в текущую позицию курсора в Google Doc. Он работает лучше, если ваш курсор находится на новой строке.

var doc = DocumentApp.getActiveDocument(); 
    var body = doc.getBody(); 
    var cursor = doc.getCursor(); 

    var element = cursor.getElement(); 
    var parent = element.getParent(); 
    //here table is an array of cells like 
    // [[r1c1, r1c2], [r2c1, r2c2]] 
    body.insertTable(parent.getChildIndex(element) + 1, table); 

Edit: Для того, чтобы получить более полное представление в выработках позиции курсора в Google Doc, я рекомендую запускать следующий курсор инспектор GitHub проект

https://github.com/google/google-apps-script-samples/tree/master/cursor_inspector

1

TL; DR: используйте код фрагмент ниже.

Похоже, что то, что Google Docs делает при выборе «Вставка»> «Таблица», состоит в том, чтобы разбить текущий абзац на два абзаца, а затем вставить новую таблицу между ними.

Трудная часть состоит в том, чтобы разделить абзац на два. Я пытался добиться этого несколькими способами. Я не мог найти какой-либо API-запрос из документации Google Apps Script, которая делает это (API-интерфейс Spreadsheet API имеет метод moveTo() на объекте Range, но это не может помочь нам здесь). Я надеялся, что смогу скопировать элементы из данной позиции в абзаце дальше к другому абзацу и удалить оригиналы. Однако, так как 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.

Смежные вопросы