Utility.Copy Scenario.Simple
The below code is used to copy data from a Scenario to a Scenario within a Cube.
TIP
By changing cube.slice to cube.sliceStatic, formula values will be ignored, and only cells with a static value will be sliced.
Process Code
vb
/**
* MODLR PROCESS SCRIPT: Copy Cube Data Between Scenarios
* -------------------------------------------------------
* Purpose:
* Copies every value in a cube from one Scenario element ("from") to
* another Scenario element ("to"), leaving every other dimension
* untouched. Optionally wipes the destination scenario slice first so
* the copy is a clean replace rather than a merge on top of old data.
*
*/
var scenarioDimensionName = "Scenario"; // name of the dimension holding scenario elements in the target cube
/**
* pre()
* Runs once before the process executes. Registers the prompts MODLR
* asks for at run time.
*/
function pre() {
script.log('process pre-execution parameters parsed.');
// Answers become the globals cube_name / scenario_from / scenario_to /
// should_wipe, available in begin()/data()/end().
script.prompt("Cube Name", "cube_name", "");
script.prompt("Scenario From", "scenario_from", "");
script.prompt("Scenario To", "scenario_to", "");
script.prompt("Wipe Destination", "should_wipe", "1"); // "1" = wipe destination scenario first, anything else = don't
};
/**
* begin()
* Runs once at the start of the process:
* 1. Validate the cube, the Scenario dimension, and both scenario
* elements exist.
* 2. Optionally wipe the destination scenario slice.
* 3. Slice the cube at the source scenario and copy every value
* across to the same coordinates under the destination scenario.
*/
function begin() {
script.log('process execution started.');
// No source scenario supplied — nothing to copy, exit quietly.
if (scenario_from == "") {
return
}
// Abort if the cube doesn't exist.
if (!cube.exists(cube_name)) {
script.abort("The specified cube is not found: " + cube_name);
return;
}
// Find the Scenario dimension's position in the cube's dimension list
// (its index is used later to know which slot in each element array
// corresponds to the scenario).
var scenarioPosition = -1;
var dims = JSON.parse(cube.dimensions(cube_name));
for (var i = 0; i < dims.length; i++) {
var dim = dims[i];
if (dimension.getName(dim.id) == scenarioDimensionName) {
scenarioPosition = i;
break;
}
}
// Abort if the cube has no Scenario dimension.
if (scenarioPosition == -1) {
script.abort("Could not find the Scenario dimension within the target cube.");
return;
}
// Abort if the source scenario element doesn't exist in that dimension.
var scenarioDim = dims[scenarioPosition];
if (!element.exists(scenarioDim.name, scenario_from)) {
script.abort("Could not find the Scenario from.");
return
}
// Abort if the destination scenario element doesn't exist in that dimension.
var scenarioDim = dims[scenarioPosition];
if (element.exists(scenarioDim.name, scenario_to) == false) {
console.log("Could not find the Scenario: " + scenario_from + " within the scenario dimension: " + scenarioDim.name + `. Adding this ${scenarioDimensionName} to the Default hierarchy`);
hierarchy.group(scenarioDimensionName, "Default", "", scenario_to)
}
// the whole destination-scenario slice is generated.
var elements = [];
for (var i = 0; i < dims.length; i++) {
if (i == scenarioPosition) {
elements.push(scenario_to); // wipe the destination scenario slice
} else {
elements.push("");
}
}
// Optionally wipe the destination scenario slice before copying, so
if (should_wipe == "1") {
cube.wipe(cube_name, elements);
}
// Reuse the same elements array as the slice filter, now pointed at
// the source scenario, with every other dimension unfiltered ("") so
// cube.slice() returns every cell under scenario_from.
elements[scenarioPosition] = scenario_from;
// Turn off cube logging for the duration of the copy — logging every
// individual cube.set() call below would be noisy and unnecessary.
cube.log(cube_name, false);
// Slice the cube at the source scenario (every other dimension = all members).
console.log("Slicing", cube_name, elements)
var slice = cube.slice(cube_name, elements);
for (var elms of slice) {
// Build the destination coordinate set: identical to the source
// element combination, except the scenario slot is swapped for
// scenario_to.
var elmsSet = [];
for (var i = 0; i < elms.length - 1; i++) {
if (i == scenarioPosition) { // swap in the destination scenario
elmsSet.push(scenario_to);
} else {
elmsSet.push(elms[i]); // same element as the source slice
}
}
// The last item in each slice row is the cell's value.
var value = elms[elms.length - 1];
if (value) { // skip empty/null cells - nothing to copy
// Write the source value into the destination scenario coordinates.
cube.set(value, cube_name, elmsSet);
}
}
// Turn cube logging back on now the bulk copy is done.
cube.log(cube_name, true);
}
/**
* data(record)
* Runs once per record on a second pass. Not used by this script —
* the copy is done entirely in begin() in a single pass.
*/
function data(record) {
}
/**
* end()
* Runs once at the end of the process.
*/
function end() {
script.log('process execution finished.');
}