2015-11-26 21 views
5

Pracuję nad dodatkiem do Dokumentów Google, który zamienia tekst w tabelę. Pozwala ona użytkownikowi albo 1) zaznaczyć fragment tekstu lub 2) umieścić swój kursor w tekście chcą, a gdy przycisk niestandardowy na pasku bocznym kliknięciu skrypt:Wstaw tabelę do dokumentu google w pozycji kursora

  1. Włóż jeden wiersz, single Tabela komórek w pozycji kursora lub początekIndex zaznaczonego tekstu, Umieść w komórce tekst wybrany przez użytkownika lub pełny tekst elementu, w którym znajduje się kursor,
  2. Usunięcie oryginalnego zaznaczonego tekstu/element tak, aby pozostała tylko tabela:

(Zasadniczo jest to po prostu "rysowanie" tabeli wokół zaznaczonego tekstu lub elementu)

Przegląd documentation pokazuje, że można wstawić tekst za pomocą var element = cursor.insertText('ಠ‿ಠ');, ale nie ma podobnej metody do wstawiania innych elementów. W związku z tym próbuję użyć insertTable(childIndex, cells) z różnym powodzeniem. Koncentrując się na sytuacji, w której użytkownik po prostu umieszcza kursor wewnątrz elementu, mogę wstawić tabelę z poprawnym tekstem i usunąć oryginalny tekst, ale nie mogę znaleźć sposobu na wstawienie tabeli we właściwej pozycji. Próbowałem następujące, bezskutecznie:

  1. var newTable = body.insertTable(cursor.getOffset(), [['Test Text']]); - Stwarza to stolik, ale umieszcza ją w niewłaściwym miejscu, pozornie w zależności od miejsca w tekście kursor znajduje się zazwyczaj w kierunku początku dokumentu .

  2. var el = cursor.getElement().asBody(); var newTable = el.insertTable(0, [['Test Text']]); - To nic nie robi

  3. var el = cursor.getElement().getParent().asBody(); var newTable = el.insertTable(0, [['Test Text']]); - To nic nie robi

  4. var el = cursor.getElement(); var parent = el.getParent().getChildIndex(el); var newTable = body.insertTable(parent, [['Test Text']]); - to wstawienie tabeli na samym początku dokumentu.

Przeszukanie przepełnienie stosu daje this very similar question z sugestią wkładając jakiś tekst zastępczy w pozycji kursora, a następnie poszukiwanie dokumentu dla tego wstawionego ciąg i umieszczenie stołu. Mam dwa główne problemy z tym podejściem:

  1. muszę zmodyfikować tekst bezpośrednio otaczający punkt wstawiania, a wkładając dodatkowy tekst wydaje się to może zrobić to trudniejsze, a
  2. Co ważniejsze, mam jeszcze zrobić nie wiem, jak uzyskać prawidłowe położenie punktu wstawienia tabeli.

Jeśli ktokolwiek mógłby rozwinąć metodę tekstu zastępczego lub dostarczyć nowe rozwiązanie, byłoby to bardzo pomocne. Dzięki!

Odpowiedz

3

Użyłem następującego kodu GAS do wstawienia tabeli w bieżącym położeniu kursora w dokumencie Google Doc. Działa lepiej, gdy kursor znajduje się na linii nowej.

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: Aby uzyskać lepszy wgląd w funkcjonowanie pozycji kursora w dokumencie Google, polecam, aby uruchomić projekt GitHub następujące kursor inspektor

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

1

TL; DR: użyć kodu fragment poniżej.

Wygląda na to, że to, co robi Dokumenty Google po wybraniu Wstaw> Tabela, polega na rozbiciu bieżącego akapitu na dwa akapity, a następnie wstawieniu nowej tabeli pomiędzy.

Trudną częścią jest podzielenie akapitu na dwie części. Próbowałem to osiągnąć na kilka sposobów. Nie mogłem znaleźć żadnego wywołania API z dokumentacji Google Apps Script, która to robi (interfejs API arkusza kalkulacyjnego ma metodę moveTo() na obiekcie Range, ale to nam nie pomoże). Miałem nadzieję, że uda mi się skopiować elementy z określonej pozycji w akapicie do kolejnego akapitu i usunąć oryginały. Jednak od czasu Document Service does not allow explicit insertion of several element types, ale można nimi manipulować tylko w miejscu, takim jak elementy Equation, kopiowanie tych jeden po drugim jest niemożliwe.

Na szczęście, Paragraph ma metodę copy(), która wykonuje głęboką kopię. Więc przyjmuję to, aby skopiować cały akapit, usunąć wszystko od pozycji kursora do przodu w oryginalnym akapicie i usunąć wszystko do miejsca, w którym kursor znajdował się w kopii akapitu. W ten sposób masz podział akapitu w środku i możesz wstawić tabelę w wymaganej pozycji. Działa to tak samo dla modelu ListItem.

Oto kod funkcji splitParagraphAt(), która zwraca nowo utworzony akapit (lub element listy, który jest następnym rodzeństwem oryginalnego). Wrzuciłem dodatkowe kontrole do kodu, aby upewnić się, że to, co robisz, jest tym, co myślisz, że robi. Następnie dodałem krótki fragment kodu, w jaki sposób można go użyć do wstawienia tabeli w bieżącej pozycji kursora. Można użyć splitParagraphAt() podobnie jak wstawić dowolny element w pozycji kursora. Nie testowałem tego dokładnie, więc wszelkie dane wejściowe są mile widziane.

/** 
* 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; 
} 

Oto fragment kodu do wstawiania tabeli w pozycji kursora i ustawienie pozycji kursora w pierwszej komórce tabeli:

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)); 

Należy pamiętać, że nie należy jeszcze pewne dodatkowe kontrole na zobacz, czy jest zaznaczenie, czy nie, itp. W szczególności zakłada się, że to cursor nie będzie null.

Powiązane problemy