Is it possible reset checklist in Documents?

709 views
Skip to first unread message

Alex

unread,
Jul 6, 2021, 11:16:15 PM7/6/21
to Google Apps Script Community
Hi!

How do you think is it possible reset it via code?
screenrecord.mp4.1625496655.gif

Best,
Alex.

Martin Hawksey

unread,
Jul 8, 2021, 5:21:55 PM7/8/21
to Google Apps Script Community
Not seeing a way with either DocumentApp or Doc API ... given this and other new features looks like the API is lagging. Might be worth logging a feature request https://issuetracker.google.com/issues?q=componentid:191640%2B&pli=1

Alex

unread,
Jul 9, 2021, 1:44:03 AM7/9/21
to Google Apps Script Community
After a little research I'm sure that is an API issue. There are no methods to manipulate lists which contain with specifics glyphs.

Clark Lind

unread,
Jul 9, 2021, 7:29:27 AM7/9/21
to Google Apps Script Community
Alex, I looked into this a bit also. They are returned as listItem and you can use listItem.clear(), but that only removes the text after the box. So I using Chrome Dev tools, I looked at the page, and the boxes (checkboxes) are actually SVGs.

You would have to find a way to manipulate/replace the SVG (checked box to unchecked box). So maybe look into how you can change the bulleted list styles (I think that is possible). In essence, I think they are treated similar to bulleted lists with different bullet styles. (maybe?)

Clark Lind

unread,
Jul 9, 2021, 8:37:05 AM7/9/21
to Google Apps Script Community
After playing around, this should get you started in the right direction. You will obviously have to get all the listItems and iterate through them all. I don't know how to check if something is "checked" or not, so this is just a simple hack.

function clearCheckbox() {
  var body = DocumentApp.getActiveDocument().getBody();
  
  var firstChild = body.getChild(0);    //get the first item
  var fcText = firstChild.asListItem().getText();  //get its text
  var template = body.getChild(6).copy();  //copy an existing blank checkbox item
  body.insertListItem(0, template);  //insert the new blank checkbox
  template.asListItem().setText(fcText);  //set the text of the new checkbox to the previous text
  body.getChild(1).removeFromParent()  //remove the lined-through item
}

before: checkbox-before.JPG After: checkbox-after.JPG

Alex

unread,
Jul 9, 2021, 10:28:12 AM7/9/21
to Google Apps Script Community
Hi Clark!

Thanks for the suggestion. I improved little.

We have to know the list id for this

/**
 * @param {globalThis.DocumentApp.Document} doc
 */
function getListIds_(doc) {
  return doc.getBody()
    .getListItems().reduce((a, c) => {
      const id = c.getListId();
      if (a.indexOf(id) === -1) a.push(id);
      return a;
    }, []);
}

/**
 * @param {globalThis.DocumentApp.Document} doc
 * @param {number} index
 */
function uncheckListById_(doc, id) {
  const body = doc.getBody();
  const lists = body.getListItems()
    .filter(l => l.getListId() === id);
  const last = lists.splice(-1)[0];
  lists.reverse().forEach(item => {
    const copy = last.copy();
    copy.asListItem().setText(item.asListItem().getText());
    body.insertListItem(0, copy);
    item.removeFromParent();
  });
}

function run() {
  uncheckListById_(DocumentApp.getActiveDocument(), 'kix.yy1s6bgaip7h');
}

function printListIds() {
  console.log(getListIds_(DocumentApp.getActiveDocument()));
}

screenrecord.mp4.1625840587.gif

The code doesn't support styles of paragraphs. But it works fine as a first approximation.

Best, Alex.

Clark Lind

unread,
Jul 9, 2021, 11:08:21 AM7/9/21
to google-apps-sc...@googlegroups.com
Awesome, great work as always!

Best,
Clark

--
You received this message because you are subscribed to a topic in the Google Groups "Google Apps Script Community" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/google-apps-script-community/Gl0hcbM0xM8/unsubscribe.
To unsubscribe from this group and all its topics, send an email to google-apps-script-c...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/google-apps-script-community/0183975c-8cb7-4ca6-a474-f39fa7f0e165n%40googlegroups.com.

Alex

unread,
Jul 9, 2021, 11:30:03 AM7/9/21
to Google Apps Script Community
I have to add an remark:
The best option for body.insertListItem(0, copy); is body.insertListItem(body.getChildIndex(item), copy);

Martin Hawksey

unread,
Jul 9, 2021, 11:40:58 AM7/9/21
to Google Apps Script Community
Nice work! Planning to write-up somewhere I can link to from pulse.appsscript.info :) If not I can just reference this thread

Alex

unread,
Jul 9, 2021, 12:20:43 PM7/9/21
to Google Apps Script Community
OK. I'm going to add this to snippets https://apps-script-snippets.contributor.pw/
Let me a day.

Rescue Squad

unread,
Aug 31, 2023, 10:10:23 AM8/31/23
to Google Apps Script Community
Thanks so much for your help with this.  I ended up needing to make modifications so that it would work with multiple lists. I'm using it for a multiple choice self test and I needed an easy way to clear my answers.

/**
 * A special function that runs when the document is opened.
 * Adds a custom menu to the Google Document.
 */
function onOpen() {
  const ui = DocumentApp.getUi();
 
  // Create a custom menu
  ui.createMenu('Custom Script Menu')
      .addItem('Reset the Test', 'run')  // The function to run when this menu item is clicked is 'run'
      .addSeparator()
     
      .addToUi();  // Add the menu to the UI
}


/**
 * @param {globalThis.DocumentApp.Document} doc
 */
function getListIds_(doc) {
  return doc.getBody()
    .getListItems().reduce((a, c) => {
      const id = c.getListId();
      if (a.indexOf(id) === -1) a.push(id);
      return a;
    }, []);
}

/**
 * @param {globalThis.DocumentApp.Document} doc
 * @param {number} index
 */
function uncheckListById_(doc, id) {
  const body = doc.getBody();
  const lists = body.getListItems()
    .filter(l => l.getListId() === id);
  const last = lists.splice(-1)[0];
 
  lists.reverse().forEach(item => {
    const position = body.getChildIndex(item);
    const copy = last.copy();
    copy.asListItem().setText(item.asListItem().getText());
    body.insertListItem(position, copy);  // Insert the copy at the original item's position
    item.removeFromParent();  // Remove the original item
  });
}


function run() {
  const doc = DocumentApp.getActiveDocument();
  const listIds = getListIds_(doc);
 
  listIds.forEach(id => {
    uncheckListById_(doc, id);
  });
}

function printListIds() {
  console.log(getListIds_(DocumentApp.getActiveDocument()));
}
Reply all
Reply to author
Forward
0 new messages