google-sheetsgoogle-apps-scriptdynamicgoogle-forms

Go to the Next section in Google Forms after an option is selected using App Script


I have a google form, the inputs to the questions are based on a google sheet. The googlesheet has two sheets "Categories" and "Projects"

Categories sheet:

Category    Options
Salary        Mike
Salary        John
Travel        Flight
Manintanence Water Supply
Manintanence Drain cleaning

Projects:
Proj1
Proj2
Proj3

the first question in the form is "select category" . Based on the category selected the next question displays a list of corresponding "Options" For example: if salary is selceted the next question shows a choice between Mike and John

The subsequent question should be "Select Projects" (which displays the list of projects from the projects column).

If Maintenance is selected it shows water supply and Drain cleaning And then moves to the projects question.

Problem: If Travel is chosen it shows Flight as an option once selected, it again shows "water supply" and "Drain Cleaning" instead of jumping to the Projects question

I have the below code: It works fine if i select the last Category. But if i select the first or second category all the subsequent Category options are displayed one after another before it jumps to the "projectDetailsSection"


const FORM_URL = "https://docs.google.com/forms/d/xxxxxxxxxxxx/edit"
let form=FormApp.openByUrl(FORM_URL)

function resetForm() {
  let items=form.getItems()
  items.forEach(item=>form.deleteItem(item))
}
function createConditionalForm(){
  resetForm();
  
  let ws = SpreadsheetApp.getActiveSpreadsheet();

  let projectsSheet = ws.getSheetByName("Projects");
  let projectsData = projectsSheet.getDataRange().getValues();
  
  let categoriesSheet = ws.getSheetByName("Categories");
  let categoriesData = categoriesSheet.getDataRange().getValues();
  categoriesData.shift(); 

  let categoryQuestion = form.addMultipleChoiceItem().setTitle("Category").setRequired(true);
  let categoryOptions = [];
  
  let categoryToSubcategories = new Map();
  categoriesData.forEach(row => {
    let category = row[0];
    let subcategory = row[1];
    if (!categoryToSubcategories.has(category)) {
      categoryToSubcategories.set(category, []);
    }
    categoryToSubcategories.get(category).push(subcategory);
  });

  let firstSubcategorySection = null;

  categoryToSubcategories.forEach((subcategories, category, index) => {
    let section = form.addPageBreakItem().setTitle(category + " - Select a Subcategory");
    if (index === 0) firstSubcategorySection = section; // Save the first subcategory section for navigation
    let subcatQuestion = form.addMultipleChoiceItem().setTitle("Subcategory").setRequired(true).setChoiceValues(subcategories);

    let catChoice = categoryQuestion.createChoice(category, section);
    categoryOptions.push(catChoice);

  });

  categoryQuestion.setChoices(categoryOptions);


  if (firstSubcategorySection) {
    categoryQuestion.setGoToPageBreakItem(firstSubcategorySection)
  }

  let projectDetailsSection = form.addPageBreakItem().setTitle("Project Details");
  let projectsQuestion = form.addListItem().setTitle("Project Name").setRequired(true).setChoiceValues(projectsData.map(row => row[0]));
  let amountQuestion = form.addTextItem().setTitle("Amount").setRequired(true);
}

Solution

  • RECOMMENDED SOLUTION

    In connection with my comments above,

    Based on what I've understood, after the users select a sub-category, you'd like them to be directed to the last part of the generated questionnaire, which will be Project Details.

    To do that, you'll need to use setGotoPage(FormApp.PageNavigationType.GO_TO_PAGE) on let section = form.addPageBreakItem().setTitle(category + " - Select a Subcategory"); since that's when the sections are being generated and it would look like something like this:

    let section = form.addPageBreakItem().setGoToPage(FormApp.PageNavigationType.GO_TO_PAGE5).setTitle(category + " - Select a Subcategory");
    

    However, this logic would not work since PAGE5 or the Project Details question has not been created yet, which would result in an error with the code.

    Instead, what I would recommend is to change how the question is generated, and you may use this code:

    const FORM_URL = "https://docs.google.com/forms/d/xxxxxxxxxxxx/edit"
    let form = FormApp.openByUrl(FORM_URL)
    
    function resetForm() {
      let items = form.getItems()
      items.forEach(item => form.deleteItem(item))
    }
    function createConditionalForm() {
      resetForm();
    
      let ws = SpreadsheetApp.getActiveSpreadsheet();
      let projectsSheet = ws.getSheetByName("Projects");
      let projectsData = projectsSheet.getDataRange().getValues();
      let categoriesSheet = ws.getSheetByName("Categories");
      let categoriesData = categoriesSheet.getDataRange().getValues();
      categoriesData.shift();
    
      form.addListItem().setTitle("Project Name").setRequired(true).setChoiceValues(projectsData.map(row => row[0]));
      form.addTextItem().setTitle("Amount").setRequired(true);
    
      let categoryQuestion = form.addMultipleChoiceItem().setTitle("Category").setRequired(true);
      let categoryOptions = [];
    
      let categoryToSubcategories = new Map();
      categoriesData.forEach(row => {
        let category = row[0];
        let subcategory = row[1];
        if (!categoryToSubcategories.has(category)) {
          categoryToSubcategories.set(category, []);
        }
        categoryToSubcategories.get(category).push(subcategory);
      });
    
      categoryToSubcategories.forEach((subcategories, category, index) => {
        let section = form.addPageBreakItem().setGoToPage(FormApp.PageNavigationType.SUBMIT).setTitle(category + " - Select a Subcategory");
        if (index === 0) firstSubcategorySection = section;
        form.addMultipleChoiceItem().setTitle("Subcategory").setRequired(true).setChoiceValues(subcategories);
    
        let catChoice = categoryQuestion.createChoice(category, section);
        categoryOptions.push(catChoice);
    
      });
      categoryQuestion.setChoices(categoryOptions);
    }
    

    This changes the logic of how your question is created.

    From:

    enter image description here

    enter image description here

    enter image description here

    enter image description here

    enter image description here

    To:

    enter image description here

    enter image description here

    enter image description here

    enter image description here

    This resolved the sub-category issue, and Project Details is going to be asked together with Category.