Filter - Change Filter on Selected Tables

From Q
Jump to navigation Jump to search

This QScript allows you to replace or remove a filter for all of the tables and charts that are currently selected. This allows for quick changes to the filters that are applied to the tables even when:

  1. The filter is applied to many tables in the project, but not all of them, and it would be time-consuming to check all of the tables in the project for the filter and change it manually.
  2. The tables in the project have many different filters applied, and the filter that you want to change is not in the same position on each table (and hence is not available to change when you select multiple tables).

Technical details

You should select the tables and charts that you want to modify before running this script. When the script runs:

  1. You will be shown a list of all of the different filters that have been selected on the tables or charts, and asked to select one to change.
  2. You will be shown a list of filters in the data and asked to select a replacement for the first filter. At this time you can also select No filter.

The filter will then be replaced wherever it appears it the selected tables or charts, or if No Filter was selected it will be removed from the selected tables and charts.

How to apply this QScript

  • Start typing the name of the QScript into the Search features and data box in the top right of the Q window.
  • Click on the QScript when it appears in the QScripts and Rules section of the search results.

OR

  • Select Automate > Browse Online Library.
  • Select this QScript from the list.

Customizing the QScript

This QScript is written in JavaScript and can be customized by copying and modifying the JavaScript.

Customizing QScripts in Q4.11 and more recent versions

  • Start typing the name of the QScript into the Search features and data box in the top right of the Q window.
  • Hover your mouse over the QScript when it appears in the QScripts and Rules section of the search results.
  • Press Edit a Copy (bottom-left corner of the preview).
  • Modify the JavaScript (see QScripts for more detail on this).
  • Either:
    • Run the QScript, by pressing the blue triangle button.
    • Save the QScript and run it at a later time, using Automate > Run QScript (Macro) from File.

Customizing QScripts in older versions

  • Copy the JavaScript shown on this page.
  • Create a new text file, giving it a file extension of .QScript. See here for more information about how to do this.
  • Modify the JavaScript (see QScripts for more detail on this).
  • Run the file using Automate > Run QScript (Macro) from File.

JavaScript

// Swap filters on selected tables
includeWeb("QScript Selection Functions");
includeWeb("QScript Functions to Generate Outputs");

if (!main())
    log("QScript cancelled.");
else
    conditionallyEmptyLog("QScript Finished.");


function main() {
    var selected_items = project.report.selectedItems();
    selected_items = selected_items.filter(function (item) { return ["Table", "Plot"].indexOf(item.type) > -1; });

    if (selected_items.length == 0) {
        log("No tables or plots selected.");
        return false;
    }

    // Go through the items and get the filters
    var all_selected_filters = [];
    selected_items.forEach(function (item) {
        all_selected_filters = all_selected_filters.concat(item.filters);
    });

    if (all_selected_filters.length == 0) {
        log("There are no filters on the selected tables and plots.");
        return false;
    }

    // Get the set of unique filters that have been applied on any of the selected tables
    var unique_filters = uniqueQObjects(all_selected_filters);
    // var unique_filters = unique_filters.map(function (v) { return v.question; });

    // Prompt the user to tell us which filter they want to change
    var target_filter = selectOneVariableByLabel("The selected tables contain the following filters. Select one to replace:", unique_filters, false);

    var data_file = target_filter.question.dataFile;
    var all_filters_in_file = data_file.variables.filter(function (v) { return v.question.isFilter; });

    // Choose a replacement. They can choose no filter (aka "Total Sample")
    var labels = ["No filter"].concat(all_filters_in_file.map(function (v) { return v.label; }));
    all_filters_in_file = [null].concat(all_filters_in_file);
    var selected_index = selectOne("Choose a replacement:", labels, null, 0);
    var new_filter = all_filters_in_file[selected_index];

    // Do the replacements
    selected_items.forEach(function (item) {
        replaceFilterOnTable(item, target_filter, new_filter);
    });

    return true;
}
    
// Given an array of Q objects (questions, variables, tables, etc) return
// an array with any duplicates removed.
function uniqueQObjects(array) {
    var uniques = [];
    array.forEach(function (obj) {
        function equalThis(x) {
            return obj.equals(x);
        }
        if (!uniques.some(equalThis))
            uniques.push(obj);
    });
    return uniques;
}

function replaceFilterOnTable(item, target_filter, new_filter) {
    var filters_on_item = item.filters;

    // Removing a filter.
    if (new_filter == null)
        filters_on_item = filters_on_item.filter(function (v) {
            return !v.equals(target_filter);
        })

    // Replacing a filter
    filters_on_item = filters_on_item.map(function (v) {
        if (v.equals(target_filter))
            return new_filter;
        else
            return v;
    });
    
    // Set the new filters
    item.filters = filters_on_item;
}

See also