All skills
secondsky avatar

/sap-sac-scripting

@620a19a
by Eddiesecondsky/sap-skills456 stars
120

Comprehensive SAC scripting skill for SAP Analytics Cloud Analytics Designer and Optimized Story Experience. This skill should be used when the user asks to "create SAC script", "debug Analytics Designer", "optimize SAC performance", "planning operations in SAC", "filter data in SAC", "use DataSource API", "chart scripting", "table manipulation", "SAC event handlers", "version management", "data locking", "Optimized Story Experience API", "OSE scripting", "OSE widget API", "OSE DataSource", "story scripting API", "OSE planning API", "OSE method", "optimized story", "SAC story scripting", "story script", "SAC scripting", "debug SAC runtime in Microsoft Edge via CDP", or works with SAC widgets, planning models, or analytics applications.

Use this Skill: https://skilld.dev/gh/secondsky/sap-skills/sap-sac-scripting

This session only. Nothing lands on disk.

referencesapi-planning.md

≈3k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Planning API Reference

Complete reference for planning operations in SAP Analytics Cloud scripting.

Source: Analytics Designer API Reference (current release)


Table of Contents

  1. Getting Planning Reference
  2. Version Management
  3. Data Operations
  4. Data Locking
  5. Data Actions
  6. Multi-Actions
  7. Planning Enumerations
  8. Complete Examples

Getting Planning Reference

Access Planning API via Table widget:

var planning = Table_1.getPlanning();

Note: Planning features require a planning-enabled model connected to the table.


Version Management

Public Versions

getPublicVersion(versionId)

Returns a public version object.

var budgetVersion = Table_1.getPlanning().getPublicVersion("Budget2024");
getPublicVersions()

Returns all public versions.

var allPublicVersions = Table_1.getPlanning().getPublicVersions();

Private Versions

getPrivateVersion(versionId)

Returns a private version object.

var draftVersion = Table_1.getPlanning().getPrivateVersion("myDraft");
getPrivateVersions()

Returns all private versions.

var allPrivateVersions = Table_1.getPlanning().getPrivateVersions();
createPrivateVersion(versionId, options)

Creates a new private version.

var newDraft = Table_1.getPlanning()
    .createPrivateVersion("Draft_" + Date.now().toString());

Version Object Methods

isDirty()

Checks if version has unsaved changes.

var version = Table_1.getPlanning().getPublicVersion("Budget2024");
if (version.isDirty()) {
    console.log("Version has unsaved changes");
}
publish()

Publishes changes to the version.

var version = Table_1.getPlanning().getPublicVersion("Budget2024");
if (version) {
    if (version.isDirty()) {
        version.publish();
    }
}
copy(targetVersionId, copyOption, category?)

Copies version to a new version.

Parameters:

Parameter Type Required Description
targetVersionId string Yes Name for new version
copyOption PlanningCopyOption Yes What to copy
category PlanningCategory No Version category
// Copy public version to new private version
var budgetVersion = Table_1.getPlanning().getPublicVersion("Budget2024");
if (budgetVersion) {
    budgetVersion.copy(
        "Budget_Copy_" + Date.now().toString(),
        PlanningCopyOption.PlanningArea
    );
}

// Copy with category
var sourceVersion = Table_1.getPlanning().getPrivateVersion("Source");
if (sourceVersion) {
    sourceVersion.copy(
        "TargetVersion",
        PlanningCopyOption.AllData,
        PlanningCategory.Budget
    );
}

// Copy as Forecast
var forecastSource = Table_1.getPlanning().getPrivateVersion("ForecastDraft");
if (forecastSource) {
    forecastSource.copy(
        "Forecast_" + Date.now().toString(),
        PlanningCopyOption.PlanningArea,
        PlanningCategory.Forecast
    );
}
revert()

Reverts unsaved changes in the version.

var version = Table_1.getPlanning().getPublicVersion("Budget2024");
version.revert();
delete()

Deletes a private version.

var draft = Table_1.getPlanning().getPrivateVersion("OldDraft");
if (draft) {
    draft.delete();
}

Data Operations

submitData()

Submits pending data changes.

Table_1.getPlanning().submitData();

getPlanningArea()

Returns planning area configuration.

var planningArea = Table_1.getPlanning().getPlanningArea();

Data Locking

getDataLocking()

Returns data locking interface.

var dataLocking = Table_1.getPlanning().getDataLocking();

getState(selection)

Returns lock state for a selection.

var selection = Table_1.getSelections()[0];
var lockState = Table_1.getPlanning().getDataLocking().getState(selection);

Lock States:

  • Locked - Data is locked by another user
  • Unlocked - Data is available for editing
  • LockedByMe - Data is locked by current user

Example: Check Before Edit

var selection = Table_1.getSelections()[0];
var lockState = Table_1.getPlanning().getDataLocking().getState(selection);

if (lockState === DataLockingState.Locked) {
    Application.showMessage(
        ApplicationMessageType.Warning,
        "Data is locked by another user"
    );
} else {
    // Proceed with edit
    performEdit();
}

Data Actions

Execute predefined data actions.

Execute Data Action

// Simple execution
DataAction_1.execute();

// With parameters
DataAction_1.setParameterValue("YEAR", "2024");
DataAction_1.setParameterValue("VERSION", "Budget");
DataAction_1.execute();

Data Action Events

DataAction_1.onBeforeExecute = function() {
    Application.showBusyIndicator();
};

DataAction_1.onAfterExecute = function(result) {
    Application.hideBusyIndicator();
    if (result.success) {
        Application.showMessage(ApplicationMessageType.Info, "Data action completed");
    } else {
        Application.showMessage(ApplicationMessageType.Error, "Data action failed");
    }
};

Background Execution

// Execute in background
DataAction_1.executeInBackground();

// Monitor status
DataAction_1.onExecutionStatusUpdate = function(status) {
    console.log("Status:", status);
    if (status === ExecutionStatus.Completed) {
        Table_1.getDataSource().refreshData();
    }
};

Multi-Actions

Execute multiple data actions in sequence.

Execute Multi-Action

MultiAction_1.execute();

With Parameters

MultiAction_1.setParameterValue("YEAR", "2024");
MultiAction_1.setParameterValue("SCENARIO", "Actual");
MultiAction_1.execute();

Events

MultiAction_1.onBeforeExecute = function() {
    Application.showBusyIndicator();
};

MultiAction_1.onAfterExecute = function(result) {
    Application.hideBusyIndicator();
    Table_1.getDataSource().refreshData();
};

Planning Enumerations

PlanningCopyOption

PlanningCopyOption.AllData       // Copy all data
PlanningCopyOption.PlanningArea  // Copy planning area only

PlanningCategory

PlanningCategory.Budget          // Budget category
PlanningCategory.Forecast        // Forecast category
PlanningCategory.Actual          // Actual category
PlanningCategory.Plan            // Plan category

DataLockingState

DataLockingState.Locked          // Locked by another user
DataLockingState.Unlocked        // Available for editing
DataLockingState.LockedByMe      // Locked by current user

ExecutionStatus

ExecutionStatus.Running          // In progress
ExecutionStatus.Completed        // Successfully completed
ExecutionStatus.Failed           // Execution failed
ExecutionStatus.Cancelled        // Cancelled by user

Complete Examples

Example 1: Version Publishing Workflow

// Button: Publish Budget
Button_Publish.onClick = function() {
    Application.showBusyIndicator();

    try {
        var budgetVersion = Table_1.getPlanning().getPublicVersion("Budget2024");

        if (!budgetVersion) {
            Application.showMessage(
                ApplicationMessageType.Error,
                "Budget version not found"
            );
            return;
        }

        if (!budgetVersion.isDirty()) {
            Application.showMessage(
                ApplicationMessageType.Info,
                "No changes to publish"
            );
            return;
        }

        budgetVersion.publish();
        Application.showMessage(
            ApplicationMessageType.Success,
            "Budget published successfully"
        );

    } catch (error) {
        console.log("Error:", error);
        Application.showMessage(
            ApplicationMessageType.Error,
            "Failed to publish budget"
        );
    } finally {
        Application.hideBusyIndicator();
    }
};

Example 2: Create Working Copy

// Button: Create Working Copy
Button_CreateCopy.onClick = function() {
    var sourceVersion = Table_1.getPlanning().getPublicVersion("Budget2024");

    if (sourceVersion) {
        var timestamp = Date.now().toString();
        var copyName = "WorkingCopy_" + timestamp;

        sourceVersion.copy(copyName, PlanningCopyOption.AllData);

        Application.showMessage(
            ApplicationMessageType.Info,
            "Created working copy: " + copyName
        );
    }
};

Example 3: Data Action with Confirmation

// Button: Run Allocation
Button_RunAllocation.onClick = function() {
    Popup_Confirm.open();
};

// Confirm button in popup
Button_ConfirmYes.onClick = function() {
    Popup_Confirm.close();

    Application.showBusyIndicator();

    // Set parameters from dropdown selections
    DataAction_Allocation.setParameterValue(
        "SOURCE_VERSION",
        Dropdown_SourceVersion.getSelectedKey()
    );
    DataAction_Allocation.setParameterValue(
        "TARGET_VERSION",
        Dropdown_TargetVersion.getSelectedKey()
    );
    DataAction_Allocation.setParameterValue(
        "YEAR",
        Dropdown_Year.getSelectedKey()
    );

    DataAction_Allocation.execute();
};

DataAction_Allocation.onAfterExecute = function(result) {
    Application.hideBusyIndicator();

    if (result.success) {
        // Refresh data
        Table_1.getDataSource().refreshData();
        Application.showMessage(
            ApplicationMessageType.Success,
            "Allocation completed successfully"
        );
    } else {
        Application.showMessage(
            ApplicationMessageType.Error,
            "Allocation failed: " + result.message
        );
    }
};

Example 4: Find Active Planning Cycle

// Find active planning cycle from attribute
function findActivePlanningCycle() {
    var allCycles = PlanningModel_1.getMembers("PlanningCycle");
    var activeCycle = null;

    for (var i = 0; i < allCycles.length; i++) {
        if (allCycles[i].properties.IsActive === "X") {
            activeCycle = allCycles[i].id;
            break;
        }
    }

    return activeCycle;
}

// Use in initialization or filter setup
var activeCycle = findActivePlanningCycle();
if (activeCycle) {
    Table_1.getDataSource().setDimensionFilter(
        "PlanningCycle",
        activeCycle
    );
}

Example 5: Revert Changes

// Button: Discard Changes
Button_Revert.onClick = function() {
    var version = Table_1.getPlanning().getPublicVersion("Budget2024");

    if (version && version.isDirty()) {
        version.revert();
        Table_1.getDataSource().refreshData();
        Application.showMessage(
            ApplicationMessageType.Info,
            "Changes discarded"
        );
    } else {
        Application.showMessage(
            ApplicationMessageType.Info,
            "No changes to discard"
        );
    }
};

Best Practices

  1. Always check version exists before operations
  2. Use isDirty() before publish to avoid unnecessary saves
  3. Show busy indicator during long operations
  4. Handle errors with try-catch blocks
  5. Refresh data after successful operations
  6. Check lock state before editing shared data

Related Documentation

Official Reference: https://help.sap.com/doc/958d4c11261f42e992e8d01a4c0dde25/release/en-US/index.html

Source: SKILL.md on GitHub

1 alert16d5 checks · Risk SAFE
  • Gen Agent Trust Hub16d

    The skill is a comprehensive reference and template collection for SAP Analytics Cloud (SAC) scripting. It provides secure instructions for setting up an associated Model Context Protocol (MCP) server, including commit pinning and security flags during installation. It also incorporates multiple security best practices for developers, such as origin validation for iframe communication.

  • Socket16d

    1 alert: gptAnomaly

  • Snyk16d

    Risk: MEDIUM · 1 issue

  • Runlayer6mo

    32/61 files flagged

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at 620a19a. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 weeks ago.

Activeupdated 2 months ago
Other metadata
metadata
{
  "maintainer": "Eduard Jiglau",
  "maintainer_email": "hello@sap-ai-skills.com",
  "website": "https://sap-ai-skills.com",
  "version": "2.4.1",
  "last_verified": "2026-06-11",
  "sac_version": "Q2 2026 (2026.8)",
  "api_reference_version": "2025.20 (OSE Q2 2026)",
  "documentation_source": "https://help.sap.com/docs/SAP_ANALYTICS_CLOUD",
  "reference_files": 66,
  "template_patterns": 56,
  "agents": 4,
  "commands": 4,
  "status": "docs_audited_runtime_pending",
  "known_issues": [
    "Live SAC story/runtime checks require tenant evidence before claiming production validation."
  ]
}

README badge

README badge for secondsky/sap-skills/sap-sac-scripting