Home > OS >  Cannot update text in paragraph of NamedRange
Cannot update text in paragraph of NamedRange

Time:02-16

I have a radio button with a few options in my google Doc. When the user selects an option, it adds a section with a heading and also paragraph. It should add the section only if the section isn't available and append the 'updated' text to the paragraph.

If the section is already available, it should only append the updated text at the end of the text.

Issue: Actually the behavior is pretty strange:

  1. For instance, if I select the section named 'Diagnoses' it will be created correctly.

Diagnoses

updated text, new range? true

  1. If I select the section named 'Anamnese'. the section will be also created correctly:

Diagnoses

updated text, new range? false

Anamnese

updated text, new range? true

  1. If I switch back to 'Diagnoses' it looks like this:

Diagnose

updated text, new range? true

Anamneseupdated text, new range? false

updated text, new range? trueupdated text, new range? false

enter image description here

function manageSection(selectedSection) { 
  section = selectedSection;
  var range = doc.getNamedRanges().find(r => r.getName() == section);
  if (!range) {
    Logger.log('No named range. Installing a named range');
    setNamedRange(section)
  } else {
    Logger.log('Named range found.');
    getNamedRange(section)
  }
}

// No namedRange found - Set new named range with name section.
function setNamedRange(section) { 
  goToLastLine();
  // Append a section header
  var s = body.appendParagraph(section);
  s.setHeading(DocumentApp.ParagraphHeading.HEADING4);
  // Append paragraph to section
  var insert = body.appendParagraph('');
  var rangeBuilder = doc.newRange();
  rangeBuilder.addElement(insert);
  var savedInsert = rangeBuilder.build()
  var namedRange = doc.addNamedRange(section, savedInsert);
  var namedRangeId = namedRange.getId();
  // select the namedRange
  doc.setSelection(doc.getNamedRangeById(namedRangeId).getRange());
  var newRange = true;
  changeTextByNamedRange(section, newRange)
}

// Existing namedRange found.
function getNamedRange(section) {
  Logger.log('getNamedRange() started')
  var newRange = false;
  changeTextByNamedRange(section, newRange)
}

// Update named range.
function changeTextByNamedRange(section, newRange) {
  docUi.alert('section:'   section);
  var range = doc.getNamedRanges().find(r => r.getName() == section);
  // test
  var updateText = "updated text, new range? "   newRange;
  //
  range.getRange().getRangeElements().forEach(e => e.getElement().asText().appendText(updateText));
}

function goToLastLine(){
  const kids = body.getNumChildren()
  const lastKid = body.getChild(kids - 1)
  let last = 0
  try {
    const lastPar = body.getChild(kids - 1).asParagraph()
    last = doc.newPosition(lastPar.getChild(0), lastPar.getText().length)
  } catch (e) {
    last = doc.newPosition(body.getChild(kids - 1), 0)    
  } finally {
    doc.setCursor(last)
  }
}

CodePudding user response:

I have a workaround working and feel free to modify if it still is within your goal.

I modified setNamedRange and changeTextByNamedRange functions. Here are their modifications:

setNamedRange:

function setNamedRange(section) { 
  // Append a section header
  goToLastLine();
  var s = body.appendParagraph(section);
  s.setHeading(DocumentApp.ParagraphHeading.HEADING4);

  // Append paragraph to section 
  // for some reason, it fails to include the 1st paragraph when it is blank
  // you can add a space, or any character just to include the 1st one properly
  var insert = body.appendParagraph("\t");
  var rangeBuilder = doc.newRange();
  rangeBuilder.addElement(insert);
  var savedInsert = rangeBuilder.build();
  var namedRange = doc.addNamedRange(section, savedInsert);
  var namedRangeId = namedRange.getId();
  // select the namedRange
  doc.setSelection(doc.getNamedRangeById(namedRangeId).getRange());
  changeTextByNamedRange(section);
}

changeTextByNamedRange:

function changeTextByNamedRange(section) {
  // docUi.alert('section:'   section);
  var range = doc.getNamedRanges().find(r => r.getName() == section);
  // get list of section names
  var sectionNames = doc.getNamedRanges().map(r => r.getName());
  var updateText = "Newer Text is appended for this section "   section   ". ";
  
  // this section contains the succeeding sections as well
  // so you have to end the loop when you encounter another section
  // use some instead of forEach to be able to break the loop.
  range.getRange().getRangeElements().some(e => {
    var element = e.getElement();
    // do anything you want. Note that this will loop to each element of that range.
    // if section has multiple elements, it will append to each element.
    // since we are only appending text to a single paragraph element, this currently works
    element.asText().appendText(updateText)
    // end loop when you encounter a text that is one of the section names
    return !sectionNames.includes(element.asText())
  });
}

Output:

  • After multiple runs on different sections, modifying the text to be appended, added some manual text then running manageSection again. This is the result.

output

  • Related