0

we have currently a large number of exercises (for math) that need to be categorized according to an existing table of contents. Each exercise has a unique number. This number should be placed into the table of contents. The depth of the toc is 3, so we have chapters, sections and subsections.

I want three drop down lists for each of the (many) exercises. The first one selects the chapter, the second the section, and the third the subsection. I can solve this with two filtered lists that depend on certain filtering of a list seperated into chapter, section, subsection. That works fine for few exercises. But, i have to make the filtered lists for each exercise seperately. That is exactly the problem. I do not want to maintain 500 lists (two per exercise)

Is there any way to hardcode this? I do not want to scroll through the many subsections each time and I need a error control. So, one should not be able to select chapter 3 and then subsection 3 from chapter 4.

EDIT: Link to Google Sheet: https://docs.google.com/spreadsheets/d/e/2PACX-1vSsRqFlLIkpgIrw18GBDLdUEl0FFmF5hSXIe2oAXztz9N50VNiO0eCP3cAB20KOgHU4nfH6gBFCWmyT/pubhtml

  • Whenever possible, you need to include a [minimal example](https://stackoverflow.com/help/minimal-reproducible-example) that reproduces the issue. You can also include the expected behavior, the actual behavior, and how they differ, that would be helpful as well. Please visit [How to ask](https://stackoverflow.com/help/how-to-ask) to have some tips on how to write a question, so the community will be able to help you out in a better way. – David Salomon Feb 10 '22 at 16:22
  • You can make a copy of your sheet and [share it with anyone with the link](https://support.google.com/drive/answer/2494822#share_publicly) and update your question with the link – David Salomon Feb 10 '22 at 16:24
  • Just updated with a minimal example how I solved this. Looking for general approach. – Peter Strouvelle Feb 10 '22 at 16:29

1 Answers1

0

1. Separate the data and the dropdows

That's a best practice, because you will need to have some auxiliary cells to create the dependency

2. Create a simple data validation dropdown

Do it for the first column in a separate sheet

3. Create the auxiliary cells

Filter the second column with the values you have in the data validation to show the values adjacent to the first column

=FILTER(B2:B,A2:A=Dropdowns!$A$2)

enter image description here

4. Repeat the process with as many columns you have

enter image description here

Here is the sample spreadsheet for you to have an idea how to implement it https://docs.google.com/spreadsheets/d/1VPsx1hfKuZDifMgrREOvUb4xEIvbVODnKPuRDWZUOF8/edit?usp=sharing

Update

I'm working on a script, I created two functions, at the moment they're not achieving the step you want, but I'm thinking on looping the number of columns as the same way I'm doing it with the rows.

const menuSheet = 'Values';
const dataSheet = 'Data';
const wsValues = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(menuSheet);
const wsData = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(dataSheet);
const data = wsData.getRange(2, 1, wsData.getLastRow() - 1, 3).getValues();
let firstCol = 1;
let secondCol = 2;
let thirdCol = 3;

/*
function setDropdownDependenciesTest() {
  const list = ['a', 'b']
  const cell = wsValues.getRange('C2')

  setDropdownDependencies(list, cell)

}
*/

function onEdit(e) {
  const activeCell = e.range
  let val = activeCell.getValue()
  let row = activeCell.getRow()
  let column = activeCell.getColumn()
  let wsName = activeCell.getSheet().getName()
  if (wsName === menuSheet && column === firstCol && row > 1) {
    applyFirstValidation(val, row)
  } else if (wsName == menuSheet && column === secondCol && row > 1) {
    applySecondValidation(val, row)
  }
}

function applyFirstValidation(val, row) {
  if (val === "") {
    wsValues.getRange(row, secondCol).clearContent()
    wsValues.getRange(row, secondCol).clearDataValidations()
    wsValues.getRange(row, thirdCol).clearContent()
    wsValues.getRange(row, thirdCol).clearDataValidations()
  } else {
    wsValues.getRange(row, secondCol).clearContent()
    wsValues.getRange(row, secondCol).clearDataValidations()
    wsValues.getRange(row, thirdCol).clearContent()
    wsValues.getRange(row, thirdCol).clearDataValidations()
    let filteredData = data.filter(info => {
      return info[0] === val;
    })

    let listToApply = filteredData.map(info => {
      return info[1]
    })

    let cell = wsValues.getRange(row, secondCol)
    setDropdownDependencies(listToApply, cell)
  }
}

function applySecondValidation(val, row) {
  if (val === "") {
    wsValues.getRange(row, thirdCol).clearContent()
    wsValues.getRange(row, thirdCol).clearDataValidations()
  } else {
    wsValues.getRange(row, thirdCol).clearContent()
    let firstColValue = wsValues.getRange(row, firstCol).getValue()
    let filteredData = data.filter(info => {
      return info[0] === firstColValue && info[1] === val;
    })

    let listToApply = filteredData.map(info => {
      return info[2]
    })

    let cell = wsValues.getRange(row, thirdCol)
    setDropdownDependencies(listToApply, cell)
  }
}

function setDropdownDependencies(list, cell) {

  const rule = SpreadsheetApp
    .newDataValidation()
    .requireValueInList(list)
    .setAllowInvalid(false)
    .build()

  cell.setDataValidation(rule)
}
David Salomon
  • 804
  • 1
  • 7
  • 24
  • Hi David, thanks for your answer. But what is the difference to my solution? I only see that you seperated the data into a second sheet (which i have done for the original project). But it does not answer the core question: How can i have multiple rows of drop down menus (filling A3-C3 for example and 300 more) without making filtered lists for each row? – Peter Strouvelle Feb 10 '22 at 18:42
  • sorry, but I can't edit your sheet and see the formulas, didn't know if you found a solution or if it was just text – David Salomon Feb 10 '22 at 18:49
  • I was looking for a solution (because in the way you want it, you need to do it programmatically in Apps Script) so I found this thread https://stackoverflow.com/a/35456798/17311782 there's a script you can copy and paste and it generates data validation rows dynamically... it's long but it works... while I test and try other solution in Apps Script – David Salomon Feb 10 '22 at 19:34
  • @PeterKeller I'm working on a script to achieve what you need, but I need to go, it seems that what I'm missing is looping over the columns to update the data dynamically. If you don't have coding knowledge, let me know and I'll continue working on that – David Salomon Feb 10 '22 at 21:43
  • Thank you David. I will have a look. I have some programming knowledge, but not in this script version. Let's see how this goes. – Peter Strouvelle Feb 11 '22 at 09:08