This article describes how to go from a table with NETs...
...to a table that sorts and indents within each NET:
Requirements
- A Pick One, Pick Any, or Pick Any - Compact table with created NETs that don't overlap between categories
Method
1. Select your table.
2. Go to Automate > Custom Rule.
3. Paste the below into the dialog:
includeWeb("JavaScript Array Functions");
form.setHeading("Group rows according to NETs");
form.setSummary("Group rows according to NETs");
var blue_question = table.blueQuestion;
var data_reduction = blue_question.dataReduction;
var use_codes;
if (["Pick One", "Pick Any - Compact"].indexOf(blue_question.questionType) > -1)
use_codes = true;
else if (["Pick Any"].indexOf(blue_question.questionType) > -1)
use_codes = false;
else
form.ruleNotApplicable("the question selected in the Brown drop-down is not Pick Any, Pick One, or Pick Any Compact");
if (arrayHasDuplicateElements(table.rowLabels))
form.ruleNotApplicable("there are duplicate row labels in the table")
var indent_label = " - ";
// Row weights are used to keep children in the correct order.
var row_weights = {};
// Find underlying row sources
var row_values = table.rowLabels
.filter(function (label) {
return label !== 'NET';
})
.map(function (label, i) {
row_weights[label] = i;
return {
label: label,
sources: use_codes
? data_reduction.getUnderlyingValues(label)
: data_reduction.getUnderlyingVariables(label).map(function (v) {
return v.name;
})
}
});
// Create a map of the rows that are sourced from a single variable
var individual_values_map = {};
row_values
.filter(function (value) {
return value.sources.length === 1;
})
.forEach(function (value) {
individual_values_map[value.sources[0]] = {label: value.label, source: value.sources[0]}
});
// Populate the rows with multiple sources with their visible individual row data
var net_values = row_values
.filter(function (value) {
return value.sources.length > 1;
})
.map(function (value) {
var new_value = {
label: value.label,
sources: value.sources,
children: value.sources
.map(function (source) {
return individual_values_map[source];
})
.filter(function (source) {
return typeof source !== 'undefined'
})
};
new_value.children.sort(function (a, b) {
return row_weights[b.label] - row_weights[a.label];
});
return new_value;
});
// Create an array to store the labels that have been updated.
var changed_row_labels_map = {};
for (var i = 0; i < net_values.length; i++) {
var value = net_values[i];
value.children.forEach(function (child) {
table.moveRowAfter(table.rowIndex(child.label), table.rowIndex(value.label));
changed_row_labels_map[child.label] = indent_label + child.label;
});
}
table.rowLabels = table.rowLabels.map(function (label) {
return typeof changed_row_labels_map[label] !== 'undefined' ? changed_row_labels_map[label] : label;
});
- This code first checks that the underlying variable in the table is of the correct data type.
- It then loops through the underlying categories for each NET and places them directly below the relevant NET with an indent character prefixed to the label.
4. OPTIONAL: Change indent_label to include a different indent character for the categories within each NET.
5. Press the Play button > Close > OK.
6. To now sort your table from highest to lowest, for example, you will need to apply a sorting rule via Automate > Browse Online Library > Sort/Reorder Rows or Columns > Sort Rows (Automatically Updates When Data Changes). See How to Automatically Sort Table Rows for further details.