diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..7e50d89 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,10 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + labels: + - "dependencies" + commit-message: + prefix: "ci" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..a18c111 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,109 @@ +name: Release + +on: + pull_request: + types: [closed] + branches: [main] + +jobs: + release: + # Only run if PR was merged (not just closed) and has a release label + if: | + github.event.pull_request.merged == true && + (contains(github.event.pull_request.labels.*.name, 'release:major') || + contains(github.event.pull_request.labels.*.name, 'release:minor') || + contains(github.event.pull_request.labels.*.name, 'release:patch')) + + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Fetch all history for tags + + - name: Get latest tag + id: get_tag + run: | + # Get the latest semver tag (handles v prefix) + LATEST_TAG=$(git tag --sort=-v:refname | grep -E '^v?[0-9]+\.[0-9]+\.[0-9]+$' | head -1) + + if [ -z "$LATEST_TAG" ]; then + echo "No existing tags found, starting from v0.0.0" + LATEST_TAG="v0.0.0" + fi + + echo "latest_tag=$LATEST_TAG" >> $GITHUB_OUTPUT + echo "Latest tag: $LATEST_TAG" + + - name: Determine version bump type + id: bump_type + run: | + if ${{ contains(github.event.pull_request.labels.*.name, 'release:major') }}; then + echo "type=major" >> $GITHUB_OUTPUT + elif ${{ contains(github.event.pull_request.labels.*.name, 'release:minor') }}; then + echo "type=minor" >> $GITHUB_OUTPUT + elif ${{ contains(github.event.pull_request.labels.*.name, 'release:patch') }}; then + echo "type=patch" >> $GITHUB_OUTPUT + fi + + - name: Calculate new version + id: new_version + run: | + LATEST_TAG="${{ steps.get_tag.outputs.latest_tag }}" + BUMP_TYPE="${{ steps.bump_type.outputs.type }}" + + # Remove 'v' prefix if present + VERSION=${LATEST_TAG#v} + + # Split version into parts + IFS='.' read -r MAJOR MINOR PATCH <<< "$VERSION" + + # Bump version based on type + case $BUMP_TYPE in + major) + MAJOR=$((MAJOR + 1)) + MINOR=0 + PATCH=0 + ;; + minor) + MINOR=$((MINOR + 1)) + PATCH=0 + ;; + patch) + PATCH=$((PATCH + 1)) + ;; + esac + + NEW_VERSION="v${MAJOR}.${MINOR}.${PATCH}" + echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT + echo "New version: $NEW_VERSION (bump type: $BUMP_TYPE)" + + - name: Create and push tag + run: | + NEW_VERSION="${{ steps.new_version.outputs.new_version }}" + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git tag -a "$NEW_VERSION" -m "Release $NEW_VERSION" + git push origin "$NEW_VERSION" + + - name: Create GitHub Release + uses: actions/github-script@v7 + with: + script: | + const newVersion = '${{ steps.new_version.outputs.new_version }}'; + const previousTag = '${{ steps.get_tag.outputs.latest_tag }}'; + + await github.rest.repos.createRelease({ + owner: context.repo.owner, + repo: context.repo.repo, + tag_name: newVersion, + name: `Release ${newVersion}`, + generate_release_notes: true, + draft: false, + prerelease: false + }); + + console.log(`Created release ${newVersion}`); diff --git a/README.md b/README.md index 69b5696..5b09e7c 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@
diff --git a/bedrock_processes_json/}bedrock.chore.execution.check.json b/bedrock_processes_json/}bedrock.chore.execution.check.json index 4f3838d..fc6310f 100644 --- a/bedrock_processes_json/}bedrock.chore.execution.check.json +++ b/bedrock_processes_json/}bedrock.chore.execution.check.json @@ -1,6 +1,6 @@ { "Name": "}bedrock.chore.execution.check", - "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.chore.execution.check', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pMonthDays', '', \r\n 'pWeekDays', '',\r\n 'pDelim', '&',\r\n 'pStartTime', 0, 'pEndTime', 24,\r\n 'pScheduleTimezone','en-AU',\r\n 'pServerTimezone','etc/UTC'\r\n );\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~## \r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This TI was created to overcome the limited scheduling options in chores. In order to use this TI it has to be the 1st TI in the chore.\r\n# As an example, if you need to run a chore every Monday & Wednesday you would schedule it to run EVERY day but set the pWeekdays parameter to Mon & Wed.\r\n# The chore would then kick off every day but this TI will perform a ProcessExitByChoreQuit function on all days NOT mentioned in pWeekdays.\r\n\r\n# Alternative setup: instead of adding this TI as the 1st TI in the chore, you could also use ExecuteProcess to call it, \r\n# from the top of the Prolog of your first TI process. This is definitely easier than hardcoding process call parameters in the chore dialog.\r\n\r\n# Timezones:\r\n# pScheduleTimezone parameter allow specifying the timezone to perform checks in if server timezone is different to schedule one. E.g. PA server is running in UTC and time or days of week are to be checked in AEST. Full list of timezones https://en.wikipedia.org/wiki/List_of_tz_database_time_zones\r\n# pServerTimezone allows to cater for situations when PA server is running in local time in yet another timezone, e.g. you want to check chore schedule in timezone Europe/Munich for server running in Asia/Singapore\r\n\r\n# Use case: For productive systems.\r\n# 1. A chore should run every 30 minutes between 8am & 8pm on weekdays. Schedule chore for every 30 minutes and include this process 1st in chore with parameters pWeekDays=MON&TUE&WED&THU&FRI pStartTime=8 pEndTime=20.\r\n# 2. A chore should run only on 1st calendar day of each month. Schedule chore for daily execution and include this process 1st in chore with parameters pMonthDays=1.\r\n\r\n# Note:\r\n# * This process will quit a chore if any time-bound, weekday-bound or date-bound conditions which define when the chore should NOT run are met.\r\n# * Only the parameter(s) needed should be specified.\r\n# * Only scheduled executions will be quit outside the parameters. The checks are bypassed if a chore is manually executed by a user. This is done by checking the TM1User function.\r\n# * Time conditions are checked using these parameters in the following order of priority.\r\n# 1. pMonthDays : Days in month when chore is allowed to run. Enter delimited list of days e.g. 1&2&30&31 (blank = no restriction on allowed days of month).\r\n# 2. pWeekDays : Days in week when chore is allowed to run Enter delimited list of weekdays e.g. MON&FRI (blank = no restriction on allowed weekdays).\r\n# 3. pStartTime & pEndTime : Time of day when chore is allowed to run e.g. pStartTime=7, pEndTime=22 execution will be allowed between 7AM & 10PM ( blank = no time-bound restrictions).\r\n#EndRegion @DOC\r\n\r\n### Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSub = cThisProcName |'_'| cTimeStamp |'_'| cRandomInt;\r\ncStartTime = NumberToString( pStartTime );\r\ncEndTime = NumberToString( pEndTime );\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent= 'User:%cUserName% Process:%cThisProcName% Message: %sMsg%';\r\ncLogInfo = 'User:%cUserName% Process:%cThisProcName% run to check if chore should run with parameters pMonthDays:%pMonthDays%, pWeekDays:%pWeekDays%, pDelim:%pDelim%, pStartTime:%cStartTime%, pEndTime:%cEndTime%, pScheduleTimezone: %pScheduleTimezone% pServerTimezone: %pServerTimezone%.' ; \r\nnErrors = 0;\r\nsMsg = '';\r\n\r\n## LogOutput parameters\r\nIF( pLogOutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nEndIf;\r\n\r\n### Check params\r\nIf( pDelim @= '' );\r\n pDelim = '&';\r\nElse;\r\n pDelim = SubSt( pDelim, 1, 1 );\r\nEndIf;\r\n\r\nIf( pMonthDays @= 'ALL' );\r\n pMonthDays = '';\r\nEndIf;\r\nIf( pMonthDays @<> '' );\r\n If( SubSt( pMonthDays, Long( pMonthDays ), 1 ) @<> pDelim );\r\n pMonthDays = pMonthDays | pDelim;\r\n EndIf;\r\nEndIf;\r\n\r\nIf( pWeekDays @= 'ALL' );\r\n pWeekDays = '';\r\nEndIf;\r\nIf( pWeekDays @<> '' );\r\n pWeekDays = Upper( pWeekDays );\r\n If( SubSt( pWeekDays, Long( pWeekDays ), 1 ) @<> pDelim );\r\n pWeekDays = pWeekDays | pDelim;\r\n EndIf;\r\nEndIf;\r\n\r\nIf( pStartTime <= 0 % pStartTime > 24 );\r\n pStartTime = 0;\r\nElse;\r\n pStartTime = Round(pStartTime);\r\nEndIf;\r\nsStartTime = NumberToString( pStartTime );\r\n\r\nIf( pEndTime <= 0 % pEndTime > 24 );\r\n pEndTime = 24;\r\nElse;\r\n pEndTime = Round(pEndTime);\r\nEndIf;\r\n\r\nIf( pEndTime < pStartTime );\r\n pEndTime = pStartTime;\r\nEndIf;\r\nsEndTime = NumberToString( pEndTime );\r\n\r\n### Initialize quit Boolean\r\nbQuit = 0;\r\n\r\n### Check the user\r\nIf( DIMIX( '}Clients', cUserName ) > 0 );\r\n If( pLogOutput >= 1 );\r\n sMsg = 'This chore will NOT quit since executed by a user.';\r\n LogOutput( 'INFO', Expand( cMsgErrorContent ) );\r\n EndIf;\r\nElse;\r\n if (pScheduleTimezone@<>'');\r\n #initate the date format for conversion\r\n pServerTimezone = if (pServerTimezone@='','etc/UTC',pServerTimezone);\r\n # need to convert to UTC first and then restate in required timezones\r\n nUTCDateFormatter = NewDateFormatter('', 'etc/UTC', 'serial', 'full', 'datetime');\r\n nScheduleDateFormatter = NewDateFormatter('', pScheduleTimezone, 'serial', 'full', 'datetime');\r\n nServerDateFormatter = NewDateFormatter('', pServerTimezone, 'serial', 'full', 'datetime');\r\n sDateFormat = 'yyyy-MM-dd HH:mm:ss';\r\n sUTCTimeStamp = FormatDate(Now, sDateFormat, nUTCDateFormatter);\r\n nServerParsedDate = ParseDate( sUTCTimeStamp, sDateFormat, nServerDateFormatter );\r\n endif;\r\n ### Check the day of the month\r\n If( pMonthDays @<> '' );\r\n if (pScheduleTimezone @= '');\r\n sDayInMonth = TimSt(Now, '\\d');\r\n else;\r\n sDayInMonth = FormatDate(nServerParsedDate, 'd', nScheduleDateFormatter);\r\n endif;\r\n If( Scan( sDayInMonth | pDelim, pMonthDays ) = 0 & Scan( sDayInMonth |' '| pDelim, pMonthDays ) = 0 );\r\n # could not find the day in the list of acceptable days\r\n bQuit = 1;\r\n sMsg = Expand('Bedrock debug %cThisProcName%: chore will quit. Could not find today %sDayInMonth% in list of acceptable days %pMonthDays%');\r\n IF( pLogOutput = 1 ); LogOutput( 'INFO', sMsg ); EndIf;\r\n Else;\r\n sMsg = Expand('Bedrock debug %cThisProcName%: today %sDayInMonth% found in list of acceptable days %pMonthDays%');\r\n IF( pLogOutput = 1 ); LogOutput( 'INFO', sMsg ); EndIf;\r\n EndIF;\r\n EndIf;\r\n\r\n ### Check the day of the week\r\n If( pWeekDays @<> '' );\r\n if (pScheduleTimezone @= '');\r\n # support for UseExcelSerialDate=T in TM1s.cfg\r\n nDayIndex = Mod( DayNo( Today ) + Dayno( '1960-01-01' ) / 21916 - 2, 7 );\r\n sWeekday = '';\r\n If( nDayIndex = 0 );\r\n sWeekday = 'SUN';\r\n ElseIf( nDayIndex = 1 );\r\n sWeekday = 'MON';\r\n ElseIf( nDayIndex = 2 );\r\n sWeekday = 'TUE';\r\n ElseIf( nDayIndex = 3 );\r\n sWeekday = 'WED';\r\n ElseIf( nDayIndex = 4 );\r\n sWeekday = 'THU';\r\n ElseIf( nDayIndex = 5 );\r\n sWeekday = 'FRI';\r\n ElseIf( nDayIndex = 6 );\r\n sWeekday = 'SAT';\r\n EndIf;\r\n else;\r\n sWeekday = Upper (FormatDate(nServerParsedDate, 'eee', nScheduleDateFormatter));\r\n endif;\r\n If( Scan( sWeekday | pDelim, pWeekDays ) = 0 & Scan( sWeekday |' '| pDelim, pWeekDays ) = 0 );\r\n # could not find the day in the list of acceptable days\r\n bQuit = 1;\r\n pWeekDays = Delet( pWeekDays, Long( pWeekDays ), 1 );\r\n sMsg = Expand('Bedrock debug %cThisProcName%: chore will quit. Could not find today %sWeekday% in list of acceptable days %pWeekDays%');\r\n IF( pLogOutput = 1 ); LogOutput( 'INFO', sMsg ); EndIf;\r\n Else;\r\n pWeekDays = Delet( pWeekDays, Long( pWeekDays ), 1 );\r\n sMsg = Expand('Bedrock debug %cThisProcName%: today %sWeekday% found in list of acceptable days %pWeekDays%');\r\n IF( pLogOutput = 1 ); LogOutput( 'INFO', sMsg ); EndIf;\r\n EndIF;\r\n EndIf;\r\n \r\n ### Check the time of day\r\n if (pScheduleTimezone @= '');\r\n sMinute = TimSt(Now, '\\h:\\i'); \r\n else;\r\n sMinute = FormatDate(nServerParsedDate, 'HH:mm', nScheduleDateFormatter);\r\n endif;\r\n vTimeNow = StringToNumber(SubSt(sMinute, 1, 2));\r\n If( pStartTime = 0 & pEndTime = 24 );\r\n # no time exclusion parameters are set\r\n ElseIf( vTimeNow < pStartTime % vTimeNow >= pEndTime );\r\n # we are in the exclusion zone do not execute chore\r\n bQuit = 1;\r\n sMsg = Expand('Bedrock debug %cThisProcName%: chore will quit. current time %sMinute% is outside the defined execution time from %sStartTime%:00 to %sEndTime%:00');\r\n IF( pLogOutput = 1 ); LogOutput( 'INFO', sMsg ); EndIf;\r\n Else;\r\n # we are not in the exclusion zone, proceed as normal \r\n sMsg = Expand('Bedrock debug %cThisProcName%: current time %sMinute% is within the defined execution time from %sStartTime%:00 to %sEndTime%:00');\r\n IF( pLogOutput = 1 ); LogOutput( 'INFO', sMsg ); EndIf;\r\n EndIF;\r\n\r\nEndIf;\r\n\r\n### Quit chore if quit conditions met\r\nIf( bQuit = 1 );\r\n sMsg = Expand('Bedrock debug %cThisProcName%: terminated the chore for the reasons stated above.');\r\n If( pLogOutput = 1 ); LogOutput( 'INFO' , Expand( cMsgErrorContent ) ); EndIf;\r\n nProcessReturnCode = ProcessExitByChoreQuit();\r\n sProcessReturnCode = 'ProcessExitByChoreQuit';\r\n ChoreQuit;\r\nElse;\r\n ### Return Code\r\n sProcessAction = Expand('Bedrock debug %cThisProcName%: validated the chore to run as normal.');\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% %sProcessAction%' );\r\n nProcessReturnCode = 1;\r\n If( pLogOutput = 1 ); LogOutput('INFO', Expand( sProcessAction ) ); EndIf;\r\nEndIf;\r\n\r\n### End Prolog ###", + "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.chore.execution.check', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pMonthDays', '', \r\n 'pWeekDays', '',\r\n 'pDelim', '&',\r\n 'pStartTime', 0, 'pEndTime', 24,\r\n 'pScheduleTimezone','en-AU',\r\n 'pServerTimezone','etc/UTC'\r\n );\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~## \r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This TI was created to overcome the limited scheduling options in chores. In order to use this TI it has to be the 1st TI in the chore.\r\n# As an example, if you need to run a chore every Monday & Wednesday you would schedule it to run EVERY day but set the pWeekdays parameter to Mon & Wed.\r\n# The chore would then kick off every day but this TI will perform a ProcessExitByChoreQuit function on all days NOT mentioned in pWeekdays.\r\n\r\n# Alternative setup: instead of adding this TI as the 1st TI in the chore, you could also use ExecuteProcess to call it, \r\n# from the top of the Prolog of your first TI process. This is definitely easier than hardcoding process call parameters in the chore dialog.\r\n\r\n# Timezones:\r\n# pScheduleTimezone parameter allow specifying the timezone to perform checks in if server timezone is different to schedule one. E.g. PA server is running in UTC and time or days of week are to be checked in AEST. Full list of timezones https://en.wikipedia.org/wiki/List_of_tz_database_time_zones\r\n# pServerTimezone allows to cater for situations when PA server is running in local time in yet another timezone, e.g. you want to check chore schedule in timezone Europe/Munich for server running in Asia/Singapore\r\n\r\n# Use case: For productive systems.\r\n# 1. A chore should run every 30 minutes between 8am & 8pm on weekdays. Schedule chore for every 30 minutes and include this process 1st in chore with parameters pWeekDays=MON&TUE&WED&THU&FRI pStartTime=8 pEndTime=20.\r\n# 2. A chore should run only on 1st calendar day of each month. Schedule chore for daily execution and include this process 1st in chore with parameters pMonthDays=1.\r\n\r\n# Note:\r\n# * This process will quit a chore if any time-bound, weekday-bound or date-bound conditions which define when the chore should NOT run are met.\r\n# * Only the parameter(s) needed should be specified.\r\n# * Only scheduled executions will be quit outside the parameters. The checks are bypassed if a chore is manually executed by a user. This is done by checking the TM1User function.\r\n# * Time conditions are checked using these parameters in the following order of priority.\r\n# 1. pMonthDays : Days in month when chore is allowed to run. Enter delimited list of days e.g. 1&2&30&31 (blank = no restriction on allowed days of month).\r\n# 2. pWeekDays : Days in week when chore is allowed to run Enter delimited list of weekdays e.g. MON&FRI (blank = no restriction on allowed weekdays).\r\n# 3. pStartTime & pEndTime : Time of day when chore is allowed to run e.g. pStartTime=7, pEndTime=22 execution will be allowed between 7AM & 10PM ( blank = no time-bound restrictions).\r\n#EndRegion @DOC\r\n\r\n### Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSub = cThisProcName |'_'| cTimeStamp |'_'| cRandomInt;\r\ncStartTime = NumberToString( pStartTime );\r\ncEndTime = NumberToString( pEndTime );\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent= 'User:%cUserName% Process:%cThisProcName% Message: %sMsg%';\r\ncLogInfo = 'User:%cUserName% Process:%cThisProcName% run to check if chore should run with parameters pMonthDays:%pMonthDays%, pWeekDays:%pWeekDays%, pDelim:%pDelim%, pStartTime:%cStartTime%, pEndTime:%cEndTime%, pScheduleTimezone: %pScheduleTimezone% pServerTimezone: %pServerTimezone%.' ; \r\nnErrors = 0;\r\nsMsg = '';\r\n\r\n#################################################################################################\r\n#Region - Process Parameters\r\n\r\npJson = IF( JsonType( pJson ) @<> 'object', '{}', pJson );\r\nsMessages = '{\"Process\": \"'|GetProcessName()|'\", \"User\": \"'|TM1User()|'\", \"Info\": [\"Process: '''|GetProcessName()|''' run by User: '''|TM1User()|'''.\"], \"Error\": []}';\r\npDefaultParameters = '{\r\n \"pDelim\": \"&\",\r\n \"pMonthDays\": \"\",\r\n \"pScheduleTimezone\": \"\",\r\n \"pServerTimezone\": \"\",\r\n \"pWeekDays\": \"\",\r\n \"pEndTime\": 24,\r\n \"pLogOutput\": 0,\r\n \"pStartTime\": 0,\r\n \"pStrictErrorHandling\": 0\r\n}';\r\n\r\npPassedParameters = '{\r\n \"pDelim\": '|StringToJson ( pDelim )|',\r\n \"pMonthDays\": '|StringToJson ( pMonthDays )|',\r\n \"pScheduleTimezone\": '|StringToJson ( pScheduleTimezone )|',\r\n \"pServerTimezone\": '|StringToJson ( pServerTimezone )|',\r\n \"pWeekDays\": '|StringToJson ( pWeekDays )|',\r\n \"pEndTime\": '|NumberToString( pEndTime )|',\r\n \"pLogOutput\": '|NumberToString( pLogOutput )|',\r\n \"pStartTime\": '|NumberToString( pStartTime )|',\r\n \"pStrictErrorHandling\": '|NumberToString( pStrictErrorHandling )|'\r\n}';\r\n\r\npJson = JsonMergePatch( pPassedParameters, pJson );\r\n# String Parameters\r\npDelim = JsonToString( JsonGet( pJson, 'pDelim' ) );\r\npMonthDays = JsonToString( JsonGet( pJson, 'pMonthDays' ) );\r\npScheduleTimezone = JsonToString( JsonGet( pJson, 'pScheduleTimezone' ) );\r\npServerTimezone = JsonToString( JsonGet( pJson, 'pServerTimezone' ) );\r\npWeekDays = JsonToString( JsonGet( pJson, 'pWeekDays' ) );\r\n# Numeric Parameters\r\npEndTime = StringToNumber( JsonToString( JsonGet( pJson, 'pEndTime' ) ) );\r\npLogOutput = StringToNumber( JsonToString( JsonGet( pJson, 'pLogOutput' ) ) );\r\npStartTime = StringToNumber( JsonToString( JsonGet( pJson, 'pStartTime' ) ) );\r\npStrictErrorHandling = StringToNumber( JsonToString( JsonGet( pJson, 'pStrictErrorHandling' ) ) );\r\n\r\n### Get the parameters that differ from the default\r\npDiffer = JsonDiff( pDefaultParameters, pJson );\r\nnSize = JsonSize( pDiffer );\r\nWHILE( nSize > 0 );\r\n nSize = nSize - 1;\r\n pDiffer = JsonReplace( pDiffer, '/'|NumberToString( nSize )|'/op', '\"add\"' );\r\nEND;\r\npJson = JsonPatch( '{}', pDiffer );\r\n\r\n### LogOutput parameters\r\nsMessages = JsonAdd( sMessages, '/Info/-', pJson );\r\nIF( pLogOutput = 1 );\r\n LogOutput('INFO', JsonToString( sMessages, '/Info/0', 0, ' ' ) );\r\nENDIF;\r\n\r\n#EndRegion - Process Parameters\r\n#################################################################################################\r\n\r\n## LogOutput parameters\r\nIF( pLogOutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nEndIf;\r\n\r\n### Check params\r\nIf( pDelim @= '' );\r\n pDelim = '&';\r\nElse;\r\n pDelim = SubSt( pDelim, 1, 1 );\r\nEndIf;\r\n\r\nIf( pMonthDays @= 'ALL' );\r\n pMonthDays = '';\r\nEndIf;\r\nIf( pMonthDays @<> '' );\r\n If( SubSt( pMonthDays, Long( pMonthDays ), 1 ) @<> pDelim );\r\n pMonthDays = pMonthDays | pDelim;\r\n EndIf;\r\nEndIf;\r\n\r\nIf( pWeekDays @= 'ALL' );\r\n pWeekDays = '';\r\nEndIf;\r\nIf( pWeekDays @<> '' );\r\n pWeekDays = Upper( pWeekDays );\r\n If( SubSt( pWeekDays, Long( pWeekDays ), 1 ) @<> pDelim );\r\n pWeekDays = pWeekDays | pDelim;\r\n EndIf;\r\nEndIf;\r\n\r\nIf( pStartTime <= 0 % pStartTime > 24 );\r\n pStartTime = 0;\r\nElse;\r\n pStartTime = Round(pStartTime);\r\nEndIf;\r\nsStartTime = NumberToString( pStartTime );\r\n\r\nIf( pEndTime <= 0 % pEndTime > 24 );\r\n pEndTime = 24;\r\nElse;\r\n pEndTime = Round(pEndTime);\r\nEndIf;\r\n\r\nIf( pEndTime < pStartTime );\r\n pEndTime = pStartTime;\r\nEndIf;\r\nsEndTime = NumberToString( pEndTime );\r\n\r\n### Initialize quit Boolean\r\nbQuit = 0;\r\n\r\n### Check the user\r\nIf( DIMIX( '}Clients', cUserName ) > 0 );\r\n If( pLogOutput >= 1 );\r\n sMsg = 'This chore will NOT quit since executed by a user.';\r\n LogOutput( 'INFO', Expand( cMsgErrorContent ) );\r\n EndIf;\r\nElse;\r\n if (pScheduleTimezone@<>'');\r\n #initate the date format for conversion\r\n pServerTimezone = if (pServerTimezone@='','etc/UTC',pServerTimezone);\r\n # need to convert to UTC first and then restate in required timezones\r\n nUTCDateFormatter = NewDateFormatter('', 'etc/UTC', 'serial', 'full', 'datetime');\r\n nScheduleDateFormatter = NewDateFormatter('', pScheduleTimezone, 'serial', 'full', 'datetime');\r\n nServerDateFormatter = NewDateFormatter('', pServerTimezone, 'serial', 'full', 'datetime');\r\n sDateFormat = 'yyyy-MM-dd HH:mm:ss';\r\n sUTCTimeStamp = FormatDate(Now, sDateFormat, nUTCDateFormatter);\r\n nServerParsedDate = ParseDate( sUTCTimeStamp, sDateFormat, nServerDateFormatter );\r\n endif;\r\n ### Check the day of the month\r\n If( pMonthDays @<> '' );\r\n if (pScheduleTimezone @= '');\r\n sDayInMonth = TimSt(Now, '\\d');\r\n else;\r\n sDayInMonth = FormatDate(nServerParsedDate, 'd', nScheduleDateFormatter);\r\n endif;\r\n If( Scan( sDayInMonth | pDelim, pMonthDays ) = 0 & Scan( sDayInMonth |' '| pDelim, pMonthDays ) = 0 );\r\n # could not find the day in the list of acceptable days\r\n bQuit = 1;\r\n sMsg = Expand('Bedrock debug %cThisProcName%: chore will quit. Could not find today %sDayInMonth% in list of acceptable days %pMonthDays%');\r\n IF( pLogOutput = 1 ); LogOutput( 'INFO', sMsg ); EndIf;\r\n Else;\r\n sMsg = Expand('Bedrock debug %cThisProcName%: today %sDayInMonth% found in list of acceptable days %pMonthDays%');\r\n IF( pLogOutput = 1 ); LogOutput( 'INFO', sMsg ); EndIf;\r\n EndIF;\r\n EndIf;\r\n\r\n ### Check the day of the week\r\n If( pWeekDays @<> '' );\r\n if (pScheduleTimezone @= '');\r\n # support for UseExcelSerialDate=T in TM1s.cfg\r\n nDayIndex = Mod( DayNo( Today ) + Dayno( '1960-01-01' ) / 21916 - 2, 7 );\r\n sWeekday = '';\r\n If( nDayIndex = 0 );\r\n sWeekday = 'SUN';\r\n ElseIf( nDayIndex = 1 );\r\n sWeekday = 'MON';\r\n ElseIf( nDayIndex = 2 );\r\n sWeekday = 'TUE';\r\n ElseIf( nDayIndex = 3 );\r\n sWeekday = 'WED';\r\n ElseIf( nDayIndex = 4 );\r\n sWeekday = 'THU';\r\n ElseIf( nDayIndex = 5 );\r\n sWeekday = 'FRI';\r\n ElseIf( nDayIndex = 6 );\r\n sWeekday = 'SAT';\r\n EndIf;\r\n else;\r\n sWeekday = Upper (FormatDate(nServerParsedDate, 'eee', nScheduleDateFormatter));\r\n endif;\r\n If( Scan( sWeekday | pDelim, pWeekDays ) = 0 & Scan( sWeekday |' '| pDelim, pWeekDays ) = 0 );\r\n # could not find the day in the list of acceptable days\r\n bQuit = 1;\r\n pWeekDays = Delet( pWeekDays, Long( pWeekDays ), 1 );\r\n sMsg = Expand('Bedrock debug %cThisProcName%: chore will quit. Could not find today %sWeekday% in list of acceptable days %pWeekDays%');\r\n IF( pLogOutput = 1 ); LogOutput( 'INFO', sMsg ); EndIf;\r\n Else;\r\n pWeekDays = Delet( pWeekDays, Long( pWeekDays ), 1 );\r\n sMsg = Expand('Bedrock debug %cThisProcName%: today %sWeekday% found in list of acceptable days %pWeekDays%');\r\n IF( pLogOutput = 1 ); LogOutput( 'INFO', sMsg ); EndIf;\r\n EndIF;\r\n EndIf;\r\n \r\n ### Check the time of day\r\n if (pScheduleTimezone @= '');\r\n sMinute = TimSt(Now, '\\h:\\i'); \r\n else;\r\n sMinute = FormatDate(nServerParsedDate, 'HH:mm', nScheduleDateFormatter);\r\n endif;\r\n vTimeNow = StringToNumber(SubSt(sMinute, 1, 2));\r\n If( pStartTime = 0 & pEndTime = 24 );\r\n # no time exclusion parameters are set\r\n ElseIf( vTimeNow < pStartTime % vTimeNow >= pEndTime );\r\n # we are in the exclusion zone do not execute chore\r\n bQuit = 1;\r\n sMsg = Expand('Bedrock debug %cThisProcName%: chore will quit. current time %sMinute% is outside the defined execution time from %sStartTime%:00 to %sEndTime%:00');\r\n IF( pLogOutput = 1 ); LogOutput( 'INFO', sMsg ); EndIf;\r\n Else;\r\n # we are not in the exclusion zone, proceed as normal \r\n sMsg = Expand('Bedrock debug %cThisProcName%: current time %sMinute% is within the defined execution time from %sStartTime%:00 to %sEndTime%:00');\r\n IF( pLogOutput = 1 ); LogOutput( 'INFO', sMsg ); EndIf;\r\n EndIF;\r\n\r\nEndIf;\r\n\r\n### Quit chore if quit conditions met\r\nIf( bQuit = 1 );\r\n sMsg = Expand('Bedrock debug %cThisProcName%: terminated the chore for the reasons stated above.');\r\n If( pLogOutput = 1 ); LogOutput( 'INFO' , Expand( cMsgErrorContent ) ); EndIf;\r\n nProcessReturnCode = ProcessExitByChoreQuit();\r\n sProcessReturnCode = 'ProcessExitByChoreQuit';\r\n ChoreQuit;\r\nElse;\r\n ### Return Code\r\n sProcessAction = Expand('Bedrock debug %cThisProcName%: validated the chore to run as normal.');\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% %sProcessAction%' );\r\n nProcessReturnCode = 1;\r\n If( pLogOutput = 1 ); LogOutput('INFO', Expand( sProcessAction ) ); EndIf;\r\nEndIf;\r\n\r\n### End Prolog ###", "MetadataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****", "DataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****", "EpilogProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n### Return code & final error message handling\r\nIf( nErrors > 0 );\r\n sMessage = 'the process incurred at least 1 error. Please see above lines in this file for more details.';\r\n nProcessReturnCode = 0;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% Process:%cThisProcName% completed with errors. Check tm1server.log for details.' );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n EndIf;\r\nElse;\r\n sProcessAction = Expand( 'Process:%cThisProcName% completed normally' );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% %sProcessAction%' );\r\n nProcessReturnCode = 1;\r\n If( pLogOutput = 1 );\r\n LogOutput('INFO', Expand( sProcessAction ) ); \r\n EndIf;\r\nEndIf;\r\n\r\n### End Epilog ###", @@ -10,45 +10,33 @@ "Type": "None" }, "Parameters": [ - { - "Name": "pLogOutput", - "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, - { - "Name": "pStrictErrorHandling", - "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, { "Name": "pMonthDays", - "Prompt": "OPTIONAL: Delimited string of days in month as dd e.g. 01 & 02 & 30 & 31 (Blank=All)", + "Prompt": "OPTIONAL: Delimited list of days in month as dd e.g. 01 & 02 & 30 & 31", "Value": "", "Type": "String" }, { "Name": "pWeekDays", - "Prompt": "OPTIONAL: Delimited string of days in week as ddd e.g. MON & WED (Blank=All)", + "Prompt": "OPTIONAL: Delimited list of days in week as ddd e.g. MON & WED", "Value": "", "Type": "String" }, { "Name": "pDelim", - "Prompt": "OPTIONAL: String array delimiter. Only 1 character allowed (Blank=&)", + "Prompt": "OPTIONAL: Delimiter for list parameters (Default = '&')", "Value": "&", "Type": "String" }, { "Name": "pStartTime", - "Prompt": "OPTIONAL: Time to start running chore from in 24 hr time (at start of hour) (Blank=0)", + "Prompt": "OPTIONAL: Hour to start running chore from in 24 hr time (at start of hour) (Default = 0)", "Value": 0, "Type": "Numeric" }, { "Name": "pEndTime", - "Prompt": "OPTIONAL: Time to finish chore being able to start in 24 hr time (Blank=24)", + "Prompt": "OPTIONAL: Hour to finish chore being able to start in 24 hr time (Default = 24)", "Value": 24, "Type": "Numeric" }, @@ -63,6 +51,24 @@ "Prompt": "OPTIONAL: Timezone for server if ScheduleTimezone is different", "Value": "", "Type": "String" + }, + { + "Name": "pLogOutput", + "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pStrictErrorHandling", + "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pJson", + "Prompt": "OPTIONAL: JSON Object with process parameter values. This will overwrite user passed parameters for all included parameters.", + "Value": "{}", + "Type": "String" } ], "Variables": [], diff --git a/bedrock_processes_json/}bedrock.cube.clone.json b/bedrock_processes_json/}bedrock.cube.clone.json index 77738dc..de9912f 100644 --- a/bedrock_processes_json/}bedrock.cube.clone.json +++ b/bedrock_processes_json/}bedrock.cube.clone.json @@ -1,6 +1,6 @@ { "Name": "}bedrock.cube.clone", - "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.clone', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pSrcCube' ,'', 'pTgtCube', '',\r\n \t'pIncludeRules', 1, 'pIncludeData', 0,\r\n \t'pFilter', '',\r\n \t'pDimDelim', '&', 'pEleStartDelim', '\u00a6', 'pEleDelim', '+',\r\n \t'pSuppressRules', 1, 'pTemp', 1, 'pCubeLogging', 0\r\n );\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process replicates an existing cube. It can include data & rules too.\r\n\r\n# Use case: Intended for development/prototyping.\r\n# 1. Take a snapshot of cube data copying all rules to values.\r\n# 2. Take an exact copy of a cube in a \"one click action\" as a starting point for prototyping rule changes or developing new features.\r\n\r\n# Note:\r\n# * There are parameter options to include data (pIncludeData) and rules (pIncludeRules) with the creation of the cube.\r\n# * If the source cube (pSrcCube) is left blank or doesn't exist in the model, process will terminate withoud doing anything.\r\n# * If the target cube (pTgtCube) already exists in the model, process will terminate withoud doing anything.\r\n# * If the target cube is left blank or is the same as the source cube the cloned cube will inherit the source cube name with \"_Clone\" appended.\r\n# * If the source cube data only needs to be partially copied, then the pFilter parameter should be entered otherwise all other parameters can be left as is.\r\n# * In productive systems this process may be called internally by other processes (}bedrock.cube.data.copy, }bedrock.cube.data.copy.intercube) if copying data via intermediate cloned cube.\r\n#EndRegion @DOC\r\n\r\n### Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSub = cThisProcName |'_'| cTimeStamp |'_'| cRandomInt;\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent= 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pSrcCube:%pSrcCube%, pTgtCube:%pTgtCube%, pIncludeRules:%pIncludeRules%, pIncludeData:%pIncludeData%, pFilter:%pFilter%, pDimDelim:%pDimDelim%, pEleStartDelim:%pEleStartDelim%, pEleDelim:%pEleDelim%, pSuppressRules:%pSuppressRules%, pTemp:%pTemp%, pCubeLogging:%pCubeLogging%.' ; \r\ncDimCountMax = 30 ;\r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\n### Initialise ###\r\nnErrors = 0;\r\nnDataCheck = 0;\r\nsDimCountMax = NumberToString( cDimCountMax );\r\nsDimsString = '';\r\nsDelim = '+';\r\n\r\n### Validate Parameters ###\r\n\r\n## Default filter delimiters\r\nIf( pDimDelim @= '' );\r\n pDimDelim = '&';\r\nEndIf;\r\nIf( pEleStartDelim@= '' );\r\n pEleStartDelim= '\u00a6';\r\nEndIf;\r\nIf( pEleDelim @= '' );\r\n pEleDelim = '+';\r\nEndIf;\r\n\r\n# Validate source cube\r\nIf( Trim( pSrcCube ) @= '' );\r\n nErrors = 1;\r\n sMessage = 'No cube specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( CubeExists( pSrcCube ) = 0 ); \r\n sMessage = Expand( 'Invalid source cube specified: %pSrcCube%.' );\r\n nErrors = 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate target cube\r\nIf( pTgtCube @= '' % pTgtCube @= pSrcCube );\r\n pTgtCube = pSrcCube | '_Clone';\r\nEndIf;\r\nIf( CubeExists( pTgtCube ) = 1 ); \r\n sMessage = Expand( 'Invalid target cube : %pTgtCube%.' );\r\n nErrors = 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n### Create the clone cube ###\r\nnDimCount = 1;\r\nWhile( TabDim( pSrcCube, nDimCount ) @<> '' );\r\n sDimName = TabDim (pSrcCube, nDimCount);\r\n sDimsString = sDimsString | sDimName | sDelim;\r\n nDimCount = nDimCount + 1;\r\nEnd;\r\nnDimCount = nDimCount - 1;\r\nsDimsString = Subst(sDimsString,1,long(sDimsString)-long(sDelim));\r\n\r\nIf( nDimCount > cDimCountMax );\r\n nErrors = 1;\r\n sMessage = Expand( 'Cube has too many dimensions: %pSrcCube% max %sDimCountMax% dims catered for, TI must be altered to accomodate.' );\r\n DataSourceType = 'NULL';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\nsProc = '}bedrock.cube.create';\r\nnRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pTgtCube,\r\n 'pDims', sDimsString,\r\n 'pRecreate', 1,\r\n 'pDelim', sDelim\r\n );\r\n\r\nIF(nRet <> 0);\r\n sMessage = 'Error creating the target cube.';\r\n nErrors = 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nENDIF;\r\n\r\n### copy data ####\r\nIf( pIncludeData = 1 );\r\nnRet = ExecuteProcess('}bedrock.cube.data.copy.intercube',\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pSrcCube',pSrcCube,\r\n \t'pFilter',pFilter,\r\n \t'pTgtCube',pTgtCube,\r\n \t'pMappingToNewDims','',\r\n \t'pSuppressConsol',1,\r\n \t'pSuppressRules',pSuppressRules,\r\n \t'pZeroTarget',0,\r\n \t'pZeroSource',0,\r\n \t'pFactor',1,\r\n 'pDimDelim', pDimDelim,\r\n 'pEleStartDelim', pEleStartDelim,\r\n 'pEleDelim', pEleDelim,\r\n 'pTemp', pTemp,\r\n 'pCubeLogging', pCubeLogging);\r\n\r\n IF(nRet <> 0);\r\n sMessage = 'Error copying data.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n\r\nEndIf;\r\n\r\n### End Prolog ###", + "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.clone', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pSrcCube' ,'', 'pTgtCube', '',\r\n \t'pIncludeRules', 1, 'pIncludeData', 0,\r\n \t'pFilter', '',\r\n \t'pDimDelim', '&', 'pEleStartDelim', '\u00a6', 'pEleDelim', '+',\r\n \t'pSuppressRules', 1, 'pTemp', 1, 'pCubeLogging', 0\r\n );\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process replicates an existing cube. It can include data & rules too.\r\n\r\n# Use case: Intended for development/prototyping.\r\n# 1. Take a snapshot of cube data copying all rules to values.\r\n# 2. Take an exact copy of a cube in a \"one click action\" as a starting point for prototyping rule changes or developing new features.\r\n\r\n# Note:\r\n# * There are parameter options to include data (pIncludeData) and rules (pIncludeRules) with the creation of the cube.\r\n# * If the source cube (pSrcCube) is left blank or doesn't exist in the model, process will terminate withoud doing anything.\r\n# * If the target cube (pTgtCube) already exists in the model, process will terminate withoud doing anything.\r\n# * If the target cube is left blank or is the same as the source cube the cloned cube will inherit the source cube name with \"_Clone\" appended.\r\n# * If the source cube data only needs to be partially copied, then the pFilter parameter should be entered otherwise all other parameters can be left as is.\r\n# * In productive systems this process may be called internally by other processes (}bedrock.cube.data.copy, }bedrock.cube.data.copy.intercube) if copying data via intermediate cloned cube.\r\n#EndRegion @DOC\r\n\r\n### Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSub = cThisProcName |'_'| cTimeStamp |'_'| cRandomInt;\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent= 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pSrcCube:%pSrcCube%, pTgtCube:%pTgtCube%, pIncludeRules:%pIncludeRules%, pIncludeData:%pIncludeData%, pFilter:%pFilter%, pDimDelim:%pDimDelim%, pEleStartDelim:%pEleStartDelim%, pEleDelim:%pEleDelim%, pSuppressRules:%pSuppressRules%, pTemp:%pTemp%, pCubeLogging:%pCubeLogging%.' ; \r\ncDimCountMax = 30 ;\r\n\r\n#################################################################################################\r\n#Region - Process Parameters\r\n\r\npJson = IF( JsonType( pJson ) @<> 'object', '{}', pJson );\r\nsMessages = '{\"Process\": \"'|GetProcessName()|'\", \"User\": \"'|TM1User()|'\", \"Info\": [\"Process: '''|GetProcessName()|''' run by User: '''|TM1User()|'''.\"], \"Error\": []}';\r\npDefaultParameters = '{\r\n \"pDimDelim\": \"&\",\r\n \"pEleDelim\": \"+\",\r\n \"pEleStartDelim\": \"\u00a6\",\r\n \"pFilter\": \"\",\r\n \"pSrcCube\": null,\r\n \"pTgtCube\": \"\",\r\n \"pIncludeData\": 0,\r\n \"pIncludeRules\": 1,\r\n \"pLogOutput\": 0,\r\n \"pStrictErrorHandling\": 0,\r\n \"pSuppressRules\": 1,\r\n \"pTemp\": 1\r\n}';\r\n\r\npPassedParameters = '{\r\n \"pDimDelim\": '|StringToJson ( pDimDelim )|',\r\n \"pEleDelim\": '|StringToJson ( pEleDelim )|',\r\n \"pEleStartDelim\": '|StringToJson ( pEleStartDelim )|',\r\n \"pFilter\": '|StringToJson ( pFilter )|',\r\n \"pSrcCube\": '|StringToJson ( pSrcCube )|',\r\n \"pTgtCube\": '|StringToJson ( pTgtCube )|',\r\n \"pIncludeData\": '|NumberToString( pIncludeData )|',\r\n \"pIncludeRules\": '|NumberToString( pIncludeRules )|',\r\n \"pLogOutput\": '|NumberToString( pLogOutput )|',\r\n \"pStrictErrorHandling\": '|NumberToString( pStrictErrorHandling )|',\r\n \"pSuppressRules\": '|NumberToString( pSuppressRules )|',\r\n \"pTemp\": '|NumberToString( pTemp )|'\r\n}';\r\n\r\npJson = JsonMergePatch( pPassedParameters, pJson );\r\n# String Parameters\r\npDimDelim = JsonToString( JsonGet( pJson, 'pDimDelim' ) );\r\npEleDelim = JsonToString( JsonGet( pJson, 'pEleDelim' ) );\r\npEleStartDelim = JsonToString( JsonGet( pJson, 'pEleStartDelim' ) );\r\npFilter = JsonToString( JsonGet( pJson, 'pFilter' ) );\r\npSrcCube = JsonToString( JsonGet( pJson, 'pSrcCube' ) );\r\npTgtCube = JsonToString( JsonGet( pJson, 'pTgtCube' ) );\r\n# Numeric Parameters\r\npIncludeData = StringToNumber( JsonToString( JsonGet( pJson, 'pIncludeData' ) ) );\r\npIncludeRules = StringToNumber( JsonToString( JsonGet( pJson, 'pIncludeRules' ) ) );\r\npLogOutput = StringToNumber( JsonToString( JsonGet( pJson, 'pLogOutput' ) ) );\r\npStrictErrorHandling = StringToNumber( JsonToString( JsonGet( pJson, 'pStrictErrorHandling' ) ) );\r\npSuppressRules = StringToNumber( JsonToString( JsonGet( pJson, 'pSuppressRules' ) ) );\r\npTemp = StringToNumber( JsonToString( JsonGet( pJson, 'pTemp' ) ) );\r\n\r\n### Get the parameters that differ from the default\r\npDiffer = JsonDiff( pDefaultParameters, pJson );\r\nnSize = JsonSize( pDiffer );\r\nWHILE( nSize > 0 );\r\n nSize = nSize - 1;\r\n pDiffer = JsonReplace( pDiffer, '/'|NumberToString( nSize )|'/op', '\"add\"' );\r\nEND;\r\npJson = JsonPatch( '{}', pDiffer );\r\n\r\n### LogOutput parameters\r\nsMessages = JsonAdd( sMessages, '/Info/-', pJson );\r\nIF( pLogOutput = 1 );\r\n LogOutput('INFO', JsonToString( sMessages, '/Info/0', 0, ' ' ) );\r\nENDIF;\r\n\r\n#EndRegion - Process Parameters\r\n#################################################################################################\r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\n### Initialise ###\r\nnErrors = 0;\r\nnDataCheck = 0;\r\nsDimCountMax = NumberToString( cDimCountMax );\r\nsDimsString = '';\r\nsDelim = '+';\r\n\r\n### Validate Parameters ###\r\n\r\n## Default filter delimiters\r\nIf( pDimDelim @= '' );\r\n pDimDelim = '&';\r\nEndIf;\r\nIf( pEleStartDelim@= '' );\r\n pEleStartDelim= '\u00a6';\r\nEndIf;\r\nIf( pEleDelim @= '' );\r\n pEleDelim = '+';\r\nEndIf;\r\n\r\n# Validate source cube\r\nIf( Trim( pSrcCube ) @= '' );\r\n nErrors = 1;\r\n sMessage = 'No cube specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( CubeExists( pSrcCube ) = 0 ); \r\n sMessage = Expand( 'Invalid source cube specified: %pSrcCube%.' );\r\n nErrors = 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate target cube\r\nIf( pTgtCube @= '' % pTgtCube @= pSrcCube );\r\n pTgtCube = pSrcCube | '_Clone';\r\nEndIf;\r\nIf( CubeExists( pTgtCube ) = 1 ); \r\n sMessage = Expand( 'Invalid target cube : %pTgtCube%.' );\r\n nErrors = 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n### Create the clone cube ###\r\nnDimCount = 1;\r\nWhile( TabDim( pSrcCube, nDimCount ) @<> '' );\r\n sDimName = TabDim (pSrcCube, nDimCount);\r\n sDimsString = sDimsString | sDimName | sDelim;\r\n nDimCount = nDimCount + 1;\r\nEnd;\r\nnDimCount = nDimCount - 1;\r\nsDimsString = Subst(sDimsString,1,long(sDimsString)-long(sDelim));\r\n\r\nIf( nDimCount > cDimCountMax );\r\n nErrors = 1;\r\n sMessage = Expand( 'Cube has too many dimensions: %pSrcCube% max %sDimCountMax% dims catered for, TI must be altered to accomodate.' );\r\n DataSourceType = 'NULL';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\nsProc = '}bedrock.cube.create';\r\nnRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pTgtCube,\r\n 'pDims', sDimsString,\r\n 'pRecreate', 1,\r\n 'pDelim', sDelim\r\n );\r\n\r\nIF(nRet <> 0);\r\n sMessage = 'Error creating the target cube.';\r\n nErrors = 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nENDIF;\r\n\r\n### copy data ####\r\nIf( pIncludeData = 1 );\r\nnRet = ExecuteProcess('}bedrock.cube.data.copy.intercube',\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pSrcCube',pSrcCube,\r\n \t'pFilter',pFilter,\r\n \t'pTgtCube',pTgtCube,\r\n \t'pMappingToNewDims','',\r\n \t'pSuppressConsol',1,\r\n \t'pSuppressRules',pSuppressRules,\r\n \t'pZeroTarget',0,\r\n \t'pZeroSource',0,\r\n \t'pFactor',1,\r\n 'pDimDelim', pDimDelim,\r\n 'pEleStartDelim', pEleStartDelim,\r\n 'pEleDelim', pEleDelim,\r\n 'pTemp', pTemp,\r\n 'pCubeLogging', pCubeLogging);\r\n\r\n IF(nRet <> 0);\r\n sMessage = 'Error copying data.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n\r\nEndIf;\r\n\r\n### End Prolog ###", "MetadataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "DataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "EpilogProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n### Attach rules to cloned cube ###\r\nIf( nErrors = 0 & pIncludeRules = 1 );\r\n sRule=CubeRuleGet( pSrcCube );\r\n If( sRule@<> '' );\r\n If( nErrors = 0 );\r\n CubeRuleSet(pTgtCube, sRule);\r\n EndIf;\r\n EndIf;\r\nEndIf;\r\n \r\n### Return code & final error message handling\r\nIf( nErrors > 0 );\r\n sMessage = 'the process incurred at least 1 error. Please see above lines in this file for more details.';\r\n nProcessReturnCode = 0;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% Process:%cThisProcName% completed with errors. Check tm1server.log for details.' );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n EndIf;\r\nElse;\r\n sProcessAction = Expand( 'Process:%cThisProcName% successfully cloned the %pSrcCube% cube to %pTgtCube%.' );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% %sProcessAction%' );\r\n nProcessReturnCode = 1;\r\n If ( pLogOutput = 1 );\r\n LogOutput('INFO', Expand ( sProcessAction ) );\r\n EndIf;\r\nEndIf;\r\n\r\n### End Epilog ###", @@ -10,83 +10,89 @@ "Type": "None" }, "Parameters": [ - { - "Name": "pLogOutput", - "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, - { - "Name": "pStrictErrorHandling", - "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, { "Name": "pSrcCube", - "Prompt": "REQUIRED: Source Cube", + "Prompt": "REQUIRED: Source cube name", "Value": "", "Type": "String" }, { "Name": "pTgtCube", - "Prompt": "OPTIONAL: Target Cube to create/re-create (Source cube_clone if left blank)", + "Prompt": "OPTIONAL: Target cube to create/re-create (Default = pSrcCube | '_Clone')", "Value": "", "Type": "String" }, { "Name": "pIncludeRules", - "Prompt": "REQUIRED: Include cube rules? (Boolean Yes = 1)", + "Prompt": "OPTIONAL: Include cube rules (Boolean. Default = 1)", "Value": 1, "Type": "Numeric" }, { "Name": "pIncludeData", - "Prompt": "REQUIRED: Include cube data? (Boolean Yes = 1)", + "Prompt": "OPTIONAL: Include cube data (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" }, { "Name": "pFilter", - "Prompt": "OPTIONAL: Filter on source cube in format Year\u00a6 2006 + 2007 & Scenario\u00a6 Actual + Budget. Blank for whole cube", + "Prompt": "OPTIONAL: Filter on cube in format: 'dim_one\u00a6 el_one + el_two & dim_two\u00a6 el_one + el_two'", "Value": "", "Type": "String" }, { "Name": "pDimDelim", - "Prompt": "OPTIONAL: Delimiter for start of Dimension/Element set (default value if blank = '&')", + "Prompt": "OPTIONAL: Delimiter for start of dimension/element set in filter parameters (Default = '&')", "Value": "&", "Type": "String" }, { "Name": "pEleStartDelim", - "Prompt": "OPTIONAL: Delimiter for start of element list (default value if blank = '\u00a6')", + "Prompt": "OPTIONAL: Delimiter for start of element list in filter parameters (Default = '\u00a6')", "Value": "\u00a6", "Type": "String" }, { "Name": "pEleDelim", - "Prompt": "OPTIONAL: Delimiter between elements (default value if blank = '+')", + "Prompt": "OPTIONAL: Delimiter between elements in filter parameters (Default = '+')", "Value": "+", "Type": "String" }, { "Name": "pSuppressRules", - "Prompt": "REQUIRED: Skip rule values? (1=skip)", + "Prompt": "OPTIONAL: Suppress rules (Boolean. Default = 1)", "Value": 1, "Type": "Numeric" }, { "Name": "pTemp", - "Prompt": "REQUIRED: Delete temporary view and Subset ( 0 = Retain View and Subsets 1 = Delete View and Subsets 2 = Delete View only )", + "Prompt": "OPTIONAL: Delete/create temporary objects (0 = Do not delete, 1 = Delete, 2 = if view and subsets are created, keep only subsets)", "Value": 1, "Type": "Numeric" }, + { + "Name": "pLogOutput", + "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pStrictErrorHandling", + "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, { "Name": "pCubeLogging", "Prompt": "OBSOLETE: This parameter does nothing and is only included for backwards compatability", "Value": 0, "Type": "Numeric" + }, + { + "Name": "pJson", + "Prompt": "OPTIONAL: JSON Object with process parameter values. This will overwrite user passed parameters for all included parameters.", + "Value": "{}", + "Type": "String" } ], "Variables": [ @@ -287,34 +293,5 @@ "EndByte": 0 } ], - "VariablesUIData": [ - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f" - ] + "VariablesUIData": [] } \ No newline at end of file diff --git a/bedrock_processes_json/}bedrock.cube.create.json b/bedrock_processes_json/}bedrock.cube.create.json index faa2019..d0ec41c 100644 --- a/bedrock_processes_json/}bedrock.cube.create.json +++ b/bedrock_processes_json/}bedrock.cube.create.json @@ -1,6 +1,6 @@ { "Name": "}bedrock.cube.create", - "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.create', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pCube', '', 'pDims', '',\r\n \t'pRecreate', 0, 'pDelim', '&'\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description: \r\n# This process automatically creates a cube based on a delimited string of dimension names.\r\n\r\n# Use case: Intended for development/prototyping.\r\n# 1/ This can be used to quickly create a cube for a demo or development.\r\n\r\n# Note:\r\n# The pDims parameter contains the dimenson list and is mandatory.\r\n# The format of the pDims parameter is as follows for delimiter of '&' (e.g. Dim1 & Dim2 & Dim3 ).\r\n# Spaces are ignored so use them to make your filter more readable.\r\n# The order of the dimension list specifies the initial index order of dimensions in the cube.\r\n# pRecreate is an optional parameter for creating new cubes:\r\n# - If a cube already exists and pRecreate is set to 0 then the process will abort.\r\n# - If a cube already exists and pRecreate is set to 1 then the process will destroy the old cube and recreate with the specified dimensionality.\r\n#EndRegion @DOC\r\n\r\n##Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncDelimDim = TRIM(pDelim);\r\nnDims = 0;\r\nnDimMax = 100;\r\nnErrors = 0;\r\nsMessage = '';\r\ncUserName = TM1User();\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pCube:%pCube%, pDims:%pDims%, pRecreate:%pRecreate%, pDelim:%pDelim%.' ; \r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\n## Validate the Cube parameter\r\nIf( TRIM(pCube) @= '' );\r\n sMessage = 'A cube name must be provided.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# If specified cube exists and recreate option not set to true then terminate process\r\nIf( CubeExists( pCube ) = 1 );\r\n If( pRecreate <> 1 );\r\n sMessage = Expand( 'Cube %pCube% already exists. Aborting cube create.' );\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\nEndIf;\r\n\r\n# Check the delimiter\r\nIf( cDelimDim @= '' );\r\n cDelimDim = '&';\r\nEndIf;\r\n\r\n# Check the dimension list can't be empty\r\nIf( pDims @= '' );\r\n sMessage = 'The dimension list is blank.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Check the dimension list must contain delimiter\r\nIf( Scan( cDelimDim, pDims ) < 2 );\r\n sMessage = 'The dimension list must contain at least 2 dimension names separated by the delimiter.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n### Initialise the dimension variables ###\r\nsDim01 = '';\r\nsDim02 = '';\r\nsDim03 = '';\r\nsDim04 = '';\r\nsDim05 = '';\r\nsDim06 = '';\r\nsDim07 = '';\r\nsDim08 = '';\r\nsDim09 = '';\r\nsDim10 = '';\r\nsDim11 = '';\r\nsDim12 = '';\r\nsDim13 = '';\r\nsDim14 = '';\r\nsDim15 = '';\r\nsDim16 = '';\r\nsDim17 = '';\r\nsDim18 = '';\r\nsDim19 = '';\r\nsDim20 = '';\r\nsDim21 = '';\r\nsDim22 = '';\r\nsDim23 = '';\r\nsDim24 = '';\r\nsDim25 = '';\r\nsDim26 = '';\r\nsDim27 = '';\r\nsDim28 = '';\r\nsDim29 = '';\r\nsDim30 = '';\r\nsDim31 = '';\r\nsDim32 = '';\r\nsDim33 = '';\r\nsDim34 = '';\r\nsDim35 = '';\r\nsDim36 = '';\r\nsDim37 = '';\r\nsDim38 = '';\r\nsDim39 = '';\r\nsDim40 = '';\r\nsDim41 = '';\r\nsDim42 = '';\r\nsDim43 = '';\r\nsDim44 = '';\r\nsDim45 = '';\r\nsDim46 = '';\r\nsDim47 = '';\r\nsDim48 = '';\r\nsDim49 = '';\r\nsDim50 = '';\r\nsDim51 = '';\r\nsDim52 = '';\r\nsDim53 = '';\r\nsDim54 = '';\r\nsDim55 = '';\r\nsDim56 = '';\r\nsDim57 = '';\r\nsDim58 = '';\r\nsDim59 = '';\r\nsDim60 = '';\r\nsDim61 = '';\r\nsDim62 = '';\r\nsDim63 = '';\r\nsDim64 = '';\r\nsDim65 = '';\r\nsDim66 = '';\r\nsDim67 = '';\r\nsDim68 = '';\r\nsDim69 = '';\r\nsDim70 = '';\r\nsDim71 = '';\r\nsDim72 = '';\r\nsDim73 = '';\r\nsDim74 = '';\r\nsDim75 = '';\r\nsDim76 = '';\r\nsDim77 = '';\r\nsDim78 = '';\r\nsDim79 = '';\r\nsDim80 = '';\r\nsDim81 = '';\r\nsDim82 = '';\r\nsDim83 = '';\r\nsDim84 = '';\r\nsDim85 = '';\r\nsDim86 = '';\r\nsDim87 = '';\r\nsDim88 = '';\r\nsDim89 = '';\r\nsDim90 = '';\r\nsDim91 = '';\r\nsDim92 = '';\r\nsDim93 = '';\r\nsDim94 = '';\r\nsDim95 = '';\r\nsDim96 = '';\r\nsDim97 = '';\r\nsDim98 = '';\r\nsDim99 = '';\r\nsDim100 = '';\r\n\r\n### Split delimited dimension list and count number of dimensions ###\r\nsDims = TRIM( pDims );\r\nnDelimIndex = 1;\r\n\r\nWhile( nDelimIndex > 0 & Long( sDims ) > 0 );\r\n\r\n nDelimIndex = Scan( cDelimDim, sDims );\r\n If( nDelimIndex > 0 );\r\n sDim = Trim( SubSt( sDims, 1, nDelimIndex - 1 ) );\r\n sDims = Trim( SubSt( sDims, nDelimIndex + Long( cDelimDim ), Long( sDims ) ) );\r\n Else;\r\n sDim = Trim( sDims );\r\n EndIf;\r\n\r\n If( DimensionExists( sDim ) = 1 );\r\n # sDim recognized as a dimension, increment the dim counter and set the dim name variable (how we wish Expand worked on the LHS of = ...)\r\n nDims = nDims + 1;\r\n If( nDims > nDimMax );\r\n sMessage = 'Maximum number of dimensions exceeded. Aborting';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\n If( nDims = 1 );\r\n sDim01 = sDim;\r\n ElseIf( nDims = 2 );\r\n sDim02 = sDim;\r\n ElseIf( nDims = 3 );\r\n sDim03 = sDim;\r\n ElseIf( nDims = 4 );\r\n sDim04 = sDim;\r\n ElseIf( nDims = 5 );\r\n sDim05 = sDim;\r\n ElseIf( nDims = 6 );\r\n sDim06 = sDim;\r\n ElseIf( nDims = 7 );\r\n sDim07 = sDim;\r\n ElseIf( nDims = 8 );\r\n sDim08 = sDim;\r\n ElseIf( nDims = 9 );\r\n sDim09 = sDim;\r\n ElseIf( nDims = 10 );\r\n sDim10 = sDim;\r\n ElseIf( nDims = 11 );\r\n sDim11 = sDim;\r\n ElseIf( nDims = 12 );\r\n sDim12 = sDim;\r\n ElseIf( nDims = 13 );\r\n sDim13 = sDim;\r\n ElseIf( nDims = 14 );\r\n sDim14 = sDim;\r\n ElseIf( nDims = 15 );\r\n sDim15 = sDim;\r\n ElseIf( nDims = 16 );\r\n sDim16 = sDim;\r\n ElseIf( nDims = 17 );\r\n sDim17 = sDim;\r\n ElseIf( nDims = 18 );\r\n sDim18 = sDim;\r\n ElseIf( nDims = 19 );\r\n sDim19 = sDim;\r\n ElseIf( nDims = 20 );\r\n sDim20 = sDim;\r\n ElseIf( nDims = 21 );\r\n sDim21 = sDim;\r\n ElseIf( nDims = 22 );\r\n sDim22 = sDim;\r\n ElseIf( nDims = 23 );\r\n sDim23 = sDim;\r\n ElseIf( nDims = 24 );\r\n sDim24 = sDim;\r\n ElseIf( nDims = 25 );\r\n sDim25 = sDim;\r\n ElseIf( nDims = 26 );\r\n sDim26 = sDim;\r\n ElseIf( nDims = 27 );\r\n sDim27 = sDim;\r\n ElseIf( nDims = 28 );\r\n sDim28 = sDim;\r\n ElseIf( nDims = 29 );\r\n sDim29 = sDim;\r\n ElseIf( nDims = 30 );\r\n sDim30 = sDim;\r\n ElseIf( nDims = 31 );\r\n sDim31 = sDim;\r\n ElseIf( nDims = 32 );\r\n sDim32 = sDim;\r\n ElseIf( nDims = 33 );\r\n sDim33 = sDim;\r\n ElseIf( nDims = 34 );\r\n sDim34 = sDim;\r\n ElseIf( nDims = 35 );\r\n sDim35 = sDim;\r\n ElseIf( nDims = 36 );\r\n sDim36 = sDim;\r\n ElseIf( nDims = 37 );\r\n sDim37 = sDim;\r\n ElseIf( nDims = 38 );\r\n sDim38 = sDim;\r\n ElseIf( nDims = 39 );\r\n sDim39 = sDim;\r\n ElseIf( nDims = 40 );\r\n sDim40 = sDim;\r\n ElseIf( nDims = 41 );\r\n sDim41 = sDim;\r\n ElseIf( nDims = 42 );\r\n sDim42 = sDim;\r\n ElseIf( nDims = 43 );\r\n sDim43 = sDim;\r\n ElseIf( nDims = 44 );\r\n sDim44 = sDim;\r\n ElseIf( nDims = 45 );\r\n sDim45 = sDim;\r\n ElseIf( nDims = 46 );\r\n sDim46 = sDim;\r\n ElseIf( nDims = 47 );\r\n sDim47 = sDim;\r\n ElseIf( nDims = 48 );\r\n sDim48 = sDim;\r\n ElseIf( nDims = 49 );\r\n sDim49 = sDim;\r\n ElseIf( nDims = 50 );\r\n sDim50 = sDim;\r\n ElseIf( nDims = 51 );\r\n sDim51 = sDim;\r\n ElseIf( nDims = 52 );\r\n sDim52 = sDim;\r\n ElseIf( nDims = 53 );\r\n sDim53 = sDim;\r\n ElseIf( nDims = 54 );\r\n sDim54 = sDim;\r\n ElseIf( nDims = 55 );\r\n sDim55 = sDim;\r\n ElseIf( nDims = 56 );\r\n sDim56 = sDim;\r\n ElseIf( nDims = 57 );\r\n sDim57 = sDim;\r\n ElseIf( nDims = 58 );\r\n sDim58 = sDim;\r\n ElseIf( nDims = 59 );\r\n sDim59 = sDim;\r\n ElseIf( nDims = 60 );\r\n sDim60 = sDim;\r\n ElseIf( nDims = 61 );\r\n sDim61 = sDim;\r\n ElseIf( nDims = 62 );\r\n sDim62 = sDim;\r\n ElseIf( nDims = 63 );\r\n sDim63 = sDim;\r\n ElseIf( nDims = 64 );\r\n sDim64 = sDim;\r\n ElseIf( nDims = 65 );\r\n sDim65 = sDim;\r\n ElseIf( nDims = 66 );\r\n sDim66 = sDim;\r\n ElseIf( nDims = 67 );\r\n sDim67 = sDim;\r\n ElseIf( nDims = 68 );\r\n sDim68 = sDim;\r\n ElseIf( nDims = 69 );\r\n sDim69 = sDim;\r\n ElseIf( nDims = 70 );\r\n sDim70 = sDim;\r\n ElseIf( nDims = 71 );\r\n sDim71 = sDim;\r\n ElseIf( nDims = 72 );\r\n sDim72 = sDim;\r\n ElseIf( nDims = 73 );\r\n sDim73 = sDim;\r\n ElseIf( nDims = 74 );\r\n sDim74 = sDim;\r\n ElseIf( nDims = 75 );\r\n sDim75 = sDim;\r\n ElseIf( nDims = 76 );\r\n sDim76 = sDim;\r\n ElseIf( nDims = 77 );\r\n sDim77 = sDim;\r\n ElseIf( nDims = 78 );\r\n sDim78 = sDim;\r\n ElseIf( nDims = 79 );\r\n sDim79 = sDim;\r\n ElseIf( nDims = 80 );\r\n sDim80 = sDim;\r\n ElseIf( nDims = 81 );\r\n sDim81 = sDim;\r\n ElseIf( nDims = 82 );\r\n sDim82 = sDim;\r\n ElseIf( nDims = 83 );\r\n sDim83 = sDim;\r\n ElseIf( nDims = 84 );\r\n sDim84 = sDim;\r\n ElseIf( nDims = 85 );\r\n sDim85 = sDim;\r\n ElseIf( nDims = 86 );\r\n sDim86 = sDim;\r\n ElseIf( nDims = 87 );\r\n sDim87 = sDim;\r\n ElseIf( nDims = 88 );\r\n sDim88 = sDim;\r\n ElseIf( nDims = 89 );\r\n sDim89 = sDim;\r\n ElseIf( nDims = 90 );\r\n sDim90 = sDim;\r\n ElseIf( nDims = 91 );\r\n sDim91 = sDim;\r\n ElseIf( nDims = 92 );\r\n sDim92 = sDim;\r\n ElseIf( nDims = 93 );\r\n sDim93 = sDim;\r\n ElseIf( nDims = 94 );\r\n sDim94 = sDim;\r\n ElseIf( nDims = 95 );\r\n sDim95 = sDim;\r\n ElseIf( nDims = 96 );\r\n sDim96 = sDim;\r\n ElseIf( nDims = 97 );\r\n sDim97 = sDim;\r\n ElseIf( nDims = 98 );\r\n sDim98 = sDim;\r\n ElseIf( nDims = 99 );\r\n sDim99 = sDim;\r\n ElseIf( nDims = 100 );\r\n sDim100 = sDim;\r\n EndIf; \r\n\r\n Else;\r\n\r\n # sDim not recognized as valid dimension\r\n sMessage = Expand( '%sDim% not recognized as valid dimension.' );\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\n\r\nEnd;\r\n\r\n### Create the cube ###\r\n\r\nIf( nDims < 2 );\r\n sMessage = 'Number of dimesnions specified is less than 2';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\nIf( CubeExists( pCube ) = 1 & pRecreate = 1 );\r\n CubeDestroy( pCube );\r\nEndIf;\r\n\r\nIf( nDims = 2 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02 );\r\nElseIf( nDims = 3 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03 );\r\nElseIf( nDims = 4 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04 );\r\nElseIf( nDims = 5 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05 );\r\nElseIf( nDims = 6 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06 );\r\nElseIf( nDims = 7 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07 );\r\nElseIf( nDims = 8 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08 );\r\nElseIf( nDims = 9 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09 );\r\nElseIf( nDims = 10 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10 );\r\nElseIf( nDims = 11 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11 );\r\nElseIf( nDims = 12 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12 );\r\nElseIf( nDims = 13 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13 );\r\nElseIf( nDims = 14 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14 );\r\nElseIf( nDims = 15 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15 );\r\nElseIf( nDims = 16 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16 );\r\nElseIf( nDims = 17 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17 );\r\nElseIf( nDims = 18 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18 );\r\nElseIf( nDims = 19 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19 );\r\nElseIf( nDims = 20 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20 );\r\nElseIf( nDims = 21 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21 );\r\nElseIf( nDims = 22 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22 );\r\nElseIf( nDims = 23 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23 );\r\nElseIf( nDims = 24 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24 );\r\nElseIf( nDims = 25 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25 );\r\nElseIf( nDims = 26 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26 );\r\nElseIf( nDims = 27 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27 );\r\nElseIf( nDims = 28 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28 );\r\nElseIf( nDims = 29 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29 );\r\nElseIf( nDims = 30 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30 );\r\nElseIf( nDims = 31 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31 );\r\nElseIf( nDims = 32 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32 );\r\nElseIf( nDims = 33 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33 );\r\nElseIf( nDims = 34 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34 );\r\nElseIf( nDims = 35 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35 );\r\nElseIf( nDims = 36 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36 );\r\nElseIf( nDims = 37 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37 );\r\nElseIf( nDims = 38 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38 );\r\nElseIf( nDims = 39 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39 );\r\nElseIf( nDims = 40 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40 );\r\nElseIf( nDims = 41 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41 );\r\nElseIf( nDims = 42 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42 );\r\nElseIf( nDims = 43 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43 );\r\nElseIf( nDims = 44 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44 );\r\nElseIf( nDims = 45 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45 );\r\nElseIf( nDims = 46 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46 );\r\nElseIf( nDims = 47 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47 );\r\nElseIf( nDims = 48 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48 );\r\nElseIf( nDims = 49 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49 );\r\nElseIf( nDims = 50 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50 );\r\nElseIf( nDims = 51 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51 );\r\nElseIf( nDims = 52 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52 );\r\nElseIf( nDims = 53 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53 );\r\nElseIf( nDims = 54 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54 );\r\nElseIf( nDims = 55 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55 );\r\nElseIf( nDims = 56 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56 );\r\nElseIf( nDims = 57 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57 );\r\nElseIf( nDims = 58 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58 );\r\nElseIf( nDims = 59 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59 );\r\nElseIf( nDims = 60 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60 );\r\nElseIf( nDims = 61 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61 );\r\nElseIf( nDims = 62 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62 );\r\nElseIf( nDims = 63 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63 );\r\nElseIf( nDims = 64 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64 );\r\nElseIf( nDims = 65 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65 );\r\nElseIf( nDims = 66 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66 );\r\nElseIf( nDims = 67 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67 );\r\nElseIf( nDims = 68 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68 );\r\nElseIf( nDims = 69 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69 );\r\nElseIf( nDims = 70 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70 );\r\nElseIf( nDims = 71 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71 );\r\nElseIf( nDims = 72 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72 );\r\nElseIf( nDims = 73 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73 );\r\nElseIf( nDims = 74 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74 );\r\nElseIf( nDims = 75 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75 );\r\nElseIf( nDims = 76 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76 );\r\nElseIf( nDims = 77 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77 );\r\nElseIf( nDims = 78 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78 );\r\nElseIf( nDims = 79 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79 );\r\nElseIf( nDims = 80 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80 );\r\nElseIf( nDims = 81 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81 );\r\nElseIf( nDims = 82 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81, sDim82 );\r\nElseIf( nDims = 83 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81, sDim82, sDim83 );\r\nElseIf( nDims = 84 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81, sDim82, sDim83, sDim84 );\r\nElseIf( nDims = 85 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81, sDim82, sDim83, sDim84, sDim85 );\r\nElseIf( nDims = 86 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81, sDim82, sDim83, sDim84, sDim85, sDim86 );\r\nElseIf( nDims = 87 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81, sDim82, sDim83, sDim84, sDim85, sDim86, sDim87 );\r\nElseIf( nDims = 88 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81, sDim82, sDim83, sDim84, sDim85, sDim86, sDim87, sDim88 );\r\nElseIf( nDims = 89 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81, sDim82, sDim83, sDim84, sDim85, sDim86, sDim87, sDim88, sDim89 );\r\nElseIf( nDims = 90 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81, sDim82, sDim83, sDim84, sDim85, sDim86, sDim87, sDim88, sDim89, sDim90 );\r\nElseIf( nDims = 91 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81, sDim82, sDim83, sDim84, sDim85, sDim86, sDim87, sDim88, sDim89, sDim90, sDim91 );\r\nElseIf( nDims = 92 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81, sDim82, sDim83, sDim84, sDim85, sDim86, sDim87, sDim88, sDim89, sDim90, sDim91, sDim92 );\r\nElseIf( nDims = 93 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81, sDim82, sDim83, sDim84, sDim85, sDim86, sDim87, sDim88, sDim89, sDim90, sDim91, sDim92, sDim93 );\r\nElseIf( nDims = 94 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81, sDim82, sDim83, sDim84, sDim85, sDim86, sDim87, sDim88, sDim89, sDim90, sDim91, sDim92, sDim93, sDim94 );\r\nElseIf( nDims = 95 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81, sDim82, sDim83, sDim84, sDim85, sDim86, sDim87, sDim88, sDim89, sDim90, sDim91, sDim92, sDim93, sDim94, sDim95 );\r\nElseIf( nDims = 96 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81, sDim82, sDim83, sDim84, sDim85, sDim86, sDim87, sDim88, sDim89, sDim90, sDim91, sDim92, sDim93, sDim94, sDim95, sDim96 );\r\nElseIf( nDims = 97 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81, sDim82, sDim83, sDim84, sDim85, sDim86, sDim87, sDim88, sDim89, sDim90, sDim91, sDim92, sDim93, sDim94, sDim95, sDim96, sDim97 );\r\nElseIf( nDims = 98 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81, sDim82, sDim83, sDim84, sDim85, sDim86, sDim87, sDim88, sDim89, sDim90, sDim91, sDim92, sDim93, sDim94, sDim95, sDim96, sDim97, sDim98 );\r\nElseIf( nDims = 99 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81, sDim82, sDim83, sDim84, sDim85, sDim86, sDim87, sDim88, sDim89, sDim90, sDim91, sDim92, sDim93, sDim94, sDim95, sDim96, sDim97, sDim98, sDim99 );\r\nElseIf( nDims = 100 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81, sDim82, sDim83, sDim84, sDim85, sDim86, sDim87, sDim88, sDim89, sDim90, sDim91, sDim92, sDim93, sDim94, sDim95, sDim96, sDim97, sDim98, sDim99, sDim100 );\r\nEndIf;\r\n\r\n", + "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.create', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pCube', '', 'pDims', '',\r\n \t'pRecreate', 0, 'pDelim', '&'\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description: \r\n# This process automatically creates a cube based on a delimited string of dimension names.\r\n\r\n# Use case: Intended for development/prototyping.\r\n# 1/ This can be used to quickly create a cube for a demo or development.\r\n\r\n# Note:\r\n# The pDims parameter contains the dimenson list and is mandatory.\r\n# The format of the pDims parameter is as follows for delimiter of '&' (e.g. Dim1 & Dim2 & Dim3 ).\r\n# Spaces are ignored so use them to make your filter more readable.\r\n# The order of the dimension list specifies the initial index order of dimensions in the cube.\r\n# pRecreate is an optional parameter for creating new cubes:\r\n# - If a cube already exists and pRecreate is set to 0 then the process will abort.\r\n# - If a cube already exists and pRecreate is set to 1 then the process will destroy the old cube and recreate with the specified dimensionality.\r\n#EndRegion @DOC\r\n\r\n##Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncDelimDim = TRIM(pDelim);\r\nnDims = 0;\r\nnDimMax = 100;\r\nnErrors = 0;\r\nsMessage = '';\r\ncUserName = TM1User();\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pCube:%pCube%, pDims:%pDims%, pRecreate:%pRecreate%, pDelim:%pDelim%.' ;\r\n\r\n#################################################################################################\r\n#Region - Process Parameters\r\n\r\npJson = IF( JsonType( pJson ) @<> 'object', '{}', pJson );\r\nsMessages = '{\"Process\": \"'|GetProcessName()|'\", \"User\": \"'|TM1User()|'\", \"Info\": [\"Process: '''|GetProcessName()|''' run by User: '''|TM1User()|'''.\"], \"Error\": []}';\r\npDefaultParameters = '{\r\n \"pCube\": null,\r\n \"pDelim\": \"&\",\r\n \"pDims\": null,\r\n \"pLogOutput\": 0,\r\n \"pRecreate\": 0,\r\n \"pStrictErrorHandling\": 0\r\n}';\r\n\r\npPassedParameters = '{\r\n \"pCube\": '|StringToJson ( pCube )|',\r\n \"pDelim\": '|StringToJson ( pDelim )|',\r\n \"pDims\": '|StringToJson ( pDims )|',\r\n \"pLogOutput\": '|NumberToString( pLogOutput )|',\r\n \"pRecreate\": '|NumberToString( pRecreate )|',\r\n \"pStrictErrorHandling\": '|NumberToString( pStrictErrorHandling )|'\r\n}';\r\n\r\npJson = JsonMergePatch( pPassedParameters, pJson );\r\n# String Parameters\r\npCube = JsonToString( JsonGet( pJson, 'pCube' ) );\r\npDelim = JsonToString( JsonGet( pJson, 'pDelim' ) );\r\npDims = JsonToString( JsonGet( pJson, 'pDims' ) );\r\n# Numeric Parameters\r\npLogOutput = StringToNumber( JsonToString( JsonGet( pJson, 'pLogOutput' ) ) );\r\npRecreate = StringToNumber( JsonToString( JsonGet( pJson, 'pRecreate' ) ) );\r\npStrictErrorHandling = StringToNumber( JsonToString( JsonGet( pJson, 'pStrictErrorHandling' ) ) );\r\n\r\n### Get the parameters that differ from the default\r\npDiffer = JsonDiff( pDefaultParameters, pJson );\r\nnSize = JsonSize( pDiffer );\r\nWHILE( nSize > 0 );\r\n nSize = nSize - 1;\r\n pDiffer = JsonReplace( pDiffer, '/'|NumberToString( nSize )|'/op', '\"add\"' );\r\nEND;\r\npJson = JsonPatch( '{}', pDiffer );\r\n\r\n### LogOutput parameters\r\nsMessages = JsonAdd( sMessages, '/Info/-', pJson );\r\nIF( pLogOutput = 1 );\r\n LogOutput('INFO', JsonToString( sMessages, '/Info/0', 0, ' ' ) );\r\nENDIF;\r\n\r\n#EndRegion - Process Parameters\r\n#################################################################################################\r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\n## Validate the Cube parameter\r\nIf( TRIM(pCube) @= '' );\r\n sMessage = 'A cube name must be provided.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# If specified cube exists and recreate option not set to true then terminate process\r\nIf( CubeExists( pCube ) = 1 );\r\n If( pRecreate <> 1 );\r\n sMessage = Expand( 'Cube %pCube% already exists. Aborting cube create.' );\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\nEndIf;\r\n\r\n# Check the delimiter\r\nIf( cDelimDim @= '' );\r\n cDelimDim = '&';\r\nEndIf;\r\n\r\n# Check the dimension list can't be empty\r\nIf( pDims @= '' );\r\n sMessage = 'The dimension list is blank.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Check the dimension list must contain delimiter\r\nIf( Scan( cDelimDim, pDims ) < 2 );\r\n sMessage = 'The dimension list must contain at least 2 dimension names separated by the delimiter.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n### Initialise the dimension variables ###\r\nsDim01 = '';\r\nsDim02 = '';\r\nsDim03 = '';\r\nsDim04 = '';\r\nsDim05 = '';\r\nsDim06 = '';\r\nsDim07 = '';\r\nsDim08 = '';\r\nsDim09 = '';\r\nsDim10 = '';\r\nsDim11 = '';\r\nsDim12 = '';\r\nsDim13 = '';\r\nsDim14 = '';\r\nsDim15 = '';\r\nsDim16 = '';\r\nsDim17 = '';\r\nsDim18 = '';\r\nsDim19 = '';\r\nsDim20 = '';\r\nsDim21 = '';\r\nsDim22 = '';\r\nsDim23 = '';\r\nsDim24 = '';\r\nsDim25 = '';\r\nsDim26 = '';\r\nsDim27 = '';\r\nsDim28 = '';\r\nsDim29 = '';\r\nsDim30 = '';\r\nsDim31 = '';\r\nsDim32 = '';\r\nsDim33 = '';\r\nsDim34 = '';\r\nsDim35 = '';\r\nsDim36 = '';\r\nsDim37 = '';\r\nsDim38 = '';\r\nsDim39 = '';\r\nsDim40 = '';\r\nsDim41 = '';\r\nsDim42 = '';\r\nsDim43 = '';\r\nsDim44 = '';\r\nsDim45 = '';\r\nsDim46 = '';\r\nsDim47 = '';\r\nsDim48 = '';\r\nsDim49 = '';\r\nsDim50 = '';\r\nsDim51 = '';\r\nsDim52 = '';\r\nsDim53 = '';\r\nsDim54 = '';\r\nsDim55 = '';\r\nsDim56 = '';\r\nsDim57 = '';\r\nsDim58 = '';\r\nsDim59 = '';\r\nsDim60 = '';\r\nsDim61 = '';\r\nsDim62 = '';\r\nsDim63 = '';\r\nsDim64 = '';\r\nsDim65 = '';\r\nsDim66 = '';\r\nsDim67 = '';\r\nsDim68 = '';\r\nsDim69 = '';\r\nsDim70 = '';\r\nsDim71 = '';\r\nsDim72 = '';\r\nsDim73 = '';\r\nsDim74 = '';\r\nsDim75 = '';\r\nsDim76 = '';\r\nsDim77 = '';\r\nsDim78 = '';\r\nsDim79 = '';\r\nsDim80 = '';\r\nsDim81 = '';\r\nsDim82 = '';\r\nsDim83 = '';\r\nsDim84 = '';\r\nsDim85 = '';\r\nsDim86 = '';\r\nsDim87 = '';\r\nsDim88 = '';\r\nsDim89 = '';\r\nsDim90 = '';\r\nsDim91 = '';\r\nsDim92 = '';\r\nsDim93 = '';\r\nsDim94 = '';\r\nsDim95 = '';\r\nsDim96 = '';\r\nsDim97 = '';\r\nsDim98 = '';\r\nsDim99 = '';\r\nsDim100 = '';\r\n\r\n### Split delimited dimension list and count number of dimensions ###\r\nsDims = TRIM( pDims );\r\nnDelimIndex = 1;\r\n\r\nWhile( nDelimIndex > 0 & Long( sDims ) > 0 );\r\n\r\n nDelimIndex = Scan( cDelimDim, sDims );\r\n If( nDelimIndex > 0 );\r\n sDim = Trim( SubSt( sDims, 1, nDelimIndex - 1 ) );\r\n sDims = Trim( SubSt( sDims, nDelimIndex + Long( cDelimDim ), Long( sDims ) ) );\r\n Else;\r\n sDim = Trim( sDims );\r\n EndIf;\r\n\r\n If( DimensionExists( sDim ) = 1 );\r\n # sDim recognized as a dimension, increment the dim counter and set the dim name variable (how we wish Expand worked on the LHS of = ...)\r\n nDims = nDims + 1;\r\n If( nDims > nDimMax );\r\n sMessage = 'Maximum number of dimensions exceeded. Aborting';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\n If( nDims = 1 );\r\n sDim01 = sDim;\r\n ElseIf( nDims = 2 );\r\n sDim02 = sDim;\r\n ElseIf( nDims = 3 );\r\n sDim03 = sDim;\r\n ElseIf( nDims = 4 );\r\n sDim04 = sDim;\r\n ElseIf( nDims = 5 );\r\n sDim05 = sDim;\r\n ElseIf( nDims = 6 );\r\n sDim06 = sDim;\r\n ElseIf( nDims = 7 );\r\n sDim07 = sDim;\r\n ElseIf( nDims = 8 );\r\n sDim08 = sDim;\r\n ElseIf( nDims = 9 );\r\n sDim09 = sDim;\r\n ElseIf( nDims = 10 );\r\n sDim10 = sDim;\r\n ElseIf( nDims = 11 );\r\n sDim11 = sDim;\r\n ElseIf( nDims = 12 );\r\n sDim12 = sDim;\r\n ElseIf( nDims = 13 );\r\n sDim13 = sDim;\r\n ElseIf( nDims = 14 );\r\n sDim14 = sDim;\r\n ElseIf( nDims = 15 );\r\n sDim15 = sDim;\r\n ElseIf( nDims = 16 );\r\n sDim16 = sDim;\r\n ElseIf( nDims = 17 );\r\n sDim17 = sDim;\r\n ElseIf( nDims = 18 );\r\n sDim18 = sDim;\r\n ElseIf( nDims = 19 );\r\n sDim19 = sDim;\r\n ElseIf( nDims = 20 );\r\n sDim20 = sDim;\r\n ElseIf( nDims = 21 );\r\n sDim21 = sDim;\r\n ElseIf( nDims = 22 );\r\n sDim22 = sDim;\r\n ElseIf( nDims = 23 );\r\n sDim23 = sDim;\r\n ElseIf( nDims = 24 );\r\n sDim24 = sDim;\r\n ElseIf( nDims = 25 );\r\n sDim25 = sDim;\r\n ElseIf( nDims = 26 );\r\n sDim26 = sDim;\r\n ElseIf( nDims = 27 );\r\n sDim27 = sDim;\r\n ElseIf( nDims = 28 );\r\n sDim28 = sDim;\r\n ElseIf( nDims = 29 );\r\n sDim29 = sDim;\r\n ElseIf( nDims = 30 );\r\n sDim30 = sDim;\r\n ElseIf( nDims = 31 );\r\n sDim31 = sDim;\r\n ElseIf( nDims = 32 );\r\n sDim32 = sDim;\r\n ElseIf( nDims = 33 );\r\n sDim33 = sDim;\r\n ElseIf( nDims = 34 );\r\n sDim34 = sDim;\r\n ElseIf( nDims = 35 );\r\n sDim35 = sDim;\r\n ElseIf( nDims = 36 );\r\n sDim36 = sDim;\r\n ElseIf( nDims = 37 );\r\n sDim37 = sDim;\r\n ElseIf( nDims = 38 );\r\n sDim38 = sDim;\r\n ElseIf( nDims = 39 );\r\n sDim39 = sDim;\r\n ElseIf( nDims = 40 );\r\n sDim40 = sDim;\r\n ElseIf( nDims = 41 );\r\n sDim41 = sDim;\r\n ElseIf( nDims = 42 );\r\n sDim42 = sDim;\r\n ElseIf( nDims = 43 );\r\n sDim43 = sDim;\r\n ElseIf( nDims = 44 );\r\n sDim44 = sDim;\r\n ElseIf( nDims = 45 );\r\n sDim45 = sDim;\r\n ElseIf( nDims = 46 );\r\n sDim46 = sDim;\r\n ElseIf( nDims = 47 );\r\n sDim47 = sDim;\r\n ElseIf( nDims = 48 );\r\n sDim48 = sDim;\r\n ElseIf( nDims = 49 );\r\n sDim49 = sDim;\r\n ElseIf( nDims = 50 );\r\n sDim50 = sDim;\r\n ElseIf( nDims = 51 );\r\n sDim51 = sDim;\r\n ElseIf( nDims = 52 );\r\n sDim52 = sDim;\r\n ElseIf( nDims = 53 );\r\n sDim53 = sDim;\r\n ElseIf( nDims = 54 );\r\n sDim54 = sDim;\r\n ElseIf( nDims = 55 );\r\n sDim55 = sDim;\r\n ElseIf( nDims = 56 );\r\n sDim56 = sDim;\r\n ElseIf( nDims = 57 );\r\n sDim57 = sDim;\r\n ElseIf( nDims = 58 );\r\n sDim58 = sDim;\r\n ElseIf( nDims = 59 );\r\n sDim59 = sDim;\r\n ElseIf( nDims = 60 );\r\n sDim60 = sDim;\r\n ElseIf( nDims = 61 );\r\n sDim61 = sDim;\r\n ElseIf( nDims = 62 );\r\n sDim62 = sDim;\r\n ElseIf( nDims = 63 );\r\n sDim63 = sDim;\r\n ElseIf( nDims = 64 );\r\n sDim64 = sDim;\r\n ElseIf( nDims = 65 );\r\n sDim65 = sDim;\r\n ElseIf( nDims = 66 );\r\n sDim66 = sDim;\r\n ElseIf( nDims = 67 );\r\n sDim67 = sDim;\r\n ElseIf( nDims = 68 );\r\n sDim68 = sDim;\r\n ElseIf( nDims = 69 );\r\n sDim69 = sDim;\r\n ElseIf( nDims = 70 );\r\n sDim70 = sDim;\r\n ElseIf( nDims = 71 );\r\n sDim71 = sDim;\r\n ElseIf( nDims = 72 );\r\n sDim72 = sDim;\r\n ElseIf( nDims = 73 );\r\n sDim73 = sDim;\r\n ElseIf( nDims = 74 );\r\n sDim74 = sDim;\r\n ElseIf( nDims = 75 );\r\n sDim75 = sDim;\r\n ElseIf( nDims = 76 );\r\n sDim76 = sDim;\r\n ElseIf( nDims = 77 );\r\n sDim77 = sDim;\r\n ElseIf( nDims = 78 );\r\n sDim78 = sDim;\r\n ElseIf( nDims = 79 );\r\n sDim79 = sDim;\r\n ElseIf( nDims = 80 );\r\n sDim80 = sDim;\r\n ElseIf( nDims = 81 );\r\n sDim81 = sDim;\r\n ElseIf( nDims = 82 );\r\n sDim82 = sDim;\r\n ElseIf( nDims = 83 );\r\n sDim83 = sDim;\r\n ElseIf( nDims = 84 );\r\n sDim84 = sDim;\r\n ElseIf( nDims = 85 );\r\n sDim85 = sDim;\r\n ElseIf( nDims = 86 );\r\n sDim86 = sDim;\r\n ElseIf( nDims = 87 );\r\n sDim87 = sDim;\r\n ElseIf( nDims = 88 );\r\n sDim88 = sDim;\r\n ElseIf( nDims = 89 );\r\n sDim89 = sDim;\r\n ElseIf( nDims = 90 );\r\n sDim90 = sDim;\r\n ElseIf( nDims = 91 );\r\n sDim91 = sDim;\r\n ElseIf( nDims = 92 );\r\n sDim92 = sDim;\r\n ElseIf( nDims = 93 );\r\n sDim93 = sDim;\r\n ElseIf( nDims = 94 );\r\n sDim94 = sDim;\r\n ElseIf( nDims = 95 );\r\n sDim95 = sDim;\r\n ElseIf( nDims = 96 );\r\n sDim96 = sDim;\r\n ElseIf( nDims = 97 );\r\n sDim97 = sDim;\r\n ElseIf( nDims = 98 );\r\n sDim98 = sDim;\r\n ElseIf( nDims = 99 );\r\n sDim99 = sDim;\r\n ElseIf( nDims = 100 );\r\n sDim100 = sDim;\r\n EndIf; \r\n\r\n Else;\r\n\r\n # sDim not recognized as valid dimension\r\n sMessage = Expand( '%sDim% not recognized as valid dimension.' );\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\n\r\nEnd;\r\n\r\n### Create the cube ###\r\n\r\nIf( nDims < 2 );\r\n sMessage = 'Number of dimesnions specified is less than 2';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\nIf( CubeExists( pCube ) = 1 & pRecreate = 1 );\r\n CubeDestroy( pCube );\r\nEndIf;\r\n\r\nIf( nDims = 2 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02 );\r\nElseIf( nDims = 3 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03 );\r\nElseIf( nDims = 4 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04 );\r\nElseIf( nDims = 5 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05 );\r\nElseIf( nDims = 6 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06 );\r\nElseIf( nDims = 7 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07 );\r\nElseIf( nDims = 8 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08 );\r\nElseIf( nDims = 9 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09 );\r\nElseIf( nDims = 10 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10 );\r\nElseIf( nDims = 11 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11 );\r\nElseIf( nDims = 12 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12 );\r\nElseIf( nDims = 13 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13 );\r\nElseIf( nDims = 14 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14 );\r\nElseIf( nDims = 15 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15 );\r\nElseIf( nDims = 16 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16 );\r\nElseIf( nDims = 17 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17 );\r\nElseIf( nDims = 18 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18 );\r\nElseIf( nDims = 19 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19 );\r\nElseIf( nDims = 20 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20 );\r\nElseIf( nDims = 21 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21 );\r\nElseIf( nDims = 22 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22 );\r\nElseIf( nDims = 23 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23 );\r\nElseIf( nDims = 24 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24 );\r\nElseIf( nDims = 25 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25 );\r\nElseIf( nDims = 26 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26 );\r\nElseIf( nDims = 27 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27 );\r\nElseIf( nDims = 28 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28 );\r\nElseIf( nDims = 29 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29 );\r\nElseIf( nDims = 30 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30 );\r\nElseIf( nDims = 31 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31 );\r\nElseIf( nDims = 32 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32 );\r\nElseIf( nDims = 33 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33 );\r\nElseIf( nDims = 34 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34 );\r\nElseIf( nDims = 35 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35 );\r\nElseIf( nDims = 36 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36 );\r\nElseIf( nDims = 37 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37 );\r\nElseIf( nDims = 38 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38 );\r\nElseIf( nDims = 39 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39 );\r\nElseIf( nDims = 40 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40 );\r\nElseIf( nDims = 41 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41 );\r\nElseIf( nDims = 42 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42 );\r\nElseIf( nDims = 43 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43 );\r\nElseIf( nDims = 44 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44 );\r\nElseIf( nDims = 45 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45 );\r\nElseIf( nDims = 46 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46 );\r\nElseIf( nDims = 47 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47 );\r\nElseIf( nDims = 48 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48 );\r\nElseIf( nDims = 49 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49 );\r\nElseIf( nDims = 50 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50 );\r\nElseIf( nDims = 51 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51 );\r\nElseIf( nDims = 52 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52 );\r\nElseIf( nDims = 53 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53 );\r\nElseIf( nDims = 54 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54 );\r\nElseIf( nDims = 55 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55 );\r\nElseIf( nDims = 56 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56 );\r\nElseIf( nDims = 57 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57 );\r\nElseIf( nDims = 58 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58 );\r\nElseIf( nDims = 59 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59 );\r\nElseIf( nDims = 60 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60 );\r\nElseIf( nDims = 61 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61 );\r\nElseIf( nDims = 62 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62 );\r\nElseIf( nDims = 63 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63 );\r\nElseIf( nDims = 64 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64 );\r\nElseIf( nDims = 65 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65 );\r\nElseIf( nDims = 66 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66 );\r\nElseIf( nDims = 67 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67 );\r\nElseIf( nDims = 68 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68 );\r\nElseIf( nDims = 69 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69 );\r\nElseIf( nDims = 70 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70 );\r\nElseIf( nDims = 71 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71 );\r\nElseIf( nDims = 72 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72 );\r\nElseIf( nDims = 73 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73 );\r\nElseIf( nDims = 74 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74 );\r\nElseIf( nDims = 75 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75 );\r\nElseIf( nDims = 76 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76 );\r\nElseIf( nDims = 77 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77 );\r\nElseIf( nDims = 78 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78 );\r\nElseIf( nDims = 79 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79 );\r\nElseIf( nDims = 80 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80 );\r\nElseIf( nDims = 81 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81 );\r\nElseIf( nDims = 82 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81, sDim82 );\r\nElseIf( nDims = 83 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81, sDim82, sDim83 );\r\nElseIf( nDims = 84 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81, sDim82, sDim83, sDim84 );\r\nElseIf( nDims = 85 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81, sDim82, sDim83, sDim84, sDim85 );\r\nElseIf( nDims = 86 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81, sDim82, sDim83, sDim84, sDim85, sDim86 );\r\nElseIf( nDims = 87 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81, sDim82, sDim83, sDim84, sDim85, sDim86, sDim87 );\r\nElseIf( nDims = 88 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81, sDim82, sDim83, sDim84, sDim85, sDim86, sDim87, sDim88 );\r\nElseIf( nDims = 89 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81, sDim82, sDim83, sDim84, sDim85, sDim86, sDim87, sDim88, sDim89 );\r\nElseIf( nDims = 90 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81, sDim82, sDim83, sDim84, sDim85, sDim86, sDim87, sDim88, sDim89, sDim90 );\r\nElseIf( nDims = 91 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81, sDim82, sDim83, sDim84, sDim85, sDim86, sDim87, sDim88, sDim89, sDim90, sDim91 );\r\nElseIf( nDims = 92 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81, sDim82, sDim83, sDim84, sDim85, sDim86, sDim87, sDim88, sDim89, sDim90, sDim91, sDim92 );\r\nElseIf( nDims = 93 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81, sDim82, sDim83, sDim84, sDim85, sDim86, sDim87, sDim88, sDim89, sDim90, sDim91, sDim92, sDim93 );\r\nElseIf( nDims = 94 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81, sDim82, sDim83, sDim84, sDim85, sDim86, sDim87, sDim88, sDim89, sDim90, sDim91, sDim92, sDim93, sDim94 );\r\nElseIf( nDims = 95 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81, sDim82, sDim83, sDim84, sDim85, sDim86, sDim87, sDim88, sDim89, sDim90, sDim91, sDim92, sDim93, sDim94, sDim95 );\r\nElseIf( nDims = 96 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81, sDim82, sDim83, sDim84, sDim85, sDim86, sDim87, sDim88, sDim89, sDim90, sDim91, sDim92, sDim93, sDim94, sDim95, sDim96 );\r\nElseIf( nDims = 97 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81, sDim82, sDim83, sDim84, sDim85, sDim86, sDim87, sDim88, sDim89, sDim90, sDim91, sDim92, sDim93, sDim94, sDim95, sDim96, sDim97 );\r\nElseIf( nDims = 98 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81, sDim82, sDim83, sDim84, sDim85, sDim86, sDim87, sDim88, sDim89, sDim90, sDim91, sDim92, sDim93, sDim94, sDim95, sDim96, sDim97, sDim98 );\r\nElseIf( nDims = 99 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81, sDim82, sDim83, sDim84, sDim85, sDim86, sDim87, sDim88, sDim89, sDim90, sDim91, sDim92, sDim93, sDim94, sDim95, sDim96, sDim97, sDim98, sDim99 );\r\nElseIf( nDims = 100 );\r\n CubeCreate( Trim( pCube ), sDim01, sDim02, sDim03, sDim04, sDim05, sDim06, sDim07, sDim08, sDim09, sDim10, sDim11, sDim12, sDim13, sDim14, sDim15, sDim16, sDim17, sDim18, sDim19, sDim20, sDim21, sDim22, sDim23, sDim24, sDim25, sDim26, sDim27, sDim28, sDim29, sDim30, sDim31, sDim32, sDim33, sDim34, sDim35, sDim36, sDim37, sDim38, sDim39, sDim40, sDim41, sDim42, sDim43, sDim44, sDim45, sDim46, sDim47, sDim48, sDim49, sDim50, sDim51, sDim52, sDim53, sDim54, sDim55, sDim56, sDim57, sDim58, sDim59, sDim60, sDim61, sDim62, sDim63, sDim64, sDim65, sDim66, sDim67, sDim68, sDim69, sDim70, sDim71, sDim72, sDim73, sDim74, sDim75, sDim76, sDim77, sDim78, sDim79, sDim80, sDim81, sDim82, sDim83, sDim84, sDim85, sDim86, sDim87, sDim88, sDim89, sDim90, sDim91, sDim92, sDim93, sDim94, sDim95, sDim96, sDim97, sDim98, sDim99, sDim100 );\r\nEndIf;\r\n\r\n", "MetadataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "DataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "EpilogProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n### Return code & final error message handling\r\nIf( nErrors > 0 );\r\n sMessage = 'the process incurred at least 1 error. Please see above lines in this file for more details.';\r\n nProcessReturnCode = 0;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% Process:%cThisProcName% completed with errors. Check tm1server.log for details.' );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n EndIf;\r\nElse;\r\n sProcessAction = Expand( 'Process:%cThisProcName% successfully created %pCube% with %pDims%.' );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% %sProcessAction%' );\r\n nProcessReturnCode = 1;\r\n If( pLogOutput = 1 );\r\n LogOutput('INFO', Expand( sProcessAction) );\r\n EndIf;\r\nEndIf;\r\n\r\n### End Epilog ###\r\n\r\n\r\n\r\n\r\n", @@ -10,41 +10,47 @@ "Type": "None" }, "Parameters": [ - { - "Name": "pLogOutput", - "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, - { - "Name": "pStrictErrorHandling", - "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, { "Name": "pCube", - "Prompt": "REQUIRED: Cube Name", + "Prompt": "REQUIRED: Cube name", "Value": "", "Type": "String" }, { "Name": "pDims", - "Prompt": "REQUIRED: Dim1 & Dim2 & Dim3 & Dim4 & Dim5", + "Prompt": "REQUIRED: Delimited dimension list. E.g. dim_one & dim_two & dim_three & dim_four & dim_five", "Value": "", "Type": "String" }, { "Name": "pRecreate", - "Prompt": "OPTIONAL: If cube exists delete and recreate (Default=0)", + "Prompt": "OPTIONAL: If target objects exists, delete and recreate (Default = 0)", "Value": 0, "Type": "Numeric" }, { "Name": "pDelim", - "Prompt": "OPTIONAL: Delimiter for Dimension list (default value if blank = '&')", + "Prompt": "OPTIONAL: Delimiter for list parameters (Default = '&')", "Value": "&", "Type": "String" + }, + { + "Name": "pLogOutput", + "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pStrictErrorHandling", + "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pJson", + "Prompt": "OPTIONAL: JSON Object with process parameter values. This will overwrite user passed parameters for all included parameters.", + "Value": "{}", + "Type": "String" } ], "Variables": [], diff --git a/bedrock_processes_json/}bedrock.cube.data.clear.json b/bedrock_processes_json/}bedrock.cube.data.clear.json index 2923f11..8fb1ac9 100644 --- a/bedrock_processes_json/}bedrock.cube.data.clear.json +++ b/bedrock_processes_json/}bedrock.cube.data.clear.json @@ -1,6 +1,6 @@ { "Name": "}bedrock.cube.data.clear", - "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.data.clear', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pCube', '', 'pView', '', 'pFilter', '',\r\n \t'pFilterParallel', '', 'pParallelThreads', 0,\r\n \t'pDimDelim', '&', 'pEleStartDelim', '\u00a6', 'pEleDelim', '+', 'pSuppressConsolStrings', 0, \r\n \t'pCubeLogging', 0, 'pTemp', 1, 'pSandbox', pSandbox, 'pSubN', 0\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process could be used extensively by custom TIs in production to clear certain data out of a cube before copying data to that cube.\r\n\r\n# Use case: Primarily for production systems.\r\n# 1/ In production system this is a \"workhorse\" process called from the prolog of most custom processes prior to querying a data source to refresh cube data.\r\n# 2/ During development/prototyping can be run manually to clear out a portion of a cube.\r\n\r\n# Note:\r\n# Wildcards can be used or a list of cubes specified to clear data out of multiple cubes simultaneouly. \r\n# If no cube (pCube) or an invalid cube is specified, the process will abort.\r\n# CAUTION: If no view (pView) or filter (pFilter) is specified, the entire cube(s) will be cleared out.\r\n# If a valid view is specified the process will simply zero out that view and ignore any filter (pFilter) specified.\r\n# If no valid view is specified then a temporary view will be built using the filter and its data deleted.\r\n# The filter can handle specific element references for any number of dimensions and elements.\r\n# - The pFilter parameter contains the dimension and elements to be used for filtering.\r\n# - The dimension parameters do not need to be given in the index order of dimensions in the cube.\r\n# - The dimension name is specified as the first member of the delimited string of elements.\r\n# If using the pFilterParallel parameter the **single dimension** used as the \"parallelization slicer\" cannot appear in\r\n# the pFilter parameters.\r\n# When using parallelization via the *RunProcess* function the elements listed in pFilterParallel will be split one_at_a_time\r\n# and passed to a recursive call of the process being added to pFilter.\r\n#EndRegion @DOC\r\n\r\n### Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent= 'Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pCube:%pCube%, pView:%pView%, pFilter:%pFilter%, pFilterParallel:%pFilterParallel%, pParallelThreads:%pParallelThreads%, pDimDelim:%pDimDelim%, pEleStartDelim:%pEleStartDelim%, pEleDelim:%pEleDelim%, pSuppressConsolStrings:%pSuppressConsolStrings%, pCubeLogging:%pCubeLogging%, pTemp:%pTemp%, pSandbox:%pSandbox%'; \r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncDefaultView = Expand( '%cThisProcName%_%cTimeStamp%_%cRandomInt%' );\r\ncTempSub = cDefaultView | '_Temp';\r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\n# Trim delimiters\r\nsDelimDim = TRIM(pDimDelim);\r\nsElementStartDelim = TRIM(pEleStartDelim);\r\nsDelimElem = TRIM(pEleDelim);\r\n\r\n### Validate Parameters ###\r\nnErrors = 0;\r\n\r\n## Default filter delimiters\r\nIf( pDimDelim @= '' );\r\n pDimDelim = '&';\r\nEndIf;\r\nIf( pEleStartDelim@= '' );\r\n pEleStartDelim= '\u00a6';\r\nEndIf;\r\nIf( pEleDelim @= '' );\r\n pEleDelim = '+';\r\nEndIf;\r\n\r\n# Check the delimiters\r\nIf( Trim( pFilter ) @<> '' );\r\n If( sDelimDim @= sElementStartDelim % sDelimDim @= sDelimElem % sElementStartDelim @= sDelimElem );\r\n sMessage = 'The delimiters cannot be the same.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\nEndIf; \r\n\r\n# consolidated strings\r\nIf( pSuppressConsolStrings <> 0 );\r\n pSuppressConsolStrings = 1;\r\nEndIf;\r\n\r\n# Validate cubelogging parameter\r\nIf( pCubeLogging <> 0 & pCubeLogging <> 1 & pCubeLogging <> 2);\r\n sMessage = 'The cube logging parameter incorrect';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# If no cube has been specified then terminate process\r\nIf( Trim( pCube ) @= '' );\r\n sMessage = 'No cube(s) specified.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate parallelization filter\r\nIf( Scan( pEleStartDelim, pFilterParallel ) > 0 );\r\n sDimParallel = SubSt( pFilterParallel, 1, Scan( pEleStartDelim, pFilterParallel ) - 1 );\r\n If( Scan( Lower(sDimParallel) | pEleStartDelim, Lower(pFilter) ) > 0 );\r\n sMessage = 'Parallelization dimension %sDimParallel% cannot exist in filter.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\nEndIf;\r\n\r\n# Validate Max Threads\r\nIf( pParallelThreads >= 1 );\r\n nMaxThreads = Round(pParallelThreads);\r\nElse;\r\n # Single thread mode\r\n nMaxThreads = 1;\r\nEndIf;\r\n\r\n# Validate Sandbox\r\nIf( TRIM( pSandbox ) @<> '' );\r\n If( ServerSandboxExists( pSandbox ) = 0 );\r\n SetUseActiveSandboxProperty( 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand('Sandbox %pSandbox% is invalid for the current user.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n Else;\r\n ServerActiveSandboxSet( pSandbox );\r\n SetUseActiveSandboxProperty( 1 );\r\n EndIf;\r\nElse;\r\n SetUseActiveSandboxProperty( 0 );\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n# Loop through cubes in pCube\r\nsCubes = pCube;\r\nnCubeDelimiterIndex = 1;\r\n# Get 1st cube\r\nWhile( nCubeDelimiterIndex <> 0 );\r\n\r\n # Extract 1st cube > sCube\r\n nCubeDelimiterIndex = Scan( pDimDelim, sCubes );\r\n If( nCubeDelimiterIndex = 0 );\r\n sCube = sCubes;\r\n Else;\r\n sCube = Trim( SubSt( sCubes, 1, nCubeDelimiterIndex - 1 ) );\r\n sCubes = Trim( Subst( sCubes, nCubeDelimiterIndex + Long(pDimDelim), Long( sCubes ) ) );\r\n EndIf;\r\n \r\n bParallel = 0;\r\n \r\n # Check if sCube has wildcard\r\n If( Scan( '*', sCube ) = 0);\r\n # Validate cube\r\n If( CubeExists(sCube) = 0 );\r\n nErrors = 1;\r\n sMessage = Expand( 'Cube %sCube% does not exist.' );\r\n LogOutput( 'ERROR', Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n Else;\r\n If( Scan( pEleStartDelim, pFilterParallel ) > 0 );\r\n nDim = 1;\r\n sDim = TABDIM( sCube, nDim);\r\n While ( sDim @<> '' );\r\n sDim = TABDIM( sCube, nDim);\r\n If ( sDim @= sDimParallel );\r\n bParallel = 1;\r\n sDim = '';\r\n EndIf;\r\n nDim = nDim + 1;\r\n End;\r\n EndIf;\r\n If( bParallel = 1 );\r\n sDimParallel = SubSt( pFilterParallel, 1, Scan( pEleStartDelim, pFilterParallel ) - 1 );\r\n sElementList = SubSt( pFilterParallel, Scan( pEleStartDelim, pFilterParallel ) + 1, Long( pFilterParallel ) );\r\n If( SubSt( sElementList, Long( sElementList ), 1 ) @<> pEleDelim );\r\n sElementList = sElementList | pEleDelim;\r\n EndIf;\r\n ## Counting elements in element list\r\n sElementListCount = sElementList;\r\n nElements = 0;\r\n While( Scan( pEleDelim, sElementListCount ) > 0 );\r\n nElements = nElements + 1;\r\n sElementListCount = SubSt( sElementListCount, Scan( pEleDelim, sElementListCount ) + 1, Long( sElementListCount ) );\r\n End;\r\n IF( Mod( nElements, nMaxThreads ) = 0 );\r\n nElemsPerThread = INT( nElements / nMaxThreads );\r\n ELSE;\r\n nElemsPerThread = INT( nElements / nMaxThreads ) + 1;\r\n ENDIF;\r\n nThreadElCounter = 0;\r\n While( Scan( pEleDelim, sElementList ) > 0 );\r\n sSlicerEle = SubSt( sElementList, 1, Scan( pEleDelim, sElementList ) - 1 );\r\n sElementList = SubSt( sElementList, Scan( pEleDelim, sElementList ) + 1, Long( sElementList ) );\r\n # Do recursive process call with new RunProcess function\r\n nThreadElCounter = nThreadElCounter + 1;\r\n sDimDelim = If(pFilter @= '', '', pDimDelim );\r\n IF( nThreadElCounter = 1 );\r\n sFilter = Expand('%pFilter%%sDimDelim%%sDimParallel%%pEleStartDelim%%sSlicerEle%');\r\n ELSE;\r\n sFilter = Expand('%sFilter%%pEleDelim%%sSlicerEle%');\r\n ENDIF;\r\n IF( nThreadElCounter >= nElemsPerThread );\r\n RunProcess( cThisProcName, 'pLogoutput', pLogoutput,\r\n \t 'pCube', pCube, 'pView', pView, 'pFilter', sFilter, 'pFilterParallel', '', \r\n \t 'pDimDelim', pDimDelim, 'pEleStartDelim', pEleStartDelim, 'pEleDelim', pEleDelim, \r\n \t 'pSuppressConsolStrings', pSuppressConsolStrings, 'pCubeLogging', pCubeLogging, 'pTemp', pTemp, 'pSandbox', pSandbox\r\n \t );\r\n \t nThreadElCounter = 0;\r\n \t sFilter = '';\r\n \t ENDIF;\r\n End;\r\n ## Process last elements - only when filter is not empty (there are still elements) otherwise the entire cube is emptied\r\n IF( sFilter @<> '' );\r\n RunProcess( cThisProcName, 'pLogoutput', pLogoutput,\r\n \t 'pCube', pCube, 'pView', pView, 'pFilter', sFilter, 'pFilterParallel', '', \r\n \t 'pDimDelim', pDimDelim, 'pEleStartDelim', pEleStartDelim, 'pEleDelim', pEleDelim, \r\n \t 'pSuppressConsolStrings', pSuppressConsolStrings, 'pCubeLogging', pCubeLogging, 'pTemp', pTemp, 'pSandbox', pSandbox\r\n \t );\r\n \t ENDIF;\r\n Else;\r\n ## Validate the View & filter parameter\r\n If( Trim( pView ) @= '' & Trim( pFilter ) @= '' & Trim( pSandbox ) @= '' );\r\n sMessage = Expand('No view OR filter specified so the entire %sCube% cube has been cleared.');\r\n\t IF( pLogoutput = 1 );\r\n \tLogOutput( 'INFO' , Expand( 'Process:%cThisProcName% Message:%sMessage%' ) );\r\n\t ENDIF;\r\n CubeClearData( sCube );\r\n Else;\r\n # Use different view/subset for different cubes\r\n sTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\n sRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\n cDefaultView = Expand( '%cThisProcName%_%sTimeStamp%_%sRandomInt%' );\r\n #cTempSub = cDefaultView;\r\n \r\n If( Trim( pView ) @= '' );\r\n cView = cDefaultView ;\r\n Else;\r\n cView = Trim( pView );\r\n EndIf;\r\n \r\n # Clear view\r\n If( ViewExists( sCube , cView ) = 0 );\r\n ## Validate that a Filter has been provided so that a view can be created.\r\n If( Trim( pFilter ) @= '' );\r\n sMessage = Expand('View %cView% does not exist in the %sCube% cube AND no Filter has not been specified in order to create a view.');\r\n LogOutput( 'INFO' , Expand( cMsgErrorContent ) );\r\n #ProcessBreak;\r\n EndIf;\r\n\r\n ### Create View using filter (temp view, therefore no need to destroy) ###\r\n sProc = '}bedrock.cube.view.create';\r\n nRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', sCube, 'pView', cView, 'pFilter', pFilter,\r\n 'pSuppressZero', 1, 'pSuppressConsol', 1, 'pSuppressRules', 1, 'pSuppressConsolStrings', pSuppressConsolStrings,\r\n 'pDimDelim', pDimDelim, 'pEleStartDelim', pEleStartDelim, 'pEleDelim', pEleDelim,\r\n 'pTemp', pTemp, 'pSubN', pSubN\r\n );\r\n\r\n # Validate Sandbox\r\n If( TRIM( pSandbox ) @<> '' );\r\n If( ServerSandboxExists( pSandbox ) = 0 );\r\n SetUseActiveSandboxProperty( 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand('Sandbox %pSandbox% is invalid for the current user.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n Else;\r\n ServerActiveSandboxSet( pSandbox );\r\n SetUseActiveSandboxProperty( 1 );\r\n EndIf;\r\n Else;\r\n SetUseActiveSandboxProperty( 0 );\r\n EndIf;\r\n\r\n ### Zero Out View ###\r\n If ( nRet = ProcessExitNormal() );\r\n ViewZeroOut( sCube, cView );\r\n sMessage = Expand( 'Succeeded in creating the %cView% view in the %sCube% cube and data has been cleared.' );\r\n \t If( pLogoutput = 1 );\r\n \tLogOutput( 'INFO', Expand( 'Process:%cThisProcName% Message:%sMessage%' ) );\r\n \t EndIf;\r\n Else;\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'Creating view by %sProc% has failed. Nothing has been cleared in the %sCube% cube.' );\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\n Else;\r\n ViewZeroOut( sCube, cView );\r\n Endif;\r\n Endif;\r\n EndIf;\r\n Endif;\r\n Else;\r\n # Create subset of cubes using Wildcard to loop through cubes in pCube with wildcard\r\n sCubeExp = '\"'|sCube|'\"';\r\n sMdx = '{TM1FILTERBYPATTERN( {TM1SUBSETALL( [}Cubes] )},'|sCubeExp| ')}';\r\n If( SubsetExists( '}Cubes' , cTempSub ) = 1 );\r\n # If a delimited list of cube names includes wildcards then we may have to re-use the subset multiple times\r\n SubsetMDXSet( '}Cubes' , cTempSub, sMDX );\r\n Else;\r\n # temp subset, therefore no need to destroy in epilog\r\n SubsetCreatebyMDX( cTempSub, sMDX, '}Cubes' , 1 );\r\n EndIf;\r\n \r\n # Loop through cubes in subset created based on wildcard\r\n nCountCube = SubsetGetSize( '}Cubes' , cTempSub );\r\n While( nCountCube >= 1 );\r\n # Use different view/subset for different cubes\r\n sTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\n sRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\n cDefaultView = Expand( '%cThisProcName%_%sTimeStamp%_%sRandomInt%' );\r\n sCube = SubsetGetElementName( '}Cubes' , cTempSub, nCountCube );\r\n # Validate cube name Not necessary as derived from subset of }Cubes\r\n If( CubeExists(sCube) = 0 );\r\n nErrors = 1;\r\n sMessage = Expand( '%sCube% does not exist.' );\r\n LogOutput( 'ERROR', Expand( cMsgErrorContent ) );\r\n Else;\r\n If( Scan( pEleStartDelim, pFilterParallel ) > 0 );\r\n nDim = 1;\r\n sDim = TABDIM( sCube, nDim);\r\n While ( sDim @<> '' );\r\n sDim = TABDIM( sCube, nDim);\r\n If ( sDim @= sDimParallel );\r\n bParallel = 1;\r\n sDim = '';\r\n EndIf;\r\n nDim = nDim + 1;\r\n End;\r\n EndIf;\r\n If( bParallel = 1 );\r\n sDimParallel = SubSt( pFilterParallel, 1, Scan( pEleStartDelim, pFilterParallel ) - 1 );\r\n sElementList = SubSt( pFilterParallel, Scan( pEleStartDelim, pFilterParallel ) + 1, Long( pFilterParallel ) );\r\n If( SubSt( sElementList, Long( sElementList ), 1 ) @<> pEleDelim );\r\n sElementList = sElementList | pEleDelim;\r\n EndIf;\r\n ## Counting elements in element list\r\n sElementListCount = sElementList;\r\n nElements = 0;\r\n While( Scan( pEleDelim, sElementListCount ) > 0 );\r\n nElements = nElements + 1;\r\n sElementListCount = SubSt( sElementListCount, Scan( pEleDelim, sElementListCount ) + 1, Long( sElementListCount ) );\r\n End;\r\n IF( Mod( nElements, nMaxThreads ) = 0 );\r\n nElemsPerThread = INT( nElements / nMaxThreads );\r\n ELSE;\r\n nElemsPerThread = INT( nElements / nMaxThreads ) + 1;\r\n ENDIF;\r\n nThreadElCounter = 0;\r\n While( Scan( pEleDelim, sElementList ) > 0 );\r\n sSlicerEle = SubSt( sElementList, 1, Scan( pEleDelim, sElementList ) - 1 );\r\n sElementList = SubSt( sElementList, Scan( pEleDelim, sElementList ) + 1, Long( sElementList ) );\r\n # Do recursive process call with new RunProcess function\r\n nThreadElCounter = nThreadElCounter + 1;\r\n sDimDelim = If(pFilter @= '', '', pDimDelim );\r\n IF( nThreadElCounter = 1 );\r\n sFilter = Expand('%pFilter%%sDimDelim%%sDimParallel%%pEleStartDelim%%sSlicerEle%');\r\n ELSE;\r\n sFilter = Expand('%sFilter%%pEleDelim%%sSlicerEle%');\r\n ENDIF;\r\n IF( nThreadElCounter >= nElemsPerThread );\r\n RunProcess( cThisProcName, 'pLogoutput', pLogoutput,\r\n \t 'pCube', pCube, 'pView', pView, 'pFilter', sFilter, 'pFilterParallel', '', \r\n \t 'pDimDelim', pDimDelim, 'pEleStartDelim', pEleStartDelim, 'pEleDelim', pEleDelim, \r\n \t 'pSuppressConsolStrings', pSuppressConsolStrings, 'pCubeLogging', pCubeLogging, 'pTemp', pTemp, 'pSandbox', pSandbox\r\n \t );\r\n \t nThreadElCounter = 0;\r\n \t sFilter = '';\r\n \t ENDIF;\r\n End;\r\n ## Process last elements\r\n IF( sFilter @<> '' );\r\n RunProcess( cThisProcName, 'pLogoutput', pLogoutput,\r\n \t 'pCube', pCube, 'pView', pView, 'pFilter', sFilter, 'pFilterParallel', '', \r\n \t 'pDimDelim', pDimDelim, 'pEleStartDelim', pEleStartDelim, 'pEleDelim', pEleDelim, \r\n \t 'pSuppressConsolStrings', pSuppressConsolStrings, 'pCubeLogging', pCubeLogging, 'pTemp', pTemp, 'pSandbox', pSandbox\r\n \t );\r\n \t ENDIF;\r\n Else;\r\n ## Validate the View & filter parameter\r\n If( Trim( pView ) @= '' & Trim( pFilter ) @= '' & Trim( pSandbox ) @= '' );\r\n # Clear entire cube\r\n sMessage = Expand('No view OR filter specified so the entire %sCube% cube has been cleared.');\r\n\t IF( pLogoutput = 1 );\r\n \tLogOutput( 'INFO' , Expand( 'Process:%cThisProcName% Message:%sMessage%' ) );\r\n\t ENDIF;\r\n CubeClearData( sCube );\r\n Else;\r\n # Clear view cView\r\n If( Trim( pView ) @= '' );\r\n cView = cDefaultView ;\r\n Else;\r\n cView = Trim( pView );\r\n EndIf;\r\n \r\n If( ViewExists( sCube, cView ) = 0 );\r\n ## Validate that a Filter has been provided so that a view can be created.\r\n If( Trim( pFilter ) @= '' );\r\n sMessage = Expand('View %cView% does not exist for %sCube% AND no Filter has not been specified in order to create a view.');\r\n LogOutput( 'ERROR' , Expand( cMsgErrorContent ) );\r\n #ProcessBreak;\r\n EndIf;\r\n \r\n ### Create View using filter (temp view, therefore no need to destroy) ###\r\n sProc = '}bedrock.cube.view.create';\r\n nRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', sCube, 'pView', cView, 'pFilter', pFilter,\r\n 'pSuppressZero', 1, 'pSuppressConsol', 1, 'pSuppressRules', 1, 'pSuppressConsolStrings', pSuppressConsolStrings,\r\n 'pDimDelim', pDimDelim, 'pEleStartDelim', pEleStartDelim, 'pEleDelim', pEleDelim,\r\n 'pTemp', pTemp, 'pSubN', pSubN\r\n );\r\n \r\n # Validate Sandbox\r\n If( TRIM( pSandbox ) @<> '' );\r\n If( ServerSandboxExists( pSandbox ) = 0 );\r\n SetUseActiveSandboxProperty( 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand('Sandbox %pSandbox% is invalid for the current user.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n Else;\r\n ServerActiveSandboxSet( pSandbox );\r\n SetUseActiveSandboxProperty( 1 );\r\n EndIf;\r\n Else;\r\n SetUseActiveSandboxProperty( 0 );\r\n EndIf;\r\n \r\n \r\n ### Zero Out View ###\r\n IF ( nRet = ProcessExitNormal() );\r\n ViewZeroOut( sCube, cView );\r\n sMessage = Expand( 'Succeeded in creating the %cView% view in the %sCube% cube and data has been cleared.' );\r\n \t\tIF( pLogoutput = 1 );\r\n LogOutput( 'INFO', Expand( 'Process:%cThisProcName% Message:%sMessage%' ) );\r\n \t\tENDIF;\r\n ELSE;\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'Creating view by %sProc% has failed. Nothing has been cleared in the %sCube% cube.' );\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n ENDIF;\r\n Else;\r\n ViewZeroOut( sCube, cView );\r\n Endif;\r\n EndIf;\r\n EndIf;\r\n nCountCube = nCountCube - 1;\r\n # Use different view/subset for different cubes\r\n sTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\n sRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\n cDefaultView = Expand( '%cThisProcName%_%sTimeStamp%_%sRandomInt%' );\r\n #cTempSub = cDefaultView; \r\n EndIf;\r\n End;\r\n EndIf;\r\nEnd;\r\n\r\n### End Prolog ###", + "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.data.clear', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pCube', '', 'pView', '', 'pFilter', '',\r\n \t'pFilterParallel', '', 'pParallelThreads', 0,\r\n \t'pDimDelim', '&', 'pEleStartDelim', '\u00a6', 'pEleDelim', '+', 'pSuppressConsolStrings', 0, \r\n \t'pCubeLogging', 0, 'pTemp', 1, 'pSandbox', pSandbox, 'pSubN', 0\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process could be used extensively by custom TIs in production to clear certain data out of a cube before copying data to that cube.\r\n\r\n# Use case: Primarily for production systems.\r\n# 1/ In production system this is a \"workhorse\" process called from the prolog of most custom processes prior to querying a data source to refresh cube data.\r\n# 2/ During development/prototyping can be run manually to clear out a portion of a cube.\r\n\r\n# Note:\r\n# Wildcards can be used or a list of cubes specified to clear data out of multiple cubes simultaneouly. \r\n# If no cube (pCube) or an invalid cube is specified, the process will abort.\r\n# CAUTION: If no view (pView) or filter (pFilter) is specified, the entire cube(s) will be cleared out.\r\n# If a valid view is specified the process will simply zero out that view and ignore any filter (pFilter) specified.\r\n# If no valid view is specified then a temporary view will be built using the filter and its data deleted.\r\n# The filter can handle specific element references for any number of dimensions and elements.\r\n# - The pFilter parameter contains the dimension and elements to be used for filtering.\r\n# - The dimension parameters do not need to be given in the index order of dimensions in the cube.\r\n# - The dimension name is specified as the first member of the delimited string of elements.\r\n# If using the pFilterParallel parameter the **single dimension** used as the \"parallelization slicer\" cannot appear in\r\n# the pFilter parameters.\r\n# When using parallelization via the *RunProcess* function the elements listed in pFilterParallel will be split one_at_a_time\r\n# and passed to a recursive call of the process being added to pFilter.\r\n#EndRegion @DOC\r\n\r\n### Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent= 'Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pCube:%pCube%, pView:%pView%, pFilter:%pFilter%, pFilterParallel:%pFilterParallel%, pParallelThreads:%pParallelThreads%, pDimDelim:%pDimDelim%, pEleStartDelim:%pEleStartDelim%, pEleDelim:%pEleDelim%, pSuppressConsolStrings:%pSuppressConsolStrings%, pCubeLogging:%pCubeLogging%, pTemp:%pTemp%, pSandbox:%pSandbox%'; \r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncDefaultView = Expand( '%cThisProcName%_%cTimeStamp%_%cRandomInt%' );\r\ncTempSub = cDefaultView | '_Temp';\r\n\r\n#################################################################################################\r\n#Region - Process Parameters\r\n\r\npJson = IF( JsonType( pJson ) @<> 'object', '{}', pJson );\r\nsMessages = '{\"Process\": \"'|GetProcessName()|'\", \"User\": \"'|TM1User()|'\", \"Info\": [\"Process: '''|GetProcessName()|''' run by User: '''|TM1User()|'''.\"], \"Error\": []}';\r\npDefaultParameters = '{\r\n \"pCube\": null,\r\n \"pDimDelim\": \"&\",\r\n \"pEleDelim\": \"+\",\r\n \"pEleStartDelim\": \"\u00a6\",\r\n \"pFilter\": \"\",\r\n \"pFilterParallel\": \"\",\r\n \"pSandbox\": \"\",\r\n \"pView\": \"\",\r\n \"pLogOutput\": 0,\r\n \"pParallelThreads\": 0,\r\n \"pStrictErrorHandling\": 0,\r\n \"pSubN\": 0,\r\n \"pSuppressConsolStrings\": 1,\r\n \"pTemp\": 1\r\n}';\r\n\r\npPassedParameters = '{\r\n \"pCube\": '|StringToJson ( pCube )|',\r\n \"pDimDelim\": '|StringToJson ( pDimDelim )|',\r\n \"pEleDelim\": '|StringToJson ( pEleDelim )|',\r\n \"pEleStartDelim\": '|StringToJson ( pEleStartDelim )|',\r\n \"pFilter\": '|StringToJson ( pFilter )|',\r\n \"pFilterParallel\": '|StringToJson ( pFilterParallel )|',\r\n \"pSandbox\": '|StringToJson ( pSandbox )|',\r\n \"pView\": '|StringToJson ( pView )|',\r\n \"pLogOutput\": '|NumberToString( pLogOutput )|',\r\n \"pParallelThreads\": '|NumberToString( pParallelThreads )|',\r\n \"pStrictErrorHandling\": '|NumberToString( pStrictErrorHandling )|',\r\n \"pSubN\": '|NumberToString( pSubN )|',\r\n \"pSuppressConsolStrings\": '|NumberToString( pSuppressConsolStrings )|',\r\n \"pTemp\": '|NumberToString( pTemp )|'\r\n}';\r\n\r\npJson = JsonMergePatch( pPassedParameters, pJson );\r\n# String Parameters\r\npCube = JsonToString( JsonGet( pJson, 'pCube' ) );\r\npDimDelim = JsonToString( JsonGet( pJson, 'pDimDelim' ) );\r\npEleDelim = JsonToString( JsonGet( pJson, 'pEleDelim' ) );\r\npEleStartDelim = JsonToString( JsonGet( pJson, 'pEleStartDelim' ) );\r\npFilter = JsonToString( JsonGet( pJson, 'pFilter' ) );\r\npFilterParallel = JsonToString( JsonGet( pJson, 'pFilterParallel' ) );\r\npSandbox = JsonToString( JsonGet( pJson, 'pSandbox' ) );\r\npView = JsonToString( JsonGet( pJson, 'pView' ) );\r\n# Numeric Parameters\r\npLogOutput = StringToNumber( JsonToString( JsonGet( pJson, 'pLogOutput' ) ) );\r\npParallelThreads = StringToNumber( JsonToString( JsonGet( pJson, 'pParallelThreads' ) ) );\r\npStrictErrorHandling = StringToNumber( JsonToString( JsonGet( pJson, 'pStrictErrorHandling' ) ) );\r\npSubN = StringToNumber( JsonToString( JsonGet( pJson, 'pSubN' ) ) );\r\npSuppressConsolStrings = StringToNumber( JsonToString( JsonGet( pJson, 'pSuppressConsolStrings' ) ) );\r\npTemp = StringToNumber( JsonToString( JsonGet( pJson, 'pTemp' ) ) );\r\n\r\n### Get the parameters that differ from the default\r\npDiffer = JsonDiff( pDefaultParameters, pJson );\r\nnSize = JsonSize( pDiffer );\r\nWHILE( nSize > 0 );\r\n nSize = nSize - 1;\r\n pDiffer = JsonReplace( pDiffer, '/'|NumberToString( nSize )|'/op', '\"add\"' );\r\nEND;\r\npJson = JsonPatch( '{}', pDiffer );\r\n\r\n### LogOutput parameters\r\nsMessages = JsonAdd( sMessages, '/Info/-', pJson );\r\nIF( pLogOutput = 1 );\r\n LogOutput('INFO', JsonToString( sMessages, '/Info/0', 0, ' ' ) );\r\nENDIF;\r\n\r\n#EndRegion - Process Parameters\r\n#################################################################################################\r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\n# Trim delimiters\r\nsDelimDim = TRIM(pDimDelim);\r\nsElementStartDelim = TRIM(pEleStartDelim);\r\nsDelimElem = TRIM(pEleDelim);\r\n\r\n### Validate Parameters ###\r\nnErrors = 0;\r\n\r\n## Default filter delimiters\r\nIf( pDimDelim @= '' );\r\n pDimDelim = '&';\r\nEndIf;\r\nIf( pEleStartDelim@= '' );\r\n pEleStartDelim= '\u00a6';\r\nEndIf;\r\nIf( pEleDelim @= '' );\r\n pEleDelim = '+';\r\nEndIf;\r\n\r\n# Check the delimiters\r\nIf( Trim( pFilter ) @<> '' );\r\n If( sDelimDim @= sElementStartDelim % sDelimDim @= sDelimElem % sElementStartDelim @= sDelimElem );\r\n sMessage = 'The delimiters cannot be the same.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\nEndIf; \r\n\r\n# consolidated strings\r\nIf( pSuppressConsolStrings <> 0 );\r\n pSuppressConsolStrings = 1;\r\nEndIf;\r\n\r\n# Validate cubelogging parameter\r\nIf( pCubeLogging <> 0 & pCubeLogging <> 1 & pCubeLogging <> 2);\r\n sMessage = 'The cube logging parameter incorrect';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# If no cube has been specified then terminate process\r\nIf( Trim( pCube ) @= '' );\r\n sMessage = 'No cube(s) specified.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate parallelization filter\r\nIf( Scan( pEleStartDelim, pFilterParallel ) > 0 );\r\n sDimParallel = SubSt( pFilterParallel, 1, Scan( pEleStartDelim, pFilterParallel ) - 1 );\r\n If( Scan( Lower(sDimParallel) | pEleStartDelim, Lower(pFilter) ) > 0 );\r\n sMessage = 'Parallelization dimension %sDimParallel% cannot exist in filter.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\nEndIf;\r\n\r\n# Validate Max Threads\r\nIf( pParallelThreads >= 1 );\r\n nMaxThreads = Round(pParallelThreads);\r\nElse;\r\n # Single thread mode\r\n nMaxThreads = 1;\r\nEndIf;\r\n\r\n# Validate Sandbox\r\nIf( TRIM( pSandbox ) @<> '' );\r\n If( ServerSandboxExists( pSandbox ) = 0 );\r\n SetUseActiveSandboxProperty( 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand('Sandbox %pSandbox% is invalid for the current user.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n Else;\r\n ServerActiveSandboxSet( pSandbox );\r\n SetUseActiveSandboxProperty( 1 );\r\n EndIf;\r\nElse;\r\n SetUseActiveSandboxProperty( 0 );\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n# Loop through cubes in pCube\r\nsCubes = pCube;\r\nnCubeDelimiterIndex = 1;\r\n# Get 1st cube\r\nWhile( nCubeDelimiterIndex <> 0 );\r\n\r\n # Extract 1st cube > sCube\r\n nCubeDelimiterIndex = Scan( pDimDelim, sCubes );\r\n If( nCubeDelimiterIndex = 0 );\r\n sCube = sCubes;\r\n Else;\r\n sCube = Trim( SubSt( sCubes, 1, nCubeDelimiterIndex - 1 ) );\r\n sCubes = Trim( Subst( sCubes, nCubeDelimiterIndex + Long(pDimDelim), Long( sCubes ) ) );\r\n EndIf;\r\n \r\n bParallel = 0;\r\n \r\n # Check if sCube has wildcard\r\n If( Scan( '*', sCube ) = 0);\r\n # Validate cube\r\n If( CubeExists(sCube) = 0 );\r\n nErrors = 1;\r\n sMessage = Expand( 'Cube %sCube% does not exist.' );\r\n LogOutput( 'ERROR', Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n Else;\r\n If( Scan( pEleStartDelim, pFilterParallel ) > 0 );\r\n nDim = 1;\r\n sDim = TABDIM( sCube, nDim);\r\n While ( sDim @<> '' );\r\n sDim = TABDIM( sCube, nDim);\r\n If ( sDim @= sDimParallel );\r\n bParallel = 1;\r\n sDim = '';\r\n EndIf;\r\n nDim = nDim + 1;\r\n End;\r\n EndIf;\r\n If( bParallel = 1 );\r\n sDimParallel = SubSt( pFilterParallel, 1, Scan( pEleStartDelim, pFilterParallel ) - 1 );\r\n sElementList = SubSt( pFilterParallel, Scan( pEleStartDelim, pFilterParallel ) + 1, Long( pFilterParallel ) );\r\n If( SubSt( sElementList, Long( sElementList ), 1 ) @<> pEleDelim );\r\n sElementList = sElementList | pEleDelim;\r\n EndIf;\r\n ## Counting elements in element list\r\n sElementListCount = sElementList;\r\n nElements = 0;\r\n While( Scan( pEleDelim, sElementListCount ) > 0 );\r\n nElements = nElements + 1;\r\n sElementListCount = SubSt( sElementListCount, Scan( pEleDelim, sElementListCount ) + 1, Long( sElementListCount ) );\r\n End;\r\n IF( Mod( nElements, nMaxThreads ) = 0 );\r\n nElemsPerThread = INT( nElements / nMaxThreads );\r\n ELSE;\r\n nElemsPerThread = INT( nElements / nMaxThreads ) + 1;\r\n ENDIF;\r\n nThreadElCounter = 0;\r\n While( Scan( pEleDelim, sElementList ) > 0 );\r\n sSlicerEle = SubSt( sElementList, 1, Scan( pEleDelim, sElementList ) - 1 );\r\n sElementList = SubSt( sElementList, Scan( pEleDelim, sElementList ) + 1, Long( sElementList ) );\r\n # Do recursive process call with new RunProcess function\r\n nThreadElCounter = nThreadElCounter + 1;\r\n sDimDelim = If(pFilter @= '', '', pDimDelim );\r\n IF( nThreadElCounter = 1 );\r\n sFilter = Expand('%pFilter%%sDimDelim%%sDimParallel%%pEleStartDelim%%sSlicerEle%');\r\n ELSE;\r\n sFilter = Expand('%sFilter%%pEleDelim%%sSlicerEle%');\r\n ENDIF;\r\n IF( nThreadElCounter >= nElemsPerThread );\r\n RunProcess( cThisProcName, 'pLogoutput', pLogoutput,\r\n \t 'pCube', pCube, 'pView', pView, 'pFilter', sFilter, 'pFilterParallel', '', \r\n \t 'pDimDelim', pDimDelim, 'pEleStartDelim', pEleStartDelim, 'pEleDelim', pEleDelim, \r\n \t 'pSuppressConsolStrings', pSuppressConsolStrings, 'pCubeLogging', pCubeLogging, 'pTemp', pTemp, 'pSandbox', pSandbox\r\n \t );\r\n \t nThreadElCounter = 0;\r\n \t sFilter = '';\r\n \t ENDIF;\r\n End;\r\n ## Process last elements - only when filter is not empty (there are still elements) otherwise the entire cube is emptied\r\n IF( sFilter @<> '' );\r\n RunProcess( cThisProcName, 'pLogoutput', pLogoutput,\r\n \t 'pCube', pCube, 'pView', pView, 'pFilter', sFilter, 'pFilterParallel', '', \r\n \t 'pDimDelim', pDimDelim, 'pEleStartDelim', pEleStartDelim, 'pEleDelim', pEleDelim, \r\n \t 'pSuppressConsolStrings', pSuppressConsolStrings, 'pCubeLogging', pCubeLogging, 'pTemp', pTemp, 'pSandbox', pSandbox\r\n \t );\r\n \t ENDIF;\r\n Else;\r\n ## Validate the View & filter parameter\r\n If( Trim( pView ) @= '' & Trim( pFilter ) @= '' & Trim( pSandbox ) @= '' );\r\n sMessage = Expand('No view OR filter specified so the entire %sCube% cube has been cleared.');\r\n\t IF( pLogoutput = 1 );\r\n \tLogOutput( 'INFO' , Expand( 'Process:%cThisProcName% Message:%sMessage%' ) );\r\n\t ENDIF;\r\n CubeClearData( sCube );\r\n Else;\r\n # Use different view/subset for different cubes\r\n sTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\n sRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\n cDefaultView = Expand( '%cThisProcName%_%sTimeStamp%_%sRandomInt%' );\r\n #cTempSub = cDefaultView;\r\n \r\n If( Trim( pView ) @= '' );\r\n cView = cDefaultView ;\r\n Else;\r\n cView = Trim( pView );\r\n EndIf;\r\n \r\n # Clear view\r\n If( ViewExists( sCube , cView ) = 0 );\r\n ## Validate that a Filter has been provided so that a view can be created.\r\n If( Trim( pFilter ) @= '' );\r\n sMessage = Expand('View %cView% does not exist in the %sCube% cube AND no Filter has not been specified in order to create a view.');\r\n LogOutput( 'INFO' , Expand( cMsgErrorContent ) );\r\n #ProcessBreak;\r\n EndIf;\r\n\r\n ### Create View using filter (temp view, therefore no need to destroy) ###\r\n sProc = '}bedrock.cube.view.create';\r\n nRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', sCube, 'pView', cView, 'pFilter', pFilter,\r\n 'pSuppressZero', 1, 'pSuppressConsol', 1, 'pSuppressRules', 1, 'pSuppressConsolStrings', pSuppressConsolStrings,\r\n 'pDimDelim', pDimDelim, 'pEleStartDelim', pEleStartDelim, 'pEleDelim', pEleDelim,\r\n 'pTemp', pTemp, 'pSubN', pSubN\r\n );\r\n\r\n # Validate Sandbox\r\n If( TRIM( pSandbox ) @<> '' );\r\n If( ServerSandboxExists( pSandbox ) = 0 );\r\n SetUseActiveSandboxProperty( 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand('Sandbox %pSandbox% is invalid for the current user.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n Else;\r\n ServerActiveSandboxSet( pSandbox );\r\n SetUseActiveSandboxProperty( 1 );\r\n EndIf;\r\n Else;\r\n SetUseActiveSandboxProperty( 0 );\r\n EndIf;\r\n\r\n ### Zero Out View ###\r\n If ( nRet = ProcessExitNormal() );\r\n ViewZeroOut( sCube, cView );\r\n sMessage = Expand( 'Succeeded in creating the %cView% view in the %sCube% cube and data has been cleared.' );\r\n \t If( pLogoutput = 1 );\r\n \tLogOutput( 'INFO', Expand( 'Process:%cThisProcName% Message:%sMessage%' ) );\r\n \t EndIf;\r\n Else;\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'Creating view by %sProc% has failed. Nothing has been cleared in the %sCube% cube.' );\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\n Else;\r\n ViewZeroOut( sCube, cView );\r\n Endif;\r\n Endif;\r\n EndIf;\r\n Endif;\r\n Else;\r\n # Create subset of cubes using Wildcard to loop through cubes in pCube with wildcard\r\n sCubeExp = '\"'|sCube|'\"';\r\n sMdx = '{TM1FILTERBYPATTERN( {TM1SUBSETALL( [}Cubes] )},'|sCubeExp| ')}';\r\n If( SubsetExists( '}Cubes' , cTempSub ) = 1 );\r\n # If a delimited list of cube names includes wildcards then we may have to re-use the subset multiple times\r\n SubsetMDXSet( '}Cubes' , cTempSub, sMDX );\r\n Else;\r\n # temp subset, therefore no need to destroy in epilog\r\n SubsetCreatebyMDX( cTempSub, sMDX, '}Cubes' , 1 );\r\n EndIf;\r\n \r\n # Loop through cubes in subset created based on wildcard\r\n nCountCube = SubsetGetSize( '}Cubes' , cTempSub );\r\n While( nCountCube >= 1 );\r\n # Use different view/subset for different cubes\r\n sTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\n sRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\n cDefaultView = Expand( '%cThisProcName%_%sTimeStamp%_%sRandomInt%' );\r\n sCube = SubsetGetElementName( '}Cubes' , cTempSub, nCountCube );\r\n # Validate cube name Not necessary as derived from subset of }Cubes\r\n If( CubeExists(sCube) = 0 );\r\n nErrors = 1;\r\n sMessage = Expand( '%sCube% does not exist.' );\r\n LogOutput( 'ERROR', Expand( cMsgErrorContent ) );\r\n Else;\r\n If( Scan( pEleStartDelim, pFilterParallel ) > 0 );\r\n nDim = 1;\r\n sDim = TABDIM( sCube, nDim);\r\n While ( sDim @<> '' );\r\n sDim = TABDIM( sCube, nDim);\r\n If ( sDim @= sDimParallel );\r\n bParallel = 1;\r\n sDim = '';\r\n EndIf;\r\n nDim = nDim + 1;\r\n End;\r\n EndIf;\r\n If( bParallel = 1 );\r\n sDimParallel = SubSt( pFilterParallel, 1, Scan( pEleStartDelim, pFilterParallel ) - 1 );\r\n sElementList = SubSt( pFilterParallel, Scan( pEleStartDelim, pFilterParallel ) + 1, Long( pFilterParallel ) );\r\n If( SubSt( sElementList, Long( sElementList ), 1 ) @<> pEleDelim );\r\n sElementList = sElementList | pEleDelim;\r\n EndIf;\r\n ## Counting elements in element list\r\n sElementListCount = sElementList;\r\n nElements = 0;\r\n While( Scan( pEleDelim, sElementListCount ) > 0 );\r\n nElements = nElements + 1;\r\n sElementListCount = SubSt( sElementListCount, Scan( pEleDelim, sElementListCount ) + 1, Long( sElementListCount ) );\r\n End;\r\n IF( Mod( nElements, nMaxThreads ) = 0 );\r\n nElemsPerThread = INT( nElements / nMaxThreads );\r\n ELSE;\r\n nElemsPerThread = INT( nElements / nMaxThreads ) + 1;\r\n ENDIF;\r\n nThreadElCounter = 0;\r\n While( Scan( pEleDelim, sElementList ) > 0 );\r\n sSlicerEle = SubSt( sElementList, 1, Scan( pEleDelim, sElementList ) - 1 );\r\n sElementList = SubSt( sElementList, Scan( pEleDelim, sElementList ) + 1, Long( sElementList ) );\r\n # Do recursive process call with new RunProcess function\r\n nThreadElCounter = nThreadElCounter + 1;\r\n sDimDelim = If(pFilter @= '', '', pDimDelim );\r\n IF( nThreadElCounter = 1 );\r\n sFilter = Expand('%pFilter%%sDimDelim%%sDimParallel%%pEleStartDelim%%sSlicerEle%');\r\n ELSE;\r\n sFilter = Expand('%sFilter%%pEleDelim%%sSlicerEle%');\r\n ENDIF;\r\n IF( nThreadElCounter >= nElemsPerThread );\r\n RunProcess( cThisProcName, 'pLogoutput', pLogoutput,\r\n \t 'pCube', pCube, 'pView', pView, 'pFilter', sFilter, 'pFilterParallel', '', \r\n \t 'pDimDelim', pDimDelim, 'pEleStartDelim', pEleStartDelim, 'pEleDelim', pEleDelim, \r\n \t 'pSuppressConsolStrings', pSuppressConsolStrings, 'pCubeLogging', pCubeLogging, 'pTemp', pTemp, 'pSandbox', pSandbox\r\n \t );\r\n \t nThreadElCounter = 0;\r\n \t sFilter = '';\r\n \t ENDIF;\r\n End;\r\n ## Process last elements\r\n IF( sFilter @<> '' );\r\n RunProcess( cThisProcName, 'pLogoutput', pLogoutput,\r\n \t 'pCube', pCube, 'pView', pView, 'pFilter', sFilter, 'pFilterParallel', '', \r\n \t 'pDimDelim', pDimDelim, 'pEleStartDelim', pEleStartDelim, 'pEleDelim', pEleDelim, \r\n \t 'pSuppressConsolStrings', pSuppressConsolStrings, 'pCubeLogging', pCubeLogging, 'pTemp', pTemp, 'pSandbox', pSandbox\r\n \t );\r\n \t ENDIF;\r\n Else;\r\n ## Validate the View & filter parameter\r\n If( Trim( pView ) @= '' & Trim( pFilter ) @= '' & Trim( pSandbox ) @= '' );\r\n # Clear entire cube\r\n sMessage = Expand('No view OR filter specified so the entire %sCube% cube has been cleared.');\r\n\t IF( pLogoutput = 1 );\r\n \tLogOutput( 'INFO' , Expand( 'Process:%cThisProcName% Message:%sMessage%' ) );\r\n\t ENDIF;\r\n CubeClearData( sCube );\r\n Else;\r\n # Clear view cView\r\n If( Trim( pView ) @= '' );\r\n cView = cDefaultView ;\r\n Else;\r\n cView = Trim( pView );\r\n EndIf;\r\n \r\n If( ViewExists( sCube, cView ) = 0 );\r\n ## Validate that a Filter has been provided so that a view can be created.\r\n If( Trim( pFilter ) @= '' );\r\n sMessage = Expand('View %cView% does not exist for %sCube% AND no Filter has not been specified in order to create a view.');\r\n LogOutput( 'ERROR' , Expand( cMsgErrorContent ) );\r\n #ProcessBreak;\r\n EndIf;\r\n \r\n ### Create View using filter (temp view, therefore no need to destroy) ###\r\n sProc = '}bedrock.cube.view.create';\r\n nRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', sCube, 'pView', cView, 'pFilter', pFilter,\r\n 'pSuppressZero', 1, 'pSuppressConsol', 1, 'pSuppressRules', 1, 'pSuppressConsolStrings', pSuppressConsolStrings,\r\n 'pDimDelim', pDimDelim, 'pEleStartDelim', pEleStartDelim, 'pEleDelim', pEleDelim,\r\n 'pTemp', pTemp, 'pSubN', pSubN\r\n );\r\n \r\n # Validate Sandbox\r\n If( TRIM( pSandbox ) @<> '' );\r\n If( ServerSandboxExists( pSandbox ) = 0 );\r\n SetUseActiveSandboxProperty( 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand('Sandbox %pSandbox% is invalid for the current user.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n Else;\r\n ServerActiveSandboxSet( pSandbox );\r\n SetUseActiveSandboxProperty( 1 );\r\n EndIf;\r\n Else;\r\n SetUseActiveSandboxProperty( 0 );\r\n EndIf;\r\n \r\n \r\n ### Zero Out View ###\r\n IF ( nRet = ProcessExitNormal() );\r\n ViewZeroOut( sCube, cView );\r\n sMessage = Expand( 'Succeeded in creating the %cView% view in the %sCube% cube and data has been cleared.' );\r\n \t\tIF( pLogoutput = 1 );\r\n LogOutput( 'INFO', Expand( 'Process:%cThisProcName% Message:%sMessage%' ) );\r\n \t\tENDIF;\r\n ELSE;\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'Creating view by %sProc% has failed. Nothing has been cleared in the %sCube% cube.' );\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n ENDIF;\r\n Else;\r\n ViewZeroOut( sCube, cView );\r\n Endif;\r\n EndIf;\r\n EndIf;\r\n nCountCube = nCountCube - 1;\r\n # Use different view/subset for different cubes\r\n sTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\n sRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\n cDefaultView = Expand( '%cThisProcName%_%sTimeStamp%_%sRandomInt%' );\r\n #cTempSub = cDefaultView; \r\n EndIf;\r\n End;\r\n EndIf;\r\nEnd;\r\n\r\n### End Prolog ###", "MetadataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "DataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "EpilogProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n### Return code & final error message handling\r\nIf( nErrors > 0 );\r\n sMessage = 'the process incurred at least 1 error. Please see above lines in this file for more details.';\r\n nProcessReturnCode = 0;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% Process:%cThisProcName% completed with errors. Check tm1server.log for details.' );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n EndIf;\r\nElse;\r\n sProcessAction = Expand( 'Process:%cThisProcName% successfully cleared data out of the %pCube% cube(s).' );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% %sProcessAction%' );\r\n nProcessReturnCode = 1;\r\n If( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( sProcessAction ) ); \r\n EndIf;\r\nEndIf;\r\n\r\n### End Epilog ###", @@ -10,21 +10,9 @@ "Type": "None" }, "Parameters": [ - { - "Name": "pLogOutput", - "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, - { - "Name": "pStrictErrorHandling", - "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, { "Name": "pCube", - "Prompt": "REQUIRED: Cube Name (wildcard * and/or cube1 & cube2 list)", + "Prompt": "REQUIRED: Cube name", "Value": "", "Type": "String" }, @@ -36,61 +24,73 @@ }, { "Name": "pFilter", - "Prompt": "Optional but ignored if view is specified: Year\u00a6 2006 + 2007 & Scenario\u00a6 Actual + Budget & Organization\u00a6 North America Operations", + "Prompt": "OPTIONAL: Filter on cube in format: 'dim_one\u00a6 el_one + el_two & dim_two\u00a6 el_one + el_two'", "Value": "", "Type": "String" }, { "Name": "pFilterParallel", - "Prompt": "OPTIONAL: Parallelization Filter: Month:Q1+Q2+Q3+Q4 (Blank=run single threaded). Single dimension parallel slices. Will be added to filter single element at a time. Dimension must not be part of filter", + "Prompt": "OPTIONAL: Parallelization filter in format: dim_one\u00a6 el_one + el_two. Dimension must not be part of filter", "Value": "", "Type": "String" }, { "Name": "pParallelThreads", - "Prompt": "OPTIONAL: Ignored if pFilterParallel is empty. Maximum number of threads to run when parallel processing is enabled ( if <2 will execute one thread, but parallel filter is still applied )", + "Prompt": "OPTIONAL: Maximum number of threads to run when parallel processing is enabled (Default = 0)", "Value": 0, "Type": "Numeric" }, { "Name": "pDimDelim", - "Prompt": "OPTIONAL: Delimiter for start of Dimension/Element set (default value if blank = '&')", + "Prompt": "OPTIONAL: Delimiter for start of dimension/element set in filter parameters (Default = '&')", "Value": "&", "Type": "String" }, { "Name": "pEleStartDelim", - "Prompt": "OPTIONAL: Delimiter for start of element list (default value if blank = '\u00a6')", + "Prompt": "OPTIONAL: Delimiter for start of element list in filter parameters (Default = '\u00a6')", "Value": "\u00a6", "Type": "String" }, { "Name": "pEleDelim", - "Prompt": "OPTIONAL: Delimiter between elements (default value if blank = '+')", + "Prompt": "OPTIONAL: Delimiter between elements in filter parameters (Default = '+')", "Value": "+", "Type": "String" }, { "Name": "pSuppressConsolStrings", - "Prompt": "OPTIONAL: Suppress Consolidated String Cells (Skip = 1)", - "Value": 0, + "Prompt": "OPTIONAL: Suppress consolidated string cells (Boolean. Default = 1)", + "Value": 1, "Type": "Numeric" }, { "Name": "pTemp", - "Prompt": "OPTIONAL: Make Views and subsets Temporary (1=Temporary)", + "Prompt": "OPTIONAL: Delete/create temporary objects (0 = Do not delete, 1 = Delete, 2 = if view and subsets are created, keep only subsets)", "Value": 1, "Type": "Numeric" }, { "Name": "pSandbox", - "Prompt": "OPTIONAL: To use sandbox not base data enter the sandbox name (invalid name will result in process error)", + "Prompt": "OPTIONAL: Use sandbox", "Value": "", "Type": "String" }, { "Name": "pSubN", - "Prompt": "OPTIONAL: Create N level subset for all dims not mentioned in pFilter", + "Prompt": "OPTIONAL: Create N level subset for all dims not specified (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pLogOutput", + "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pStrictErrorHandling", + "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" }, @@ -99,6 +99,12 @@ "Prompt": "OBSOLETE: This parameter does nothing and is only included for backwards compatability", "Value": 0, "Type": "Numeric" + }, + { + "Name": "pJson", + "Prompt": "OPTIONAL: JSON Object with process parameter values. This will overwrite user passed parameters for all included parameters.", + "Value": "{}", + "Type": "String" } ], "Variables": [], diff --git a/bedrock_processes_json/}bedrock.cube.data.copy.intercube.json b/bedrock_processes_json/}bedrock.cube.data.copy.intercube.json index 9b749d3..9ee5867 100644 --- a/bedrock_processes_json/}bedrock.cube.data.copy.intercube.json +++ b/bedrock_processes_json/}bedrock.cube.data.copy.intercube.json @@ -1,11 +1,11 @@ { "Name": "}bedrock.cube.data.copy.intercube", - "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.data.copy.intercube', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pSrcCube', '', 'pFilter', '',\r\n \t'pFilterParallel', '', 'pParallelThreads', 0,\r\n \t'pTgtCube', '', 'pMappingToNewDims', '',\r\n \t'pSuppressConsol', 1, 'pSuppressConsolStrings', 0, 'pSuppressRules', 1, 'pSuppressZero', 1, \r\n \t'pZeroTarget', 1, 'pZeroSource', 0,\r\n \t'pFactor', 1,\r\n \t'pDimDelim', '&', 'pEleStartDelim', '\u00a6', 'pEleDelim', '+',\r\n \t'pTemp', 1, 'pCubeLogging', 0, 'pSandbox', pSandbox, 'pSubN', 0, \r\n \t'pFile', 0, 'pDelim', ',', 'pQuote', '\"', 'pDecimalSeparator', '.', 'pThousandSeparator', ','\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# ## Description\r\n# This is the process used to copy data from a source cube to a different target cube.\r\n# \r\n# ## Use Cases \r\n# 1. This process could be used to populate a Reporting cube from multiple source cubes.\r\n# 2. The process could be used to archive data from one cube to another one for any use.\r\n#\r\n# ## Notes\r\n# * The target cube may have a different number of dimensions as the source cube.\r\n# * Where the target and source cubes share the same dimensions, the process will match the dimensions even if their position in the cube is different.\r\n# * An input element must be specified for each dimension which is in the target but not in the source using the parameter pMappingToNewDims.\r\n# * The format of parameter pMappingToNewDims using default delimiters & and : is DimInTargetButNotSource1:ElementOfDim & DimInTargetButNotSource2:ElementOfDim.\r\n# * The input element must be an N level unless pSuppressConsol is set to 0.\r\n# * The maximum number of dimensions catered for in the target cube is 27. (In principle adding support for cubes with higher dimensionality is not difficult).\r\n#\r\n# For dimensions in the source but not the target, the process will accumulate the values of all n level elements\r\n# (or all n level elements specified by the pFilter parameter).\r\n# The pFilter parameter contains the dimensions and elements to be used for filtering the source cube.\r\n# The format of the pFilter parameter is as follows, using default delimiters & + : Dim1: Elem1 + Elem2 & Dim2: Elem3 + Elem4.\r\n# The dimension parameters do not need to be given in the index order of dimensions in the cube.\r\n# The dimension name is specified as the first member of the delimited string of elements.\r\n# If consolidations are skipped the N level children of any consolidated filter elements will be used.\r\n# Spaces are ignored so use them to make your filter more readable.\r\n# If using the pFilterParallel parameter the **single dimension** used as the \"parallelization slicer\" cannot appear in\r\n# the pFilter parameters.\r\n# When using parallelization via the *RunProcess* function the elements listed in pFilterParallel will be split one_at_a_time\r\n# and passed to a recursive call of the process being added to pFilter.\r\n#\r\n# An example:\r\n# To copy the 2011 Actual Sales data from the Sales cube to the General Ledger cube set pFilter to Year: 2011 & Version: Actual.\r\n# Say the General Ledger cube has an Account dimension but the Sales cube doesn't and the Account for sales is 9999 (an n level element).\r\n# Set the pMappingToNewDims parameter to Account:9999.\r\n# This will copy all Actual 2011 Sales to Account 9999 in the General Ledger.\r\n# If only sales for Company X are to be copied, set pFilter to Year: 2011 & Version: Actual & Company:X.\r\n# If sales from other companies are already in the General Ledger set pZeroTarget to 0 to add Company X's data to the existing data.\r\n# Setting pZeroTarget to 1 will clear our data in the target cube for the elements specified in the\r\n# pMappingToNewDims parameter and the pFilter parameter for dimensions that are in the target.\r\n#EndRegion @DOC\r\n\r\n### Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = '%cThisProcName% : %sMessage% : %cUserName%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pSrcCube:%pSrcCube%, pFilter:%pFilter%, pFilterParallel:%pFilterParallel%, pParallelThreads:%pParallelThreads%, pTgtCube:%pTgtCube%, pMappingToNewDims:%pMappingToNewDims%, pSuppressConsol:%pSuppressConsol%, pSuppressConsolStrings:%pSuppressConsolStrings%, pSuppressRules:%pSuppressRules%, pSuppressZero:%pSuppressZero%, pZeroTarget:%pZeroTarget%, pZeroSource:%pZeroSource%, pFactor:%pFactor%, pDimDelim:%pDimDelim%, pEleStartDelim:%pEleStartDelim%, pEleDelim:%pEleDelim%, pTemp:%pTemp%, pCubeLogging:%pCubeLogging%, pSandbox:%pSandbox%, pFile:%pFile%, pThreadMode:%pThreadMode%.'; \r\n\r\nsDelimDim = TRIM(pDimDelim);\r\nsElementStartDelim = TRIM(pElEStartDelim);\r\nsDelimElem = TRIM(pEleDelim);\r\nnErrors = 0;\r\ncLenASCIICode = 3;\r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\n# Make sure pFactor not zero\r\nnFactor = If( pFactor = 0, 1, pFactor );\r\n\r\nsView = cThisProcName | cTimeStamp | cRandomInt;\r\nsSubset = sView;\r\nsTargetView = 'Target '| sView;\r\nsTargetSubset = sTargetView;\r\n\r\n## check operating system\r\nIf( SubSt( GetProcessErrorFileDirectory, 2, 1 ) @= ':' );\r\n sOS = 'Windows';\r\n sOSDelim = '\\';\r\nElseIf( Scan( '/', GetProcessErrorFileDirectory ) > 0 );\r\n sOS = 'Linux';\r\n sOSDelim = '/';\r\nElse;\r\n sOS = 'Windows';\r\n sOSDelim = '\\';\r\nEndIf;\r\n\r\n## File location for indirect data copy\r\ncDir = GetProcessErrorFileDirectory;\r\ncFileName = pSrcCube | cTimeStamp | cRandomInt | '.csv';\r\ncFile = cDir | cFileName;\r\ncTitleRows = 1;\r\n\r\n# Validate file delimiter & quote character\r\nIf( pDelim @= '' );\r\n pDelim = ',';\r\nElse;\r\n # If length of pDelim is exactly 3 chars and each of them is decimal digit, then the pDelim is entered as ASCII code\r\n nValid = 0;\r\n If ( LONG(pDelim) = cLenASCIICode );\r\n nChar = 1;\r\n While ( nChar <= cLenASCIICode );\r\n If( CODE( pDelim, nChar ) >= CODE( '0', 1 ) & CODE( pDelim, nChar ) <= CODE( '9', 1 ) );\r\n nValid = 1;\r\n Else;\r\n nValid = 0;\r\n Break;\r\n EndIf;\r\n nChar = nChar + 1;\r\n End;\r\n EndIf;\r\n If ( nValid<>0 );\r\n pDelim=CHAR(StringToNumber( pDelim ));\r\n Else;\r\n pDelim = SubSt( Trim( pDelim ), 1, 1 );\r\n EndIf;\r\nEndIf;\r\ncDelimiter = pDelim;\r\n\r\nIf( pQuote @= '' );\r\n ## Use no quote character\r\nElse;\r\n # If length of pQuote is exactly 3 chars and each of them is decimal digit, then the pQuote is entered as ASCII code\r\n nValid = 0;\r\n If ( LONG(pQuote) = cLenASCIICode );\r\n nChar = 1;\r\n While ( nChar <= cLenASCIICode );\r\n If( CODE( pQuote, nChar ) >= CODE( '0', 1 ) & CODE( pQuote, nChar ) <= CODE( '9', 1 ) );\r\n nValid = 1;\r\n Else;\r\n nValid = 0;\r\n Break;\r\n EndIf;\r\n nChar = nChar + 1;\r\n End;\r\n EndIf;\r\n If ( nValid<>0 );\r\n pQuote=CHAR(StringToNumber( pQuote ));\r\n Else;\r\n pQuote = SubSt( Trim( pQuote ), 1, 1 );\r\n EndIf;\r\nEndIf;\r\ncQuote = pQuote;\r\n\r\n#Region ## Check Parameters ###\r\n\r\n## Default filter delimiters\r\nIf( pDimDelim @= '' );\r\n pDimDelim = '&';\r\nEndIf;\r\nIf( pEleStartDelim@= '' );\r\n pEleStartDelim= '\u00a6';\r\nEndIf;\r\nIf( pEleDelim @= '' );\r\n pEleDelim = '+';\r\nEndIf;\r\n\r\nIf( pDecimalSeparator @= '' );\r\n \tpDecimalSeparator = '.';\r\nEndIf;\r\nIf ( LONG(pDecimalSeparator) = cLenASCIICode );\r\n nValid = 0;\r\n nChar = 1;\r\n While ( nChar <= cLenASCIICode );\r\n If( CODE( pDecimalSeparator, nChar ) >= CODE( '0', 1 ) & CODE( pDecimalSeparator, nChar ) <= CODE( '9', 1 ) );\r\n nValid = 1;\r\n Else;\r\n nValid = 0;\r\n Break;\r\n EndIf;\r\n nChar = nChar + 1;\r\n End;\r\n If ( nValid<>0 );\r\n pDecimalSeparator = CHAR(StringToNumber( pDecimalSeparator ));\r\n Else;\r\n pDecimalSeparator = SubSt( Trim( pDecimalSeparator ), 1, 1 );\r\n EndIf;\r\nEndIf;\r\nsDecimalSeparator = pDecimalSeparator;\r\n\r\nIf( pThousandSeparator @= '' );\r\n \tpThousandSeparator = ',';\r\nEndIf;\r\nIf ( LONG(pThousandSeparator) = cLenASCIICode );\r\n nValid = 0;\r\n nChar = 1;\r\n While ( nChar <= cLenASCIICode );\r\n If( CODE( pThousandSeparator, nChar ) >= CODE( '0', 1 ) & CODE( pThousandSeparator, nChar ) <= CODE( '9', 1 ) );\r\n nValid = 1;\r\n Else;\r\n nValid = 0;\r\n Break;\r\n EndIf;\r\n nChar = nChar + 1;\r\n End;\r\n If ( nValid<>0 );\r\n pThousandSeparator = CHAR(StringToNumber( pThousandSeparator ));\r\n Else;\r\n pThousandSeparator = SubSt( Trim( pThousandSeparator ), 1, 1 );\r\n EndIf;\r\nEndIf;\r\nsThousandSeparator = pThousandSeparator;\r\n\r\n# If specified source cube doesn't exist then terminate process\r\nIf( CubeExists( pSrcCube ) = 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'Invalid source cube specified: %pSrcCube%.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# If specified target cube doesn't exist then terminate process\r\nIf( CubeExists( pTgtCube ) = 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'Invalid target cube specified: %pTgtCube%.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate parallelization filter\r\nIf( Scan( pEleStartDelim, pFilterParallel ) > 0 );\r\n sDimParallel = SubSt( pFilterParallel, 1, Scan( pEleStartDelim, pFilterParallel ) - 1 );\r\n If( Scan( Lower(sDimParallel) | pEleStartDelim, Lower(pFilter) ) > 0 );\r\n sMessage = 'Parallelization dimension %sDimParallel% cannot exist in filter.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\nEndIf;\r\n\r\n# Validate Max Threads\r\nIf( pParallelThreads > 0 );\r\n nMaxThreads = pParallelThreads;\r\nElse;\r\n nMaxThreads = 1;\r\nEndIf;\r\n\r\n# Validate Sandbox\r\nIf( TRIM( pSandbox ) @<> '' );\r\n If( ServerSandboxExists( pSandbox ) = 0 );\r\n SetUseActiveSandboxProperty( 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand('Sandbox %pSandbox% is invalid for the current user.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n Else;\r\n ServerActiveSandboxSet( pSandbox );\r\n SetUseActiveSandboxProperty( 1 );\r\n EndIf;\r\nElse;\r\n SetUseActiveSandboxProperty( 0 );\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n#EndRegion\r\n#Region \r\n## Set variables =0 or '' ################################################################################################# ########################\r\n### Placeholders for mappped dimensions\r\nnMappedDim1 = 0;\r\nnMappedDim2 = 0;\r\nnMappedDim3 = 0;\r\nnMappedDim4 = 0;\r\nnMappedDim5 = 0;\r\nnMappedDim6 = 0;\r\nnMappedDim7 = 0;\r\nnMappedDim8 = 0;\r\nnMappedDim9 = 0;\r\nnMappedDim10 = 0;\r\nnMappedDim11 = 0;\r\nnMappedDim12 = 0;\r\nnMappedDim13 = 0;\r\nnMappedDim14 = 0;\r\nnMappedDim15 = 0;\r\nnMappedDim16 = 0;\r\nnMappedDim17 = 0;\r\nnMappedDim18 = 0;\r\nnMappedDim19 = 0;\r\nnMappedDim20 = 0;\r\nnMappedDim21 = 0;\r\nnMappedDim22 = 0;\r\nnMappedDim23 = 0;\r\nnMappedDim24 = 0;\r\nnMappedDim25 = 0;\r\nnMappedDim26 = 0;\r\nnMappedDim27 = 0;\r\n\r\nsMappedV1 = '';\r\nsMappedV2 = '';\r\nsMappedV3 = '';\r\nsMappedV4 = '';\r\nsMappedV5 = '';\r\nsMappedV6 = '';\r\nsMappedV7 = '';\r\nsMappedV8 = '';\r\nsMappedV9 = '';\r\nsMappedV10 = '';\r\nsMappedV11 = '';\r\nsMappedV12 = '';\r\nsMappedV13 = '';\r\nsMappedV14 = '';\r\nsMappedV15 = '';\r\nsMappedV16 = '';\r\nsMappedV17 = '';\r\nsMappedV18 = '';\r\nsMappedV19 = '';\r\nsMappedV20 = '';\r\nsMappedV21 = '';\r\nsMappedV22 = '';\r\nsMappedV23 = '';\r\nsMappedV24 = '';\r\nsMappedV25 = '';\r\nsMappedV26 = '';\r\nsMappedV27 = '';\r\nsMappedV28 = '';\r\n\r\n### Placeholders for new dimensions\r\nnNewDim1 = 0;\r\nnNewDim2 = 0;\r\nnNewDim3 = 0;\r\nnNewDim4 = 0;\r\nnNewDim5 = 0;\r\nnNewDim6 = 0;\r\nnNewDim7 = 0;\r\nnNewDim8 = 0;\r\nnNewDim9 = 0;\r\nnNewDim10 = 0;\r\nnNewDim11 = 0;\r\nnNewDim12 = 0;\r\nnNewDim13 = 0;\r\nnNewDim14 = 0;\r\nnNewDim15 = 0;\r\nnNewDim16 = 0;\r\nnNewDim17 = 0;\r\nnNewDim18 = 0;\r\nnNewDim19 = 0;\r\nnNewDim20 = 0;\r\nnNewDim21 = 0;\r\nnNewDim22 = 0;\r\nnNewDim23 = 0;\r\nnNewDim24 = 0;\r\nnNewDim25 = 0;\r\nnNewDim26 = 0;\r\nnNewDim27 = 0;\r\n\r\nsNewV1 = '';\r\nsNewV2 = '';\r\nsNewV3 = '';\r\nsNewV4 = '';\r\nsNewV5 = '';\r\nsNewV6 = '';\r\nsNewV7 = '';\r\nsNewV8 = '';\r\nsNewV9 = '';\r\nsNewV10 = '';\r\nsNewV11 = '';\r\nsNewV12 = '';\r\nsNewV13 = '';\r\nsNewV14 = '';\r\nsNewV15 = '';\r\nsNewV16 = '';\r\nsNewV17 = '';\r\nsNewV18 = '';\r\nsNewV19 = '';\r\nsNewV20 = '';\r\nsNewV21 = '';\r\nsNewV22 = '';\r\nsNewV23 = '';\r\nsNewV24 = '';\r\nsNewV25 = '';\r\nsNewV26 = '';\r\nsNewV27 = '';\r\n\r\n### Determine dimensions in target cube, we need to know this to test cell type before loading ###\r\n# only numbers get converted from strings to numbers\r\nsDim1 = TabDim( pTgtCube, 1 );\r\nsDim2 = TabDim( pTgtCube, 2 );\r\nsDim3 = TabDim( pTgtCube, 3 );\r\nsDim4 = TabDim( pTgtCube, 4 );\r\nsDim5 = TabDim( pTgtCube, 5 );\r\nsDim6 = TabDim( pTgtCube, 6 );\r\nsDim7 = TabDim( pTgtCube, 7 );\r\nsDim8 = TabDim( pTgtCube, 8 );\r\nsDim9 = TabDim( pTgtCube, 9 );\r\nsDim10 = TabDim( pTgtCube, 10 );\r\nsDim11 = TabDim( pTgtCube, 11 );\r\nsDim12 = TabDim( pTgtCube, 12 );\r\nsDim13 = TabDim( pTgtCube, 13 );\r\nsDim14 = TabDim( pTgtCube, 14 );\r\nsDim15 = TabDim( pTgtCube, 15 );\r\nsDim16 = TabDim( pTgtCube, 16 );\r\nsDim17 = TabDim( pTgtCube, 17 );\r\nsDim18 = TabDim( pTgtCube, 18 );\r\nsDim19 = TabDim( pTgtCube, 19 );\r\nsDim20 = TabDim( pTgtCube, 20 );\r\nsDim21 = TabDim( pTgtCube, 21 );\r\nsDim22 = TabDim( pTgtCube, 22 );\r\nsDim23 = TabDim( pTgtCube, 23 );\r\nsDim24 = TabDim( pTgtCube, 24 );\r\nsDim25 = TabDim( pTgtCube, 25 );\r\nsDim26 = TabDim( pTgtCube, 26 );\r\nsDim27 = TabDim( pTgtCube, 27 );\r\n#EndRegion\r\nsTgtDimString = '^^'|sDim1|'^^'|sDim2|'^^'|sDim3|'^^'|sDim4|'^^'|sDim5|'^^'|sDim6|'^^'|sDim7|'^^'|sDim8|'^^'|sDim9|'^^'|sDim10|'^^'\r\n |sDim11|'^^'|sDim12|'^^'|sDim13|'^^'|sDim14|'^^'|sDim15|'^^'|sDim16|'^^'|sDim17|'^^'|sDim18|'^^'|sDim19|'^^'|sDim20|'^^'\r\n |sDim21|'^^'|sDim22|'^^'|sDim23|'^^'|sDim24|'^^'|sDim25|'^^'|sDim26|'^^'|sDim27|'^^';\r\n\r\n### We have to remove spaces from the search string before going to include the string in searching loop\r\nsTgtDimString = UPPER( sTgtDimString );\r\nnSPIndex = SCAN( ' ', sTgtDimString );\r\nWhile ( nSPIndex <> 0);\r\n sTgtDimString = DELET( sTgtDimString, nSPIndex, 1 );\r\n nSPIndex = SCAN( ' ', sTgtDimString );\r\nEnd;\r\n\r\n###########################################\r\n#Region ### MAPPING Target DIMENSIONS #####\r\n###########################################\r\nnSourceIndex = 1;\r\nWhile( TabDim( pSrcCube, nSourceIndex ) @<> '' );\r\n sSourceDim = TabDim( pSrcCube, nSourceIndex);\r\n # reset target index if another source dimension has been found\r\n nTargetIndex = 1;\r\n WHILE(TabDim( pTgtCube, nTargetIndex ) @<> '');\r\n sTargetDim = TabDim( pTgtCube, nTargetIndex );\r\n If(sSourceDim @= sTargetDim);\r\n If( pFile = 0 );\r\n If(nTargetIndex = 1);\r\n nMappedDim1 = 1;\r\n sMappedV1 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 2);\r\n nMappedDim2 = 1;\r\n sMappedV2 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 3);\r\n nMappedDim3 = 1;\r\n sMappedV3 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 4);\r\n nMappedDim4 = 1;\r\n sMappedV4 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 5);\r\n nMappedDim5 = 1;\r\n sMappedV5 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 6);\r\n nMappedDim6 = 1;\r\n sMappedV6 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 7);\r\n nMappedDim7 = 1;\r\n sMappedV7 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 8);\r\n nMappedDim8 = 1;\r\n sMappedV8 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 9);\r\n nMappedDim9 = 1;\r\n sMappedV9 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 10);\r\n nMappedDim10 = 1;\r\n sMappedV10 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 11);\r\n nMappedDim11 = 1;\r\n sMappedV11 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 12);\r\n nMappedDim12 = 1;\r\n sMappedV12 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 13);\r\n nMappedDim13 = 1;\r\n sMappedV13 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 14);\r\n nMappedDim14 = 1;\r\n sMappedV14 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 15);\r\n nMappedDim15 = 1;\r\n sMappedV15 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 16);\r\n nMappedDim16 = 1;\r\n sMappedV16 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 17);\r\n nMappedDim17 = 1;\r\n sMappedV17 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 18);\r\n nMappedDim18 = 1;\r\n sMappedV18 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 19);\r\n nMappedDim19 = 1;\r\n sMappedV19 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 20);\r\n nMappedDim20 = 1;\r\n sMappedV20 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 21);\r\n nMappedDim21 = 1;\r\n sMappedV21 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 22);\r\n nMappedDim22 = 1;\r\n sMappedV22 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 23);\r\n nMappedDim23 = 1;\r\n sMappedV23 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 24);\r\n nMappedDim24 = 1;\r\n sMappedV24 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 25);\r\n nMappedDim25 = 1;\r\n sMappedV25 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 26);\r\n nMappedDim26 = 1;\r\n sMappedV26 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 27);\r\n nMappedDim27 = 1;\r\n sMappedV27 = 'V' | NumberToString(nSourceIndex);\r\n EndIf;\r\n ElseIf( pFile > 0 );\r\n ## If using source file first variable holds tha cube name, so all the other ones have the index increased by 1\r\n If(nTargetIndex = 1);\r\n nMappedDim1 = 1;\r\n sMappedV1 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 2);\r\n nMappedDim2 = 1;\r\n sMappedV2 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 3);\r\n nMappedDim3 = 1;\r\n sMappedV3 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 4);\r\n nMappedDim4 = 1;\r\n sMappedV4 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 5);\r\n nMappedDim5 = 1;\r\n sMappedV5 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 6);\r\n nMappedDim6 = 1;\r\n sMappedV6 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 7);\r\n nMappedDim7 = 1;\r\n sMappedV7 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 8);\r\n nMappedDim8 = 1;\r\n sMappedV8 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 9);\r\n nMappedDim9 = 1;\r\n sMappedV9 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 10);\r\n nMappedDim10 = 1;\r\n sMappedV10 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 11);\r\n nMappedDim11 = 1;\r\n sMappedV11 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 12);\r\n nMappedDim12 = 1;\r\n sMappedV12 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 13);\r\n nMappedDim13 = 1;\r\n sMappedV13 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 14);\r\n nMappedDim14 = 1;\r\n sMappedV14 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 15);\r\n nMappedDim15 = 1;\r\n sMappedV15 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 16);\r\n nMappedDim16 = 1;\r\n sMappedV16 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 17);\r\n nMappedDim17 = 1;\r\n sMappedV17 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 18);\r\n nMappedDim18 = 1;\r\n sMappedV18 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 19);\r\n nMappedDim19 = 1;\r\n sMappedV19 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 20);\r\n nMappedDim20 = 1;\r\n sMappedV20 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 21);\r\n nMappedDim21 = 1;\r\n sMappedV21 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 22);\r\n nMappedDim22 = 1;\r\n sMappedV22 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 23);\r\n nMappedDim23 = 1;\r\n sMappedV23 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 24);\r\n nMappedDim24 = 1;\r\n sMappedV24 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 25);\r\n nMappedDim25 = 1;\r\n sMappedV25 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 26);\r\n nMappedDim26 = 1;\r\n sMappedV26 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 27);\r\n nMappedDim27 = 1;\r\n sMappedV27 = 'V' | NumberToString(nSourceIndex + 1);\r\n EndIf;\r\n EndIf;\r\n\r\n EndIf;\r\n\r\n nTargetIndex = nTargetIndex + 1;\r\n\r\n END;\r\n\r\n nSourceIndex = nSourceIndex + 1;\r\n\r\nEND;\r\n\r\n# The last variable in the data source holds the values\r\n# which need to be mapped to the last variable in the target\r\n\r\nIf( pFile = 0 );\r\n If(nTargetIndex = 1);\r\n nMappedDim1 = 1;\r\n sMappedV1 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 2);\r\n nMappedDim2 = 1;\r\n sMappedV2 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 3);\r\n nMappedDim3 = 1;\r\n sMappedV3 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 4);\r\n nMappedDim4 = 1;\r\n sMappedV4 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 5);\r\n nMappedDim5 = 1;\r\n sMappedV5 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 6);\r\n nMappedDim6 = 1;\r\n sMappedV6 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 7);\r\n nMappedDim7 = 1;\r\n sMappedV7 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 8);\r\n nMappedDim8 = 1;\r\n sMappedV8 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 9);\r\n nMappedDim9 = 1;\r\n sMappedV9 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 10);\r\n nMappedDim10 = 1;\r\n sMappedV10 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 11);\r\n nMappedDim11 = 1;\r\n sMappedV11 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 12);\r\n nMappedDim12 = 1;\r\n sMappedV12 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 13);\r\n nMappedDim13 = 1;\r\n sMappedV13 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 14);\r\n nMappedDim14 = 1;\r\n sMappedV14 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 15);\r\n nMappedDim15 = 1;\r\n sMappedV15 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 16);\r\n nMappedDim16 = 1;\r\n sMappedV16 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 17);\r\n nMappedDim17 = 1;\r\n sMappedV17 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 18);\r\n nMappedDim18 = 1;\r\n sMappedV18 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 19);\r\n nMappedDim19 = 1;\r\n sMappedV19 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 20);\r\n nMappedDim20 = 1;\r\n sMappedV20 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 21);\r\n nMappedDim21 = 1;\r\n sMappedV21 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 22);\r\n nMappedDim22 = 1;\r\n sMappedV22 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 23);\r\n nMappedDim23 = 1;\r\n sMappedV23 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 24);\r\n nMappedDim24 = 1;\r\n sMappedV24 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 25);\r\n nMappedDim25 = 1;\r\n sMappedV25 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 26);\r\n nMappedDim26 = 1;\r\n sMappedV26 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 27);\r\n nMappedDim27 = 1;\r\n sMappedV27 = 'V' | NumberToString(nSourceIndex);\r\n \r\n # a cube with 27 dimensions uses V28 to hold the values\r\n ElseIf(nTargetIndex = 28);\r\n nMappedDim28 = 1;\r\n sMapped28 = 'V' | NumberToString(nSourceIndex);\r\n EndIf;\r\nElseIf( pFile > 0 );\r\n If(nTargetIndex = 1);\r\n nMappedDim1 = 1;\r\n sMappedV1 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 2);\r\n nMappedDim2 = 1;\r\n sMappedV2 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 3);\r\n nMappedDim3 = 1;\r\n sMappedV3 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 4);\r\n nMappedDim4 = 1;\r\n sMappedV4 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 5);\r\n nMappedDim5 = 1;\r\n sMappedV5 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 6);\r\n nMappedDim6 = 1;\r\n sMappedV6 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 7);\r\n nMappedDim7 = 1;\r\n sMappedV7 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 8);\r\n nMappedDim8 = 1;\r\n sMappedV8 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 9);\r\n nMappedDim9 = 1;\r\n sMappedV9 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 10);\r\n nMappedDim10 = 1;\r\n sMappedV10 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 11);\r\n nMappedDim11 = 1;\r\n sMappedV11 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 12);\r\n nMappedDim12 = 1;\r\n sMappedV12 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 13);\r\n nMappedDim13 = 1;\r\n sMappedV13 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 14);\r\n nMappedDim14 = 1;\r\n sMappedV14 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 15);\r\n nMappedDim15 = 1;\r\n sMappedV15 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 16);\r\n nMappedDim16 = 1;\r\n sMappedV16 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 17);\r\n nMappedDim17 = 1;\r\n sMappedV17 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 18);\r\n nMappedDim18 = 1;\r\n sMappedV18 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 19);\r\n nMappedDim19 = 1;\r\n sMappedV19 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 20);\r\n nMappedDim20 = 1;\r\n sMappedV20 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 21);\r\n nMappedDim21 = 1;\r\n sMappedV21 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 22);\r\n nMappedDim22 = 1;\r\n sMappedV22 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 23);\r\n nMappedDim23 = 1;\r\n sMappedV23 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 24);\r\n nMappedDim24 = 1;\r\n sMappedV24 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 25);\r\n nMappedDim25 = 1;\r\n sMappedV25 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 26);\r\n nMappedDim26 = 1;\r\n sMappedV26 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 27);\r\n nMappedDim27 = 1;\r\n sMappedV27 = 'V' | NumberToString(nSourceIndex + 1);\r\n \r\n # a cube with 27 dimensions uses V29 to hold the values if export file is used as source\r\n ElseIf(nTargetIndex = 28);\r\n nMappedDim28 = 1;\r\n sMapped28 = 'V' | NumberToString(nSourceIndex + 1);\r\n EndIf;\r\nEndIf;\r\n#EndRegion\r\n\r\n###########################################\r\n### SPLIT MAPPING TO NEW DIMS PARAMETER ###\r\n###########################################\r\n\r\n# now deduct 1 to set these indices to the number of dimensions in each cube\r\nnSourceDimensionCount = nSourceIndex - 1;\r\nnTargetCubeDimensionCount = nTargetIndex - 1;\r\n# default dimension count is for target\r\nnDimensionCount = nTargetIndex - 1;\r\n\r\nsElementMapping = TRIM( pMappingToNewDims );\r\nnChar = 1;\r\nnCharCount = LONG( sElementMapping );\r\n\r\nsTargetFilter = '';\r\nsWord = '';\r\nsLastDelim = '';\r\nnIndex = 1;\r\n\r\n# Add a trailing element delimiter so that the last element is picked up\r\nIf( nCharCount > 0 );\r\n sElementMapping = sElementMapping | sDelimDim;\r\n nCharCount = nCharCount + LONG(sDelimDim);\r\nEndIf;\r\n\r\nWHILE (nChar <= nCharCount);\r\n sChar = SUBST( sElementMapping, nChar, 1);\r\n\r\n # Used for delimiters, required for multiple character delimiters\r\n sDelim = '';\r\n nAddExtra = 0;\r\n\r\n # Ignore spaces\r\n IF (TRIM(sChar) @<> '' );\r\n\r\n ### Dimension Name ###\r\n\r\n # If the delimiter is more than 1 character peek ahead the same amount\r\n # Ignore the first character\r\n sDelim = sChar;\r\n nCount = LONG(sElementStartDelim) - 1;\r\n If( nCount > 0 & nChar + nCount <= nCharCount );\r\n # Add the extra characters\r\n sDelim = sDelim | SUBST( sElementMapping, nChar + 1, nCount);\r\n # Move to the end of the delimter\r\n nAddExtra = nCount;\r\n EndIf;\r\n\r\n If( sDelim @= sElementStartDelim );\r\n\r\n sChar = sDelim;\r\n\r\n If( sLastDelim @<> '' & sLastDelim @<> sDelimDim );\r\n sMessage = 'In pMappingToNewDims the name of a dimension must follow a dimension delimiter (' | sDelimDim | ')';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n EndIf;\r\n\r\n # Found a dimension\r\n sDimension = sWord;\r\n\r\n If( DimensionExists( sDimension ) = 0 );\r\n # The dimension does not exist in the model. Cancel process\r\n sMessage = 'In pMappingToNewDims - Dimension: ' | sDimension | ' does not exist';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n EndIf;\r\n\r\n # Find the index of the dimension is in the Target cube\r\n nTargetIndexCounter = 1;\r\n\r\n WHILE(nTargetIndexCounter <= nTargetCubeDimensionCount );\r\n sNthDimension = TabDim( pTgtCube, nTargetIndexCounter );\r\n\r\n If(sDimension @= sNthDimension);\r\n nTargetIndex = nTargetIndexCounter;\r\n nTargetIndexCounter = 1000;\r\n EndIf;\r\n\r\n nTargetIndexCounter = nTargetIndexCounter + 1;\r\n END;\r\n \r\n #Add to the Target filter\r\n IF(sTargetFilter@='');\r\n sTargetFilter=sDimension; \r\n Else;\r\n sTargetFilter=sTargetFilter|sDelimDim|sDimension;\r\n Endif; \r\n \r\n sLastDelim = sChar;\r\n # Clear the word\r\n sWord = '';\r\n\r\n Else;\r\n\r\n # Reset extra chars\r\n nAddExtra = 0;\r\n\r\n ### Check both dim delimiter and element delimiter ###\r\n nIsDelimiter = 0;\r\n\r\n ## Check dimension delimiter first\r\n # If the delimiter is more than 1 character peek ahead the same amount\r\n # Ignore the first character\r\n sDelim = sChar;\r\n nCount = LONG(sDelimDim) - 1;\r\n If( nCount > 0 & nChar + nCount <= nCharCount );\r\n # Add the extra characters\r\n sDelim = sDelim | SUBST( sElementMapping, nChar + 1, nCount);\r\n EndIf;\r\n\r\n If( sDelim @= sDelimDim );\r\n nIsDelimiter = 1;\r\n sChar = sDelim;\r\n \r\n # Move to the end of the delimter\r\n nAddExtra = nCount;\r\n EndIf;\r\n\r\n If ( nIsDelimiter = 1 );\r\n\r\n If( sLastDelim @= '' % sLastDelim @= sDelimDim );\r\n sMessage = 'In pMappingToNewDims - an element delimiter must follow a dimension name: ' | sChar | ' (' | NumberToString(nChar) | ')';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n EndIf;\r\n\r\n # an element has been found\r\n sElement = sWord;\r\n\r\n If( DIMIX( sDimension, sElement ) = 0 );\r\n # The element does not exist in the dimension. Cancel process\r\n sMessage = 'In pMappingToNewDims - Element: ' | sElement | ' in dimension ' | sDimension | ' does not exist';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n EndIf;\r\n\r\n # Allow consolidations only if pSuppressConsol is set to 0\r\n\r\n If ( DTYPE( sDimension, sElement) @= 'C' );\r\n sMessage = Expand( 'In pMappingToNewDims - Target element: %sElement% for dimension %sDimension% is consolidated' );\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n Endif; \r\n \r\n\r\n # Add the element to the source or target depending on whether it's the first or the second element\r\n # Get principal name\r\n # in case source element and this element are using different aliases\r\n\r\n sElement = DimensionElementPrincipalName(sDimension,sElement);\r\n\r\n ### Update the variable for InputElement Target Dim ######################################\r\n If(nTargetIndex = 1);\r\n nNewDim1 = 1;\r\n sNewV1 = sElement;\r\n ElseIf(nTargetIndex = 2);\r\n nNewDim2 = 1;\r\n sNewV2 = sElement;\r\n ElseIf(nTargetIndex = 3);\r\n nNewDim3 = 1;\r\n sNewV3 = sElement;\r\n ElseIf(nTargetIndex = 4);\r\n nNewDim4 = 1;\r\n sNewV4 = sElement;\r\n ElseIf(nTargetIndex = 5);\r\n nNewDim5 = 1;\r\n sNewV5 = sElement;\r\n ElseIf(nTargetIndex = 6);\r\n nNewDim6 = 1;\r\n sNewV6 = sElement;\r\n ElseIf(nTargetIndex = 7);\r\n nNewDim7 = 1;\r\n sNewV7 = sElement;\r\n ElseIf(nTargetIndex = 8);\r\n nNewDim8 = 1;\r\n sNewV8 = sElement;\r\n ElseIf(nTargetIndex = 9);\r\n nNewDim9 = 1;\r\n sNewV9 = sElement;\r\n ElseIf(nTargetIndex = 10);\r\n nNewDim10 = 1;\r\n sNewV10 = sElement;\r\n ElseIf(nTargetIndex = 11);\r\n nNewDim11 = 1;\r\n sNewV11 = sElement;\r\n ElseIf(nTargetIndex = 12);\r\n nNewDim12 = 1;\r\n sNewV12 = sElement;\r\n ElseIf(nTargetIndex = 13);\r\n nNewDim13 = 1;\r\n sNewV13 = sElement;\r\n ElseIf(nTargetIndex = 14);\r\n nNewDim14 = 1;\r\n sNewV14 = sElement;\r\n ElseIf(nTargetIndex = 15);\r\n nNewDim15 = 1;\r\n sNewV15 = sElement;\r\n ElseIf(nTargetIndex = 16);\r\n nNewDim16 = 1;\r\n sNewV16 = sElement;\r\n ElseIf(nTargetIndex = 17);\r\n nNewDim17 = 1;\r\n sNewV17 = sElement;\r\n ElseIf(nTargetIndex = 18);\r\n nNewDim18 = 1;\r\n sNewV18 = sElement;\r\n ElseIf(nTargetIndex = 19);\r\n nNewDim19 = 1;\r\n sNewV19 = sElement;\r\n ElseIf(nTargetIndex = 20);\r\n nNewDim20 = 1;\r\n sNewV20 = sElement;\r\n ElseIf(nTargetIndex = 21);\r\n nNewDim21 = 1;\r\n sNewV21 = sElement;\r\n ElseIf(nTargetIndex = 22);\r\n nNewDim22 = 1;\r\n sNewV22 = sElement;\r\n ElseIf(nTargetIndex = 23);\r\n nNewDim23 = 1;\r\n sNewV23 = sElement;\r\n ElseIf(nTargetIndex = 24);\r\n nNewDim24 = 1;\r\n sNewV24 = sElement;\r\n ElseIf(nTargetIndex = 25);\r\n nNewDim25 = 1;\r\n sNewV25 = sElement;\r\n ElseIf(nTargetIndex = 26);\r\n nNewDim26 = 1;\r\n sNewV26 = sElement;\r\n ElseIf(nTargetIndex = 27);\r\n nNewDim27 = 1;\r\n sNewV27 = sElement;\r\n EndIf;\r\n\r\n #Add to the Target filter\r\n sTargetFilter=sTargetFilter|sElementStartDelim|sElement;\r\n \r\n # Clear the word\r\n sWord = '';\r\n sLastDelim = sChar;\r\n \r\n Else;\r\n sWord = sWord | sChar;\r\n EndIf;\r\n\r\n EndIf;\r\n\r\n EndIf;\r\n\r\n nChar = nChar + nAddExtra + 1;\r\n\r\nEND;\r\n\r\n# Check that an input element or variable has been specified for all dimensions in the target cube\r\n\r\nnIndexInTarget = 1;\r\nWHILE(nIndexInTarget <= nTargetCubeDimensionCount);\r\n \r\n sMapped = Expand('%nMappedDim'| NumberToString(nIndexInTarget) |'%'); \r\n sMapped = Subst( sMapped , Scan( '.' , sMapped )-1 , 99);\r\n nMapped = StringToNumber( Trim( sMapped ) );\r\n sNew = Expand('%nNewDim'| NumberToString(nIndexInTarget) |'%'); \r\n sNew = Subst( sNew , Scan( '.' , sNew )-1 , 99);\r\n nNew = StringToNumber( Trim( sNew ) );\r\n \r\n If(nMapped = 0 & nNew = 0 );\r\n # there's no input element and this dimension is not in the source\r\n nErrors = nErrors + 1;\r\n sTargetDimName = TabDim( pTgtCube, nIndexInTarget );\r\n sMessage = 'Dimension ' | sTargetDimName | ' is missing an input element in pMappingToNewDims';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n EndIf;\r\n \r\n nIndexInTarget = nIndexInTarget + 1;\r\nEND;\r\n\r\n\r\n############################# Clear out target ################################\r\n\r\n# Target is cleared for the elements specified in pMappingToNewDims\r\n# and for the parts of pFilter for dimensions in the target\r\n# This code works through pFilter looking for the parts relating to the target cube\r\n# the code which finds individual elements has been left in\r\n# so that it can be changed later to deal with consolidated elements\r\n\r\nsFilter = TRIM( pFilter );\r\nnChar = 1;\r\nnCharCount = LONG( sFilter );\r\nsWord = '';\r\nsLastDelim = '';\r\n\r\n# Add a trailing element delimiter so that the last Dimension:Element/s clause is picked up\r\nIf( nCharCount > 0 );\r\n sFilter = sFilter | sDelimElem;\r\n nCharCount = nCharCount + LONG(sDelimElem);\r\nEndIf;\r\n\r\nWHILE (nChar <= nCharCount);\r\n\r\n sChar = SUBST( sFilter, nChar, 1);\r\n\r\n # Used for delimiters, required for multiple character dilimiters\r\n sDelim = '';\r\n nAddExtra = 0;\r\n\r\n # Ignore spaces\r\n IF (TRIM(sChar) @<> '' );\r\n\r\n ### Dimension Name ###\r\n\r\n # If the delimiter is more than 1 character peek ahead the same amount\r\n # Ignore the first character\r\n sDelim = sChar;\r\n nCount = LONG(sElementStartDelim) - 1;\r\n If( nCount > 0 & nChar + nCount <= nCharCount );\r\n # Add the extra characters\r\n sDelim = sDelim | SUBST( sFilter, nChar + 1, nCount);\r\n # Move to the end of the delimter\r\n nAddExtra = nCount;\r\n EndIf;\r\n\r\n If( sDelim @= sElementStartDelim );\r\n\r\n sChar = sDelim;\r\n\r\n If( sLastDelim @<> '' & sLastDelim @<> sDelimDim );\r\n sMessage = 'In pFilter - the name of a dimension must follow a dimension delimiter (' | sDelimDim | ')';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n EndIf;\r\n\r\n # Found a dimension!\r\n sDimension = UPPER( sWord );\r\n nDimInTgt=0;\r\n # See if the dimension is in the target cube\r\n IF(scan('^^'|sDimension|'^^', sTgtDimString)>0);\r\n If(sTargetFilter@='');\r\n sTargetFilter = sDimension;\r\n Else; \r\n sTargetFilter = sTargetFilter | sDelimDim | sDimension;\r\n endif;\r\n nDimInTgt=1;\r\n Endif; \r\n\r\n sLastDelim = sChar;\r\n # Clear the word\r\n sWord = '';\r\n #reset element count\r\n nElementCount = 1;\r\n\r\n Else;\r\n\r\n # Reset extra chars\r\n nAddExtra = 0;\r\n\r\n ### Check both both dim delimiter and element delimiter ###\r\n nIsDelimiter = 0;\r\n\r\n ## Check dimension delimiter first\r\n # If the delimiter is more than 1 character peek ahead the same amount\r\n # Ignore the first character\r\n sDelim = sChar;\r\n nCount = LONG(sDelimDim) - 1;\r\n If( nCount > 0 & nChar + nCount <= nCharCount );\r\n # Add the extra characters\r\n sDelim = sDelim | SUBST( sFilter, nChar + 1, nCount);\r\n # Move to the end of the delimter\r\n nAddExtra = nCount;\r\n EndIf;\r\n\r\n If( sDelim @= sDelimDim );\r\n nIsDelimiter = 1;\r\n sChar = sDelim;\r\n Else;\r\n # Reset extra chars\r\n nAddExtra = 0;\r\n\r\n ## Check element delimiter\r\n\r\n # If the delimiter is more than 1 character peek ahead the same amount\r\n # Ignore the first character\r\n sDelim = sChar;\r\n nCount = LONG(sDelimElem) - 1;\r\n If( nCount > 0 & nChar + nCount <= nCharCount );\r\n # Add the extra characters\r\n sDelim = sDelim | SUBST( sFilter, nChar + 1, nCount);\r\n # Move to the end of the delimter\r\n nAddExtra = nCount;\r\n EndIf;\r\n\r\n If( sDelim @= sDelimElem );\r\n nIsDelimiter = 1;\r\n sChar = sDelim;\r\n Else;\r\n # Reset extra chars\r\n nAddExtra = 0;\r\n EndIf;\r\n\r\n EndIf;\r\n\r\n If ( nIsDelimiter = 1 );\r\n\r\n If( sLastDelim @= '' % sLastDelim @= sDelimDim );\r\n sMessage = 'In pFilter - an element delimiter must follow a dimension name: ' | sChar | ' (' | NumberToString(nChar) | ')';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n EndIf;\r\n\r\n # Found an element\r\n sElement = sWord;\r\n\r\n IF(DIMIX(sDimension, sElement) > 0 & nDimInTgt=1);\r\n # first element\r\n IF(nElementCount = 1);\r\n sTargetFilter = sTargetFilter | sElementStartDelim | sElement;\r\n # later elements\r\n Else;\r\n sTargetFilter = sTargetFilter | sDelimElem | sElement;\r\n EndIf;\r\n EndIf;\r\n\r\n nElementCount = nElementCount + 1;\r\n sLastDelim = sChar;\r\n\r\n # Clear the word\r\n sWord = '';\r\n Else;\r\n sWord = sWord | sChar;\r\n EndIf;\r\n\r\n EndIf;\r\n\r\n EndIf;\r\n\r\n nChar = nChar + nAddExtra + 1;\r\n\r\nEND;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n# Branch depending on whether to do recursive calls to self on independent threads or run all in this thread\r\nIf( Scan( pEleStartDelim, pFilterParallel ) > 0 );\r\n sDimParallel = SubSt( pFilterParallel, 1, Scan( pEleStartDelim, pFilterParallel ) - 1 );\r\n sElementList = SubSt( pFilterParallel, Scan( pEleStartDelim, pFilterParallel ) + 1, Long( pFilterParallel ) );\r\n If( SubSt( sElementList, Long( sElementList ), 1 ) @<> pEleDelim );\r\n sElementList = sElementList | pEleDelim;\r\n EndIf;\r\n ## Counting elements in element list\r\n sElementListCount = sElementList;\r\n nElements = 0;\r\n While( Scan( pEleDelim, sElementListCount ) > 0 );\r\n nElements = nElements + 1;\r\n sElementListCount = SubSt( sElementListCount, Scan( pEleDelim, sElementListCount ) + 1, Long( sElementListCount ) );\r\n End;\r\n IF( Mod( nElements, nMaxThreads ) = 0 );\r\n nElemsPerThread = INT( nElements / nMaxThreads );\r\n ELSE;\r\n nElemsPerThread = INT( nElements / nMaxThreads ) + 1;\r\n ENDIF;\r\n nThreadElCounter = 0;\r\n While( Scan( pEleDelim, sElementList ) > 0 );\r\n sSlicerEle = SubSt( sElementList, 1, Scan( pEleDelim, sElementList ) - 1 );\r\n sElementList = SubSt( sElementList, Scan( pEleDelim, sElementList ) + 1, Long( sElementList ) );\r\n # Do recursive process call with new RunProcess function\r\n nThreadElCounter = nThreadElCounter + 1;\r\n sDimDelim = If(pFilter @= '', '', pDimDelim );\r\n IF( nThreadElCounter = 1 );\r\n sFilter = Expand('%pFilter%%sDimDelim%%sDimParallel%%pEleStartDelim%%sSlicerEle%');\r\n ELSE;\r\n sFilter = Expand('%sFilter%%pEleDelim%%sSlicerEle%');\r\n ENDIF;\r\n IF( nThreadElCounter >= nElemsPerThread );\r\n RunProcess( cThisProcName, 'pLogoutput', pLogoutput,\r\n \t'pSrcCube', pSrcCube, 'pFilter', sFilter, 'pFilterParallel', '', 'pTgtCube', pTgtCube, 'pMappingToNewDims', pMappingToNewDims,\r\n \t'pSuppressConsol', pSuppressConsol, 'pSuppressConsolStrings', pSuppressConsolStrings, 'pSuppressRules', pSuppressRules, 'pSuppressZero', pSuppressZero, 'pZeroTarget', pZeroTarget, 'pZeroSource', pZeroSource,\r\n 'pFactor', pFactor, 'pDimDelim', pDimDelim, 'pEleStartDelim', pEleStartDelim, 'pEleDelim', pEleDelim,\r\n 'pTemp', pTemp, 'pCubeLogging', pCubeLogging, 'pSandbox', pSandbox, 'pFile', pFile, 'pThreadMode', 1\r\n );\r\n \t nThreadElCounter = 0;\r\n \t sFilter = '';\r\n \t ENDIF;\r\n End;\r\n ## Process last elements - only when filter is not empty (there are still elements)\r\n IF( sFilter @<> '' );\r\n RunProcess( cThisProcName, 'pLogoutput', pLogoutput,\r\n \t'pSrcCube', pSrcCube, 'pFilter', sFilter, 'pFilterParallel', '', 'pTgtCube', pTgtCube, 'pMappingToNewDims', pMappingToNewDims,\r\n \t'pSuppressConsol', pSuppressConsol, 'pSuppressConsolStrings', pSuppressConsolStrings, 'pSuppressRules', pSuppressRules, 'pSuppressZero', pSuppressZero, 'pZeroTarget', pZeroTarget, 'pZeroSource', pZeroSource,\r\n 'pFactor', pFactor, 'pDimDelim', pDimDelim, 'pEleStartDelim', pEleStartDelim, 'pEleDelim', pEleDelim,\r\n 'pTemp', pTemp, 'pCubeLogging', pCubeLogging, 'pSandbox', pSandbox, 'pFile', pFile, 'pThreadMode', 1\r\n );\r\n ENDIF; \r\n DataSourceType = 'NULL';\r\nElse;\r\n # Clear out target view\r\n If(pZeroTarget = 1 & LONG(sTargetFilter)>= 0 & nErrors = 0);\r\n ###### Create View of target to clear out ###\r\n # Create View of target ###\r\n nRet = ExecuteProcess('}bedrock.cube.view.create',\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pTgtCube,\r\n 'pView', sTargetView ,\r\n 'pFilter', sTargetFilter,\r\n 'pSuppressZero', pSuppressZero,\r\n 'pSuppressConsol', pSuppressConsol,\r\n 'pSuppressRules', pSuppressRules,\r\n 'pSuppressConsolStrings', pSuppressConsolStrings, \r\n 'pDimDelim', pDimDelim,\r\n 'pEleStartDelim', pEleStartDelim,\r\n 'pEleDelim', pEleDelim ,\r\n 'pTemp', pTemp\r\n );\r\n \r\n IF(nRet <> 0);\r\n sMessage = 'Error creating the view from the filter.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n \r\n nRet = ExecuteProcess( '}bedrock.cube.data.clear',\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pTgtCube,\r\n 'pView', sTargetView,\r\n 'pFilter', sTargetFilter,\r\n 'pDimDelim', pDimDelim,\r\n 'pEleStartDelim', pEleStartDelim,\r\n 'pEleDelim', pEleDelim,\r\n 'pTemp', pTemp,\r\n 'pCubeLogging', pCubeLogging,\r\n 'pSandbox', pSandbox\r\n );\r\n \r\n IF(nRet <> 0);\r\n sMessage = 'Error clearing the target view.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n \r\n Endif;\r\n \r\n If( pFile = 0 );\r\n ### Create View of Source ###\r\n IF(pSuppressConsol = 0 & pSuppressConsolStrings = 1);\r\n pSubN=1;\r\n else;\r\n pSubN=0;\r\n Endif; \r\n \r\n nRet = ExecuteProcess('}bedrock.cube.view.create',\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pSrcCube,\r\n 'pView', sView,\r\n 'pFilter', pFilter,\r\n 'pSuppressZero', pSuppressZero,\r\n 'pSuppressConsol', pSuppressConsol,\r\n 'pSuppressRules', pSuppressRules,\r\n 'pSuppressConsolStrings', pSuppressConsolStrings, \r\n 'pDimDelim', pDimDelim,\r\n 'pEleStartDelim', pEleStartDelim,\r\n 'pEleDelim', pEleDelim ,\r\n 'pTemp', pTemp,\r\n 'pSubN', pSubN\r\n );\r\n \r\n IF(nRet <> 0);\r\n sMessage = 'Error creating the view from the filter.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n \r\n ElseIf( pFile > 0 );\r\n ### Export to File in case of Copy Data Via File ###\r\n IF(pSuppressConsol = 0);\r\n pSubN=1;\r\n else;\r\n pSubN=0;\r\n Endif; \r\n \r\n nRet = ExecuteProcess('}bedrock.cube.data.export',\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pSrcCube,\r\n 'pView', sView,\r\n 'pFilter', pFilter,\r\n 'pFilterParallel', '',\r\n 'pParallelThreads', 0,\r\n 'pDimDelim', pDimDelim,\r\n 'pEleStartDelim', pEleStartDelim,\r\n 'pEleDelim', pEleDelim,\r\n 'pSuppressZero', pSuppressZero,\r\n 'pSuppressConsol', pSuppressConsol,\r\n 'pSuppressRules', pSuppressRules,\r\n 'pSuppressConsolStrings', pSuppressConsolStrings, \r\n 'pZeroSource', 0,\r\n 'pCubeLogging', pCubeLogging,\r\n 'pTemp', pTemp,\r\n 'pFilePath', cDir,\r\n 'pFileName', cFileName,\r\n 'pDelim', cDelimiter,\r\n 'pDecimalSeparator', sDecimalSeparator,\r\n 'pThousandSeparator', sThousandSeparator,\r\n 'pQuote', cQuote,\r\n 'pTitleRecord', cTitleRows,\r\n 'pSandbox', pSandbox,\r\n 'pSubN', pSubN\r\n );\r\n \r\n IF(nRet <> 0);\r\n sMessage = 'Error exporting data to file.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n ENDIF;\r\n \r\n ### Assign Datasource ###\r\n If( pFile = 0 );\r\n DataSourceType = 'VIEW';\r\n DatasourceNameForServer = pSrcCube;\r\n DatasourceNameForClient = pSrcCube;\r\n DatasourceCubeView = sView;\r\n ElseIf( pFile > 0 );\r\n DataSourceType = 'CHARACTERDELIMITED';\r\n DatasourceNameForServer = cFile;\r\n DatasourceNameForClient = cFile;\r\n DatasourceASCIIHeaderRecords = cTitleRows;\r\n DatasourceASCIIDelimiter = cDelimiter;\r\n DatasourceASCIIQuoteCharacter = cQuote;\r\n EndIf;\r\nEndIf;\r\n\r\n### End Prolog ###", + "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.data.copy.intercube', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pSrcCube', '', 'pFilter', '',\r\n \t'pFilterParallel', '', 'pParallelThreads', 0,\r\n \t'pTgtCube', '', 'pMappingToNewDims', '',\r\n \t'pSuppressConsol', 1, 'pSuppressConsolStrings', 0, 'pSuppressRules', 1, 'pSuppressZero', 1, \r\n \t'pZeroTarget', 1, 'pZeroSource', 0,\r\n \t'pFactor', 1,\r\n \t'pDimDelim', '&', 'pEleStartDelim', '\u00a6', 'pEleDelim', '+',\r\n \t'pTemp', 1, 'pCubeLogging', 0, 'pSandbox', pSandbox, 'pSubN', 0, \r\n \t'pFile', 0, 'pDelim', ',', 'pQuote', '\"', 'pDecimalSeparator', '.', 'pThousandSeparator', ','\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# ## Description\r\n# This is the process used to copy data from a source cube to a different target cube.\r\n# \r\n# ## Use Cases \r\n# 1. This process could be used to populate a Reporting cube from multiple source cubes.\r\n# 2. The process could be used to archive data from one cube to another one for any use.\r\n#\r\n# ## Notes\r\n# * The target cube may have a different number of dimensions as the source cube.\r\n# * Where the target and source cubes share the same dimensions, the process will match the dimensions even if their position in the cube is different.\r\n# * An input element must be specified for each dimension which is in the target but not in the source using the parameter pMappingToNewDims.\r\n# * The format of parameter pMappingToNewDims using default delimiters & and : is DimInTargetButNotSource1:ElementOfDim & DimInTargetButNotSource2:ElementOfDim.\r\n# * The input element must be an N level unless pSuppressConsol is set to 0.\r\n# * The maximum number of dimensions catered for in the target cube is 27. (In principle adding support for cubes with higher dimensionality is not difficult).\r\n#\r\n# For dimensions in the source but not the target, the process will accumulate the values of all n level elements\r\n# (or all n level elements specified by the pFilter parameter).\r\n# The pFilter parameter contains the dimensions and elements to be used for filtering the source cube.\r\n# The format of the pFilter parameter is as follows, using default delimiters & + : Dim1: Elem1 + Elem2 & Dim2: Elem3 + Elem4.\r\n# The dimension parameters do not need to be given in the index order of dimensions in the cube.\r\n# The dimension name is specified as the first member of the delimited string of elements.\r\n# If consolidations are skipped the N level children of any consolidated filter elements will be used.\r\n# Spaces are ignored so use them to make your filter more readable.\r\n# If using the pFilterParallel parameter the **single dimension** used as the \"parallelization slicer\" cannot appear in\r\n# the pFilter parameters.\r\n# When using parallelization via the *RunProcess* function the elements listed in pFilterParallel will be split one_at_a_time\r\n# and passed to a recursive call of the process being added to pFilter.\r\n#\r\n# An example:\r\n# To copy the 2011 Actual Sales data from the Sales cube to the General Ledger cube set pFilter to Year: 2011 & Version: Actual.\r\n# Say the General Ledger cube has an Account dimension but the Sales cube doesn't and the Account for sales is 9999 (an n level element).\r\n# Set the pMappingToNewDims parameter to Account:9999.\r\n# This will copy all Actual 2011 Sales to Account 9999 in the General Ledger.\r\n# If only sales for Company X are to be copied, set pFilter to Year: 2011 & Version: Actual & Company:X.\r\n# If sales from other companies are already in the General Ledger set pZeroTarget to 0 to add Company X's data to the existing data.\r\n# Setting pZeroTarget to 1 will clear our data in the target cube for the elements specified in the\r\n# pMappingToNewDims parameter and the pFilter parameter for dimensions that are in the target.\r\n#EndRegion @DOC\r\n\r\n### Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = '%cThisProcName% : %sMessage% : %cUserName%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pSrcCube:%pSrcCube%, pFilter:%pFilter%, pFilterParallel:%pFilterParallel%, pParallelThreads:%pParallelThreads%, pTgtCube:%pTgtCube%, pMappingToNewDims:%pMappingToNewDims%, pSuppressConsol:%pSuppressConsol%, pSuppressConsolStrings:%pSuppressConsolStrings%, pSuppressRules:%pSuppressRules%, pSuppressZero:%pSuppressZero%, pZeroTarget:%pZeroTarget%, pZeroSource:%pZeroSource%, pFactor:%pFactor%, pDimDelim:%pDimDelim%, pEleStartDelim:%pEleStartDelim%, pEleDelim:%pEleDelim%, pTemp:%pTemp%, pCubeLogging:%pCubeLogging%, pSandbox:%pSandbox%, pFile:%pFile%, pThreadMode:%pThreadMode%.';\r\n\r\n#################################################################################################\r\n#Region - Process Parameters\r\n\r\npJson = IF( JsonType( pJson ) @<> 'object', '{}', pJson );\r\nsMessages = '{\"Process\": \"'|GetProcessName()|'\", \"User\": \"'|TM1User()|'\", \"Info\": [\"Process: '''|GetProcessName()|''' run by User: '''|TM1User()|'''.\"], \"Error\": []}';\r\npDefaultParameters = '{\r\n \"pDecimalSeparator\": \".\",\r\n \"pDelim\": \"&\",\r\n \"pDimDelim\": \"&\",\r\n \"pEleDelim\": \"+\",\r\n \"pEleStartDelim\": \"\u00a6\",\r\n \"pFilter\": \"\",\r\n \"pFilterParallel\": \"\",\r\n \"pMappingToNewDims\": \"\",\r\n \"pQuote\": \"\"\",\r\n \"pSandbox\": \"\",\r\n \"pSrcCube\": null,\r\n \"pTgtCube\": null,\r\n \"pThousandSeparator\": \",\",\r\n \"pFactor\": 1,\r\n \"pFile\": 0,\r\n \"pLogOutput\": 0,\r\n \"pParallelThreads\": 0,\r\n \"pStrictErrorHandling\": 0,\r\n \"pSubN\": 0,\r\n \"pSuppressConsol\": 1,\r\n \"pSuppressConsolStrings\": 1,\r\n \"pSuppressRules\": 1,\r\n \"pSuppressZero\": 1,\r\n \"pTemp\": 1,\r\n \"pThreadMode\": 0,\r\n \"pZeroSource\": 0,\r\n \"pZeroTarget\": 1\r\n}';\r\n\r\npPassedParameters = '{\r\n \"pDecimalSeparator\": '|StringToJson ( pDecimalSeparator )|',\r\n \"pDelim\": '|StringToJson ( pDelim )|',\r\n \"pDimDelim\": '|StringToJson ( pDimDelim )|',\r\n \"pEleDelim\": '|StringToJson ( pEleDelim )|',\r\n \"pEleStartDelim\": '|StringToJson ( pEleStartDelim )|',\r\n \"pFilter\": '|StringToJson ( pFilter )|',\r\n \"pFilterParallel\": '|StringToJson ( pFilterParallel )|',\r\n \"pMappingToNewDims\": '|StringToJson ( pMappingToNewDims )|',\r\n \"pQuote\": '|StringToJson ( pQuote )|',\r\n \"pSandbox\": '|StringToJson ( pSandbox )|',\r\n \"pSrcCube\": '|StringToJson ( pSrcCube )|',\r\n \"pTgtCube\": '|StringToJson ( pTgtCube )|',\r\n \"pThousandSeparator\": '|StringToJson ( pThousandSeparator )|',\r\n \"pFactor\": '|NumberToString( pFactor )|',\r\n \"pFile\": '|NumberToString( pFile )|',\r\n \"pLogOutput\": '|NumberToString( pLogOutput )|',\r\n \"pParallelThreads\": '|NumberToString( pParallelThreads )|',\r\n \"pStrictErrorHandling\": '|NumberToString( pStrictErrorHandling )|',\r\n \"pSubN\": '|NumberToString( pSubN )|',\r\n \"pSuppressConsol\": '|NumberToString( pSuppressConsol )|',\r\n \"pSuppressConsolStrings\": '|NumberToString( pSuppressConsolStrings )|',\r\n \"pSuppressRules\": '|NumberToString( pSuppressRules )|',\r\n \"pSuppressZero\": '|NumberToString( pSuppressZero )|',\r\n \"pTemp\": '|NumberToString( pTemp )|',\r\n \"pThreadMode\": '|NumberToString( pThreadMode )|',\r\n \"pZeroSource\": '|NumberToString( pZeroSource )|',\r\n \"pZeroTarget\": '|NumberToString( pZeroTarget )|'\r\n}';\r\n\r\npJson = JsonMergePatch( pPassedParameters, pJson );\r\n# String Parameters\r\npDecimalSeparator = JsonToString( JsonGet( pJson, 'pDecimalSeparator' ) );\r\npDelim = JsonToString( JsonGet( pJson, 'pDelim' ) );\r\npDimDelim = JsonToString( JsonGet( pJson, 'pDimDelim' ) );\r\npEleDelim = JsonToString( JsonGet( pJson, 'pEleDelim' ) );\r\npEleStartDelim = JsonToString( JsonGet( pJson, 'pEleStartDelim' ) );\r\npFilter = JsonToString( JsonGet( pJson, 'pFilter' ) );\r\npFilterParallel = JsonToString( JsonGet( pJson, 'pFilterParallel' ) );\r\npMappingToNewDims = JsonToString( JsonGet( pJson, 'pMappingToNewDims' ) );\r\npQuote = JsonToString( JsonGet( pJson, 'pQuote' ) );\r\npSandbox = JsonToString( JsonGet( pJson, 'pSandbox' ) );\r\npSrcCube = JsonToString( JsonGet( pJson, 'pSrcCube' ) );\r\npTgtCube = JsonToString( JsonGet( pJson, 'pTgtCube' ) );\r\npThousandSeparator = JsonToString( JsonGet( pJson, 'pThousandSeparator' ) );\r\n# Numeric Parameters\r\npFactor = StringToNumber( JsonToString( JsonGet( pJson, 'pFactor' ) ) );\r\npFile = StringToNumber( JsonToString( JsonGet( pJson, 'pFile' ) ) );\r\npLogOutput = StringToNumber( JsonToString( JsonGet( pJson, 'pLogOutput' ) ) );\r\npParallelThreads = StringToNumber( JsonToString( JsonGet( pJson, 'pParallelThreads' ) ) );\r\npStrictErrorHandling = StringToNumber( JsonToString( JsonGet( pJson, 'pStrictErrorHandling' ) ) );\r\npSubN = StringToNumber( JsonToString( JsonGet( pJson, 'pSubN' ) ) );\r\npSuppressConsol = StringToNumber( JsonToString( JsonGet( pJson, 'pSuppressConsol' ) ) );\r\npSuppressConsolStrings = StringToNumber( JsonToString( JsonGet( pJson, 'pSuppressConsolStrings' ) ) );\r\npSuppressRules = StringToNumber( JsonToString( JsonGet( pJson, 'pSuppressRules' ) ) );\r\npSuppressZero = StringToNumber( JsonToString( JsonGet( pJson, 'pSuppressZero' ) ) );\r\npTemp = StringToNumber( JsonToString( JsonGet( pJson, 'pTemp' ) ) );\r\npThreadMode = StringToNumber( JsonToString( JsonGet( pJson, 'pThreadMode' ) ) );\r\npZeroSource = StringToNumber( JsonToString( JsonGet( pJson, 'pZeroSource' ) ) );\r\npZeroTarget = StringToNumber( JsonToString( JsonGet( pJson, 'pZeroTarget' ) ) );\r\n\r\n### Get the parameters that differ from the default\r\npDiffer = JsonDiff( pDefaultParameters, pJson );\r\nnSize = JsonSize( pDiffer );\r\nWHILE( nSize > 0 );\r\n nSize = nSize - 1;\r\n pDiffer = JsonReplace( pDiffer, '/'|NumberToString( nSize )|'/op', '\"add\"' );\r\nEND;\r\npJson = JsonPatch( '{}', pDiffer );\r\n\r\n### LogOutput parameters\r\nsMessages = JsonAdd( sMessages, '/Info/-', pJson );\r\nIF( pLogOutput = 1 );\r\n LogOutput('INFO', JsonToString( sMessages, '/Info/0', 0, ' ' ) );\r\nENDIF;\r\n\r\n#EndRegion - Process Parameters\r\n#################################################################################################\r\n\r\nsDelimDim = TRIM(pDimDelim);\r\nsElementStartDelim = TRIM(pElEStartDelim);\r\nsDelimElem = TRIM(pEleDelim);\r\nnErrors = 0;\r\ncLenASCIICode = 3;\r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\n# Make sure pFactor not zero\r\nnFactor = If( pFactor = 0, 1, pFactor );\r\n\r\nsView = cThisProcName | cTimeStamp | cRandomInt;\r\nsSubset = sView;\r\nsTargetView = 'Target '| sView;\r\nsTargetSubset = sTargetView;\r\n\r\n## check operating system\r\nIf( SubSt( GetProcessErrorFileDirectory, 2, 1 ) @= ':' );\r\n sOS = 'Windows';\r\n sOSDelim = '\\';\r\nElseIf( Scan( '/', GetProcessErrorFileDirectory ) > 0 );\r\n sOS = 'Linux';\r\n sOSDelim = '/';\r\nElse;\r\n sOS = 'Windows';\r\n sOSDelim = '\\';\r\nEndIf;\r\n\r\n## File location for indirect data copy\r\ncDir = GetProcessErrorFileDirectory;\r\ncFileName = pSrcCube | cTimeStamp | cRandomInt | '.csv';\r\ncFile = cDir | cFileName;\r\ncTitleRows = 1;\r\n\r\n# Validate file delimiter & quote character\r\nIf( pDelim @= '' );\r\n pDelim = ',';\r\nElse;\r\n # If length of pDelim is exactly 3 chars and each of them is decimal digit, then the pDelim is entered as ASCII code\r\n nValid = 0;\r\n If ( LONG(pDelim) = cLenASCIICode );\r\n nChar = 1;\r\n While ( nChar <= cLenASCIICode );\r\n If( CODE( pDelim, nChar ) >= CODE( '0', 1 ) & CODE( pDelim, nChar ) <= CODE( '9', 1 ) );\r\n nValid = 1;\r\n Else;\r\n nValid = 0;\r\n Break;\r\n EndIf;\r\n nChar = nChar + 1;\r\n End;\r\n EndIf;\r\n If ( nValid<>0 );\r\n pDelim=CHAR(StringToNumber( pDelim ));\r\n Else;\r\n pDelim = SubSt( Trim( pDelim ), 1, 1 );\r\n EndIf;\r\nEndIf;\r\ncDelimiter = pDelim;\r\n\r\nIf( pQuote @= '' );\r\n ## Use no quote character\r\nElse;\r\n # If length of pQuote is exactly 3 chars and each of them is decimal digit, then the pQuote is entered as ASCII code\r\n nValid = 0;\r\n If ( LONG(pQuote) = cLenASCIICode );\r\n nChar = 1;\r\n While ( nChar <= cLenASCIICode );\r\n If( CODE( pQuote, nChar ) >= CODE( '0', 1 ) & CODE( pQuote, nChar ) <= CODE( '9', 1 ) );\r\n nValid = 1;\r\n Else;\r\n nValid = 0;\r\n Break;\r\n EndIf;\r\n nChar = nChar + 1;\r\n End;\r\n EndIf;\r\n If ( nValid<>0 );\r\n pQuote=CHAR(StringToNumber( pQuote ));\r\n Else;\r\n pQuote = SubSt( Trim( pQuote ), 1, 1 );\r\n EndIf;\r\nEndIf;\r\ncQuote = pQuote;\r\n\r\n#Region ## Check Parameters ###\r\n\r\n## Default filter delimiters\r\nIf( pDimDelim @= '' );\r\n pDimDelim = '&';\r\nEndIf;\r\nIf( pEleStartDelim@= '' );\r\n pEleStartDelim= '\u00a6';\r\nEndIf;\r\nIf( pEleDelim @= '' );\r\n pEleDelim = '+';\r\nEndIf;\r\n\r\nIf( pDecimalSeparator @= '' );\r\n \tpDecimalSeparator = '.';\r\nEndIf;\r\nIf ( LONG(pDecimalSeparator) = cLenASCIICode );\r\n nValid = 0;\r\n nChar = 1;\r\n While ( nChar <= cLenASCIICode );\r\n If( CODE( pDecimalSeparator, nChar ) >= CODE( '0', 1 ) & CODE( pDecimalSeparator, nChar ) <= CODE( '9', 1 ) );\r\n nValid = 1;\r\n Else;\r\n nValid = 0;\r\n Break;\r\n EndIf;\r\n nChar = nChar + 1;\r\n End;\r\n If ( nValid<>0 );\r\n pDecimalSeparator = CHAR(StringToNumber( pDecimalSeparator ));\r\n Else;\r\n pDecimalSeparator = SubSt( Trim( pDecimalSeparator ), 1, 1 );\r\n EndIf;\r\nEndIf;\r\nsDecimalSeparator = pDecimalSeparator;\r\n\r\nIf( pThousandSeparator @= '' );\r\n \tpThousandSeparator = ',';\r\nEndIf;\r\nIf ( LONG(pThousandSeparator) = cLenASCIICode );\r\n nValid = 0;\r\n nChar = 1;\r\n While ( nChar <= cLenASCIICode );\r\n If( CODE( pThousandSeparator, nChar ) >= CODE( '0', 1 ) & CODE( pThousandSeparator, nChar ) <= CODE( '9', 1 ) );\r\n nValid = 1;\r\n Else;\r\n nValid = 0;\r\n Break;\r\n EndIf;\r\n nChar = nChar + 1;\r\n End;\r\n If ( nValid<>0 );\r\n pThousandSeparator = CHAR(StringToNumber( pThousandSeparator ));\r\n Else;\r\n pThousandSeparator = SubSt( Trim( pThousandSeparator ), 1, 1 );\r\n EndIf;\r\nEndIf;\r\nsThousandSeparator = pThousandSeparator;\r\n\r\n# If specified source cube doesn't exist then terminate process\r\nIf( CubeExists( pSrcCube ) = 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'Invalid source cube specified: %pSrcCube%.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# If specified target cube doesn't exist then terminate process\r\nIf( CubeExists( pTgtCube ) = 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'Invalid target cube specified: %pTgtCube%.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate parallelization filter\r\nIf( Scan( pEleStartDelim, pFilterParallel ) > 0 );\r\n sDimParallel = SubSt( pFilterParallel, 1, Scan( pEleStartDelim, pFilterParallel ) - 1 );\r\n If( Scan( Lower(sDimParallel) | pEleStartDelim, Lower(pFilter) ) > 0 );\r\n sMessage = 'Parallelization dimension %sDimParallel% cannot exist in filter.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\nEndIf;\r\n\r\n# Validate Max Threads\r\nIf( pParallelThreads > 0 );\r\n nMaxThreads = pParallelThreads;\r\nElse;\r\n nMaxThreads = 1;\r\nEndIf;\r\n\r\n# Validate Sandbox\r\nIf( TRIM( pSandbox ) @<> '' );\r\n If( ServerSandboxExists( pSandbox ) = 0 );\r\n SetUseActiveSandboxProperty( 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand('Sandbox %pSandbox% is invalid for the current user.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n Else;\r\n ServerActiveSandboxSet( pSandbox );\r\n SetUseActiveSandboxProperty( 1 );\r\n EndIf;\r\nElse;\r\n SetUseActiveSandboxProperty( 0 );\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n#EndRegion\r\n#Region \r\n## Set variables =0 or '' ################################################################################################# ########################\r\n### Placeholders for mappped dimensions\r\nnMappedDim1 = 0;\r\nnMappedDim2 = 0;\r\nnMappedDim3 = 0;\r\nnMappedDim4 = 0;\r\nnMappedDim5 = 0;\r\nnMappedDim6 = 0;\r\nnMappedDim7 = 0;\r\nnMappedDim8 = 0;\r\nnMappedDim9 = 0;\r\nnMappedDim10 = 0;\r\nnMappedDim11 = 0;\r\nnMappedDim12 = 0;\r\nnMappedDim13 = 0;\r\nnMappedDim14 = 0;\r\nnMappedDim15 = 0;\r\nnMappedDim16 = 0;\r\nnMappedDim17 = 0;\r\nnMappedDim18 = 0;\r\nnMappedDim19 = 0;\r\nnMappedDim20 = 0;\r\nnMappedDim21 = 0;\r\nnMappedDim22 = 0;\r\nnMappedDim23 = 0;\r\nnMappedDim24 = 0;\r\nnMappedDim25 = 0;\r\nnMappedDim26 = 0;\r\nnMappedDim27 = 0;\r\n\r\nsMappedV1 = '';\r\nsMappedV2 = '';\r\nsMappedV3 = '';\r\nsMappedV4 = '';\r\nsMappedV5 = '';\r\nsMappedV6 = '';\r\nsMappedV7 = '';\r\nsMappedV8 = '';\r\nsMappedV9 = '';\r\nsMappedV10 = '';\r\nsMappedV11 = '';\r\nsMappedV12 = '';\r\nsMappedV13 = '';\r\nsMappedV14 = '';\r\nsMappedV15 = '';\r\nsMappedV16 = '';\r\nsMappedV17 = '';\r\nsMappedV18 = '';\r\nsMappedV19 = '';\r\nsMappedV20 = '';\r\nsMappedV21 = '';\r\nsMappedV22 = '';\r\nsMappedV23 = '';\r\nsMappedV24 = '';\r\nsMappedV25 = '';\r\nsMappedV26 = '';\r\nsMappedV27 = '';\r\nsMappedV28 = '';\r\n\r\n### Placeholders for new dimensions\r\nnNewDim1 = 0;\r\nnNewDim2 = 0;\r\nnNewDim3 = 0;\r\nnNewDim4 = 0;\r\nnNewDim5 = 0;\r\nnNewDim6 = 0;\r\nnNewDim7 = 0;\r\nnNewDim8 = 0;\r\nnNewDim9 = 0;\r\nnNewDim10 = 0;\r\nnNewDim11 = 0;\r\nnNewDim12 = 0;\r\nnNewDim13 = 0;\r\nnNewDim14 = 0;\r\nnNewDim15 = 0;\r\nnNewDim16 = 0;\r\nnNewDim17 = 0;\r\nnNewDim18 = 0;\r\nnNewDim19 = 0;\r\nnNewDim20 = 0;\r\nnNewDim21 = 0;\r\nnNewDim22 = 0;\r\nnNewDim23 = 0;\r\nnNewDim24 = 0;\r\nnNewDim25 = 0;\r\nnNewDim26 = 0;\r\nnNewDim27 = 0;\r\n\r\nsNewV1 = '';\r\nsNewV2 = '';\r\nsNewV3 = '';\r\nsNewV4 = '';\r\nsNewV5 = '';\r\nsNewV6 = '';\r\nsNewV7 = '';\r\nsNewV8 = '';\r\nsNewV9 = '';\r\nsNewV10 = '';\r\nsNewV11 = '';\r\nsNewV12 = '';\r\nsNewV13 = '';\r\nsNewV14 = '';\r\nsNewV15 = '';\r\nsNewV16 = '';\r\nsNewV17 = '';\r\nsNewV18 = '';\r\nsNewV19 = '';\r\nsNewV20 = '';\r\nsNewV21 = '';\r\nsNewV22 = '';\r\nsNewV23 = '';\r\nsNewV24 = '';\r\nsNewV25 = '';\r\nsNewV26 = '';\r\nsNewV27 = '';\r\n\r\n### Determine dimensions in target cube, we need to know this to test cell type before loading ###\r\n# only numbers get converted from strings to numbers\r\nsDim1 = TabDim( pTgtCube, 1 );\r\nsDim2 = TabDim( pTgtCube, 2 );\r\nsDim3 = TabDim( pTgtCube, 3 );\r\nsDim4 = TabDim( pTgtCube, 4 );\r\nsDim5 = TabDim( pTgtCube, 5 );\r\nsDim6 = TabDim( pTgtCube, 6 );\r\nsDim7 = TabDim( pTgtCube, 7 );\r\nsDim8 = TabDim( pTgtCube, 8 );\r\nsDim9 = TabDim( pTgtCube, 9 );\r\nsDim10 = TabDim( pTgtCube, 10 );\r\nsDim11 = TabDim( pTgtCube, 11 );\r\nsDim12 = TabDim( pTgtCube, 12 );\r\nsDim13 = TabDim( pTgtCube, 13 );\r\nsDim14 = TabDim( pTgtCube, 14 );\r\nsDim15 = TabDim( pTgtCube, 15 );\r\nsDim16 = TabDim( pTgtCube, 16 );\r\nsDim17 = TabDim( pTgtCube, 17 );\r\nsDim18 = TabDim( pTgtCube, 18 );\r\nsDim19 = TabDim( pTgtCube, 19 );\r\nsDim20 = TabDim( pTgtCube, 20 );\r\nsDim21 = TabDim( pTgtCube, 21 );\r\nsDim22 = TabDim( pTgtCube, 22 );\r\nsDim23 = TabDim( pTgtCube, 23 );\r\nsDim24 = TabDim( pTgtCube, 24 );\r\nsDim25 = TabDim( pTgtCube, 25 );\r\nsDim26 = TabDim( pTgtCube, 26 );\r\nsDim27 = TabDim( pTgtCube, 27 );\r\n#EndRegion\r\nsTgtDimString = '^^'|sDim1|'^^'|sDim2|'^^'|sDim3|'^^'|sDim4|'^^'|sDim5|'^^'|sDim6|'^^'|sDim7|'^^'|sDim8|'^^'|sDim9|'^^'|sDim10|'^^'\r\n |sDim11|'^^'|sDim12|'^^'|sDim13|'^^'|sDim14|'^^'|sDim15|'^^'|sDim16|'^^'|sDim17|'^^'|sDim18|'^^'|sDim19|'^^'|sDim20|'^^'\r\n |sDim21|'^^'|sDim22|'^^'|sDim23|'^^'|sDim24|'^^'|sDim25|'^^'|sDim26|'^^'|sDim27|'^^';\r\n\r\n### We have to remove spaces from the search string before going to include the string in searching loop\r\nsTgtDimString = UPPER( sTgtDimString );\r\nnSPIndex = SCAN( ' ', sTgtDimString );\r\nWhile ( nSPIndex <> 0);\r\n sTgtDimString = DELET( sTgtDimString, nSPIndex, 1 );\r\n nSPIndex = SCAN( ' ', sTgtDimString );\r\nEnd;\r\n\r\n###########################################\r\n#Region ### MAPPING Target DIMENSIONS #####\r\n###########################################\r\nnSourceIndex = 1;\r\nWhile( TabDim( pSrcCube, nSourceIndex ) @<> '' );\r\n sSourceDim = TabDim( pSrcCube, nSourceIndex);\r\n # reset target index if another source dimension has been found\r\n nTargetIndex = 1;\r\n WHILE(TabDim( pTgtCube, nTargetIndex ) @<> '');\r\n sTargetDim = TabDim( pTgtCube, nTargetIndex );\r\n If(sSourceDim @= sTargetDim);\r\n If( pFile = 0 );\r\n If(nTargetIndex = 1);\r\n nMappedDim1 = 1;\r\n sMappedV1 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 2);\r\n nMappedDim2 = 1;\r\n sMappedV2 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 3);\r\n nMappedDim3 = 1;\r\n sMappedV3 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 4);\r\n nMappedDim4 = 1;\r\n sMappedV4 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 5);\r\n nMappedDim5 = 1;\r\n sMappedV5 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 6);\r\n nMappedDim6 = 1;\r\n sMappedV6 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 7);\r\n nMappedDim7 = 1;\r\n sMappedV7 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 8);\r\n nMappedDim8 = 1;\r\n sMappedV8 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 9);\r\n nMappedDim9 = 1;\r\n sMappedV9 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 10);\r\n nMappedDim10 = 1;\r\n sMappedV10 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 11);\r\n nMappedDim11 = 1;\r\n sMappedV11 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 12);\r\n nMappedDim12 = 1;\r\n sMappedV12 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 13);\r\n nMappedDim13 = 1;\r\n sMappedV13 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 14);\r\n nMappedDim14 = 1;\r\n sMappedV14 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 15);\r\n nMappedDim15 = 1;\r\n sMappedV15 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 16);\r\n nMappedDim16 = 1;\r\n sMappedV16 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 17);\r\n nMappedDim17 = 1;\r\n sMappedV17 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 18);\r\n nMappedDim18 = 1;\r\n sMappedV18 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 19);\r\n nMappedDim19 = 1;\r\n sMappedV19 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 20);\r\n nMappedDim20 = 1;\r\n sMappedV20 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 21);\r\n nMappedDim21 = 1;\r\n sMappedV21 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 22);\r\n nMappedDim22 = 1;\r\n sMappedV22 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 23);\r\n nMappedDim23 = 1;\r\n sMappedV23 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 24);\r\n nMappedDim24 = 1;\r\n sMappedV24 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 25);\r\n nMappedDim25 = 1;\r\n sMappedV25 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 26);\r\n nMappedDim26 = 1;\r\n sMappedV26 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 27);\r\n nMappedDim27 = 1;\r\n sMappedV27 = 'V' | NumberToString(nSourceIndex);\r\n EndIf;\r\n ElseIf( pFile > 0 );\r\n ## If using source file first variable holds tha cube name, so all the other ones have the index increased by 1\r\n If(nTargetIndex = 1);\r\n nMappedDim1 = 1;\r\n sMappedV1 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 2);\r\n nMappedDim2 = 1;\r\n sMappedV2 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 3);\r\n nMappedDim3 = 1;\r\n sMappedV3 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 4);\r\n nMappedDim4 = 1;\r\n sMappedV4 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 5);\r\n nMappedDim5 = 1;\r\n sMappedV5 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 6);\r\n nMappedDim6 = 1;\r\n sMappedV6 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 7);\r\n nMappedDim7 = 1;\r\n sMappedV7 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 8);\r\n nMappedDim8 = 1;\r\n sMappedV8 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 9);\r\n nMappedDim9 = 1;\r\n sMappedV9 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 10);\r\n nMappedDim10 = 1;\r\n sMappedV10 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 11);\r\n nMappedDim11 = 1;\r\n sMappedV11 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 12);\r\n nMappedDim12 = 1;\r\n sMappedV12 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 13);\r\n nMappedDim13 = 1;\r\n sMappedV13 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 14);\r\n nMappedDim14 = 1;\r\n sMappedV14 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 15);\r\n nMappedDim15 = 1;\r\n sMappedV15 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 16);\r\n nMappedDim16 = 1;\r\n sMappedV16 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 17);\r\n nMappedDim17 = 1;\r\n sMappedV17 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 18);\r\n nMappedDim18 = 1;\r\n sMappedV18 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 19);\r\n nMappedDim19 = 1;\r\n sMappedV19 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 20);\r\n nMappedDim20 = 1;\r\n sMappedV20 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 21);\r\n nMappedDim21 = 1;\r\n sMappedV21 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 22);\r\n nMappedDim22 = 1;\r\n sMappedV22 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 23);\r\n nMappedDim23 = 1;\r\n sMappedV23 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 24);\r\n nMappedDim24 = 1;\r\n sMappedV24 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 25);\r\n nMappedDim25 = 1;\r\n sMappedV25 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 26);\r\n nMappedDim26 = 1;\r\n sMappedV26 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 27);\r\n nMappedDim27 = 1;\r\n sMappedV27 = 'V' | NumberToString(nSourceIndex + 1);\r\n EndIf;\r\n EndIf;\r\n\r\n EndIf;\r\n\r\n nTargetIndex = nTargetIndex + 1;\r\n\r\n END;\r\n\r\n nSourceIndex = nSourceIndex + 1;\r\n\r\nEND;\r\n\r\n# The last variable in the data source holds the values\r\n# which need to be mapped to the last variable in the target\r\n\r\nIf( pFile = 0 );\r\n If(nTargetIndex = 1);\r\n nMappedDim1 = 1;\r\n sMappedV1 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 2);\r\n nMappedDim2 = 1;\r\n sMappedV2 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 3);\r\n nMappedDim3 = 1;\r\n sMappedV3 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 4);\r\n nMappedDim4 = 1;\r\n sMappedV4 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 5);\r\n nMappedDim5 = 1;\r\n sMappedV5 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 6);\r\n nMappedDim6 = 1;\r\n sMappedV6 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 7);\r\n nMappedDim7 = 1;\r\n sMappedV7 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 8);\r\n nMappedDim8 = 1;\r\n sMappedV8 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 9);\r\n nMappedDim9 = 1;\r\n sMappedV9 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 10);\r\n nMappedDim10 = 1;\r\n sMappedV10 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 11);\r\n nMappedDim11 = 1;\r\n sMappedV11 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 12);\r\n nMappedDim12 = 1;\r\n sMappedV12 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 13);\r\n nMappedDim13 = 1;\r\n sMappedV13 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 14);\r\n nMappedDim14 = 1;\r\n sMappedV14 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 15);\r\n nMappedDim15 = 1;\r\n sMappedV15 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 16);\r\n nMappedDim16 = 1;\r\n sMappedV16 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 17);\r\n nMappedDim17 = 1;\r\n sMappedV17 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 18);\r\n nMappedDim18 = 1;\r\n sMappedV18 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 19);\r\n nMappedDim19 = 1;\r\n sMappedV19 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 20);\r\n nMappedDim20 = 1;\r\n sMappedV20 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 21);\r\n nMappedDim21 = 1;\r\n sMappedV21 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 22);\r\n nMappedDim22 = 1;\r\n sMappedV22 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 23);\r\n nMappedDim23 = 1;\r\n sMappedV23 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 24);\r\n nMappedDim24 = 1;\r\n sMappedV24 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 25);\r\n nMappedDim25 = 1;\r\n sMappedV25 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 26);\r\n nMappedDim26 = 1;\r\n sMappedV26 = 'V' | NumberToString(nSourceIndex);\r\n ElseIf(nTargetIndex = 27);\r\n nMappedDim27 = 1;\r\n sMappedV27 = 'V' | NumberToString(nSourceIndex);\r\n \r\n # a cube with 27 dimensions uses V28 to hold the values\r\n ElseIf(nTargetIndex = 28);\r\n nMappedDim28 = 1;\r\n sMapped28 = 'V' | NumberToString(nSourceIndex);\r\n EndIf;\r\nElseIf( pFile > 0 );\r\n If(nTargetIndex = 1);\r\n nMappedDim1 = 1;\r\n sMappedV1 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 2);\r\n nMappedDim2 = 1;\r\n sMappedV2 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 3);\r\n nMappedDim3 = 1;\r\n sMappedV3 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 4);\r\n nMappedDim4 = 1;\r\n sMappedV4 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 5);\r\n nMappedDim5 = 1;\r\n sMappedV5 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 6);\r\n nMappedDim6 = 1;\r\n sMappedV6 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 7);\r\n nMappedDim7 = 1;\r\n sMappedV7 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 8);\r\n nMappedDim8 = 1;\r\n sMappedV8 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 9);\r\n nMappedDim9 = 1;\r\n sMappedV9 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 10);\r\n nMappedDim10 = 1;\r\n sMappedV10 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 11);\r\n nMappedDim11 = 1;\r\n sMappedV11 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 12);\r\n nMappedDim12 = 1;\r\n sMappedV12 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 13);\r\n nMappedDim13 = 1;\r\n sMappedV13 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 14);\r\n nMappedDim14 = 1;\r\n sMappedV14 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 15);\r\n nMappedDim15 = 1;\r\n sMappedV15 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 16);\r\n nMappedDim16 = 1;\r\n sMappedV16 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 17);\r\n nMappedDim17 = 1;\r\n sMappedV17 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 18);\r\n nMappedDim18 = 1;\r\n sMappedV18 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 19);\r\n nMappedDim19 = 1;\r\n sMappedV19 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 20);\r\n nMappedDim20 = 1;\r\n sMappedV20 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 21);\r\n nMappedDim21 = 1;\r\n sMappedV21 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 22);\r\n nMappedDim22 = 1;\r\n sMappedV22 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 23);\r\n nMappedDim23 = 1;\r\n sMappedV23 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 24);\r\n nMappedDim24 = 1;\r\n sMappedV24 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 25);\r\n nMappedDim25 = 1;\r\n sMappedV25 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 26);\r\n nMappedDim26 = 1;\r\n sMappedV26 = 'V' | NumberToString(nSourceIndex + 1);\r\n ElseIf(nTargetIndex = 27);\r\n nMappedDim27 = 1;\r\n sMappedV27 = 'V' | NumberToString(nSourceIndex + 1);\r\n \r\n # a cube with 27 dimensions uses V29 to hold the values if export file is used as source\r\n ElseIf(nTargetIndex = 28);\r\n nMappedDim28 = 1;\r\n sMapped28 = 'V' | NumberToString(nSourceIndex + 1);\r\n EndIf;\r\nEndIf;\r\n#EndRegion\r\n\r\n###########################################\r\n### SPLIT MAPPING TO NEW DIMS PARAMETER ###\r\n###########################################\r\n\r\n# now deduct 1 to set these indices to the number of dimensions in each cube\r\nnSourceDimensionCount = nSourceIndex - 1;\r\nnTargetCubeDimensionCount = nTargetIndex - 1;\r\n# default dimension count is for target\r\nnDimensionCount = nTargetIndex - 1;\r\n\r\nsElementMapping = TRIM( pMappingToNewDims );\r\nnChar = 1;\r\nnCharCount = LONG( sElementMapping );\r\n\r\nsTargetFilter = '';\r\nsWord = '';\r\nsLastDelim = '';\r\nnIndex = 1;\r\n\r\n# Add a trailing element delimiter so that the last element is picked up\r\nIf( nCharCount > 0 );\r\n sElementMapping = sElementMapping | sDelimDim;\r\n nCharCount = nCharCount + LONG(sDelimDim);\r\nEndIf;\r\n\r\nWHILE (nChar <= nCharCount);\r\n sChar = SUBST( sElementMapping, nChar, 1);\r\n\r\n # Used for delimiters, required for multiple character delimiters\r\n sDelim = '';\r\n nAddExtra = 0;\r\n\r\n # Ignore spaces\r\n IF (TRIM(sChar) @<> '' );\r\n\r\n ### Dimension Name ###\r\n\r\n # If the delimiter is more than 1 character peek ahead the same amount\r\n # Ignore the first character\r\n sDelim = sChar;\r\n nCount = LONG(sElementStartDelim) - 1;\r\n If( nCount > 0 & nChar + nCount <= nCharCount );\r\n # Add the extra characters\r\n sDelim = sDelim | SUBST( sElementMapping, nChar + 1, nCount);\r\n # Move to the end of the delimter\r\n nAddExtra = nCount;\r\n EndIf;\r\n\r\n If( sDelim @= sElementStartDelim );\r\n\r\n sChar = sDelim;\r\n\r\n If( sLastDelim @<> '' & sLastDelim @<> sDelimDim );\r\n sMessage = 'In pMappingToNewDims the name of a dimension must follow a dimension delimiter (' | sDelimDim | ')';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n EndIf;\r\n\r\n # Found a dimension\r\n sDimension = sWord;\r\n\r\n If( DimensionExists( sDimension ) = 0 );\r\n # The dimension does not exist in the model. Cancel process\r\n sMessage = 'In pMappingToNewDims - Dimension: ' | sDimension | ' does not exist';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n EndIf;\r\n\r\n # Find the index of the dimension is in the Target cube\r\n nTargetIndexCounter = 1;\r\n\r\n WHILE(nTargetIndexCounter <= nTargetCubeDimensionCount );\r\n sNthDimension = TabDim( pTgtCube, nTargetIndexCounter );\r\n\r\n If(sDimension @= sNthDimension);\r\n nTargetIndex = nTargetIndexCounter;\r\n nTargetIndexCounter = 1000;\r\n EndIf;\r\n\r\n nTargetIndexCounter = nTargetIndexCounter + 1;\r\n END;\r\n \r\n #Add to the Target filter\r\n IF(sTargetFilter@='');\r\n sTargetFilter=sDimension; \r\n Else;\r\n sTargetFilter=sTargetFilter|sDelimDim|sDimension;\r\n Endif; \r\n \r\n sLastDelim = sChar;\r\n # Clear the word\r\n sWord = '';\r\n\r\n Else;\r\n\r\n # Reset extra chars\r\n nAddExtra = 0;\r\n\r\n ### Check both dim delimiter and element delimiter ###\r\n nIsDelimiter = 0;\r\n\r\n ## Check dimension delimiter first\r\n # If the delimiter is more than 1 character peek ahead the same amount\r\n # Ignore the first character\r\n sDelim = sChar;\r\n nCount = LONG(sDelimDim) - 1;\r\n If( nCount > 0 & nChar + nCount <= nCharCount );\r\n # Add the extra characters\r\n sDelim = sDelim | SUBST( sElementMapping, nChar + 1, nCount);\r\n EndIf;\r\n\r\n If( sDelim @= sDelimDim );\r\n nIsDelimiter = 1;\r\n sChar = sDelim;\r\n \r\n # Move to the end of the delimter\r\n nAddExtra = nCount;\r\n EndIf;\r\n\r\n If ( nIsDelimiter = 1 );\r\n\r\n If( sLastDelim @= '' % sLastDelim @= sDelimDim );\r\n sMessage = 'In pMappingToNewDims - an element delimiter must follow a dimension name: ' | sChar | ' (' | NumberToString(nChar) | ')';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n EndIf;\r\n\r\n # an element has been found\r\n sElement = sWord;\r\n\r\n If( DIMIX( sDimension, sElement ) = 0 );\r\n # The element does not exist in the dimension. Cancel process\r\n sMessage = 'In pMappingToNewDims - Element: ' | sElement | ' in dimension ' | sDimension | ' does not exist';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n EndIf;\r\n\r\n # Allow consolidations only if pSuppressConsol is set to 0\r\n\r\n If ( DTYPE( sDimension, sElement) @= 'C' );\r\n sMessage = Expand( 'In pMappingToNewDims - Target element: %sElement% for dimension %sDimension% is consolidated' );\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n Endif; \r\n \r\n\r\n # Add the element to the source or target depending on whether it's the first or the second element\r\n # Get principal name\r\n # in case source element and this element are using different aliases\r\n\r\n sElement = DimensionElementPrincipalName(sDimension,sElement);\r\n\r\n ### Update the variable for InputElement Target Dim ######################################\r\n If(nTargetIndex = 1);\r\n nNewDim1 = 1;\r\n sNewV1 = sElement;\r\n ElseIf(nTargetIndex = 2);\r\n nNewDim2 = 1;\r\n sNewV2 = sElement;\r\n ElseIf(nTargetIndex = 3);\r\n nNewDim3 = 1;\r\n sNewV3 = sElement;\r\n ElseIf(nTargetIndex = 4);\r\n nNewDim4 = 1;\r\n sNewV4 = sElement;\r\n ElseIf(nTargetIndex = 5);\r\n nNewDim5 = 1;\r\n sNewV5 = sElement;\r\n ElseIf(nTargetIndex = 6);\r\n nNewDim6 = 1;\r\n sNewV6 = sElement;\r\n ElseIf(nTargetIndex = 7);\r\n nNewDim7 = 1;\r\n sNewV7 = sElement;\r\n ElseIf(nTargetIndex = 8);\r\n nNewDim8 = 1;\r\n sNewV8 = sElement;\r\n ElseIf(nTargetIndex = 9);\r\n nNewDim9 = 1;\r\n sNewV9 = sElement;\r\n ElseIf(nTargetIndex = 10);\r\n nNewDim10 = 1;\r\n sNewV10 = sElement;\r\n ElseIf(nTargetIndex = 11);\r\n nNewDim11 = 1;\r\n sNewV11 = sElement;\r\n ElseIf(nTargetIndex = 12);\r\n nNewDim12 = 1;\r\n sNewV12 = sElement;\r\n ElseIf(nTargetIndex = 13);\r\n nNewDim13 = 1;\r\n sNewV13 = sElement;\r\n ElseIf(nTargetIndex = 14);\r\n nNewDim14 = 1;\r\n sNewV14 = sElement;\r\n ElseIf(nTargetIndex = 15);\r\n nNewDim15 = 1;\r\n sNewV15 = sElement;\r\n ElseIf(nTargetIndex = 16);\r\n nNewDim16 = 1;\r\n sNewV16 = sElement;\r\n ElseIf(nTargetIndex = 17);\r\n nNewDim17 = 1;\r\n sNewV17 = sElement;\r\n ElseIf(nTargetIndex = 18);\r\n nNewDim18 = 1;\r\n sNewV18 = sElement;\r\n ElseIf(nTargetIndex = 19);\r\n nNewDim19 = 1;\r\n sNewV19 = sElement;\r\n ElseIf(nTargetIndex = 20);\r\n nNewDim20 = 1;\r\n sNewV20 = sElement;\r\n ElseIf(nTargetIndex = 21);\r\n nNewDim21 = 1;\r\n sNewV21 = sElement;\r\n ElseIf(nTargetIndex = 22);\r\n nNewDim22 = 1;\r\n sNewV22 = sElement;\r\n ElseIf(nTargetIndex = 23);\r\n nNewDim23 = 1;\r\n sNewV23 = sElement;\r\n ElseIf(nTargetIndex = 24);\r\n nNewDim24 = 1;\r\n sNewV24 = sElement;\r\n ElseIf(nTargetIndex = 25);\r\n nNewDim25 = 1;\r\n sNewV25 = sElement;\r\n ElseIf(nTargetIndex = 26);\r\n nNewDim26 = 1;\r\n sNewV26 = sElement;\r\n ElseIf(nTargetIndex = 27);\r\n nNewDim27 = 1;\r\n sNewV27 = sElement;\r\n EndIf;\r\n\r\n #Add to the Target filter\r\n sTargetFilter=sTargetFilter|sElementStartDelim|sElement;\r\n \r\n # Clear the word\r\n sWord = '';\r\n sLastDelim = sChar;\r\n \r\n Else;\r\n sWord = sWord | sChar;\r\n EndIf;\r\n\r\n EndIf;\r\n\r\n EndIf;\r\n\r\n nChar = nChar + nAddExtra + 1;\r\n\r\nEND;\r\n\r\n# Check that an input element or variable has been specified for all dimensions in the target cube\r\n\r\nnIndexInTarget = 1;\r\nWHILE(nIndexInTarget <= nTargetCubeDimensionCount);\r\n \r\n sMapped = Expand('%nMappedDim'| NumberToString(nIndexInTarget) |'%'); \r\n sMapped = Subst( sMapped , Scan( '.' , sMapped )-1 , 99);\r\n nMapped = StringToNumber( Trim( sMapped ) );\r\n sNew = Expand('%nNewDim'| NumberToString(nIndexInTarget) |'%'); \r\n sNew = Subst( sNew , Scan( '.' , sNew )-1 , 99);\r\n nNew = StringToNumber( Trim( sNew ) );\r\n \r\n If(nMapped = 0 & nNew = 0 );\r\n # there's no input element and this dimension is not in the source\r\n nErrors = nErrors + 1;\r\n sTargetDimName = TabDim( pTgtCube, nIndexInTarget );\r\n sMessage = 'Dimension ' | sTargetDimName | ' is missing an input element in pMappingToNewDims';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n EndIf;\r\n \r\n nIndexInTarget = nIndexInTarget + 1;\r\nEND;\r\n\r\n\r\n############################# Clear out target ################################\r\n\r\n# Target is cleared for the elements specified in pMappingToNewDims\r\n# and for the parts of pFilter for dimensions in the target\r\n# This code works through pFilter looking for the parts relating to the target cube\r\n# the code which finds individual elements has been left in\r\n# so that it can be changed later to deal with consolidated elements\r\n\r\nsFilter = TRIM( pFilter );\r\nnChar = 1;\r\nnCharCount = LONG( sFilter );\r\nsWord = '';\r\nsLastDelim = '';\r\n\r\n# Add a trailing element delimiter so that the last Dimension:Element/s clause is picked up\r\nIf( nCharCount > 0 );\r\n sFilter = sFilter | sDelimElem;\r\n nCharCount = nCharCount + LONG(sDelimElem);\r\nEndIf;\r\n\r\nWHILE (nChar <= nCharCount);\r\n\r\n sChar = SUBST( sFilter, nChar, 1);\r\n\r\n # Used for delimiters, required for multiple character dilimiters\r\n sDelim = '';\r\n nAddExtra = 0;\r\n\r\n # Ignore spaces\r\n IF (TRIM(sChar) @<> '' );\r\n\r\n ### Dimension Name ###\r\n\r\n # If the delimiter is more than 1 character peek ahead the same amount\r\n # Ignore the first character\r\n sDelim = sChar;\r\n nCount = LONG(sElementStartDelim) - 1;\r\n If( nCount > 0 & nChar + nCount <= nCharCount );\r\n # Add the extra characters\r\n sDelim = sDelim | SUBST( sFilter, nChar + 1, nCount);\r\n # Move to the end of the delimter\r\n nAddExtra = nCount;\r\n EndIf;\r\n\r\n If( sDelim @= sElementStartDelim );\r\n\r\n sChar = sDelim;\r\n\r\n If( sLastDelim @<> '' & sLastDelim @<> sDelimDim );\r\n sMessage = 'In pFilter - the name of a dimension must follow a dimension delimiter (' | sDelimDim | ')';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n EndIf;\r\n\r\n # Found a dimension!\r\n sDimension = UPPER( sWord );\r\n nDimInTgt=0;\r\n # See if the dimension is in the target cube\r\n IF(scan('^^'|sDimension|'^^', sTgtDimString)>0);\r\n If(sTargetFilter@='');\r\n sTargetFilter = sDimension;\r\n Else; \r\n sTargetFilter = sTargetFilter | sDelimDim | sDimension;\r\n endif;\r\n nDimInTgt=1;\r\n Endif; \r\n\r\n sLastDelim = sChar;\r\n # Clear the word\r\n sWord = '';\r\n #reset element count\r\n nElementCount = 1;\r\n\r\n Else;\r\n\r\n # Reset extra chars\r\n nAddExtra = 0;\r\n\r\n ### Check both both dim delimiter and element delimiter ###\r\n nIsDelimiter = 0;\r\n\r\n ## Check dimension delimiter first\r\n # If the delimiter is more than 1 character peek ahead the same amount\r\n # Ignore the first character\r\n sDelim = sChar;\r\n nCount = LONG(sDelimDim) - 1;\r\n If( nCount > 0 & nChar + nCount <= nCharCount );\r\n # Add the extra characters\r\n sDelim = sDelim | SUBST( sFilter, nChar + 1, nCount);\r\n # Move to the end of the delimter\r\n nAddExtra = nCount;\r\n EndIf;\r\n\r\n If( sDelim @= sDelimDim );\r\n nIsDelimiter = 1;\r\n sChar = sDelim;\r\n Else;\r\n # Reset extra chars\r\n nAddExtra = 0;\r\n\r\n ## Check element delimiter\r\n\r\n # If the delimiter is more than 1 character peek ahead the same amount\r\n # Ignore the first character\r\n sDelim = sChar;\r\n nCount = LONG(sDelimElem) - 1;\r\n If( nCount > 0 & nChar + nCount <= nCharCount );\r\n # Add the extra characters\r\n sDelim = sDelim | SUBST( sFilter, nChar + 1, nCount);\r\n # Move to the end of the delimter\r\n nAddExtra = nCount;\r\n EndIf;\r\n\r\n If( sDelim @= sDelimElem );\r\n nIsDelimiter = 1;\r\n sChar = sDelim;\r\n Else;\r\n # Reset extra chars\r\n nAddExtra = 0;\r\n EndIf;\r\n\r\n EndIf;\r\n\r\n If ( nIsDelimiter = 1 );\r\n\r\n If( sLastDelim @= '' % sLastDelim @= sDelimDim );\r\n sMessage = 'In pFilter - an element delimiter must follow a dimension name: ' | sChar | ' (' | NumberToString(nChar) | ')';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n EndIf;\r\n\r\n # Found an element\r\n sElement = sWord;\r\n\r\n IF(DIMIX(sDimension, sElement) > 0 & nDimInTgt=1);\r\n # first element\r\n IF(nElementCount = 1);\r\n sTargetFilter = sTargetFilter | sElementStartDelim | sElement;\r\n # later elements\r\n Else;\r\n sTargetFilter = sTargetFilter | sDelimElem | sElement;\r\n EndIf;\r\n EndIf;\r\n\r\n nElementCount = nElementCount + 1;\r\n sLastDelim = sChar;\r\n\r\n # Clear the word\r\n sWord = '';\r\n Else;\r\n sWord = sWord | sChar;\r\n EndIf;\r\n\r\n EndIf;\r\n\r\n EndIf;\r\n\r\n nChar = nChar + nAddExtra + 1;\r\n\r\nEND;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n# Branch depending on whether to do recursive calls to self on independent threads or run all in this thread\r\nIf( Scan( pEleStartDelim, pFilterParallel ) > 0 );\r\n sDimParallel = SubSt( pFilterParallel, 1, Scan( pEleStartDelim, pFilterParallel ) - 1 );\r\n sElementList = SubSt( pFilterParallel, Scan( pEleStartDelim, pFilterParallel ) + 1, Long( pFilterParallel ) );\r\n If( SubSt( sElementList, Long( sElementList ), 1 ) @<> pEleDelim );\r\n sElementList = sElementList | pEleDelim;\r\n EndIf;\r\n ## Counting elements in element list\r\n sElementListCount = sElementList;\r\n nElements = 0;\r\n While( Scan( pEleDelim, sElementListCount ) > 0 );\r\n nElements = nElements + 1;\r\n sElementListCount = SubSt( sElementListCount, Scan( pEleDelim, sElementListCount ) + 1, Long( sElementListCount ) );\r\n End;\r\n IF( Mod( nElements, nMaxThreads ) = 0 );\r\n nElemsPerThread = INT( nElements / nMaxThreads );\r\n ELSE;\r\n nElemsPerThread = INT( nElements / nMaxThreads ) + 1;\r\n ENDIF;\r\n nThreadElCounter = 0;\r\n While( Scan( pEleDelim, sElementList ) > 0 );\r\n sSlicerEle = SubSt( sElementList, 1, Scan( pEleDelim, sElementList ) - 1 );\r\n sElementList = SubSt( sElementList, Scan( pEleDelim, sElementList ) + 1, Long( sElementList ) );\r\n # Do recursive process call with new RunProcess function\r\n nThreadElCounter = nThreadElCounter + 1;\r\n sDimDelim = If(pFilter @= '', '', pDimDelim );\r\n IF( nThreadElCounter = 1 );\r\n sFilter = Expand('%pFilter%%sDimDelim%%sDimParallel%%pEleStartDelim%%sSlicerEle%');\r\n ELSE;\r\n sFilter = Expand('%sFilter%%pEleDelim%%sSlicerEle%');\r\n ENDIF;\r\n IF( nThreadElCounter >= nElemsPerThread );\r\n RunProcess( cThisProcName, 'pLogoutput', pLogoutput,\r\n \t'pSrcCube', pSrcCube, 'pFilter', sFilter, 'pFilterParallel', '', 'pTgtCube', pTgtCube, 'pMappingToNewDims', pMappingToNewDims,\r\n \t'pSuppressConsol', pSuppressConsol, 'pSuppressConsolStrings', pSuppressConsolStrings, 'pSuppressRules', pSuppressRules, 'pSuppressZero', pSuppressZero, 'pZeroTarget', pZeroTarget, 'pZeroSource', pZeroSource,\r\n 'pFactor', pFactor, 'pDimDelim', pDimDelim, 'pEleStartDelim', pEleStartDelim, 'pEleDelim', pEleDelim,\r\n 'pTemp', pTemp, 'pCubeLogging', pCubeLogging, 'pSandbox', pSandbox, 'pFile', pFile, 'pThreadMode', 1\r\n );\r\n \t nThreadElCounter = 0;\r\n \t sFilter = '';\r\n \t ENDIF;\r\n End;\r\n ## Process last elements - only when filter is not empty (there are still elements)\r\n IF( sFilter @<> '' );\r\n RunProcess( cThisProcName, 'pLogoutput', pLogoutput,\r\n \t'pSrcCube', pSrcCube, 'pFilter', sFilter, 'pFilterParallel', '', 'pTgtCube', pTgtCube, 'pMappingToNewDims', pMappingToNewDims,\r\n \t'pSuppressConsol', pSuppressConsol, 'pSuppressConsolStrings', pSuppressConsolStrings, 'pSuppressRules', pSuppressRules, 'pSuppressZero', pSuppressZero, 'pZeroTarget', pZeroTarget, 'pZeroSource', pZeroSource,\r\n 'pFactor', pFactor, 'pDimDelim', pDimDelim, 'pEleStartDelim', pEleStartDelim, 'pEleDelim', pEleDelim,\r\n 'pTemp', pTemp, 'pCubeLogging', pCubeLogging, 'pSandbox', pSandbox, 'pFile', pFile, 'pThreadMode', 1\r\n );\r\n ENDIF; \r\n DataSourceType = 'NULL';\r\nElse;\r\n # Clear out target view\r\n If(pZeroTarget = 1 & LONG(sTargetFilter)>= 0 & nErrors = 0);\r\n ###### Create View of target to clear out ###\r\n # Create View of target ###\r\n nRet = ExecuteProcess('}bedrock.cube.view.create',\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pTgtCube,\r\n 'pView', sTargetView ,\r\n 'pFilter', sTargetFilter,\r\n 'pSuppressZero', pSuppressZero,\r\n 'pSuppressConsol', pSuppressConsol,\r\n 'pSuppressRules', pSuppressRules,\r\n 'pSuppressConsolStrings', pSuppressConsolStrings, \r\n 'pDimDelim', pDimDelim,\r\n 'pEleStartDelim', pEleStartDelim,\r\n 'pEleDelim', pEleDelim ,\r\n 'pTemp', pTemp\r\n );\r\n \r\n IF(nRet <> 0);\r\n sMessage = 'Error creating the view from the filter.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n \r\n nRet = ExecuteProcess( '}bedrock.cube.data.clear',\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pTgtCube,\r\n 'pView', sTargetView,\r\n 'pFilter', sTargetFilter,\r\n 'pDimDelim', pDimDelim,\r\n 'pEleStartDelim', pEleStartDelim,\r\n 'pEleDelim', pEleDelim,\r\n 'pTemp', pTemp,\r\n 'pCubeLogging', pCubeLogging,\r\n 'pSandbox', pSandbox\r\n );\r\n \r\n IF(nRet <> 0);\r\n sMessage = 'Error clearing the target view.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n \r\n Endif;\r\n \r\n If( pFile = 0 );\r\n ### Create View of Source ###\r\n IF(pSuppressConsol = 0 & pSuppressConsolStrings = 1);\r\n pSubN=1;\r\n else;\r\n pSubN=0;\r\n Endif; \r\n \r\n nRet = ExecuteProcess('}bedrock.cube.view.create',\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pSrcCube,\r\n 'pView', sView,\r\n 'pFilter', pFilter,\r\n 'pSuppressZero', pSuppressZero,\r\n 'pSuppressConsol', pSuppressConsol,\r\n 'pSuppressRules', pSuppressRules,\r\n 'pSuppressConsolStrings', pSuppressConsolStrings, \r\n 'pDimDelim', pDimDelim,\r\n 'pEleStartDelim', pEleStartDelim,\r\n 'pEleDelim', pEleDelim ,\r\n 'pTemp', pTemp,\r\n 'pSubN', pSubN\r\n );\r\n \r\n IF(nRet <> 0);\r\n sMessage = 'Error creating the view from the filter.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n \r\n ElseIf( pFile > 0 );\r\n ### Export to File in case of Copy Data Via File ###\r\n IF(pSuppressConsol = 0);\r\n pSubN=1;\r\n else;\r\n pSubN=0;\r\n Endif; \r\n \r\n nRet = ExecuteProcess('}bedrock.cube.data.export',\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pSrcCube,\r\n 'pView', sView,\r\n 'pFilter', pFilter,\r\n 'pFilterParallel', '',\r\n 'pParallelThreads', 0,\r\n 'pDimDelim', pDimDelim,\r\n 'pEleStartDelim', pEleStartDelim,\r\n 'pEleDelim', pEleDelim,\r\n 'pSuppressZero', pSuppressZero,\r\n 'pSuppressConsol', pSuppressConsol,\r\n 'pSuppressRules', pSuppressRules,\r\n 'pSuppressConsolStrings', pSuppressConsolStrings, \r\n 'pZeroSource', 0,\r\n 'pCubeLogging', pCubeLogging,\r\n 'pTemp', pTemp,\r\n 'pFilePath', cDir,\r\n 'pFileName', cFileName,\r\n 'pDelim', cDelimiter,\r\n 'pDecimalSeparator', sDecimalSeparator,\r\n 'pThousandSeparator', sThousandSeparator,\r\n 'pQuote', cQuote,\r\n 'pTitleRecord', cTitleRows,\r\n 'pSandbox', pSandbox,\r\n 'pSubN', pSubN\r\n );\r\n \r\n IF(nRet <> 0);\r\n sMessage = 'Error exporting data to file.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n ENDIF;\r\n \r\n ### Assign Datasource ###\r\n If( pFile = 0 );\r\n DataSourceType = 'VIEW';\r\n DatasourceNameForServer = pSrcCube;\r\n DatasourceNameForClient = pSrcCube;\r\n DatasourceCubeView = sView;\r\n ElseIf( pFile > 0 );\r\n DataSourceType = 'CHARACTERDELIMITED';\r\n DatasourceNameForServer = cFile;\r\n DatasourceNameForClient = cFile;\r\n DatasourceASCIIHeaderRecords = cTitleRows;\r\n DatasourceASCIIDelimiter = cDelimiter;\r\n DatasourceASCIIQuoteCharacter = cQuote;\r\n EndIf;\r\nEndIf;\r\n\r\n### End Prolog ###", "MetadataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****", "DataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n # The exapand function gives the value of the variable passed to it\r\n # So if the say the third dimension in the source cube is the first dimension in the target cube\r\n # the string variable Source Variable for Target varialbe V1 is set on the prolog to V3 (see Mapped part)\r\n # which means Expand(%V3%) gives the value of V3\r\n # and Target sV1 will equal V3\r\nIf( pFile = 0 ); \r\n sV1 =IF(nMappedDim1=1, Expand('%'|sMappedV1|'%'), IF(nNewDim1=1, sNewV1,V1));\r\n sV2 =IF(nMappedDim2=1, Expand('%'|sMappedV2|'%'), IF(nNewDim2=1, sNewV2,V2));\r\n sV3 =IF(nMappedDim3=1, Expand('%'|sMappedV3|'%'), IF(nNewDim3=1, sNewV3,V3));\r\n sV4 =IF(nMappedDim4=1, Expand('%'|sMappedV4|'%'), IF(nNewDim4=1, sNewV4,V4));\r\n sV5 =IF(nMappedDim5=1, Expand('%'|sMappedV5|'%'), IF(nNewDim5=1, sNewV5,V5));\r\n sV6 =IF(nMappedDim6=1, Expand('%'|sMappedV6|'%'), IF(nNewDim6=1, sNewV6,V6));\r\n sV7 =IF(nMappedDim7=1, Expand('%'|sMappedV7|'%'), IF(nNewDim7=1, sNewV7,V7));\r\n sV8 =IF(nMappedDim8=1, Expand('%'|sMappedV8|'%'), IF(nNewDim8=1, sNewV8,V8));\r\n sV9 =IF(nMappedDim9=1, Expand('%'|sMappedV9|'%'), IF(nNewDim9=1, sNewV9,V9));\r\n sV10=IF(nMappedDim10=1, Expand('%'|sMappedV10|'%'),IF(nNewDim10=1,sNewV10,V10));\r\n sV11=IF(nMappedDim11=1, Expand('%'|sMappedV11|'%'),IF(nNewDim11=1,sNewV11,V11));\r\n sV12=IF(nMappedDim12=1, Expand('%'|sMappedV12|'%'),IF(nNewDim12=1,sNewV12,V12)); \r\n sV13=IF(nMappedDim13=1, Expand('%'|sMappedV13|'%'),IF(nNewDim13=1,sNewV13,V13)); \r\n sV14=IF(nMappedDim14=1, Expand('%'|sMappedV14|'%'),IF(nNewDim14=1,sNewV14,V14)); \r\n sV15=IF(nMappedDim15=1, Expand('%'|sMappedV15|'%'),IF(nNewDim15=1,sNewV15,V15)); \r\n sV16=IF(nMappedDim16=1, Expand('%'|sMappedV16|'%'),IF(nNewDim16=1,sNewV16,V16)); \r\n sV17=IF(nMappedDim17=1, Expand('%'|sMappedV17|'%'),IF(nNewDim17=1,sNewV17,V17)); \r\n sV18=IF(nMappedDim18=1, Expand('%'|sMappedV18|'%'),IF(nNewDim18=1,sNewV18,V18)); \r\n sV19=IF(nMappedDim19=1, Expand('%'|sMappedV19|'%'),IF(nNewDim19=1,sNewV19,V19)); \r\n sV20=IF(nMappedDim20=1, Expand('%'|sMappedV20|'%'),IF(nNewDim20=1,sNewV20,V20)); \r\n sV21=IF(nMappedDim21=1, Expand('%'|sMappedV21|'%'),IF(nNewDim21=1,sNewV21,V21)); \r\n sV22=IF(nMappedDim22=1, Expand('%'|sMappedV22|'%'),IF(nNewDim22=1,sNewV22,V22)); \r\n sV23=IF(nMappedDim23=1, Expand('%'|sMappedV23|'%'),IF(nNewDim23=1,sNewV23,V23)); \r\n sV24=IF(nMappedDim24=1, Expand('%'|sMappedV24|'%'),IF(nNewDim24=1,sNewV24,V24)); \r\n sV25=IF(nMappedDim25=1, Expand('%'|sMappedV25|'%'),IF(nNewDim25=1,sNewV25,V25)); \r\n sV26=IF(nMappedDim26=1, Expand('%'|sMappedV26|'%'),IF(nNewDim26=1,sNewV26,V26)); \r\n sV27=IF(nMappedDim27=1, Expand('%'|sMappedV27|'%'),IF(nNewDim27=1,sNewV27,V27));\r\n sV28=IF(nMappedDim28=1, Expand('%'|sMappedV28|'%'),V28); \r\nElseIf( pFile > 0 );\r\n sV1 =IF(nMappedDim1=1, Expand('%'|sMappedV1|'%'), IF(nNewDim1=1, sNewV1,V2));\r\n sV2 =IF(nMappedDim2=1, Expand('%'|sMappedV2|'%'), IF(nNewDim2=1, sNewV2,V3));\r\n sV3 =IF(nMappedDim3=1, Expand('%'|sMappedV3|'%'), IF(nNewDim3=1, sNewV3,V4));\r\n sV4 =IF(nMappedDim4=1, Expand('%'|sMappedV4|'%'), IF(nNewDim4=1, sNewV4,V5));\r\n sV5 =IF(nMappedDim5=1, Expand('%'|sMappedV5|'%'), IF(nNewDim5=1, sNewV5,V6));\r\n sV6 =IF(nMappedDim6=1, Expand('%'|sMappedV6|'%'), IF(nNewDim6=1, sNewV6,V7));\r\n sV7 =IF(nMappedDim7=1, Expand('%'|sMappedV7|'%'), IF(nNewDim7=1, sNewV7,V8));\r\n sV8 =IF(nMappedDim8=1, Expand('%'|sMappedV8|'%'), IF(nNewDim8=1, sNewV8,V9));\r\n sV9 =IF(nMappedDim9=1, Expand('%'|sMappedV9|'%'), IF(nNewDim9=1, sNewV9,V10));\r\n sV10=IF(nMappedDim10=1, Expand('%'|sMappedV10|'%'),IF(nNewDim10=1,sNewV10,V11));\r\n sV11=IF(nMappedDim11=1, Expand('%'|sMappedV11|'%'),IF(nNewDim11=1,sNewV11,V12));\r\n sV12=IF(nMappedDim12=1, Expand('%'|sMappedV12|'%'),IF(nNewDim12=1,sNewV12,V13)); \r\n sV13=IF(nMappedDim13=1, Expand('%'|sMappedV13|'%'),IF(nNewDim13=1,sNewV13,V14)); \r\n sV14=IF(nMappedDim14=1, Expand('%'|sMappedV14|'%'),IF(nNewDim14=1,sNewV14,V15)); \r\n sV15=IF(nMappedDim15=1, Expand('%'|sMappedV15|'%'),IF(nNewDim15=1,sNewV15,V16)); \r\n sV16=IF(nMappedDim16=1, Expand('%'|sMappedV16|'%'),IF(nNewDim16=1,sNewV16,V17)); \r\n sV17=IF(nMappedDim17=1, Expand('%'|sMappedV17|'%'),IF(nNewDim17=1,sNewV17,V18)); \r\n sV18=IF(nMappedDim18=1, Expand('%'|sMappedV18|'%'),IF(nNewDim18=1,sNewV18,V19)); \r\n sV19=IF(nMappedDim19=1, Expand('%'|sMappedV19|'%'),IF(nNewDim19=1,sNewV19,V20)); \r\n sV20=IF(nMappedDim20=1, Expand('%'|sMappedV20|'%'),IF(nNewDim20=1,sNewV20,V21)); \r\n sV21=IF(nMappedDim21=1, Expand('%'|sMappedV21|'%'),IF(nNewDim21=1,sNewV21,V22)); \r\n sV22=IF(nMappedDim22=1, Expand('%'|sMappedV22|'%'),IF(nNewDim22=1,sNewV22,V23)); \r\n sV23=IF(nMappedDim23=1, Expand('%'|sMappedV23|'%'),IF(nNewDim23=1,sNewV23,V24)); \r\n sV24=IF(nMappedDim24=1, Expand('%'|sMappedV24|'%'),IF(nNewDim24=1,sNewV24,V25)); \r\n sV25=IF(nMappedDim25=1, Expand('%'|sMappedV25|'%'),IF(nNewDim25=1,sNewV25,V26)); \r\n sV26=IF(nMappedDim26=1, Expand('%'|sMappedV26|'%'),IF(nNewDim26=1,sNewV26,V27)); \r\n sV27=IF(nMappedDim27=1, Expand('%'|sMappedV27|'%'),IF(nNewDim27=1,sNewV27,V28));\r\n sV28=IF(nMappedDim28=1, Expand('%'|sMappedV28|'%'),V29);\r\nEndIf;\r\n \r\n##########################################################################################################\r\n### Write data from source file to target cube ###########################################################\r\n\r\n If( nDimensionCount = 2 );\r\n If( CellIsUpdateable( pTgtCube, sV1, sV2 ) = 1 );\r\n sElType = DType( sDim2, sV2 );\r\n IF( SubSt( pTgtCube, 1, 17 ) @= '}ElementSecurity_');\r\n sV3 = IF( sV3 @= '', 'NONE', sV3 );\r\n ElementSecurityPut( sV3, sDim1, sV1, sV2 );\r\n ELSEIF( sElType @= 'AA' );\r\n AttrPutS( sV3, sDim1, sV1, sV2, 1 );\r\n ELSEIF( sElType @= 'AS' );\r\n AttrPutS( sV3, sDim1, sV1, sV2 );\r\n ELSEIF( sElType @= 'AN' );\r\n AttrPutN( StringToNumberEx( sV3, sDecimalSeparator, sThousandSeparator ) * nFactor, sDim1, sV1, sV2 );\r\n ElseIf( sElType @= 'S' );\r\n CellPutS( sV3, pTgtCube, sV1, sV2 );\r\n Else;\r\n nObal = CellGetN( pTgtCube, sV1, sV2 );\r\n nCbal = nObal + StringToNumberEx( sV3, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n CellPutN( nCbal, pTgtCube, sV1, sV2 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 3 );\r\n If( CellIsUpdateable( pTgtCube, sV1, sV2, sV3 ) = 1 );\r\n sElType = DType( sDim3, sV3 );\r\n If( sElType @<> 'S' );\r\n nObal = CellGetN( pTgtCube, sV1, sV2, sV3 );\r\n nCbal = nObal + StringToNumberEx( sV4, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n CellPutN( nCbal, pTgtCube, sV1, sV2, sV3 );\r\n Else;\r\n CellPutS( sV4, pTgtCube, sV1, sV2, sV3 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 4 );\r\n If( CellIsUpdateable( pTgtCube, sV1, sV2, sV3, sV4 ) = 1 );\r\n sElType = DType( sDim4, sV4 );\r\n If( sElType @<> 'S' );\r\n nObal = CellGetN( pTgtCube, sV1, sV2, sV3, sV4);\r\n nCbal = nObal + StringToNumberEx( sV5, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n CellPutN( nCbal, pTgtCube, sV1, sV2, sV3, sV4);\r\n Else;\r\n CellPutS( sV5, pTgtCube, sV1, sV2, sV3, sV4);\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 5 );\r\n If( CellIsUpdateable( pTgtCube, sV1, sV2, sV3, sV4, sV5 ) = 1 );\r\n sElType = DType( sDim5, sV5 );\r\n If( sElType @<> 'S' );\r\n nObal = CellGetN( pTgtCube, sV1, sV2, sV3, sV4, sV5 );\r\n nCbal = nObal + StringToNumberEx( sV6, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n CellPutN( nCbal, pTgtCube, sV1, sV2, sV3, sV4, sV5 );\r\n Else;\r\n CellPutS( sV6, pTgtCube, sV1, sV2, sV3, sV4, sV5 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 6 );\r\n If( CellIsUpdateable( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6 ) = 1 );\r\n sElType = DType( sDim6, sV6 );\r\n If( sElType @<> 'S' );\r\n nObal = CellGetN( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6 );\r\n nCbal = nObal + StringToNumberEx( sV7, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n CellPutN( nCbal, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6 );\r\n Else;\r\n CellPutS( sV7, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 7 );\r\n If( CellIsUpdateable( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7 ) = 1 );\r\n sElType = DType( sDim7, sV7 );\r\n If( sElType @<> 'S' );\r\n nObal = CellGetN( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7 );\r\n nCbal = nObal + StringToNumberEx( sV8, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n CellPutN( nCbal, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7 );\r\n Else;\r\n CellPutS( sV8, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 8 );\r\n If( CellIsUpdateable( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8 ) = 1 );\r\n sElType = DType( sDim8, sV8 );\r\n If( sElType @<> 'S' );\r\n nObal = CellGetN( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8 );\r\n nCbal = nObal + StringToNumberEx( sV9, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n CellPutN( nCbal, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8 );\r\n Else;\r\n CellPutS( sV9, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 9 );\r\n If( CellIsUpdateable( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9 ) = 1 );\r\n sElType = DType( sDim9, sV9 );\r\n If( sElType @<> 'S' );\r\n nObal = CellGetN( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9 );\r\n nCbal = nObal + StringToNumberEx( sV10, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n CellPutN( nCbal, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9 );\r\n Else;\r\n CellPutS( sV10, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 10 );\r\n If( CellIsUpdateable( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10 ) = 1 );\r\n sElType = DType( sDim10, sV10 );\r\n If( sElType @<> 'S' );\r\n nObal = CellGetN( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10 );\r\n nCbal = nObal + StringToNumberEx( sV11, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n CellPutN( nCbal, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10 );\r\n Else;\r\n CellPutS( sV11, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 11 );\r\n If( CellIsUpdateable( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11 ) = 1 );\r\n sElType = DType( sDim11, sV11 );\r\n If( sElType @<> 'S' );\r\n nObal = CellGetN( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11 );\r\n nCbal = nObal + StringToNumberEx( sV12, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n CellPutN( nCbal, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11 );\r\n Else;\r\n CellPutS( sV12, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 12 );\r\n If( CellIsUpdateable( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12 ) = 1 );\r\n sElType = DType( sDim12, sV12 );\r\n If( sElType @<> 'S' );\r\n nObal = CellGetN( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12 );\r\n nCbal = nObal + StringToNumberEx( sV13, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n CellPutN( nCbal, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12 );\r\n Else;\r\n CellPutS( sV13, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 13 );\r\n If( CellIsUpdateable( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13 ) = 1 );\r\n sElType = DType( sDim13, sV13 );\r\n If( sElType @<> 'S' );\r\n nObal = CellGetN( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13 );\r\n nCbal = nObal + StringToNumberEx( sV14, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n CellPutN( nCbal, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13 );\r\n Else;\r\n CellPutS( sV14, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 14 );\r\n If( CellIsUpdateable( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14 ) = 1 );\r\n sElType = DType( sDim14, sV14 );\r\n If( sElType @<> 'S' );\r\n nObal = CellGetN( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14 );\r\n nCbal = nObal + StringToNumberEx( sV15, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n CellPutN( nCbal, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14 );\r\n Else;\r\n CellPutS( sV15, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 15 );\r\n If( CellIsUpdateable( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15 ) = 1 );\r\n sElType = DType( sDim15, sV15 );\r\n If( sElType @<> 'S' );\r\n nObal = CellGetN( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15 );\r\n nCbal = nObal + StringToNumberEx( sV16, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n CellPutN( nCbal, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15 );\r\n Else;\r\n CellPutS( sV16, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 16 );\r\n If( CellIsUpdateable( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16 ) = 1 );\r\n sElType = DType( sDim16, sV16 );\r\n If( sElType @<> 'S' );\r\n nObal = CellGetN( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16 );\r\n nCbal = nObal + StringToNumberEx( sV17, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n CellPutN( nCbal, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16 );\r\n Else;\r\n CellPutS( sV17, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 17 );\r\n If( CellIsUpdateable( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17 ) = 1 );\r\n sElType = DType( sDim17, sV17 );\r\n If( sElType @<> 'S' );\r\n nObal = CellGetN( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17 );\r\n nCbal = nObal + StringToNumberEx( sV18, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n CellPutN( nCbal, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17 );\r\n Else;\r\n CellPutS( sV18, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 18 );\r\n If( CellIsUpdateable( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18 ) = 1 );\r\n sElType = DType( sDim18, sV18 );\r\n If( sElType @<> 'S' );\r\n nObal = CellGetN( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18 );\r\n nCbal = nObal + StringToNumberEx( sV19, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n CellPutN( nCbal, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18 );\r\n Else;\r\n CellPutS( sV19, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 19 );\r\n If( CellIsUpdateable( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18, sV19 ) = 1 );\r\n sElType = DType( sDim19, sV19 );\r\n If( sElType @<> 'S' );\r\n nObal = CellGetN( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18, sV19 );\r\n nCbal = nObal + StringToNumberEx( sV20, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n CellPutN( nCbal, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18, sV19 );\r\n Else;\r\n CellPutS( sV20, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18, sV19 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 20 );\r\n If( CellIsUpdateable( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18, sV19, sV20 ) = 1 );\r\n sElType = DType( sDim20, sV20 );\r\n If( sElType @<> 'S' );\r\n nObal = CellGetN( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18, sV19, sV20 );\r\n nCbal = nObal + StringToNumberEx( sV21, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n CellPutN( nCbal, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18, sV19, sV20 );\r\n Else;\r\n CellPutS( sV21, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18, sV19, sV20 );\r\n EndIf;\r\n EndIf; \r\n ElseIf( nDimensionCount = 21 );\r\n If( CellIsUpdateable( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18, sV19, sV20, sV21 ) = 1 );\r\n sElType = DType( sDim21, sV21 );\r\n If( sElType @<> 'S' );\r\n nObal = CellGetN( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18, sV19, sV20, sV21 );\r\n nCbal = nObal + StringToNumberEx( sV22, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n CellPutN( nCbal, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18, sV19, sV20, sV21 );\r\n Else;\r\n CellPutS( sV22, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18, sV19, sV20, sV21 );\r\n EndIf;\r\n EndIf; \r\n ElseIf( nDimensionCount = 22 );\r\n If( CellIsUpdateable( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18, sV19, sV20, sV21, sV22 ) = 1 );\r\n sElType = DType( sDim22, sV22 );\r\n If( sElType @<> 'S' );\r\n nObal = CellGetN( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18, sV19, sV20, sV21, sV22 );\r\n nCbal = nObal + StringToNumberEx( sV23, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n CellPutN( nCbal, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18, sV19, sV20, sV21, sV22 );\r\n Else;\r\n CellPutS( sV23, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18, sV19, sV20, sV21, sV22 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 23 );\r\n If( CellIsUpdateable( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18, sV19, sV20, sV21, sV22, sV23 ) = 1 );\r\n sElType = DType( sDim23, sV23 );\r\n If( sElType @<> 'S' );\r\n nObal = CellGetN( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18, sV19, sV20, sV21, sV22, sV23 );\r\n nCbal = nObal + StringToNumberEx( sV24, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n CellPutN( nCbal, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18, sV19, sV20, sV21, sV22, sV23 );\r\n Else;\r\n CellPutS( sV24, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18, sV19, sV20, sV21, sV22, sV23 );\r\n EndIf;\r\n EndIf; \r\n ElseIf( nDimensionCount = 24 );\r\n If( CellIsUpdateable( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18, sV19, sV20, sV21, sV22, sV23, sV24 ) = 1 );\r\n sElType = DType( sDim24, sV24 );\r\n If( sElType @<> 'S' );\r\n nObal = CellGetN( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18, sV19, sV20, sV21, sV22, sV23, sV24 );\r\n nCbal = nObal + StringToNumberEx( sV25, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n CellPutN( nCbal, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18, sV19, sV20, sV21, sV22, sV23, sV24 );\r\n Else;\r\n CellPutS( sV25, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18, sV19, sV20, sV21, sV22, sV23, sV24 );\r\n EndIf;\r\n EndIf; \r\n ElseIf( nDimensionCount = 25 );\r\n If( CellIsUpdateable( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18, sV19, sV20, sV21, sV22, sV23, sV24, sV25 ) = 1 );\r\n sElType = DType( sDim25, sV25 );\r\n If( sElType @<> 'S' );\r\n nObal = CellGetN( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18, sV19, sV20, sV21, sV22, sV23, sV24, sV25 );\r\n nCbal = nObal + StringToNumberEx( sV26, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n CellPutN( nCbal, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18, sV19, sV20, sV21, sV22, sV23, sV24, sV25 );\r\n Else;\r\n CellPutS( sV26, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18, sV19, sV20, sV21, sV22, sV23, sV24, sV25 );\r\n EndIf;\r\n EndIf; \r\n ElseIf( nDimensionCount = 26 );\r\n If( CellIsUpdateable( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18, sV19, sV20, sV21, sV22, sV23, sV24, sV25, sV26 ) = 1 );\r\n sElType = DType( sDim26, sV26 );\r\n If( sElType @<> 'S' );\r\n nObal = CellGetN( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18, sV19, sV20, sV21, sV22, sV23, sV24, sV25, sV26 );\r\n nCbal = nObal + StringToNumberEx( sV27, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n CellPutN( nCbal, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18, sV19, sV20, sV21, sV22, sV23, sV24, sV25, sV26 );\r\n Else;\r\n CellPutS( sV27, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18, sV19, sV20, sV21, sV22, sV23, sV24, sV25, sV26 );\r\n EndIf;\r\n EndIf; \r\n ElseIf( nDimensionCount = 27 );\r\n If( CellIsUpdateable( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18, sV19, sV20, sV21, sV22, sV23, sV24, sV25, sV26, sV27 ) = 1 );\r\n sElType = DType( sDim27, sV27 );\r\n If( sElType @<> 'S' );\r\n nObal = CellGetN( pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18, sV19, sV20, sV21, sV22, sV23, sV24, sV25, sV26, sV27 );\r\n nCbal = nObal + StringToNumberEx( sV28, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n CellPutN( nCbal, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18, sV19, sV20, sV21, sV22, sV23, sV24, sV25, sV26, sV27 );\r\n Else;\r\n CellPutS( sV28, pTgtCube, sV1, sV2, sV3, sV4, sV5, sV6, sV7, sV8, sV9, sV10, sV11, sV12, sV13, sV14, sV15, sV16, sV17, sV18, sV19, sV20, sV21, sV22, sV23, sV24, sV25, sV26, sV27 );\r\n EndIf;\r\n EndIf; \r\n \r\n EndIf;\r\n \r\n### End Data ###", "EpilogProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n## Zero Source\r\nIf( pZeroSource = 1 & nErrors = 0 );\r\n ViewZeroOut( pSrcCube, sView );\r\nEndIf;\r\n\r\n### Delete export file if used\r\nIf( pFile = 1 );\r\n ASCIIDelete( cFile );\r\nEndIf;\r\n\r\n### Return code & final error message handling\r\nIf( nErrors > 0 );\r\n sMessage = 'the process incurred at least 1 error. Please see above lines in this file for more details.';\r\n nProcessReturnCode = 0;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% Process:%cThisProcName% completed with errors. Check tm1server.log for details.' );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n EndIf;\r\nElse;\r\n sProcessAction = Expand( 'Process:%cThisProcName% successfully copied data from %pSrcCube% cube to the %pTgtCube% cube.' );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% %sProcessAction%' );\r\n nProcessReturnCode = 1;\r\nEndIf;\r\n\r\n### End Epilog ###", "HasSecurityAccess": true, - "UIData": "_ParameterConstraints=e30=\f", + "UIData": "", "DataSource": { "Type": "TM1CubeView", "dataSourceNameForClient": "Bedrock Source Cube", @@ -13,123 +13,111 @@ "view": "Default" }, "Parameters": [ - { - "Name": "pLogOutput", - "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, - { - "Name": "pStrictErrorHandling", - "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, { "Name": "pSrcCube", - "Prompt": "REQUIRED: Cube data is being copied from", + "Prompt": "REQUIRED: Source cube name", "Value": "", "Type": "String" }, { "Name": "pFilter", - "Prompt": "OPTIONAL: Filter on source cube in format Year\u00a6 2006 + 2007 & Scenario\u00a6 Actual + Budget. Blank for whole cube", + "Prompt": "OPTIONAL: Filter on cube in format: 'dim_one\u00a6 el_one + el_two & dim_two\u00a6 el_one + el_two'", "Value": "", "Type": "String" }, { "Name": "pFilterParallel", - "Prompt": "OPTIONAL: Parallelization Filter: Month\u00a6Q1+Q2+Q3+Q4 (Blank=run single threaded). Single dimension parallel slices. Will be added to filter single element at a time. Dimension must not be part of filter", + "Prompt": "OPTIONAL: Parallelization filter in format: dim_one\u00a6 el_one + el_two. Dimension must not be part of filter", "Value": "", "Type": "String" }, { "Name": "pParallelThreads", - "Prompt": "Maximum number of threads to run when parallel processing is enabled ( if <2 will execute one thread, but parallel filter is still applied )", + "Prompt": "OPTIONAL: Maximum number of threads to run when parallel processing is enabled (Default = 0)", "Value": 0, "Type": "Numeric" }, { "Name": "pTgtCube", - "Prompt": "REQUIRED: Name of cube to copy the values to", + "Prompt": "REQUIRED: Target cube name", "Value": "", "Type": "String" }, { "Name": "pMappingToNewDims", - "Prompt": "REQUIRED IF TARGET HAS DIMS NOT IN SOURCE: DimX\u00a6InputElementForDimX & DimY\u00a6InputElementForDimY (specify an N level element for each new dim)", + "Prompt": "OPTIONAL: Required if target has dims not in source. Format: 'dim_one\u00a6 el_one & dim_two\u00a6 el_two'", "Value": "", "Type": "String" }, { "Name": "pSuppressConsol", - "Prompt": "OPTIONAL: Suppress Consolidations (Skip = 1) Only use 0 for strings", + "Prompt": "OPTIONAL: Suppress consolidated values (Boolean. Default = 1)", "Value": 1, "Type": "Numeric" }, { "Name": "pSuppressConsolStrings", - "Prompt": "OPTIONAL: Suppress Consolidated String Cells (Skip = 1)", - "Value": 0, + "Prompt": "OPTIONAL: Suppress consolidated string cells (Boolean. Default = 1)", + "Value": 1, "Type": "Numeric" }, { "Name": "pSuppressRules", - "Prompt": "OPTIONAL: Suppress Rules (Skip = 1)", + "Prompt": "OPTIONAL: Suppress rules (Boolean. Default = 1)", "Value": 1, "Type": "Numeric" }, { "Name": "pSuppressZero", - "Prompt": "OPTIONAL: Suppress Null Cells (Skip = 1)", + "Prompt": "OPTIONAL: Suppress zeroes (Boolean. Default = 1)", "Value": 1, "Type": "Numeric" }, { "Name": "pZeroTarget", - "Prompt": "OPTIONAL: Zero out Target Element PRIOR to Copy? (Boolean 1=True) Clears combination of pFilter and pMappingToNewDims", + "Prompt": "OPTIONAL: Zero out target before start of process (Boolean. Default = 1)", "Value": 1, "Type": "Numeric" }, { "Name": "pZeroSource", - "Prompt": "OPTIONAL: Zero out Source Element AFTER Copy? (Boolean 1=True). If pFilter is blank the whole source cube is cleared!", + "Prompt": "OPTIONAL: Zero out source after end of process (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" }, { "Name": "pFactor", - "Prompt": "OPTIONAL: Multiply source value by factor (1 keeps the value as is). To modify existing values make the target element the same as the source with pZeroTarget = 0", + "Prompt": "OPTIONAL: Multiply source values by factor (Default = 1)", "Value": 1, "Type": "Numeric" }, { "Name": "pDimDelim", - "Prompt": "OPTIONAL. Delimiter for start of Dimension/Element set", + "Prompt": "OPTIONAL: Delimiter for start of dimension/element set in filter parameters (Default = '&')", "Value": "&", "Type": "String" }, { "Name": "pEleStartDelim", - "Prompt": "OPTIONAL: Delimiter for start of element list", + "Prompt": "OPTIONAL: Delimiter for start of element list in filter parameters (Default = '\u00a6')", "Value": "\u00a6", "Type": "String" }, { "Name": "pEleDelim", - "Prompt": "OPTIONAL: Delimiter between elements", + "Prompt": "OPTIONAL: Delimiter between elements in filter parameters (Default = '+')", "Value": "+", "Type": "String" }, { "Name": "pTemp", - "Prompt": "OPTIONAL: Delete temporary view and Subset ( 0 = Retain View and Subsets 1 = Delete View and Subsets 2 = Delete View only )", + "Prompt": "OPTIONAL: Delete/create temporary objects (0 = Do not delete, 1 = Delete, 2 = if view and subsets are created, keep only subsets)", "Value": 1, "Type": "Numeric" }, { "Name": "pSandbox", - "Prompt": "OPTIONAL: To use sandbox not base data enter the sandbox name (invalid name will result in process error)", + "Prompt": "OPTIONAL: Use sandbox", "Value": "", "Type": "String" }, @@ -141,37 +129,43 @@ }, { "Name": "pDelim", - "Prompt": "OPTIONAL: For pFile > 0. AsciiOutput delimiter character (Default = ',' exactly 3 digits = ASCII code)", - "Value": ",", + "Prompt": "OPTIONAL: Delimiter for list parameters (Default = '&')", + "Value": "&", "Type": "String" }, { "Name": "pQuote", - "Prompt": "OPTIONAL: For pFile > 0. AsciiOutput quote character (Default = '\"' exactly 3 digits = ASCII code)", + "Prompt": "OPTIONAL: Quote character (2 or 3 digits = ASCII code. Default = '\"')", "Value": "\"", "Type": "String" }, { "Name": "pDecimalSeparator", - "Prompt": "OPTIONAL: For pFile > 0. Decimal separator for conversion of NumberToStringEx and StringToNumberEx (default = '.' exactly 3 digits = ASCII code)", + "Prompt": "OPTIONAL: Decimal separator for string/number conversion (Exactly 3 digits = ASCII code. Default ='.')", "Value": ".", "Type": "String" }, { "Name": "pThousandSeparator", - "Prompt": "OPTIONAL: For pFile > 0. Thousand separator for conversion of NumberToStringEx and StringToNumberEx (default = ',' exactly 3 digits = ASCII code)", + "Prompt": "OPTIONAL: Thousand separator for string/number conversion (Exactly 3 digits = ASCII code. Default = ',')", "Value": ",", "Type": "String" }, { "Name": "pSubN", - "Prompt": "OPTIONAL: Create N level subset for all dims not mentioned in pFilter", + "Prompt": "OPTIONAL: Create N level subset for all dims not specified (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" }, { - "Name": "pThreadMode", - "Prompt": "DO NOT USE: Internal parameter only, please do not use", + "Name": "pLogOutput", + "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pStrictErrorHandling", + "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" }, @@ -180,6 +174,18 @@ "Prompt": "OBSOLETE: This parameter does nothing and is only included for backwards compatability", "Value": 0, "Type": "Numeric" + }, + { + "Name": "pThreadMode", + "Prompt": "DO NOT USE: Internal parameter only, please do not use", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pJson", + "Prompt": "OPTIONAL: JSON Object with process parameter values. This will overwrite user passed parameters for all included parameters.", + "Value": "{}", + "Type": "String" } ], "Variables": [ @@ -387,35 +393,5 @@ "EndByte": 0 } ], - "VariablesUIData": [ - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f" - ] + "VariablesUIData": [] } \ No newline at end of file diff --git a/bedrock_processes_json/}bedrock.cube.data.copy.json b/bedrock_processes_json/}bedrock.cube.data.copy.json index 3b0f482..c5ae8cb 100644 --- a/bedrock_processes_json/}bedrock.cube.data.copy.json +++ b/bedrock_processes_json/}bedrock.cube.data.copy.json @@ -1,11 +1,11 @@ { "Name": "}bedrock.cube.data.copy", - "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.data.copy', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pCube', '', 'pSrcView', '', 'pTgtView', '', 'pFilter', '',\r\n \t'pFilterParallel', '', 'pParallelThreads', 0,\r\n \t'pEleMapping', '', 'pMappingDelim', '->',\r\n \t'pDimDelim', '&', 'pEleStartDelim', '\u00a6', 'pEleDelim', '+',\r\n \t'pFactor', 1, 'pSuppressConsol', 1, 'pSuppressConsolStrings', 0, 'pSuppressRules', 1, 'pSuppressZero', 1, 'pIncludeDescendants',0, 'pCumulate', 0,\r\n \t'pZeroTarget', 1, 'pZeroSource', 0,\r\n \t'pTemp', 1, 'pCubeLogging', 0, 'pSandbox', '', \r\n \t'pFile', 0, 'pDelim', ',', 'pQuote', '\"', 'pDecimalSeparator', '.', 'pThousandSeparator', ',', 'pSubN', 0\r\n );\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n#################################################################################################\r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n#################################################################################################\r\n\r\n#Region @DOC\r\n# Description:\r\n# This TI is intended to copy data from one element of a dimension to another in the same cube.\r\n\r\n# Use case: Mainly used in production environments.\r\n# 1/ Typically, this would be used to archive a Budget or Forecast element of a version dimension.\r\n# 2/ Could also be used to prepopulate a version from a prior year.\r\n\r\n# Note:\r\n# Naturally, a valid cube name (pCube) is required. otherwise the process will abort.\r\n# Element mapping (pEleMapping) is also required, otherwise the process will abort.\r\n# A filter parameter (pFilter) can also be used to filter dimensions that have not been mapped.\r\n# Source (pSrcView) & target (pTgtView) views will be assigned temporary names if left blank.\r\n# All other parameters may be left as is but be sure to use them appropriately when specifying pEleMapping & pFilter parameters.\r\n# - Since this TI has a view as a data source, it requires the implicit variables NValue, SValue and Value_is_String.\r\n# - To edit this TI in Architect a tmp cube with minimum 24 dims is needed as the preview data source or set the data\r\n# source to ASCII and manually edit the TI in notepad after saving to add back the required implicit view variables.\r\n# - If using the pFilterParallel parameter the **single dimension** used as the \"parallelization slicer\" cannot appear in\r\n# the pFilter and pEleMapping parameters.\r\n# - When using parallelization via the *RunProcess* function the elements listed in pFilterParallel will be split one_at_a_time\r\n# and passed to a recursive call of the process being added to pFilter.\r\n#EndRegion @DOC\r\n\r\nIf( pThreadControlFile @<> '' );\r\n LogOutput( 'INFO', 'Executed as subTI with Thread Control File: ' | pThreadControlFile );\r\nEndIf;\r\n\r\n##Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode = 0;\r\n# Target Filter Variable for shell processes\r\nStringGlobalVariable('sTargetFilter');\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSub = cThisProcName |'_'| cTimeStamp |'_'| cRandomInt;\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent= 'Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pCube:%pCube%, pSrcView:%pSrcView%, pTgtView:%pTgtView%, pFilter:%pFilter%, pFilterParallel:%pFilterParallel%, pParallelThreads:%pParallelThreads%, pEleMapping:%pEleMapping%, pMappingDelim:%pMappingDelim%, pDimDelim:%pDimDelim%, pEleStartDelim:%pEleStartDelim%, pEleDelim:%pEleDelim%, pFactor:%pFactor%, pSuppressConsol:%pSuppressConsol%, pSuppressConsolStrings:%pSuppressConsolStrings%, pSuppressRules:%pSuppressRules%, pSuppressZero:%pSuppressZero% pIncludeDescendants %pIncludeDescendants% pCumulate:%pCumulate% pZeroTarget:%pZeroTarget%, pZeroSource:%pZeroSource%, pTemp:%pTemp%, pCubeLogging:%pCubeLogging%, pSandbox:%pSandbox%, pFile:%pFile%.';\r\ncDefaultView = Expand( '%cThisProcName%_%cTimeStamp%_%cRandomInt%' );\r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) );\r\nENDIF;\r\n\r\n# Variables\r\nnDataCount = 0;\r\nnExistingSourceFlag = 0;\r\nnAttrCubeFlag = 0;\r\ncSuffixSource = 'S';\r\ncSuffixTarget = 'T';\r\ncPrefixElementAttributes = '}ElementAttributes_';\r\ncDimCountMax = 27;\r\nsDimCountMax = NumberToString( cDimCountMax );\r\nnFactor = If( pFactor = 0, 1, pFactor );\r\ncLenASCIICode = 3;\r\n\r\n## check operating system\r\nIf( SubSt( GetProcessErrorFileDirectory, 2, 1 ) @= ':' );\r\n sOS = 'Windows';\r\n sOSDelim = '\\';\r\nElseIf( Scan( '/', GetProcessErrorFileDirectory ) > 0 );\r\n sOS = 'Linux';\r\n sOSDelim = '/';\r\nElse;\r\n sOS = 'Windows';\r\n sOSDelim = '\\';\r\nEndIf;\r\n\r\n# Validate file delimiter & quote character\r\nIf( pDelim @= '' );\r\n pDelim = ',';\r\nElse;\r\n # If length of pDelim is exactly 3 chars and each of them is decimal digit, then the pDelim is entered as ASCII code\r\n nValid = 0;\r\n If ( LONG(pDelim) = cLenASCIICode );\r\n nChar = 1;\r\n While ( nChar <= cLenASCIICode );\r\n If( CODE( pDelim, nChar ) >= CODE( '0', 1 ) & CODE( pDelim, nChar ) <= CODE( '9', 1 ) );\r\n nValid = 1;\r\n Else;\r\n nValid = 0;\r\n Break;\r\n EndIf;\r\n nChar = nChar + 1;\r\n End;\r\n EndIf;\r\n If ( nValid<>0 );\r\n pDelim=CHAR(StringToNumber( pDelim ));\r\n Else;\r\n pDelim = SubSt( Trim( pDelim ), 1, 1 );\r\n EndIf;\r\nEndIf;\r\n\r\nIf( pQuote @= '' );\r\n ## Use no quote character\r\nElse;\r\n # If length of pQuote is exactly 3 chars and each of them is decimal digit, then the pQuote is entered as ASCII code\r\n nValid = 0;\r\n If ( LONG(pQuote) = cLenASCIICode );\r\n nChar = 1;\r\n While ( nChar <= cLenASCIICode );\r\n If( CODE( pQuote, nChar ) >= CODE( '0', 1 ) & CODE( pQuote, nChar ) <= CODE( '9', 1 ) );\r\n nValid = 1;\r\n Else;\r\n nValid = 0;\r\n Break;\r\n EndIf;\r\n nChar = nChar + 1;\r\n End;\r\n EndIf;\r\n If ( nValid<>0 );\r\n pQuote=CHAR(StringToNumber( pQuote ));\r\n Else;\r\n pQuote = SubSt( Trim( pQuote ), 1, 1 );\r\n EndIf;\r\nEndIf;\r\n\r\n## File location for indirect data copy\r\ncDir = GetProcessErrorFileDirectory;\r\ncFileName = LOWER(pCube) | cTimeStamp | cRandomInt | '.csv';\r\ncFile = cDir | cFileName;\r\ncTitleRows = 1;\r\ncDelimiter = pDelim;\r\ncQuote = pQuote;\r\n\r\n# nMappedDimX is a binary switch used to keep track of which dimensions have been mapped from the source to the target\r\nnMappedDim1 = 0;\r\nnMappedDim2 = 0;\r\nnMappedDim3 = 0;\r\nnMappedDim4 = 0;\r\nnMappedDim5 = 0;\r\nnMappedDim6 = 0;\r\nnMappedDim7 = 0;\r\nnMappedDim8 = 0;\r\nnMappedDim9 = 0;\r\nnMappedDim10 = 0;\r\nnMappedDim11 = 0;\r\nnMappedDim12 = 0;\r\nnMappedDim13 = 0;\r\nnMappedDim14 = 0;\r\nnMappedDim15 = 0;\r\nnMappedDim16 = 0;\r\nnMappedDim17 = 0;\r\nnMappedDim18 = 0;\r\nnMappedDim19 = 0;\r\nnMappedDim20 = 0;\r\nnMappedDim21 = 0;\r\nnMappedDim22 = 0;\r\nnMappedDim23 = 0;\r\nnMappedDim24 = 0;\r\nnMappedDim25 = 0;\r\nnMappedDim26 = 0;\r\nnMappedDim27 = 0;\r\n\r\n### Determine dimensions in target cube - we need to know this to test the cell type before loading ###\r\nsDim1 = TabDim( pCube, 1 );\r\nsDim2 = TabDim( pCube, 2 );\r\nsDim3 = TabDim( pCube, 3 );\r\nsDim4 = TabDim( pCube, 4 );\r\nsDim5 = TabDim( pCube, 5 );\r\nsDim6 = TabDim( pCube, 6 );\r\nsDim7 = TabDim( pCube, 7 );\r\nsDim8 = TabDim( pCube, 8 );\r\nsDim9 = TabDim( pCube, 9 );\r\nsDim10 = TabDim( pCube, 10 );\r\nsDim11 = TabDim( pCube, 11 );\r\nsDim12 = TabDim( pCube, 12 );\r\nsDim13 = TabDim( pCube, 13 );\r\nsDim14 = TabDim( pCube, 14 );\r\nsDim15 = TabDim( pCube, 15 );\r\nsDim16 = TabDim( pCube, 16 );\r\nsDim17 = TabDim( pCube, 17 );\r\nsDim18 = TabDim( pCube, 18 );\r\nsDim19 = TabDim( pCube, 19 );\r\nsDim20 = TabDim( pCube, 20 );\r\nsDim21 = TabDim( pCube, 21 );\r\nsDim22 = TabDim( pCube, 22 );\r\nsDim23 = TabDim( pCube, 23 );\r\nsDim24 = TabDim( pCube, 24 );\r\nsDim25 = TabDim( pCube, 25 );\r\nsDim26 = TabDim( pCube, 26 );\r\nsDim27 = TabDim( pCube, 27 );\r\n\r\n###########################\r\n### Validate Parameters ###\r\n###########################\r\nnErrors = 0;\r\n\r\n## Default filter delimiters\r\nIf( pDimDelim @= '' );\r\n pDimDelim = '&';\r\nEndIf;\r\n\r\nIf( pEleStartDelim@= '' );\r\n pEleStartDelim= '\u00a6';\r\nEndIf;\r\n\r\nIf( pEleDelim @= '' );\r\n pEleDelim = '+';\r\nEndIf;\r\n\r\nIf( pMappingDelim @= '' );\r\n pMappingDelim = '->';\r\nEndIf;\r\n\r\nIf( pDecimalSeparator @= '' );\r\n \tpDecimalSeparator = '.';\r\nEndIf;\r\nIf ( LONG(pDecimalSeparator) = cLenASCIICode );\r\n nValid = 0;\r\n nChar = 1;\r\n While ( nChar <= cLenASCIICode );\r\n If( CODE( pDecimalSeparator, nChar ) >= CODE( '0', 1 ) & CODE( pDecimalSeparator, nChar ) <= CODE( '9', 1 ) );\r\n nValid = 1;\r\n Else;\r\n nValid = 0;\r\n Break;\r\n EndIf;\r\n nChar = nChar + 1;\r\n End;\r\n If ( nValid<>0 );\r\n pDecimalSeparator = CHAR(StringToNumber( pDecimalSeparator ));\r\n Else;\r\n pDecimalSeparator = SubSt( Trim( pDecimalSeparator ), 1, 1 );\r\n EndIf;\r\nEndIf;\r\nsDecimalSeparator = pDecimalSeparator;\r\n\r\nIf( pThousandSeparator @= '' );\r\n \tpThousandSeparator = ',';\r\nEndIf;\r\nIf ( LONG(pThousandSeparator) = cLenASCIICode );\r\n nValid = 0;\r\n nChar = 1;\r\n While ( nChar <= cLenASCIICode );\r\n If( CODE( pThousandSeparator, nChar ) >= CODE( '0', 1 ) & CODE( pThousandSeparator, nChar ) <= CODE( '9', 1 ) );\r\n nValid = 1;\r\n Else;\r\n nValid = 0;\r\n Break;\r\n EndIf;\r\n nChar = nChar + 1;\r\n End;\r\n If ( nValid<>0 );\r\n pThousandSeparator = CHAR(StringToNumber( pThousandSeparator ));\r\n Else;\r\n pThousandSeparator = SubSt( Trim( pThousandSeparator ), 1, 1 );\r\n EndIf;\r\nEndIf;\r\nsThousandSeparator = pThousandSeparator;\r\n\r\n# Validate cube\r\nIf( Trim( pCube ) @= '' );\r\n nErrors = 1;\r\n sMessage = 'No cube specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( CubeExists( pCube ) = 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'Invalid source cube specified: %pCube%.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n### Determine number of dims in target cube ###\r\nnCount = 1;\r\nWhile( TabDim( pCube, nCount ) @<> '' );\r\n sDimension = TabDim( pCube, nCount );\r\n nCount = nCount + 1;\r\nEnd;\r\nnDimensionCount = nCount - 1;\r\n\r\n## If dimension count exceeds the current maximum then terminate process\r\nIf( nDimensionCount > cDimCountMax );\r\n nErrors = nErrors + 1;\r\n sMessage = 'Cube has too many dimensions: %pCube%. Max %sDimCountMax% dims catered for, TI must be altered to accommodate.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n## Validate the View parameter\r\nIf( TRIM(pSrcView) @<> '' & TRIM(pSrcView) @= TRIM(pTgtView) );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'Source and Target Views can not be the same: %pSrcView%.' ) ;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n## Validate the View parameter\r\nIf( TRIM( pSrcView) @= '' );\r\n cViewSource = Expand( '%cDefaultView%_%cSuffixSource%' ) ;\r\nElse ;\r\n cViewSource = pSrcView ;\r\n nExistingSourceFlag = 1;\r\nEndIf;\r\n\r\n## Validate the View parameter\r\nIf( TRIM( pTgtView ) @= '' );\r\n cViewTarget = Expand( '%cDefaultView%_%cSuffixTarget%' ) ;\r\nElse ;\r\n cViewTarget = pTgtView ;\r\nEndIf;\r\n\r\n# Validate parallelization filter\r\nIf( Scan( pEleStartDelim, pFilterParallel ) > 0 );\r\n sDimParallel = SubSt( pFilterParallel, 1, Scan( pEleStartDelim, pFilterParallel ) - 1 );\r\n If( Scan( Lower(sDimParallel) | pEleStartDelim, Lower(pFilter) ) > 0 );\r\n sMessage = 'Parallelization dimension %sDimParallel% cannot exist in filter.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\n If( Scan( Lower(sDimParallel) | pEleStartDelim, Lower(pEleMapping) ) > 0 );\r\n sMessage = 'Parallelization dimension %sDimParallel% cannot exist in element mapping.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\nEndIf;\r\n\r\n# Validate Max Threads\r\nIf( pParallelThreads > 0 );\r\n nMaxThreads = pParallelThreads;\r\nElse;\r\n nMaxThreads = 1;\r\nEndIf;\r\n\r\n# Validate Mapping parameter\r\nIf( pDimDelim @= pEleStartDelim % pDimDelim @= pEleDelim % pEleStartDelim @= pEleDelim );\r\n sMessage = 'The delimiters cannot me the same.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate Mapping parameter\r\nIf( TRIM( pEleMapping ) @<> '' & TRIM( pMappingDelim) @= '');\r\n nErrors = nErrors + 1;\r\n sMessage = 'Mapping Delimiter & Element Mapping can not both be empty.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndif;\r\n\r\n# Validate Sandbox\r\nIf( TRIM( pSandbox ) @<> '' );\r\n If( ServerSandboxExists( pSandbox ) = 0 );\r\n SetUseActiveSandboxProperty( 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand('Sandbox %pSandbox% is invalid for the current user.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n Else;\r\n ServerActiveSandboxSet( pSandbox );\r\n SetUseActiveSandboxProperty( 1 );\r\n EndIf;\r\nElse;\r\n SetUseActiveSandboxProperty( 0 );\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n########## pEleMapping ######################################################\r\n### Split ElementMapping parameter and create variables to be substituted ###\r\n################################################################################################# #############\r\nsElementMapping = TRIM( pEleMapping );\r\nsMappingDelimiter = TRIM( pMappingDelim );\r\nsElementStartDelim = TRIM( pEleStartDelim );\r\nsDelimDim = TRIM( pDimDelim );\r\nsDecimalSeparator = TRIM(pDecimalSeparator);\r\nsThousandSeparator = TRIM(pThousandSeparator);\r\nsFilter = TRIM( pFilter);\r\nsTargetFilter = '';\r\nnSuppressConsol = pSuppressConsol;\r\nnChar = 1;\r\nnCharCount = LONG( sElementMapping );\r\n\r\n# If there's no element mapping then the process can be used to multiply existing value by a factor\r\nIf( nCharCount > 0 );\r\n\r\n sWord = '';\r\n sLastDelim = '';\r\n\r\n # Add a trailing element delimiter so that the last element is picked up\r\n If( nCharCount > 0 );\r\n sElementMapping = sElementMapping | sMappingDelimiter ;\r\n nCharCount = nCharCount + LONG(sMappingDelimiter );\r\n EndIf;\r\n\r\n WHILE (nChar <= nCharCount);\r\n sChar = SUBST( sElementMapping, nChar, 1);\r\n\r\n # Used for delimiters, required for multiple character delimiters\r\n sDelim = '';\r\n nAddExtra = 0;\r\n\r\n # Ignore spaces\r\n IF (TRIM(sChar) @<> '' );\r\n\r\n ### Dimension Name ###\r\n\r\n # If the delimiter is more than 1 character peek ahead the same amount\r\n # Ignore the first character\r\n sDelim = sChar;\r\n nCount = LONG(sElementStartDelim) - 1;\r\n If( nCount > 0 & nChar + nCount <= nCharCount );\r\n # Add the extra characters\r\n sDelim = sDelim | SUBST( sElementMapping, nChar + 1, nCount);\r\n # Move to the end of the delimter\r\n nAddExtra = nCount;\r\n EndIf;\r\n\r\n If( sDelim @= sElementStartDelim );\r\n\r\n sChar = sDelim;\r\n\r\n If( sLastDelim @<> '' & sLastDelim @<> sDelimDim );\r\n sMessage = Expand ( 'The name of a dimension must follow a dimension delimiter %sDelimDim%' );\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n EndIf;\r\n\r\n sDimension = sWord;\r\n\r\n If( DimensionExists( sDimension ) = 0 );\r\n # The dimension does not exist in the model. Cancel process\r\n sMessage = Expand( 'Dimension: %sDimension% does not exist');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n EndIf;\r\n\r\n # Check that the dimension is in the cube\r\n i = 1;\r\n iMax = 30;\r\n sDimInCube = 'No';\r\n While( i <= iMax );\r\n sDimensionOfCube = TabDim( pCube, i );\r\n If(sDimension @= sDimensionOfCube);\r\n sDimInCube = 'Yes';\r\n # record where the loop stops\r\n nIndex = i;\r\n i = 100;\r\n Else;\r\n i = i + 1;\r\n EndIf;\r\n End;\r\n\r\n If( sDimInCube @<> 'Yes' );\r\n # The dimension does not exist in the cube. Cancel process\r\n sMessage = Expand( 'Dimension %sDimension% does not exist in this cube');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n EndIf;\r\n\r\n ### Dimension exists so add it to the filters\r\n IF(LONG(sFilter) > 0 & sLastDelim @= '');\r\n sTargetFilter = sFilter | sDelimDim | sDimension | sElementStartDelim;\r\n sFilter = sFilter | sDelimDim | sDimension | sElementStartDelim;\r\n ElseiF(LONG(sFilter) > 0 & sLastDelim@<>'');\r\n sFilter = sFilter | sDelimDim | sDimension | sElementStartDelim;\r\n sTargetFilter = sTargetFilter | sDelimDim | sDimension | sElementStartDelim;\r\n Else;\r\n sFilter = sDimension | sElementStartDelim;\r\n sTargetFilter = sDimension | sElementStartDelim;\r\n EndIf;\r\n\r\n #Reset the source and target elements\r\n sSource = '';\r\n sTarget = '';\r\n\r\n # The variable nElementCount is used to keep track of how many elements there are per dimension\r\n # the first element is the source\r\n # the second element is the target\r\n # There shouldn't be any more than 2 elements per dimension\r\n\r\n # A new dimension has been found so reset the element count so\r\n # the code can tell how many elements have been specified for each dimension\r\n # There should just be 2\r\n\r\n nElementCount = 1;\r\n sLastDelim = sChar;\r\n\r\n # Clear the word\r\n sWord = '';\r\n\r\n Else;\r\n\r\n # Reset extra chars\r\n nAddExtra = 0;\r\n\r\n ### Check both dim delimiter and element delimiter ###\r\n nIsDelimiter = 0;\r\n\r\n # Check dim delim\r\n # If the delimiter is more than 1 character peek ahead the same amount\r\n # Ignore the first character\r\n sDelim = sChar;\r\n nCount = LONG(sDelimDim) - 1;\r\n If( nCount > 0 & nChar + nCount <= nCharCount );\r\n # Add the extra characters\r\n sDelim = sDelim | SUBST( sElementMapping, nChar + 1, nCount);\r\n # Move to the end of the delimter\r\n nAddExtra = nCount;\r\n EndIf;\r\n\r\n If( sDelim @= sDelimDim );\r\n nIsDelimiter = 1;\r\n sChar = sDelim;\r\n Else;\r\n # Reset extra chars\r\n nAddExtra = 0;\r\n\r\n ## Check element delimiter\r\n\r\n # If the delimiter is more than 1 character peek ahead the same amount\r\n # Ignore the first character\r\n sDelim = sChar;\r\n nCount = LONG(sMappingDelimiter) - 1;\r\n If( nCount > 0 & nChar + nCount <= nCharCount );\r\n # Add the extra characters\r\n sDelim = sDelim | SUBST( sElementMapping, nChar + 1, nCount);\r\n # Move to the end of the delimter\r\n nAddExtra = nCount;\r\n EndIf;\r\n\r\n If( sDelim @= sMappingDelimiter );\r\n nIsDelimiter = 1;\r\n sChar = sDelim;\r\n Else;\r\n # Reset extra chars\r\n nAddExtra = 0;\r\n EndIf;\r\n\r\n EndIf;\r\n\r\n If ( nIsDelimiter = 1 );\r\n\r\n If( sLastDelim @= '' % sLastDelim @= sDelimDim );\r\n sMessage = 'An element start delimiter must follow a dimension name: ' | sChar | ' (' | NumberToString(nChar) | ')';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n EndIf;\r\n\r\n # an element has been found!\r\n sElement = sWord;\r\n\r\n If( DIMIX( sDimension, sElement ) = 0 );\r\n # The element does not exist in the dimension. Cancel process\r\n sMessage = Expand( 'Element: %sElement% does not exist in dimension %sDimension%' );\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\n\r\n # Allow consolidations only if pSuppressConsol is not set to 1\r\n # Consolidations may be made allowable\r\n # so that you can copy strings between c levels\r\n # or copy from a consolidated source element to an n level target element\r\n\r\n ### Check for errors before continuing\r\n If( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n EndIf;\r\n\r\n If ( DTYPE( sDimension, sElement) @= 'C' );\r\n IF( nElementCount = 1 );\r\n If( pSuppressConsol <> 1 );\r\n nSuppressConsol = 0;\r\n EndIf;\r\n pSubN = 1;\r\n Else;\r\n sMessage = Expand( 'Target element: %sElement% for dimension %sDimension% is consolidated' );\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessBreak;\r\n Endif;\r\n Endif;\r\n\r\n # Add the element to the source or target depending on whether it's the first or the second element\r\n # Get principal name\r\n # in case source element and this element are using different aliases\r\n\r\n sElement = DimensionElementPrincipalName(sDimension,sElement);\r\n\r\n # first element\r\n IF(nElementCount = 1);\r\n\r\n sSource = sElement;\r\n sFilter = sFilter | sElement;\r\n\r\n # second element\r\n ElseIf(nElementCount = 2);\r\n\r\n sTarget = sElement;\r\n sTargetFilter = sTargetFilter | sElement;\r\n\r\n Else;\r\n\r\n sMessage = Expand( 'There should only be 2 elements per dimension: %sDimension% , a source and a target');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n\r\n EndIf;\r\n\r\n If(nIndex = 1);\r\n nMappedDim1 = 1;\r\n sSourceDim1 = sSource;\r\n sTargetDim1 = sTarget;\r\n ElseIf(nIndex = 2);\r\n nMappedDim2 = 1;\r\n sSourceDim2 = sSource;\r\n sTargetDim2 = sTarget;\r\n ElseIf(nIndex = 3);\r\n nMappedDim3 = 1;\r\n sSourceDim3 = sSource;\r\n sTargetDim3 = sTarget;\r\n ElseIf(nIndex = 4);\r\n nMappedDim4 = 1;\r\n sSourceDim4 = sSource;\r\n sTargetDim4 = sTarget;\r\n ElseIf(nIndex = 5);\r\n nMappedDim5 = 1;\r\n sSourceDim5 = sSource;\r\n sTargetDim5 = sTarget;\r\n ElseIf(nIndex = 6);\r\n nMappedDim6 = 1;\r\n sSourceDim6 = sSource;\r\n sTargetDim6 = sTarget;\r\n ElseIf(nIndex = 7);\r\n nMappedDim7 = 1;\r\n sSourceDim7 = sSource;\r\n sTargetDim7 = sTarget;\r\n ElseIf(nIndex = 8);\r\n nMappedDim8 = 1;\r\n sSourceDim8 = sSource;\r\n sTargetDim8 = sTarget;\r\n ElseIf(nIndex = 9);\r\n nMappedDim9 = 1;\r\n sSourceDim9 = sSource;\r\n sTargetDim9 = sTarget;\r\n ElseIf(nIndex = 10);\r\n nMappedDim10 = 1;\r\n sSourceDim10 = sSource;\r\n sTargetDim10 = sTarget;\r\n ElseIf(nIndex = 11);\r\n nMappedDim11 = 1;\r\n sSourceDim11 = sSource;\r\n sTargetDim11 = sTarget;\r\n ElseIf(nIndex = 12);\r\n nMappedDim12 = 1;\r\n sSourceDim12 = sSource;\r\n sTargetDim12 = sTarget;\r\n ElseIf(nIndex = 13);\r\n nMappedDim13 = 1;\r\n sSourceDim13 = sSource;\r\n sTargetDim13 = sTarget;\r\n ElseIf(nIndex = 14);\r\n nMappedDim14 = 1;\r\n sSourceDim14 = sSource;\r\n sTargetDim14 = sTarget;\r\n ElseIf(nIndex = 15);\r\n nMappedDim15 = 1;\r\n sSourceDim15 = sSource;\r\n sTargetDim15 = sTarget;\r\n ElseIf(nIndex = 16);\r\n nMappedDim16 = 1;\r\n sSourceDim16 = sSource;\r\n sTargetDim16 = sTarget;\r\n ElseIf(nIndex = 17);\r\n nMappedDim17 = 1;\r\n sSourceDim17 = sSource;\r\n sTargetDim17 = sTarget;\r\n ElseIf(nIndex = 18);\r\n nMappedDim18 = 1;\r\n sSourceDim18 = sSource;\r\n sTargetDim18 = sTarget;\r\n ElseIf(nIndex = 19);\r\n nMappedDim19 = 1;\r\n sSourceDim19 = sSource;\r\n sTargetDim19 = sTarget;\r\n ElseIf(nIndex = 20);\r\n nMappedDim20 = 1;\r\n sSourceDim20 = sSource;\r\n sTargetDim20 = sTarget;\r\n ElseIf(nIndex = 21);\r\n nMappedDim21 = 1;\r\n sSourceDim21 = sSource;\r\n sTargetDim21 = sTarget;\r\n ElseIf(nIndex = 22);\r\n nMappedDim22 = 1;\r\n sSourceDim22 = sSource;\r\n sTargetDim22 = sTarget;\r\n ElseIf(nIndex = 23);\r\n nMappedDim23 = 1;\r\n sSourceDim23 = sSource;\r\n sTargetDim23 = sTarget;\r\n ElseIf(nIndex = 24);\r\n nMappedDim24 = 1;\r\n sSourceDim24 = sSource;\r\n sTargetDim24 = sTarget;\r\n ElseIf(nIndex = 25);\r\n nMappedDim25 = 1;\r\n sSourceDim25 = sSource;\r\n sTargetDim25 = sTarget;\r\n ElseIf(nIndex = 26);\r\n nMappedDim26 = 1;\r\n sSourceDim26 = sSource;\r\n sTargetDim26 = sTarget;\r\n ElseIf(nIndex = 27);\r\n nMappedDim27 = 1;\r\n sSourceDim27 = sSource;\r\n sTargetDim27 = sTarget;\r\n EndIf;\r\n\r\n sLastDelim = sChar;\r\n\r\n # Clear the word\r\n sWord = '';\r\n\r\n nElementCount = nElementCount + 1;\r\n\r\n Else;\r\n sWord = sWord | sChar;\r\n EndIf;\r\n\r\n EndIf;\r\n\r\n EndIf;\r\n\r\n nChar = nChar + nAddExtra + 1;\r\n\r\n END;\r\nENDIF;\r\n\r\n\r\n### Check that there if a dimension is used, there is a source element and a target element\r\ncSourceVariableStem = 'sSourceDim';\r\ncTargetVariableStem = 'sTargetDim';\r\ncMappedDimVariableStem = 'nMappedDim';\r\n\r\nnCounter = 1;\r\nWHILE(nCounter <= nDimensionCount);\r\n\r\n sMappedDimVariable = 'nMappedDim ' | NumberToString(nCounter);\r\n sDimensionUsedPadded = Expand('%' | sMappedDimVariable | '%');\r\n\r\n nMappedDim = StringToNumber(Trim(sDimensionUsedPadded));\r\n If(nMappedDim = 1);\r\n sDim = TabDim( pCube, nCounter );\r\n sSourceVariable = cSourceVariableStem | NumberToString(nCounter);\r\n sSourcePadded = Expand('%' | sSourceVariable | '%');\r\n sSource = Trim(sSourcePadded);\r\n\r\n sTargetVariable = cTargetVariableStem | NumberToString(nCounter);\r\n sTargetPadded = Expand('%' | sTargetVariable | '%');\r\n sTarget = Trim(sTargetPadded);\r\n\r\n If(sSource @='' % sTarget @='');\r\n sMessage = 'Source and/or target element is blank for dimension ' | sDim;\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n EndIf;\r\n\r\n EndIf;\r\n\r\nnCounter = nCounter + 1;\r\n\r\nEND;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n DataSourceType = 'NULL';\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n# Branch depending on whether to do recursive calls to self on independent threads or run all in this thread\r\nIf( Scan( pEleStartDelim, pFilterParallel ) > 0 );\r\n sDimParallel = SubSt( pFilterParallel, 1, Scan( pEleStartDelim, pFilterParallel ) - 1 );\r\n sElementList = SubSt( pFilterParallel, Scan( pEleStartDelim, pFilterParallel ) + Long( pEleStartDelim ), Long( pFilterParallel ) );\r\n If( SubSt( sElementList, Long( sElementList ), 1 ) @<> pEleDelim );\r\n sElementList = sElementList | pEleDelim;\r\n EndIf;\r\n ## Counting elements in element list\r\n sElementListCount = sElementList;\r\n nElements = 0;\r\n While( Scan( pEleDelim, sElementListCount ) > 0 );\r\n nElements = nElements + 1;\r\n sElementListCount = SubSt( sElementListCount, Scan( pEleDelim, sElementListCount ) + Long( pEleDelim ), Long( sElementListCount ) );\r\n End;\r\n IF( Mod( nElements, nMaxThreads ) = 0 );\r\n nElemsPerThread = INT( nElements / nMaxThreads );\r\n ELSE;\r\n nElemsPerThread = INT( nElements / nMaxThreads ) + 1;\r\n ENDIF;\r\n nThreadElCounter = 0;\r\n nThreads = 0;\r\n While( Scan( pEleDelim, sElementList ) > 0 );\r\n sSlicerEle = SubSt( sElementList, 1, Scan( pEleDelim, sElementList ) - 1 );\r\n sElementList = SubSt( sElementList, Scan( pEleDelim, sElementList ) + Long( pEleDelim ), Long( sElementList ) );\r\n # Do recursive process call with new RunProcess function\r\n nThreadElCounter = nThreadElCounter + 1;\r\n sDimDelim = If(pFilter @= '', '', pDimDelim );\r\n IF( nThreadElCounter = 1 );\r\n sFilter = Expand('%pFilter%%sDimDelim%%sDimParallel%%pEleStartDelim%%sSlicerEle%');\r\n ELSE;\r\n sFilter = Expand('%sFilter%%pEleDelim%%sSlicerEle%');\r\n ENDIF;\r\n IF( nThreadElCounter >= nElemsPerThread );\r\n nThreadID = INT( RAND( ) * 10000 + 1) + Numbr(cTimeStamp);\r\n sThreadControlFile = LOWER( GetProcessName() | '_ThreadControlFile_' | cRandomInt | '_' | NumberToString(nThreadID) | '_' | cTimeStamp );\r\n AsciiOutput( cDir | sThreadControlFile | '.txt', '' );\r\n LogOutput( 'INFO', 'Executing subTI with Thread ID: ' | NumberToString(nThreadID) );\r\n RunProcess( cThisProcName, 'pLogoutput', pLogoutput,\r\n \t'pCube', pCube, 'pSrcView', pSrcView, 'pTgtView', pTgtView,\r\n \t'pFilter', sFilter, 'pFilterParallel', '', 'pEleMapping', pEleMapping, 'pMappingDelim', pMappingDelim,\r\n \t'pDimDelim', pDimDelim, 'pEleStartDelim', pEleStartDelim, 'pEleDelim', pEleDelim,\r\n \t'pFactor', pFactor, 'pSuppressConsol', pSuppressConsol, 'pSuppressConsolStrings', pSuppressConsolStrings, 'pSuppressRules', pSuppressRules, 'pSuppressZero', pSuppressZero, 'pCumulate', pCumulate,\r\n \t'pZeroTarget', pZeroTarget, 'pZeroSource', pZeroSource, 'pTemp', pTemp, 'pCubeLogging', pCubeLogging, 'pSandbox', pSandbox, 'pFile', pFile, 'pDecimalSeparator', pDecimalSeparator, 'pThousandSeparator', pThousandSeparator,\r\n 'pThreadMode', 1, 'pThreadControlFile', sThreadControlFile\r\n );\r\n \t nThreadElCounter = 0;\r\n \t sFilter = '';\r\n \t nThreads = nThreads + 1;\r\n \tENDIF;\r\n End;\r\n ## Process last elements - only when filter is not empty (there are still elements)\r\n IF( sFilter @<> '' );\r\n RunProcess( cThisProcName, 'pLogoutput', pLogoutput,\r\n \t'pCube', pCube, 'pSrcView', pSrcView, 'pTgtView', pTgtView,\r\n \t'pFilter', sFilter, 'pFilterParallel', '', 'pEleMapping', pEleMapping, 'pMappingDelim', pMappingDelim,\r\n \t'pDimDelim', pDimDelim, 'pEleStartDelim', pEleStartDelim, 'pEleDelim', pEleDelim,\r\n \t'pFactor', pFactor, 'pSuppressConsol', pSuppressConsol, 'pSuppressConsolStrings', pSuppressConsolStrings, 'pSuppressRules', pSuppressRules, 'pSuppressZero', pSuppressZero, 'pCumulate', pCumulate,\r\n \t'pZeroTarget', pZeroTarget, 'pZeroSource', pZeroSource, 'pTemp', pTemp, 'pCubeLogging', pCubeLogging, 'pSandbox', pSandbox, 'pFile', pFile, 'pDecimalSeparator', pDecimalSeparator, 'pThousandSeparator', pThousandSeparator,\r\n 'pThreadMode', 1, 'pThreadControlFile', sThreadControlFile\r\n );\r\n ENDIF;\r\n DataSourceType = 'NULL';\r\n Sleep( 1000 );\r\nElse;\r\n ### Create View of target to zero out\r\n ### Check that there's something in sTargetFilter so the cube doesn't accidentally get wiped out\r\n IF( pThreadControlFile @<> '' );\r\n LogOutput( 'info', 'creating thread file ' | cDir | pThreadControlFile | '.txt' );\r\n AsciiOutput( cDir | pThreadControlFile | '.txt', '' );\r\n ENDIF;\r\n If(pZeroTarget = 1 & LONG(sTargetFilter)> 0);\r\n\r\n sProc = '}bedrock.cube.data.clear';\r\n nRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCube,\r\n 'pView', cViewTarget,\r\n 'pFilter', sTargetFilter,\r\n 'pDimDelim', pDimDelim,\r\n 'pEleStartDelim', pEleStartDelim,\r\n 'pEleDelim', pEleDelim,\r\n 'pCubeLogging', pCubeLogging,\r\n 'pTemp', pTemp,\r\n 'pSandbox', pSandbox\r\n );\r\n\r\n IF(nRet <> 0);\r\n sMessage = 'Error clearing the target view.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n\r\n Endif;\r\n\r\n If( pFile = 0 );\r\n\r\n ### Create View of Source ###\r\n\r\n nRet = ExecuteProcess('}bedrock.cube.view.create',\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCube,\r\n 'pView', cViewSource,\r\n 'pFilter', sFilter,\r\n 'pSuppressZero', pSuppressZero,\r\n 'pSuppressConsol', nSuppressConsol,\r\n 'pSuppressRules', pSuppressRules,\r\n 'pSuppressConsolStrings', pSuppressConsolStrings,\r\n 'pIncludeDescendants',pIncludeDescendants,\r\n 'pDimDelim', pDimDelim,\r\n 'pEleStartDelim', pEleStartDelim,\r\n 'pEleDelim', pEleDelim ,\r\n 'pTemp', pTemp,\r\n 'pSubN', pSubN\r\n );\r\n\r\n IF(nRet <> 0);\r\n sMessage = 'Error creating the view from the filter.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n\r\n\r\n ### Assign Datasource ###\r\n DataSourceType = 'VIEW';\r\n DatasourceNameForServer = pCube;\r\n DatasourceNameForClient = pCube;\r\n DatasourceCubeView = cViewSource;\r\n nThreadMode = 1;\r\n Else;\r\n ### Export Data to file ###\r\n\r\n nRet = ExecuteProcess('}bedrock.cube.data.export',\r\n 'pLogoutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCube,\r\n 'pView', cViewSource,\r\n 'pFilter', sFilter,\r\n 'pFilterParallel', '',\r\n 'pParallelThreads', 0,\r\n 'pDimDelim', pDimDelim,\r\n 'pEleStartDelim', pEleStartDelim,\r\n 'pEleDelim', pEleDelim,\r\n 'pSuppressZero', pSuppressZero,\r\n 'pSuppressConsol', nSuppressConsol,\r\n 'pSuppressRules', pSuppressRules,\r\n 'pSuppressConsolStrings', pSuppressConsolStrings,\r\n 'pIncludeDescendants',pIncludeDescendants,\r\n 'pZeroSource', 0,\r\n 'pCubeLogging', pCubeLogging,\r\n 'pTemp', pTemp,\r\n 'pFilePath', cDir,\r\n 'pFileName', cFileName,\r\n 'pDelim', cDelimiter,\r\n 'pDecimalSeparator', sDecimalSeparator,\r\n 'pThousandSeparator', sThousandSeparator,\r\n 'pQuote', cQuote,\r\n 'pTitleRecord', cTitleRows,\r\n 'pSandbox', pSandbox\r\n );\r\n\r\n IF(nRet <> 0);\r\n sMessage = 'Error exporting data to file.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n\r\n If(FileExists(cFile) = 0);\r\n # If the file does not exist, it means that nothing got exported, so there is nothing to import\r\n If( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( 'Process:%cThisProcName% is skipping import as export file %cFile% was not found.' ) );\r\n EndIf;\r\n DataSourceType = 'NULL';\r\n Else;\r\n ### Assign Datasource ###\r\n DataSourceType = 'CHARACTERDELIMITED';\r\n DatasourceNameForServer = cFile;\r\n DatasourceNameForClient = cFile;\r\n DatasourceASCIIHeaderRecords = cTitleRows;\r\n DatasourceASCIIDelimiter = cDelimiter;\r\n DatasourceASCIIQuoteCharacter = cQuote;\r\n EndIf;\r\n\r\n nThreadMode = 1;\r\n\r\n EndIf;\r\n\r\nEndIf;\r\n\r\n### End Prolog ###\r\n", + "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.data.copy', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pCube', '', 'pSrcView', '', 'pTgtView', '', 'pFilter', '',\r\n \t'pFilterParallel', '', 'pParallelThreads', 0,\r\n \t'pEleMapping', '', 'pMappingDelim', '->',\r\n \t'pDimDelim', '&', 'pEleStartDelim', '\u00a6', 'pEleDelim', '+',\r\n \t'pFactor', 1, 'pSuppressConsol', 1, 'pSuppressConsolStrings', 0, 'pSuppressRules', 1, 'pSuppressZero', 1, 'pIncludeDescendants',0, 'pCumulate', 0,\r\n \t'pZeroTarget', 1, 'pZeroSource', 0,\r\n \t'pTemp', 1, 'pCubeLogging', 0, 'pSandbox', '', \r\n \t'pFile', 0, 'pDelim', ',', 'pQuote', '\"', 'pDecimalSeparator', '.', 'pThousandSeparator', ',', 'pSubN', 0\r\n );\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n#################################################################################################\r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n#################################################################################################\r\n\r\n#Region @DOC\r\n# Description:\r\n# This TI is intended to copy data from one element of a dimension to another in the same cube.\r\n\r\n# Use case: Mainly used in production environments.\r\n# 1/ Typically, this would be used to archive a Budget or Forecast element of a version dimension.\r\n# 2/ Could also be used to prepopulate a version from a prior year.\r\n\r\n# Note:\r\n# Naturally, a valid cube name (pCube) is required. otherwise the process will abort.\r\n# Element mapping (pEleMapping) is also required, otherwise the process will abort.\r\n# A filter parameter (pFilter) can also be used to filter dimensions that have not been mapped.\r\n# Source (pSrcView) & target (pTgtView) views will be assigned temporary names if left blank.\r\n# All other parameters may be left as is but be sure to use them appropriately when specifying pEleMapping & pFilter parameters.\r\n# - Since this TI has a view as a data source, it requires the implicit variables NValue, SValue and Value_is_String.\r\n# - To edit this TI in Architect a tmp cube with minimum 24 dims is needed as the preview data source or set the data\r\n# source to ASCII and manually edit the TI in notepad after saving to add back the required implicit view variables.\r\n# - If using the pFilterParallel parameter the **single dimension** used as the \"parallelization slicer\" cannot appear in\r\n# the pFilter and pEleMapping parameters.\r\n# - When using parallelization via the *RunProcess* function the elements listed in pFilterParallel will be split one_at_a_time\r\n# and passed to a recursive call of the process being added to pFilter.\r\n#EndRegion @DOC\r\n\r\nIf( pThreadControlFile @<> '' );\r\n LogOutput( 'INFO', 'Executed as subTI with Thread Control File: ' | pThreadControlFile );\r\nEndIf;\r\n\r\n##Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode = 0;\r\n# Target Filter Variable for shell processes\r\nStringGlobalVariable('sTargetFilter');\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSub = cThisProcName |'_'| cTimeStamp |'_'| cRandomInt;\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent= 'Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pCube:%pCube%, pSrcView:%pSrcView%, pTgtView:%pTgtView%, pFilter:%pFilter%, pFilterParallel:%pFilterParallel%, pParallelThreads:%pParallelThreads%, pEleMapping:%pEleMapping%, pMappingDelim:%pMappingDelim%, pDimDelim:%pDimDelim%, pEleStartDelim:%pEleStartDelim%, pEleDelim:%pEleDelim%, pFactor:%pFactor%, pSuppressConsol:%pSuppressConsol%, pSuppressConsolStrings:%pSuppressConsolStrings%, pSuppressRules:%pSuppressRules%, pSuppressZero:%pSuppressZero% pIncludeDescendants %pIncludeDescendants% pCumulate:%pCumulate% pZeroTarget:%pZeroTarget%, pZeroSource:%pZeroSource%, pTemp:%pTemp%, pCubeLogging:%pCubeLogging%, pSandbox:%pSandbox%, pFile:%pFile%.';\r\ncDefaultView = Expand( '%cThisProcName%_%cTimeStamp%_%cRandomInt%' );\r\n\r\n#################################################################################################\r\n#Region - Process Parameters\r\n\r\npJson = IF( JsonType( pJson ) @<> 'object', '{}', pJson );\r\nsMessages = '{\"Process\": \"'|GetProcessName()|'\", \"User\": \"'|TM1User()|'\", \"Info\": [\"Process: '''|GetProcessName()|''' run by User: '''|TM1User()|'''.\"], \"Error\": []}';\r\npDefaultParameters = '{\r\n \"pCube\": null,\r\n \"pDecimalSeparator\": \".\",\r\n \"pDelim\": \"&\",\r\n \"pDimDelim\": \"&\",\r\n \"pEleDelim\": \"+\",\r\n \"pEleMapping\": null,\r\n \"pEleStartDelim\": \"\u00a6\",\r\n \"pFilter\": \"\",\r\n \"pFilterParallel\": \"\",\r\n \"pMappingDelim\": \"->\",\r\n \"pQuote\": \"\"\",\r\n \"pSandbox\": \"\",\r\n \"pSrcView\": \"\",\r\n \"pTgtView\": \"\",\r\n \"pThousandSeparator\": \",\",\r\n \"pThreadControlFile\": \"\",\r\n \"pCumulate\": 0,\r\n \"pFactor\": 1,\r\n \"pFile\": 0,\r\n \"pIncludeDescendants\": 0,\r\n \"pLogOutput\": 0,\r\n \"pMaxWaitSeconds\": 1800,\r\n \"pParallelThreads\": 0,\r\n \"pStrictErrorHandling\": 0,\r\n \"pSubN\": 0,\r\n \"pSuppressConsol\": 1,\r\n \"pSuppressConsolStrings\": 1,\r\n \"pSuppressRules\": 1,\r\n \"pSuppressZero\": 1,\r\n \"pTemp\": 1,\r\n \"pThreadMode\": 0,\r\n \"pZeroSource\": 0,\r\n \"pZeroTarget\": 1\r\n}';\r\n\r\npPassedParameters = '{\r\n \"pCube\": '|StringToJson ( pCube )|',\r\n \"pDecimalSeparator\": '|StringToJson ( pDecimalSeparator )|',\r\n \"pDelim\": '|StringToJson ( pDelim )|',\r\n \"pDimDelim\": '|StringToJson ( pDimDelim )|',\r\n \"pEleDelim\": '|StringToJson ( pEleDelim )|',\r\n \"pEleMapping\": '|StringToJson ( pEleMapping )|',\r\n \"pEleStartDelim\": '|StringToJson ( pEleStartDelim )|',\r\n \"pFilter\": '|StringToJson ( pFilter )|',\r\n \"pFilterParallel\": '|StringToJson ( pFilterParallel )|',\r\n \"pMappingDelim\": '|StringToJson ( pMappingDelim )|',\r\n \"pQuote\": '|StringToJson ( pQuote )|',\r\n \"pSandbox\": '|StringToJson ( pSandbox )|',\r\n \"pSrcView\": '|StringToJson ( pSrcView )|',\r\n \"pTgtView\": '|StringToJson ( pTgtView )|',\r\n \"pThousandSeparator\": '|StringToJson ( pThousandSeparator )|',\r\n \"pThreadControlFile\": '|StringToJson ( pThreadControlFile )|',\r\n \"pCumulate\": '|NumberToString( pCumulate )|',\r\n \"pFactor\": '|NumberToString( pFactor )|',\r\n \"pFile\": '|NumberToString( pFile )|',\r\n \"pIncludeDescendants\": '|NumberToString( pIncludeDescendants )|',\r\n \"pLogOutput\": '|NumberToString( pLogOutput )|',\r\n \"pMaxWaitSeconds\": '|NumberToString( pMaxWaitSeconds )|',\r\n \"pParallelThreads\": '|NumberToString( pParallelThreads )|',\r\n \"pStrictErrorHandling\": '|NumberToString( pStrictErrorHandling )|',\r\n \"pSubN\": '|NumberToString( pSubN )|',\r\n \"pSuppressConsol\": '|NumberToString( pSuppressConsol )|',\r\n \"pSuppressConsolStrings\": '|NumberToString( pSuppressConsolStrings )|',\r\n \"pSuppressRules\": '|NumberToString( pSuppressRules )|',\r\n \"pSuppressZero\": '|NumberToString( pSuppressZero )|',\r\n \"pTemp\": '|NumberToString( pTemp )|',\r\n \"pThreadMode\": '|NumberToString( pThreadMode )|',\r\n \"pZeroSource\": '|NumberToString( pZeroSource )|',\r\n \"pZeroTarget\": '|NumberToString( pZeroTarget )|'\r\n}';\r\n\r\npJson = JsonMergePatch( pPassedParameters, pJson );\r\n# String Parameters\r\npCube = JsonToString( JsonGet( pJson, 'pCube' ) );\r\npDecimalSeparator = JsonToString( JsonGet( pJson, 'pDecimalSeparator' ) );\r\npDelim = JsonToString( JsonGet( pJson, 'pDelim' ) );\r\npDimDelim = JsonToString( JsonGet( pJson, 'pDimDelim' ) );\r\npEleDelim = JsonToString( JsonGet( pJson, 'pEleDelim' ) );\r\npEleMapping = JsonToString( JsonGet( pJson, 'pEleMapping' ) );\r\npEleStartDelim = JsonToString( JsonGet( pJson, 'pEleStartDelim' ) );\r\npFilter = JsonToString( JsonGet( pJson, 'pFilter' ) );\r\npFilterParallel = JsonToString( JsonGet( pJson, 'pFilterParallel' ) );\r\npMappingDelim = JsonToString( JsonGet( pJson, 'pMappingDelim' ) );\r\npQuote = JsonToString( JsonGet( pJson, 'pQuote' ) );\r\npSandbox = JsonToString( JsonGet( pJson, 'pSandbox' ) );\r\npSrcView = JsonToString( JsonGet( pJson, 'pSrcView' ) );\r\npTgtView = JsonToString( JsonGet( pJson, 'pTgtView' ) );\r\npThousandSeparator = JsonToString( JsonGet( pJson, 'pThousandSeparator' ) );\r\npThreadControlFile = JsonToString( JsonGet( pJson, 'pThreadControlFile' ) );\r\n# Numeric Parameters\r\npCumulate = StringToNumber( JsonToString( JsonGet( pJson, 'pCumulate' ) ) );\r\npFactor = StringToNumber( JsonToString( JsonGet( pJson, 'pFactor' ) ) );\r\npFile = StringToNumber( JsonToString( JsonGet( pJson, 'pFile' ) ) );\r\npIncludeDescendants = StringToNumber( JsonToString( JsonGet( pJson, 'pIncludeDescendants' ) ) );\r\npLogOutput = StringToNumber( JsonToString( JsonGet( pJson, 'pLogOutput' ) ) );\r\npMaxWaitSeconds = StringToNumber( JsonToString( JsonGet( pJson, 'pMaxWaitSeconds' ) ) );\r\npParallelThreads = StringToNumber( JsonToString( JsonGet( pJson, 'pParallelThreads' ) ) );\r\npStrictErrorHandling = StringToNumber( JsonToString( JsonGet( pJson, 'pStrictErrorHandling' ) ) );\r\npSubN = StringToNumber( JsonToString( JsonGet( pJson, 'pSubN' ) ) );\r\npSuppressConsol = StringToNumber( JsonToString( JsonGet( pJson, 'pSuppressConsol' ) ) );\r\npSuppressConsolStrings = StringToNumber( JsonToString( JsonGet( pJson, 'pSuppressConsolStrings' ) ) );\r\npSuppressRules = StringToNumber( JsonToString( JsonGet( pJson, 'pSuppressRules' ) ) );\r\npSuppressZero = StringToNumber( JsonToString( JsonGet( pJson, 'pSuppressZero' ) ) );\r\npTemp = StringToNumber( JsonToString( JsonGet( pJson, 'pTemp' ) ) );\r\npThreadMode = StringToNumber( JsonToString( JsonGet( pJson, 'pThreadMode' ) ) );\r\npZeroSource = StringToNumber( JsonToString( JsonGet( pJson, 'pZeroSource' ) ) );\r\npZeroTarget = StringToNumber( JsonToString( JsonGet( pJson, 'pZeroTarget' ) ) );\r\n\r\n### Get the parameters that differ from the default\r\npDiffer = JsonDiff( pDefaultParameters, pJson );\r\nnSize = JsonSize( pDiffer );\r\nWHILE( nSize > 0 );\r\n nSize = nSize - 1;\r\n pDiffer = JsonReplace( pDiffer, '/'|NumberToString( nSize )|'/op', '\"add\"' );\r\nEND;\r\npJson = JsonPatch( '{}', pDiffer );\r\n\r\n### LogOutput parameters\r\nsMessages = JsonAdd( sMessages, '/Info/-', pJson );\r\nIF( pLogOutput = 1 );\r\n LogOutput('INFO', JsonToString( sMessages, '/Info/0', 0, ' ' ) );\r\nENDIF;\r\n\r\n#EndRegion - Process Parameters\r\n#################################################################################################\r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) );\r\nENDIF;\r\n\r\n# Variables\r\nnDataCount = 0;\r\nnExistingSourceFlag = 0;\r\nnAttrCubeFlag = 0;\r\ncSuffixSource = 'S';\r\ncSuffixTarget = 'T';\r\ncPrefixElementAttributes = '}ElementAttributes_';\r\ncDimCountMax = 27;\r\nsDimCountMax = NumberToString( cDimCountMax );\r\nnFactor = If( pFactor = 0, 1, pFactor );\r\ncLenASCIICode = 3;\r\n\r\n## check operating system\r\nIf( SubSt( GetProcessErrorFileDirectory, 2, 1 ) @= ':' );\r\n sOS = 'Windows';\r\n sOSDelim = '\\';\r\nElseIf( Scan( '/', GetProcessErrorFileDirectory ) > 0 );\r\n sOS = 'Linux';\r\n sOSDelim = '/';\r\nElse;\r\n sOS = 'Windows';\r\n sOSDelim = '\\';\r\nEndIf;\r\n\r\n# Validate file delimiter & quote character\r\nIf( pDelim @= '' );\r\n pDelim = ',';\r\nElse;\r\n # If length of pDelim is exactly 3 chars and each of them is decimal digit, then the pDelim is entered as ASCII code\r\n nValid = 0;\r\n If ( LONG(pDelim) = cLenASCIICode );\r\n nChar = 1;\r\n While ( nChar <= cLenASCIICode );\r\n If( CODE( pDelim, nChar ) >= CODE( '0', 1 ) & CODE( pDelim, nChar ) <= CODE( '9', 1 ) );\r\n nValid = 1;\r\n Else;\r\n nValid = 0;\r\n Break;\r\n EndIf;\r\n nChar = nChar + 1;\r\n End;\r\n EndIf;\r\n If ( nValid<>0 );\r\n pDelim=CHAR(StringToNumber( pDelim ));\r\n Else;\r\n pDelim = SubSt( Trim( pDelim ), 1, 1 );\r\n EndIf;\r\nEndIf;\r\n\r\nIf( pQuote @= '' );\r\n ## Use no quote character\r\nElse;\r\n # If length of pQuote is exactly 3 chars and each of them is decimal digit, then the pQuote is entered as ASCII code\r\n nValid = 0;\r\n If ( LONG(pQuote) = cLenASCIICode );\r\n nChar = 1;\r\n While ( nChar <= cLenASCIICode );\r\n If( CODE( pQuote, nChar ) >= CODE( '0', 1 ) & CODE( pQuote, nChar ) <= CODE( '9', 1 ) );\r\n nValid = 1;\r\n Else;\r\n nValid = 0;\r\n Break;\r\n EndIf;\r\n nChar = nChar + 1;\r\n End;\r\n EndIf;\r\n If ( nValid<>0 );\r\n pQuote=CHAR(StringToNumber( pQuote ));\r\n Else;\r\n pQuote = SubSt( Trim( pQuote ), 1, 1 );\r\n EndIf;\r\nEndIf;\r\n\r\n## File location for indirect data copy\r\ncDir = GetProcessErrorFileDirectory;\r\ncFileName = LOWER(pCube) | cTimeStamp | cRandomInt | '.csv';\r\ncFile = cDir | cFileName;\r\ncTitleRows = 1;\r\ncDelimiter = pDelim;\r\ncQuote = pQuote;\r\n\r\n# nMappedDimX is a binary switch used to keep track of which dimensions have been mapped from the source to the target\r\nnMappedDim1 = 0;\r\nnMappedDim2 = 0;\r\nnMappedDim3 = 0;\r\nnMappedDim4 = 0;\r\nnMappedDim5 = 0;\r\nnMappedDim6 = 0;\r\nnMappedDim7 = 0;\r\nnMappedDim8 = 0;\r\nnMappedDim9 = 0;\r\nnMappedDim10 = 0;\r\nnMappedDim11 = 0;\r\nnMappedDim12 = 0;\r\nnMappedDim13 = 0;\r\nnMappedDim14 = 0;\r\nnMappedDim15 = 0;\r\nnMappedDim16 = 0;\r\nnMappedDim17 = 0;\r\nnMappedDim18 = 0;\r\nnMappedDim19 = 0;\r\nnMappedDim20 = 0;\r\nnMappedDim21 = 0;\r\nnMappedDim22 = 0;\r\nnMappedDim23 = 0;\r\nnMappedDim24 = 0;\r\nnMappedDim25 = 0;\r\nnMappedDim26 = 0;\r\nnMappedDim27 = 0;\r\n\r\n### Determine dimensions in target cube - we need to know this to test the cell type before loading ###\r\nsDim1 = TabDim( pCube, 1 );\r\nsDim2 = TabDim( pCube, 2 );\r\nsDim3 = TabDim( pCube, 3 );\r\nsDim4 = TabDim( pCube, 4 );\r\nsDim5 = TabDim( pCube, 5 );\r\nsDim6 = TabDim( pCube, 6 );\r\nsDim7 = TabDim( pCube, 7 );\r\nsDim8 = TabDim( pCube, 8 );\r\nsDim9 = TabDim( pCube, 9 );\r\nsDim10 = TabDim( pCube, 10 );\r\nsDim11 = TabDim( pCube, 11 );\r\nsDim12 = TabDim( pCube, 12 );\r\nsDim13 = TabDim( pCube, 13 );\r\nsDim14 = TabDim( pCube, 14 );\r\nsDim15 = TabDim( pCube, 15 );\r\nsDim16 = TabDim( pCube, 16 );\r\nsDim17 = TabDim( pCube, 17 );\r\nsDim18 = TabDim( pCube, 18 );\r\nsDim19 = TabDim( pCube, 19 );\r\nsDim20 = TabDim( pCube, 20 );\r\nsDim21 = TabDim( pCube, 21 );\r\nsDim22 = TabDim( pCube, 22 );\r\nsDim23 = TabDim( pCube, 23 );\r\nsDim24 = TabDim( pCube, 24 );\r\nsDim25 = TabDim( pCube, 25 );\r\nsDim26 = TabDim( pCube, 26 );\r\nsDim27 = TabDim( pCube, 27 );\r\n\r\n###########################\r\n### Validate Parameters ###\r\n###########################\r\nnErrors = 0;\r\n\r\n## Default filter delimiters\r\nIf( pDimDelim @= '' );\r\n pDimDelim = '&';\r\nEndIf;\r\n\r\nIf( pEleStartDelim@= '' );\r\n pEleStartDelim= '\u00a6';\r\nEndIf;\r\n\r\nIf( pEleDelim @= '' );\r\n pEleDelim = '+';\r\nEndIf;\r\n\r\nIf( pMappingDelim @= '' );\r\n pMappingDelim = '->';\r\nEndIf;\r\n\r\nIf( pDecimalSeparator @= '' );\r\n \tpDecimalSeparator = '.';\r\nEndIf;\r\nIf ( LONG(pDecimalSeparator) = cLenASCIICode );\r\n nValid = 0;\r\n nChar = 1;\r\n While ( nChar <= cLenASCIICode );\r\n If( CODE( pDecimalSeparator, nChar ) >= CODE( '0', 1 ) & CODE( pDecimalSeparator, nChar ) <= CODE( '9', 1 ) );\r\n nValid = 1;\r\n Else;\r\n nValid = 0;\r\n Break;\r\n EndIf;\r\n nChar = nChar + 1;\r\n End;\r\n If ( nValid<>0 );\r\n pDecimalSeparator = CHAR(StringToNumber( pDecimalSeparator ));\r\n Else;\r\n pDecimalSeparator = SubSt( Trim( pDecimalSeparator ), 1, 1 );\r\n EndIf;\r\nEndIf;\r\nsDecimalSeparator = pDecimalSeparator;\r\n\r\nIf( pThousandSeparator @= '' );\r\n \tpThousandSeparator = ',';\r\nEndIf;\r\nIf ( LONG(pThousandSeparator) = cLenASCIICode );\r\n nValid = 0;\r\n nChar = 1;\r\n While ( nChar <= cLenASCIICode );\r\n If( CODE( pThousandSeparator, nChar ) >= CODE( '0', 1 ) & CODE( pThousandSeparator, nChar ) <= CODE( '9', 1 ) );\r\n nValid = 1;\r\n Else;\r\n nValid = 0;\r\n Break;\r\n EndIf;\r\n nChar = nChar + 1;\r\n End;\r\n If ( nValid<>0 );\r\n pThousandSeparator = CHAR(StringToNumber( pThousandSeparator ));\r\n Else;\r\n pThousandSeparator = SubSt( Trim( pThousandSeparator ), 1, 1 );\r\n EndIf;\r\nEndIf;\r\nsThousandSeparator = pThousandSeparator;\r\n\r\n# Validate cube\r\nIf( Trim( pCube ) @= '' );\r\n nErrors = 1;\r\n sMessage = 'No cube specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( CubeExists( pCube ) = 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'Invalid source cube specified: %pCube%.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n### Determine number of dims in target cube ###\r\nnCount = 1;\r\nWhile( TabDim( pCube, nCount ) @<> '' );\r\n sDimension = TabDim( pCube, nCount );\r\n nCount = nCount + 1;\r\nEnd;\r\nnDimensionCount = nCount - 1;\r\n\r\n## If dimension count exceeds the current maximum then terminate process\r\nIf( nDimensionCount > cDimCountMax );\r\n nErrors = nErrors + 1;\r\n sMessage = 'Cube has too many dimensions: %pCube%. Max %sDimCountMax% dims catered for, TI must be altered to accommodate.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n## Validate the View parameter\r\nIf( TRIM(pSrcView) @<> '' & TRIM(pSrcView) @= TRIM(pTgtView) );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'Source and Target Views can not be the same: %pSrcView%.' ) ;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n## Validate the View parameter\r\nIf( TRIM( pSrcView) @= '' );\r\n cViewSource = Expand( '%cDefaultView%_%cSuffixSource%' ) ;\r\nElse ;\r\n cViewSource = pSrcView ;\r\n nExistingSourceFlag = 1;\r\nEndIf;\r\n\r\n## Validate the View parameter\r\nIf( TRIM( pTgtView ) @= '' );\r\n cViewTarget = Expand( '%cDefaultView%_%cSuffixTarget%' ) ;\r\nElse ;\r\n cViewTarget = pTgtView ;\r\nEndIf;\r\n\r\n# Validate parallelization filter\r\nIf( Scan( pEleStartDelim, pFilterParallel ) > 0 );\r\n sDimParallel = SubSt( pFilterParallel, 1, Scan( pEleStartDelim, pFilterParallel ) - 1 );\r\n If( Scan( Lower(sDimParallel) | pEleStartDelim, Lower(pFilter) ) > 0 );\r\n sMessage = 'Parallelization dimension %sDimParallel% cannot exist in filter.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\n If( Scan( Lower(sDimParallel) | pEleStartDelim, Lower(pEleMapping) ) > 0 );\r\n sMessage = 'Parallelization dimension %sDimParallel% cannot exist in element mapping.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\nEndIf;\r\n\r\n# Validate Max Threads\r\nIf( pParallelThreads > 0 );\r\n nMaxThreads = pParallelThreads;\r\nElse;\r\n nMaxThreads = 1;\r\nEndIf;\r\n\r\n# Validate Mapping parameter\r\nIf( pDimDelim @= pEleStartDelim % pDimDelim @= pEleDelim % pEleStartDelim @= pEleDelim );\r\n sMessage = 'The delimiters cannot me the same.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate Mapping parameter\r\nIf( TRIM( pEleMapping ) @<> '' & TRIM( pMappingDelim) @= '');\r\n nErrors = nErrors + 1;\r\n sMessage = 'Mapping Delimiter & Element Mapping can not both be empty.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndif;\r\n\r\n# Validate Sandbox\r\nIf( TRIM( pSandbox ) @<> '' );\r\n If( ServerSandboxExists( pSandbox ) = 0 );\r\n SetUseActiveSandboxProperty( 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand('Sandbox %pSandbox% is invalid for the current user.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n Else;\r\n ServerActiveSandboxSet( pSandbox );\r\n SetUseActiveSandboxProperty( 1 );\r\n EndIf;\r\nElse;\r\n SetUseActiveSandboxProperty( 0 );\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n########## pEleMapping ######################################################\r\n### Split ElementMapping parameter and create variables to be substituted ###\r\n################################################################################################# #############\r\nsElementMapping = TRIM( pEleMapping );\r\nsMappingDelimiter = TRIM( pMappingDelim );\r\nsElementStartDelim = TRIM( pEleStartDelim );\r\nsDelimDim = TRIM( pDimDelim );\r\nsDecimalSeparator = TRIM(pDecimalSeparator);\r\nsThousandSeparator = TRIM(pThousandSeparator);\r\nsFilter = TRIM( pFilter);\r\nsTargetFilter = '';\r\nnSuppressConsol = pSuppressConsol;\r\nnChar = 1;\r\nnCharCount = LONG( sElementMapping );\r\n\r\n# If there's no element mapping then the process can be used to multiply existing value by a factor\r\nIf( nCharCount > 0 );\r\n\r\n sWord = '';\r\n sLastDelim = '';\r\n\r\n # Add a trailing element delimiter so that the last element is picked up\r\n If( nCharCount > 0 );\r\n sElementMapping = sElementMapping | sMappingDelimiter ;\r\n nCharCount = nCharCount + LONG(sMappingDelimiter );\r\n EndIf;\r\n\r\n WHILE (nChar <= nCharCount);\r\n sChar = SUBST( sElementMapping, nChar, 1);\r\n\r\n # Used for delimiters, required for multiple character delimiters\r\n sDelim = '';\r\n nAddExtra = 0;\r\n\r\n # Ignore spaces\r\n IF (TRIM(sChar) @<> '' );\r\n\r\n ### Dimension Name ###\r\n\r\n # If the delimiter is more than 1 character peek ahead the same amount\r\n # Ignore the first character\r\n sDelim = sChar;\r\n nCount = LONG(sElementStartDelim) - 1;\r\n If( nCount > 0 & nChar + nCount <= nCharCount );\r\n # Add the extra characters\r\n sDelim = sDelim | SUBST( sElementMapping, nChar + 1, nCount);\r\n # Move to the end of the delimter\r\n nAddExtra = nCount;\r\n EndIf;\r\n\r\n If( sDelim @= sElementStartDelim );\r\n\r\n sChar = sDelim;\r\n\r\n If( sLastDelim @<> '' & sLastDelim @<> sDelimDim );\r\n sMessage = Expand ( 'The name of a dimension must follow a dimension delimiter %sDelimDim%' );\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n EndIf;\r\n\r\n sDimension = sWord;\r\n\r\n If( DimensionExists( sDimension ) = 0 );\r\n # The dimension does not exist in the model. Cancel process\r\n sMessage = Expand( 'Dimension: %sDimension% does not exist');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n EndIf;\r\n\r\n # Check that the dimension is in the cube\r\n i = 1;\r\n iMax = 30;\r\n sDimInCube = 'No';\r\n While( i <= iMax );\r\n sDimensionOfCube = TabDim( pCube, i );\r\n If(sDimension @= sDimensionOfCube);\r\n sDimInCube = 'Yes';\r\n # record where the loop stops\r\n nIndex = i;\r\n i = 100;\r\n Else;\r\n i = i + 1;\r\n EndIf;\r\n End;\r\n\r\n If( sDimInCube @<> 'Yes' );\r\n # The dimension does not exist in the cube. Cancel process\r\n sMessage = Expand( 'Dimension %sDimension% does not exist in this cube');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n EndIf;\r\n\r\n ### Dimension exists so add it to the filters\r\n IF(LONG(sFilter) > 0 & sLastDelim @= '');\r\n sTargetFilter = sFilter | sDelimDim | sDimension | sElementStartDelim;\r\n sFilter = sFilter | sDelimDim | sDimension | sElementStartDelim;\r\n ElseiF(LONG(sFilter) > 0 & sLastDelim@<>'');\r\n sFilter = sFilter | sDelimDim | sDimension | sElementStartDelim;\r\n sTargetFilter = sTargetFilter | sDelimDim | sDimension | sElementStartDelim;\r\n Else;\r\n sFilter = sDimension | sElementStartDelim;\r\n sTargetFilter = sDimension | sElementStartDelim;\r\n EndIf;\r\n\r\n #Reset the source and target elements\r\n sSource = '';\r\n sTarget = '';\r\n\r\n # The variable nElementCount is used to keep track of how many elements there are per dimension\r\n # the first element is the source\r\n # the second element is the target\r\n # There shouldn't be any more than 2 elements per dimension\r\n\r\n # A new dimension has been found so reset the element count so\r\n # the code can tell how many elements have been specified for each dimension\r\n # There should just be 2\r\n\r\n nElementCount = 1;\r\n sLastDelim = sChar;\r\n\r\n # Clear the word\r\n sWord = '';\r\n\r\n Else;\r\n\r\n # Reset extra chars\r\n nAddExtra = 0;\r\n\r\n ### Check both dim delimiter and element delimiter ###\r\n nIsDelimiter = 0;\r\n\r\n # Check dim delim\r\n # If the delimiter is more than 1 character peek ahead the same amount\r\n # Ignore the first character\r\n sDelim = sChar;\r\n nCount = LONG(sDelimDim) - 1;\r\n If( nCount > 0 & nChar + nCount <= nCharCount );\r\n # Add the extra characters\r\n sDelim = sDelim | SUBST( sElementMapping, nChar + 1, nCount);\r\n # Move to the end of the delimter\r\n nAddExtra = nCount;\r\n EndIf;\r\n\r\n If( sDelim @= sDelimDim );\r\n nIsDelimiter = 1;\r\n sChar = sDelim;\r\n Else;\r\n # Reset extra chars\r\n nAddExtra = 0;\r\n\r\n ## Check element delimiter\r\n\r\n # If the delimiter is more than 1 character peek ahead the same amount\r\n # Ignore the first character\r\n sDelim = sChar;\r\n nCount = LONG(sMappingDelimiter) - 1;\r\n If( nCount > 0 & nChar + nCount <= nCharCount );\r\n # Add the extra characters\r\n sDelim = sDelim | SUBST( sElementMapping, nChar + 1, nCount);\r\n # Move to the end of the delimter\r\n nAddExtra = nCount;\r\n EndIf;\r\n\r\n If( sDelim @= sMappingDelimiter );\r\n nIsDelimiter = 1;\r\n sChar = sDelim;\r\n Else;\r\n # Reset extra chars\r\n nAddExtra = 0;\r\n EndIf;\r\n\r\n EndIf;\r\n\r\n If ( nIsDelimiter = 1 );\r\n\r\n If( sLastDelim @= '' % sLastDelim @= sDelimDim );\r\n sMessage = 'An element start delimiter must follow a dimension name: ' | sChar | ' (' | NumberToString(nChar) | ')';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n EndIf;\r\n\r\n # an element has been found!\r\n sElement = sWord;\r\n\r\n If( DIMIX( sDimension, sElement ) = 0 );\r\n # The element does not exist in the dimension. Cancel process\r\n sMessage = Expand( 'Element: %sElement% does not exist in dimension %sDimension%' );\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\n\r\n # Allow consolidations only if pSuppressConsol is not set to 1\r\n # Consolidations may be made allowable\r\n # so that you can copy strings between c levels\r\n # or copy from a consolidated source element to an n level target element\r\n\r\n ### Check for errors before continuing\r\n If( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n EndIf;\r\n\r\n If ( DTYPE( sDimension, sElement) @= 'C' );\r\n IF( nElementCount = 1 );\r\n If( pSuppressConsol <> 1 );\r\n nSuppressConsol = 0;\r\n EndIf;\r\n pSubN = 1;\r\n Else;\r\n sMessage = Expand( 'Target element: %sElement% for dimension %sDimension% is consolidated' );\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessBreak;\r\n Endif;\r\n Endif;\r\n\r\n # Add the element to the source or target depending on whether it's the first or the second element\r\n # Get principal name\r\n # in case source element and this element are using different aliases\r\n\r\n sElement = DimensionElementPrincipalName(sDimension,sElement);\r\n\r\n # first element\r\n IF(nElementCount = 1);\r\n\r\n sSource = sElement;\r\n sFilter = sFilter | sElement;\r\n\r\n # second element\r\n ElseIf(nElementCount = 2);\r\n\r\n sTarget = sElement;\r\n sTargetFilter = sTargetFilter | sElement;\r\n\r\n Else;\r\n\r\n sMessage = Expand( 'There should only be 2 elements per dimension: %sDimension% , a source and a target');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n\r\n EndIf;\r\n\r\n If(nIndex = 1);\r\n nMappedDim1 = 1;\r\n sSourceDim1 = sSource;\r\n sTargetDim1 = sTarget;\r\n ElseIf(nIndex = 2);\r\n nMappedDim2 = 1;\r\n sSourceDim2 = sSource;\r\n sTargetDim2 = sTarget;\r\n ElseIf(nIndex = 3);\r\n nMappedDim3 = 1;\r\n sSourceDim3 = sSource;\r\n sTargetDim3 = sTarget;\r\n ElseIf(nIndex = 4);\r\n nMappedDim4 = 1;\r\n sSourceDim4 = sSource;\r\n sTargetDim4 = sTarget;\r\n ElseIf(nIndex = 5);\r\n nMappedDim5 = 1;\r\n sSourceDim5 = sSource;\r\n sTargetDim5 = sTarget;\r\n ElseIf(nIndex = 6);\r\n nMappedDim6 = 1;\r\n sSourceDim6 = sSource;\r\n sTargetDim6 = sTarget;\r\n ElseIf(nIndex = 7);\r\n nMappedDim7 = 1;\r\n sSourceDim7 = sSource;\r\n sTargetDim7 = sTarget;\r\n ElseIf(nIndex = 8);\r\n nMappedDim8 = 1;\r\n sSourceDim8 = sSource;\r\n sTargetDim8 = sTarget;\r\n ElseIf(nIndex = 9);\r\n nMappedDim9 = 1;\r\n sSourceDim9 = sSource;\r\n sTargetDim9 = sTarget;\r\n ElseIf(nIndex = 10);\r\n nMappedDim10 = 1;\r\n sSourceDim10 = sSource;\r\n sTargetDim10 = sTarget;\r\n ElseIf(nIndex = 11);\r\n nMappedDim11 = 1;\r\n sSourceDim11 = sSource;\r\n sTargetDim11 = sTarget;\r\n ElseIf(nIndex = 12);\r\n nMappedDim12 = 1;\r\n sSourceDim12 = sSource;\r\n sTargetDim12 = sTarget;\r\n ElseIf(nIndex = 13);\r\n nMappedDim13 = 1;\r\n sSourceDim13 = sSource;\r\n sTargetDim13 = sTarget;\r\n ElseIf(nIndex = 14);\r\n nMappedDim14 = 1;\r\n sSourceDim14 = sSource;\r\n sTargetDim14 = sTarget;\r\n ElseIf(nIndex = 15);\r\n nMappedDim15 = 1;\r\n sSourceDim15 = sSource;\r\n sTargetDim15 = sTarget;\r\n ElseIf(nIndex = 16);\r\n nMappedDim16 = 1;\r\n sSourceDim16 = sSource;\r\n sTargetDim16 = sTarget;\r\n ElseIf(nIndex = 17);\r\n nMappedDim17 = 1;\r\n sSourceDim17 = sSource;\r\n sTargetDim17 = sTarget;\r\n ElseIf(nIndex = 18);\r\n nMappedDim18 = 1;\r\n sSourceDim18 = sSource;\r\n sTargetDim18 = sTarget;\r\n ElseIf(nIndex = 19);\r\n nMappedDim19 = 1;\r\n sSourceDim19 = sSource;\r\n sTargetDim19 = sTarget;\r\n ElseIf(nIndex = 20);\r\n nMappedDim20 = 1;\r\n sSourceDim20 = sSource;\r\n sTargetDim20 = sTarget;\r\n ElseIf(nIndex = 21);\r\n nMappedDim21 = 1;\r\n sSourceDim21 = sSource;\r\n sTargetDim21 = sTarget;\r\n ElseIf(nIndex = 22);\r\n nMappedDim22 = 1;\r\n sSourceDim22 = sSource;\r\n sTargetDim22 = sTarget;\r\n ElseIf(nIndex = 23);\r\n nMappedDim23 = 1;\r\n sSourceDim23 = sSource;\r\n sTargetDim23 = sTarget;\r\n ElseIf(nIndex = 24);\r\n nMappedDim24 = 1;\r\n sSourceDim24 = sSource;\r\n sTargetDim24 = sTarget;\r\n ElseIf(nIndex = 25);\r\n nMappedDim25 = 1;\r\n sSourceDim25 = sSource;\r\n sTargetDim25 = sTarget;\r\n ElseIf(nIndex = 26);\r\n nMappedDim26 = 1;\r\n sSourceDim26 = sSource;\r\n sTargetDim26 = sTarget;\r\n ElseIf(nIndex = 27);\r\n nMappedDim27 = 1;\r\n sSourceDim27 = sSource;\r\n sTargetDim27 = sTarget;\r\n EndIf;\r\n\r\n sLastDelim = sChar;\r\n\r\n # Clear the word\r\n sWord = '';\r\n\r\n nElementCount = nElementCount + 1;\r\n\r\n Else;\r\n sWord = sWord | sChar;\r\n EndIf;\r\n\r\n EndIf;\r\n\r\n EndIf;\r\n\r\n nChar = nChar + nAddExtra + 1;\r\n\r\n END;\r\nENDIF;\r\n\r\n\r\n### Check that there if a dimension is used, there is a source element and a target element\r\ncSourceVariableStem = 'sSourceDim';\r\ncTargetVariableStem = 'sTargetDim';\r\ncMappedDimVariableStem = 'nMappedDim';\r\n\r\nnCounter = 1;\r\nWHILE(nCounter <= nDimensionCount);\r\n\r\n sMappedDimVariable = 'nMappedDim ' | NumberToString(nCounter);\r\n sDimensionUsedPadded = Expand('%' | sMappedDimVariable | '%');\r\n\r\n nMappedDim = StringToNumber(Trim(sDimensionUsedPadded));\r\n If(nMappedDim = 1);\r\n sDim = TabDim( pCube, nCounter );\r\n sSourceVariable = cSourceVariableStem | NumberToString(nCounter);\r\n sSourcePadded = Expand('%' | sSourceVariable | '%');\r\n sSource = Trim(sSourcePadded);\r\n\r\n sTargetVariable = cTargetVariableStem | NumberToString(nCounter);\r\n sTargetPadded = Expand('%' | sTargetVariable | '%');\r\n sTarget = Trim(sTargetPadded);\r\n\r\n If(sSource @='' % sTarget @='');\r\n sMessage = 'Source and/or target element is blank for dimension ' | sDim;\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n EndIf;\r\n\r\n EndIf;\r\n\r\nnCounter = nCounter + 1;\r\n\r\nEND;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n DataSourceType = 'NULL';\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n# Branch depending on whether to do recursive calls to self on independent threads or run all in this thread\r\nIf( Scan( pEleStartDelim, pFilterParallel ) > 0 );\r\n sDimParallel = SubSt( pFilterParallel, 1, Scan( pEleStartDelim, pFilterParallel ) - 1 );\r\n sElementList = SubSt( pFilterParallel, Scan( pEleStartDelim, pFilterParallel ) + Long( pEleStartDelim ), Long( pFilterParallel ) );\r\n If( SubSt( sElementList, Long( sElementList ), 1 ) @<> pEleDelim );\r\n sElementList = sElementList | pEleDelim;\r\n EndIf;\r\n ## Counting elements in element list\r\n sElementListCount = sElementList;\r\n nElements = 0;\r\n While( Scan( pEleDelim, sElementListCount ) > 0 );\r\n nElements = nElements + 1;\r\n sElementListCount = SubSt( sElementListCount, Scan( pEleDelim, sElementListCount ) + Long( pEleDelim ), Long( sElementListCount ) );\r\n End;\r\n IF( Mod( nElements, nMaxThreads ) = 0 );\r\n nElemsPerThread = INT( nElements / nMaxThreads );\r\n ELSE;\r\n nElemsPerThread = INT( nElements / nMaxThreads ) + 1;\r\n ENDIF;\r\n nThreadElCounter = 0;\r\n nThreads = 0;\r\n While( Scan( pEleDelim, sElementList ) > 0 );\r\n sSlicerEle = SubSt( sElementList, 1, Scan( pEleDelim, sElementList ) - 1 );\r\n sElementList = SubSt( sElementList, Scan( pEleDelim, sElementList ) + Long( pEleDelim ), Long( sElementList ) );\r\n # Do recursive process call with new RunProcess function\r\n nThreadElCounter = nThreadElCounter + 1;\r\n sDimDelim = If(pFilter @= '', '', pDimDelim );\r\n IF( nThreadElCounter = 1 );\r\n sFilter = Expand('%pFilter%%sDimDelim%%sDimParallel%%pEleStartDelim%%sSlicerEle%');\r\n ELSE;\r\n sFilter = Expand('%sFilter%%pEleDelim%%sSlicerEle%');\r\n ENDIF;\r\n IF( nThreadElCounter >= nElemsPerThread );\r\n nThreadID = INT( RAND( ) * 10000 + 1) + Numbr(cTimeStamp);\r\n sThreadControlFile = LOWER( GetProcessName() | '_ThreadControlFile_' | cRandomInt | '_' | NumberToString(nThreadID) | '_' | cTimeStamp );\r\n AsciiOutput( cDir | sThreadControlFile | '.txt', '' );\r\n LogOutput( 'INFO', 'Executing subTI with Thread ID: ' | NumberToString(nThreadID) );\r\n RunProcess( cThisProcName, 'pLogoutput', pLogoutput,\r\n \t'pCube', pCube, 'pSrcView', pSrcView, 'pTgtView', pTgtView,\r\n \t'pFilter', sFilter, 'pFilterParallel', '', 'pEleMapping', pEleMapping, 'pMappingDelim', pMappingDelim,\r\n \t'pDimDelim', pDimDelim, 'pEleStartDelim', pEleStartDelim, 'pEleDelim', pEleDelim,\r\n \t'pFactor', pFactor, 'pSuppressConsol', pSuppressConsol, 'pSuppressConsolStrings', pSuppressConsolStrings, 'pSuppressRules', pSuppressRules, 'pSuppressZero', pSuppressZero, 'pCumulate', pCumulate,\r\n \t'pZeroTarget', pZeroTarget, 'pZeroSource', pZeroSource, 'pTemp', pTemp, 'pCubeLogging', pCubeLogging, 'pSandbox', pSandbox, 'pFile', pFile, 'pDecimalSeparator', pDecimalSeparator, 'pThousandSeparator', pThousandSeparator,\r\n 'pThreadMode', 1, 'pThreadControlFile', sThreadControlFile\r\n );\r\n \t nThreadElCounter = 0;\r\n \t sFilter = '';\r\n \t nThreads = nThreads + 1;\r\n \tENDIF;\r\n End;\r\n ## Process last elements - only when filter is not empty (there are still elements)\r\n IF( sFilter @<> '' );\r\n RunProcess( cThisProcName, 'pLogoutput', pLogoutput,\r\n \t'pCube', pCube, 'pSrcView', pSrcView, 'pTgtView', pTgtView,\r\n \t'pFilter', sFilter, 'pFilterParallel', '', 'pEleMapping', pEleMapping, 'pMappingDelim', pMappingDelim,\r\n \t'pDimDelim', pDimDelim, 'pEleStartDelim', pEleStartDelim, 'pEleDelim', pEleDelim,\r\n \t'pFactor', pFactor, 'pSuppressConsol', pSuppressConsol, 'pSuppressConsolStrings', pSuppressConsolStrings, 'pSuppressRules', pSuppressRules, 'pSuppressZero', pSuppressZero, 'pCumulate', pCumulate,\r\n \t'pZeroTarget', pZeroTarget, 'pZeroSource', pZeroSource, 'pTemp', pTemp, 'pCubeLogging', pCubeLogging, 'pSandbox', pSandbox, 'pFile', pFile, 'pDecimalSeparator', pDecimalSeparator, 'pThousandSeparator', pThousandSeparator,\r\n 'pThreadMode', 1, 'pThreadControlFile', sThreadControlFile\r\n );\r\n ENDIF;\r\n DataSourceType = 'NULL';\r\n Sleep( 1000 );\r\nElse;\r\n ### Create View of target to zero out\r\n ### Check that there's something in sTargetFilter so the cube doesn't accidentally get wiped out\r\n IF( pThreadControlFile @<> '' );\r\n LogOutput( 'info', 'creating thread file ' | cDir | pThreadControlFile | '.txt' );\r\n AsciiOutput( cDir | pThreadControlFile | '.txt', '' );\r\n ENDIF;\r\n If(pZeroTarget = 1 & LONG(sTargetFilter)> 0);\r\n\r\n sProc = '}bedrock.cube.data.clear';\r\n nRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCube,\r\n 'pView', cViewTarget,\r\n 'pFilter', sTargetFilter,\r\n 'pDimDelim', pDimDelim,\r\n 'pEleStartDelim', pEleStartDelim,\r\n 'pEleDelim', pEleDelim,\r\n 'pCubeLogging', pCubeLogging,\r\n 'pTemp', pTemp,\r\n 'pSandbox', pSandbox\r\n );\r\n\r\n IF(nRet <> 0);\r\n sMessage = 'Error clearing the target view.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n\r\n Endif;\r\n\r\n If( pFile = 0 );\r\n\r\n ### Create View of Source ###\r\n\r\n nRet = ExecuteProcess('}bedrock.cube.view.create',\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCube,\r\n 'pView', cViewSource,\r\n 'pFilter', sFilter,\r\n 'pSuppressZero', pSuppressZero,\r\n 'pSuppressConsol', nSuppressConsol,\r\n 'pSuppressRules', pSuppressRules,\r\n 'pSuppressConsolStrings', pSuppressConsolStrings,\r\n 'pIncludeDescendants',pIncludeDescendants,\r\n 'pDimDelim', pDimDelim,\r\n 'pEleStartDelim', pEleStartDelim,\r\n 'pEleDelim', pEleDelim ,\r\n 'pTemp', pTemp,\r\n 'pSubN', pSubN\r\n );\r\n\r\n IF(nRet <> 0);\r\n sMessage = 'Error creating the view from the filter.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n\r\n\r\n ### Assign Datasource ###\r\n DataSourceType = 'VIEW';\r\n DatasourceNameForServer = pCube;\r\n DatasourceNameForClient = pCube;\r\n DatasourceCubeView = cViewSource;\r\n nThreadMode = 1;\r\n Else;\r\n ### Export Data to file ###\r\n\r\n nRet = ExecuteProcess('}bedrock.cube.data.export',\r\n 'pLogoutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCube,\r\n 'pView', cViewSource,\r\n 'pFilter', sFilter,\r\n 'pFilterParallel', '',\r\n 'pParallelThreads', 0,\r\n 'pDimDelim', pDimDelim,\r\n 'pEleStartDelim', pEleStartDelim,\r\n 'pEleDelim', pEleDelim,\r\n 'pSuppressZero', pSuppressZero,\r\n 'pSuppressConsol', nSuppressConsol,\r\n 'pSuppressRules', pSuppressRules,\r\n 'pSuppressConsolStrings', pSuppressConsolStrings,\r\n 'pIncludeDescendants',pIncludeDescendants,\r\n 'pZeroSource', 0,\r\n 'pCubeLogging', pCubeLogging,\r\n 'pTemp', pTemp,\r\n 'pFilePath', cDir,\r\n 'pFileName', cFileName,\r\n 'pDelim', cDelimiter,\r\n 'pDecimalSeparator', sDecimalSeparator,\r\n 'pThousandSeparator', sThousandSeparator,\r\n 'pQuote', cQuote,\r\n 'pTitleRecord', cTitleRows,\r\n 'pSandbox', pSandbox\r\n );\r\n\r\n IF(nRet <> 0);\r\n sMessage = 'Error exporting data to file.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n\r\n If(FileExists(cFile) = 0);\r\n # If the file does not exist, it means that nothing got exported, so there is nothing to import\r\n If( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( 'Process:%cThisProcName% is skipping import as export file %cFile% was not found.' ) );\r\n EndIf;\r\n DataSourceType = 'NULL';\r\n Else;\r\n ### Assign Datasource ###\r\n DataSourceType = 'CHARACTERDELIMITED';\r\n DatasourceNameForServer = cFile;\r\n DatasourceNameForClient = cFile;\r\n DatasourceASCIIHeaderRecords = cTitleRows;\r\n DatasourceASCIIDelimiter = cDelimiter;\r\n DatasourceASCIIQuoteCharacter = cQuote;\r\n EndIf;\r\n\r\n nThreadMode = 1;\r\n\r\n EndIf;\r\n\r\nEndIf;\r\n\r\n### End Prolog ###\r\n", "MetadataProcedure": "#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "DataProcedure": "#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n\r\n#################################################################################################\r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n#################################################################################################\r\n\r\nIf( pFile > 0 );\r\n v0 = v1; v1 = v2; v2 = v3; v3 = v4; v4 = v5; v5 = v6; v6 = v7; v7 = v8; v8 = v9; v9 = v10; v10 = v11; v11 = v12; v12 = v13; v13 = v14; v14 = v15;\r\n v15 = v16; v16 = v17; v17 = v18; v18 = v19; v19 = v20; v20 = v21; v21 = v22; v22 = v23; v23 = v24; v24 = v25; v25 = v26; v26 = v27; v27 = v28; v28 = v29;\r\nEndIf;\r\n\r\nv1 = IF(nMappedDim1 = 1, IF(v1 @= sSourceDim1 % elisanc(sDim1,sSourceDim1,v1)=1, sTargetDim1, v1), v1);\r\nv2 = IF(nMappedDim2 = 1, IF(v2 @= sSourceDim2 % elisanc(sDim2,sSourceDim2,v2)=1, sTargetDim2, v2), v2);\r\nv3 = IF(nMappedDim3 = 1, IF(v3 @= sSourceDim3 % elisanc(sDim3,sSourceDim3,v3)=1, sTargetDim3, v3), v3);\r\nv4 = IF(nMappedDim4 = 1, IF(v4 @= sSourceDim4 % elisanc(sDim4,sSourceDim4,v4)=1, sTargetDim4, v4), v4);\r\nv5 = IF(nMappedDim5 = 1, IF(v5 @= sSourceDim5 % elisanc(sDim5,sSourceDim5,v5)=1, sTargetDim5, v5), v5);\r\nv6 = IF(nMappedDim6 = 1, IF(v6 @= sSourceDim6 % elisanc(sDim6,sSourceDim6,v6)=1, sTargetDim6, v6), v6);\r\nv7 = IF(nMappedDim7 = 1, IF(v7 @= sSourceDim7 % elisanc(sDim7,sSourceDim7,v7)=1, sTargetDim7, v7), v7);\r\nv8 = IF(nMappedDim8 = 1, IF(v8 @= sSourceDim8 % elisanc(sDim8,sSourceDim8,v8)=1, sTargetDim8, v8), v8);\r\nv9 = IF(nMappedDim9 = 1, IF(v9 @= sSourceDim9 % elisanc(sDim9,sSourceDim9,v9)=1, sTargetDim9, v9), v9);\r\nv10 = IF(nMappedDim10 = 1, IF(v10 @= sSourceDim10 % elisanc(sDim10,sSourceDim10,v10)=1, sTargetDim10, v10), v10);\r\nv11 = IF(nMappedDim11 = 1, IF(v11 @= sSourceDim11 % elisanc(sDim11,sSourceDim11,v11)=1, sTargetDim11, v11), v11);\r\nv12 = IF(nMappedDim12 = 1, IF(v12 @= sSourceDim12 % elisanc(sDim12,sSourceDim12,v12)=1, sTargetDim12, v12), v12);\r\nv13 = IF(nMappedDim13 = 1, IF(v13 @= sSourceDim13 % elisanc(sDim13,sSourceDim13,v13)=1, sTargetDim13, v13), v13);\r\nv14 = IF(nMappedDim14 = 1, IF(v14 @= sSourceDim14 % elisanc(sDim14,sSourceDim14,v14)=1, sTargetDim14, v14), v14);\r\nv15 = IF(nMappedDim15 = 1, IF(v15 @= sSourceDim15 % elisanc(sDim15,sSourceDim15,v15)=1, sTargetDim15, v15), v15);\r\nv16 = IF(nMappedDim16 = 1, IF(v16 @= sSourceDim16 % elisanc(sDim16,sSourceDim16,v16)=1, sTargetDim16, v16), v16);\r\nv17 = IF(nMappedDim17 = 1, IF(v17 @= sSourceDim17 % elisanc(sDim17,sSourceDim17,v17)=1, sTargetDim17, v17), v17);\r\nv18 = IF(nMappedDim18 = 1, IF(v18 @= sSourceDim18 % elisanc(sDim18,sSourceDim18,v18)=1, sTargetDim18, v18), v18);\r\nv19 = IF(nMappedDim19 = 1, IF(v19 @= sSourceDim19 % elisanc(sDim19,sSourceDim19,v19)=1, sTargetDim19, v19), v19);\r\nv20 = IF(nMappedDim20 = 1, IF(v20 @= sSourceDim20 % elisanc(sDim20,sSourceDim20,v20)=1, sTargetDim20, v20), v20);\r\nv21 = IF(nMappedDim21 = 1, IF(v21 @= sSourceDim21 % elisanc(sDim21,sSourceDim21,v21)=1, sTargetDim21, v21), v21);\r\nv22 = IF(nMappedDim22 = 1, IF(v22 @= sSourceDim22 % elisanc(sDim22,sSourceDim22,v22)=1, sTargetDim22, v22), v22);\r\nv23 = IF(nMappedDim23 = 1, IF(v23 @= sSourceDim23 % elisanc(sDim23,sSourceDim23,v23)=1, sTargetDim23, v23), v23);\r\nv24 = IF(nMappedDim24 = 1, IF(v24 @= sSourceDim24 % elisanc(sDim23,sSourceDim24,v24)=1, sTargetDim24, v24), v24);\r\nv25 = IF(nMappedDim25 = 1, IF(v25 @= sSourceDim25 % elisanc(sDim25,sSourceDim25,v25)=1, sTargetDim25, v25), v25);\r\nv26 = IF(nMappedDim26 = 1, IF(v26 @= sSourceDim26 % elisanc(sDim26,sSourceDim26,v26)=1, sTargetDim26, v26), v26);\r\nv27 = IF(nMappedDim27 = 1, IF(v27 @= sSourceDim27 % elisanc(sDim27,sSourceDim27,v27)=1, sTargetDim27, v27), v27);\r\n\r\n\r\n### Write data from source version to target version ###\r\n\r\n# Selects the correct CellPut formula depending upon the number of dimensions in the cube\r\n# and whether the value is numeric or string ( max 27 dims catered for in this code )\r\n# value type determined by element type of last dimension in cube\r\n# could have used Value_is_String = 1 and NValue/SValue but this works just as well\r\n\r\n\r\nIf( nDimensionCount = 2 );\r\n If( CellIsUpdateable( pCube, v1, v2 ) = 1 );\r\n sElType = DType( sDim2, v2 );\r\n IF( SubSt( pCube, 1, 17 ) @= '}ElementSecurity_');\r\n v3 = IF( v3 @= '', 'NONE', v3 );\r\n ElementSecurityPut( v3, sDim1, v1, v2 );\r\n ELSEIF( sElType @= 'AA' );\r\n AttrPutS( v3, sDim1, v1, v2, 1 );\r\n ELSEIF( sElType @= 'AS' );\r\n AttrPutS( v3, sDim1, v1, v2 );\r\n ELSEIF( sElType @= 'AN' );\r\n AttrPutN( StringToNumberEx( v3, sDecimalSeparator, sThousandSeparator ) * nFactor, sDim1, v1, v2 );\r\n ElseIf( sElType @= 'S' );\r\n CellPutS( v3, pCube, v1, v2 );\r\n Else;\r\n IF( pCumulate = 1);\r\n nObal = CellGetN( pCube, v1, v2 );\r\n nCbal = nObal + StringToNumberEx( v3, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n ELSE;\r\n nCbal = StringToNumberEx( v3, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n Endif;\r\n CellPutN( nCbal, pCube, v1, v2 );\r\n EndIf;\r\n EndIf;\r\nElseIf( nDimensionCount = 3 );\r\n If( CellIsUpdateable( pCube, v1, v2, v3 ) = 1 );\r\n sElType = DType( sDim3, v3 );\r\n If( sElType @<> 'S' );\r\n IF( pCumulate = 1);\r\n nObal = CellGetN( pCube, v1, v2, v3 );\r\n nCbal = nObal + StringToNumberEx( v4, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n ELSE;\r\n nCbal = StringToNumberEx( v4, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n Endif;\r\n CellPutN( nCbal, pCube, v1, v2, v3 );\r\n Else;\r\n CellPutS( v4, pCube, v1, v2, v3 );\r\n EndIf;\r\n EndIf;\r\nElseIf( nDimensionCount = 4 );\r\n If( CellIsUpdateable( pCube, v1, v2, v3, v4 ) = 1 );\r\n sElType = DType( sDim4, v4 );\r\n If( sElType @<> 'S' );\r\n IF( pCumulate = 1);\r\n nObal = CellGetN( pCube, v1, v2, v3, v4);\r\n nCbal = nObal + StringToNumberEx( v5, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n ELSE;\r\n nCbal = StringToNumberEx( v5, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n Endif;\r\n CellPutN( nCbal, pCube, v1, v2, v3, v4);\r\n Else;\r\n CellPutS( v5, pCube, v1, v2, v3, v4);\r\n EndIf;\r\n EndIf;\r\nElseIf( nDimensionCount = 5 );\r\n If( CellIsUpdateable( pCube, v1, v2, v3, v4, v5 ) = 1 );\r\n sElType = DType( sDim5, v5 );\r\n If( sElType @<> 'S' );\r\n IF(pCumulate = 1);\r\n nObal = CellGetN( pCube, v1, v2, v3, v4, v5 );\r\n nCbal = nObal + StringToNumberEx( v6, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n ELSE;\r\n nCbal = StringToNumberEx( v6, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n Endif;\r\n CellPutN( nCbal, pCube, v1, v2, v3, v4, v5 );\r\n Else;\r\n CellPutS( v6, pCube, v1, v2, v3, v4, v5 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 6 );\r\n If( CellIsUpdateable( pCube, v1, v2, v3, v4, v5, v6 ) = 1 );\r\n sElType = DType( sDim6, v6 );\r\n If( sElType @<> 'S' );\r\n IF( pCumulate = 1);\r\n nObal = CellGetN( pCube, v1, v2, v3, v4, v5, v6 );\r\n nCbal = nObal + StringToNumberEx( v7, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n ELSE;\r\n nCbal = StringToNumberEx( v7, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n Endif;\r\n CellPutN( nCbal, pCube, v1, v2, v3, v4, v5, v6 );\r\n Else;\r\n CellPutS( v7, pCube, v1, v2, v3, v4, v5, v6 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 7 );\r\n If( CellIsUpdateable( pCube, v1, v2, v3, v4, v5, v6, v7 ) = 1 );\r\n sElType = DType( sDim7, v7 );\r\n If( sElType @<> 'S' );\r\n IF( pCumulate = 1);\r\n nObal = CellGetN( pCube, v1, v2, v3, v4, v5, v6, v7 );\r\n nCbal = nObal + StringToNumberEx( v8, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n ELSE;\r\n nCbal = StringToNumberEx( v8, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n Endif;\r\n CellPutN( nCbal, pCube, v1, v2, v3, v4, v5, v6, v7 );\r\n Else;\r\n CellPutS( v8, pCube, v1, v2, v3, v4, v5, v6, v7 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 8 );\r\n If( CellIsUpdateable( pCube, v1, v2, v3, v4, v5, v6, v7, v8 ) = 1 );\r\n sElType = DType( sDim8, v8 );\r\n If( sElType @<> 'S' );\r\n IF( pCumulate = 1);\r\n nObal = CellGetN( pCube, v1, v2, v3, v4, v5, v6, v7, v8 );\r\n nCbal = nObal + StringToNumberEx( v9, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n ELSE;\r\n nCbal = StringToNumberEx( v9, sDecimalSeparator, sThousandSeparator )* nFactor;\r\n Endif;\r\n CellPutN( nCbal, pCube, v1, v2, v3, v4, v5, v6, v7, v8 );\r\n Else;\r\n CellPutS( v9, pCube, v1, v2, v3, v4, v5, v6, v7, v8 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 9 );\r\n If( CellIsUpdateable( pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9 ) = 1 );\r\n sElType = DType( sDim9, v9 );\r\n If( sElType @<> 'S' );\r\n IF( pCumulate = 1);\r\n nObal = CellGetN( pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9 );\r\n nCbal = nObal + StringToNumberEx( v10, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n ELSE;\r\n nCbal = StringToNumberEx( v10, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n Endif;\r\n CellPutN( nCbal, pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9 );\r\n Else;\r\n CellPutS( v10, pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 10 );\r\n If( CellIsUpdateable( pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10 ) = 1 );\r\n sElType = DType( sDim10, v10 );\r\n If( sElType @<> 'S' );\r\n IF( pCumulate = 1);\r\n nObal = CellGetN( pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10 );\r\n nCbal = nObal + StringToNumberEx( v11, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n ELSE;\r\n nCbal = StringToNumberEx( v11, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n Endif;\r\n CellPutN( nCbal, pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10 );\r\n Else;\r\n CellPutS( v11, pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 11 );\r\n If( CellIsUpdateable( pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11 ) = 1 );\r\n sElType = DType( sDim11, v11 );\r\n If( sElType @<> 'S' );\r\n IF( pCumulate = 1);\r\n nObal = CellGetN( pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11 );\r\n nCbal = nObal + StringToNumberEx( v12, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n ELSE;\r\n nCbal = StringToNumberEx( v12, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n Endif;\r\n CellPutN( nCbal, pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11 );\r\n Else;\r\n CellPutS( v12, pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 12 );\r\n If( CellIsUpdateable( pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12 ) = 1 );\r\n sElType = DType( sDim12, v12 );\r\n If( sElType @<> 'S' );\r\n IF( pCumulate = 1);\r\n nObal = CellGetN( pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12 );\r\n nCbal = nObal + StringToNumberEx( v13, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n ELSE;\r\n nCbal = StringToNumberEx( v13, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n Endif;\r\n CellPutN( nCbal, pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12 );\r\n Else;\r\n CellPutS( v13, pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 13 );\r\n If( CellIsUpdateable( pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13 ) = 1 );\r\n sElType = DType( sDim13, v13 );\r\n If( sElType @<> 'S' );\r\n IF( pCumulate = 1);\r\n nObal = CellGetN( pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13 );\r\n nCbal = nObal + StringToNumberEx( v14, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n ELSE;\r\n nCbal = StringToNumberEx( v14, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n Endif;\r\n CellPutN( nCbal, pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13 );\r\n Else;\r\n CellPutS( v14, pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 14 );\r\n If( CellIsUpdateable( pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14 ) = 1 );\r\n sElType = DType( sDim14, v14 );\r\n If( sElType @<> 'S' );\r\n IF( pCumulate = 1);\r\n nObal = CellGetN( pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14 );\r\n nCbal = nObal + StringToNumberEx( v15, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n ELSE;\r\n nCbal = StringToNumberEx( v15, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n Endif;\r\n CellPutN( nCbal, pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14 );\r\n Else;\r\n CellPutS( v15, pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 15 );\r\n If( CellIsUpdateable( pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15 ) = 1 );\r\n sElType = DType( sDim15, v15 );\r\n If( sElType @<> 'S' );\r\n IF( pCumulate = 1);\r\n nObal = CellGetN( pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15 );\r\n nCbal = nObal + StringToNumberEx( v16, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n ELSE;\r\n nCbal = StringToNumberEx( v16, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n Endif;\r\n CellPutN( nCbal, pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15 );\r\n Else;\r\n CellPutS( v16, pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 16 );\r\n If( CellIsUpdateable( pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16 ) = 1 );\r\n sElType = DType( sDim16, v16 );\r\n If( sElType @<> 'S' );\r\n IF( pCumulate = 1);\r\n nObal = CellGetN( pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16 );\r\n nCbal = nObal + StringToNumberEx( v17, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n ELSE;\r\n nCbal = StringToNumberEx( v17, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n Endif;\r\n CellPutN( nCbal, pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16 );\r\n Else;\r\n CellPutS( v17, pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 17 );\r\n If( CellIsUpdateable( pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17 ) = 1 );\r\n sElType = DType( sDim17, v17 );\r\n If( sElType @<> 'S' );\r\n IF( pCumulate = 1);\r\n nObal = CellGetN( pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17 );\r\n nCbal = nObal + StringToNumberEx( v18, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n ELSE;\r\n nCbal = StringToNumberEx( v18, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n Endif;\r\n CellPutN( nCbal, pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17 );\r\n Else;\r\n CellPutS( v18, pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 18 );\r\n If( CellIsUpdateable( pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18 ) = 1 );\r\n sElType = DType( sDim18, v18 );\r\n If( sElType @<> 'S' );\r\n IF( pCumulate = 1);\r\n nObal = CellGetN( pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18 );\r\n nCbal = nObal + StringToNumberEx( v19, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n ELSE;\r\n nCbal = StringToNumberEx( v19, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n Endif;\r\n CellPutN( nCbal, pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18 );\r\n Else;\r\n CellPutS( v19, pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 19 );\r\n If( CellIsUpdateable( pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19 ) = 1 );\r\n sElType = DType( sDim19, v19 );\r\n If( sElType @<> 'S' );\r\n IF( pCumulate = 1);\r\n nObal = CellGetN( pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19 );\r\n nCbal = nObal + StringToNumberEx( v20, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n ELSE;\r\n nCbal = StringToNumberEx( v20, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n Endif;\r\n CellPutN( nCbal, pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19 );\r\n Else;\r\n CellPutS( v20, pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 20 );\r\n If( CellIsUpdateable( pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20 ) = 1 );\r\n sElType = DType( sDim20, v20 );\r\n If( sElType @<> 'S' );\r\n IF( pCumulate = 1);\r\n nObal = CellGetN( pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20 );\r\n nCbal = nObal + StringToNumberEx( v21, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n ELSE;\r\n nCbal = StringToNumberEx( v21, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n Endif;\r\n CellPutN( nCbal, pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20 );\r\n Else;\r\n CellPutS( v21, pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 21 );\r\n If( CellIsUpdateable( pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21 ) = 1 );\r\n sElType = DType( sDim21, v21 );\r\n If( sElType @<> 'S' );\r\n IF( pCumulate = 1);\r\n nObal = CellGetN( pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21 );\r\n nCbal = nObal + StringToNumberEx( v22, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n ELSE;\r\n nCbal = StringToNumberEx( v22, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n Endif;\r\n CellPutN( nCbal, pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21 );\r\n Else;\r\n CellPutS( v22, pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 22 );\r\n If( CellIsUpdateable( pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22 ) = 1 );\r\n sElType = DType( sDim22, v22 );\r\n If( sElType @<> 'S' );\r\n IF( pCumulate = 1);\r\n nObal = CellGetN( pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22 );\r\n nCbal = nObal + StringToNumberEx( v23, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n ELSE;\r\n nCbal = StringToNumberEx( v23, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n Endif;\r\n CellPutN( nCbal, pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22 );\r\n Else;\r\n CellPutS( v23, pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 23 );\r\n If( CellIsUpdateable( pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21,\r\n v22, v23 ) = 1 );\r\n sElType = DType( sDim23, v23 );\r\n If( sElType @<> 'S' );\r\n IF( pCumulate >= 1);\r\n nObal = CellGetN( pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23 );\r\n nCbal = nObal + StringToNumberEx( v24, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n ELSE;\r\n nCbal = StringToNumberEx( v24, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n Endif;\r\n CellPutN( nCbal, pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23 );\r\n Else;\r\n CellPutS( v24, pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 24 );\r\n If( CellIsUpdateable( pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24 ) = 1 );\r\n sElType = DType( sDim24, v24 );\r\n If( sElType @<> 'S' );\r\n IF( pCumulate = 1);\r\n nObal = CellGetN( pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24 );\r\n nCbal = nObal + StringToNumberEx( v25, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n ELSE;\r\n nCbal = StringToNumberEx( v25, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n Endif;\r\n CellPutN( nCbal, pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24 );\r\n Else;\r\n CellPutS( v25, pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 25 );\r\n If( CellIsUpdateable( pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25 ) = 1 );\r\n sElType = DType( sDim25, v25 );\r\n If( sElType @<> 'S' );\r\n IF( pCumulate = 1);\r\n nObal = CellGetN( pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25 );\r\n nCbal = nObal + StringToNumberEx( v26, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n ELSE;\r\n nCbal = StringToNumberEx( v26, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n Endif;\r\n CellPutN( nCbal, pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25 );\r\n Else;\r\n CellPutS( v26, pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25 );\r\n EndIf;\r\n EndIf;\r\nElseIf( nDimensionCount = 26 );\r\n If( CellIsUpdateable( pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21,\r\n v22, v23, v24, v25, v26 ) = 1 );\r\n sElType = DType( sDim26, v26 );\r\n If( sElType @<> 'S' );\r\n IF( pCumulate = 1);\r\n nObal = CellGetN( pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26 );\r\n nCbal = nObal + StringToNumberEx( v27, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n ELSE;\r\n nCbal = StringToNumberEx( v27, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n Endif;\r\n CellPutN( nCbal, pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26 );\r\n Else;\r\n CellPutS( v27, pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26 );\r\n EndIf;\r\n EndIf;\r\nElseIf( nDimensionCount = 27 );\r\n If( CellIsUpdateable( pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27 ) = 1 );\r\n sElType = DType( sDim27, v27 );\r\n If( sElType @<> 'S' );\r\n IF( pCumulate >= 1);\r\n nObal = CellGetN( pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27 );\r\n nCbal = nObal + StringToNumberEx( v28, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n ELSE;\r\n nCbal = StringToNumberEx( v28, sDecimalSeparator, sThousandSeparator ) * nFactor;\r\n Endif;\r\n CellPutN( nCbal, pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27 );\r\n Else;\r\n CellPutS( v28, pCube, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27 );\r\n EndIf;\r\n EndIf;\r\n\r\n EndIf;\r\n\r\n\r\n### End Data ###", "EpilogProcedure": "#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n\r\n#################################################################################################\r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n#################################################################################################\r\n\r\n# Zero out source cube #\r\nIF( pZeroSource = 1 & nErrors = 0 );\r\n sProc = '}bedrock.cube.data.clear';\r\n nRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCube,\r\n 'pView', cViewSource,\r\n 'pFilter', sFilter,\r\n 'pDimDelim', pDimDelim,\r\n 'pEleStartDelim', pEleStartDelim,\r\n 'pEleDelim', pEleDelim,\r\n 'pTemp', pTemp,\r\n 'pCubeLogging', pCubeLogging,\r\n 'pSandbox', pSandbox\r\n );\r\n If(nRet <> 0);\r\n sMessage = 'Error clearing the source view.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n ProcessError();\r\n EndIf;\r\nEndIf;\r\n\r\n### Delete export file if used\r\nIf( pFile = 1 );\r\n# ASCIIDelete( cFile );\r\nEndIf;\r\n\r\n### Delete thread control file if used\r\nIF( pThreadControlFile @<> '' );\r\n LogOutput( 'INFO', 'Removing thread control file: ' | cDir | pThreadControlFile | '.txt' );\r\n ASCIIDelete( cDir | pThreadControlFile | '.txt' );\r\nENDIF;\r\n\r\n### Wait for all parallel threads to finish if using pFilterParallel\r\nIf( pFilterParallel @<> '' );\r\n sThreadFilePattern = LOWER( GetProcessName() | '_ThreadControlFile_' | cRandomInt | '_' | '*.txt' );\r\n LogOutput( 'INFO', 'Checking for: ' | sThreadFilePattern );\r\n i = 1;\r\n While( i < pMaxWaitSeconds );\r\n sThreadCheck = WildcardFileSearch( cDir | sThreadFilePattern, '' );\r\n If( sThreadCheck @<> '' );\r\n Sleep( 1000 );\r\n Else;\r\n Break;\r\n EndIf;\r\n\r\n i = i + 1;\r\n End;\r\nEndIf;\r\n\r\n### Return code & final error message handling\r\nIf( nErrors > 0 );\r\n sMessage = 'the process incurred at least 1 error. Please see above lines in this file for more details.';\r\n nProcessReturnCode = 0;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% Process:%cThisProcName% completed with errors. Check tm1server.log for details.' );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n EndIf;\r\nElse;\r\n sProcessAction = Expand( 'Process:%cThisProcName% successfully copied data from %pSrcView% view to the %pTgtView% view in the %pCube% cube.' );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% %sProcessAction%' );\r\n nProcessReturnCode = 1;\r\n If( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( sProcessAction ) ); \r\n EndIf;\r\nEndIf;\r\n\r\n### End Epilog ###", "HasSecurityAccess": true, - "UIData": "_ParameterConstraints=e30=\f", + "UIData": "", "DataSource": { "Type": "TM1CubeView", "dataSourceNameForClient": "zzSYS 50 Dim Cube", @@ -13,21 +13,9 @@ "view": "Temp" }, "Parameters": [ - { - "Name": "pLogOutput", - "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, - { - "Name": "pStrictErrorHandling", - "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, { "Name": "pCube", - "Prompt": "REQUIRED: Cube", + "Prompt": "REQUIRED: Cube name", "Value": "", "Type": "String" }, @@ -45,115 +33,115 @@ }, { "Name": "pFilter", - "Prompt": "OPTIONAL: Filter Unmapped Dimensions using format: Year\u00a6 2006 + 2007 & Scenario\u00a6 Actual + Budget etc", + "Prompt": "OPTIONAL: Filter on cube in format: 'dim_one\u00a6 el_one + el_two & dim_two\u00a6 el_one + el_two'", "Value": "", "Type": "String" }, { "Name": "pFilterParallel", - "Prompt": "OPTIONAL: Parallelization Filter: Month:Q1+Q2+Q3+Q4 (Blank=run single threaded). Single dimension parallel slices. Will be added to filter single element at a time. Dimension must not be part of filter", + "Prompt": "OPTIONAL: Parallelization filter in format: dim_one\u00a6 el_one + el_two. Dimension must not be part of filter", "Value": "", "Type": "String" }, { "Name": "pParallelThreads", - "Prompt": "Maximum number of threads to run when parallel processing is enabled ( if <2 will execute one thread, but parallel filter is still applied )", + "Prompt": "OPTIONAL: Maximum number of threads to run when parallel processing is enabled (Default = 0)", "Value": 0, "Type": "Numeric" }, { "Name": "pEleMapping", - "Prompt": "REQUIRED: Map source elements to target elements using format Dim1ToCopy\u00a6SourceElement->TargetElement & Dim2ToCopy\u00a6Source Element->TargetElement etc", + "Prompt": "REQUIRED: Map source elements to target elements using format: dim_one\u00a6 el_one -> el_two & dim_two\u00a6 el_one -> el_two'", "Value": "", "Type": "String" }, { "Name": "pMappingDelim", - "Prompt": "OPTIONAL: Delimiter between source element and target element in pEleMapping (default value if blank = '->')", + "Prompt": "OPTIONAL: Delimiter between source element and target element in pEleMapping (Default = '->')", "Value": "->", "Type": "String" }, { "Name": "pDimDelim", - "Prompt": "OPTIONAL: Delimiter for start of Dimension/Element set (default value if blank = '&')", + "Prompt": "OPTIONAL: Delimiter for start of dimension/element set in filter parameters (Default = '&')", "Value": "&", "Type": "String" }, { "Name": "pEleStartDelim", - "Prompt": "OPTIONAL: Delimiter for start of element list (default value if blank = '\u00a6')", + "Prompt": "OPTIONAL: Delimiter for start of element list in filter parameters (Default = '\u00a6')", "Value": "\u00a6", "Type": "String" }, { "Name": "pEleDelim", - "Prompt": "OPTIONAL: Delimiter between elements (default value if blank = '+')", + "Prompt": "OPTIONAL: Delimiter between elements in filter parameters (Default = '+')", "Value": "+", "Type": "String" }, { "Name": "pFactor", - "Prompt": "OPTIONAL: Multiply source value by factor (1 keeps the value as is). To modify existing values make the target element the same as the source with pZeroTarget = 0", + "Prompt": "OPTIONAL: Multiply source values by factor (Default = 1)", "Value": 1, "Type": "Numeric" }, { "Name": "pSuppressConsol", - "Prompt": "OPTIONAL: Suppress Consolidated Cells (Skip = 1)", + "Prompt": "OPTIONAL: Suppress consolidated values (Boolean. Default = 1)", "Value": 1, "Type": "Numeric" }, { "Name": "pSuppressConsolStrings", - "Prompt": "OPTIONAL: Suppress Consolidated String Cells (Skip = 1)", - "Value": 0, + "Prompt": "OPTIONAL: Suppress consolidated string cells (Boolean. Default = 1)", + "Value": 1, "Type": "Numeric" }, { "Name": "pSuppressRules", - "Prompt": "OPTIONAL: Suppress Rules (Skip = 1)", + "Prompt": "OPTIONAL: Suppress rules (Boolean. Default = 1)", "Value": 1, "Type": "Numeric" }, { "Name": "pSuppressZero", - "Prompt": "OPTIONAL: Suppress Null Cells (Skip = 1)", + "Prompt": "OPTIONAL: Suppress zeroes (Boolean. Default = 1)", "Value": 1, "Type": "Numeric" }, { "Name": "pIncludeDescendants", - "Prompt": "OPTIONAL: Include all descendants when copying consolidated values", + "Prompt": "OPTIONAL: Include all descendants when source has consolidations (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" }, { "Name": "pCumulate", - "Prompt": "OPTIONAL: 1 = Add source to existing value in target (if zero out target = 0 False). 0 = Replace target with source.", + "Prompt": "OPTIONAL: Accumulate amounts (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" }, { "Name": "pZeroTarget", - "Prompt": "OPTIONAL: Zero out Target Element PRIOR to Copy? (Boolean 1=True)", + "Prompt": "OPTIONAL: Zero out target before start of process (Boolean. Default = 1)", "Value": 1, "Type": "Numeric" }, { "Name": "pZeroSource", - "Prompt": "OPTIONAL: Zero out Source Element AFTER Copy? (Boolean 1=True)", + "Prompt": "OPTIONAL: Zero out source after end of process (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" }, { "Name": "pTemp", - "Prompt": "OPTIONAL: Delete temporary view and Subset ( 0 = Retain View and Subsets 1 = Delete View and Subsets 2 = Delete View only )", + "Prompt": "OPTIONAL: Delete/create temporary objects (0 = Do not delete, 1 = Delete, 2 = if view and subsets are created, keep only subsets)", "Value": 1, "Type": "Numeric" }, { "Name": "pSandbox", - "Prompt": "OPTIONAL: To use sandbox not base data enter the sandbox name (invalid name will result in process error)", + "Prompt": "OPTIONAL: Use sandbox", "Value": "", "Type": "String" }, @@ -165,50 +153,50 @@ }, { "Name": "pDelim", - "Prompt": "OPTIONAL: For pFile > 0. AsciiOutput delimiter character (Default = ',' exactly 3 digits = ASCII code)", - "Value": ",", + "Prompt": "OPTIONAL: Delimiter for list parameters (Default = '&')", + "Value": "&", "Type": "String" }, { "Name": "pQuote", - "Prompt": "OPTIONAL: For pFile > 0. AsciiOutput quote character (Default = '\"' exactly 3 digits = ASCII code)", + "Prompt": "OPTIONAL: Quote character (2 or 3 digits = ASCII code. Default = '\"')", "Value": "\"", "Type": "String" }, { "Name": "pDecimalSeparator", - "Prompt": "OPTIONAL: For pFile > 0. Decimal separator for conversion of NumberToStringEx and StringToNumberEx (default = '.' exactly 3 digits = ASCII code)", + "Prompt": "OPTIONAL: Decimal separator for string/number conversion (Exactly 3 digits = ASCII code. Default ='.')", "Value": ".", "Type": "String" }, { "Name": "pThousandSeparator", - "Prompt": "OPTIONAL: For pFile > 0. Thousand separator for conversion of NumberToStringEx and StringToNumberEx (default = ',' exactly 3 digits = ASCII code)", + "Prompt": "OPTIONAL: Thousand separator for string/number conversion (Exactly 3 digits = ASCII code. Default = ',')", "Value": ",", "Type": "String" }, { "Name": "pSubN", - "Prompt": "OPTIONAL: Create N level subset for all dims not mentioned in pFilter", + "Prompt": "OPTIONAL: Create N level subset for all dims not specified (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" }, { - "Name": "pThreadMode", - "Prompt": "DO NOT USE: Internal parameter only, please do not use", - "Value": 0, + "Name": "pMaxWaitSeconds", + "Prompt": "OPTIONAL: Max wait time for threads before timing out (Default = 1800)", + "Value": 1800, "Type": "Numeric" }, { - "Name": "pThreadControlFile", - "Prompt": "DO NOT USE: Internal parameter only, please do not use", - "Value": "", - "Type": "String" + "Name": "pLogOutput", + "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" }, { - "Name": "pMaxWaitSeconds", - "Prompt": "OPTIONAL: Used with parallel to define wait time", - "Value": 1800, + "Name": "pStrictErrorHandling", + "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean. Default = 0)", + "Value": 0, "Type": "Numeric" }, { @@ -216,6 +204,24 @@ "Prompt": "OBSOLETE: This parameter does nothing and is only included for backwards compatability", "Value": 0, "Type": "Numeric" + }, + { + "Name": "pThreadMode", + "Prompt": "DO NOT USE: Internal parameter only, please do not use", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pThreadControlFile", + "Prompt": "DO NOT USE: Internal parameter only, please do not use", + "Value": "", + "Type": "String" + }, + { + "Name": "pJson", + "Prompt": "OPTIONAL: JSON Object with process parameter values. This will overwrite user passed parameters for all included parameters.", + "Value": "{}", + "Type": "String" } ], "Variables": [ @@ -577,57 +583,5 @@ "EndByte": 0 } ], - "VariablesUIData": [ - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=33\fColType=827\f" - ] + "VariablesUIData": [] } \ No newline at end of file diff --git a/bedrock_processes_json/}bedrock.cube.data.export.json b/bedrock_processes_json/}bedrock.cube.data.export.json index 6fb3daf..54052b8 100644 --- a/bedrock_processes_json/}bedrock.cube.data.export.json +++ b/bedrock_processes_json/}bedrock.cube.data.export.json @@ -1,11 +1,11 @@ { "Name": "}bedrock.cube.data.export", - "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.data.export', 'pLogoutput', pLogoutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pCube', '', 'pView', '', 'pFilter', '',\r\n \t'pFilterParallel', '', 'pParallelThreads', 0,\r\n \t'pDimDelim', '&', 'pEleStartDelim', '\u00a6', 'pEleDelim', '+',\r\n \t'pSuppressZero', 1, 'pSuppressConsol', 1, 'pSuppressRules', 1, 'pSuppressConsolStrings', 1, 'pIncludeDescendants',0,\r\n \t'pZeroSource', 0, 'pCubeLogging', 0, 'pTemp', 1,\r\n \t'pFilePath', '', 'pFileName', '',\r\n \t'pDelim', ',','pDecimalSeparator','.','pThousandSeparator',',',\r\n 'pQuote', '\"', 'pTitleRecord', 1, 'pSandbox', pSandbox, 'pSubN', pSubN, 'pCubeNameExport', pCubeNameExport\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n#################################################################################################\r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n#################################################################################################\r\n\r\n#Region @DOC\r\n# Description:\r\n# This TI is designed to export data in a given cube to a flat file for a given \"slice\" (any dimension/element combination).\r\n#\r\n# Use case: Intended for development/prototyping or in Production environment.\r\n# 1. Export data for import into another TM1 model to eliminate possibility of locking.\r\n# 2. Export data for import into ERP system.\r\n#\r\n# Note:\r\n# * Naturally, a valid cube name (pCube) is mandatory otherwise the process will abort.\r\n# * All other parameters are optional, however, the filter (pFilter) should be specified to limit the size of the file.\r\n# * The default output path is the same as the error file path.\r\n# * As this TI has a view as a data source it requires the implicit variables NValue, SValue and Value_is_String\r\n# * To edit this TI in Architect a tmp cube with minimum 24 dims is needed as the preview data source or set the data\r\n# source to ASCII and manually edit the TI in notepad after saving to add back the required implicit view variables\r\n# * If using the pFilterParallel parameter the **single dimension** used as the \"parallelization slicer\" cannot appear in\r\n# the pFilter parameter\r\n# * When using parallelization via the *RunProcess* function the elements listed in pFilterParallel will be split one_at_a_time\r\n# and passed to a recursive call of the process being added to pFilter. Each element name will also be appended to the filename\r\n#\r\n# Warning:\r\n# As the *RunProcess* function currently has no mechanism to check for the state of the called process if more processes are\r\n# released than available CPU cores on the server then this could lead to TM1 consuming all available server resources and a\r\n# associated performance issue. Be careful that the number of slicer elements listed in pFilterParallel should not exceed the\r\n# number of available cores.\r\n#EndRegion @DOC\r\n\r\n##Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nStringGlobalVariable('sBedrockViewCreateParsedFilter');\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pCube:%pCube%, pView:%pView%, pFilter:%pFilter%, pFilterParallel:%pFilterParallel%, pParallelThreads:%pParallelThreads%, pDimDelim:%pDimDelim%, pEleStartDelim:%pEleStartDelim%, pEleDelim:%pEleDelim%, pSuppressZero:%pSuppressZero%, pSuppressConsol:%pSuppressConsol%, pSuppressRules:%pSuppressRules%, pZeroSource:%pZeroSource%, pCubeLogging:%pCubeLogging%, pTemp:%pTemp%, pFilePath:%pFilePath%, pFileName:%pFileName%, pDelim:%pDelim%, pQuote:%pQuote%, pTitleRecord:%pTitleRecord%, pSandbox:%pSandbox%, pSuppressConsolStrings:%pSuppressConsolStrings% pIncludeDescendants %pIncludeDescendants%.';\r\ncDefaultView = Expand( '%cThisProcName%_%cTimeStamp%_%cRandomInt%' );\r\ncLenASCIICode = 3;\r\n\r\npFieldDelim = TRIM(pDelim);\r\npDimDelim = TRIM(pDimDelim);\r\npEleStartDelim = TRIM(pEleStartDelim);\r\npEleDelim = TRIM(pEleDelim);\r\npDecimalSeparator = TRIM(pDecimalSeparator);\r\npThousandSeparator= TRIM(pThousandSeparator);\r\nnDataCount = 0;\r\nnErrors = 0;\r\n\r\n## Default filter delimiters\r\nIf( pDimDelim @= '' );\r\n pDimDelim = '&';\r\nEndIf;\r\nIf( pEleStartDelim@= '' );\r\n pEleStartDelim= '\u00a6';\r\nEndIf;\r\nIf( pEleDelim @= '' );\r\n pEleDelim = '+';\r\nEndIf;\r\nIf( pDecimalSeparator @= '' );\r\n \tpDecimalSeparator = '.';\r\nEndIf;\r\nIf( pThousandSeparator @= '' );\r\n \tpThousandSeparator = ',';\r\nEndIf;\r\nsDelimDim = pDimDelim;\r\nsElementStartDelim = pEleStartDelim;\r\nsDelimelem = pEleDelim;\r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) );\r\nENDIF;\r\n\r\n### Validate Parameters ###\r\n\r\n# If no cube has been specified then terminate process\r\nIf( Trim( pCube ) @= '' );\r\n sMessage = 'No cube specified.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( CubeExists( pCube ) = 0 );\r\n sMessage = Expand( 'Cube: %pCube% does not exist.' );\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n## Validate the View parameter\r\nIf( TRIM(pView) @= '' );\r\n cView = cDefaultView ;\r\nElse ;\r\n cView = pView ;\r\nEndIf;\r\ncSubset = cView;\r\n\r\n## check operating system\r\nIf( SubSt( GetProcessErrorFileDirectory, 2, 1 ) @= ':' );\r\n sOS = 'Windows';\r\n sOSDelim = '\\';\r\nElseIf( Scan( '/', GetProcessErrorFileDirectory ) > 0 );\r\n sOS = 'Linux';\r\n sOSDelim = '/';\r\nElse;\r\n sOS = 'Windows';\r\n sOSDelim = '\\';\r\nEndIf;\r\n\r\n# Validate file path\r\nIf(Trim( pFilePath ) @= '' );\r\n pFilePath = GetProcessErrorFileDirectory;\r\nEndIf;\r\nIf( SubSt( pFilePath, Long( pFilePath ), 1 ) @= sOSDelim );\r\n pFilePath = SubSt( pFilePath, 1, Long( pFilePath ) -1 );\r\nEndIf;\r\nIf( FileExists( pFilePath ) = 0 );\r\n sMessage = Expand('Invalid export directory: %pFilePath%');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\npFilePath = pFilePath | sOSDelim;\r\n\r\n# Validate file name\r\nIf( pFileName @= '' );\r\n sBaseFileName = Expand('%pCube%_Export');\r\n sExt = '.csv';\r\n pFileName = sBaseFileName | '.csv';\r\nElse;\r\n # determine file extension. If no file extension entered then use .csv as default\r\n If( Scan( '.', pFileName ) = 0 );\r\n sExt = '.csv';\r\n sBaseFileName = pFileName;\r\n Else;\r\n sExt = SubSt( pFileName, Scan( '.', pFileName ), Long( pFileName ) );\r\n sBaseFileName = SubSt( pFileName, 1, Scan( '.', pFileName ) - 1 );\r\n EndIf;\r\n pFileName = sBaseFileName | sExt;\r\nEndIf;\r\ncExportFile = pFilePath | pFileName;\r\n\r\n# Validate parallelization filter\r\nIf( Scan( pEleStartDelim, pFilterParallel ) > 0 );\r\n sDimParallel = SubSt( pFilterParallel, 1, Scan( pEleStartDelim, pFilterParallel ) - 1 );\r\n If( Scan( Lower(sDimParallel) | pEleStartDelim, Lower(pFilter) ) > 0 );\r\n sMessage = 'Parallelization dimension %sDimParallel% cannot exist in filter.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\nEndIf;\r\n\r\n# Validate Max Threads\r\nIf( pParallelThreads > 0 );\r\n nMaxThreads = pParallelThreads;\r\nElse;\r\n nMaxThreads = 1;\r\nEndIf;\r\n\r\n# Validate file delimiter & quote character\r\nIf( pFieldDelim @= '' );\r\n pFieldDelim = ',';\r\nElse;\r\n # If length of pFieldDelim is exactly 3 chars and each of them is decimal digit, then the pFieldDelim is entered as ASCII code\r\n nValid = 0;\r\n If ( LONG(pFieldDelim) = cLenASCIICode );\r\n nChar = 1;\r\n While ( nChar <= cLenASCIICode );\r\n If( CODE( pFieldDelim, nChar ) >= CODE( '0', 1 ) & CODE( pFieldDelim, nChar ) <= CODE( '9', 1 ) );\r\n nValid = 1;\r\n Else;\r\n nValid = 0;\r\n Break;\r\n EndIf;\r\n nChar = nChar + 1;\r\n End;\r\n EndIf;\r\n If ( nValid<>0 );\r\n pFieldDelim=CHAR(StringToNumber( pFieldDelim ));\r\n Else;\r\n pFieldDelim = SubSt( Trim( pFieldDelim ), 1, 1 );\r\n EndIf;\r\nEndIf;\r\n\r\nIf( pQuote @= '' );\r\n ## Use no quote character\r\nElse;\r\n # If length of pQuote is exactly 3 chars and each of them is decimal digit, then the pQuote is entered as ASCII code\r\n nValid = 0;\r\n If ( LONG(pQuote) = cLenASCIICode );\r\n nChar = 1;\r\n While ( nChar <= cLenASCIICode );\r\n If( CODE( pQuote, nChar ) >= CODE( '0', 1 ) & CODE( pQuote, nChar ) <= CODE( '9', 1 ) );\r\n nValid = 1;\r\n Else;\r\n nValid = 0;\r\n Break;\r\n EndIf;\r\n nChar = nChar + 1;\r\n End;\r\n EndIf;\r\n If ( nValid<>0 );\r\n pQuote=CHAR(StringToNumber( pQuote ));\r\n Else;\r\n pQuote = SubSt( Trim( pQuote ), 1, 1 );\r\n EndIf;\r\nEndIf;\r\n\r\nIf ( LONG(pDecimalSeparator) = cLenASCIICode );\r\n nValid = 0;\r\n nChar = 1;\r\n While ( nChar <= cLenASCIICode );\r\n If( CODE( pDecimalSeparator, nChar ) >= CODE( '0', 1 ) & CODE( pDecimalSeparator, nChar ) <= CODE( '9', 1 ) );\r\n nValid = 1;\r\n Else;\r\n nValid = 0;\r\n Break;\r\n EndIf;\r\n nChar = nChar + 1;\r\n End;\r\n If ( nValid<>0 );\r\n pDecimalSeparator = CHAR(StringToNumber( pDecimalSeparator ));\r\n Else;\r\n pDecimalSeparator = SubSt( Trim( pDecimalSeparator ), 1, 1 );\r\n EndIf;\r\nEndIf;\r\nsDecimalSeparator = pDecimalSeparator;\r\n\r\nIf ( LONG(pThousandSeparator) = cLenASCIICode );\r\n nValid = 0;\r\n nChar = 1;\r\n While ( nChar <= cLenASCIICode );\r\n If( CODE( pThousandSeparator, nChar ) >= CODE( '0', 1 ) & CODE( pThousandSeparator, nChar ) <= CODE( '9', 1 ) );\r\n nValid = 1;\r\n Else;\r\n nValid = 0;\r\n Break;\r\n EndIf;\r\n nChar = nChar + 1;\r\n End;\r\n If ( nValid<>0 );\r\n pThousandSeparator = CHAR(StringToNumber( pThousandSeparator ));\r\n Else;\r\n pThousandSeparator = SubSt( Trim( pThousandSeparator ), 1, 1 );\r\n EndIf;\r\nEndIf;\r\nsThousandSeparator = pThousandSeparator;\r\n\r\n# Validate Sandbox\r\nIf( TRIM( pSandbox ) @<> '' );\r\n If( ServerSandboxExists( pSandbox ) = 0 );\r\n SetUseActiveSandboxProperty( 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand('Sandbox %pSandbox% is invalid for the current user.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n Else;\r\n ServerActiveSandboxSet( pSandbox );\r\n SetUseActiveSandboxProperty( 1 );\r\n EndIf;\r\nElse;\r\n SetUseActiveSandboxProperty( 0 );\r\nEndIf;\r\n\r\n# Validate Character Set\r\nIf(Trim( pCharacterSet ) @= '' );\r\n pCharacterSet = 'TM1CS_UTF8';\r\nEndIf;\r\n\r\n# Jump to Epilog if any errors so far\r\nIF ( nErrors > 0 );\r\n DataSourceType = 'NULL';\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nENDIF;\r\n\r\n# Branch depending on whether to do recursive calls to self on independent threads or run all in this thread\r\nIf( Scan( pEleStartDelim, pFilterParallel ) > 0 );\r\n sDimParallel = SubSt( pFilterParallel, 1, Scan( pEleStartDelim, pFilterParallel ) - 1 );\r\n sElementList = SubSt( pFilterParallel, Scan( pEleStartDelim, pFilterParallel ) + 1, Long( pFilterParallel ) );\r\n If( SubSt( sElementList, Long( sElementList ), 1 ) @<> pEleDelim );\r\n sElementList = sElementList | pEleDelim;\r\n EndIf;\r\n ## Counting elements in element list\r\n sElementListCount = sElementList;\r\n nElements = 0;\r\n While( Scan( pEleDelim, sElementListCount ) > 0 );\r\n nElements = nElements + 1;\r\n sElementListCount = SubSt( sElementListCount, Scan( pEleDelim, sElementListCount ) + 1, Long( sElementListCount ) );\r\n End;\r\n IF( Mod( nElements, nMaxThreads ) = 0 );\r\n nElemsPerThread = INT( nElements \\ nMaxThreads );\r\n ELSE;\r\n nElemsPerThread = INT( nElements \\ nMaxThreads ) + 1;\r\n ENDIF;\r\n nThreadElCounter = 0;\r\n While( Scan( pEleDelim, sElementList ) > 0 );\r\n sSlicerEle = SubSt( sElementList, 1, Scan( pEleDelim, sElementList ) - 1 );\r\n sElementList = SubSt( sElementList, Scan( pEleDelim, sElementList ) + 1, Long( sElementList ) );\r\n # Do recursive process call with new RunProcess function\r\n nThreadElCounter = nThreadElCounter + 1;\r\n sDimDelim = If(pFilter @= '', '', pDimDelim );\r\n IF( nThreadElCounter = 1 );\r\n sFilter = Expand('%pFilter%%sDimDelim%%sDimParallel%%pEleStartDelim%%sSlicerEle%');\r\n sFileName = Expand('%sBaseFileName%_%sDimParallel%_%sSlicerEle%');\r\n ELSE;\r\n sFilter = Expand('%sFilter%%pEleDelim%%sSlicerEle%');\r\n sFileName = Expand('%sFileName%+%sSlicerEle%');\r\n ENDIF;\r\n IF( nThreadElCounter >= nElemsPerThread );\r\n sFileName = Expand('%sFileName%%sExt%');\r\n RunProcess( cThisProcName, 'pLogoutput', pLogoutput,\r\n \t'pCube', pCube, 'pView', '',\r\n \t'pFilter', sFilter, 'pFilterParallel', '',\r\n \t'pDimDelim', pDimDelim, 'pEleStartDelim', pEleStartDelim, 'pEleDelim', pEleDelim,\r\n \t'pSuppressZero', pSuppressZero, 'pSuppressConsol', pSuppressConsol, 'pSuppressRules', pSuppressRules,\r\n \t'pZeroSource', pZeroSource, 'pCubeLogging', pCubeLogging,\r\n \t'pTemp', pTemp, 'pFilePath', pFilePath, 'pFileName', sFileName,\r\n \t'pDelim', pFieldDelim, 'pDecimalSeparator', pDecimalSeparator, 'pThousandSeparator', pThousandSeparator,\r\n 'pQuote', pQuote, 'pTitleRecord', pTitleRecord, 'pSandbox', pSandbox, 'pSuppressConsolStrings', pSuppressConsolStrings, 'pCubeNameExport', pCubeNameExport\r\n );\r\n \t nThreadElCounter = 0;\r\n \t sFilter = '';\r\n \t sFileName = '';\r\n \t ENDIF;\r\n End;\r\n ## Process last elements - only when filter is not empty (there are still elements)\r\n IF( sFilter @<> '' );\r\n sFileName = Expand('%sFileName%%sExt%');\r\n RunProcess( cThisProcName, 'pLogoutput', pLogoutput,\r\n \t'pCube', pCube, 'pView', '',\r\n \t'pFilter', sFilter, 'pFilterParallel', '',\r\n \t'pDimDelim', pDimDelim, 'pEleStartDelim', pEleStartDelim, 'pEleDelim', pEleDelim,\r\n \t'pSuppressZero', pSuppressZero, 'pSuppressConsol', pSuppressConsol, 'pSuppressRules', pSuppressRules,\r\n \t'pZeroSource', pZeroSource, 'pCubeLogging', pCubeLogging,\r\n \t'pTemp', pTemp, 'pFilePath', pFilePath, 'pFileName', sFileName,\r\n \t'pDelim', pFieldDelim, 'pDecimalSeparator', pDecimalSeparator, 'pThousandSeparator', pThousandSeparator,\r\n 'pQuote', pQuote, 'pTitleRecord', pTitleRecord, 'pSandbox', pSandbox, 'pSuppressConsolStrings', pSuppressConsolStrings, 'pCubeNameExport', pCubeNameExport\r\n );\r\n ENDIF;\r\n DataSourceType = 'NULL';\r\n nParallelRun = 1;\r\nElse;\r\n # No parallelization is being used. Proceed as normal and do everything internally\r\n\r\n # Determine number of dims in source cube & create strings to expand on title and rows\r\n nCount = 1;\r\n nDimensionIndex = 0;\r\n\r\n ## Skip cube name from export\r\n IF (pCubeNameExport = 0);\r\n sTitle = '';\r\n sRow = '';\r\n\r\n While( TabDim( pCube, nCount ) @<> '' );\r\n sDimension = TabDim( pCube, nCount );\r\n\r\n ## Determine title string for the source cube\r\n sTitle = sTitle|'%pQuote%'|sDimension|'%pQuote%%pFieldDelim%';\r\n # Determine row string for the source cube\r\n sRow = sRow|'%pQuote%%V'| numbertostring(nCount) |'%%pQuote%%pFieldDelim%';\r\n\r\n nCount = nCount + 1;\r\n End;\r\n nDimensionCount = nCount - 1;\r\n\r\n # Finish off the strings\r\n sTitle = sTitle|'%pQuote%Value%pQuote%';\r\n sRow = sRow|'%pQuote%%sValue%%pQuote%';\r\n\r\n ELSE;\r\n sTitle = '%pQuote%Cube%pQuote%';\r\n sRow = '%pQuote%%pCube%%pQuote%';\r\n\r\n While( TabDim( pCube, nCount ) @<> '' );\r\n sDimension = TabDim( pCube, nCount );\r\n\r\n ## Determine title string for the source cube\r\n sTitle = sTitle|'%pFieldDelim%%pQuote%'|sDimension|'%pQuote%';\r\n # Determine row string for the source cube\r\n sRow = sRow|'%pFieldDelim%%pQuote%%V'| numbertostring(nCount) |'%%pQuote%';\r\n\r\n nCount = nCount + 1;\r\n End;\r\n nDimensionCount = nCount - 1;\r\n\r\n # Finish off the strings\r\n sTitle = sTitle|'%pFieldDelim%%pQuote%Value%pQuote%';\r\n sRow = sRow|'%pFieldDelim%%pQuote%%sValue%%pQuote%';\r\n ENDIF;\r\n\r\n # Create Processing View for source version\r\n nRet = ExecuteProcess('}bedrock.cube.view.create',\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCube,\r\n 'pView', cView,\r\n 'pFilter', pFilter,\r\n 'pSuppressZero', pSuppressZero,\r\n 'pSuppressConsol', pSuppressConsol,\r\n 'pSuppressRules', pSuppressRules,\r\n 'pSuppressConsolStrings', pSuppressConsolStrings,\r\n 'pIncludeDescendants',pIncludeDescendants,\r\n 'pDimDelim', pDimDelim,\r\n 'pEleStartDelim', pEleStartDelim,\r\n 'pEleDelim', pEleDelim,\r\n 'pTemp', pTemp,\r\n 'pSubN', pSubN\r\n );\r\n\r\n # Validate Sandbox\r\n If( TRIM( pSandbox ) @<> '' );\r\n If( ServerSandboxExists( pSandbox ) = 0 );\r\n SetUseActiveSandboxProperty( 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand('Sandbox %pSandbox% is invalid for the current user.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n Else;\r\n ServerActiveSandboxSet( pSandbox );\r\n SetUseActiveSandboxProperty( 1 );\r\n EndIf;\r\n Else;\r\n SetUseActiveSandboxProperty( 0 );\r\n EndIf;\r\n\r\n\r\n IF( nRet <> ProcessExitNormal() );\r\n sMessage = 'Error creating the view from the filter.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n\r\n sParsedFilter = sBedrockViewCreateParsedFilter;\r\n sFilterRow = '%pQuote%%pCube%%pQuote%%pFieldDelim%%pQuote%Filter%pQuote%%pFieldDelim%%pQuote%%sParsedFilter%%pQuote%%pFieldDelim%%pQuote%%pDimDelim%%pQuote%%pFieldDelim%%pQuote%%pEleStartDelim%%pQuote%%pFieldDelim%%pQuote%%pEleDelim%%pQuote%';\r\n\r\n # Assign Datasource\r\n DataSourceType = 'VIEW';\r\n DatasourceNameForServer = pCube;\r\n DatasourceNameForClient = pCube;\r\n DatasourceCubeView = cView;\r\n DatasourceAsciiDelimiter= pFieldDelim;\r\n DatasourceAsciiQuoteCharacter = '';\r\n nParallelRun = 0;\r\nEndIf;\r\n\r\n### End Prolog ###", + "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.data.export', 'pLogoutput', pLogoutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pCube', '', 'pView', '', 'pFilter', '',\r\n \t'pFilterParallel', '', 'pParallelThreads', 0,\r\n \t'pDimDelim', '&', 'pEleStartDelim', '\u00a6', 'pEleDelim', '+',\r\n \t'pSuppressZero', 1, 'pSuppressConsol', 1, 'pSuppressRules', 1, 'pSuppressConsolStrings', 1, 'pIncludeDescendants',0,\r\n \t'pZeroSource', 0, 'pCubeLogging', 0, 'pTemp', 1,\r\n \t'pFilePath', '', 'pFileName', '',\r\n \t'pDelim', ',','pDecimalSeparator','.','pThousandSeparator',',',\r\n 'pQuote', '\"', 'pTitleRecord', 1, 'pSandbox', pSandbox, 'pSubN', pSubN, 'pCubeNameExport', pCubeNameExport\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n#################################################################################################\r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n#################################################################################################\r\n\r\n#Region @DOC\r\n# Description:\r\n# This TI is designed to export data in a given cube to a flat file for a given \"slice\" (any dimension/element combination).\r\n#\r\n# Use case: Intended for development/prototyping or in Production environment.\r\n# 1. Export data for import into another TM1 model to eliminate possibility of locking.\r\n# 2. Export data for import into ERP system.\r\n#\r\n# Note:\r\n# * Naturally, a valid cube name (pCube) is mandatory otherwise the process will abort.\r\n# * All other parameters are optional, however, the filter (pFilter) should be specified to limit the size of the file.\r\n# * The default output path is the same as the error file path.\r\n# * As this TI has a view as a data source it requires the implicit variables NValue, SValue and Value_is_String\r\n# * To edit this TI in Architect a tmp cube with minimum 24 dims is needed as the preview data source or set the data\r\n# source to ASCII and manually edit the TI in notepad after saving to add back the required implicit view variables\r\n# * If using the pFilterParallel parameter the **single dimension** used as the \"parallelization slicer\" cannot appear in\r\n# the pFilter parameter\r\n# * When using parallelization via the *RunProcess* function the elements listed in pFilterParallel will be split one_at_a_time\r\n# and passed to a recursive call of the process being added to pFilter. Each element name will also be appended to the filename\r\n#\r\n# Warning:\r\n# As the *RunProcess* function currently has no mechanism to check for the state of the called process if more processes are\r\n# released than available CPU cores on the server then this could lead to TM1 consuming all available server resources and a\r\n# associated performance issue. Be careful that the number of slicer elements listed in pFilterParallel should not exceed the\r\n# number of available cores.\r\n#EndRegion @DOC\r\n\r\n##Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nStringGlobalVariable('sBedrockViewCreateParsedFilter');\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pCube:%pCube%, pView:%pView%, pFilter:%pFilter%, pFilterParallel:%pFilterParallel%, pParallelThreads:%pParallelThreads%, pDimDelim:%pDimDelim%, pEleStartDelim:%pEleStartDelim%, pEleDelim:%pEleDelim%, pSuppressZero:%pSuppressZero%, pSuppressConsol:%pSuppressConsol%, pSuppressRules:%pSuppressRules%, pZeroSource:%pZeroSource%, pCubeLogging:%pCubeLogging%, pTemp:%pTemp%, pFilePath:%pFilePath%, pFileName:%pFileName%, pDelim:%pDelim%, pQuote:%pQuote%, pTitleRecord:%pTitleRecord%, pSandbox:%pSandbox%, pSuppressConsolStrings:%pSuppressConsolStrings% pIncludeDescendants %pIncludeDescendants%.';\r\ncDefaultView = Expand( '%cThisProcName%_%cTimeStamp%_%cRandomInt%' );\r\ncLenASCIICode = 3;\r\n\r\n#################################################################################################\r\n#Region - Process Parameters\r\n\r\npJson = IF( JsonType( pJson ) @<> 'object', '{}', pJson );\r\nsMessages = '{\"Process\": \"'|GetProcessName()|'\", \"User\": \"'|TM1User()|'\", \"Info\": [\"Process: '''|GetProcessName()|''' run by User: '''|TM1User()|'''.\"], \"Error\": []}';\r\npDefaultParameters = '{\r\n \"pCharacterSet\": \"TM1CS_UTF8\",\r\n \"pCube\": null,\r\n \"pDecimalSeparator\": \".\",\r\n \"pDelim\": \"&\",\r\n \"pDimDelim\": \"&\",\r\n \"pEleDelim\": \"+\",\r\n \"pEleStartDelim\": \"\u00a6\",\r\n \"pFileName\": \"\",\r\n \"pFilePath\": \"\",\r\n \"pFilter\": \"\",\r\n \"pFilterParallel\": \"\",\r\n \"pQuote\": \"\"\",\r\n \"pSandbox\": \"\",\r\n \"pThousandSeparator\": \",\",\r\n \"pView\": \"\",\r\n \"pCubeNameExport\": 1,\r\n \"pIncludeDescendants\": 0,\r\n \"pLogOutput\": 0,\r\n \"pParallelThreads\": 0,\r\n \"pStrictErrorHandling\": 0,\r\n \"pSubN\": 0,\r\n \"pSuppressConsol\": 1,\r\n \"pSuppressConsolStrings\": 1,\r\n \"pSuppressRules\": 1,\r\n \"pSuppressZero\": 1,\r\n \"pTemp\": 1,\r\n \"pTitleRecord\": 1,\r\n \"pZeroSource\": 0\r\n}';\r\n\r\npPassedParameters = '{\r\n \"pCharacterSet\": '|StringToJson ( pCharacterSet )|',\r\n \"pCube\": '|StringToJson ( pCube )|',\r\n \"pDecimalSeparator\": '|StringToJson ( pDecimalSeparator )|',\r\n \"pDelim\": '|StringToJson ( pDelim )|',\r\n \"pDimDelim\": '|StringToJson ( pDimDelim )|',\r\n \"pEleDelim\": '|StringToJson ( pEleDelim )|',\r\n \"pEleStartDelim\": '|StringToJson ( pEleStartDelim )|',\r\n \"pFileName\": '|StringToJson ( pFileName )|',\r\n \"pFilePath\": '|StringToJson ( pFilePath )|',\r\n \"pFilter\": '|StringToJson ( pFilter )|',\r\n \"pFilterParallel\": '|StringToJson ( pFilterParallel )|',\r\n \"pQuote\": '|StringToJson ( pQuote )|',\r\n \"pSandbox\": '|StringToJson ( pSandbox )|',\r\n \"pThousandSeparator\": '|StringToJson ( pThousandSeparator )|',\r\n \"pView\": '|StringToJson ( pView )|',\r\n \"pCubeNameExport\": '|NumberToString( pCubeNameExport )|',\r\n \"pIncludeDescendants\": '|NumberToString( pIncludeDescendants )|',\r\n \"pLogOutput\": '|NumberToString( pLogOutput )|',\r\n \"pParallelThreads\": '|NumberToString( pParallelThreads )|',\r\n \"pStrictErrorHandling\": '|NumberToString( pStrictErrorHandling )|',\r\n \"pSubN\": '|NumberToString( pSubN )|',\r\n \"pSuppressConsol\": '|NumberToString( pSuppressConsol )|',\r\n \"pSuppressConsolStrings\": '|NumberToString( pSuppressConsolStrings )|',\r\n \"pSuppressRules\": '|NumberToString( pSuppressRules )|',\r\n \"pSuppressZero\": '|NumberToString( pSuppressZero )|',\r\n \"pTemp\": '|NumberToString( pTemp )|',\r\n \"pTitleRecord\": '|NumberToString( pTitleRecord )|',\r\n \"pZeroSource\": '|NumberToString( pZeroSource )|'\r\n}';\r\n\r\npJson = JsonMergePatch( pPassedParameters, pJson );\r\n# String Parameters\r\npCharacterSet = JsonToString( JsonGet( pJson, 'pCharacterSet' ) );\r\npCube = JsonToString( JsonGet( pJson, 'pCube' ) );\r\npDecimalSeparator = JsonToString( JsonGet( pJson, 'pDecimalSeparator' ) );\r\npDelim = JsonToString( JsonGet( pJson, 'pDelim' ) );\r\npDimDelim = JsonToString( JsonGet( pJson, 'pDimDelim' ) );\r\npEleDelim = JsonToString( JsonGet( pJson, 'pEleDelim' ) );\r\npEleStartDelim = JsonToString( JsonGet( pJson, 'pEleStartDelim' ) );\r\npFileName = JsonToString( JsonGet( pJson, 'pFileName' ) );\r\npFilePath = JsonToString( JsonGet( pJson, 'pFilePath' ) );\r\npFilter = JsonToString( JsonGet( pJson, 'pFilter' ) );\r\npFilterParallel = JsonToString( JsonGet( pJson, 'pFilterParallel' ) );\r\npQuote = JsonToString( JsonGet( pJson, 'pQuote' ) );\r\npSandbox = JsonToString( JsonGet( pJson, 'pSandbox' ) );\r\npThousandSeparator = JsonToString( JsonGet( pJson, 'pThousandSeparator' ) );\r\npView = JsonToString( JsonGet( pJson, 'pView' ) );\r\n# Numeric Parameters\r\npCubeNameExport = StringToNumber( JsonToString( JsonGet( pJson, 'pCubeNameExport' ) ) );\r\npIncludeDescendants = StringToNumber( JsonToString( JsonGet( pJson, 'pIncludeDescendants' ) ) );\r\npLogOutput = StringToNumber( JsonToString( JsonGet( pJson, 'pLogOutput' ) ) );\r\npParallelThreads = StringToNumber( JsonToString( JsonGet( pJson, 'pParallelThreads' ) ) );\r\npStrictErrorHandling = StringToNumber( JsonToString( JsonGet( pJson, 'pStrictErrorHandling' ) ) );\r\npSubN = StringToNumber( JsonToString( JsonGet( pJson, 'pSubN' ) ) );\r\npSuppressConsol = StringToNumber( JsonToString( JsonGet( pJson, 'pSuppressConsol' ) ) );\r\npSuppressConsolStrings = StringToNumber( JsonToString( JsonGet( pJson, 'pSuppressConsolStrings' ) ) );\r\npSuppressRules = StringToNumber( JsonToString( JsonGet( pJson, 'pSuppressRules' ) ) );\r\npSuppressZero = StringToNumber( JsonToString( JsonGet( pJson, 'pSuppressZero' ) ) );\r\npTemp = StringToNumber( JsonToString( JsonGet( pJson, 'pTemp' ) ) );\r\npTitleRecord = StringToNumber( JsonToString( JsonGet( pJson, 'pTitleRecord' ) ) );\r\npZeroSource = StringToNumber( JsonToString( JsonGet( pJson, 'pZeroSource' ) ) );\r\n\r\n### Get the parameters that differ from the default\r\npDiffer = JsonDiff( pDefaultParameters, pJson );\r\nnSize = JsonSize( pDiffer );\r\nWHILE( nSize > 0 );\r\n nSize = nSize - 1;\r\n pDiffer = JsonReplace( pDiffer, '/'|NumberToString( nSize )|'/op', '\"add\"' );\r\nEND;\r\npJson = JsonPatch( '{}', pDiffer );\r\n\r\n### LogOutput parameters\r\nsMessages = JsonAdd( sMessages, '/Info/-', pJson );\r\nIF( pLogOutput = 1 );\r\n LogOutput('INFO', JsonToString( sMessages, '/Info/0', 0, ' ' ) );\r\nENDIF;\r\n\r\n#EndRegion - Process Parameters\r\n#################################################################################################\r\n\r\npFieldDelim = TRIM(pDelim);\r\npDimDelim = TRIM(pDimDelim);\r\npEleStartDelim = TRIM(pEleStartDelim);\r\npEleDelim = TRIM(pEleDelim);\r\npDecimalSeparator = TRIM(pDecimalSeparator);\r\npThousandSeparator= TRIM(pThousandSeparator);\r\nnDataCount = 0;\r\nnErrors = 0;\r\n\r\n## Default filter delimiters\r\nIf( pDimDelim @= '' );\r\n pDimDelim = '&';\r\nEndIf;\r\nIf( pEleStartDelim@= '' );\r\n pEleStartDelim= '\u00a6';\r\nEndIf;\r\nIf( pEleDelim @= '' );\r\n pEleDelim = '+';\r\nEndIf;\r\nIf( pDecimalSeparator @= '' );\r\n \tpDecimalSeparator = '.';\r\nEndIf;\r\nIf( pThousandSeparator @= '' );\r\n \tpThousandSeparator = ',';\r\nEndIf;\r\nsDelimDim = pDimDelim;\r\nsElementStartDelim = pEleStartDelim;\r\nsDelimelem = pEleDelim;\r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) );\r\nENDIF;\r\n\r\n### Validate Parameters ###\r\n\r\n# If no cube has been specified then terminate process\r\nIf( Trim( pCube ) @= '' );\r\n sMessage = 'No cube specified.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( CubeExists( pCube ) = 0 );\r\n sMessage = Expand( 'Cube: %pCube% does not exist.' );\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n## Validate the View parameter\r\nIf( TRIM(pView) @= '' );\r\n cView = cDefaultView ;\r\nElse ;\r\n cView = pView ;\r\nEndIf;\r\ncSubset = cView;\r\n\r\n## check operating system\r\nIf( SubSt( GetProcessErrorFileDirectory, 2, 1 ) @= ':' );\r\n sOS = 'Windows';\r\n sOSDelim = '\\';\r\nElseIf( Scan( '/', GetProcessErrorFileDirectory ) > 0 );\r\n sOS = 'Linux';\r\n sOSDelim = '/';\r\nElse;\r\n sOS = 'Windows';\r\n sOSDelim = '\\';\r\nEndIf;\r\n\r\n# Validate file path\r\nIf(Trim( pFilePath ) @= '' );\r\n pFilePath = GetProcessErrorFileDirectory;\r\nEndIf;\r\nIf( SubSt( pFilePath, Long( pFilePath ), 1 ) @= sOSDelim );\r\n pFilePath = SubSt( pFilePath, 1, Long( pFilePath ) -1 );\r\nEndIf;\r\nIf( FileExists( pFilePath ) = 0 );\r\n sMessage = Expand('Invalid export directory: %pFilePath%');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\npFilePath = pFilePath | sOSDelim;\r\n\r\n# Validate file name\r\nIf( pFileName @= '' );\r\n sBaseFileName = Expand('%pCube%_Export');\r\n sExt = '.csv';\r\n pFileName = sBaseFileName | '.csv';\r\nElse;\r\n # determine file extension. If no file extension entered then use .csv as default\r\n If( Scan( '.', pFileName ) = 0 );\r\n sExt = '.csv';\r\n sBaseFileName = pFileName;\r\n Else;\r\n sExt = SubSt( pFileName, Scan( '.', pFileName ), Long( pFileName ) );\r\n sBaseFileName = SubSt( pFileName, 1, Scan( '.', pFileName ) - 1 );\r\n EndIf;\r\n pFileName = sBaseFileName | sExt;\r\nEndIf;\r\ncExportFile = pFilePath | pFileName;\r\n\r\n# Validate parallelization filter\r\nIf( Scan( pEleStartDelim, pFilterParallel ) > 0 );\r\n sDimParallel = SubSt( pFilterParallel, 1, Scan( pEleStartDelim, pFilterParallel ) - 1 );\r\n If( Scan( Lower(sDimParallel) | pEleStartDelim, Lower(pFilter) ) > 0 );\r\n sMessage = 'Parallelization dimension %sDimParallel% cannot exist in filter.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\nEndIf;\r\n\r\n# Validate Max Threads\r\nIf( pParallelThreads > 0 );\r\n nMaxThreads = pParallelThreads;\r\nElse;\r\n nMaxThreads = 1;\r\nEndIf;\r\n\r\n# Validate file delimiter & quote character\r\nIf( pFieldDelim @= '' );\r\n pFieldDelim = ',';\r\nElse;\r\n # If length of pFieldDelim is exactly 3 chars and each of them is decimal digit, then the pFieldDelim is entered as ASCII code\r\n nValid = 0;\r\n If ( LONG(pFieldDelim) = cLenASCIICode );\r\n nChar = 1;\r\n While ( nChar <= cLenASCIICode );\r\n If( CODE( pFieldDelim, nChar ) >= CODE( '0', 1 ) & CODE( pFieldDelim, nChar ) <= CODE( '9', 1 ) );\r\n nValid = 1;\r\n Else;\r\n nValid = 0;\r\n Break;\r\n EndIf;\r\n nChar = nChar + 1;\r\n End;\r\n EndIf;\r\n If ( nValid<>0 );\r\n pFieldDelim=CHAR(StringToNumber( pFieldDelim ));\r\n Else;\r\n pFieldDelim = SubSt( Trim( pFieldDelim ), 1, 1 );\r\n EndIf;\r\nEndIf;\r\n\r\nIf( pQuote @= '' );\r\n ## Use no quote character\r\nElse;\r\n # If length of pQuote is exactly 3 chars and each of them is decimal digit, then the pQuote is entered as ASCII code\r\n nValid = 0;\r\n If ( LONG(pQuote) = cLenASCIICode );\r\n nChar = 1;\r\n While ( nChar <= cLenASCIICode );\r\n If( CODE( pQuote, nChar ) >= CODE( '0', 1 ) & CODE( pQuote, nChar ) <= CODE( '9', 1 ) );\r\n nValid = 1;\r\n Else;\r\n nValid = 0;\r\n Break;\r\n EndIf;\r\n nChar = nChar + 1;\r\n End;\r\n EndIf;\r\n If ( nValid<>0 );\r\n pQuote=CHAR(StringToNumber( pQuote ));\r\n Else;\r\n pQuote = SubSt( Trim( pQuote ), 1, 1 );\r\n EndIf;\r\nEndIf;\r\n\r\nIf ( LONG(pDecimalSeparator) = cLenASCIICode );\r\n nValid = 0;\r\n nChar = 1;\r\n While ( nChar <= cLenASCIICode );\r\n If( CODE( pDecimalSeparator, nChar ) >= CODE( '0', 1 ) & CODE( pDecimalSeparator, nChar ) <= CODE( '9', 1 ) );\r\n nValid = 1;\r\n Else;\r\n nValid = 0;\r\n Break;\r\n EndIf;\r\n nChar = nChar + 1;\r\n End;\r\n If ( nValid<>0 );\r\n pDecimalSeparator = CHAR(StringToNumber( pDecimalSeparator ));\r\n Else;\r\n pDecimalSeparator = SubSt( Trim( pDecimalSeparator ), 1, 1 );\r\n EndIf;\r\nEndIf;\r\nsDecimalSeparator = pDecimalSeparator;\r\n\r\nIf ( LONG(pThousandSeparator) = cLenASCIICode );\r\n nValid = 0;\r\n nChar = 1;\r\n While ( nChar <= cLenASCIICode );\r\n If( CODE( pThousandSeparator, nChar ) >= CODE( '0', 1 ) & CODE( pThousandSeparator, nChar ) <= CODE( '9', 1 ) );\r\n nValid = 1;\r\n Else;\r\n nValid = 0;\r\n Break;\r\n EndIf;\r\n nChar = nChar + 1;\r\n End;\r\n If ( nValid<>0 );\r\n pThousandSeparator = CHAR(StringToNumber( pThousandSeparator ));\r\n Else;\r\n pThousandSeparator = SubSt( Trim( pThousandSeparator ), 1, 1 );\r\n EndIf;\r\nEndIf;\r\nsThousandSeparator = pThousandSeparator;\r\n\r\n# Validate Sandbox\r\nIf( TRIM( pSandbox ) @<> '' );\r\n If( ServerSandboxExists( pSandbox ) = 0 );\r\n SetUseActiveSandboxProperty( 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand('Sandbox %pSandbox% is invalid for the current user.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n Else;\r\n ServerActiveSandboxSet( pSandbox );\r\n SetUseActiveSandboxProperty( 1 );\r\n EndIf;\r\nElse;\r\n SetUseActiveSandboxProperty( 0 );\r\nEndIf;\r\n\r\n# Validate Character Set\r\nIf(Trim( pCharacterSet ) @= '' );\r\n pCharacterSet = 'TM1CS_UTF8';\r\nEndIf;\r\n\r\n# Jump to Epilog if any errors so far\r\nIF ( nErrors > 0 );\r\n DataSourceType = 'NULL';\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nENDIF;\r\n\r\n# Branch depending on whether to do recursive calls to self on independent threads or run all in this thread\r\nIf( Scan( pEleStartDelim, pFilterParallel ) > 0 );\r\n sDimParallel = SubSt( pFilterParallel, 1, Scan( pEleStartDelim, pFilterParallel ) - 1 );\r\n sElementList = SubSt( pFilterParallel, Scan( pEleStartDelim, pFilterParallel ) + 1, Long( pFilterParallel ) );\r\n If( SubSt( sElementList, Long( sElementList ), 1 ) @<> pEleDelim );\r\n sElementList = sElementList | pEleDelim;\r\n EndIf;\r\n ## Counting elements in element list\r\n sElementListCount = sElementList;\r\n nElements = 0;\r\n While( Scan( pEleDelim, sElementListCount ) > 0 );\r\n nElements = nElements + 1;\r\n sElementListCount = SubSt( sElementListCount, Scan( pEleDelim, sElementListCount ) + 1, Long( sElementListCount ) );\r\n End;\r\n IF( Mod( nElements, nMaxThreads ) = 0 );\r\n nElemsPerThread = INT( nElements \\ nMaxThreads );\r\n ELSE;\r\n nElemsPerThread = INT( nElements \\ nMaxThreads ) + 1;\r\n ENDIF;\r\n nThreadElCounter = 0;\r\n While( Scan( pEleDelim, sElementList ) > 0 );\r\n sSlicerEle = SubSt( sElementList, 1, Scan( pEleDelim, sElementList ) - 1 );\r\n sElementList = SubSt( sElementList, Scan( pEleDelim, sElementList ) + 1, Long( sElementList ) );\r\n # Do recursive process call with new RunProcess function\r\n nThreadElCounter = nThreadElCounter + 1;\r\n sDimDelim = If(pFilter @= '', '', pDimDelim );\r\n IF( nThreadElCounter = 1 );\r\n sFilter = Expand('%pFilter%%sDimDelim%%sDimParallel%%pEleStartDelim%%sSlicerEle%');\r\n sFileName = Expand('%sBaseFileName%_%sDimParallel%_%sSlicerEle%');\r\n ELSE;\r\n sFilter = Expand('%sFilter%%pEleDelim%%sSlicerEle%');\r\n sFileName = Expand('%sFileName%+%sSlicerEle%');\r\n ENDIF;\r\n IF( nThreadElCounter >= nElemsPerThread );\r\n sFileName = Expand('%sFileName%%sExt%');\r\n RunProcess( cThisProcName, 'pLogoutput', pLogoutput,\r\n \t'pCube', pCube, 'pView', '',\r\n \t'pFilter', sFilter, 'pFilterParallel', '',\r\n \t'pDimDelim', pDimDelim, 'pEleStartDelim', pEleStartDelim, 'pEleDelim', pEleDelim,\r\n \t'pSuppressZero', pSuppressZero, 'pSuppressConsol', pSuppressConsol, 'pSuppressRules', pSuppressRules,\r\n \t'pZeroSource', pZeroSource, 'pCubeLogging', pCubeLogging,\r\n \t'pTemp', pTemp, 'pFilePath', pFilePath, 'pFileName', sFileName,\r\n \t'pDelim', pFieldDelim, 'pDecimalSeparator', pDecimalSeparator, 'pThousandSeparator', pThousandSeparator,\r\n 'pQuote', pQuote, 'pTitleRecord', pTitleRecord, 'pSandbox', pSandbox, 'pSuppressConsolStrings', pSuppressConsolStrings, 'pCubeNameExport', pCubeNameExport\r\n );\r\n \t nThreadElCounter = 0;\r\n \t sFilter = '';\r\n \t sFileName = '';\r\n \t ENDIF;\r\n End;\r\n ## Process last elements - only when filter is not empty (there are still elements)\r\n IF( sFilter @<> '' );\r\n sFileName = Expand('%sFileName%%sExt%');\r\n RunProcess( cThisProcName, 'pLogoutput', pLogoutput,\r\n \t'pCube', pCube, 'pView', '',\r\n \t'pFilter', sFilter, 'pFilterParallel', '',\r\n \t'pDimDelim', pDimDelim, 'pEleStartDelim', pEleStartDelim, 'pEleDelim', pEleDelim,\r\n \t'pSuppressZero', pSuppressZero, 'pSuppressConsol', pSuppressConsol, 'pSuppressRules', pSuppressRules,\r\n \t'pZeroSource', pZeroSource, 'pCubeLogging', pCubeLogging,\r\n \t'pTemp', pTemp, 'pFilePath', pFilePath, 'pFileName', sFileName,\r\n \t'pDelim', pFieldDelim, 'pDecimalSeparator', pDecimalSeparator, 'pThousandSeparator', pThousandSeparator,\r\n 'pQuote', pQuote, 'pTitleRecord', pTitleRecord, 'pSandbox', pSandbox, 'pSuppressConsolStrings', pSuppressConsolStrings, 'pCubeNameExport', pCubeNameExport\r\n );\r\n ENDIF;\r\n DataSourceType = 'NULL';\r\n nParallelRun = 1;\r\nElse;\r\n # No parallelization is being used. Proceed as normal and do everything internally\r\n\r\n # Determine number of dims in source cube & create strings to expand on title and rows\r\n nCount = 1;\r\n nDimensionIndex = 0;\r\n\r\n ## Skip cube name from export\r\n IF (pCubeNameExport = 0);\r\n sTitle = '';\r\n sRow = '';\r\n\r\n While( TabDim( pCube, nCount ) @<> '' );\r\n sDimension = TabDim( pCube, nCount );\r\n\r\n ## Determine title string for the source cube\r\n sTitle = sTitle|'%pQuote%'|sDimension|'%pQuote%%pFieldDelim%';\r\n # Determine row string for the source cube\r\n sRow = sRow|'%pQuote%%V'| numbertostring(nCount) |'%%pQuote%%pFieldDelim%';\r\n\r\n nCount = nCount + 1;\r\n End;\r\n nDimensionCount = nCount - 1;\r\n\r\n # Finish off the strings\r\n sTitle = sTitle|'%pQuote%Value%pQuote%';\r\n sRow = sRow|'%pQuote%%sValue%%pQuote%';\r\n\r\n ELSE;\r\n sTitle = '%pQuote%Cube%pQuote%';\r\n sRow = '%pQuote%%pCube%%pQuote%';\r\n\r\n While( TabDim( pCube, nCount ) @<> '' );\r\n sDimension = TabDim( pCube, nCount );\r\n\r\n ## Determine title string for the source cube\r\n sTitle = sTitle|'%pFieldDelim%%pQuote%'|sDimension|'%pQuote%';\r\n # Determine row string for the source cube\r\n sRow = sRow|'%pFieldDelim%%pQuote%%V'| numbertostring(nCount) |'%%pQuote%';\r\n\r\n nCount = nCount + 1;\r\n End;\r\n nDimensionCount = nCount - 1;\r\n\r\n # Finish off the strings\r\n sTitle = sTitle|'%pFieldDelim%%pQuote%Value%pQuote%';\r\n sRow = sRow|'%pFieldDelim%%pQuote%%sValue%%pQuote%';\r\n ENDIF;\r\n\r\n # Create Processing View for source version\r\n nRet = ExecuteProcess('}bedrock.cube.view.create',\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCube,\r\n 'pView', cView,\r\n 'pFilter', pFilter,\r\n 'pSuppressZero', pSuppressZero,\r\n 'pSuppressConsol', pSuppressConsol,\r\n 'pSuppressRules', pSuppressRules,\r\n 'pSuppressConsolStrings', pSuppressConsolStrings,\r\n 'pIncludeDescendants',pIncludeDescendants,\r\n 'pDimDelim', pDimDelim,\r\n 'pEleStartDelim', pEleStartDelim,\r\n 'pEleDelim', pEleDelim,\r\n 'pTemp', pTemp,\r\n 'pSubN', pSubN\r\n );\r\n\r\n # Validate Sandbox\r\n If( TRIM( pSandbox ) @<> '' );\r\n If( ServerSandboxExists( pSandbox ) = 0 );\r\n SetUseActiveSandboxProperty( 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand('Sandbox %pSandbox% is invalid for the current user.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n Else;\r\n ServerActiveSandboxSet( pSandbox );\r\n SetUseActiveSandboxProperty( 1 );\r\n EndIf;\r\n Else;\r\n SetUseActiveSandboxProperty( 0 );\r\n EndIf;\r\n\r\n\r\n IF( nRet <> ProcessExitNormal() );\r\n sMessage = 'Error creating the view from the filter.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n\r\n sParsedFilter = sBedrockViewCreateParsedFilter;\r\n sFilterRow = '%pQuote%%pCube%%pQuote%%pFieldDelim%%pQuote%Filter%pQuote%%pFieldDelim%%pQuote%%sParsedFilter%%pQuote%%pFieldDelim%%pQuote%%pDimDelim%%pQuote%%pFieldDelim%%pQuote%%pEleStartDelim%%pQuote%%pFieldDelim%%pQuote%%pEleDelim%%pQuote%';\r\n\r\n # Assign Datasource\r\n DataSourceType = 'VIEW';\r\n DatasourceNameForServer = pCube;\r\n DatasourceNameForClient = pCube;\r\n DatasourceCubeView = cView;\r\n DatasourceAsciiDelimiter= pFieldDelim;\r\n DatasourceAsciiQuoteCharacter = '';\r\n nParallelRun = 0;\r\nEndIf;\r\n\r\n### End Prolog ###", "MetadataProcedure": "#****Begin: Generated Statements***\r\n#****End: Generated Statements****", "DataProcedure": "#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n#################################################################################################\r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n#################################################################################################\r\n\r\n# Set the output character set\r\nSetOutputCharacterSet( cExportFile, pCharacterSet );\r\n\r\n### Data Count ###\r\nnDataCount = nDataCount + 1;\r\n\r\n# Output the title string\r\nIF( nDataCount = 1 & pTitleRecord >= 1 );\r\n TextOutput( cExportFile, Expand(sTitle) );\r\nEndif;\r\n\r\n### Export filter into the 1st record of the file, it will be used from import process to zero out the corresponding slice, if specified\r\nIF( nDataCount = 1 & pTitleRecord = 2 );\r\n TextOutput( cExportFile, Expand(sFilterRow) );\r\nEndif;\r\n\r\n### Export data from source version to file ###\r\nIf( value_is_string = 0 );\r\n sValue = NumberToStringEx( nValue, '#,0.#############', sDecimalSeparator, sThousandSeparator );\r\nEndIf;\r\n\r\n# Selects the correct TextOutput formula depending upon the number of dimensions in the cube\r\nIF(SCAN( CHAR( 10 ), sValue ) > 0 );\r\n sValueCleaned = '';\r\n nNoChar = 1;\r\n nLimit = LONG( sValue );\r\n WHILE( nNoChar <= nLimit ) ;\r\n sChar = SUBST( sValue, nNoChar, 1 );\r\n IF( CODE( sChar, 1 ) <> 10 );\r\n sValueCleaned = sValueCleaned | sChar ;\r\n ELSE;\r\n sValueCleaned = sValueCleaned | ' ';\r\n ENDIF;\r\n nNoChar = nNoChar + 1;\r\n END;\r\n sValue = sValueCleaned;\r\nENDIF;\r\n\r\n# Output data\r\nTextOutput( cExportFile, Expand(sRow) );\r\n\r\n### End Data ###", "EpilogProcedure": "#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n#################################################################################################\r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n#################################################################################################\r\n\r\n### Delete source data ###\r\nIf( pZeroSource = 1 & nErrors = 0 & nParallelRun = 0 );\r\n ViewZeroOut( pCube, cView );\r\nEndIf;\r\n\r\n### Return code & final error message handling\r\nIf( nErrors > 0 );\r\n sMessage = 'the process incurred at least 1 error. Please see above lines in this file for more details.';\r\n nProcessReturnCode = 0;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% Process:%cThisProcName% completed with errors. Check tm1server.log for details.' );\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n EndIf;\r\nElse;\r\n sDataCount = NUMBERTOSTRING (nDataCount);\r\n sProcessAction = Expand( 'Process:%cThisProcName% exported %sDataCount% records from %pCube% based on filter %pFilter%.' );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% %sProcessAction%' );\r\n nProcessReturnCode = 1;\r\n If( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( sProcessAction ) );\r\n EndIf;\r\n\r\nEndIf ;\r\n\r\n### End Epilog ###", "HasSecurityAccess": true, - "UIData": "_ParameterConstraints=e30=\f", + "UIData": "", "DataSource": { "Type": "TM1CubeView", "dataSourceNameForClient": "}APQ Staging TempSource", @@ -13,18 +13,6 @@ "view": "}TI_Dummy_View" }, "Parameters": [ - { - "Name": "pLogoutput", - "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, - { - "Name": "pStrictErrorHandling", - "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, { "Name": "pCube", "Prompt": "REQUIRED: Cube name", @@ -39,153 +27,171 @@ }, { "Name": "pFilter", - "Prompt": "OPTIONAL: Filter: Year\u00a6 2006 + 2007 & Scenario\u00a6 Actual + Budget & Organization\u00a6 North America Operations (Blank=whole cube)", + "Prompt": "OPTIONAL: Filter on cube in format: 'dim_one\u00a6 el_one + el_two & dim_two\u00a6 el_one + el_two'", "Value": "", "Type": "String" }, { "Name": "pFilterParallel", - "Prompt": "OPTIONAL: Parallelization Filter: Month:Q1+Q2+Q3+Q4 (Blank=run single threaded). Single dimension parallel slices. Will be added to filter single element at a time. Dimension must not be part of filter", + "Prompt": "OPTIONAL: Parallelization filter in format: dim_one\u00a6 el_one + el_two. Dimension must not be part of filter", "Value": "", "Type": "String" }, { "Name": "pParallelThreads", - "Prompt": "OPTIONAL: Maximum number of threads to run when parallel processing is enabled ( if <2 will execute one thread, but parallel filter is still applied )", + "Prompt": "OPTIONAL: Maximum number of threads to run when parallel processing is enabled (Default = 0)", "Value": 0, "Type": "Numeric" }, { "Name": "pDimDelim", - "Prompt": "OPTIONAL: Delimiter between dimensions (default value if blank = '&')", + "Prompt": "OPTIONAL: Delimiter for start of dimension/element set in filter parameters (Default = '&')", "Value": "&", "Type": "String" }, { "Name": "pEleStartDelim", - "Prompt": "OPTIONAL: Delimiter for start of element list (default value if blank = '\u00a6')", + "Prompt": "OPTIONAL: Delimiter for start of element list in filter parameters (Default = '\u00a6')", "Value": "\u00a6", "Type": "String" }, { "Name": "pEleDelim", - "Prompt": "OPTIONAL: Delimiter between elements (default value if blank = '+')", + "Prompt": "OPTIONAL: Delimiter between elements in filter parameters (Default = '+')", "Value": "+", "Type": "String" }, { "Name": "pSuppressZero", - "Prompt": "OPTIONAL: Suppress Zero Values (1=Suppress)", + "Prompt": "OPTIONAL: Suppress zeroes (Boolean. Default = 1)", "Value": 1, "Type": "Numeric" }, { "Name": "pSuppressConsol", - "Prompt": "OPTIONAL: Suppress Consolidated Values? (1=Suppress)", + "Prompt": "OPTIONAL: Suppress consolidated values (Boolean. Default = 1)", "Value": 1, "Type": "Numeric" }, { "Name": "pSuppressRules", - "Prompt": "OPTIONAL: Suppress Rule Values? (1=Suppress)", + "Prompt": "OPTIONAL: Suppress rules (Boolean. Default = 1)", "Value": 1, "Type": "Numeric" }, { "Name": "pSuppressConsolStrings", - "Prompt": "OPTIONAL: Suppress Strings on Consolidations (Skip = 1) (Default = 0)", - "Value": 0, + "Prompt": "OPTIONAL: Suppress consolidated string cells (Boolean. Default = 1)", + "Value": 1, "Type": "Numeric" }, { "Name": "pIncludeDescendants", - "Prompt": "", + "Prompt": "OPTIONAL: Include all descendants when source has consolidations (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" }, { "Name": "pZeroSource", - "Prompt": "OPTIONAL: Zero Out view AFTER Copy? (Boolean 1=True)", + "Prompt": "OPTIONAL: Zero out source after end of process (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" }, { "Name": "pTemp", - "Prompt": "OPTIONAL: Retain temporary view and Subset ( 0 = retain View and Subsets 1 = use temp objects)", + "Prompt": "OPTIONAL: Delete/create temporary objects (0 = Do not delete, 1 = Delete, 2 = if view and subsets are created, keep only subsets)", "Value": 1, "Type": "Numeric" }, { "Name": "pFilePath", - "Prompt": "OPTIONAL: Export Directory (will default to error file path)", + "Prompt": "OPTIONAL: File directory (Default = GetProcessErrorFileDirectory)", "Value": "", "Type": "String" }, { "Name": "pFileName", - "Prompt": "OPTIONAL: Export Filename (If Left Blank Defaults to cube_export.csv)", + "Prompt": "OPTIONAL: File name (Default = pCube | '_Export.csv')", "Value": "", "Type": "String" }, { "Name": "pDelim", - "Prompt": "OPTIONAL: AsciiOutput delimiter character (Default = ',' exactly 3 digits = ASCII code)", - "Value": ",", + "Prompt": "OPTIONAL: Delimiter for list parameters (Default = '&')", + "Value": "&", "Type": "String" }, { "Name": "pDecimalSeparator", - "Prompt": "OPTIONAL: Decimal separator for conversion of number to string and string to number (default = '.' exactly 3 digits = ASCII code)", + "Prompt": "OPTIONAL: Decimal separator for string/number conversion (Exactly 3 digits = ASCII code. Default ='.')", "Value": ".", "Type": "String" }, { "Name": "pThousandSeparator", - "Prompt": "OPTIONAL: Thousand separator for conversion of number to string and string to number (default = ',' exactly 3 digits = ASCII code)", + "Prompt": "OPTIONAL: Thousand separator for string/number conversion (Exactly 3 digits = ASCII code. Default = ',')", "Value": ",", "Type": "String" }, { "Name": "pQuote", - "Prompt": "OPTIONAL: AsciiOutput quote character (Accepts empty quote, exactly 3 digits = ASCII code)", + "Prompt": "OPTIONAL: Quote character (2 or 3 digits = ASCII code. Default = '\"')", "Value": "\"", "Type": "String" }, { "Name": "pTitleRecord", - "Prompt": "OPTIONAL: Include Title Record in Export File? (Boolean 0=false, 1=true, 2=title and filter line Default=1)", + "Prompt": "OPTIONAL: Delete temporary view and subsets (0 = Retain View and Subsets, 1 = Delete View and Subsets, 2 = Delete View only. Default = 1)", "Value": 1, "Type": "Numeric" }, { "Name": "pSandbox", - "Prompt": "OPTIONAL: To use sandbox not base data enter the sandbox name (invalid name will result in process error)", + "Prompt": "OPTIONAL: Use sandbox", "Value": "", "Type": "String" }, { "Name": "pSubN", - "Prompt": "OPTIONAL: Create N level subset for all dims not mentioned in pFilter (default=0)", + "Prompt": "OPTIONAL: Create N level subset for all dims not specified (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" }, { "Name": "pCharacterSet", - "Prompt": "OPTIONAL: The output character set (defaults to TM1CS_UTF8 if blank)", - "Value": "", + "Prompt": "OPTIONAL: The output character set (Default = 'TM1CS_UTF8')", + "Value": "TM1CS_UTF8", "Type": "String" }, { "Name": "pCubeNameExport", - "Prompt": "OPTIONAL: Skip cube name from export file, including header (Skip = 0) (Default = 1)", + "Prompt": "OPTIONAL: Export cube name and header to export file (Boolean. Default = 1)", "Value": 1, "Type": "Numeric" }, + { + "Name": "pLogOutput", + "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pStrictErrorHandling", + "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, { "Name": "pCubeLogging", "Prompt": "OBSOLETE: This parameter does nothing and is only included for backwards compatability", "Value": 0, "Type": "Numeric" + }, + { + "Name": "pJson", + "Prompt": "OPTIONAL: JSON Object with process parameter values. This will overwrite user passed parameters for all included parameters.", + "Value": "{}", + "Type": "String" } ], "Variables": [ diff --git a/bedrock_processes_json/}bedrock.cube.data.hold.json b/bedrock_processes_json/}bedrock.cube.data.hold.json index cd319a6..82d3249 100644 --- a/bedrock_processes_json/}bedrock.cube.data.hold.json +++ b/bedrock_processes_json/}bedrock.cube.data.hold.json @@ -1,6 +1,6 @@ { "Name": "}bedrock.cube.data.hold", - "PrologProcedure": "#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.data.hold', 'pLogOutput', pLogOutput, 'pStrictErrorHandling', pStrictErrorHandling, \r\n 'pMode', 'C / D / R / X / M', 'pCube', '', 'pClient', '', 'pGroup', '', 'pDelim', '&', 'pDir', '', 'pSkipNonExistentHoldsCubes', 1 );\r\nEndIf;\r\n\r\n#################################################################################################\r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n#################################################################################################\r\n\r\n# Description:\r\n# This TI process can manage TM1 cube holds. Holds are a personal tool for a TM1 user in any TM1 client.\r\n# A hold by client A does not restrict data entry by client B.\r\n# A client needs write access to a cell in order to apply a hold to the cell.\r\n# Existing Bedrock processes are leveraged including their default parameter values.\r\n#\r\n# Use case: Intended for development/prototyping or in Production environment.\r\n# - When a user has applied holds and logs off (or is forced to log off), the holds are lost (even though the Holds cube still exists)\r\n# - When the TM1 model is restarted, all holds are lost (even though the Holds cube still exists)\r\n# - The customer could provide a set of holds to be applied, in several cubes and to several clients and even data entry groups of clients. Applying the holds manually would be tedious.\r\n# - A regular clean up of Holds cubes that are out of date could be wise\r\n#\r\n# Parameters:\r\n# - pLogOutput (standard Bedrock parameter, Boolean True = 1)\r\n# - pStrictErrorHandling (standard Bedrock parameter, Boolean True = 1)\r\n# - pMode (see below). It should be one of: C / D / R / X / M\r\n# - pCube (mandatory). Provide the base cuube name(s), not the Holds cube names! It could be a combination of:\r\n# * multiple cubes separated with pDelim\r\n# * wildcards * and ?\r\n# * the keyword MODELCUBES (the cubes excluding the control cubes)\r\n# - pClient (mandatory or used in conjunction with pGroup). It could be a combination of:\r\n# * multiple clients separated with pDelim\r\n# * wildcards * and ?\r\n# * the keyword MYSELF (the client running this TI process)\r\n# - pGroup (mandatory or used in conjunction with pClient). It could be a combination of:\r\n# * multiple clients separated with pDelim\r\n# * wildcards * and ?\r\n# * the keyword MYGROUPS (the groups that the client running this TI process is a member of)\r\n# - pDelim (standard Bedrock parameter to manage above lists, default value if blank = '&')\r\n# - pDir (only used when exporting or importing flat files. If empty, the error file directory is used. If not existing, an error is returned.)\r\n# - pSkipNonExistentHoldsCubes (not used for mode C) (When using lists and wildcards, it can lead to non-existent holds cubes. Use 1 to skip silently.\r\n#\r\n# Supported functionality related to holds, given the selections made:\r\n# - pMode = C: creation of a holds cube\r\n# - pMode = D: destruction of a holds cube\r\n# - pMode = R: release all holds\r\n# - pMode = X: export of holds to text files\r\n# - pMode = M: import of holds from text files (either new holds to be set, either holds exported earlier)\r\n#\r\n# Note:\r\n# - When exporting holds, the file format will respect the default values of the Bedrock process to export data. The file name is '}Hold_[ClientName]_}}_[CubeName].csv so it matches the Holds cubename.\r\n# - To import holds, the file format needs to respect the default values of the Bedrock process to import data. The file name is '}Hold_[ClientName]_}}_[CubeName].csv so it matches the Holds cubename.\r\n# - When importing holds, the cell value needs to be either H or C\r\n# * A value of C is to be put in a consolidated cell of the Holds cube\r\n# * A value of H is to be put in a level 0 cell of the Holds cube\r\n# * Any other combination will not lead to an error but TM1 will not apply the hold as intended\r\n# * String cells should not be used in data holds\r\n# - When importing holds, an additional zeroout should be done with a call to this process with mode 'R'\r\n# - The selections for pClient and pGroup will lead to a list of unique clients, to which the selected mode is applied\r\n# For a group, the members in the group are retrieved, and added to the selected client(s).\r\n# - At least 1 client should be returned from the provided parameter values, if not the process will abort\r\n# - No support for PAW alternate hierarchies\r\n#\r\n###########################################################\r\n\r\n##Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode = 0;\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSub = cThisProcName |'_'| cTimeStamp |'_'| cRandomInt;\r\ncUserName = TM1User;\r\ncHoldsCube = '}Hold_%sClient%_}}_%sCube%';\r\ncMsrDim = '}Hold';\r\nnCubes = 0;\r\nnDimMax = 100;\r\nnErrors = 0;\r\nsMessage = '';\r\ncUserName = TM1User();\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pCube:%pCube%, pClient:%pClient%, pGroup:%pGroup%, pDelim:%pDelim%, pMode:%pMode%, pDir:%pDir%, pSkipNonExistentHoldsCubes:%pSkipNonExistentHoldsCubes%.' ;\r\n\r\n\r\n## LogOutput parameters\r\nIF( pLogOutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) );\r\nENDIF;\r\n\r\n### Validate Parameters ###\r\nnErrors = 0;\r\n\r\n## Validate the Cube parameter\r\nIf( TRIM(pCube) @= '' );\r\n sMessage = 'A cube name must be provided.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# If no clients and groups have been specified then terminate process\r\nIf( Trim( pClient ) @= '' & Trim( pGroup ) @= '' );\r\n nErrors = 1;\r\n sMessage = 'No clients and groups specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# The mode is a restricted list of actions\r\nIf( pMode @<> 'C'\r\n & pMode @<> 'D'\r\n & pMode @<> 'R'\r\n & pMode @<> 'X'\r\n & pMode @<> 'M' );\r\n nErrors = 1;\r\n sMessage = Expand( 'Incorrect value for pMode: %pMode%. Valid values are: C, D, R, X, M.' );\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElse;\r\n pMode = Upper( Trim( pMode ));\r\nEndIf;\r\n\r\n# If blank delimiter specified then convert to default\r\nIf( pDelim @= '' );\r\n pDelim = '&';\r\nEndIf;\r\n\r\n# Skipping non-existent holds cubes\r\nIf( pSkipNonExistentHoldsCubes <> 1 );\r\n pSkipNonExistentHoldsCubes = 0;\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n\r\n\r\n# # # # # # # # # # SEARCH FOR CUBES BY INSPECTING CUBE PARAMETER\r\n# - pCube (mandatory). It could be a combination of:\r\n# * multiple cubes separated with pDelim\r\n# * wildcards * and ?\r\n# * the keyword MODELCUBES (the cubes excluding the control cubes)\r\n\r\n### Split parameter into individual cubes and store in a temporary subset ###\r\nSubsetCreate( '}Cubes', 'Cubes subset', 1 );\r\n\r\nsCubes = pCube;\r\nnDelimiterIndex = 1;\r\nWhile( nDelimiterIndex <> 0 );\r\n nDelimiterIndex = Scan( pDelim, sCubes );\r\n If( nDelimiterIndex = 0 );\r\n sCube = sCubes;\r\n Else;\r\n sCube = Trim( SubSt( sCubes, 1, nDelimiterIndex - 1 ) );\r\n sCubes = Trim( Delet( sCubes, 1, nDelimiterIndex + Long(pDelim) ) );\r\n EndIf;\r\n\r\n If( sCube @<> '' );\r\n # Create subset of cubes. Wildcards could be involved.\r\n\r\n If( sCube @= 'MODELCUBES' );\r\n sMDX = '{Except( TM1SubsetAll( [}Cubes] ), TM1FilterByPattern( TM1SubsetAll( [}Cubes] ), \"}*\" ))}';\r\n Else;\r\n sMDX = '{TM1FilterByPattern( TM1SubsetAll( [}Cubes] ), \"' | sCube | '\" )}';\r\n EndIf;\r\n\r\n If( SubsetExists( '}Cubes', cTempSub ) = 1 );\r\n # If a delimited list of cube names includes wildcards then we may have to re-use the subset multiple times\r\n SubsetMDXSet( '}Cubes', cTempSub, sMDX );\r\n Else;\r\n # temp subset, therefore no need to destroy in the Epilog tab\r\n SubsetCreatebyMDX( cTempSub, sMDX, '}Cubes', 1 );\r\n EndIf;\r\n\r\n # Loop through the returned cubes, if any\r\n nCountCubes = 1;\r\n While( nCountCubes <= SubsetGetSize( '}Cubes', cTempSub ) );\r\n sCurrCube = SubsetGetElementName( '}Cubes', cTempSub, nCountCubes );\r\n # Validate cube name\r\n If( CubeExists( sCurrCube ) = 1 );\r\n If( SubsetElementExists( '}Cubes', 'Cubes subset', sCurrCube ) = 0 );\r\n SubsetElementInsert( '}Cubes', 'Cubes subset', sCurrCube, 0 );\r\n EndIf;\r\n EndIf;\r\n nCountCubes = nCountCubes + 1;\r\n End;\r\n EndIf;\r\n\r\nEnd;\r\n\r\n# If no cubes found\r\nnFoundCubesCount = SubsetGetSize( '}Cubes', 'Cubes subset' );\r\nIf( nFoundCubesCount = 0 );\r\n nErrors = 1;\r\n sMessage = 'No cubes found after processing pCube.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElse;\r\n If( pLogOutput = 1 );\r\n sMessage = 'Number of cubes found that match pCube: ' | NumberToString( nFoundCubesCount );\r\n LogOutput('INFO', Expand( sMessage ) );\r\n EndIf;\r\nEndIf;\r\n\r\n\r\n# # # # # # # # # # SEARCH FOR CLIENTS BY INSPECTING CLIENTS AND GROUPS PARAMETERS\r\n# - pClient (mandatory or used in conjunction with pGroup). It could be a combination of:\r\n# * multiple clients separated with pDelim\r\n# * wildcards * and ?\r\n# * the keyword MYSELF (the client running this TI process)\r\n\r\n# - pGroup (mandatory or used in conjunction with pClient). It could be a combination of:\r\n# * multiple clients separated with pDelim\r\n# * wildcards * and ?\r\n# * the keyword MYGROUPS (the groups that the client running this TI process is a member of)\r\n\r\n### Split parameter into individual clients and store in a temporary subset ###\r\nSubsetCreate( '}Clients', 'Clients subset', 1 );\r\n\r\nsClients = pClient;\r\nnDelimiterIndex = 1;\r\nWhile( nDelimiterIndex <> 0 );\r\n nDelimiterIndex = Scan( pDelim, sClients );\r\n If( nDelimiterIndex = 0 );\r\n sClient = sClients;\r\n Else;\r\n sClient = Trim( SubSt( sClients, 1, nDelimiterIndex - 1 ) );\r\n sClients = Trim( Delet( sClients, 1, nDelimiterIndex + Long(pDelim) ) );\r\n EndIf;\r\n\r\n If( sClient @<> '' );\r\n\r\n If( sClient @= 'MYSELF' );\r\n sClient = cUserName;\r\n EndIf;\r\n\r\n # Create subset of clients using Wildcard. Wildcards could be involved.\r\n sMDX = '{TM1FilterByPattern( TM1SubsetAll( [}Clients] ), \"' | sClient | '\" )}';\r\n\r\n If( SubsetExists( '}Clients', cTempSub ) = 1 );\r\n # If a delimited list of client names includes wildcards then we may have to re-use the subset multiple times\r\n SubsetMDXSet( '}Clients', cTempSub, sMDX );\r\n Else;\r\n # temp subset, therefore no need to destroy in the Epilog tab\r\n SubsetCreatebyMDX( cTempSub, sMDX, '}Clients', 1 );\r\n EndIf;\r\n\r\n # Loop through the returned clients, if any\r\n nCountClients = 1;\r\n While( nCountClients <= SubsetGetSize( '}Clients', cTempSub ) );\r\n sCurrClient = SubsetGetElementName( '}Clients', cTempSub, nCountClients );\r\n # Validate client name\r\n If( Dimix( '}Clients', sCurrClient ) > 0 );\r\n If( SubsetElementExists( '}Clients', 'Clients subset', sCurrClient ) = 0 );\r\n SubsetElementInsert( '}Clients', 'Clients subset', sCurrClient, 0 );\r\n EndIf;\r\n EndIf;\r\n nCountClients = nCountClients + 1;\r\n End;\r\n EndIf;\r\n\r\nEnd;\r\n\r\n\r\n### Split parameter into individual groups and store in a temporary subset ###\r\nSubsetCreate( '}Groups', 'Groups subset', 1 );\r\n\r\nsGroups = pGroup;\r\nnDelimiterIndex = 1;\r\nWhile( nDelimiterIndex <> 0 );\r\n nDelimiterIndex = Scan( pDelim, sGroups );\r\n If( nDelimiterIndex = 0 );\r\n sGroup = sGroups;\r\n Else;\r\n sGroup = Trim( SubSt( sGroups, 1, nDelimiterIndex - 1 ) );\r\n sGroups = Trim( Delet( sGroups, 1, nDelimiterIndex + Long(pDelim) ) );\r\n EndIf;\r\n\r\n If( sGroup @<> '' );\r\n # Create subset of groups. Wildcards could be involved.\r\n\r\n If( sGroup @= 'MYGROUPS' );\r\n sMDX = '{Filter( TM1SubsetAll( [}Groups] ), [}ClientGroups].( [}Clients].[' | cUserName | '] ) <> \"\" )}';\r\n Else;\r\n sMDX = '{TM1FilterByPattern( TM1SubsetAll( [}Groups] ), \"' | sGroup | '\" )}';\r\n EndIf;\r\n\r\n If( SubsetExists( '}Groups', cTempSub ) = 1 );\r\n # If a delimited list of group names includes wildcards then we may have to re-use the subset multiple times\r\n SubsetMDXSet( '}Groups', cTempSub, sMDX );\r\n Else;\r\n # temp subset, therefore no need to destroy in the Epilog tab\r\n SubsetCreatebyMDX( cTempSub, sMDX, '}Groups', 1 );\r\n EndIf;\r\n\r\n # Loop through the returned groups, if any\r\n nCountGroups = 1;\r\n While( nCountGroups <= SubsetGetSize( '}Groups', cTempSub ) );\r\n sCurrGroup = SubsetGetElementName( '}Groups', cTempSub, nCountGroups );\r\n # Validate group name\r\n If( Dimix( '}Groups', sCurrGroup ) > 0 );\r\n If( SubsetElementExists( '}Groups', 'Groups subset', sCurrGroup ) = 0 );\r\n SubsetElementInsert( '}Groups', 'Groups subset', sCurrGroup, 0 );\r\n EndIf;\r\n EndIf;\r\n nCountGroups = nCountGroups + 1;\r\n End;\r\n EndIf;\r\n\r\nEnd;\r\nnFoundGroupsCount = SubsetGetSize( '}Groups', 'Groups subset' );\r\n\r\n\r\n# Now rework groups into their clients through the security memberships\r\nIf( nFoundGroupsCount > 0 );\r\n\r\n # Create subset of clients using Wildcard. Wildcards could be involved.\r\n sMDX = 'Generate( TM1SubsetToSet([}Groups], \"Groups subset\" ), Filter( TM1SubsetAll([}Clients]), [}ClientGroups].([}Groups].CurrentMember) <> \"\" ))';\r\n If( SubsetExists( '}Clients', cTempSub ) = 1 );\r\n SubsetMDXSet( '}Clients', cTempSub, sMDX );\r\n Else;\r\n SubsetCreatebyMDX( cTempSub, sMDX, '}Clients', 1 );\r\n EndIf;\r\n\r\n # Loop through the returned clients, if any\r\n nCountClients = 1;\r\n While( nCountClients <= SubsetGetSize( '}Clients', cTempSub ) );\r\n sCurrClient = SubsetGetElementName( '}Clients', cTempSub, nCountClients );\r\n If( SubsetElementExists( '}Clients', 'Clients subset', sCurrClient ) = 0 );\r\n SubsetElementInsert( '}Clients', 'Clients subset', sCurrClient, 0 );\r\n EndIf;\r\n nCountClients = nCountClients + 1;\r\n End;\r\nEndIf;\r\n\r\n\r\n# If no clients found\r\nnFoundClientsCount = SubsetGetSize( '}Clients', 'Clients subset' );\r\nIf( nFoundClientsCount = 0 );\r\n nErrors = 1;\r\n sMessage = 'No clients found after processing pClient and pGroup.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElse;\r\n If( pLogOutput = 1 );\r\n sMessage = 'Number of clients found that match pClient and pGroup: ' | NumberToString( nFoundClientsCount );\r\n LogOutput('INFO', Expand( sMessage ) );\r\n EndIf;\r\nEndIf;\r\n\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n\r\n# A double loop over cubes and clients to apply the selected action\r\nnCountCubes = 1;\r\nWhile( nCountCubes <= nFoundCubesCount );\r\n sCube = SubsetGetElementName( '}Cubes', 'Cubes subset', nCountCubes );\r\n nCubeDimCount = CubeDimensionCountGet( sCube );\r\n\r\n nCountClients = 1;\r\n While( nCountClients <= nFoundClientsCount );\r\n sClient = SubsetGetElementName( '}Clients', 'Clients subset', nCountClients );\r\n\r\n sHoldsCube = Expand( cHoldsCube );\r\n\r\n\r\n If( pMode @= 'C' );\r\n\r\n\r\n # Create a Holds cube\r\n If( CubeExists( sHoldsCube ) = 1 );\r\n nErrors = 1;\r\n sMessage = Expand( 'The holds cube ''%sHoldsCube%'' already exists so it could not be created.' );\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n EndIf;\r\n\r\n If( nCubeDimCount > nDimMax );\r\n nErrors = 1;\r\n sMessage = Expand( 'The base cube ''%sCube%'' for the holds cube ''%sHoldsCube%'' contains too many dimensions. ' | NumberToString( nCubeDimCount ) | ' instead of at most ' | NumberToString( nDimMax ) | '.' );\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n EndIf;\r\n\r\n # Create a measures dimension\r\n If( DimensionExists( cMsrDim ) = 0 );\r\n If( pLogOutput = 1 );\r\n sMessage = Expand( 'The measures dimension for hold cubes (%cMsrDim%) does not exist and will be created.' );\r\n LogOutput('INFO', Expand( sMessage ) );\r\n EndIf;\r\n nRet = ExecuteProcess( '}bedrock.hier.create', 'pLogOutput', pLogOutput, 'pStrictErrorHandling', pStrictErrorHandling, 'pDim', cMsrDim );\r\n If( nRet <> 0 );\r\n sMessage = Expand( 'Error creating the dimension ''%cMsrDim%''.' );\r\n nErrors = 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n EndIf;\r\n DimensionElementInsert( cMsrDim, '', 'HoldStatus', 'S' );\r\n EndIf;\r\n\r\n # Get the dimension names for the hold cube\r\n sDims = '';\r\n d = 1;\r\n While( d <= nCubeDimCount );\r\n sDim = Tabdim( sCube, d );\r\n sDims = sDims | pDelim | sDim;\r\n d = d + 1;\r\n End;\r\n sDims = sDims | pDelim | cMsrDim;\r\n sDims = Delet( sDims, 1, Long( pDelim ));\r\n\r\n nRet = ExecuteProcess( '}bedrock.cube.create', 'pLogOutput', pLogOutput, 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', sHoldsCube, 'pDims', sDims, 'pRecreate', 0, 'pDelim', pDelim );\r\n If( nRet <> 0 );\r\n sMessage = Expand( 'Error creating the cube ''%sHoldsCube%''.' );\r\n nErrors = 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n EndIf;\r\n If( pLogOutput = 1 );\r\n sMessage = Expand( 'The holds cube ''%sHoldsCube%'' was created.' );\r\n LogOutput('INFO', Expand( sMessage ) );\r\n EndIf;\r\n\r\n\r\n ElseIf( pMode @= 'D' );\r\n\r\n\r\n # Destroy a Holds cube\r\n If( CubeExists( sHoldsCube ) = 0 );\r\n If( pSkipNonExistentHoldsCubes = 0 );\r\n # nErrors = 1;\r\n # sMessage = Expand( 'The holds cube ''%sHoldsCube%'' does not exist so it could not be destroyed.' );\r\n # LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n # If( pStrictErrorHandling = 1 );\r\n # ProcessQuit;\r\n # Else;\r\n # ProcessBreak;\r\n # EndIf;\r\n If( pLogOutput = 1 );\r\n sMessage = Expand( 'The holds cube ''%sHoldsCube%'' does not exist so it could not be destroyed.' );\r\n LogOutput('INFO', Expand( sMessage ) );\r\n EndIf;\r\n EndIf;\r\n Else;\r\n\r\n CubeDestroy( sHoldsCube );\r\n If( pLogOutput = 1 );\r\n sMessage = Expand( 'The holds cube ''%sHoldsCube%'' was destroyed.' );\r\n LogOutput('INFO', Expand( sMessage ) );\r\n EndIf;\r\n EndIf;\r\n\r\n\r\n ElseIf( pMode @= 'R' );\r\n\r\n\r\n # In an existing Holds cube, delete all holds (Release)\r\n If( CubeExists( sHoldsCube ) = 0 );\r\n If( pSkipNonExistentHoldsCubes = 0 );\r\n nErrors = 1;\r\n sMessage = Expand( 'The holds cube ''%sHoldsCube%'' does not exist so all of its holds (if any) could not be released.' );\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n EndIf;\r\n Else;\r\n\r\n CubeClearData( sHoldsCube );\r\n # nRet = ExecuteProcess( '}bedrock.cube.data.clear', 'pLogOutput', pLogOutput, 'pStrictErrorHandling', pStrictErrorHandling,\r\n # 'pCube', sHoldsCube, 'pView', '', 'pFilter', '', 'pSuppressConsolStrings', 0, 'pCubeLogging', 2 );\r\n # If( nRet <> 0 );\r\n # sMessage = 'Error releasing all the holds in the cube ''%sHoldsCube%''.';\r\n # nErrors = 1;\r\n # LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n # If( pStrictErrorHandling = 1 );\r\n # ProcessQuit;\r\n # Else;\r\n # ProcessBreak;\r\n # EndIf;\r\n # EndIf;\r\n If( pLogOutput = 1 );\r\n sMessage = Expand( 'All the holds in the cube ''%sHoldsCube%'' were released.' );\r\n LogOutput('INFO', Expand( sMessage ) );\r\n EndIf;\r\n\r\n EndIf;\r\n\r\n\r\n ElseIf( pMode @= 'X' );\r\n\r\n\r\n # From an existing Holds cube, export all entries\r\n If( CubeExists( sHoldsCube ) = 0 );\r\n If( pSkipNonExistentHoldsCubes = 0 );\r\n nErrors = 1;\r\n sMessage = Expand( 'The holds cube ''%sHoldsCube%'' does not exist so all of its holds (if any) could not be exported.' );\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n EndIf;\r\n Else;\r\n\r\n If( nCubeDimCount > nDimMax );\r\n nErrors = 1;\r\n sMessage = Expand( 'The base cube ''%sCube%'' for the holds cube ''%sHoldsCube%'' contains too many dimensions. ' | NumberToString( nCubeDimCount ) | ' instead of at most ' | NumberToString( nDimMax ) | '.' );\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n EndIf;\r\n\r\n # the file directory (If empty, the error file directory is used. If not existing, an error is returned.)\r\n # this is done by the called Bedrock process\r\n # the file name is simply the Holds cube name with file extension csv\r\n sFileName = sHoldsCube | '.csv';\r\n nRet = ExecuteProcess( '}bedrock.cube.data.export', 'pLogOutput', pLogOutput, 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', sHoldsCube, 'pView', '', 'pFilter', '', 'pSuppressConsol', 0, 'pSuppressConsolStrings', 0,\r\n 'pCubeLogging', 2, 'pFilePath', pDir, 'pFileName', sFileName );\r\n If( nRet <> 0 );\r\n sMessage = Expand( 'Error exporting all the holds from the cube ''%sHoldsCube%'' to a flat file.' );\r\n nErrors = 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n EndIf;\r\n If( pLogOutput = 1 );\r\n sMessage = Expand( 'All the holds in the cube ''%sHoldsCube%'' were exported.' );\r\n LogOutput('INFO', Expand( sMessage ) );\r\n EndIf;\r\n EndIf;\r\n\r\n\r\n ElseIf( pMode @= 'M' );\r\n\r\n\r\n # To an existing Holds cube, import all entries\r\n # If the Holds cube does not exist, you need to create it first with mode C\r\n If( CubeExists( sHoldsCube ) = 0 );\r\n If( pSkipNonExistentHoldsCubes = 0 );\r\n nErrors = 1;\r\n sMessage = Expand( 'The holds cube ''%sHoldsCube%'' does not exist so holds (if any) could not be imported. You might want to create it first using mode ''C''.' );\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n EndIf;\r\n Else;\r\n\r\n # the file directory (If empty, the error file directory is used. If not existing, an error is returned.)\r\n # this is done by the called Bedrock process\r\n # the file name is simply the Holds cube name with file extension csv\r\n sFileName = sHoldsCube | '.csv';\r\n nRet = ExecuteProcess( '}bedrock.cube.data.import', 'pLogOutput', pLogOutput, 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', sHoldsCube, 'pSrcDir', pDir, 'pSrcFile', sFileName, 'pCubeLogging', 2, 'pFileDelete', 0, 'pSkipInvalidRecords', 0 );\r\n If( nRet <> 0 );\r\n sMessage = Expand( 'Error importing all the holds to the cube ''%sHoldsCube%'' from a flat file.' );\r\n nErrors = 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n EndIf;\r\n If( pLogOutput = 1 );\r\n sMessage = Expand( 'All the holds were imported to the cube ''%sHoldsCube%''.' );\r\n LogOutput('INFO', Expand( sMessage ) );\r\n EndIf;\r\n EndIf;\r\n EndIf;\r\n\r\n nCountClients = nCountClients + 1;\r\n End;\r\n\r\n nCountCubes = nCountCubes + 1;\r\nEnd;", + "PrologProcedure": "#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.data.hold', 'pLogOutput', pLogOutput, 'pStrictErrorHandling', pStrictErrorHandling, \r\n 'pMode', 'C / D / R / X / M', 'pCube', '', 'pClient', '', 'pGroup', '', 'pDelim', '&', 'pDir', '', 'pSkipNonExistentHoldsCubes', 1 );\r\nEndIf;\r\n\r\n#################################################################################################\r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n#################################################################################################\r\n\r\n# Description:\r\n# This TI process can manage TM1 cube holds. Holds are a personal tool for a TM1 user in any TM1 client.\r\n# A hold by client A does not restrict data entry by client B.\r\n# A client needs write access to a cell in order to apply a hold to the cell.\r\n# Existing Bedrock processes are leveraged including their default parameter values.\r\n#\r\n# Use case: Intended for development/prototyping or in Production environment.\r\n# - When a user has applied holds and logs off (or is forced to log off), the holds are lost (even though the Holds cube still exists)\r\n# - When the TM1 model is restarted, all holds are lost (even though the Holds cube still exists)\r\n# - The customer could provide a set of holds to be applied, in several cubes and to several clients and even data entry groups of clients. Applying the holds manually would be tedious.\r\n# - A regular clean up of Holds cubes that are out of date could be wise\r\n#\r\n# Parameters:\r\n# - pLogOutput (standard Bedrock parameter, Boolean True = 1)\r\n# - pStrictErrorHandling (standard Bedrock parameter, Boolean True = 1)\r\n# - pMode (see below). It should be one of: C / D / R / X / M\r\n# - pCube (mandatory). Provide the base cuube name(s), not the Holds cube names! It could be a combination of:\r\n# * multiple cubes separated with pDelim\r\n# * wildcards * and ?\r\n# * the keyword MODELCUBES (the cubes excluding the control cubes)\r\n# - pClient (mandatory or used in conjunction with pGroup). It could be a combination of:\r\n# * multiple clients separated with pDelim\r\n# * wildcards * and ?\r\n# * the keyword MYSELF (the client running this TI process)\r\n# - pGroup (mandatory or used in conjunction with pClient). It could be a combination of:\r\n# * multiple clients separated with pDelim\r\n# * wildcards * and ?\r\n# * the keyword MYGROUPS (the groups that the client running this TI process is a member of)\r\n# - pDelim (standard Bedrock parameter to manage above lists, default value if blank = '&')\r\n# - pDir (only used when exporting or importing flat files. If empty, the error file directory is used. If not existing, an error is returned.)\r\n# - pSkipNonExistentHoldsCubes (not used for mode C) (When using lists and wildcards, it can lead to non-existent holds cubes. Use 1 to skip silently.\r\n#\r\n# Supported functionality related to holds, given the selections made:\r\n# - pMode = C: creation of a holds cube\r\n# - pMode = D: destruction of a holds cube\r\n# - pMode = R: release all holds\r\n# - pMode = X: export of holds to text files\r\n# - pMode = M: import of holds from text files (either new holds to be set, either holds exported earlier)\r\n#\r\n# Note:\r\n# - When exporting holds, the file format will respect the default values of the Bedrock process to export data. The file name is '}Hold_[ClientName]_}}_[CubeName].csv so it matches the Holds cubename.\r\n# - To import holds, the file format needs to respect the default values of the Bedrock process to import data. The file name is '}Hold_[ClientName]_}}_[CubeName].csv so it matches the Holds cubename.\r\n# - When importing holds, the cell value needs to be either H or C\r\n# * A value of C is to be put in a consolidated cell of the Holds cube\r\n# * A value of H is to be put in a level 0 cell of the Holds cube\r\n# * Any other combination will not lead to an error but TM1 will not apply the hold as intended\r\n# * String cells should not be used in data holds\r\n# - When importing holds, an additional zeroout should be done with a call to this process with mode 'R'\r\n# - The selections for pClient and pGroup will lead to a list of unique clients, to which the selected mode is applied\r\n# For a group, the members in the group are retrieved, and added to the selected client(s).\r\n# - At least 1 client should be returned from the provided parameter values, if not the process will abort\r\n# - No support for PAW alternate hierarchies\r\n#\r\n###########################################################\r\n\r\n##Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode = 0;\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSub = cThisProcName |'_'| cTimeStamp |'_'| cRandomInt;\r\ncUserName = TM1User;\r\ncHoldsCube = '}Hold_%sClient%_}}_%sCube%';\r\ncMsrDim = '}Hold';\r\nnCubes = 0;\r\nnDimMax = 100;\r\nnErrors = 0;\r\nsMessage = '';\r\ncUserName = TM1User();\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pCube:%pCube%, pClient:%pClient%, pGroup:%pGroup%, pDelim:%pDelim%, pMode:%pMode%, pDir:%pDir%, pSkipNonExistentHoldsCubes:%pSkipNonExistentHoldsCubes%.' ;\r\n\r\n\r\n#################################################################################################\r\n#Region - Process Parameters\r\n\r\npJson = IF( JsonType( pJson ) @<> 'object', '{}', pJson );\r\nsMessages = '{\"Process\": \"'|GetProcessName()|'\", \"User\": \"'|TM1User()|'\", \"Info\": [\"Process: '''|GetProcessName()|''' run by User: '''|TM1User()|'''.\"], \"Error\": []}';\r\npDefaultParameters = '{\r\n \"pClient\": null,\r\n \"pCube\": null,\r\n \"pDelim\": \"&\",\r\n \"pDir\": \"\",\r\n \"pGroup\": null,\r\n \"pMode\": null,\r\n \"pLogOutput\": 0,\r\n \"pSkipNonExistentHoldsCubes\": 0,\r\n \"pStrictErrorHandling\": 0\r\n}';\r\n\r\npPassedParameters = '{\r\n \"pClient\": '|StringToJson ( pClient )|',\r\n \"pCube\": '|StringToJson ( pCube )|',\r\n \"pDelim\": '|StringToJson ( pDelim )|',\r\n \"pDir\": '|StringToJson ( pDir )|',\r\n \"pGroup\": '|StringToJson ( pGroup )|',\r\n \"pMode\": '|StringToJson ( pMode )|',\r\n \"pLogOutput\": '|NumberToString( pLogOutput )|',\r\n \"pSkipNonExistentHoldsCubes\": '|NumberToString( pSkipNonExistentHoldsCubes )|',\r\n \"pStrictErrorHandling\": '|NumberToString( pStrictErrorHandling )|'\r\n}';\r\n\r\npJson = JsonMergePatch( pPassedParameters, pJson );\r\n# String Parameters\r\npClient = JsonToString( JsonGet( pJson, 'pClient' ) );\r\npCube = JsonToString( JsonGet( pJson, 'pCube' ) );\r\npDelim = JsonToString( JsonGet( pJson, 'pDelim' ) );\r\npDir = JsonToString( JsonGet( pJson, 'pDir' ) );\r\npGroup = JsonToString( JsonGet( pJson, 'pGroup' ) );\r\npMode = JsonToString( JsonGet( pJson, 'pMode' ) );\r\n# Numeric Parameters\r\npLogOutput = StringToNumber( JsonToString( JsonGet( pJson, 'pLogOutput' ) ) );\r\npSkipNonExistentHoldsCubes = StringToNumber( JsonToString( JsonGet( pJson, 'pSkipNonExistentHoldsCubes' ) ) );\r\npStrictErrorHandling = StringToNumber( JsonToString( JsonGet( pJson, 'pStrictErrorHandling' ) ) );\r\n\r\n### Get the parameters that differ from the default\r\npDiffer = JsonDiff( pDefaultParameters, pJson );\r\nnSize = JsonSize( pDiffer );\r\nWHILE( nSize > 0 );\r\n nSize = nSize - 1;\r\n pDiffer = JsonReplace( pDiffer, '/'|NumberToString( nSize )|'/op', '\"add\"' );\r\nEND;\r\npJson = JsonPatch( '{}', pDiffer );\r\n\r\n### LogOutput parameters\r\nsMessages = JsonAdd( sMessages, '/Info/-', pJson );\r\nIF( pLogOutput = 1 );\r\n LogOutput('INFO', JsonToString( sMessages, '/Info/0', 0, ' ' ) );\r\nENDIF;\r\n\r\n#EndRegion - Process Parameters\r\n#################################################################################################\r\n\r\n## LogOutput parameters\r\nIF( pLogOutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) );\r\nENDIF;\r\n\r\n### Validate Parameters ###\r\nnErrors = 0;\r\n\r\n## Validate the Cube parameter\r\nIf( TRIM(pCube) @= '' );\r\n sMessage = 'A cube name must be provided.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# If no clients and groups have been specified then terminate process\r\nIf( Trim( pClient ) @= '' & Trim( pGroup ) @= '' );\r\n nErrors = 1;\r\n sMessage = 'No clients and groups specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# The mode is a restricted list of actions\r\nIf( pMode @<> 'C'\r\n & pMode @<> 'D'\r\n & pMode @<> 'R'\r\n & pMode @<> 'X'\r\n & pMode @<> 'M' );\r\n nErrors = 1;\r\n sMessage = Expand( 'Incorrect value for pMode: %pMode%. Valid values are: C, D, R, X, M.' );\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElse;\r\n pMode = Upper( Trim( pMode ));\r\nEndIf;\r\n\r\n# If blank delimiter specified then convert to default\r\nIf( pDelim @= '' );\r\n pDelim = '&';\r\nEndIf;\r\n\r\n# Skipping non-existent holds cubes\r\nIf( pSkipNonExistentHoldsCubes <> 1 );\r\n pSkipNonExistentHoldsCubes = 0;\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n\r\n\r\n# # # # # # # # # # SEARCH FOR CUBES BY INSPECTING CUBE PARAMETER\r\n# - pCube (mandatory). It could be a combination of:\r\n# * multiple cubes separated with pDelim\r\n# * wildcards * and ?\r\n# * the keyword MODELCUBES (the cubes excluding the control cubes)\r\n\r\n### Split parameter into individual cubes and store in a temporary subset ###\r\nSubsetCreate( '}Cubes', 'Cubes subset', 1 );\r\n\r\nsCubes = pCube;\r\nnDelimiterIndex = 1;\r\nWhile( nDelimiterIndex <> 0 );\r\n nDelimiterIndex = Scan( pDelim, sCubes );\r\n If( nDelimiterIndex = 0 );\r\n sCube = sCubes;\r\n Else;\r\n sCube = Trim( SubSt( sCubes, 1, nDelimiterIndex - 1 ) );\r\n sCubes = Trim( Delet( sCubes, 1, nDelimiterIndex + Long(pDelim) ) );\r\n EndIf;\r\n\r\n If( sCube @<> '' );\r\n # Create subset of cubes. Wildcards could be involved.\r\n\r\n If( sCube @= 'MODELCUBES' );\r\n sMDX = '{Except( TM1SubsetAll( [}Cubes] ), TM1FilterByPattern( TM1SubsetAll( [}Cubes] ), \"}*\" ))}';\r\n Else;\r\n sMDX = '{TM1FilterByPattern( TM1SubsetAll( [}Cubes] ), \"' | sCube | '\" )}';\r\n EndIf;\r\n\r\n If( SubsetExists( '}Cubes', cTempSub ) = 1 );\r\n # If a delimited list of cube names includes wildcards then we may have to re-use the subset multiple times\r\n SubsetMDXSet( '}Cubes', cTempSub, sMDX );\r\n Else;\r\n # temp subset, therefore no need to destroy in the Epilog tab\r\n SubsetCreatebyMDX( cTempSub, sMDX, '}Cubes', 1 );\r\n EndIf;\r\n\r\n # Loop through the returned cubes, if any\r\n nCountCubes = 1;\r\n While( nCountCubes <= SubsetGetSize( '}Cubes', cTempSub ) );\r\n sCurrCube = SubsetGetElementName( '}Cubes', cTempSub, nCountCubes );\r\n # Validate cube name\r\n If( CubeExists( sCurrCube ) = 1 );\r\n If( SubsetElementExists( '}Cubes', 'Cubes subset', sCurrCube ) = 0 );\r\n SubsetElementInsert( '}Cubes', 'Cubes subset', sCurrCube, 0 );\r\n EndIf;\r\n EndIf;\r\n nCountCubes = nCountCubes + 1;\r\n End;\r\n EndIf;\r\n\r\nEnd;\r\n\r\n# If no cubes found\r\nnFoundCubesCount = SubsetGetSize( '}Cubes', 'Cubes subset' );\r\nIf( nFoundCubesCount = 0 );\r\n nErrors = 1;\r\n sMessage = 'No cubes found after processing pCube.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElse;\r\n If( pLogOutput = 1 );\r\n sMessage = 'Number of cubes found that match pCube: ' | NumberToString( nFoundCubesCount );\r\n LogOutput('INFO', Expand( sMessage ) );\r\n EndIf;\r\nEndIf;\r\n\r\n\r\n# # # # # # # # # # SEARCH FOR CLIENTS BY INSPECTING CLIENTS AND GROUPS PARAMETERS\r\n# - pClient (mandatory or used in conjunction with pGroup). It could be a combination of:\r\n# * multiple clients separated with pDelim\r\n# * wildcards * and ?\r\n# * the keyword MYSELF (the client running this TI process)\r\n\r\n# - pGroup (mandatory or used in conjunction with pClient). It could be a combination of:\r\n# * multiple clients separated with pDelim\r\n# * wildcards * and ?\r\n# * the keyword MYGROUPS (the groups that the client running this TI process is a member of)\r\n\r\n### Split parameter into individual clients and store in a temporary subset ###\r\nSubsetCreate( '}Clients', 'Clients subset', 1 );\r\n\r\nsClients = pClient;\r\nnDelimiterIndex = 1;\r\nWhile( nDelimiterIndex <> 0 );\r\n nDelimiterIndex = Scan( pDelim, sClients );\r\n If( nDelimiterIndex = 0 );\r\n sClient = sClients;\r\n Else;\r\n sClient = Trim( SubSt( sClients, 1, nDelimiterIndex - 1 ) );\r\n sClients = Trim( Delet( sClients, 1, nDelimiterIndex + Long(pDelim) ) );\r\n EndIf;\r\n\r\n If( sClient @<> '' );\r\n\r\n If( sClient @= 'MYSELF' );\r\n sClient = cUserName;\r\n EndIf;\r\n\r\n # Create subset of clients using Wildcard. Wildcards could be involved.\r\n sMDX = '{TM1FilterByPattern( TM1SubsetAll( [}Clients] ), \"' | sClient | '\" )}';\r\n\r\n If( SubsetExists( '}Clients', cTempSub ) = 1 );\r\n # If a delimited list of client names includes wildcards then we may have to re-use the subset multiple times\r\n SubsetMDXSet( '}Clients', cTempSub, sMDX );\r\n Else;\r\n # temp subset, therefore no need to destroy in the Epilog tab\r\n SubsetCreatebyMDX( cTempSub, sMDX, '}Clients', 1 );\r\n EndIf;\r\n\r\n # Loop through the returned clients, if any\r\n nCountClients = 1;\r\n While( nCountClients <= SubsetGetSize( '}Clients', cTempSub ) );\r\n sCurrClient = SubsetGetElementName( '}Clients', cTempSub, nCountClients );\r\n # Validate client name\r\n If( Dimix( '}Clients', sCurrClient ) > 0 );\r\n If( SubsetElementExists( '}Clients', 'Clients subset', sCurrClient ) = 0 );\r\n SubsetElementInsert( '}Clients', 'Clients subset', sCurrClient, 0 );\r\n EndIf;\r\n EndIf;\r\n nCountClients = nCountClients + 1;\r\n End;\r\n EndIf;\r\n\r\nEnd;\r\n\r\n\r\n### Split parameter into individual groups and store in a temporary subset ###\r\nSubsetCreate( '}Groups', 'Groups subset', 1 );\r\n\r\nsGroups = pGroup;\r\nnDelimiterIndex = 1;\r\nWhile( nDelimiterIndex <> 0 );\r\n nDelimiterIndex = Scan( pDelim, sGroups );\r\n If( nDelimiterIndex = 0 );\r\n sGroup = sGroups;\r\n Else;\r\n sGroup = Trim( SubSt( sGroups, 1, nDelimiterIndex - 1 ) );\r\n sGroups = Trim( Delet( sGroups, 1, nDelimiterIndex + Long(pDelim) ) );\r\n EndIf;\r\n\r\n If( sGroup @<> '' );\r\n # Create subset of groups. Wildcards could be involved.\r\n\r\n If( sGroup @= 'MYGROUPS' );\r\n sMDX = '{Filter( TM1SubsetAll( [}Groups] ), [}ClientGroups].( [}Clients].[' | cUserName | '] ) <> \"\" )}';\r\n Else;\r\n sMDX = '{TM1FilterByPattern( TM1SubsetAll( [}Groups] ), \"' | sGroup | '\" )}';\r\n EndIf;\r\n\r\n If( SubsetExists( '}Groups', cTempSub ) = 1 );\r\n # If a delimited list of group names includes wildcards then we may have to re-use the subset multiple times\r\n SubsetMDXSet( '}Groups', cTempSub, sMDX );\r\n Else;\r\n # temp subset, therefore no need to destroy in the Epilog tab\r\n SubsetCreatebyMDX( cTempSub, sMDX, '}Groups', 1 );\r\n EndIf;\r\n\r\n # Loop through the returned groups, if any\r\n nCountGroups = 1;\r\n While( nCountGroups <= SubsetGetSize( '}Groups', cTempSub ) );\r\n sCurrGroup = SubsetGetElementName( '}Groups', cTempSub, nCountGroups );\r\n # Validate group name\r\n If( Dimix( '}Groups', sCurrGroup ) > 0 );\r\n If( SubsetElementExists( '}Groups', 'Groups subset', sCurrGroup ) = 0 );\r\n SubsetElementInsert( '}Groups', 'Groups subset', sCurrGroup, 0 );\r\n EndIf;\r\n EndIf;\r\n nCountGroups = nCountGroups + 1;\r\n End;\r\n EndIf;\r\n\r\nEnd;\r\nnFoundGroupsCount = SubsetGetSize( '}Groups', 'Groups subset' );\r\n\r\n\r\n# Now rework groups into their clients through the security memberships\r\nIf( nFoundGroupsCount > 0 );\r\n\r\n # Create subset of clients using Wildcard. Wildcards could be involved.\r\n sMDX = 'Generate( TM1SubsetToSet([}Groups], \"Groups subset\" ), Filter( TM1SubsetAll([}Clients]), [}ClientGroups].([}Groups].CurrentMember) <> \"\" ))';\r\n If( SubsetExists( '}Clients', cTempSub ) = 1 );\r\n SubsetMDXSet( '}Clients', cTempSub, sMDX );\r\n Else;\r\n SubsetCreatebyMDX( cTempSub, sMDX, '}Clients', 1 );\r\n EndIf;\r\n\r\n # Loop through the returned clients, if any\r\n nCountClients = 1;\r\n While( nCountClients <= SubsetGetSize( '}Clients', cTempSub ) );\r\n sCurrClient = SubsetGetElementName( '}Clients', cTempSub, nCountClients );\r\n If( SubsetElementExists( '}Clients', 'Clients subset', sCurrClient ) = 0 );\r\n SubsetElementInsert( '}Clients', 'Clients subset', sCurrClient, 0 );\r\n EndIf;\r\n nCountClients = nCountClients + 1;\r\n End;\r\nEndIf;\r\n\r\n\r\n# If no clients found\r\nnFoundClientsCount = SubsetGetSize( '}Clients', 'Clients subset' );\r\nIf( nFoundClientsCount = 0 );\r\n nErrors = 1;\r\n sMessage = 'No clients found after processing pClient and pGroup.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElse;\r\n If( pLogOutput = 1 );\r\n sMessage = 'Number of clients found that match pClient and pGroup: ' | NumberToString( nFoundClientsCount );\r\n LogOutput('INFO', Expand( sMessage ) );\r\n EndIf;\r\nEndIf;\r\n\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n\r\n# A double loop over cubes and clients to apply the selected action\r\nnCountCubes = 1;\r\nWhile( nCountCubes <= nFoundCubesCount );\r\n sCube = SubsetGetElementName( '}Cubes', 'Cubes subset', nCountCubes );\r\n nCubeDimCount = CubeDimensionCountGet( sCube );\r\n\r\n nCountClients = 1;\r\n While( nCountClients <= nFoundClientsCount );\r\n sClient = SubsetGetElementName( '}Clients', 'Clients subset', nCountClients );\r\n\r\n sHoldsCube = Expand( cHoldsCube );\r\n\r\n\r\n If( pMode @= 'C' );\r\n\r\n\r\n # Create a Holds cube\r\n If( CubeExists( sHoldsCube ) = 1 );\r\n nErrors = 1;\r\n sMessage = Expand( 'The holds cube ''%sHoldsCube%'' already exists so it could not be created.' );\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n EndIf;\r\n\r\n If( nCubeDimCount > nDimMax );\r\n nErrors = 1;\r\n sMessage = Expand( 'The base cube ''%sCube%'' for the holds cube ''%sHoldsCube%'' contains too many dimensions. ' | NumberToString( nCubeDimCount ) | ' instead of at most ' | NumberToString( nDimMax ) | '.' );\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n EndIf;\r\n\r\n # Create a measures dimension\r\n If( DimensionExists( cMsrDim ) = 0 );\r\n If( pLogOutput = 1 );\r\n sMessage = Expand( 'The measures dimension for hold cubes (%cMsrDim%) does not exist and will be created.' );\r\n LogOutput('INFO', Expand( sMessage ) );\r\n EndIf;\r\n nRet = ExecuteProcess( '}bedrock.hier.create', 'pLogOutput', pLogOutput, 'pStrictErrorHandling', pStrictErrorHandling, 'pDim', cMsrDim );\r\n If( nRet <> 0 );\r\n sMessage = Expand( 'Error creating the dimension ''%cMsrDim%''.' );\r\n nErrors = 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n EndIf;\r\n DimensionElementInsert( cMsrDim, '', 'HoldStatus', 'S' );\r\n EndIf;\r\n\r\n # Get the dimension names for the hold cube\r\n sDims = '';\r\n d = 1;\r\n While( d <= nCubeDimCount );\r\n sDim = Tabdim( sCube, d );\r\n sDims = sDims | pDelim | sDim;\r\n d = d + 1;\r\n End;\r\n sDims = sDims | pDelim | cMsrDim;\r\n sDims = Delet( sDims, 1, Long( pDelim ));\r\n\r\n nRet = ExecuteProcess( '}bedrock.cube.create', 'pLogOutput', pLogOutput, 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', sHoldsCube, 'pDims', sDims, 'pRecreate', 0, 'pDelim', pDelim );\r\n If( nRet <> 0 );\r\n sMessage = Expand( 'Error creating the cube ''%sHoldsCube%''.' );\r\n nErrors = 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n EndIf;\r\n If( pLogOutput = 1 );\r\n sMessage = Expand( 'The holds cube ''%sHoldsCube%'' was created.' );\r\n LogOutput('INFO', Expand( sMessage ) );\r\n EndIf;\r\n\r\n\r\n ElseIf( pMode @= 'D' );\r\n\r\n\r\n # Destroy a Holds cube\r\n If( CubeExists( sHoldsCube ) = 0 );\r\n If( pSkipNonExistentHoldsCubes = 0 );\r\n # nErrors = 1;\r\n # sMessage = Expand( 'The holds cube ''%sHoldsCube%'' does not exist so it could not be destroyed.' );\r\n # LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n # If( pStrictErrorHandling = 1 );\r\n # ProcessQuit;\r\n # Else;\r\n # ProcessBreak;\r\n # EndIf;\r\n If( pLogOutput = 1 );\r\n sMessage = Expand( 'The holds cube ''%sHoldsCube%'' does not exist so it could not be destroyed.' );\r\n LogOutput('INFO', Expand( sMessage ) );\r\n EndIf;\r\n EndIf;\r\n Else;\r\n\r\n CubeDestroy( sHoldsCube );\r\n If( pLogOutput = 1 );\r\n sMessage = Expand( 'The holds cube ''%sHoldsCube%'' was destroyed.' );\r\n LogOutput('INFO', Expand( sMessage ) );\r\n EndIf;\r\n EndIf;\r\n\r\n\r\n ElseIf( pMode @= 'R' );\r\n\r\n\r\n # In an existing Holds cube, delete all holds (Release)\r\n If( CubeExists( sHoldsCube ) = 0 );\r\n If( pSkipNonExistentHoldsCubes = 0 );\r\n nErrors = 1;\r\n sMessage = Expand( 'The holds cube ''%sHoldsCube%'' does not exist so all of its holds (if any) could not be released.' );\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n EndIf;\r\n Else;\r\n\r\n CubeClearData( sHoldsCube );\r\n # nRet = ExecuteProcess( '}bedrock.cube.data.clear', 'pLogOutput', pLogOutput, 'pStrictErrorHandling', pStrictErrorHandling,\r\n # 'pCube', sHoldsCube, 'pView', '', 'pFilter', '', 'pSuppressConsolStrings', 0, 'pCubeLogging', 2 );\r\n # If( nRet <> 0 );\r\n # sMessage = 'Error releasing all the holds in the cube ''%sHoldsCube%''.';\r\n # nErrors = 1;\r\n # LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n # If( pStrictErrorHandling = 1 );\r\n # ProcessQuit;\r\n # Else;\r\n # ProcessBreak;\r\n # EndIf;\r\n # EndIf;\r\n If( pLogOutput = 1 );\r\n sMessage = Expand( 'All the holds in the cube ''%sHoldsCube%'' were released.' );\r\n LogOutput('INFO', Expand( sMessage ) );\r\n EndIf;\r\n\r\n EndIf;\r\n\r\n\r\n ElseIf( pMode @= 'X' );\r\n\r\n\r\n # From an existing Holds cube, export all entries\r\n If( CubeExists( sHoldsCube ) = 0 );\r\n If( pSkipNonExistentHoldsCubes = 0 );\r\n nErrors = 1;\r\n sMessage = Expand( 'The holds cube ''%sHoldsCube%'' does not exist so all of its holds (if any) could not be exported.' );\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n EndIf;\r\n Else;\r\n\r\n If( nCubeDimCount > nDimMax );\r\n nErrors = 1;\r\n sMessage = Expand( 'The base cube ''%sCube%'' for the holds cube ''%sHoldsCube%'' contains too many dimensions. ' | NumberToString( nCubeDimCount ) | ' instead of at most ' | NumberToString( nDimMax ) | '.' );\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n EndIf;\r\n\r\n # the file directory (If empty, the error file directory is used. If not existing, an error is returned.)\r\n # this is done by the called Bedrock process\r\n # the file name is simply the Holds cube name with file extension csv\r\n sFileName = sHoldsCube | '.csv';\r\n nRet = ExecuteProcess( '}bedrock.cube.data.export', 'pLogOutput', pLogOutput, 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', sHoldsCube, 'pView', '', 'pFilter', '', 'pSuppressConsol', 0, 'pSuppressConsolStrings', 0,\r\n 'pCubeLogging', 2, 'pFilePath', pDir, 'pFileName', sFileName );\r\n If( nRet <> 0 );\r\n sMessage = Expand( 'Error exporting all the holds from the cube ''%sHoldsCube%'' to a flat file.' );\r\n nErrors = 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n EndIf;\r\n If( pLogOutput = 1 );\r\n sMessage = Expand( 'All the holds in the cube ''%sHoldsCube%'' were exported.' );\r\n LogOutput('INFO', Expand( sMessage ) );\r\n EndIf;\r\n EndIf;\r\n\r\n\r\n ElseIf( pMode @= 'M' );\r\n\r\n\r\n # To an existing Holds cube, import all entries\r\n # If the Holds cube does not exist, you need to create it first with mode C\r\n If( CubeExists( sHoldsCube ) = 0 );\r\n If( pSkipNonExistentHoldsCubes = 0 );\r\n nErrors = 1;\r\n sMessage = Expand( 'The holds cube ''%sHoldsCube%'' does not exist so holds (if any) could not be imported. You might want to create it first using mode ''C''.' );\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n EndIf;\r\n Else;\r\n\r\n # the file directory (If empty, the error file directory is used. If not existing, an error is returned.)\r\n # this is done by the called Bedrock process\r\n # the file name is simply the Holds cube name with file extension csv\r\n sFileName = sHoldsCube | '.csv';\r\n nRet = ExecuteProcess( '}bedrock.cube.data.import', 'pLogOutput', pLogOutput, 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', sHoldsCube, 'pSrcDir', pDir, 'pSrcFile', sFileName, 'pCubeLogging', 2, 'pFileDelete', 0, 'pSkipInvalidRecords', 0 );\r\n If( nRet <> 0 );\r\n sMessage = Expand( 'Error importing all the holds to the cube ''%sHoldsCube%'' from a flat file.' );\r\n nErrors = 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n EndIf;\r\n If( pLogOutput = 1 );\r\n sMessage = Expand( 'All the holds were imported to the cube ''%sHoldsCube%''.' );\r\n LogOutput('INFO', Expand( sMessage ) );\r\n EndIf;\r\n EndIf;\r\n EndIf;\r\n\r\n nCountClients = nCountClients + 1;\r\n End;\r\n\r\n nCountCubes = nCountCubes + 1;\r\nEnd;", "MetadataProcedure": "#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "DataProcedure": "#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "EpilogProcedure": "#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n#################################################################################################\r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n#################################################################################################\r\n\r\n### Return code & final error message handling\r\nIf( nErrors > 0 );\r\n sMessage = 'the process incurred at least 1 error. Please see above lines in this file for more details.';\r\n nProcessReturnCode = 0;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% Process:%cThisProcName% completed with errors. Check tm1server.log for details.' );\r\n If( pStrictErrorHandling = 1 );\r\n ProcessQuit;\r\n EndIf;\r\nElse;\r\n sProcessAction = Expand( 'Process:%cThisProcName% successfully performed %pMode% for cube ''%pCube%'', with client ''%pGroup%'' and group ''%pGroup%''.' );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% %sProcessAction%' );\r\n nProcessReturnCode = 1;\r\n If( pLogOutput = 1 );\r\n LogOutput('INFO', Expand( sProcessAction ) );\r\n EndIf;\r\nEndIf;", @@ -10,18 +10,6 @@ "Type": "None" }, "Parameters": [ - { - "Name": "pLogOutput", - "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, - { - "Name": "pStrictErrorHandling", - "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, { "Name": "pMode", "Prompt": "REQUIRED: Use C / D / R / X / M. See inside process for information. Supported operations for holds cubes: Create, Destroy, Release, Export, Import.", @@ -30,39 +18,57 @@ }, { "Name": "pCube", - "Prompt": "REQUIRED: Treat which Holds cube(s) ? Provide the base cube name(s). Supports a list and wildcards * and ? and keyword MODELCUBES.", + "Prompt": "REQUIRED: Cube name", "Value": "", "Type": "String" }, { "Name": "pClient", - "Prompt": "REQUIRED or used in conjunction with pGroup. Treat the Holds cube(s) of which client(s) ? Supports a list and wildcards * and ? and keyword MYSELF.", + "Prompt": "REQUIRED: or used in conjunction with pGroup. Treat the Holds cube(s) of which client(s) ? Supports a list and wildcards * and ? and keyword MYSELF.", "Value": "", "Type": "String" }, { "Name": "pGroup", - "Prompt": "REQUIRED or used in conjunction with pClient. Treat the Holds cube(s) of which client(s) in which group(s) ? Supports a list and wildcards * and ? and keyword MYGROUPS.", + "Prompt": "REQUIRED: or used in conjunction with pClient. Treat the Holds cube(s) of which client(s) in which group(s) ? Delimited list of groups", "Value": "", "Type": "String" }, { "Name": "pDelim", - "Prompt": "OPTIONAL: delimiter character for the different lists. (default value if blank = '&')", + "Prompt": "OPTIONAL: Delimiter for list parameters (Default = '&')", "Value": "&", "Type": "String" }, { "Name": "pDir", - "Prompt": "OPTIONAL: Directory (will default to error file path)", + "Prompt": "OPTIONAL: File directory (Default = GetProcessErrorFileDirectory)", "Value": "", "Type": "String" }, { "Name": "pSkipNonExistentHoldsCubes", - "Prompt": "OPTIONAL: When using lists and wildcards, it can lead to non-existent holds cubes. 1=Silently ignore these. Default=0.", + "Prompt": "OPTIONAL: When using lists and wildcards, it can lead to non-existent holds cubes (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" + }, + { + "Name": "pLogOutput", + "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pStrictErrorHandling", + "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pJson", + "Prompt": "OPTIONAL: JSON Object with process parameter values. This will overwrite user passed parameters for all included parameters.", + "Value": "{}", + "Type": "String" } ], "Variables": [], diff --git a/bedrock_processes_json/}bedrock.cube.data.import.json b/bedrock_processes_json/}bedrock.cube.data.import.json index 8eaa9ba..45be8a0 100644 --- a/bedrock_processes_json/}bedrock.cube.data.import.json +++ b/bedrock_processes_json/}bedrock.cube.data.import.json @@ -1,11 +1,11 @@ { "Name": "}bedrock.cube.data.import", - "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.data.import', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pCube', '', 'pSrcDir', '', 'pSrcFile', '',\r\n \t'pDim', '', 'pSrcEle', '', 'pTgtEle', '',\r\n \t'pTitleRows', 1, 'pDelim', ',', 'pQuote', '\"', 'pDecimalSeparator', '.', 'pThousandSeparator', ',',\r\n \t'pCumulate', 0, 'pCubeLogging', 0, 'pSandbox', pSandbox, 'pZeroFilter', 0, \r\n \t'pMappingToNewDims','', 'pDimDelim', '&', 'pEleStartDelim', '\u00a6', 'pEleDelim', '+', 'pFileDelete', 0, 'pSkipInvalidRecords', 0\r\n );\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process will load a csv text file to the target cube.\r\n\r\n# Use case: Intended for development/prototyping or in Production environment.\r\n#1/ Import data from another TM1 model.\r\n#2/ To eliminate possibility of locking it is sometimes better to export and import when needing to copy data from one cube to another.\r\n\r\n# Note:\r\n# Naturally, a valid target cube name (pCube) is mandatory otherwise the process will abort.\r\n# Element mapping for new dimensions (pMappingToNewDims ) is also required when the target cube has more dimensions than the source, otherwise the process will abort.\r\n# The default input path is the same as the error file path if not specified.\r\n# If the file name is left blank, the process will look for a file called pCube_Export.csv.\r\n\r\n# Format:\r\n# The assumed file format is as per standard CMA export:\r\n# - v1 specIfies cube name, subsequent fields specify cube address ( individual element names ).\r\n# - vN specIfies cell data value to load. With provision for files with header rows.\r\n# Format of filter row for Zero out:\r\n# - v1 specifies source cube name\r\n# - v2 must be equal to \"Filter\".\r\n# - v3 specifies the filter to be used to zero out. Please note if target cube has additional dimensions this is the final filter used if pMappingToNewDims is not speficied. All the elements in additional dimensions will be cleaned \r\n# - v4 specifies the dimension delimiter used in filter\r\n# - v5 specifies the element start delimiter used in filter\r\n# - v6 specifies the element delimiter used in filter\r\n# Note about the Zero out:\r\n# if pMappingToNewDims parameter is specified, it will be concatenated to the filter in the file to restict the cube slice to be zeroed out. Similarly, if pDim is specified the source element is substituted with the targed one, sould it be in the filter string\r\n# in both cases the delimiters in the source file must match the delimiters passed in parameters of this process.\r\n#EndRegion @DOC\r\n\r\n### Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSub = cThisProcName |'_'| cTimeStamp |'_'| cRandomInt;\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pSrcDir:%pSrcDir%, pSrcFile:%pSrcFile%, pCube:%pCube%, pDim:%pDim%, pSrcEle:%pSrcEle%, pTgtEle:%pTgtEle%, pTitleRows:%pTitleRows%, pDelim:%pDelim%, pQuote:%pQuote%, pCumulate:%pCumulate%, pCubeLogging:%pCubeLogging%, pSandbox:%pSandbox%, pZeroFilter:%pZeroFilter%, pMappingToNewDims:%pMappingToNewDims%, pDimDelim:%pDimDelim%, pEleStartDelim:%pEleStartDelim%, pEleDelim:%pEleDelim%.'; \r\ncMinLenASCIICode = 2;\r\ncMaxLenASCIICode = 3;\r\n\r\npDelimiter = TRIM(pDelim);\r\nsDelimDim = TRIM(pDimDelim);\r\nsElementStartDelim = TRIM(pElEStartDelim);\r\nsDelimElem = TRIM(pEleDelim);\r\npDecimalSeparator = TRIM(pDecimalSeparator);\r\npThousandSeparator = TRIM(pThousandSeparator);\r\n\r\n## LogOutput parameters\r\nIf( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\nnRecordProcessedCount = 0;\r\nnRecordPostedCount = 0;\r\nnErrors = 0;\r\n\r\n\r\n### Validate Parameters ###\r\npSourceDir = TRIM(pSrcDir);\r\npSourceFile = TRIM(pSrcFile);\r\n\r\n## check operating system\r\nIf( SubSt( GetProcessErrorFileDirectory, 2, 1 ) @= ':' );\r\n sOS = 'Windows';\r\n sOSDelim = '\\';\r\nElseIf( Scan( '/', GetProcessErrorFileDirectory ) > 0 );\r\n sOS = 'Linux';\r\n sOSDelim = '/';\r\nElse;\r\n sOS = 'Windows';\r\n sOSDelim = '\\';\r\nEndIf;\r\n\r\n# Validate source directory\r\nIf(Trim( pSourceDir ) @= '' );\r\n pSourceDir = GetProcessErrorFileDirectory;\r\nEndIf;\r\n\r\nIf( SubSt( pSourceDir, Long( pSourceDir ), 1 ) @= sOSDelim );\r\n pSourceDir = SubSt( pSourceDir, 1, Long( pSourceDir ) - 1 );\r\nEndIf;\r\n\r\nIf( FileExists( pSourceDir ) = 0 );\r\n sMessage = 'Invalid source directory specified: folder does not exist.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\nIf( pSourceFile @= '' );\r\n pSourceFile = Expand('%pCube%_Export.csv');\r\nEndIf;\r\n\r\nsFile = pSourceDir | sOSDelim | pSourceFile;\r\n# Validate source file\r\nIf( FileExists( sFile ) = 0 );\r\n sMessage = 'Invalid source file specified: file does not exist in directory:' | sFile;\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Automatic file deletion\r\nIf( pFileDelete <> 1 );\r\n pFileDelete = 0;\r\nEndIf;\r\n\r\n# Skip invalid records\r\nIf( pSkipInvalidRecords <> 1 );\r\n pSkipInvalidRecords = 0;\r\nEndIf;\r\n\r\n## Validate cube\r\nIf( Trim( pCube ) @= '' );\r\n sMessage = 'No target cube specified.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( CubeExists( pCube ) = 0 );\r\n sMessage = 'Invalid target cube specified: ' | pCube;\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate file delimiter & quote character\r\nIf( pDelimiter @= '' );\r\n pDelimiter = ',';\r\nElse;\r\n # If length of pDelimiter is between 2 and 3 chars and each of them is decimal digit, then the pDelimiter is entered as ASCII code\r\n If ( LONG(pDelimiter) <= cMaxLenASCIICode & LONG(pDelimiter) >= cMinLenASCIICode );\r\n nValid = 1;\r\n nChar = 1;\r\n While ( nChar <= LONG(pDelimiter) );\r\n If( CODE( pDelimiter, nChar ) < CODE( '0', 1 ) % CODE( pDelimiter, nChar ) > CODE( '9', 1 ) );\r\n nValid = 0;\r\n Break;\r\n EndIf;\r\n nChar = nChar + 1;\r\n End;\r\n If ( nValid<>0 );\r\n pDelimiter=CHAR(StringToNumber( pDelimiter ));\r\n EndIf;\r\n EndIf;\r\nEndIf;\r\n\r\nIf( pQuote @= '' );\r\n ## Use no quote character \r\nElse;\r\n # If length of pQuote is between 2 and 3 chars and each of them is decimal digit, then the pQuote is entered as ASCII code\r\n If ( LONG(pQuote) <= cMaxLenASCIICode & LONG(pQuote) >= cMinLenASCIICode);\r\n nValid = 1;\r\n nChar = 1;\r\n While ( nChar <= LONG(pQuote) );\r\n If( CODE( pQuote, nChar ) < CODE( '0', 1 ) % CODE( pQuote, nChar ) > CODE( '9', 1 ) );\r\n nValid = 0;\r\n Break;\r\n EndIf;\r\n nChar = nChar + 1;\r\n End;\r\n If ( nValid<>0 );\r\n pQuote=CHAR(StringToNumber( pQuote ));\r\n EndIf;\r\n EndIf;\r\nEndIf;\r\n\r\nIf ( LONG(pDecimalSeparator) <= cMaxLenASCIICode & LONG(pDecimalSeparator) >= cMinLenASCIICode );\r\n nValid = 0;\r\n nChar = 1;\r\n While ( nChar <= LONG(pDecimalSeparator) );\r\n If( CODE( pDecimalSeparator, nChar ) >= CODE( '0', 1 ) & CODE( pDecimalSeparator, nChar ) <= CODE( '9', 1 ) );\r\n nValid = 1;\r\n Else;\r\n nValid = 0;\r\n Break;\r\n EndIf;\r\n nChar = nChar + 1;\r\n End;\r\n If ( nValid<>0 );\r\n pDecimalSeparator = CHAR(StringToNumber( pDecimalSeparator ));\r\n Else;\r\n pDecimalSeparator = SubSt( Trim( pDecimalSeparator ), 1, 1 );\r\n EndIf;\r\nEndIf;\r\nsDecimalSeparator = pDecimalSeparator;\r\n\r\nIf ( LONG(pThousandSeparator) <= cMaxLenASCIICode & LONG(pThousandSeparator) >= cMinLenASCIICode );\r\n nValid = 0;\r\n nChar = 1;\r\n While ( nChar <= LONG(pThousandSeparator) );\r\n If( CODE( pThousandSeparator, nChar ) >= CODE( '0', 1 ) & CODE( pThousandSeparator, nChar ) <= CODE( '9', 1 ) );\r\n nValid = 1;\r\n Else;\r\n nValid = 0;\r\n Break;\r\n EndIf;\r\n nChar = nChar + 1;\r\n End;\r\n If ( nValid<>0 );\r\n pThousandSeparator = CHAR(StringToNumber( pThousandSeparator ));\r\n Else;\r\n pThousandSeparator = SubSt( Trim( pThousandSeparator ), 1, 1 );\r\n EndIf;\r\nEndIf;\r\nsThousandSeparator = pThousandSeparator;\r\n\r\n# Validate Sandbox\r\nIf( TRIM( pSandbox ) @<> '' );\r\n If( ServerSandboxExists( pSandbox ) = 0 );\r\n SetUseActiveSandboxProperty( 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand('Sandbox %pSandbox% is invalid for the current user.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n Else;\r\n ServerActiveSandboxSet( pSandbox );\r\n SetUseActiveSandboxProperty( 1 );\r\n EndIf;\r\nElse;\r\n SetUseActiveSandboxProperty( 0 );\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n## Validate Dimension\r\npDimension = TRIM( pDim);\r\npSourceElement = TRIM(pSrcEle);\r\npTargetElement = TRIM(pTgtEle);\r\n\r\nIf( pDimension @<> '');\r\n \r\n If( DimensionExists( pDimension ) = 0 );\r\n sMessage = 'Invalid dimension specified: ' | pDimension;\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\n\r\n # Validate Source Element\r\n If( pSourceElement @= '' );\r\n sMessage = 'Error: The Source Element parameter is blank.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\n\r\n If( DimIx( pDimension, pSourceElement ) = 0 );\r\n sMessage = 'Invalid source element, ' | pSourceElement | ' specified for ' | pDimension | ' dimension.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\n sSourceElement = DimensionElementPrincipalName( pDimension, pSourceElement);\r\n\r\n # Validate Target Element\r\n If( pTargetElement @= '' );\r\n sMessage = 'Error: The Target Element parameter is blank.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n ElseIf( DimIx( pDimension, pTargetElement ) = 0 );\r\n sMessage = 'Invalid target element, ' | pTargetElement | ' specified for ' | pDimension | ' dimension.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\n sTargetElement = DimensionElementPrincipalName( pDimension, pTargetElement);\r\n\r\nENDIF;\r\n\r\n## Validate delimiter\r\n\r\nIf( pDelimiter @= '' );\r\n sMessage = 'Error: The file delimiter parameter is blank.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( Long( pDelimiter ) > 1 );\r\n sMessage = 'Invalid delimiter specified: ' | pDelimiter | ' field delimiter must be single character or 2-3 symbols number representing ASCII code.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n## Validate quote character\r\nIf( Long( pQuote ) > 1 );\r\n sMessage = 'Invalid string qualIfier: ' | pQuote | ' quote character must be single character or empty string or 2-3 symbols number representing ASCII code.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n### Determine number of dims in target cube ###\r\nnCount = 1;\r\nnSubstututeDimensionIndex = 0;\r\nWhile( \r\nTabDim( pCube, nCount ) @<> '' );\r\n sDimension = TabDim( pCube, nCount );\r\n If( sDimension @= pDimension );\r\n nSubstututeDimensionIndex = nCount;\r\n EndIf;\r\n nCount = nCount + 1;\r\nEnd;\r\nnDimensionCount = nCount - 1;\r\n\r\n## Validate the dimension is part of the cube.\r\nIf( pDimension @= '');\r\n ## CONTINUE;\r\nELSEIf( nSubstututeDimensionIndex = 0 );\r\n sMessage = 'Specified dimension: ' | pDimension | ' is not a component of the cube: ' | pCube;\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nENDIF;\r\n\r\n ## Default filter delimiters\r\n If( pDimDelim @= '' );\r\n pDimDelim = '&';\r\n EndIf;\r\n If( pEleStartDelim@= '' );\r\n pEleStartDelim= '\u00a6';\r\n EndIf;\r\n If( pEleDelim @= '' );\r\n pEleDelim = '+';\r\n EndIf;\r\n \r\n\r\nIf( nDimensionCount > 27 );\r\n sMessage = 'Cube has too many dimensions: ' | pCube | ' max 27 dimensions.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n### Determine dimensions in target cube, we need to know this to test cell type before loading ###\r\nsDim1 = TabDim( pCube, 1 );\r\nsDim2 = TabDim( pCube, 2 );\r\nsDim3 = TabDim( pCube, 3 );\r\nsDim4 = TabDim( pCube, 4 );\r\nsDim5 = TabDim( pCube, 5 );\r\nsDim6 = TabDim( pCube, 6 );\r\nsDim7 = TabDim( pCube, 7 );\r\nsDim8 = TabDim( pCube, 8 );\r\nsDim9 = TabDim( pCube, 9 );\r\nsDim10 = TabDim( pCube, 10 );\r\nsDim11 = TabDim( pCube, 11 );\r\nsDim12 = TabDim( pCube, 12 );\r\nsDim13 = TabDim( pCube, 13 );\r\nsDim14 = TabDim( pCube, 14 );\r\nsDim15 = TabDim( pCube, 15 );\r\nsDim16 = TabDim( pCube, 16 );\r\nsDim17 = TabDim( pCube, 17 );\r\nsDim18 = TabDim( pCube, 18 );\r\nsDim19 = TabDim( pCube, 19 );\r\nsDim20 = TabDim( pCube, 20 );\r\nsDim21 = TabDim( pCube, 21 );\r\nsDim22 = TabDim( pCube, 22 );\r\nsDim23 = TabDim( pCube, 23 );\r\nsDim24 = TabDim( pCube, 24 );\r\nsDim25 = TabDim( pCube, 25 );\r\nsDim26 = TabDim( pCube, 26 );\r\nsDim27 = TabDim( pCube, 27 );\r\n\r\n### Placeholders for mappped dimensions and for new dimensions\r\n\r\nnMappedDim1 = 0;\tsMappedV1 = '';\t\tnNewDim1 = 0;\t sNewV1 = '';\r\nnMappedDim2 = 0;\tsMappedV2 = '';\t\tnNewDim2 = 0;\t sNewV2 = '';\r\nnMappedDim3 = 0;\tsMappedV3 = '';\t\tnNewDim3 = 0;\t sNewV3 = '';\r\nnMappedDim4 = 0;\tsMappedV4 = '';\t\tnNewDim4 = 0;\t sNewV4 = '';\r\nnMappedDim5 = 0;\tsMappedV5 = '';\t\tnNewDim5 = 0;\t sNewV5 = '';\r\nnMappedDim6 = 0;\tsMappedV6 = '';\t\tnNewDim6 = 0;\t sNewV6 = '';\r\nnMappedDim7 = 0;\tsMappedV7 = '';\t\tnNewDim7 = 0;\t sNewV7 = '';\r\nnMappedDim8 = 0;\tsMappedV8 = '';\t\tnNewDim8 = 0;\t sNewV8 = '';\r\nnMappedDim9 = 0;\tsMappedV9 = '';\t\tnNewDim9 = 0;\t sNewV9 = '';\r\nnMappedDim10 = 0;\tsMappedV10 = '';\tnNewDim10 = 0;\tsNewV10 = '';\r\nnMappedDim11 = 0;\tsMappedV11 = '';\tnNewDim11 = 0;\tsNewV11 = '';\r\nnMappedDim12 = 0;\tsMappedV12 = '';\tnNewDim12 = 0;\tsNewV12 = '';\r\nnMappedDim13 = 0;\tsMappedV13 = '';\tnNewDim13 = 0;\tsNewV13 = '';\r\nnMappedDim14 = 0;\tsMappedV14 = '';\tnNewDim14 = 0;\tsNewV14 = '';\r\nnMappedDim15 = 0;\tsMappedV15 = '';\tnNewDim15 = 0;\tsNewV15 = '';\r\nnMappedDim16 = 0;\tsMappedV16 = '';\tnNewDim16 = 0;\tsNewV16 = '';\r\nnMappedDim17 = 0;\tsMappedV17 = '';\tnNewDim17 = 0;\tsNewV17 = '';\r\nnMappedDim18 = 0;\tsMappedV18 = '';\tnNewDim18 = 0;\tsNewV18 = '';\r\nnMappedDim19 = 0;\tsMappedV19 = '';\tnNewDim19 = 0;\tsNewV19 = '';\r\nnMappedDim20 = 0;\tsMappedV20 = '';\tnNewDim20 = 0;\tsNewV20 = '';\r\nnMappedDim21 = 0;\tsMappedV21 = '';\tnNewDim21 = 0;\tsNewV21 = '';\r\nnMappedDim22 = 0;\tsMappedV22 = '';\tnNewDim22 = 0;\tsNewV22 = '';\r\nnMappedDim23 = 0;\tsMappedV23 = '';\tnNewDim23 = 0;\tsNewV23 = '';\r\nnMappedDim24 = 0;\tsMappedV24 = '';\tnNewDim24 = 0;\tsNewV24 = '';\r\nnMappedDim25 = 0;\tsMappedV25 = '';\tnNewDim25 = 0;\tsNewV25 = '';\r\nnMappedDim26 = 0;\tsMappedV26 = '';\tnNewDim26 = 0;\tsNewV26 = '';\r\nnMappedDim27 = 0;\tsMappedV27 = '';\tnNewDim27 = 0;\tsNewV27 = '';\r\n sMappedV28 = '';\r\n\r\n###########################################\r\n### SPLIT MAPPING TO NEW DIMS PARAMETER ###\r\n###########################################\r\n\r\nnTargetCubeDimensionCount = nDimensionCount;\r\n\r\nsElementMapping = TRIM( pMappingToNewDims );\r\nnChar = 1;\r\nnCharCount = LONG( sElementMapping );\r\n\r\nsTargetFilter = '';\r\nsWord = '';\r\nsLastDelim = '';\r\nnIndex = 1;\r\n\r\n# Add a trailing element delimiter so that the last element is picked up\r\nIf( nCharCount > 0 );\r\n sElementMapping = sElementMapping | sDelimDim;\r\n nCharCount = nCharCount + LONG(sDelimDim);\r\nEndIf;\r\n\r\nWHILE (nChar <= nCharCount);\r\n sChar = SUBST( sElementMapping, nChar, 1);\r\n\r\n # Used for delimiters, required for multiple character delimiters\r\n sDelim = '';\r\n nAddExtra = 0;\r\n\r\n # Ignore spaces\r\n IF (TRIM(sChar) @<> '' );\r\n\r\n ### Dimension Name ###\r\n\r\n # If the delimiter is more than 1 character peek ahead the same amount\r\n # Ignore the first character\r\n sDelim = sChar;\r\n nCount = LONG(sElementStartDelim) - 1;\r\n If( nCount > 0 & nChar + nCount <= nCharCount );\r\n # Add the extra characters\r\n sDelim = sDelim | SUBST( sElementMapping, nChar + 1, nCount);\r\n # Move to the end of the delimter\r\n\r\n EndIf;\r\n\r\n If( sDelim @= sElementStartDelim );\r\n nAddExtra = nCount;\r\n sChar = sDelim;\r\n\r\n If( sLastDelim @<> '' & sLastDelim @<> sDelimDim );\r\n sMessage = 'In pMappingToNewDims the name of a dimension must follow a dimension delimiter (' | sDelimDim | ')';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n EndIf;\r\n\r\n # Found a dimension\r\n sDimension = sWord;\r\n\r\n If( DimensionExists( sDimension ) = 0 );\r\n # The dimension does not exist in the model. Cancel process\r\n sMessage = 'In pMappingToNewDims - Dimension: ' | sDimension | ' does not exist';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n EndIf;\r\n \r\n ### Determine the dimension is a member of the cube ###\r\n nMapCount = 1;\r\n nMapDimensionIndex = 0;\r\n While( TabDim( pCube, nMapCount ) @<> '' );\r\n sMapCubeDimName = TabDim( pCube, nMapCount );\r\n If( sDimension @= sMapCubeDimName );\r\n nMapDimensionIndex = nMapCount;\r\n EndIf;\r\n nMapCount = nMapCount + 1;\r\n End;\r\n\r\n If( nMapDimensionIndex = 0 );\r\n # The dimension does not exist in the cube. Cancel process\r\n sMessage = 'Dimension: ' | sDimension | ' is not a member of: '| pCube | ' cube.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n EndIf;\r\n\r\n # Find the index of the dimension is in the Target cube\r\n nTargetIndexCounter = 1;\r\n\r\n WHILE(nTargetIndexCounter <= nTargetCubeDimensionCount );\r\n sNthDimension = TabDim( pCube, nTargetIndexCounter );\r\n\r\n If(sDimension @= sNthDimension);\r\n nTargetIndex = nTargetIndexCounter;\r\n nTargetIndexCounter = 1000;\r\n EndIf;\r\n\r\n nTargetIndexCounter = nTargetIndexCounter + 1;\r\n END;\r\n \r\n #Add to the Target filter\r\n If(sTargetFilter@='');\r\n sTargetFilter=sDimension; \r\n Else;\r\n sTargetFilter=sTargetFilter|sDelimDim|sDimension;\r\n Endif; \r\n \r\n sLastDelim = sChar;\r\n # Clear the word\r\n sWord = '';\r\n\r\n Else;\r\n\r\n # Reset extra chars\r\n nAddExtra = 0;\r\n\r\n ### Check both dim delimiter and element delimiter ###\r\n nIsDelimiter = 0;\r\n\r\n ## Check dimension delimiter first\r\n # If the delimiter is more than 1 character peek ahead the same amount\r\n # Ignore the first character\r\n sDelim = sChar;\r\n nCount = LONG(sDelimDim) - 1;\r\n If( nCount > 0 & nChar + nCount <= nCharCount );\r\n # Add the extra characters\r\n sDelim = sDelim | SUBST( sElementMapping, nChar + 1, nCount);\r\n # Move to the end of the delimter\r\n \r\n EndIf;\r\n\r\n If( sDelim @= sDelimDim );\r\n nIsDelimiter = 1;\r\n sChar = sDelim;\r\n nAddExtra = nCount;\r\n EndIf;\r\n\r\n If ( nIsDelimiter = 1 );\r\n\r\n If( sLastDelim @= '' % sLastDelim @= sDelimDim );\r\n sMessage = 'In pMappingToNewDims - an element delimiter must follow a dimension name: ' | sChar | ' (' | NumberToString(nChar) | ')';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n EndIf;\r\n\r\n # an element has been found\r\n sElement = sWord;\r\n\r\n If( DimIx( sDimension, sElement ) = 0 );\r\n # The element does not exist in the dimension. Cancel process\r\n sMessage = 'In pMappingToNewDims - Element: ' | sElement | ' in dimension ' | sDimension | ' does not exist';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n EndIf;\r\n\r\n # Allow consolidations only if pSuppressConsol is set to 0\r\n\r\n If ( DTYPE( sDimension, sElement) @= 'C' );\r\n sMessage = Expand( 'In pMappingToNewDims - Target element: %sElement% for dimension %sDimension% is consolidated' );\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n Endif; \r\n \r\n\r\n # Add the element to the source or target depending on whether it's the first or the second element\r\n # Get principal name\r\n # in case source element and this element are using different aliases\r\n\r\n sElement = DimensionElementPrincipalName(sDimension,sElement);\r\n\r\n ### Update the variable for InputElement Target Dim ######################################\r\n If(nTargetIndex = 1);\r\n nNewDim1 = 1;\r\n sNewV1 = sElement;\r\n ElseIf(nTargetIndex = 2);\r\n nNewDim2 = 1;\r\n sNewV2 = sElement;\r\n ElseIf(nTargetIndex = 3);\r\n nNewDim3 = 1;\r\n sNewV3 = sElement;\r\n ElseIf(nTargetIndex = 4);\r\n nNewDim4 = 1;\r\n sNewV4 = sElement;\r\n ElseIf(nTargetIndex = 5);\r\n nNewDim5 = 1;\r\n sNewV5 = sElement;\r\n ElseIf(nTargetIndex = 6);\r\n nNewDim6 = 1;\r\n sNewV6 = sElement;\r\n ElseIf(nTargetIndex = 7);\r\n nNewDim7 = 1;\r\n sNewV7 = sElement;\r\n ElseIf(nTargetIndex = 8);\r\n nNewDim8 = 1;\r\n sNewV8 = sElement;\r\n ElseIf(nTargetIndex = 9);\r\n nNewDim9 = 1;\r\n sNewV9 = sElement;\r\n ElseIf(nTargetIndex = 10);\r\n nNewDim10 = 1;\r\n sNewV10 = sElement;\r\n ElseIf(nTargetIndex = 11);\r\n nNewDim11 = 1;\r\n sNewV11 = sElement;\r\n ElseIf(nTargetIndex = 12);\r\n nNewDim12 = 1;\r\n sNewV12 = sElement;\r\n ElseIf(nTargetIndex = 13);\r\n nNewDim13 = 1;\r\n sNewV13 = sElement;\r\n ElseIf(nTargetIndex = 14);\r\n nNewDim14 = 1;\r\n sNewV14 = sElement;\r\n ElseIf(nTargetIndex = 15);\r\n nNewDim15 = 1;\r\n sNewV15 = sElement;\r\n ElseIf(nTargetIndex = 16);\r\n nNewDim16 = 1;\r\n sNewV16 = sElement;\r\n ElseIf(nTargetIndex = 17);\r\n nNewDim17 = 1;\r\n sNewV17 = sElement;\r\n ElseIf(nTargetIndex = 18);\r\n nNewDim18 = 1;\r\n sNewV18 = sElement;\r\n ElseIf(nTargetIndex = 19);\r\n nNewDim19 = 1;\r\n sNewV19 = sElement;\r\n ElseIf(nTargetIndex = 20);\r\n nNewDim20 = 1;\r\n sNewV20 = sElement;\r\n ElseIf(nTargetIndex = 21);\r\n nNewDim21 = 1;\r\n sNewV21 = sElement;\r\n ElseIf(nTargetIndex = 22);\r\n nNewDim22 = 1;\r\n sNewV22 = sElement;\r\n ElseIf(nTargetIndex = 23);\r\n nNewDim23 = 1;\r\n sNewV23 = sElement;\r\n ElseIf(nTargetIndex = 24);\r\n nNewDim24 = 1;\r\n sNewV24 = sElement;\r\n ElseIf(nTargetIndex = 25);\r\n nNewDim25 = 1;\r\n sNewV25 = sElement;\r\n ElseIf(nTargetIndex = 26);\r\n nNewDim26 = 1;\r\n sNewV26 = sElement;\r\n ElseIf(nTargetIndex = 27);\r\n nNewDim27 = 1;\r\n sNewV27 = sElement;\r\n EndIf;\r\n\r\n #Add to the Target filter - no need to manage element separators, since just one target element is possible in mapping\r\n sTargetFilter=sTargetFilter|sElementStartDelim|sElement;\r\n \r\n # Clear the word\r\n sWord = '';\r\n sLastDelim = sChar;\r\n \r\n Else;\r\n sWord = sWord | sChar;\r\n EndIf;\r\n\r\n EndIf;\r\n\r\n EndIf;\r\n\r\n nChar = nChar + nAddExtra + 1;\r\n\r\nEND;\r\n\r\n\r\n###########################################\r\n#Region ### MAPPING Target DIMENSIONS #####\r\n\r\n## Source index starting from 2, since first columns holds the export cube name\r\nnSourceIndex = 2;\r\nnTargetIndex = 1;\r\nWHILE(TabDim( pCube, nTargetIndex ) @<> '');\r\n sTargetDim = TabDim( pCube, nTargetIndex );\r\n \r\n If(nTargetIndex = 1);\r\n If( nNewDim1 = 0 );\r\n nMappedDim1 = 1;\r\n sMappedV1 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n Else;\r\n \r\n EndIf;\r\n ElseIf(nTargetIndex = 2 & nNewDim2 = 0);\r\n nMappedDim2 = 1;\r\n sMappedV2 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 3 & nNewDim3 = 0);\r\n nMappedDim3 = 1;\r\n sMappedV3 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 4 & nNewDim4 = 0);\r\n nMappedDim4 = 1;\r\n sMappedV4 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 5 & nNewDim5 = 0);\r\n nMappedDim5 = 1;\r\n sMappedV5 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 6 & nNewDim6 = 0);\r\n nMappedDim6 = 1;\r\n sMappedV6 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 7 & nNewDim7 = 0);\r\n nMappedDim7 = 1;\r\n sMappedV7 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 8 & nNewDim8 = 0);\r\n nMappedDim8 = 1;\r\n sMappedV8 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 9 & nNewDim9 = 0);\r\n nMappedDim9 = 1;\r\n sMappedV9 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 10 & nNewDim10 = 0);\r\n nMappedDim10 = 1;\r\n sMappedV10 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 11 & nNewDim11 = 0);\r\n nMappedDim11 = 1;\r\n sMappedV11 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 12 & nNewDim12 = 0 );\r\n nMappedDim12 = 1;\r\n sMappedV12 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 13 & nNewDim13 = 0 );\r\n nMappedDim13 = 1;\r\n sMappedV13 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 14 & nNewDim14 = 0 );\r\n nMappedDim14 = 1;\r\n sMappedV14 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 15 & nNewDim15 = 0 );\r\n nMappedDim15 = 1;\r\n sMappedV15 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 16 & nNewDim16 = 0 );\r\n nMappedDim16 = 1;\r\n sMappedV16 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 17 & nNewDim17 = 0 );\r\n nMappedDim17 = 1;\r\n sMappedV17 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 18 & nNewDim18 = 0 );\r\n nMappedDim18 = 1;\r\n sMappedV18 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 19 & nNewDim19 = 0 );\r\n nMappedDim19 = 1;\r\n sMappedV19 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 20 & nNewDim20 = 0 );\r\n nMappedDim20 = 1;\r\n sMappedV20 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 21 & nNewDim21 = 0 );\r\n nMappedDim21 = 1;\r\n sMappedV21 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 22 & nNewDim22 = 0 );\r\n nMappedDim22 = 1;\r\n sMappedV22 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 23 & nNewDim23 = 0 );\r\n nMappedDim23 = 1;\r\n sMappedV23 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 24 & nNewDim24 = 0 );\r\n nMappedDim24 = 1;\r\n sMappedV24 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 25 & nNewDim25 = 0 );\r\n nMappedDim25 = 1;\r\n sMappedV25 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 26 & nNewDim26 = 0 );\r\n nMappedDim26 = 1;\r\n sMappedV26 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 27 & nNewDim27 = 0 );\r\n nMappedDim27 = 1;\r\n sMappedV27 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n EndIf;\r\n\r\n nTargetIndex = nTargetIndex + 1;\r\n\r\nEND;\r\n\r\n# The last variable in the data source holds the values\r\n# which need to be mapped to the last variable in the target\r\n\r\nIf(nTargetIndex = 1 & nNewDim1 = 0);\r\n nMappedDim1 = 1;\r\n sMappedV1 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 2 & nNewDim2 = 0);\r\n nMappedDim2 = 1;\r\n sMappedV2 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 3 & nNewDim3 = 0);\r\n nMappedDim3 = 1;\r\n sMappedV3 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 4 & nNewDim4 = 0);\r\n nMappedDim4 = 1;\r\n sMappedV4 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 5 & nNewDim5 = 0);\r\n nMappedDim5 = 1;\r\n sMappedV5 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 6 & nNewDim6 = 0);\r\n nMappedDim6 = 1;\r\n sMappedV6 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 7 & nNewDim7 = 0);\r\n nMappedDim7 = 1;\r\n sMappedV7 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 8 & nNewDim8 = 0);\r\n nMappedDim8 = 1;\r\n sMappedV8 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 9 & nNewDim9 = 0);\r\n nMappedDim9 = 1;\r\n sMappedV9 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 10 & nNewDim10 = 0);\r\n nMappedDim10 = 1;\r\n sMappedV10 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 11 & nNewDim11 = 0);\r\n nMappedDim11 = 1;\r\n sMappedV11 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 12);\r\n nMappedDim12 = 1;\r\n sMappedV12 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 13);\r\n nMappedDim13 = 1;\r\n sMappedV13 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 14);\r\n nMappedDim14 = 1;\r\n sMappedV14 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 15);\r\n nMappedDim15 = 1;\r\n sMappedV15 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 16);\r\n nMappedDim16 = 1;\r\n sMappedV16 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 17);\r\n nMappedDim17 = 1;\r\n sMappedV17 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 18);\r\n nMappedDim18 = 1;\r\n sMappedV18 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 19);\r\n nMappedDim19 = 1;\r\n sMappedV19 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 20);\r\n nMappedDim20 = 1;\r\n sMappedV20 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 21);\r\n nMappedDim21 = 1;\r\n sMappedV21 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 22);\r\n nMappedDim22 = 1;\r\n sMappedV22 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 23);\r\n nMappedDim23 = 1;\r\n sMappedV23 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 24);\r\n nMappedDim24 = 1;\r\n sMappedV24 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 25);\r\n nMappedDim25 = 1;\r\n sMappedV25 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 26);\r\n nMappedDim26 = 1;\r\n sMappedV26 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 27);\r\n nMappedDim27 = 1;\r\n sMappedV27 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n\r\n# a cube with 27 dimensions uses V28 to hold the values\r\nElseIf(nTargetIndex = 28);\r\n nMappedDim28 = 1;\r\n sMapped28 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nEndIf;\r\n\r\n# Check that an input element or variable has been specified for all dimensions in the target cube\r\n\r\nnIndexInTarget = 1;\r\nWHILE(nIndexInTarget <= nTargetCubeDimensionCount);\r\n \r\n sMapped = Expand('%nMappedDim'| NumberToString(nIndexInTarget) |'%'); \r\n sMapped = Subst( sMapped , Scan( '.' , sMapped )-1 , 99);\r\n nMapped = StringToNumber( Trim( sMapped ) );\r\n sNew = Expand('%nNewDim'| NumberToString(nIndexInTarget) |'%'); \r\n sNew = Subst( sNew , Scan( '.' , sNew )-1 , 99);\r\n nNew = StringToNumber( Trim( sNew ) );\r\n \r\n If(nMapped = 0 & nNew = 0 );\r\n # there's no input element and this dimension is not in the source\r\n nErrors = nErrors + 1;\r\n sTargetDimName = TabDim( pCube, nIndexInTarget );\r\n sMessage = 'Dimension ' | sTargetDimName | ' is missing an input element in pMappingToNewDims';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n EndIf;\r\n \r\n nIndexInTarget = nIndexInTarget + 1;\r\nEND;\r\n#EndRegion ### MAPPING Target DIMENSIONS #####\r\n##############################################\r\n\r\n### Assign Datasource ###\r\nDataSourceType = 'CHARACTERDELIMITED';\r\nDatasourceNameForServer = sFile;\r\nDatasourceNameForClient = sFile;\r\nDatasourceASCIIHeaderRecords = pTitleRows;\r\nDatasourceASCIIDelimiter = pDelimiter;\r\nDatasourceASCIIQuoteCharacter = pQuote;\r\nSetInputCharacterSet (pCharacterSet);\r\n\r\n### End Prolog ###", + "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.data.import', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pCube', '', 'pSrcDir', '', 'pSrcFile', '',\r\n \t'pDim', '', 'pSrcEle', '', 'pTgtEle', '',\r\n \t'pTitleRows', 1, 'pDelim', ',', 'pQuote', '\"', 'pDecimalSeparator', '.', 'pThousandSeparator', ',',\r\n \t'pCumulate', 0, 'pCubeLogging', 0, 'pSandbox', pSandbox, 'pZeroFilter', 0, \r\n \t'pMappingToNewDims','', 'pDimDelim', '&', 'pEleStartDelim', '\u00a6', 'pEleDelim', '+', 'pFileDelete', 0, 'pSkipInvalidRecords', 0\r\n );\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process will load a csv text file to the target cube.\r\n\r\n# Use case: Intended for development/prototyping or in Production environment.\r\n#1/ Import data from another TM1 model.\r\n#2/ To eliminate possibility of locking it is sometimes better to export and import when needing to copy data from one cube to another.\r\n\r\n# Note:\r\n# Naturally, a valid target cube name (pCube) is mandatory otherwise the process will abort.\r\n# Element mapping for new dimensions (pMappingToNewDims ) is also required when the target cube has more dimensions than the source, otherwise the process will abort.\r\n# The default input path is the same as the error file path if not specified.\r\n# If the file name is left blank, the process will look for a file called pCube_Export.csv.\r\n\r\n# Format:\r\n# The assumed file format is as per standard CMA export:\r\n# - v1 specIfies cube name, subsequent fields specify cube address ( individual element names ).\r\n# - vN specIfies cell data value to load. With provision for files with header rows.\r\n# Format of filter row for Zero out:\r\n# - v1 specifies source cube name\r\n# - v2 must be equal to \"Filter\".\r\n# - v3 specifies the filter to be used to zero out. Please note if target cube has additional dimensions this is the final filter used if pMappingToNewDims is not speficied. All the elements in additional dimensions will be cleaned \r\n# - v4 specifies the dimension delimiter used in filter\r\n# - v5 specifies the element start delimiter used in filter\r\n# - v6 specifies the element delimiter used in filter\r\n# Note about the Zero out:\r\n# if pMappingToNewDims parameter is specified, it will be concatenated to the filter in the file to restict the cube slice to be zeroed out. Similarly, if pDim is specified the source element is substituted with the targed one, sould it be in the filter string\r\n# in both cases the delimiters in the source file must match the delimiters passed in parameters of this process.\r\n#EndRegion @DOC\r\n\r\n### Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSub = cThisProcName |'_'| cTimeStamp |'_'| cRandomInt;\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pSrcDir:%pSrcDir%, pSrcFile:%pSrcFile%, pCube:%pCube%, pDim:%pDim%, pSrcEle:%pSrcEle%, pTgtEle:%pTgtEle%, pTitleRows:%pTitleRows%, pDelim:%pDelim%, pQuote:%pQuote%, pCumulate:%pCumulate%, pCubeLogging:%pCubeLogging%, pSandbox:%pSandbox%, pZeroFilter:%pZeroFilter%, pMappingToNewDims:%pMappingToNewDims%, pDimDelim:%pDimDelim%, pEleStartDelim:%pEleStartDelim%, pEleDelim:%pEleDelim%.'; \r\ncMinLenASCIICode = 2;\r\ncMaxLenASCIICode = 3;\r\n\r\n#################################################################################################\r\n#Region - Process Parameters\r\n\r\npJson = IF( JsonType( pJson ) @<> 'object', '{}', pJson );\r\nsMessages = '{\"Process\": \"'|GetProcessName()|'\", \"User\": \"'|TM1User()|'\", \"Info\": [\"Process: '''|GetProcessName()|''' run by User: '''|TM1User()|'''.\"], \"Error\": []}';\r\npDefaultParameters = '{\r\n \"pCharacterSet\": \"TM1CS_UTF8\",\r\n \"pCube\": null,\r\n \"pDecimalSeparator\": \".\",\r\n \"pDelim\": \"\",\r\n \"pDim\": \"\",\r\n \"pDimDelim\": \"&\",\r\n \"pEleDelim\": \"+\",\r\n \"pEleStartDelim\": \"\u00a6\",\r\n \"pMappingToNewDims\": \"\",\r\n \"pQuote\": \"\"\",\r\n \"pSandbox\": \"\",\r\n \"pSrcDir\": \"\",\r\n \"pSrcEle\": \"\",\r\n \"pSrcFile\": \"\",\r\n \"pTgtEle\": \"\",\r\n \"pThousandSeparator\": \",\",\r\n \"pCumulate\": 0,\r\n \"pFileDelete\": 0,\r\n \"pLogOutput\": 0,\r\n \"pSkipInvalidRecords\": 0,\r\n \"pStrictErrorHandling\": 0,\r\n \"pTitleRows\": 1,\r\n \"pZeroFilter\": 0\r\n}';\r\n\r\npPassedParameters = '{\r\n \"pCharacterSet\": '|StringToJson ( pCharacterSet )|',\r\n \"pCube\": '|StringToJson ( pCube )|',\r\n \"pDecimalSeparator\": '|StringToJson ( pDecimalSeparator )|',\r\n \"pDelim\": '|StringToJson ( pDelim )|',\r\n \"pDim\": '|StringToJson ( pDim )|',\r\n \"pDimDelim\": '|StringToJson ( pDimDelim )|',\r\n \"pEleDelim\": '|StringToJson ( pEleDelim )|',\r\n \"pEleStartDelim\": '|StringToJson ( pEleStartDelim )|',\r\n \"pMappingToNewDims\": '|StringToJson ( pMappingToNewDims )|',\r\n \"pQuote\": '|StringToJson ( pQuote )|',\r\n \"pSandbox\": '|StringToJson ( pSandbox )|',\r\n \"pSrcDir\": '|StringToJson ( pSrcDir )|',\r\n \"pSrcEle\": '|StringToJson ( pSrcEle )|',\r\n \"pSrcFile\": '|StringToJson ( pSrcFile )|',\r\n \"pTgtEle\": '|StringToJson ( pTgtEle )|',\r\n \"pThousandSeparator\": '|StringToJson ( pThousandSeparator )|',\r\n \"pCumulate\": '|NumberToString( pCumulate )|',\r\n \"pFileDelete\": '|NumberToString( pFileDelete )|',\r\n \"pLogOutput\": '|NumberToString( pLogOutput )|',\r\n \"pSkipInvalidRecords\": '|NumberToString( pSkipInvalidRecords )|',\r\n \"pStrictErrorHandling\": '|NumberToString( pStrictErrorHandling )|',\r\n \"pTitleRows\": '|NumberToString( pTitleRows )|',\r\n \"pZeroFilter\": '|NumberToString( pZeroFilter )|'\r\n}';\r\n\r\npJson = JsonMergePatch( pPassedParameters, pJson );\r\n# String Parameters\r\npCharacterSet = JsonToString( JsonGet( pJson, 'pCharacterSet' ) );\r\npCube = JsonToString( JsonGet( pJson, 'pCube' ) );\r\npDecimalSeparator = JsonToString( JsonGet( pJson, 'pDecimalSeparator' ) );\r\npDelim = JsonToString( JsonGet( pJson, 'pDelim' ) );\r\npDim = JsonToString( JsonGet( pJson, 'pDim' ) );\r\npDimDelim = JsonToString( JsonGet( pJson, 'pDimDelim' ) );\r\npEleDelim = JsonToString( JsonGet( pJson, 'pEleDelim' ) );\r\npEleStartDelim = JsonToString( JsonGet( pJson, 'pEleStartDelim' ) );\r\npMappingToNewDims = JsonToString( JsonGet( pJson, 'pMappingToNewDims' ) );\r\npQuote = JsonToString( JsonGet( pJson, 'pQuote' ) );\r\npSandbox = JsonToString( JsonGet( pJson, 'pSandbox' ) );\r\npSrcDir = JsonToString( JsonGet( pJson, 'pSrcDir' ) );\r\npSrcEle = JsonToString( JsonGet( pJson, 'pSrcEle' ) );\r\npSrcFile = JsonToString( JsonGet( pJson, 'pSrcFile' ) );\r\npTgtEle = JsonToString( JsonGet( pJson, 'pTgtEle' ) );\r\npThousandSeparator = JsonToString( JsonGet( pJson, 'pThousandSeparator' ) );\r\n# Numeric Parameters\r\npCumulate = StringToNumber( JsonToString( JsonGet( pJson, 'pCumulate' ) ) );\r\npFileDelete = StringToNumber( JsonToString( JsonGet( pJson, 'pFileDelete' ) ) );\r\npLogOutput = StringToNumber( JsonToString( JsonGet( pJson, 'pLogOutput' ) ) );\r\npSkipInvalidRecords = StringToNumber( JsonToString( JsonGet( pJson, 'pSkipInvalidRecords' ) ) );\r\npStrictErrorHandling = StringToNumber( JsonToString( JsonGet( pJson, 'pStrictErrorHandling' ) ) );\r\npTitleRows = StringToNumber( JsonToString( JsonGet( pJson, 'pTitleRows' ) ) );\r\npZeroFilter = StringToNumber( JsonToString( JsonGet( pJson, 'pZeroFilter' ) ) );\r\n\r\n### Get the parameters that differ from the default\r\npDiffer = JsonDiff( pDefaultParameters, pJson );\r\nnSize = JsonSize( pDiffer );\r\nWHILE( nSize > 0 );\r\n nSize = nSize - 1;\r\n pDiffer = JsonReplace( pDiffer, '/'|NumberToString( nSize )|'/op', '\"add\"' );\r\nEND;\r\npJson = JsonPatch( '{}', pDiffer );\r\n\r\n### LogOutput parameters\r\nsMessages = JsonAdd( sMessages, '/Info/-', pJson );\r\nIF( pLogOutput = 1 );\r\n LogOutput('INFO', JsonToString( sMessages, '/Info/0', 0, ' ' ) );\r\nENDIF;\r\n\r\n#EndRegion - Process Parameters\r\n#################################################################################################\r\n\r\npDelimiter = TRIM(pDelim);\r\nsDelimDim = TRIM(pDimDelim);\r\nsElementStartDelim = TRIM(pElEStartDelim);\r\nsDelimElem = TRIM(pEleDelim);\r\npDecimalSeparator = TRIM(pDecimalSeparator);\r\npThousandSeparator = TRIM(pThousandSeparator);\r\n\r\n## LogOutput parameters\r\nIf( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\nnRecordProcessedCount = 0;\r\nnRecordPostedCount = 0;\r\nnErrors = 0;\r\n\r\n\r\n### Validate Parameters ###\r\npSourceDir = TRIM(pSrcDir);\r\npSourceFile = TRIM(pSrcFile);\r\n\r\n## check operating system\r\nIf( SubSt( GetProcessErrorFileDirectory, 2, 1 ) @= ':' );\r\n sOS = 'Windows';\r\n sOSDelim = '\\';\r\nElseIf( Scan( '/', GetProcessErrorFileDirectory ) > 0 );\r\n sOS = 'Linux';\r\n sOSDelim = '/';\r\nElse;\r\n sOS = 'Windows';\r\n sOSDelim = '\\';\r\nEndIf;\r\n\r\n# Validate source directory\r\nIf(Trim( pSourceDir ) @= '' );\r\n pSourceDir = GetProcessErrorFileDirectory;\r\nEndIf;\r\n\r\nIf( SubSt( pSourceDir, Long( pSourceDir ), 1 ) @= sOSDelim );\r\n pSourceDir = SubSt( pSourceDir, 1, Long( pSourceDir ) - 1 );\r\nEndIf;\r\n\r\nIf( FileExists( pSourceDir ) = 0 );\r\n sMessage = 'Invalid source directory specified: folder does not exist.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\nIf( pSourceFile @= '' );\r\n pSourceFile = Expand('%pCube%_Export.csv');\r\nEndIf;\r\n\r\nsFile = pSourceDir | sOSDelim | pSourceFile;\r\n# Validate source file\r\nIf( FileExists( sFile ) = 0 );\r\n sMessage = 'Invalid source file specified: file does not exist in directory:' | sFile;\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Automatic file deletion\r\nIf( pFileDelete <> 1 );\r\n pFileDelete = 0;\r\nEndIf;\r\n\r\n# Skip invalid records\r\nIf( pSkipInvalidRecords <> 1 );\r\n pSkipInvalidRecords = 0;\r\nEndIf;\r\n\r\n## Validate cube\r\nIf( Trim( pCube ) @= '' );\r\n sMessage = 'No target cube specified.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( CubeExists( pCube ) = 0 );\r\n sMessage = 'Invalid target cube specified: ' | pCube;\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate file delimiter & quote character\r\nIf( pDelimiter @= '' );\r\n pDelimiter = ',';\r\nElse;\r\n # If length of pDelimiter is between 2 and 3 chars and each of them is decimal digit, then the pDelimiter is entered as ASCII code\r\n If ( LONG(pDelimiter) <= cMaxLenASCIICode & LONG(pDelimiter) >= cMinLenASCIICode );\r\n nValid = 1;\r\n nChar = 1;\r\n While ( nChar <= LONG(pDelimiter) );\r\n If( CODE( pDelimiter, nChar ) < CODE( '0', 1 ) % CODE( pDelimiter, nChar ) > CODE( '9', 1 ) );\r\n nValid = 0;\r\n Break;\r\n EndIf;\r\n nChar = nChar + 1;\r\n End;\r\n If ( nValid<>0 );\r\n pDelimiter=CHAR(StringToNumber( pDelimiter ));\r\n EndIf;\r\n EndIf;\r\nEndIf;\r\n\r\nIf( pQuote @= '' );\r\n ## Use no quote character \r\nElse;\r\n # If length of pQuote is between 2 and 3 chars and each of them is decimal digit, then the pQuote is entered as ASCII code\r\n If ( LONG(pQuote) <= cMaxLenASCIICode & LONG(pQuote) >= cMinLenASCIICode);\r\n nValid = 1;\r\n nChar = 1;\r\n While ( nChar <= LONG(pQuote) );\r\n If( CODE( pQuote, nChar ) < CODE( '0', 1 ) % CODE( pQuote, nChar ) > CODE( '9', 1 ) );\r\n nValid = 0;\r\n Break;\r\n EndIf;\r\n nChar = nChar + 1;\r\n End;\r\n If ( nValid<>0 );\r\n pQuote=CHAR(StringToNumber( pQuote ));\r\n EndIf;\r\n EndIf;\r\nEndIf;\r\n\r\nIf ( LONG(pDecimalSeparator) <= cMaxLenASCIICode & LONG(pDecimalSeparator) >= cMinLenASCIICode );\r\n nValid = 0;\r\n nChar = 1;\r\n While ( nChar <= LONG(pDecimalSeparator) );\r\n If( CODE( pDecimalSeparator, nChar ) >= CODE( '0', 1 ) & CODE( pDecimalSeparator, nChar ) <= CODE( '9', 1 ) );\r\n nValid = 1;\r\n Else;\r\n nValid = 0;\r\n Break;\r\n EndIf;\r\n nChar = nChar + 1;\r\n End;\r\n If ( nValid<>0 );\r\n pDecimalSeparator = CHAR(StringToNumber( pDecimalSeparator ));\r\n Else;\r\n pDecimalSeparator = SubSt( Trim( pDecimalSeparator ), 1, 1 );\r\n EndIf;\r\nEndIf;\r\nsDecimalSeparator = pDecimalSeparator;\r\n\r\nIf ( LONG(pThousandSeparator) <= cMaxLenASCIICode & LONG(pThousandSeparator) >= cMinLenASCIICode );\r\n nValid = 0;\r\n nChar = 1;\r\n While ( nChar <= LONG(pThousandSeparator) );\r\n If( CODE( pThousandSeparator, nChar ) >= CODE( '0', 1 ) & CODE( pThousandSeparator, nChar ) <= CODE( '9', 1 ) );\r\n nValid = 1;\r\n Else;\r\n nValid = 0;\r\n Break;\r\n EndIf;\r\n nChar = nChar + 1;\r\n End;\r\n If ( nValid<>0 );\r\n pThousandSeparator = CHAR(StringToNumber( pThousandSeparator ));\r\n Else;\r\n pThousandSeparator = SubSt( Trim( pThousandSeparator ), 1, 1 );\r\n EndIf;\r\nEndIf;\r\nsThousandSeparator = pThousandSeparator;\r\n\r\n# Validate Sandbox\r\nIf( TRIM( pSandbox ) @<> '' );\r\n If( ServerSandboxExists( pSandbox ) = 0 );\r\n SetUseActiveSandboxProperty( 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand('Sandbox %pSandbox% is invalid for the current user.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n Else;\r\n ServerActiveSandboxSet( pSandbox );\r\n SetUseActiveSandboxProperty( 1 );\r\n EndIf;\r\nElse;\r\n SetUseActiveSandboxProperty( 0 );\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n## Validate Dimension\r\npDimension = TRIM( pDim);\r\npSourceElement = TRIM(pSrcEle);\r\npTargetElement = TRIM(pTgtEle);\r\n\r\nIf( pDimension @<> '');\r\n \r\n If( DimensionExists( pDimension ) = 0 );\r\n sMessage = 'Invalid dimension specified: ' | pDimension;\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\n\r\n # Validate Source Element\r\n If( pSourceElement @= '' );\r\n sMessage = 'Error: The Source Element parameter is blank.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\n\r\n If( DimIx( pDimension, pSourceElement ) = 0 );\r\n sMessage = 'Invalid source element, ' | pSourceElement | ' specified for ' | pDimension | ' dimension.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\n sSourceElement = DimensionElementPrincipalName( pDimension, pSourceElement);\r\n\r\n # Validate Target Element\r\n If( pTargetElement @= '' );\r\n sMessage = 'Error: The Target Element parameter is blank.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n ElseIf( DimIx( pDimension, pTargetElement ) = 0 );\r\n sMessage = 'Invalid target element, ' | pTargetElement | ' specified for ' | pDimension | ' dimension.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\n sTargetElement = DimensionElementPrincipalName( pDimension, pTargetElement);\r\n\r\nENDIF;\r\n\r\n## Validate delimiter\r\n\r\nIf( pDelimiter @= '' );\r\n sMessage = 'Error: The file delimiter parameter is blank.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( Long( pDelimiter ) > 1 );\r\n sMessage = 'Invalid delimiter specified: ' | pDelimiter | ' field delimiter must be single character or 2-3 symbols number representing ASCII code.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n## Validate quote character\r\nIf( Long( pQuote ) > 1 );\r\n sMessage = 'Invalid string qualIfier: ' | pQuote | ' quote character must be single character or empty string or 2-3 symbols number representing ASCII code.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n### Determine number of dims in target cube ###\r\nnCount = 1;\r\nnSubstututeDimensionIndex = 0;\r\nWhile( \r\nTabDim( pCube, nCount ) @<> '' );\r\n sDimension = TabDim( pCube, nCount );\r\n If( sDimension @= pDimension );\r\n nSubstututeDimensionIndex = nCount;\r\n EndIf;\r\n nCount = nCount + 1;\r\nEnd;\r\nnDimensionCount = nCount - 1;\r\n\r\n## Validate the dimension is part of the cube.\r\nIf( pDimension @= '');\r\n ## CONTINUE;\r\nELSEIf( nSubstututeDimensionIndex = 0 );\r\n sMessage = 'Specified dimension: ' | pDimension | ' is not a component of the cube: ' | pCube;\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nENDIF;\r\n\r\n ## Default filter delimiters\r\n If( pDimDelim @= '' );\r\n pDimDelim = '&';\r\n EndIf;\r\n If( pEleStartDelim@= '' );\r\n pEleStartDelim= '\u00a6';\r\n EndIf;\r\n If( pEleDelim @= '' );\r\n pEleDelim = '+';\r\n EndIf;\r\n \r\n\r\nIf( nDimensionCount > 27 );\r\n sMessage = 'Cube has too many dimensions: ' | pCube | ' max 27 dimensions.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n### Determine dimensions in target cube, we need to know this to test cell type before loading ###\r\nsDim1 = TabDim( pCube, 1 );\r\nsDim2 = TabDim( pCube, 2 );\r\nsDim3 = TabDim( pCube, 3 );\r\nsDim4 = TabDim( pCube, 4 );\r\nsDim5 = TabDim( pCube, 5 );\r\nsDim6 = TabDim( pCube, 6 );\r\nsDim7 = TabDim( pCube, 7 );\r\nsDim8 = TabDim( pCube, 8 );\r\nsDim9 = TabDim( pCube, 9 );\r\nsDim10 = TabDim( pCube, 10 );\r\nsDim11 = TabDim( pCube, 11 );\r\nsDim12 = TabDim( pCube, 12 );\r\nsDim13 = TabDim( pCube, 13 );\r\nsDim14 = TabDim( pCube, 14 );\r\nsDim15 = TabDim( pCube, 15 );\r\nsDim16 = TabDim( pCube, 16 );\r\nsDim17 = TabDim( pCube, 17 );\r\nsDim18 = TabDim( pCube, 18 );\r\nsDim19 = TabDim( pCube, 19 );\r\nsDim20 = TabDim( pCube, 20 );\r\nsDim21 = TabDim( pCube, 21 );\r\nsDim22 = TabDim( pCube, 22 );\r\nsDim23 = TabDim( pCube, 23 );\r\nsDim24 = TabDim( pCube, 24 );\r\nsDim25 = TabDim( pCube, 25 );\r\nsDim26 = TabDim( pCube, 26 );\r\nsDim27 = TabDim( pCube, 27 );\r\n\r\n### Placeholders for mappped dimensions and for new dimensions\r\n\r\nnMappedDim1 = 0;\tsMappedV1 = '';\t\tnNewDim1 = 0;\t sNewV1 = '';\r\nnMappedDim2 = 0;\tsMappedV2 = '';\t\tnNewDim2 = 0;\t sNewV2 = '';\r\nnMappedDim3 = 0;\tsMappedV3 = '';\t\tnNewDim3 = 0;\t sNewV3 = '';\r\nnMappedDim4 = 0;\tsMappedV4 = '';\t\tnNewDim4 = 0;\t sNewV4 = '';\r\nnMappedDim5 = 0;\tsMappedV5 = '';\t\tnNewDim5 = 0;\t sNewV5 = '';\r\nnMappedDim6 = 0;\tsMappedV6 = '';\t\tnNewDim6 = 0;\t sNewV6 = '';\r\nnMappedDim7 = 0;\tsMappedV7 = '';\t\tnNewDim7 = 0;\t sNewV7 = '';\r\nnMappedDim8 = 0;\tsMappedV8 = '';\t\tnNewDim8 = 0;\t sNewV8 = '';\r\nnMappedDim9 = 0;\tsMappedV9 = '';\t\tnNewDim9 = 0;\t sNewV9 = '';\r\nnMappedDim10 = 0;\tsMappedV10 = '';\tnNewDim10 = 0;\tsNewV10 = '';\r\nnMappedDim11 = 0;\tsMappedV11 = '';\tnNewDim11 = 0;\tsNewV11 = '';\r\nnMappedDim12 = 0;\tsMappedV12 = '';\tnNewDim12 = 0;\tsNewV12 = '';\r\nnMappedDim13 = 0;\tsMappedV13 = '';\tnNewDim13 = 0;\tsNewV13 = '';\r\nnMappedDim14 = 0;\tsMappedV14 = '';\tnNewDim14 = 0;\tsNewV14 = '';\r\nnMappedDim15 = 0;\tsMappedV15 = '';\tnNewDim15 = 0;\tsNewV15 = '';\r\nnMappedDim16 = 0;\tsMappedV16 = '';\tnNewDim16 = 0;\tsNewV16 = '';\r\nnMappedDim17 = 0;\tsMappedV17 = '';\tnNewDim17 = 0;\tsNewV17 = '';\r\nnMappedDim18 = 0;\tsMappedV18 = '';\tnNewDim18 = 0;\tsNewV18 = '';\r\nnMappedDim19 = 0;\tsMappedV19 = '';\tnNewDim19 = 0;\tsNewV19 = '';\r\nnMappedDim20 = 0;\tsMappedV20 = '';\tnNewDim20 = 0;\tsNewV20 = '';\r\nnMappedDim21 = 0;\tsMappedV21 = '';\tnNewDim21 = 0;\tsNewV21 = '';\r\nnMappedDim22 = 0;\tsMappedV22 = '';\tnNewDim22 = 0;\tsNewV22 = '';\r\nnMappedDim23 = 0;\tsMappedV23 = '';\tnNewDim23 = 0;\tsNewV23 = '';\r\nnMappedDim24 = 0;\tsMappedV24 = '';\tnNewDim24 = 0;\tsNewV24 = '';\r\nnMappedDim25 = 0;\tsMappedV25 = '';\tnNewDim25 = 0;\tsNewV25 = '';\r\nnMappedDim26 = 0;\tsMappedV26 = '';\tnNewDim26 = 0;\tsNewV26 = '';\r\nnMappedDim27 = 0;\tsMappedV27 = '';\tnNewDim27 = 0;\tsNewV27 = '';\r\n sMappedV28 = '';\r\n\r\n###########################################\r\n### SPLIT MAPPING TO NEW DIMS PARAMETER ###\r\n###########################################\r\n\r\nnTargetCubeDimensionCount = nDimensionCount;\r\n\r\nsElementMapping = TRIM( pMappingToNewDims );\r\nnChar = 1;\r\nnCharCount = LONG( sElementMapping );\r\n\r\nsTargetFilter = '';\r\nsWord = '';\r\nsLastDelim = '';\r\nnIndex = 1;\r\n\r\n# Add a trailing element delimiter so that the last element is picked up\r\nIf( nCharCount > 0 );\r\n sElementMapping = sElementMapping | sDelimDim;\r\n nCharCount = nCharCount + LONG(sDelimDim);\r\nEndIf;\r\n\r\nWHILE (nChar <= nCharCount);\r\n sChar = SUBST( sElementMapping, nChar, 1);\r\n\r\n # Used for delimiters, required for multiple character delimiters\r\n sDelim = '';\r\n nAddExtra = 0;\r\n\r\n # Ignore spaces\r\n IF (TRIM(sChar) @<> '' );\r\n\r\n ### Dimension Name ###\r\n\r\n # If the delimiter is more than 1 character peek ahead the same amount\r\n # Ignore the first character\r\n sDelim = sChar;\r\n nCount = LONG(sElementStartDelim) - 1;\r\n If( nCount > 0 & nChar + nCount <= nCharCount );\r\n # Add the extra characters\r\n sDelim = sDelim | SUBST( sElementMapping, nChar + 1, nCount);\r\n # Move to the end of the delimter\r\n\r\n EndIf;\r\n\r\n If( sDelim @= sElementStartDelim );\r\n nAddExtra = nCount;\r\n sChar = sDelim;\r\n\r\n If( sLastDelim @<> '' & sLastDelim @<> sDelimDim );\r\n sMessage = 'In pMappingToNewDims the name of a dimension must follow a dimension delimiter (' | sDelimDim | ')';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n EndIf;\r\n\r\n # Found a dimension\r\n sDimension = sWord;\r\n\r\n If( DimensionExists( sDimension ) = 0 );\r\n # The dimension does not exist in the model. Cancel process\r\n sMessage = 'In pMappingToNewDims - Dimension: ' | sDimension | ' does not exist';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n EndIf;\r\n \r\n ### Determine the dimension is a member of the cube ###\r\n nMapCount = 1;\r\n nMapDimensionIndex = 0;\r\n While( TabDim( pCube, nMapCount ) @<> '' );\r\n sMapCubeDimName = TabDim( pCube, nMapCount );\r\n If( sDimension @= sMapCubeDimName );\r\n nMapDimensionIndex = nMapCount;\r\n EndIf;\r\n nMapCount = nMapCount + 1;\r\n End;\r\n\r\n If( nMapDimensionIndex = 0 );\r\n # The dimension does not exist in the cube. Cancel process\r\n sMessage = 'Dimension: ' | sDimension | ' is not a member of: '| pCube | ' cube.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n EndIf;\r\n\r\n # Find the index of the dimension is in the Target cube\r\n nTargetIndexCounter = 1;\r\n\r\n WHILE(nTargetIndexCounter <= nTargetCubeDimensionCount );\r\n sNthDimension = TabDim( pCube, nTargetIndexCounter );\r\n\r\n If(sDimension @= sNthDimension);\r\n nTargetIndex = nTargetIndexCounter;\r\n nTargetIndexCounter = 1000;\r\n EndIf;\r\n\r\n nTargetIndexCounter = nTargetIndexCounter + 1;\r\n END;\r\n \r\n #Add to the Target filter\r\n If(sTargetFilter@='');\r\n sTargetFilter=sDimension; \r\n Else;\r\n sTargetFilter=sTargetFilter|sDelimDim|sDimension;\r\n Endif; \r\n \r\n sLastDelim = sChar;\r\n # Clear the word\r\n sWord = '';\r\n\r\n Else;\r\n\r\n # Reset extra chars\r\n nAddExtra = 0;\r\n\r\n ### Check both dim delimiter and element delimiter ###\r\n nIsDelimiter = 0;\r\n\r\n ## Check dimension delimiter first\r\n # If the delimiter is more than 1 character peek ahead the same amount\r\n # Ignore the first character\r\n sDelim = sChar;\r\n nCount = LONG(sDelimDim) - 1;\r\n If( nCount > 0 & nChar + nCount <= nCharCount );\r\n # Add the extra characters\r\n sDelim = sDelim | SUBST( sElementMapping, nChar + 1, nCount);\r\n # Move to the end of the delimter\r\n \r\n EndIf;\r\n\r\n If( sDelim @= sDelimDim );\r\n nIsDelimiter = 1;\r\n sChar = sDelim;\r\n nAddExtra = nCount;\r\n EndIf;\r\n\r\n If ( nIsDelimiter = 1 );\r\n\r\n If( sLastDelim @= '' % sLastDelim @= sDelimDim );\r\n sMessage = 'In pMappingToNewDims - an element delimiter must follow a dimension name: ' | sChar | ' (' | NumberToString(nChar) | ')';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n EndIf;\r\n\r\n # an element has been found\r\n sElement = sWord;\r\n\r\n If( DimIx( sDimension, sElement ) = 0 );\r\n # The element does not exist in the dimension. Cancel process\r\n sMessage = 'In pMappingToNewDims - Element: ' | sElement | ' in dimension ' | sDimension | ' does not exist';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n EndIf;\r\n\r\n # Allow consolidations only if pSuppressConsol is set to 0\r\n\r\n If ( DTYPE( sDimension, sElement) @= 'C' );\r\n sMessage = Expand( 'In pMappingToNewDims - Target element: %sElement% for dimension %sDimension% is consolidated' );\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n Endif; \r\n \r\n\r\n # Add the element to the source or target depending on whether it's the first or the second element\r\n # Get principal name\r\n # in case source element and this element are using different aliases\r\n\r\n sElement = DimensionElementPrincipalName(sDimension,sElement);\r\n\r\n ### Update the variable for InputElement Target Dim ######################################\r\n If(nTargetIndex = 1);\r\n nNewDim1 = 1;\r\n sNewV1 = sElement;\r\n ElseIf(nTargetIndex = 2);\r\n nNewDim2 = 1;\r\n sNewV2 = sElement;\r\n ElseIf(nTargetIndex = 3);\r\n nNewDim3 = 1;\r\n sNewV3 = sElement;\r\n ElseIf(nTargetIndex = 4);\r\n nNewDim4 = 1;\r\n sNewV4 = sElement;\r\n ElseIf(nTargetIndex = 5);\r\n nNewDim5 = 1;\r\n sNewV5 = sElement;\r\n ElseIf(nTargetIndex = 6);\r\n nNewDim6 = 1;\r\n sNewV6 = sElement;\r\n ElseIf(nTargetIndex = 7);\r\n nNewDim7 = 1;\r\n sNewV7 = sElement;\r\n ElseIf(nTargetIndex = 8);\r\n nNewDim8 = 1;\r\n sNewV8 = sElement;\r\n ElseIf(nTargetIndex = 9);\r\n nNewDim9 = 1;\r\n sNewV9 = sElement;\r\n ElseIf(nTargetIndex = 10);\r\n nNewDim10 = 1;\r\n sNewV10 = sElement;\r\n ElseIf(nTargetIndex = 11);\r\n nNewDim11 = 1;\r\n sNewV11 = sElement;\r\n ElseIf(nTargetIndex = 12);\r\n nNewDim12 = 1;\r\n sNewV12 = sElement;\r\n ElseIf(nTargetIndex = 13);\r\n nNewDim13 = 1;\r\n sNewV13 = sElement;\r\n ElseIf(nTargetIndex = 14);\r\n nNewDim14 = 1;\r\n sNewV14 = sElement;\r\n ElseIf(nTargetIndex = 15);\r\n nNewDim15 = 1;\r\n sNewV15 = sElement;\r\n ElseIf(nTargetIndex = 16);\r\n nNewDim16 = 1;\r\n sNewV16 = sElement;\r\n ElseIf(nTargetIndex = 17);\r\n nNewDim17 = 1;\r\n sNewV17 = sElement;\r\n ElseIf(nTargetIndex = 18);\r\n nNewDim18 = 1;\r\n sNewV18 = sElement;\r\n ElseIf(nTargetIndex = 19);\r\n nNewDim19 = 1;\r\n sNewV19 = sElement;\r\n ElseIf(nTargetIndex = 20);\r\n nNewDim20 = 1;\r\n sNewV20 = sElement;\r\n ElseIf(nTargetIndex = 21);\r\n nNewDim21 = 1;\r\n sNewV21 = sElement;\r\n ElseIf(nTargetIndex = 22);\r\n nNewDim22 = 1;\r\n sNewV22 = sElement;\r\n ElseIf(nTargetIndex = 23);\r\n nNewDim23 = 1;\r\n sNewV23 = sElement;\r\n ElseIf(nTargetIndex = 24);\r\n nNewDim24 = 1;\r\n sNewV24 = sElement;\r\n ElseIf(nTargetIndex = 25);\r\n nNewDim25 = 1;\r\n sNewV25 = sElement;\r\n ElseIf(nTargetIndex = 26);\r\n nNewDim26 = 1;\r\n sNewV26 = sElement;\r\n ElseIf(nTargetIndex = 27);\r\n nNewDim27 = 1;\r\n sNewV27 = sElement;\r\n EndIf;\r\n\r\n #Add to the Target filter - no need to manage element separators, since just one target element is possible in mapping\r\n sTargetFilter=sTargetFilter|sElementStartDelim|sElement;\r\n \r\n # Clear the word\r\n sWord = '';\r\n sLastDelim = sChar;\r\n \r\n Else;\r\n sWord = sWord | sChar;\r\n EndIf;\r\n\r\n EndIf;\r\n\r\n EndIf;\r\n\r\n nChar = nChar + nAddExtra + 1;\r\n\r\nEND;\r\n\r\n\r\n###########################################\r\n#Region ### MAPPING Target DIMENSIONS #####\r\n\r\n## Source index starting from 2, since first columns holds the export cube name\r\nnSourceIndex = 2;\r\nnTargetIndex = 1;\r\nWHILE(TabDim( pCube, nTargetIndex ) @<> '');\r\n sTargetDim = TabDim( pCube, nTargetIndex );\r\n \r\n If(nTargetIndex = 1);\r\n If( nNewDim1 = 0 );\r\n nMappedDim1 = 1;\r\n sMappedV1 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n Else;\r\n \r\n EndIf;\r\n ElseIf(nTargetIndex = 2 & nNewDim2 = 0);\r\n nMappedDim2 = 1;\r\n sMappedV2 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 3 & nNewDim3 = 0);\r\n nMappedDim3 = 1;\r\n sMappedV3 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 4 & nNewDim4 = 0);\r\n nMappedDim4 = 1;\r\n sMappedV4 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 5 & nNewDim5 = 0);\r\n nMappedDim5 = 1;\r\n sMappedV5 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 6 & nNewDim6 = 0);\r\n nMappedDim6 = 1;\r\n sMappedV6 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 7 & nNewDim7 = 0);\r\n nMappedDim7 = 1;\r\n sMappedV7 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 8 & nNewDim8 = 0);\r\n nMappedDim8 = 1;\r\n sMappedV8 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 9 & nNewDim9 = 0);\r\n nMappedDim9 = 1;\r\n sMappedV9 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 10 & nNewDim10 = 0);\r\n nMappedDim10 = 1;\r\n sMappedV10 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 11 & nNewDim11 = 0);\r\n nMappedDim11 = 1;\r\n sMappedV11 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 12 & nNewDim12 = 0 );\r\n nMappedDim12 = 1;\r\n sMappedV12 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 13 & nNewDim13 = 0 );\r\n nMappedDim13 = 1;\r\n sMappedV13 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 14 & nNewDim14 = 0 );\r\n nMappedDim14 = 1;\r\n sMappedV14 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 15 & nNewDim15 = 0 );\r\n nMappedDim15 = 1;\r\n sMappedV15 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 16 & nNewDim16 = 0 );\r\n nMappedDim16 = 1;\r\n sMappedV16 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 17 & nNewDim17 = 0 );\r\n nMappedDim17 = 1;\r\n sMappedV17 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 18 & nNewDim18 = 0 );\r\n nMappedDim18 = 1;\r\n sMappedV18 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 19 & nNewDim19 = 0 );\r\n nMappedDim19 = 1;\r\n sMappedV19 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 20 & nNewDim20 = 0 );\r\n nMappedDim20 = 1;\r\n sMappedV20 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 21 & nNewDim21 = 0 );\r\n nMappedDim21 = 1;\r\n sMappedV21 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 22 & nNewDim22 = 0 );\r\n nMappedDim22 = 1;\r\n sMappedV22 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 23 & nNewDim23 = 0 );\r\n nMappedDim23 = 1;\r\n sMappedV23 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 24 & nNewDim24 = 0 );\r\n nMappedDim24 = 1;\r\n sMappedV24 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 25 & nNewDim25 = 0 );\r\n nMappedDim25 = 1;\r\n sMappedV25 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 26 & nNewDim26 = 0 );\r\n nMappedDim26 = 1;\r\n sMappedV26 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n ElseIf(nTargetIndex = 27 & nNewDim27 = 0 );\r\n nMappedDim27 = 1;\r\n sMappedV27 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n EndIf;\r\n\r\n nTargetIndex = nTargetIndex + 1;\r\n\r\nEND;\r\n\r\n# The last variable in the data source holds the values\r\n# which need to be mapped to the last variable in the target\r\n\r\nIf(nTargetIndex = 1 & nNewDim1 = 0);\r\n nMappedDim1 = 1;\r\n sMappedV1 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 2 & nNewDim2 = 0);\r\n nMappedDim2 = 1;\r\n sMappedV2 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 3 & nNewDim3 = 0);\r\n nMappedDim3 = 1;\r\n sMappedV3 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 4 & nNewDim4 = 0);\r\n nMappedDim4 = 1;\r\n sMappedV4 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 5 & nNewDim5 = 0);\r\n nMappedDim5 = 1;\r\n sMappedV5 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 6 & nNewDim6 = 0);\r\n nMappedDim6 = 1;\r\n sMappedV6 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 7 & nNewDim7 = 0);\r\n nMappedDim7 = 1;\r\n sMappedV7 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 8 & nNewDim8 = 0);\r\n nMappedDim8 = 1;\r\n sMappedV8 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 9 & nNewDim9 = 0);\r\n nMappedDim9 = 1;\r\n sMappedV9 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 10 & nNewDim10 = 0);\r\n nMappedDim10 = 1;\r\n sMappedV10 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 11 & nNewDim11 = 0);\r\n nMappedDim11 = 1;\r\n sMappedV11 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 12);\r\n nMappedDim12 = 1;\r\n sMappedV12 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 13);\r\n nMappedDim13 = 1;\r\n sMappedV13 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 14);\r\n nMappedDim14 = 1;\r\n sMappedV14 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 15);\r\n nMappedDim15 = 1;\r\n sMappedV15 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 16);\r\n nMappedDim16 = 1;\r\n sMappedV16 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 17);\r\n nMappedDim17 = 1;\r\n sMappedV17 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 18);\r\n nMappedDim18 = 1;\r\n sMappedV18 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 19);\r\n nMappedDim19 = 1;\r\n sMappedV19 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 20);\r\n nMappedDim20 = 1;\r\n sMappedV20 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 21);\r\n nMappedDim21 = 1;\r\n sMappedV21 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 22);\r\n nMappedDim22 = 1;\r\n sMappedV22 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 23);\r\n nMappedDim23 = 1;\r\n sMappedV23 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 24);\r\n nMappedDim24 = 1;\r\n sMappedV24 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 25);\r\n nMappedDim25 = 1;\r\n sMappedV25 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 26);\r\n nMappedDim26 = 1;\r\n sMappedV26 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nElseIf(nTargetIndex = 27);\r\n nMappedDim27 = 1;\r\n sMappedV27 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\n\r\n# a cube with 27 dimensions uses V28 to hold the values\r\nElseIf(nTargetIndex = 28);\r\n nMappedDim28 = 1;\r\n sMapped28 = 'V' | NumberToString(nSourceIndex);\r\n nSourceIndex = nSourceIndex + 1;\r\nEndIf;\r\n\r\n# Check that an input element or variable has been specified for all dimensions in the target cube\r\n\r\nnIndexInTarget = 1;\r\nWHILE(nIndexInTarget <= nTargetCubeDimensionCount);\r\n \r\n sMapped = Expand('%nMappedDim'| NumberToString(nIndexInTarget) |'%'); \r\n sMapped = Subst( sMapped , Scan( '.' , sMapped )-1 , 99);\r\n nMapped = StringToNumber( Trim( sMapped ) );\r\n sNew = Expand('%nNewDim'| NumberToString(nIndexInTarget) |'%'); \r\n sNew = Subst( sNew , Scan( '.' , sNew )-1 , 99);\r\n nNew = StringToNumber( Trim( sNew ) );\r\n \r\n If(nMapped = 0 & nNew = 0 );\r\n # there's no input element and this dimension is not in the source\r\n nErrors = nErrors + 1;\r\n sTargetDimName = TabDim( pCube, nIndexInTarget );\r\n sMessage = 'Dimension ' | sTargetDimName | ' is missing an input element in pMappingToNewDims';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n EndIf;\r\n \r\n nIndexInTarget = nIndexInTarget + 1;\r\nEND;\r\n#EndRegion ### MAPPING Target DIMENSIONS #####\r\n##############################################\r\n\r\n### Assign Datasource ###\r\nDataSourceType = 'CHARACTERDELIMITED';\r\nDatasourceNameForServer = sFile;\r\nDatasourceNameForClient = sFile;\r\nDatasourceASCIIHeaderRecords = pTitleRows;\r\nDatasourceASCIIDelimiter = pDelimiter;\r\nDatasourceASCIIQuoteCharacter = pQuote;\r\nSetInputCharacterSet (pCharacterSet);\r\n\r\n### End Prolog ###", "MetadataProcedure": "#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "DataProcedure": "#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n# It would be too exhaustive to error trap elements not existing in dimension for each possible number of dimensions\r\n# If an incorrect source file is specfied for a target cube then the TI will error with standard TI error messages.\r\n# Note: that the assumed file format is standard .cma cube export of Cube, d1, d2, dn, value\r\n# This is equivalent to using the Bedrock.Cube.ExportToFile TI.\r\n\r\n## Increase Record count\r\nnRecordProcessedCount = nRecordProcessedCount + 1;\r\n\r\n### Zero out Target view using filter in the 1st record of the data source, if requested\r\nIf( nRecordProcessedCount = 1 );\r\n If( pZeroFilter = 2 );\r\n sRowIsFilter = v2;\r\n sImportedFilter = v3;\r\n sImportedDelimDim = v4;\r\n sImportedElementStartDelim = v5;\r\n sImportedDelimElem = v6;\r\n ### Check Filter row\r\n If(sRowIsFilter @<> 'Filter');\r\n sMessage = 'Filter row in source file not having the expected format.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n ### Check delimiters are the same when using any mapping. This because filter from the file and mappings form the params will be concatenated / substituted\r\n If((sElementMapping @<> '' % pDimension @<>'') & (sDelimDim @<> sImportedDelimDim % sElementStartDelim @<> sImportedElementStartDelim % sDelimElem @<> sImportedDelimElem));\r\n sMessage = 'Error zeroing out target slice corresponding to the filter plus new mapped dimensions: delimiters in source file do not match with the ones in parameters.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n \r\n ### Check filter in source file and validate its dimensions\r\n sFilter = TRIM( sImportedFilter );\r\n nChar = 1;\r\n nCharCount = LONG( sFilter );\r\n sWord = '';\r\n sLastDelim = '';\r\n nIndex = 1;\r\n # Add a trailing element delimiter so that the last element is picked up\r\n If( nCharCount > 0 );\r\n sFilter = sFilter | sDelimElem;\r\n nCharCount = nCharCount + LONG(sDelimElem);\r\n EndIf;\r\n \r\n WHILE (nChar <= nCharCount);\r\n sChar = SUBST( sFilter, nChar, 1);\r\n \r\n # Used for delimiters, required for multiple character delimiters\r\n sDelim = '';\r\n nAddExtra = 0;\r\n \r\n # Ignore spaces\r\n IF (TRIM(sChar) @<> '' );\r\n \r\n ### Dimension Name ###\r\n \r\n # If the delimiter is more than 1 character peek ahead the same amount\r\n # Ignore the first character\r\n sDelim = sChar;\r\n nCount = LONG(sElementStartDelim) - 1;\r\n If( nCount > 0 & nChar + nCount <= nCharCount );\r\n # Add the extra characters\r\n sDelim = sDelim | SUBST( sFilter, nChar + 1, nCount);\r\n # Move to the end of the delimter\r\n nAddExtra = nCount;\r\n EndIf;\r\n \r\n If( sDelim @= sElementStartDelim );\r\n \r\n sChar = sDelim;\r\n \r\n If( sLastDelim @<> '' & sLastDelim @<> sDelimDim );\r\n sMessage = 'The name of a dimension must follow a dimension delimiter (' | sDelimDim | ')';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\n \r\n sDimension = sWord;\r\n \r\n If( DimensionExists( sDimension ) = 0 );\r\n # The dimension does not exist in the model. Cancel process\r\n sMessage = 'Dimension: ' | sDimension | ' does not exist';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\n \r\n ### Determine the dimension is a member of the cube ###\r\n nCount = 1;\r\n nDimensionIndex = 0;\r\n While( TabDim( pCube, nCount ) @<> '' );\r\n sCubeDimName = TabDim( pCube, nCount );\r\n If( sDimension @= sCubeDimName );\r\n nDimensionIndex = nCount;\r\n EndIf;\r\n nCount = nCount + 1;\r\n End;\r\n \r\n If( nDimensionIndex = 0 );\r\n # The dimension does not exist in the cube. Cancel process\r\n sMessage = 'Dimension: ' | sDimension | ' is not a member of: '| pCube | ' cube.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\n \r\n\r\n \r\n nIndex = 1;\r\n sLastDelim = sChar;\r\n # Clear the word\r\n sWord = '';\r\n Else;\r\n \r\n # Reset extra chars\r\n nAddExtra = 0;\r\n \r\n ### Check both both dim delimiter and element delimiter ###\r\n nIsDelimiter = 0;\r\n \r\n ## Check dimension delimiter first\r\n # If the delimiter is more than 1 character peek ahead the same amount\r\n # Ignore the first character\r\n sDelim = sChar;\r\n nCount = LONG(sDelimDim) - 1;\r\n If( nCount > 0 & nChar + nCount <= nCharCount );\r\n # Add the extra characters\r\n sDelim = sDelim | SUBST( sFilter, nChar + 1, nCount);\r\n # Move to the end of the delimter\r\n nAddExtra = nCount;\r\n EndIf;\r\n \r\n If( sDelim @= sDelimDim );\r\n nIsDelimiter = 1;\r\n sChar = sDelim;\r\n Else;\r\n # Reset extra chars\r\n nAddExtra = 0;\r\n \r\n ## Check element delimiter\r\n \r\n # If the delimiter is more than 1 character peek ahead the same amount\r\n # Ignore the first character\r\n sDelim = sChar;\r\n nCount = LONG(sDelimElem) - 1;\r\n If( nCount > 0 & nChar + nCount <= nCharCount );\r\n # Add the extra characters\r\n sDelim = sDelim | SUBST( sFilter, nChar + 1, nCount);\r\n # Move to the end of the delimter\r\n nAddExtra = nCount;\r\n EndIf;\r\n \r\n If( sDelim @= sDelimElem );\r\n nIsDelimiter = 1;\r\n sChar = sDelim;\r\n Else;\r\n # Reset extra chars\r\n nAddExtra = 0;\r\n EndIf;\r\n \r\n EndIf;\r\n \r\n If ( nIsDelimiter = 1 );\r\n \r\n If( sLastDelim @= '' % sLastDelim @= sDelimDim );\r\n sMessage = 'An element delimiter must follow a dimension name: ' | sChar | ' (' | NumberToString(nChar) | ')';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n EndIf;\r\n \r\n sElement = sWord;\r\n \r\n If( DimIx( sDimension, sElement ) = 0 );\r\n # The element does not exist in the dimension. Cancel process\r\n sMessage = 'Element: ' | sElement | ' in dimension ' | sDimension | ' does not exist';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n EndIf;\r\n \r\n nIndex = nIndex + 1;\r\n sLastDelim = sChar;\r\n \r\n # Clear the word\r\n sWord = '';\r\n Else;\r\n sWord = sWord | sChar;\r\n EndIf;\r\n \r\n EndIf;\r\n \r\n EndIf;\r\n \r\n nChar = nChar + nAddExtra + 1;\r\n END;\r\n\r\n ### Check for errors before continuing\r\n If( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n EndIf;\r\n \r\n If( sTargetFilter @= '' );\r\n sTargetFilter = sImportedFilter;\r\n Else;\r\n sTargetFilter = sTargetFilter | sDelimDim | sImportedFilter;\r\n EndIf;\r\n ### Determine target dimension substitution in data clear filter\r\n If( pDimension @<>'');\r\n If( sTargetFilter @= '' );\r\n sTargetFilter = pDimension | sElementStartDelim | sTargetElement;\r\n Else;\r\n ### Remove spaces from the string, then remove source element from the filter if present\r\n sTargetFilter = UPPER( sTargetFilter );\r\n nSPIndex = SCAN( ' ', sTargetFilter );\r\n While ( nSPIndex <> 0);\r\n sTargetFilter = DELET( sTargetFilter, nSPIndex, 1 );\r\n nSPIndex = SCAN( ' ', sTargetFilter );\r\n End;\r\n sRemoveString = UPPER( sDelimDim | pDimension | sElementStartDelim | pSrcEle );\r\n nRemoveIndex = SCAN( sRemoveString, sTargetFilter );\r\n If( nRemoveIndex <> 0 );\r\n sTargetFilter = DELET( sTargetFilter, nRemoveIndex, Long(sRemoveString) );\r\n EndIf;\r\n sRemoveString2 = UPPER( pDimension | sElementStartDelim | pSrcEle | sDelimDim );\r\n nRemoveIndex = SCAN( sRemoveString2, sTargetFilter );\r\n If( nRemoveIndex <> 0 );\r\n sTargetFilter = DELET( sTargetFilter, nRemoveIndex, Long(sRemoveString2) );\r\n EndIf;\r\n sRemoveString3 = UPPER( sDelimDim | pDimension | sElementStartDelim | sSourceElement );\r\n nRemoveIndex = SCAN( sRemoveString3, sTargetFilter );\r\n If( nRemoveIndex <> 0 );\r\n sTargetFilter = DELET( sTargetFilter, nRemoveIndex, Long(sRemoveString3) );\r\n EndIf;\r\n sRemoveString4 = UPPER( pDimension | sElementStartDelim | sSourceElement | sDelimDim );\r\n nRemoveIndex = SCAN( sRemoveString4, sTargetFilter );\r\n If( nRemoveIndex <> 0 );\r\n sTargetFilter = DELET( sTargetFilter, nRemoveIndex, Long(sRemoveString4) );\r\n EndIf;\r\n ## Add target element to the filter\r\n sTargetFilter = sTargetFilter | sDelimDim | pDimension | sElementStartDelim | sTargetElement;\r\n EndIf;\r\n Endif;\r\n \r\n nRet = ExecuteProcess('}bedrock.cube.data.clear',\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCube,\r\n 'pView', '',\r\n 'pFilter', sTargetFilter,\r\n 'pFilterParallel', '',\r\n 'pParallelThreads', 0,\r\n 'pDimDelim', sImportedDelimDim,\r\n 'pEleStartDelim', sImportedElementStartDelim,\r\n 'pEleDelim', sImportedDelimElem,\r\n 'pCubeLogging', pCubeLogging,\r\n 'pTemp', 1,\r\n 'pSandbox', pSandbox\r\n );\r\n \r\n If(nRet <> 0);\r\n sMessage = 'Error zeroing out target slice corresponding to the filter.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n ENDIF;\r\n If( pZeroFilter > 0 );\r\n ItemSkip;\r\n ENDIF;\r\nEndif;\r\n\r\n### Determine target dimension SubStitution ###\r\nIf( pDimension @<>'');\r\n \r\n If(sSourceElement@<>Expand('%v'|numbertostring(nSubstututeDimensionIndex+1)|'%'));\r\n # leave variable as is\r\n Else; \r\n \r\n v2 = If(nSubstututeDimensionIndex = 1, sTargetElement, v2);\r\n v3 = If(nSubstututeDimensionIndex = 2, sTargetElement, v3);\r\n v4 = If(nSubstututeDimensionIndex = 3, sTargetElement, v4);\r\n v5 = If(nSubstututeDimensionIndex = 4, sTargetElement, v5);\r\n v6 = If(nSubstututeDimensionIndex = 5, sTargetElement, v6);\r\n v7 = If(nSubstututeDimensionIndex = 6, sTargetElement, v7);\r\n v8 = If(nSubstututeDimensionIndex = 7, sTargetElement, v8);\r\n v9 = If(nSubstututeDimensionIndex = 8, sTargetElement, v9);\r\n v10 = If(nSubstututeDimensionIndex = 9, sTargetElement, v10);\r\n v11 = If(nSubstututeDimensionIndex = 10, sTargetElement, v11);\r\n v12 = If(nSubstututeDimensionIndex = 11, sTargetElement, v12);\r\n v13 = If(nSubstututeDimensionIndex = 12, sTargetElement, v13);\r\n v14 = If(nSubstututeDimensionIndex = 13, sTargetElement, v14);\r\n v15 = If(nSubstututeDimensionIndex = 14, sTargetElement, v15);\r\n v16 = If(nSubstututeDimensionIndex = 15, sTargetElement, v16);\r\n v17 = If(nSubstututeDimensionIndex = 16, sTargetElement, v17);\r\n v18 = If(nSubstututeDimensionIndex = 17, sTargetElement, v18);\r\n v19 = If(nSubstututeDimensionIndex = 18, sTargetElement, v19);\r\n v20 = If(nSubstututeDimensionIndex = 19, sTargetElement, v20);\r\n v21 = If(nSubstututeDimensionIndex = 20, sTargetElement, v21);\r\n v22 = If(nSubstututeDimensionIndex = 21, sTargetElement, v22);\r\n v23 = If(nSubstututeDimensionIndex = 22, sTargetElement, v23);\r\n v24 = If(nSubstututeDimensionIndex = 23, sTargetElement, v24);\r\n v25 = If(nSubstututeDimensionIndex = 24, sTargetElement, v25);\r\n v26 = If(nSubstututeDimensionIndex = 25, sTargetElement, v26);\r\n v27 = If(nSubstututeDimensionIndex = 26, sTargetElement, v27);\r\n EndIf;\r\n\r\nEndif;\r\n\r\n### Determine dimension Mapping SubStitution ###\r\nsV2 =If(nMappedDim1=1, Expand('%'|sMappedV1|'%'), If(nNewDim1=1, sNewV1,V1));\r\nsV3 =If(nMappedDim2=1, Expand('%'|sMappedV2|'%'), If(nNewDim2=1, sNewV2,V2));\r\nsV4 =If(nMappedDim3=1, Expand('%'|sMappedV3|'%'), If(nNewDim3=1, sNewV3,V3));\r\nsV5 =If(nMappedDim4=1, Expand('%'|sMappedV4|'%'), If(nNewDim4=1, sNewV4,V4));\r\nsV6 =If(nMappedDim5=1, Expand('%'|sMappedV5|'%'), If(nNewDim5=1, sNewV5,V5));\r\nsV7 =If(nMappedDim6=1, Expand('%'|sMappedV6|'%'), If(nNewDim6=1, sNewV6,V6));\r\nsV8 =If(nMappedDim7=1, Expand('%'|sMappedV7|'%'), If(nNewDim7=1, sNewV7,V7));\r\nsV9 =If(nMappedDim8=1, Expand('%'|sMappedV8|'%'), If(nNewDim8=1, sNewV8,V8));\r\nsV10 =If(nMappedDim9=1, Expand('%'|sMappedV9|'%'), If(nNewDim9=1, sNewV9,V9));\r\nsV11=If(nMappedDim10=1, Expand('%'|sMappedV10|'%'),If(nNewDim10=1,sNewV10,V10));\r\nsV12=If(nMappedDim11=1, Expand('%'|sMappedV11|'%'),If(nNewDim11=1,sNewV11,V11));\r\nsV13=If(nMappedDim12=1, Expand('%'|sMappedV12|'%'),If(nNewDim12=1,sNewV12,V12)); \r\nsV14=If(nMappedDim13=1, Expand('%'|sMappedV13|'%'),If(nNewDim13=1,sNewV13,V13)); \r\nsV15=If(nMappedDim14=1, Expand('%'|sMappedV14|'%'),If(nNewDim14=1,sNewV14,V14)); \r\nsV16=If(nMappedDim15=1, Expand('%'|sMappedV15|'%'),If(nNewDim15=1,sNewV15,V15)); \r\nsV17=If(nMappedDim16=1, Expand('%'|sMappedV16|'%'),If(nNewDim16=1,sNewV16,V16)); \r\nsV18=If(nMappedDim17=1, Expand('%'|sMappedV17|'%'),If(nNewDim17=1,sNewV17,V17)); \r\nsV19=If(nMappedDim18=1, Expand('%'|sMappedV18|'%'),If(nNewDim18=1,sNewV18,V18)); \r\nsV20=If(nMappedDim19=1, Expand('%'|sMappedV19|'%'),If(nNewDim19=1,sNewV19,V19)); \r\nsV21=If(nMappedDim20=1, Expand('%'|sMappedV20|'%'),If(nNewDim20=1,sNewV20,V20)); \r\nsV22=If(nMappedDim21=1, Expand('%'|sMappedV21|'%'),If(nNewDim21=1,sNewV21,V21)); \r\nsV23=If(nMappedDim22=1, Expand('%'|sMappedV22|'%'),If(nNewDim22=1,sNewV22,V22)); \r\nsV24=If(nMappedDim23=1, Expand('%'|sMappedV23|'%'),If(nNewDim23=1,sNewV23,V23)); \r\nsV25=If(nMappedDim24=1, Expand('%'|sMappedV24|'%'),If(nNewDim24=1,sNewV24,V24)); \r\nsV26=If(nMappedDim25=1, Expand('%'|sMappedV25|'%'),If(nNewDim25=1,sNewV25,V25)); \r\nsV27=If(nMappedDim26=1, Expand('%'|sMappedV26|'%'),If(nNewDim26=1,sNewV26,V26)); \r\nsV28=If(nMappedDim27=1, Expand('%'|sMappedV27|'%'),If(nNewDim27=1,sNewV27,V27));\r\nsV29=If(nMappedDim28=1, Expand('%'|sMappedV28|'%'),V28); \r\n \r\nV1 = V1;\r\nV2 = sV2; \r\nV3 = sV3; \r\nV4 = sV4; \r\nV5 = sV5; \r\nV6 = sV6; \r\nV7 = sV7; \r\nV8 = sV8; \r\nV9 = sV9; \r\nV10= sV10;\r\nV11= sV11;\r\nV12= sV12;\r\nV13= sV13;\r\nV14= sV14;\r\nV15= sV15;\r\nV16= sV16;\r\nV17= sV17;\r\nV18= sV18;\r\nV19= sV19;\r\nV20= sV20;\r\nV21= sV21;\r\nV22= sV22;\r\nV23= sV23;\r\nV24= sV24;\r\nV25= sV25;\r\nV26= sV26;\r\nV27= sV27;\r\nV28= sV28;\r\nV29= sV29;\r\n \r\nIf( pSkipInvalidRecords < 1 );\r\n ## Do not check for a valid datapoint (any element that doesn't exist will generate error message on CellPut attempt)\r\nElse;\r\n ## Allow records that do not have a valid datapoint to be skipped.\r\n If( nDimensionCount >= 2 & (DimIx( sDim1, v2 ) = 0 % DimIx( sDim2, v3 ) = 0 ) );\r\n ItemSkip;\r\n EndIf;\r\n \r\n If( nDimensionCount >= 3 & DimIx( sDim3, v4 ) = 0 );\r\n ItemSkip;\r\n EndIf;\r\n\r\n If( nDimensionCount >= 4 & DimIx( sDim4, v5 ) = 0 );\r\n ItemSkip;\r\n EndIf;\r\n \r\n If( nDimensionCount >= 5 & DimIx( sDim5, v6 ) = 0 );\r\n ItemSkip;\r\n EndIf;\r\n\r\n If( nDimensionCount >= 6 & DimIx( sDim6, v7 ) = 0 );\r\n ItemSkip;\r\n EndIf;\r\n\r\n If( nDimensionCount >= 7 & DimIx( sDim7, v8 ) = 0 );\r\n ItemSkip;\r\n EndIf;\r\n \r\n If( nDimensionCount >= 8 & DimIx( sDim8, v9 ) = 0 );\r\n ItemSkip;\r\n EndIf;\r\n \r\n If( nDimensionCount >= 9 & DimIx( sDim9, v10 ) = 0 );\r\n ItemSkip;\r\n EndIf;\r\n \r\n If( nDimensionCount >= 10 & DimIx( sDim10, v11 ) = 0 );\r\n ItemSkip;\r\n EndIf;\r\n \r\n If( nDimensionCount >= 11 & DimIx( sDim11, v12 ) = 0 );\r\n ItemSkip;\r\n EndIf;\r\n \r\n If( nDimensionCount >= 12 & DimIx( sDim12, v13 ) = 0 );\r\n ItemSkip;\r\n EndIf;\r\n \r\n If( nDimensionCount >= 13 & DimIx( sDim13, v14 ) = 0 );\r\n ItemSkip;\r\n EndIf;\r\n \r\n If( nDimensionCount >= 14 & DimIx( sDim14, v15 ) = 0 );\r\n ItemSkip;\r\n EndIf;\r\n \r\n If( nDimensionCount >= 15 & DimIx( sDim15, v16 ) = 0 );\r\n ItemSkip;\r\n EndIf;\r\n \r\n If( nDimensionCount >= 16 & DimIx( sDim16, v17 ) = 0 );\r\n ItemSkip;\r\n EndIf;\r\n \r\n If( nDimensionCount >= 17 & DimIx( sDim17, v18 ) = 0 );\r\n ItemSkip;\r\n EndIf;\r\n \r\n If( nDimensionCount >= 18 & DimIx( sDim18, v19 ) = 0 );\r\n ItemSkip;\r\n EndIf;\r\n \r\n If( nDimensionCount >= 19 & DimIx( sDim19, v20 ) = 0 );\r\n ItemSkip;\r\n EndIf;\r\n \r\n If( nDimensionCount >= 20 & DimIx( sDim20, v21 ) = 0 );\r\n ItemSkip;\r\n EndIf;\r\n \r\n If( nDimensionCount >= 21 & DimIx( sDim21, v22 ) = 0 );\r\n ItemSkip;\r\n EndIf;\r\n \r\n If( nDimensionCount >= 22 & DimIx( sDim22, v23 ) = 0 );\r\n ItemSkip;\r\n EndIf;\r\n \r\n If( nDimensionCount >= 23 & DimIx( sDim23, v24 ) = 0 );\r\n ItemSkip;\r\n EndIf;\r\n\r\n If( nDimensionCount >= 24 & DimIx( sDim24, v25 ) = 0 );\r\n ItemSkip;\r\n EndIf;\r\n \r\n If( nDimensionCount >= 25 & DimIx( sDim25, v26 ) = 0 );\r\n ItemSkip;\r\n EndIf;\r\n \r\n If( nDimensionCount >= 26 & DimIx( sDim25, v27 ) = 0 );\r\n ItemSkip;\r\n EndIf;\r\n \r\n If( nDimensionCount >= 27 & DimIx( sDim27, v28 ) = 0 );\r\n ItemSkip;\r\n EndIf;\r\n\r\nEndIf;\r\n\r\n### Write data from source file to target cube ###\r\n\r\nIf( nDimensionCount = 2 );\r\n If( CellIsUpdateable( pCube, v2, v3 ) = 1 );\r\n sElType = DType( sDim2, v3 );\r\n If( SubSt( sDim2, 1, 19 ) @= '}ElementAttributes_' % SubSt( pCube, 1, 17 ) @= '}ElementSecurity_' );\r\n sDim = sDim1;\r\n EndIf;\r\n If( SubSt( pCube, 1, 17 ) @= '}ElementSecurity_' );\r\n v4 = If( v4 @= '', 'NONE', v4 );\r\n ElementSecurityPut( v4, sDim, v2, v3 );\r\n ElseIf( SubSt( sDim2, 1, 19 ) @= '}ElementAttributes_' );\r\n If( sElType @= 'AS');\r\n AttrPutS( v4, sDim, v2, v3 );\r\n ElseIf( sElType @= 'AA');\r\n AttrPutS( v4, sDim, v2, v3, 1 );\r\n ElseIf( sElType @= 'AN');\r\n AttrPutN( StringToNumberEx(v4, sDecimalSeparator, sThousandSeparator), sDim, v2, v3 );\r\n EndIf;\r\n ElseIf( SubSt( sElType, 1, 1) @= 'A' );\r\n If( sElType @= 'AA' % sElType @= 'AS' );\r\n If( pCube @= '}ChoreAttributes' );\r\n ChoreAttrPutS( v4, v2, v3 );\r\n ElseIf( pCube @= '}CubeAttributes' );\r\n CubeAttrPutS( v4, v2, v3 );\r\n ElseIf( pCube @= '}DimensionAttributes' );\r\n DimensionAttrPutS( v4, v2, v3 );\r\n ElseIf( pCube @= '}ProcessAttributes' );\r\n ProcessAttrPutS( v4, v2, v3 );\r\n EndIf;\r\n ElseIf( sElType @= 'AN');\r\n If( pCube @= '}ChoreAttributes' );\r\n ChoreAttrPutN( StringToNumberEx(v4, sDecimalSeparator, sThousandSeparator), v2, v3 );\r\n ElseIf( pCube @= '}CubeAttributes' );\r\n CubeAttrPutN( StringToNumberEx(v4, sDecimalSeparator, sThousandSeparator), v2, v3 );\r\n ElseIf( pCube @= '}DimensionAttributes' );\r\n DimensionAttrPutN( StringToNumberEx(v4, sDecimalSeparator, sThousandSeparator), v2, v3 );\r\n ElseIf( pCube @= '}ProcessAttributes' );\r\n ProcessAttrPutN( StringToNumberEx(v4, sDecimalSeparator, sThousandSeparator), v2, v3 );\r\n EndIf;\r\n EndIf;\r\n ElseIf( sElType @= 'S');\r\n CellPutS( v4, pCube, v2, v3 );\r\n ElseIf( sElType @= 'N' & DimIx( sDim2, v3 ) <> 0 );\r\n If(pCumulate = 1);\r\n nObal = CellGetN( pCube, v2, v3 );\r\n nCbal = nObal + StringToNumberEx(v4, sDecimalSeparator, sThousandSeparator);\r\n ELSE;\r\n nCbal = StringToNumberEx(v4, sDecimalSeparator, sThousandSeparator);\r\n Endif;\r\n CellPutN( nCbal, pCube, v2, v3 );\r\n Else;\r\n If( pStrictErrorHandling = 1 );\r\n sErr = Expand('Unhandled element type %sElType% of element %v3% in dimension %sDim2%');\r\n ItemReject( sErr );\r\n EndIf;\r\n EndIf;\r\n EndIf;\r\nElseIf( nDimensionCount = 3 );\r\n If( CellIsUpdateable( pCube, v2, v3, v4 ) = 1 );\r\n sElType = DType( sDim3, v4 );\r\n If( SubSt( sElType, 1, 1 ) @= 'A' );\r\n If( SubSt( pCube, 1, 28 ) @= '}LocalizedElementAttributes_' );\r\n sDim = sDim1;\r\n If( sElType @= 'AS' );\r\n AttrPutS(v5, sDim, v2, v4, v3);\r\n ElseIf( sElType @= 'AA' );\r\n AttrPutS(v5, sDim, v2, v4, v3, 1);\r\n ElseIf( sElType @= 'AN' );\r\n AttrPutN(StringToNumberEx(v5, sDecimalSeparator, sThousandSeparator), sDim, v2, v4, v3);\r\n EndIf;\r\n ElseIf( pCube @= '}LocalizedChoreAttributes' );\r\n If( sElType @= 'AS' % sElType @= 'AA' );\r\n ChoreAttrPutS(v5, v2, v4, v3);\r\n ElseIf( sElType @= 'AN' );\r\n ChoreAttrPutN(StringToNumberEx(v5, sDecimalSeparator, sThousandSeparator), v2, v4, v3);\r\n EndIf;\r\n ElseIf( pCube @= '}LocalizedCubeAttributes' );\r\n If( sElType @= 'AS' % sElType @= 'AA' );\r\n CubeAttrPutS(v5, v2, v4, v3);\r\n ElseIf( sElType @= 'AN' );\r\n CubeAttrPutN(StringToNumberEx(v5, sDecimalSeparator, sThousandSeparator), v2, v4, v3);\r\n EndIf;\r\n ElseIf( pCube @= '}LocalizedDimensionAttributes' );\r\n If( sElType @= 'AS' % sElType @= 'AA' );\r\n DimensionAttrPutS(v5, v2, v4, v3);\r\n ElseIf( sElType @= 'AN' );\r\n DimensionAttrPutN(StringToNumberEx(v5, sDecimalSeparator, sThousandSeparator), v2, v4, v3);\r\n EndIf;\r\n ElseIf( pCube @= '}LocalizedProcessAttributes' );\r\n If( sElType @= 'AS' % sElType @= 'AA' );\r\n ProcessAttrPutS(v5, v2, v4, v3);\r\n ElseIf( sElType @= 'AN' );\r\n ProcessAttrPutN(StringToNumberEx(v5, sDecimalSeparator, sThousandSeparator), v2, v4, v3);\r\n EndIf;\r\n EndIf;\r\n ElseIf( sElType @= 'N' );\r\n If(pCumulate = 1);\r\n nObal = CellGetN( pCube, v2, v3, v4 );\r\n nCbal = nObal + StringToNumberEx(v5, sDecimalSeparator, sThousandSeparator);\r\n ELSE;\r\n nCbal = StringToNumberEx(v5, sDecimalSeparator, sThousandSeparator);\r\n Endif;\r\n CellPutN( nCbal, pCube, v2, v3, v4 );\r\n ElseIf( sElType @= 'S' );\r\n CellPutS( v5, pCube, v2, v3, v4 );\r\n Else;\r\n If( pStrictErrorHandling = 1 );\r\n sErr = Expand('Unhandled element type %sElType% of element %v4% in dimension %sDim3%');\r\n ItemReject( sErr );\r\n EndIf;\r\n EndIf;\r\n EndIf;\r\nElseIf( nDimensionCount = 4 );\r\n If( CellIsUpdateable( pCube, v2, v3, v4, v5 ) = 1 );\r\n sElType = DType( sDim4, v5 );\r\n If( sElType @= 'N' );\r\n If(pCumulate = 1);\r\n nObal = CellGetN( pCube, v2, v3, v4, v5 );\r\n nCbal = nObal + StringToNumberEx(v6, sDecimalSeparator, sThousandSeparator);\r\n ELSE;\r\n nCbal = StringToNumberEx(v6, sDecimalSeparator, sThousandSeparator);\r\n Endif;\r\n CellPutN( nCbal, pCube, v2, v3, v4, v5 );\r\n ElseIf( sElType @= 'S' );\r\n CellPutS( v6, pCube, v2, v3, v4, v5 );\r\n Else;\r\n If( pStrictErrorHandling = 1 );\r\n sErr = Expand('Unhandled element type %sElType% of element %v5% in dimension %sDim4%');\r\n ItemReject( sErr );\r\n EndIf;\r\n EndIf;\r\n EndIf;\r\nElseIf( nDimensionCount = 5 );\r\n If( CellIsUpdateable( pCube, v2, v3, v4, v5, v6 ) = 1 );\r\n sElType = DType( sDim5, v6 );\r\n If( sElType @= 'N' );\r\n If(pCumulate = 1);\r\n nObal = CellGetN( pCube, v2, v3, v4, v5, v6 );\r\n nCbal = nObal + StringToNumberEx(v7, sDecimalSeparator, sThousandSeparator);\r\n ELSE;\r\n nCbal = StringToNumberEx(v7, sDecimalSeparator, sThousandSeparator);\r\n Endif;\r\n CellPutN( nCbal, pCube, v2, v3, v4, v5, v6 );\r\n ElseIf( sElType @= 'S' );\r\n CellPutS( v7, pCube, v2, v3, v4, v5, v6 );\r\n Else;\r\n If( pStrictErrorHandling = 1 );\r\n sErr = Expand('Unhandled element type %sElType% of element %v6% in dimension %sDim5%');\r\n ItemReject( sErr );\r\n EndIf;\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 6 );\r\n If( CellIsUpdateable( pCube, v2, v3, v4, v5, v6, v7 ) = 1 );\r\n sElType = DType( sDim6, v7 );\r\n If( sElType @= 'N' );\r\n If(pCumulate = 1);\r\n nObal = CellGetN( pCube, v2, v3, v4, v5, v6, v7 );\r\n nCbal = nObal + StringToNumberEx(v8, sDecimalSeparator, sThousandSeparator);\r\n ELSE;\r\n nCbal = StringToNumberEx(v8, sDecimalSeparator, sThousandSeparator);\r\n Endif;\r\n CellPutN( nCbal, pCube, v2, v3, v4, v5, v6, v7 );\r\n ElseIf( sElType @= 'S' );\r\n CellPutS( v8, pCube, v2, v3, v4, v5, v6, v7 );\r\n EndIf;\r\n Else;\r\n If( pStrictErrorHandling = 1 );\r\n sErr = Expand('Unhandled element type %sElType% of element %v7% in dimension %sDim6%');\r\n ItemReject( sErr );\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 7 );\r\n If( CellIsUpdateable( pCube, v2, v3, v4, v5, v6, v7, v8 ) = 1 );\r\n sElType = DType( sDim7, v8 );\r\n If( sElType @= 'N' );\r\n If( pCumulate = 1);\r\n nObal = CellGetN( pCube, v2, v3, v4, v5, v6, v7, v8 );\r\n nCbal = nObal + StringToNumberEx(v9, sDecimalSeparator, sThousandSeparator);\r\n ELSE;\r\n nCbal = StringToNumberEx(v9, sDecimalSeparator, sThousandSeparator);\r\n Endif;\r\n CellPutN( nCbal, pCube, v2, v3, v4, v5, v6, v7, v8 );\r\n ElseIf( sElType @= 'S' );\r\n CellPutS( v9, pCube, v2, v3, v4, v5, v6, v7, v8 );\r\n Else;\r\n If( pStrictErrorHandling = 1 );\r\n sErr = Expand('Unhandled element type %sElType% of element %v8% in dimension %sDim7%');\r\n ItemReject( sErr );\r\n EndIf;\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 8 );\r\n If( CellIsUpdateable( pCube, v2, v3, v4, v5, v6, v7, v8, v9 ) = 1 );\r\n sElType = DType( sDim8, v9 );\r\n If( sElType @= 'N' );\r\n If( pCumulate = 1);\r\n nObal = CellGetN( pCube, v2, v3, v4, v5, v6, v7, v8, v9 );\r\n nCbal = nObal + StringToNumberEx(v10, sDecimalSeparator, sThousandSeparator);\r\n ELSE;\r\n nCbal = StringToNumberEx(v10, sDecimalSeparator, sThousandSeparator);\r\n Endif;\r\n CellPutN( nCbal, pCube, v2, v3, v4, v5, v6, v7, v8, v9 );\r\n ElseIf( sElType @= 'S' );\r\n CellPutS( v10, pCube, v2, v3, v4, v5, v6, v7, v8, v9 );\r\n Else;\r\n If( pStrictErrorHandling = 1 );\r\n sErr = Expand('Unhandled element type %sElType% of element %v9% in dimension %sDim8%');\r\n ItemReject( sErr );\r\n EndIf;\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 9 );\r\n If( CellIsUpdateable( pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10 ) = 1 );\r\n sElType = DType( sDim9, v10 );\r\n If( sElType @= 'N' );\r\n If( pCumulate = 1);\r\n nObal = CellGetN( pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10 );\r\n nCbal = nObal + StringToNumberEx(v11, sDecimalSeparator, sThousandSeparator);\r\n ELSE;\r\n nCbal = StringToNumberEx(v11, sDecimalSeparator, sThousandSeparator);\r\n Endif;\r\n CellPutN( nCbal, pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10 );\r\n ElseIf( sElType @= 'S' );\r\n CellPutS( v11, pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10 );\r\n Else;\r\n If( pStrictErrorHandling = 1 );\r\n sErr = Expand('Unhandled element type %sElType% of element %v10% in dimension %sDim9%');\r\n ItemReject( sErr );\r\n EndIf;\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 10 );\r\n If( CellIsUpdateable( pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11 ) = 1 );\r\n sElType = DType( sDim10, v11 );\r\n If( sElType @= 'N' );\r\n If(pCumulate = 1);\r\n nObal = CellGetN( pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11 );\r\n nCbal = nObal + StringToNumberEx(v12, sDecimalSeparator, sThousandSeparator);\r\n ELSE;\r\n nCbal = StringToNumberEx(v12, sDecimalSeparator, sThousandSeparator);\r\n Endif;\r\n CellPutN( nCbal, pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11 );\r\n ElseIf( sElType @= 'S' );\r\n CellPutS( v12, pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11 );\r\n Else;\r\n If( pStrictErrorHandling = 1 );\r\n sErr = Expand('Unhandled element type %sElType% of element %v11% in dimension %sDim10%');\r\n ItemReject( sErr );\r\n EndIf;\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 11 );\r\n If( CellIsUpdateable( pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12 ) = 1 );\r\n sElType = DType( sDim11, v12 );\r\n If( sElType @= 'N' );\r\n If(pCumulate = 1);\r\n nObal = CellGetN( pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12 );\r\n nCbal = nObal + StringToNumberEx(v13, sDecimalSeparator, sThousandSeparator);\r\n ELSE;\r\n nCbal = StringToNumberEx(v13, sDecimalSeparator, sThousandSeparator);\r\n Endif;\r\n CellPutN( nCbal, pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12 );\r\n ElseIf( sElType @= 'S' );\r\n CellPutS( v13, pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12 );\r\n Else;\r\n If( pStrictErrorHandling = 1 );\r\n sErr = Expand('Unhandled element type %sElType% of element %v12% in dimension %sDim11%');\r\n ItemReject( sErr );\r\n EndIf;\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 12 );\r\n If( CellIsUpdateable( pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13 ) = 1 );\r\n sElType = DType( sDim12, v13 );\r\n If( sElType @= 'N' );\r\n If( pCumulate = 1);\r\n nObal = CellGetN( pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13 );\r\n nCbal = nObal + StringToNumberEx(v14, sDecimalSeparator, sThousandSeparator);\r\n ELSE;\r\n nCbal = StringToNumberEx(v14, sDecimalSeparator, sThousandSeparator);\r\n Endif;\r\n CellPutN( nCbal, pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13 );\r\n ElseIf( sElType @= 'S' );\r\n CellPutS( v14, pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13 );\r\n Else;\r\n If( pStrictErrorHandling = 1 );\r\n sErr = Expand('Unhandled element type %sElType% of element %v13% in dimension %sDim12%');\r\n ItemReject( sErr );\r\n EndIf;\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 13 );\r\n If( CellIsUpdateable( pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14 ) = 1 );\r\n sElType = DType( sDim13, v14 );\r\n If( sElType @= 'N' );\r\n If(pCumulate = 1);\r\n nObal = CellGetN( pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14 );\r\n nCbal = nObal + StringToNumberEx(v15, sDecimalSeparator, sThousandSeparator);\r\n ELSE;\r\n nCbal = StringToNumberEx(v15, sDecimalSeparator, sThousandSeparator);\r\n Endif;\r\n CellPutN( nCbal, pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14 );\r\n ElseIf( sElType @= 'S' );\r\n CellPutS( v15, pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14 );\r\n Else;\r\n If( pStrictErrorHandling = 1 );\r\n sErr = Expand('Unhandled element type %sElType% of element %v14% in dimension %sDim13%');\r\n ItemReject( sErr );\r\n EndIf;\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 14 );\r\n If( CellIsUpdateable( pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15 ) = 1 );\r\n sElType = DType( sDim14, v15 );\r\n If( sElType @= 'N' );\r\n If(pCumulate = 1);\r\n nObal = CellGetN( pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15 );\r\n nCbal = nObal + StringToNumberEx(v16, sDecimalSeparator, sThousandSeparator);\r\n ELSE;\r\n nCbal = StringToNumberEx(v16, sDecimalSeparator, sThousandSeparator);\r\n Endif;\r\n CellPutN( nCbal, pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15 );\r\n ElseIf( sElType @= 'S' );\r\n CellPutS( v16, pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15 );\r\n Else;\r\n If( pStrictErrorHandling = 1 );\r\n sErr = Expand('Unhandled element type %sElType% of element %v15% in dimension %sDim14%');\r\n ItemReject( sErr );\r\n EndIf;\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 15 );\r\n If( CellIsUpdateable( pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16 ) = 1 );\r\n sElType = DType( sDim15, v16 );\r\n If( sElType @= 'N' );\r\n If(pCumulate = 1);\r\n nObal = CellGetN( pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16 );\r\n nCbal = nObal + StringToNumberEx(v17, sDecimalSeparator, sThousandSeparator);\r\n ELSE;\r\n nCbal = StringToNumberEx(v17, sDecimalSeparator, sThousandSeparator);\r\n Endif;\r\n CellPutN( nCbal, pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16 );\r\n ElseIf( sElType @= 'S' );\r\n CellPutS( v17, pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16 );\r\n Else;\r\n If( pStrictErrorHandling = 1 );\r\n sErr = Expand('Unhandled element type %sElType% of element %v16% in dimension %sDim15%');\r\n ItemReject( sErr );\r\n EndIf;\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 16 );\r\n If( CellIsUpdateable( pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17 ) = 1 );\r\n sElType = DType( sDim16, v17 );\r\n If(pCumulate = 1);\r\n nObal = CellGetN( pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17 );\r\n nCbal = nObal + StringToNumberEx(v18, sDecimalSeparator, sThousandSeparator);\r\n ELSE;\r\n nCbal = StringToNumberEx(v18, sDecimalSeparator, sThousandSeparator);\r\n Endif;\r\n If( sElType @= 'N' );\r\n CellPutN( nCbal, pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17 );\r\n ElseIf( sElType @= 'S' );\r\n CellPutS( v18, pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17 );\r\n Else;\r\n If( pStrictErrorHandling = 1 );\r\n sErr = Expand('Unhandled element type %sElType% of element %v17% in dimension %sDim16%');\r\n ItemReject( sErr );\r\n EndIf;\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 17 );\r\n If( CellIsUpdateable( pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18 ) = 1 );\r\n sElType = DType( sDim17, v18 );\r\n If( sElType @= 'N' );\r\n If(pCumulate = 1);\r\n nObal = CellGetN( pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18 );\r\n nCbal = nObal + StringToNumberEx(v19, sDecimalSeparator, sThousandSeparator);\r\n ELSE;\r\n nCbal = StringToNumberEx(v19, sDecimalSeparator, sThousandSeparator);\r\n Endif;\r\n CellPutN( nCbal, pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18 );\r\n ElseIf( sElType @= 'S' );\r\n CellPutS( v19, pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18 );\r\n Else;\r\n If( pStrictErrorHandling = 1 );\r\n sErr = Expand('Unhandled element type %sElType% of element %v18% in dimension %sDim17%');\r\n ItemReject( sErr );\r\n EndIf;\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 18 );\r\n If( CellIsUpdateable( pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19 ) = 1 );\r\n sElType = DType( sDim18, v19 );\r\n If( sElType @= 'N' );\r\n If(pCumulate = 1);\r\n nObal = CellGetN( pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19 );\r\n nCbal = nObal + StringToNumberEx(v20, sDecimalSeparator, sThousandSeparator);\r\n ELSE;\r\n nCbal = StringToNumberEx(v20, sDecimalSeparator, sThousandSeparator);\r\n Endif;\r\n CellPutN( nCbal, pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19 );\r\n ElseIf( sElType @= 'S' );\r\n CellPutS( v20, pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19 );\r\n Else;\r\n If( pStrictErrorHandling = 1 );\r\n sErr = Expand('Unhandled element type %sElType% of element %v19% in dimension %sDim18%');\r\n ItemReject( sErr );\r\n EndIf;\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 19 );\r\n If( CellIsUpdateable( pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20 ) = 1 );\r\n sElType = DType( sDim19, v20 );\r\n If( sElType @= 'N' );\r\n If(pCumulate = 1);\r\n nObal = CellGetN( pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20 );\r\n nCbal = nObal + StringToNumberEx(v21, sDecimalSeparator, sThousandSeparator);\r\n ELSE;\r\n nCbal = StringToNumberEx(v21, sDecimalSeparator, sThousandSeparator);\r\n Endif;\r\n CellPutN( nCbal, pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20 );\r\n ElseIf( sElType @= 'S' );\r\n CellPutS( v21, pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20 );\r\n Else;\r\n If( pStrictErrorHandling = 1 );\r\n sErr = Expand('Unhandled element type %sElType% of element %v20% in dimension %sDim19%');\r\n ItemReject( sErr );\r\n EndIf;\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 20 );\r\n If( CellIsUpdateable( pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21 ) = 1 );\r\n sElType = DType( sDim20, v21 );\r\n If( sElType @= 'N' );\r\n If(pCumulate = 1);\r\n nObal = CellGetN( pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21 );\r\n nCbal = nObal + StringToNumberEx(v22, sDecimalSeparator, sThousandSeparator);\r\n ELSE;\r\n nCbal = StringToNumberEx(v22, sDecimalSeparator, sThousandSeparator);\r\n Endif;\r\n CellPutN( nCbal, pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21 );\r\n ElseIf( sElType @= 'S' );\r\n CellPutS( v22, pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21 );\r\n Else;\r\n If( pStrictErrorHandling = 1 );\r\n sErr = Expand('Unhandled element type %sElType% of element %v21% in dimension %sDim20%');\r\n ItemReject( sErr );\r\n EndIf;\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 21 );\r\n If( CellIsUpdateable( pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22 ) = 1 );\r\n sElType = DType( sDim21, v22 );\r\n If( sElType @= 'N' );\r\n If(pCumulate = 1);\r\n nObal = CellGetN( pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22 );\r\n nCbal = nObal + StringToNumberEx(v23, sDecimalSeparator, sThousandSeparator);\r\n ELSE;\r\n nCbal = StringToNumberEx(v23, sDecimalSeparator, sThousandSeparator);\r\n Endif;\r\n CellPutN( nCbal, pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22 );\r\n ElseIf( sElType @= 'S' );\r\n CellPutS( v23, pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22 );\r\n Else;\r\n If( pStrictErrorHandling = 1 );\r\n sErr = Expand('Unhandled element type %sElType% of element %v22% in dimension %sDim21%');\r\n ItemReject( sErr );\r\n EndIf;\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 22 );\r\n If( CellIsUpdateable( pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23 ) = 1 );\r\n sElType = DType( sDim22, v23 );\r\n If( sElType @= 'N' );\r\n If(pCumulate = 1);\r\n nObal = CellGetN( pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23 );\r\n nCbal = nObal + StringToNumberEx(v24, sDecimalSeparator, sThousandSeparator);\r\n ELSE;\r\n nCbal = StringToNumberEx(v24, sDecimalSeparator, sThousandSeparator);\r\n Endif;\r\n CellPutN( nCbal, pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23 );\r\n ElseIf( sElType @= 'S' );\r\n CellPutS( v24, pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23 );\r\n Else;\r\n If( pStrictErrorHandling = 1 );\r\n sErr = Expand('Unhandled element type %sElType% of element %v23% in dimension %sDim22%');\r\n ItemReject( sErr );\r\n EndIf;\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 23 );\r\n If( CellIsUpdateable( pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22,\r\n v23, v24 ) = 1 );\r\n sElType = DType( sDim23, v24 );\r\n If( sElType @= 'N' );\r\n If(pCumulate = 1);\r\n nObal = CellGetN( pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22,\r\n v23, v24 );\r\n nCbal = nObal + StringToNumberEx(v25, sDecimalSeparator, sThousandSeparator);\r\n ELSE;\r\n nCbal = StringToNumberEx(v25, sDecimalSeparator, sThousandSeparator);\r\n Endif;\r\n CellPutN( nCbal, pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24 );\r\n ElseIf( sElType @= 'S' );\r\n CellPutS( v25, pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24 );\r\n Else;\r\n If( pStrictErrorHandling = 1 );\r\n sErr = Expand('Unhandled element type %sElType% of element %v24% in dimension %sDim23%');\r\n ItemReject( sErr );\r\n EndIf;\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 24 );\r\n If( CellIsUpdateable( pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22,\r\n v23, v24, v25 ) = 1 );\r\n sElType = DType( sDim24, v25 );\r\n If( sElType @= 'N' );\r\n If(pCumulate = 1);\r\n nObal = CellGetN( pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22,\r\n v23, v24, v25 );\r\n nCbal = nObal + StringToNumberEx(v26, sDecimalSeparator, sThousandSeparator);\r\n ELSE;\r\n nCbal = StringToNumberEx(v26, sDecimalSeparator, sThousandSeparator);\r\n Endif;\r\n CellPutN( nCbal, pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25 );\r\n ElseIf( sElType @= 'S' );\r\n CellPutS( v26, pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25 );\r\n Else;\r\n If( pStrictErrorHandling = 1 );\r\n sErr = Expand('Unhandled element type %sElType% of element %v25% in dimension %sDim24%');\r\n ItemReject( sErr );\r\n EndIf;\r\n EndIf;\r\n EndIf;\r\n ElseIf( nDimensionCount = 25 );\r\n If( CellIsUpdateable( pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26 ) = 1 );\r\n sElType = DType( sDim25, v26 );\r\n If( sElType @= 'N' );\r\n If(pCumulate = 1);\r\n nObal = CellGetN( pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26 );\r\n nCbal = nObal + StringToNumberEx(v27, sDecimalSeparator, sThousandSeparator);\r\n ELSE;\r\n nCbal = StringToNumberEx(v27, sDecimalSeparator, sThousandSeparator);\r\n Endif;\r\n CellPutN( nCbal, pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26 );\r\n ElseIf( sElType @= 'S' );\r\n CellPutS( v27, pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26 );\r\n Else;\r\n If( pStrictErrorHandling = 1 );\r\n sErr = Expand('Unhandled element type %sElType% of element %v26% in dimension %sDim25%');\r\n ItemReject( sErr );\r\n EndIf;\r\n EndIf;\r\n EndIf;\r\nElseIf( nDimensionCount = 26 );\r\n If( CellIsUpdateable( pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27 ) = 1 );\r\n sElType = DType( sDim26, v27 );\r\n If( sElType @= 'N' );\r\n If( pCumulate = 1);\r\n nObal = CellGetN( pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27 );\r\n nCbal = nObal + StringToNumberEx(v28, sDecimalSeparator, sThousandSeparator);\r\n ELSE;\r\n nCbal = StringToNumberEx(v28, sDecimalSeparator, sThousandSeparator);\r\n Endif;\r\n CellPutN( nCbal, pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27 );\r\n ElseIf( sElType @= 'S' );\r\n CellPutS( v28, pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27 );\r\n Else;\r\n If( pStrictErrorHandling = 1 );\r\n sErr = Expand('Unhandled element type %sElType% of element %v27% in dimension %sDim26%');\r\n ItemReject( sErr );\r\n EndIf;\r\n EndIf;\r\n EndIf;\r\nElseIf( nDimensionCount = 27 );\r\n If( CellIsUpdateable( pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28 ) = 1 );\r\n sElType = DType( sDim27, v28 );\r\n If( sElType @= 'N' );\r\n If(pCumulate = 1);\r\n nObal = CellGetN( pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28 );\r\n nCbal = nObal + StringToNumberEx(v29, sDecimalSeparator, sThousandSeparator);\r\n ELSE;\r\n nCbal = StringToNumberEx(v29, sDecimalSeparator, sThousandSeparator);\r\n Endif;\r\n CellPutN( nCbal, pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28 );\r\n ElseIf( sElType @= 'S' );\r\n CellPutS( v29, pCube, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28 );\r\n Else;\r\n If( pStrictErrorHandling = 1 );\r\n sErr = Expand('Unhandled element type %sElType% of element %v28% in dimension %sDim27%');\r\n ItemReject( sErr );\r\n EndIf;\r\n EndIf;\r\n EndIf;\r\n\r\n\r\n EndIf;\r\n \r\n## Increase Record count\r\nnRecordPostedCount = nRecordPostedCount + 1;\r\n### End Data ###", "EpilogProcedure": "#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n### Delete source file (only if no errors) ###\r\nIf( nErrors = 0 & pFileDelete = 1 );\r\n ASCIIDelete(sFile);\r\nEndIf;\r\n \r\n### If errors occurred terminate process with a major error status ###\r\nIf( nErrors > 0 );\r\n sMessage = 'the process incurred at least 1 major error and consequently aborted. Please see above lines in this file for more details.';\r\n nProcessReturnCode = 0;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% Process:%cThisProcName% aborted. Check tm1server.log for details.' );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n EndIf;\r\nEndIf;\r\n\r\n### Return code & final error message handling\r\nIf( nErrors > 0 );\r\n sMessage = 'the process incurred at least 1 error. Please see above lines in this file for more details.';\r\n nProcessReturnCode = 0;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% Process:%cThisProcName% completed with errors. Check tm1server.log for details.' );\r\nElse;\r\n sProcessAction = Expand( 'Process:%cThisProcName% successfully imported data from file %sFile%.' );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% %sProcessAction%' );\r\n nProcessReturnCode = 1;\r\n If( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( sProcessAction ) ); \r\n EndIf;\r\nEndIf;\r\n\r\n### End Epilog ###", "HasSecurityAccess": true, - "UIData": "_ParameterConstraints=e30=\f", + "UIData": "", "DataSource": { "Type": "ASCII", "asciiDecimalSeparator": ".", @@ -18,93 +18,81 @@ "dataSourceNameForServer": "C:/TM1/Bedrock/Data/Bedrock.Z.Cube.Placeholder.csv" }, "Parameters": [ - { - "Name": "pLogOutput", - "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, - { - "Name": "pStrictErrorHandling", - "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, { "Name": "pCube", - "Prompt": "REQUIRED: Target Cube", + "Prompt": "REQUIRED: Cube name", "Value": "", "Type": "String" }, { "Name": "pSrcDir", - "Prompt": "OPTIONAL: Source Directory (will default to error log path)", + "Prompt": "OPTIONAL: File directory (Default = GetProcessErrorFileDirectory)", "Value": "", "Type": "String" }, { "Name": "pSrcFile", - "Prompt": "OPTIONAL: Source File (will default to pCube_Export.csv )", + "Prompt": "OPTIONAL: File name (Default = pCube | '_Export.csv')", "Value": "", "Type": "String" }, { "Name": "pDim", - "Prompt": "OPTIONAL: Dimension", + "Prompt": "OPTIONAL: Dimension name for element substitution", "Value": "", "Type": "String" }, { "Name": "pSrcEle", - "Prompt": "OPTIONAL: Source Element ( Only required if a Dimension is used.)", + "Prompt": "OPTIONAL: Source element for element substitution", "Value": "", "Type": "String" }, { "Name": "pTgtEle", - "Prompt": "OPTIONAL: Target Element (Only required if Dimension is used.)", + "Prompt": "OPTIONAL: Target element for element substitution", "Value": "", "Type": "String" }, { "Name": "pTitleRows", - "Prompt": "REQUIRED: Number of Title Rows to Skip", + "Prompt": "OPTIONAL: Number of title rows to skip (Default = 1)", "Value": 1, "Type": "Numeric" }, { "Name": "pDelim", - "Prompt": "REQUIRED: AsciiOutput delimiter character (Default=comma, 2 or 3 digits = ASCII code)", - "Value": ",", + "Prompt": "OPTIONAL: AsciiOutput delimiter character (2 or 3 digits = ASCII code. Default = ',')", + "Value": "", "Type": "String" }, { "Name": "pQuote", - "Prompt": "REQUIRED: Quote (Accepts empty quote, 2 or 3 digits = ASCII code)", + "Prompt": "OPTIONAL: Quote character (2 or 3 digits = ASCII code. Default = '\"')", "Value": "\"", "Type": "String" }, { "Name": "pDecimalSeparator", - "Prompt": "OPTIONAL: Decimal separator for conversion of number to string and string to number (default = '.' exactly 3 digits = ASCII code)", + "Prompt": "OPTIONAL: Decimal separator for string/number conversion (Exactly 3 digits = ASCII code. Default ='.')", "Value": ".", "Type": "String" }, { "Name": "pThousandSeparator", - "Prompt": "OPTIONAL: Thousand separator for conversion of number to string and string to number (default = ',' exactly 3 digits = ASCII code)", + "Prompt": "OPTIONAL: Thousand separator for string/number conversion (Exactly 3 digits = ASCII code. Default = ',')", "Value": ",", "Type": "String" }, { "Name": "pCumulate", - "Prompt": "REQUIRED: Accumulate Amounts (0 = Overwrite values, 1 = Accumulate values)", + "Prompt": "OPTIONAL: Accumulate amounts (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" }, { "Name": "pSandbox", - "Prompt": "OPTIONAL: To use sandbox not base data enter the sandbox name (invalid name will result in process error)", + "Prompt": "OPTIONAL: Use sandbox", "Value": "", "Type": "String" }, @@ -116,43 +104,55 @@ }, { "Name": "pMappingToNewDims", - "Prompt": "REQUIRED IF TARGET HAS DIMS NOT IN SOURCE: DimX\u00a6InputElementForDimX & DimY\u00a6InputElementForDimY (specify an N level element for each new dim)", + "Prompt": "OPTIONAL: Required if target has dims not in source. Format: 'dim_one\u00a6 el_one & dim_two\u00a6 el_two'", "Value": "", "Type": "String" }, { "Name": "pDimDelim", - "Prompt": "OPTIONAL. Delimiter for start of Dimension/Element set", + "Prompt": "OPTIONAL: Delimiter for start of dimension/element set in filter parameters (Default = '&')", "Value": "&", "Type": "String" }, { "Name": "pEleStartDelim", - "Prompt": "OPTIONAL: Delimiter for start of element list", + "Prompt": "OPTIONAL: Delimiter for start of element list in filter parameters (Default = '\u00a6')", "Value": "\u00a6", "Type": "String" }, { "Name": "pEleDelim", - "Prompt": "OPTIONAL: Delimiter between elements", + "Prompt": "OPTIONAL: Delimiter between elements in filter parameters (Default = '+')", "Value": "+", "Type": "String" }, { "Name": "pCharacterSet", - "Prompt": "OPTIONAL: The output character set (defaults to TM1CS_UTF8 if blank)", + "Prompt": "OPTIONAL: The output character set (Default = 'TM1CS_UTF8')", "Value": "TM1CS_UTF8", "Type": "String" }, { "Name": "pFileDelete", - "Prompt": "OPTIONAL: Delete the source file on conclusion of import (Boolean 1/0, default = 0)", + "Prompt": "OPTIONAL: Delete the file on conclusion of process (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" }, { "Name": "pSkipInvalidRecords", - "Prompt": "OPTIONAL: Skip records with invalid elements rather than creating error log", + "Prompt": "OPTIONAL: Skip records with invalid elements rather than creating error log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pLogOutput", + "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pStrictErrorHandling", + "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" }, @@ -161,6 +161,12 @@ "Prompt": "OBSOLETE: This parameter does nothing and is only included for backwards compatability", "Value": 0, "Type": "Numeric" + }, + { + "Name": "pJson", + "Prompt": "OPTIONAL: JSON Object with process parameter values. This will overwrite user passed parameters for all included parameters.", + "Value": "{}", + "Type": "String" } ], "Variables": [ @@ -375,36 +381,5 @@ "EndByte": 0 } ], - "VariablesUIData": [ - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f", - "VarType=32\fColType=827\f" - ] + "VariablesUIData": [] } \ No newline at end of file diff --git a/bedrock_processes_json/}bedrock.cube.data.save.json b/bedrock_processes_json/}bedrock.cube.data.save.json index b0a4c59..38714be 100644 --- a/bedrock_processes_json/}bedrock.cube.data.save.json +++ b/bedrock_processes_json/}bedrock.cube.data.save.json @@ -10,28 +10,34 @@ "Type": "None" }, "Parameters": [ + { + "Name": "pCube", + "Prompt": "REQUIRED: Cube name", + "Value": "", + "Type": "String" + }, + { + "Name": "pDelim", + "Prompt": "OPTIONAL: Delimiter for list parameters (Default = '&')", + "Value": "&", + "Type": "String" + }, { "Name": "pLogOutput", - "Prompt": "OPTIONAL: write parameters and action summary to server message log (Boolean True = 1)", + "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" }, { "Name": "pStrictErrorHandling", - "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean True = 1)", + "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" }, { - "Name": "pCube", - "Prompt": "REQUIRED: Save data for this cube (Separated by Delimiter, Accepts Wild card)", - "Value": "", - "Type": "String" - }, - { - "Name": "pDelim", - "Prompt": "OPTIONAL: Delimiter", - "Value": "&", + "Name": "pJson", + "Prompt": "OPTIONAL: JSON Object with process parameter values. This will overwrite user passed parameters.", + "Value": "{}", "Type": "String" } ], diff --git a/bedrock_processes_json/}bedrock.cube.delete.json b/bedrock_processes_json/}bedrock.cube.delete.json index 549d615..35418d3 100644 --- a/bedrock_processes_json/}bedrock.cube.delete.json +++ b/bedrock_processes_json/}bedrock.cube.delete.json @@ -1,6 +1,6 @@ { "Name": "}bedrock.cube.delete", - "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.delete', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pCube', '', 'pDelim', '&',\r\n \t'pCtrlObj', 0\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process deletes cube(s).\r\n\r\n# Use case: Intended for cleaning up after development/prototyping.\r\n# 1\\ Delete all cubes not needed after Go Live.\r\n\r\n# Note:\r\n# A list of cubes can be specified and/or wild cards can be used.\r\n# Naturally valid cube name(s) must be specified otherwise the process will abort.\r\n# By default (pCtrlObj) the process will not delete control cubes (i.e. attributes, security etc).\r\n#EndRegion @DOC\r\n\r\n##Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n### Constants ###\r\n\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSub = cThisProcName |'_'| cTimeStamp |'_'| cRandomInt;\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pCube:%pCube%, pDelim:%pDelim%, pCtrlObj:%pCtrlObj%.' ; \r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\n### Validate Parameters ###\r\n\r\nnErrors = 0;\r\n\r\n# If blank delimiter specified then convert to default\r\nIf( pDelim @= '' );\r\n pDelim = '&';\r\nEndIf;\r\n\r\n# If no cubes have been specified, then log error message\r\nIf( Trim( pCube ) @= '' );\r\n nErrors = 1;\r\n sMessage = 'No cubes specified';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n# If no wildcard and no delimiter, log error message if cubename is invalid \r\nIf( Scan( pDelim, pCube ) = 0 & Scan( '*', pCube ) = 0 & Trim( pCube ) @<> '' & CubeExists( pCube ) = 0 ); \r\n nErrors = 1;\r\n sMessage = 'Cubename ' | pCube | ' is invalid';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n### Split parameter into individual cubes and delete ###\r\nsCubes = pCube;\r\nnDelimiterIndex = 1;\r\nsMdx = '';\r\n\r\nWhile( nDelimiterIndex <> 0 );\r\n nDelimiterIndex = Scan( pDelim, sCubes );\r\n If( nDelimiterIndex = 0 );\r\n sCube = sCubes;\r\n Else;\r\n sCube = Trim( SubSt( sCubes, 1, nDelimiterIndex - 1 ) );\r\n sCubes = Trim( Subst( sCubes, nDelimiterIndex + Long(pDelim), Long( sCubes ) ) );\r\n EndIf;\r\n \r\n # Check if a wildcard has been used to specify the Cube name.\r\n # If it hasn't then just delete the Cube if it exists\r\n # If it has then create cubes subset using Wildcard expression in Mdx\r\n If( Scan( '*', sCube ) = 0 );\r\n If( CubeExists( sCube ) = 1 ); \r\n If(Subst(sCube,1,1) @= '}');\r\n If(pCtrlObj = 1);\r\n CubeDestroy( sCube );\r\n Endif;\r\n Else;\r\n CubeDestroy( sCube );\r\n Endif;\r\n Endif;\r\n Else;\r\n # Create subset of cubes using Wildcard\r\n sCubeExp = '\"'|sCube|'\"';\r\n IF( pCtrlObj = 1 );\r\n sMdxPart = '{TM1FILTERBYPATTERN( TM1SUBSETALL( [}Cubes] ) ,'| sCubeExp | ')}';\r\n ELSE;\r\n sMdxPart = '{TM1FILTERBYPATTERN( EXCEPT( TM1SUBSETALL( [}Cubes] ) , TM1FILTERBYPATTERN( TM1SUBSETALL( [}Cubes] ) , \"}*\" ) ) ,'| sCubeExp | ')}'; \r\n ENDIF;\r\n IF( sMdx @= ''); \r\n sMdx = sMdxPart; \r\n ELSE;\r\n sMdx = sMdx | ' + ' | sMdxPart;\r\n ENDIF;\r\n \r\n If( SubsetExists( '}Cubes' , cTempSub ) = 1 );\r\n # If a delimited list of cube names includes wildcards then we may have to re-use the subset multiple times\r\n SubsetMDXSet( '}Cubes' , cTempSub, sMDX );\r\n Else;\r\n # temp subset, therefore no need to destroy in epilog\r\n SubsetCreatebyMDX( cTempSub, sMDX, '}Cubes' , 1 );\r\n EndIf;\r\n \r\n # Loop through cubes in subset created based on wildcard\r\n nCountCubes = SubsetGetSize( '}Cubes' , cTempSub );\r\n While( nCountCubes >= 1 );\r\n sCurrCube = SubsetGetElementName( '}Cubes' , cTempSub, nCountCubes );\r\n # Validate cube name\r\n If( CubeExists( sCurrCube ) = 1 ); \r\n # Destroy Cube\r\n If(Subst(sCube,1,1) @= '}');\r\n If(pCtrlObj = 1);\r\n CubeDestroy( sCurrCube );\r\n Endif;\r\n Else;\r\n CubeDestroy( sCurrCube );\r\n Endif;\r\n Endif;\r\n nCountCubes = nCountCubes - 1;\r\n End;\r\n EndIf;\r\n\r\nEnd;\r\n\r\n\r\n### End Prolog ###", + "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.delete', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pCube', '', 'pDelim', '&',\r\n \t'pCtrlObj', 0\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process deletes cube(s).\r\n\r\n# Use case: Intended for cleaning up after development/prototyping.\r\n# 1\\ Delete all cubes not needed after Go Live.\r\n\r\n# Note:\r\n# A list of cubes can be specified and/or wild cards can be used.\r\n# Naturally valid cube name(s) must be specified otherwise the process will abort.\r\n# By default (pCtrlObj) the process will not delete control cubes (i.e. attributes, security etc).\r\n#EndRegion @DOC\r\n\r\n##Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n### Constants ###\r\n\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSub = cThisProcName |'_'| cTimeStamp |'_'| cRandomInt;\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pCube:%pCube%, pDelim:%pDelim%, pCtrlObj:%pCtrlObj%.' ; \r\n\r\n#################################################################################################\r\n#Region - Process Parameters\r\n\r\npJson = IF( JsonType( pJson ) @<> 'object', '{}', pJson );\r\nsMessages = '{\"Process\": \"'|GetProcessName()|'\", \"User\": \"'|TM1User()|'\", \"Info\": [\"Process: '''|GetProcessName()|''' run by User: '''|TM1User()|'''.\"], \"Error\": []}';\r\npDefaultParameters = '{\r\n \"pCube\": null,\r\n \"pDelim\": \"&\",\r\n \"pCtrlObj\": 0,\r\n \"pLogOutput\": 0,\r\n \"pStrictErrorHandling\": 0\r\n}';\r\n\r\npPassedParameters = '{\r\n \"pCube\": '|StringToJson ( pCube )|',\r\n \"pDelim\": '|StringToJson ( pDelim )|',\r\n \"pCtrlObj\": '|NumberToString( pCtrlObj )|',\r\n \"pLogOutput\": '|NumberToString( pLogOutput )|',\r\n \"pStrictErrorHandling\": '|NumberToString( pStrictErrorHandling )|'\r\n}';\r\n\r\npJson = JsonMergePatch( pPassedParameters, pJson );\r\n# String Parameters\r\npCube = JsonToString( JsonGet( pJson, 'pCube' ) );\r\npDelim = JsonToString( JsonGet( pJson, 'pDelim' ) );\r\n# Numeric Parameters\r\npCtrlObj = StringToNumber( JsonToString( JsonGet( pJson, 'pCtrlObj' ) ) );\r\npLogOutput = StringToNumber( JsonToString( JsonGet( pJson, 'pLogOutput' ) ) );\r\npStrictErrorHandling = StringToNumber( JsonToString( JsonGet( pJson, 'pStrictErrorHandling' ) ) );\r\n\r\n### Get the parameters that differ from the default\r\npDiffer = JsonDiff( pDefaultParameters, pJson );\r\nnSize = JsonSize( pDiffer );\r\nWHILE( nSize > 0 );\r\n nSize = nSize - 1;\r\n pDiffer = JsonReplace( pDiffer, '/'|NumberToString( nSize )|'/op', '\"add\"' );\r\nEND;\r\npJson = JsonPatch( '{}', pDiffer );\r\n\r\n### LogOutput parameters\r\nsMessages = JsonAdd( sMessages, '/Info/-', pJson );\r\nIF( pLogOutput = 1 );\r\n LogOutput('INFO', JsonToString( sMessages, '/Info/0', 0, ' ' ) );\r\nENDIF;\r\n\r\n#EndRegion - Process Parameters\r\n#################################################################################################\r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\n### Validate Parameters ###\r\n\r\nnErrors = 0;\r\n\r\n# If blank delimiter specified then convert to default\r\nIf( pDelim @= '' );\r\n pDelim = '&';\r\nEndIf;\r\n\r\n# If no cubes have been specified, then log error message\r\nIf( Trim( pCube ) @= '' );\r\n nErrors = 1;\r\n sMessage = 'No cubes specified';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n# If no wildcard and no delimiter, log error message if cubename is invalid \r\nIf( Scan( pDelim, pCube ) = 0 & Scan( '*', pCube ) = 0 & Trim( pCube ) @<> '' & CubeExists( pCube ) = 0 ); \r\n nErrors = 1;\r\n sMessage = 'Cubename ' | pCube | ' is invalid';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n### Split parameter into individual cubes and delete ###\r\nsCubes = pCube;\r\nnDelimiterIndex = 1;\r\nsMdx = '';\r\n\r\nWhile( nDelimiterIndex <> 0 );\r\n nDelimiterIndex = Scan( pDelim, sCubes );\r\n If( nDelimiterIndex = 0 );\r\n sCube = sCubes;\r\n Else;\r\n sCube = Trim( SubSt( sCubes, 1, nDelimiterIndex - 1 ) );\r\n sCubes = Trim( Subst( sCubes, nDelimiterIndex + Long(pDelim), Long( sCubes ) ) );\r\n EndIf;\r\n \r\n # Check if a wildcard has been used to specify the Cube name.\r\n # If it hasn't then just delete the Cube if it exists\r\n # If it has then create cubes subset using Wildcard expression in Mdx\r\n If( Scan( '*', sCube ) = 0 );\r\n If( CubeExists( sCube ) = 1 ); \r\n If(Subst(sCube,1,1) @= '}');\r\n If(pCtrlObj = 1);\r\n CubeDestroy( sCube );\r\n Endif;\r\n Else;\r\n CubeDestroy( sCube );\r\n Endif;\r\n Endif;\r\n Else;\r\n # Create subset of cubes using Wildcard\r\n sCubeExp = '\"'|sCube|'\"';\r\n IF( pCtrlObj = 1 );\r\n sMdxPart = '{TM1FILTERBYPATTERN( TM1SUBSETALL( [}Cubes] ) ,'| sCubeExp | ')}';\r\n ELSE;\r\n sMdxPart = '{TM1FILTERBYPATTERN( EXCEPT( TM1SUBSETALL( [}Cubes] ) , TM1FILTERBYPATTERN( TM1SUBSETALL( [}Cubes] ) , \"}*\" ) ) ,'| sCubeExp | ')}'; \r\n ENDIF;\r\n IF( sMdx @= ''); \r\n sMdx = sMdxPart; \r\n ELSE;\r\n sMdx = sMdx | ' + ' | sMdxPart;\r\n ENDIF;\r\n \r\n If( SubsetExists( '}Cubes' , cTempSub ) = 1 );\r\n # If a delimited list of cube names includes wildcards then we may have to re-use the subset multiple times\r\n SubsetMDXSet( '}Cubes' , cTempSub, sMDX );\r\n Else;\r\n # temp subset, therefore no need to destroy in epilog\r\n SubsetCreatebyMDX( cTempSub, sMDX, '}Cubes' , 1 );\r\n EndIf;\r\n \r\n # Loop through cubes in subset created based on wildcard\r\n nCountCubes = SubsetGetSize( '}Cubes' , cTempSub );\r\n While( nCountCubes >= 1 );\r\n sCurrCube = SubsetGetElementName( '}Cubes' , cTempSub, nCountCubes );\r\n # Validate cube name\r\n If( CubeExists( sCurrCube ) = 1 ); \r\n # Destroy Cube\r\n If(Subst(sCube,1,1) @= '}');\r\n If(pCtrlObj = 1);\r\n CubeDestroy( sCurrCube );\r\n Endif;\r\n Else;\r\n CubeDestroy( sCurrCube );\r\n Endif;\r\n Endif;\r\n nCountCubes = nCountCubes - 1;\r\n End;\r\n EndIf;\r\n\r\nEnd;\r\n\r\n\r\n### End Prolog ###", "MetadataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "DataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "EpilogProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n### Return code & final error message handling\r\nIf( nErrors > 0 );\r\n sMessage = 'the process incurred at least 1 error. Please see above lines in this file for more details.';\r\n nProcessReturnCode = 0;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% Process:%cThisProcName% completed with errors. Check tm1server.log for details.' );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n EndIf;\r\nElse;\r\n sProcessAction = Expand( 'Process:%cThisProcName% successfully deleted cube %pCube%.' );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% %sProcessAction%' );\r\n nProcessReturnCode = 1;\r\n If( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( sProcessAction ) ); \r\n EndIf;\r\nEndIf;\r\n\r\n### End Epilog ###\r\n", @@ -10,35 +10,41 @@ "Type": "None" }, "Parameters": [ - { - "Name": "pLogOutput", - "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, - { - "Name": "pStrictErrorHandling", - "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, { "Name": "pCube", - "Prompt": "REQUIRED: List of Cubes to Delete (Separated by Delimiter, Accepts wildcard)", + "Prompt": "REQUIRED: Cube name", "Value": "", "Type": "String" }, { "Name": "pDelim", - "Prompt": "OPTIONAL: Delimiter", + "Prompt": "OPTIONAL: Delimiter for list parameters (Default = '&')", "Value": "&", "Type": "String" }, { "Name": "pCtrlObj", - "Prompt": "OPTIONAL: To Delete control cube 1=Delete control objects, 0=Do not delete control objects, Default value 0", + "Prompt": "OPTIONAL: OPTIONAL: Allow modification of control objects (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" + }, + { + "Name": "pLogOutput", + "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pStrictErrorHandling", + "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pJson", + "Prompt": "OPTIONAL: JSON Object with process parameter values. This will overwrite user passed parameters for all included parameters.", + "Value": "{}", + "Type": "String" } ], "Variables": [], diff --git a/bedrock_processes_json/}bedrock.cube.dimension.add.json b/bedrock_processes_json/}bedrock.cube.dimension.add.json index bb884d7..14cd811 100644 --- a/bedrock_processes_json/}bedrock.cube.dimension.add.json +++ b/bedrock_processes_json/}bedrock.cube.dimension.add.json @@ -1,6 +1,6 @@ { "Name": "}bedrock.cube.dimension.add", - "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.dimension.add', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pCube', '', 'pDim', '', 'pDimIndex', 1,\r\n \t'pIncludeData', 0, 'pEle', '', 'pIncludeRules', 2,\r\n \t'pCtrlObj', 0, 'pTemp', 1\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This TI adds a dimension to a cube that has already been built with the ability to preserve data.\r\n\r\n# Use case: Intended for development/prototyping.\r\n# 1/ Rebuild existing cube with extra dimension without losing data.\r\n\r\n# Note:\r\n# Naturally, a valid target cube name (pCube) is mandatory otherwise the process will abort.\r\n# Also, a valid new dimension name (pDim) is mandatory otherwise the process will abort.\r\n# When data needs to be kept (using pIncludeData) a valid element (pEle) must be specified where to store the data in new dimension.\r\n# Rule can be kept as backup file only or reloaded back.\r\n#EndRegion @DOC\r\n\r\n### Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSub = cThisProcName |'_'| cTimeStamp |'_'| cRandomInt;\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent= 'Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pCube:%pCube%, pDim:%pDim%, pDimIndex:%pDimIndex%, pIncludeData:%pIncludeData%, pEle:%pEle%, pIncludeRules:%pIncludeRules%, pCtrlObj:%pCtrlObj%, pTemp:%pTemp%.';\r\n\r\n## check operating system\r\nIf( SubSt( GetProcessErrorFileDirectory, 2, 1 ) @= ':' );\r\n sOS = 'Windows';\r\n sOSDelim = '\\';\r\nElseIf( Scan( '/', GetProcessErrorFileDirectory ) > 0 );\r\n sOS = 'Linux';\r\n sOSDelim = '/';\r\nElse;\r\n sOS = 'Windows';\r\n sOSDelim = '\\';\r\nEndIf;\r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\n### Validate Parameters ###\r\nnErrors = 0;\r\n# Validate cube\r\ncDimCount = 0;\r\nIf( Trim( pCube ) @= '' );\r\n nErrors = nErrors + 1;\r\n sMessage = 'No cube specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( CubeExists( pCube ) = 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'Invalid cube specified: %pCube%.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElse;\r\n cDimCount = CubeDimensionCountGet(pCube);\r\nEndIf;\r\n\r\n# Don't allow system cubes to be modified\r\nIf( SubSt( pCube, 1, 1 ) @= '}' & pCtrlObj <= 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'Do not modify system cubes: %pCube%.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate index\r\nIf( pDimIndex = 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'Index for new dimension is a REQUIRED parameter!');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( pDimIndex > cDimCount + 1 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'Cube %pCube% has %cDimCount% dimensions. %pDimIndex% is not valid for the new dimension index!');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate dimension\r\nIf( Trim( pDim ) @= '' );\r\n nErrors = nErrors + 1;\r\n sMessage = 'No dimension specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( DimensionExists( pDim ) = 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'New dimension: %pDim% does not exist');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# check element chosen in new dimension\r\nIf( pIncludeData = 1 & Trim(pEle)@='' );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'No element specified in new dimension %pDim% to store cube data.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\nIf( pIncludeData = 1 & DIMIX(pDim, pEle)=0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'Invalid element %pEle% specified for the new dimension %pDim% to store cube data.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\nIF(pIncludeRules = 1 % pIncludeRules = 2);\r\n sRule=CubeRuleGet( pCube );\r\n If( sRule@= '' );\r\n pIncludeRules = 0;\r\n LogOutput( 'INFO', Expand( 'No rule found for %pCube%.' ) );\r\n Endif;\r\nEndif; \r\n\r\n### Determine number of dims in source cube & create strings to check and recreate ###\r\nnCount = 1;\r\nsDimString = '';\r\nsDimCheck = '';\r\nsDelim = '+';\r\nnNewFound = 0;\r\nnIncrement = 1;\r\nWhile( TabDim( pCube, nCount ) @<> '' );\r\n sDim = TabDim( pCube, nCount );\r\n IF(nCount = pDimIndex & nNewFound = 0);\r\n sNewDim = pDim;\r\n nNewFound = 1;\r\n nIncrement = 0;\r\n else;\r\n sNewDim = sDim;\r\n nIncrement = 1;\r\n Endif; \r\n sDimCheck = sDimCheck|'+'|sDim|'+';\r\n sDimString = sDimString|'+'|sNewDim;\r\n nCount = nCount + nIncrement;\r\nEnd;\r\nnDimensionCount = nCount;\r\n\r\n# Cover case of new dimension in last position (pDimIndex = cDimCount+1)\r\nIf( nDimensionCount = pDimIndex & nNewFound = 0 );\r\n nNewFound = 1;\r\n sNewDim=pDim;\r\n sDimString = sDimString|'+'|sNewDim;\r\nEndIf;\r\n\r\n# Remove any leading +\r\nIF( Subst( sDimString , 1 , 1 ) @= '+' );\r\n sDimString = Subst ( sDimString , 2, Long(sDimString)-1 );\r\nEndIf;\r\n\r\nIF( Scan('+'|Lower(pDim)|'+', Lower(sDimCheck)) > 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'The chosen new dimension %pDim% already exists in cube %pCube%.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndif;\r\n\r\n# Check if cube exceeds current max dimenions\r\nIf( nDimensionCount > 27 );\r\n sMessage = 'Process needs to be modified to handle cubes with more than 27 dimensions';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n###### CALLING THE STEP PROCESSES #####\r\n\r\n# Keep the rule\r\nIF(pIncludeRules = 1 % pIncludeRules = 2);\r\n \r\n sProc = '}bedrock.cube.rule.manage';\r\n nRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCube,\r\n 'pMode', 'UNLOAD'\r\n );\r\n \r\n IF(nRet <> 0);\r\n sMessage = 'Error unloading the rule for %pCube%.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n \r\nEndif; \r\n\r\n# create clone cube with data\r\nIF(pIncludeData = 1);\r\n \r\n pCloneCube = pCube | '_Clone';\r\n nIncludeRules = IF(pIncludeRules = 1 % pIncludeRules = 2, 1, 0);\r\n nSuppressRules = IF(nIncludeRules = 1, 1, 0);\r\n \r\n sProc = '}bedrock.cube.clone';\r\n nRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pSrcCube', pCube,\r\n 'pTgtCube', pCloneCube,\r\n 'pIncludeRules', nIncludeRules,\r\n 'pIncludeData', pIncludeData,\r\n 'pSuppressRules', nSuppressRules,\r\n 'pTemp', pTemp,\r\n 'pCubeLogging', 0\r\n );\r\n\r\n IF(nRet <> 0);\r\n sMessage = 'Error creating cloned cube for keeping data.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\nEndif;\r\n\r\n# recreate the cube\r\nsProc = '}bedrock.cube.create';\r\nnRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCube,\r\n 'pDims', sDimString,\r\n 'pRecreate', 1,\r\n 'pDelim', sDelim\r\n );\r\n\r\nIF(nRet <> 0);\r\n sMessage = Expand('Error recreating the cube: %pCube%.');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nENDIF;\r\n\r\n# copy back the data\r\nIF(pIncludeData = 1);\r\n sEleStartDelim = '\u00a6';\r\n sMappingToNewDims = pDim|sEleStartDelim|pEle;\r\n \r\n nRet = ExecuteProcess('}bedrock.cube.data.copy.intercube',\r\n \t'pLogOutput',pLogOutput,\r\n \t'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pSrcCube',pCloneCube,\r\n \t'pFilter','',\r\n \t'pTgtCube',pCube,\r\n \t'pMappingToNewDims',sMappingToNewDims,\r\n 'pSuppressConsol', 1,\r\n 'pSuppressRules', nSuppressRules,\r\n \t'pZeroTarget',0,\r\n \t'pZeroSource',0,\r\n \t'pFactor',1,\r\n \t'pDimDelim','&',\r\n \t'pEleStartDelim',sEleStartDelim,\r\n \t'pEleDelim','+',\r\n \t'pTemp',pTemp,\r\n \t'pCubeLogging',0);\r\n \r\n IF(nRet <> 0);\r\n sMessage = Expand('Error copying back the data from clone cube: %pCloneCube%.');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n \r\n # destroy clone cube\r\n IF(pTemp=1);\r\n sProc = '}bedrock.cube.delete';\r\n nRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCloneCube,\r\n 'pCtrlObj', 0\r\n );\r\n\r\n IF(nRet <> 0);\r\n sMessage = Expand('Error deleting the clone cube: %pCloneCube%.');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n Endif;\r\n\r\nEndif; \r\n\r\n# reload the rule\r\nIF(pIncludeRules = 2);\r\n \r\n sProc = '}bedrock.cube.rule.manage';\r\n\r\n nRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCube,\r\n 'pMode', 'LOAD'\r\n );\r\n \r\n IF(nRet <> 0);\r\n sMessage = Expand('Error reloading the rule for %pCube%.');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n # Create error rule file \r\n cErrorRuleName = 'ErrorRuleFile.txt';\r\n \r\n IF(FileExists( Lower(cErrorRuleName) ) = 0 );\r\n sFile = '.' | sOSDelim | Lower(cErrorRuleName);\r\n LogOutput(cMsgErrorLevel, 'Rule could not be attached due to invalid !Dimension references. Please recover from the backup and fix manually.');\r\n ENDIF;\r\n \r\n ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCube,\r\n 'pFileName', Lower(cErrorRuleName),\r\n 'pMode', 'LOAD'\r\n );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n \r\nEndif; \r\n\r\n### End Prolog ###", + "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.dimension.add', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pCube', '', 'pDim', '', 'pDimIndex', 1,\r\n \t'pIncludeData', 0, 'pEle', '', 'pIncludeRules', 2,\r\n \t'pCtrlObj', 0, 'pTemp', 1\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This TI adds a dimension to a cube that has already been built with the ability to preserve data.\r\n\r\n# Use case: Intended for development/prototyping.\r\n# 1/ Rebuild existing cube with extra dimension without losing data.\r\n\r\n# Note:\r\n# Naturally, a valid target cube name (pCube) is mandatory otherwise the process will abort.\r\n# Also, a valid new dimension name (pDim) is mandatory otherwise the process will abort.\r\n# When data needs to be kept (using pIncludeData) a valid element (pEle) must be specified where to store the data in new dimension.\r\n# Rule can be kept as backup file only or reloaded back.\r\n#EndRegion @DOC\r\n\r\n### Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSub = cThisProcName |'_'| cTimeStamp |'_'| cRandomInt;\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent= 'Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pCube:%pCube%, pDim:%pDim%, pDimIndex:%pDimIndex%, pIncludeData:%pIncludeData%, pEle:%pEle%, pIncludeRules:%pIncludeRules%, pCtrlObj:%pCtrlObj%, pTemp:%pTemp%.';\r\n\r\n#################################################################################################\r\n#Region - Process Parameters\r\n\r\npJson = IF( JsonType( pJson ) @<> 'object', '{}', pJson );\r\nsMessages = '{\"Process\": \"'|GetProcessName()|'\", \"User\": \"'|TM1User()|'\", \"Info\": [\"Process: '''|GetProcessName()|''' run by User: '''|TM1User()|'''.\"], \"Error\": []}';\r\npDefaultParameters = '{\r\n \"pCube\": null,\r\n \"pDim\": null,\r\n \"pEle\": \"\",\r\n \"pCtrlObj\": 0,\r\n \"pDimIndex\": null,\r\n \"pIncludeData\": 0,\r\n \"pIncludeRules\": 1,\r\n \"pLogOutput\": 0,\r\n \"pStrictErrorHandling\": 0,\r\n \"pTemp\": 1\r\n}';\r\n\r\npPassedParameters = '{\r\n \"pCube\": '|StringToJson ( pCube )|',\r\n \"pDim\": '|StringToJson ( pDim )|',\r\n \"pEle\": '|StringToJson ( pEle )|',\r\n \"pCtrlObj\": '|NumberToString( pCtrlObj )|',\r\n \"pDimIndex\": '|NumberToString( pDimIndex )|',\r\n \"pIncludeData\": '|NumberToString( pIncludeData )|',\r\n \"pIncludeRules\": '|NumberToString( pIncludeRules )|',\r\n \"pLogOutput\": '|NumberToString( pLogOutput )|',\r\n \"pStrictErrorHandling\": '|NumberToString( pStrictErrorHandling )|',\r\n \"pTemp\": '|NumberToString( pTemp )|'\r\n}';\r\n\r\npJson = JsonMergePatch( pPassedParameters, pJson );\r\n# String Parameters\r\npCube = JsonToString( JsonGet( pJson, 'pCube' ) );\r\npDim = JsonToString( JsonGet( pJson, 'pDim' ) );\r\npEle = JsonToString( JsonGet( pJson, 'pEle' ) );\r\n# Numeric Parameters\r\npCtrlObj = StringToNumber( JsonToString( JsonGet( pJson, 'pCtrlObj' ) ) );\r\npDimIndex = StringToNumber( JsonToString( JsonGet( pJson, 'pDimIndex' ) ) );\r\npIncludeData = StringToNumber( JsonToString( JsonGet( pJson, 'pIncludeData' ) ) );\r\npIncludeRules = StringToNumber( JsonToString( JsonGet( pJson, 'pIncludeRules' ) ) );\r\npLogOutput = StringToNumber( JsonToString( JsonGet( pJson, 'pLogOutput' ) ) );\r\npStrictErrorHandling = StringToNumber( JsonToString( JsonGet( pJson, 'pStrictErrorHandling' ) ) );\r\npTemp = StringToNumber( JsonToString( JsonGet( pJson, 'pTemp' ) ) );\r\n\r\n### Get the parameters that differ from the default\r\npDiffer = JsonDiff( pDefaultParameters, pJson );\r\nnSize = JsonSize( pDiffer );\r\nWHILE( nSize > 0 );\r\n nSize = nSize - 1;\r\n pDiffer = JsonReplace( pDiffer, '/'|NumberToString( nSize )|'/op', '\"add\"' );\r\nEND;\r\npJson = JsonPatch( '{}', pDiffer );\r\n\r\n### LogOutput parameters\r\nsMessages = JsonAdd( sMessages, '/Info/-', pJson );\r\nIF( pLogOutput = 1 );\r\n LogOutput('INFO', JsonToString( sMessages, '/Info/0', 0, ' ' ) );\r\nENDIF;\r\n\r\n#EndRegion - Process Parameters\r\n#################################################################################################\r\n\r\n## check operating system\r\nIf( SubSt( GetProcessErrorFileDirectory, 2, 1 ) @= ':' );\r\n sOS = 'Windows';\r\n sOSDelim = '\\';\r\nElseIf( Scan( '/', GetProcessErrorFileDirectory ) > 0 );\r\n sOS = 'Linux';\r\n sOSDelim = '/';\r\nElse;\r\n sOS = 'Windows';\r\n sOSDelim = '\\';\r\nEndIf;\r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\n### Validate Parameters ###\r\nnErrors = 0;\r\n# Validate cube\r\ncDimCount = 0;\r\nIf( Trim( pCube ) @= '' );\r\n nErrors = nErrors + 1;\r\n sMessage = 'No cube specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( CubeExists( pCube ) = 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'Invalid cube specified: %pCube%.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElse;\r\n cDimCount = CubeDimensionCountGet(pCube);\r\nEndIf;\r\n\r\n# Don't allow system cubes to be modified\r\nIf( SubSt( pCube, 1, 1 ) @= '}' & pCtrlObj <= 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'Do not modify system cubes: %pCube%.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate index\r\nIf( pDimIndex = 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'Index for new dimension is a REQUIRED parameter!');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( pDimIndex > cDimCount + 1 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'Cube %pCube% has %cDimCount% dimensions. %pDimIndex% is not valid for the new dimension index!');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate dimension\r\nIf( Trim( pDim ) @= '' );\r\n nErrors = nErrors + 1;\r\n sMessage = 'No dimension specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( DimensionExists( pDim ) = 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'New dimension: %pDim% does not exist');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# check element chosen in new dimension\r\nIf( pIncludeData = 1 & Trim(pEle)@='' );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'No element specified in new dimension %pDim% to store cube data.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\nIf( pIncludeData = 1 & DIMIX(pDim, pEle)=0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'Invalid element %pEle% specified for the new dimension %pDim% to store cube data.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\nIF(pIncludeRules = 1 % pIncludeRules = 2);\r\n sRule=CubeRuleGet( pCube );\r\n If( sRule@= '' );\r\n pIncludeRules = 0;\r\n LogOutput( 'INFO', Expand( 'No rule found for %pCube%.' ) );\r\n Endif;\r\nEndif; \r\n\r\n### Determine number of dims in source cube & create strings to check and recreate ###\r\nnCount = 1;\r\nsDimString = '';\r\nsDimCheck = '';\r\nsDelim = '+';\r\nnNewFound = 0;\r\nnIncrement = 1;\r\nWhile( TabDim( pCube, nCount ) @<> '' );\r\n sDim = TabDim( pCube, nCount );\r\n IF(nCount = pDimIndex & nNewFound = 0);\r\n sNewDim = pDim;\r\n nNewFound = 1;\r\n nIncrement = 0;\r\n else;\r\n sNewDim = sDim;\r\n nIncrement = 1;\r\n Endif; \r\n sDimCheck = sDimCheck|'+'|sDim|'+';\r\n sDimString = sDimString|'+'|sNewDim;\r\n nCount = nCount + nIncrement;\r\nEnd;\r\nnDimensionCount = nCount;\r\n\r\n# Cover case of new dimension in last position (pDimIndex = cDimCount+1)\r\nIf( nDimensionCount = pDimIndex & nNewFound = 0 );\r\n nNewFound = 1;\r\n sNewDim=pDim;\r\n sDimString = sDimString|'+'|sNewDim;\r\nEndIf;\r\n\r\n# Remove any leading +\r\nIF( Subst( sDimString , 1 , 1 ) @= '+' );\r\n sDimString = Subst ( sDimString , 2, Long(sDimString)-1 );\r\nEndIf;\r\n\r\nIF( Scan('+'|Lower(pDim)|'+', Lower(sDimCheck)) > 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'The chosen new dimension %pDim% already exists in cube %pCube%.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndif;\r\n\r\n# Check if cube exceeds current max dimenions\r\nIf( nDimensionCount > 27 );\r\n sMessage = 'Process needs to be modified to handle cubes with more than 27 dimensions';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n###### CALLING THE STEP PROCESSES #####\r\n\r\n# Keep the rule\r\nIF(pIncludeRules = 1 % pIncludeRules = 2);\r\n \r\n sProc = '}bedrock.cube.rule.manage';\r\n nRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCube,\r\n 'pMode', 'UNLOAD'\r\n );\r\n \r\n IF(nRet <> 0);\r\n sMessage = 'Error unloading the rule for %pCube%.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n \r\nEndif; \r\n\r\n# create clone cube with data\r\nIF(pIncludeData = 1);\r\n \r\n pCloneCube = pCube | '_Clone';\r\n nIncludeRules = IF(pIncludeRules = 1 % pIncludeRules = 2, 1, 0);\r\n nSuppressRules = IF(nIncludeRules = 1, 1, 0);\r\n \r\n sProc = '}bedrock.cube.clone';\r\n nRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pSrcCube', pCube,\r\n 'pTgtCube', pCloneCube,\r\n 'pIncludeRules', nIncludeRules,\r\n 'pIncludeData', pIncludeData,\r\n 'pSuppressRules', nSuppressRules,\r\n 'pTemp', pTemp,\r\n 'pCubeLogging', 0\r\n );\r\n\r\n IF(nRet <> 0);\r\n sMessage = 'Error creating cloned cube for keeping data.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\nEndif;\r\n\r\n# recreate the cube\r\nsProc = '}bedrock.cube.create';\r\nnRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCube,\r\n 'pDims', sDimString,\r\n 'pRecreate', 1,\r\n 'pDelim', sDelim\r\n );\r\n\r\nIF(nRet <> 0);\r\n sMessage = Expand('Error recreating the cube: %pCube%.');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nENDIF;\r\n\r\n# copy back the data\r\nIF(pIncludeData = 1);\r\n sEleStartDelim = '\u00a6';\r\n sMappingToNewDims = pDim|sEleStartDelim|pEle;\r\n \r\n nRet = ExecuteProcess('}bedrock.cube.data.copy.intercube',\r\n \t'pLogOutput',pLogOutput,\r\n \t'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pSrcCube',pCloneCube,\r\n \t'pFilter','',\r\n \t'pTgtCube',pCube,\r\n \t'pMappingToNewDims',sMappingToNewDims,\r\n 'pSuppressConsol', 1,\r\n 'pSuppressRules', nSuppressRules,\r\n \t'pZeroTarget',0,\r\n \t'pZeroSource',0,\r\n \t'pFactor',1,\r\n \t'pDimDelim','&',\r\n \t'pEleStartDelim',sEleStartDelim,\r\n \t'pEleDelim','+',\r\n \t'pTemp',pTemp,\r\n \t'pCubeLogging',0);\r\n \r\n IF(nRet <> 0);\r\n sMessage = Expand('Error copying back the data from clone cube: %pCloneCube%.');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n \r\n # destroy clone cube\r\n IF(pTemp=1);\r\n sProc = '}bedrock.cube.delete';\r\n nRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCloneCube,\r\n 'pCtrlObj', 0\r\n );\r\n\r\n IF(nRet <> 0);\r\n sMessage = Expand('Error deleting the clone cube: %pCloneCube%.');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n Endif;\r\n\r\nEndif; \r\n\r\n# reload the rule\r\nIF(pIncludeRules = 2);\r\n \r\n sProc = '}bedrock.cube.rule.manage';\r\n\r\n nRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCube,\r\n 'pMode', 'LOAD'\r\n );\r\n \r\n IF(nRet <> 0);\r\n sMessage = Expand('Error reloading the rule for %pCube%.');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n # Create error rule file \r\n cErrorRuleName = 'ErrorRuleFile.txt';\r\n \r\n IF(FileExists( Lower(cErrorRuleName) ) = 0 );\r\n sFile = '.' | sOSDelim | Lower(cErrorRuleName);\r\n LogOutput(cMsgErrorLevel, 'Rule could not be attached due to invalid !Dimension references. Please recover from the backup and fix manually.');\r\n ENDIF;\r\n \r\n ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCube,\r\n 'pFileName', Lower(cErrorRuleName),\r\n 'pMode', 'LOAD'\r\n );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n \r\nEndif; \r\n\r\n### End Prolog ###", "MetadataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "DataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "EpilogProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n### Return code & final error message handling\r\nIf( nErrors > 0 );\r\n sMessage = 'the process incurred at least 1 error. Please see above lines in this file for more details.';\r\n nProcessReturnCode = 0;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% Process:%cThisProcName% completed with errors. Check tm1server.log for details.' );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n EndIf;\r\nElse;\r\n sProcessAction = Expand( 'Process:%cThisProcName% successfully added dimension %pDim%.' );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% %sProcessAction%' );\r\n nProcessReturnCode = 1;\r\n If( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( sProcessAction ) ); \r\n EndIf;\r\nEndIf;\r\n\r\n### End Epilog ###", @@ -10,18 +10,6 @@ "Type": "None" }, "Parameters": [ - { - "Name": "pLogOutput", - "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, - { - "Name": "pStrictErrorHandling", - "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, { "Name": "pCube", "Prompt": "REQUIRED: Cube name", @@ -36,39 +24,57 @@ }, { "Name": "pDimIndex", - "Prompt": "REQUIRED: Dimension number of the new dimension in the cube", - "Value": 1, + "Prompt": "REQUIRED: Index in dimension list where pDim will be inserted", + "Value": 0, "Type": "Numeric" }, { "Name": "pIncludeData", - "Prompt": "OPTIONAL: If 1 then data is kept (copied through clone cube)", + "Prompt": "OPTIONAL: Include cube data (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" }, { "Name": "pEle", - "Prompt": "REQUIRED: if IncludeData flag =1: Element of new dimension where to store data", + "Prompt": "OPTIONAL: Required if IncludeData flag =1. Element of new dimension where the existing data will be stored", "Value": "", "Type": "String" }, { "Name": "pIncludeRules", - "Prompt": "Unload and reload the rule (0 = do not keep the rule, 1 = unload the rule, 2 = unload the rule and reload on new cube)", - "Value": 2, + "Prompt": "OPTIONAL: Include cube rules (Boolean. Default = 1)", + "Value": 1, "Type": "Numeric" }, { "Name": "pCtrlObj", - "Prompt": "OPTIONAL: Allow overwrite control cubes (default = 0)", + "Prompt": "OPTIONAL: OPTIONAL: Allow modification of control objects (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" }, { "Name": "pTemp", - "Prompt": "OPTIONAL: Delete the clone cube (1 = delete, 0 = not delete)", + "Prompt": "OPTIONAL: Delete/create temporary objects (0 = Do not delete, 1 = Delete, 2 = if view and subsets are created, keep only subsets)", "Value": 1, "Type": "Numeric" + }, + { + "Name": "pLogOutput", + "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pStrictErrorHandling", + "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pJson", + "Prompt": "OPTIONAL: JSON Object with process parameter values. This will overwrite user passed parameters for all included parameters.", + "Value": "{}", + "Type": "String" } ], "Variables": [], diff --git a/bedrock_processes_json/}bedrock.cube.dimension.delete.json b/bedrock_processes_json/}bedrock.cube.dimension.delete.json index 8983ae7..cbeaf87 100644 --- a/bedrock_processes_json/}bedrock.cube.dimension.delete.json +++ b/bedrock_processes_json/}bedrock.cube.dimension.delete.json @@ -1,6 +1,6 @@ { "Name": "}bedrock.cube.dimension.delete", - "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.dimension.delete', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pCube', '', 'pDim', '',\r\n \t'pIncludeData', 1, 'pIncludeRules', 2,\r\n \t'pCtrlObj', 0, 'pTemp', 1\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This TI deletes a dimension from a cube that has already been built with the ability to preserve data.\r\n\r\n# Use case: Intended for development/prototyping.\r\n# 1/ Rebuild existing cube with the removal of one dimension without losing all the data.\r\n\r\n# Note:\r\n# Naturally, a valid cube name (pCube) is mandatory otherwise the process will abort.\r\n# Also, a valid dimension name (pDim) is mandatory otherwise the process will abort.\r\n# If data needs to be kept (using pIncludeData), data from pDim will be summed.\r\n# Rule can be kept as backup file only or reloaded back.\r\n#EndRegion @DOC\r\n\r\n### Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSub = cThisProcName |'_'| cTimeStamp |'_'| cRandomInt;\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent= 'Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pCube:%pCube%, pDim:%pDim%, pIncludeData:%pIncludeData%, pIncludeRules:%pIncludeRules%, pCtrlObj:%pCtrlObj%, pTemp:%pTemp%.';\r\n\r\n## check operating system\r\nIf( SubSt( GetProcessErrorFileDirectory, 2, 1 ) @= ':' );\r\n sOS = 'Windows';\r\n sOSDelim = '\\';\r\nElseIf( Scan( '/', GetProcessErrorFileDirectory ) > 0 );\r\n sOS = 'Linux';\r\n sOSDelim = '/';\r\nElse;\r\n sOS = 'Windows';\r\n sOSDelim = '\\';\r\nEndIf;\r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\n### Validate Parameters ###\r\nnErrors = 0;\r\n# Validate cube\r\nIf( Trim( pCube ) @= '' );\r\n nErrors = nErrors + 1;\r\n sMessage = 'No cube specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( CubeExists( pCube ) = 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'Invalid cube specified: %pCube%.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Don't allow system cubes to be modified\r\nIf( SubSt( pCube, 1, 1 ) @= '}' & pCtrlObj <= 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'Do not modify system cubes: %pCube%.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate dimension\r\nIf( Trim( pDim ) @= '' );\r\n nErrors = nErrors + 1;\r\n sMessage = 'No dimension specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( DimensionExists( pDim ) = 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'New dimension: %pDim% does not exist');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\nIF(pIncludeRules = 1 % pIncludeRules = 2);\r\n cCubeRule=CubeRuleGet( pCube );\r\n If(cCubeRule @= '');\r\n pIncludeRules = 0;\r\n LogOutput( 'INFO', Expand( 'No rule found for %pCube%.' ) );\r\n Endif;\r\nEndif; \r\n\r\n### Determine number of dims in source cube & create strings to check and recreate ###\r\nnCount = 1;\r\nsDimString = '';\r\nsDimCheck = '';\r\nsDelim = '+';\r\nnSkip=0;\r\nnIncrement = 1;\r\nWhile( TabDim( pCube, nCount ) @<> '' );\r\n sDim = TabDim( pCube, nCount );\r\n IF(sDim@=pDim);\r\n nSkip = 1;\r\n else;\r\n nSkip = 0;\r\n Endif; \r\n sDimCheck = sDimCheck|'+'|sDim|'+';\r\n IF(nSkip = 0);\r\n sDimString = sDimString|'+'|sDim;\r\n Endif;\r\n nCount = nCount + 1;\r\nEnd;\r\nnDimensionCount = nCount-1;\r\n\r\n#Remove any leading +\r\nIF( Subst( sDimString , 1 , 1 ) @= '+' );\r\n sDimString = Subst ( sDimString , 2 , Long(sDimString)-1 );\r\nEndIf;\r\n\r\nIF( Scan('+'|Lower(pDim)|'+', Lower(sDimCheck)) = 0);\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'The chosen dimension %pDim% does not exists in cube %pCube%.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndif;\r\n\r\n# Check if cube exceeds current max dimenions\r\nIf( nDimensionCount > 27 );\r\n sMessage = 'Process needs to be modified to handle cubes with more than 27 dimensions';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n###### CALLING THE STEP PROCESSES #####\r\n\r\n# Keep the rule\r\nIF(pIncludeRules = 1 % pIncludeRules = 2);\r\n \r\n sProc = '}bedrock.cube.rule.manage';\r\n\r\n nRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCube,\r\n 'pMode', 'UNLOAD'\r\n );\r\n \r\n IF(nRet <> 0);\r\n sMessage = 'Error unloading the rule for %pCube%.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n \r\nEndif; \r\n\r\n# create clone cube with data\r\nIF(pIncludeData = 1);\r\n pCloneCube = pCube | '_Clone';\r\n nIncludeRules = IF(pIncludeRules = 1 % pIncludeRules = 2, 1, 0);\r\n nSuppressRules = IF(nIncludeRules = 1, 1, 0);\r\n \r\n sProc = '}bedrock.cube.clone';\r\n nRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pSrcCube', pCube,\r\n 'pTgtCube', pCloneCube,\r\n 'pIncludeRules', nIncludeRules,\r\n 'pIncludeData', pIncludeData,\r\n 'pSuppressRules', nSuppressRules,\r\n 'pTemp', pTemp,\r\n 'pCubeLogging', 0\r\n );\r\n\r\n IF(nRet <> 0);\r\n sMessage = 'Error creating cloned cube for keeping data.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n \r\nEndif;\r\n\r\n#Processbreak;\r\n\r\n# recreate the cube\r\nsProc = '}bedrock.cube.create';\r\nnRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCube,\r\n 'pDims', sDimString,\r\n 'pRecreate', 1,\r\n 'pDelim', sDelim\r\n );\r\n\r\nIF(nRet <> 0);\r\n sMessage = Expand('Error recreating the cube: %pCube%.');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nENDIF;\r\n\r\n#Processbreak;\r\n\r\n# copy back the data\r\nIF(pIncludeData = 1);\r\n sProc = '}bedrock.cube.data.copy.intercube';\r\n nRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pSrcCube', pCloneCube,\r\n 'pFilter', '',\r\n 'pTgtCube', pCube,\r\n 'pMappingToNewDims', '',\r\n 'pSuppressConsol', 1,\r\n 'pSuppressRules', nSuppressRules,\r\n 'pZeroSource', 0,\r\n 'pZeroTarget', 0,\r\n 'pFactor', 1,\r\n 'pTemp', pTemp,\r\n 'pCubeLogging', 0\r\n ); \r\n \r\n IF(nRet <> 0);\r\n sMessage = Expand('Error copying back the data from clone cube: %pCloneCube%.');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n \r\n # destroy clone cube\r\n IF(pTemp=1);\r\n sProc = '}bedrock.cube.delete';\r\n nRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCloneCube,\r\n 'pCtrlObj', 0\r\n );\r\n\r\n IF(nRet <> 0);\r\n sMessage = Expand('Error deleting cloned cube: %pCloneCube%.');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n Endif;\r\n \r\nEndif; \r\n\r\n# reload the rule\r\nIF(pIncludeRules = 2);\r\n \r\n sProc = '}bedrock.cube.rule.manage';\r\n\r\n nRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCube,\r\n 'pMode', 'LOAD'\r\n );\r\n \r\n IF(nRet <> 0);\r\n sMessage = Expand('Error reloading the rule for %pCube%.');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n # Create error rule file \r\n cErrorRuleName = 'ErrorRuleFile.rux';\r\n\r\n IF(FileExists( Lower(cErrorRuleName) ) = 0 );\r\n sFile = '.' | sOSDelim | Lower(cErrorRuleName);\r\n LogOutput(cMsgErrorLevel, 'Rule could not be attached due to invalid !Dimension references. Please recover from the backup and fix manually.');\r\n ENDIF;\r\n\r\n ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCube,\r\n 'pFileName', Lower(cErrorRuleName),\r\n 'pMode', 'LOAD'\r\n );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n \r\nEndif; \r\n\r\n### End Prolog ###", + "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.dimension.delete', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pCube', '', 'pDim', '',\r\n \t'pIncludeData', 1, 'pIncludeRules', 2,\r\n \t'pCtrlObj', 0, 'pTemp', 1\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This TI deletes a dimension from a cube that has already been built with the ability to preserve data.\r\n\r\n# Use case: Intended for development/prototyping.\r\n# 1/ Rebuild existing cube with the removal of one dimension without losing all the data.\r\n\r\n# Note:\r\n# Naturally, a valid cube name (pCube) is mandatory otherwise the process will abort.\r\n# Also, a valid dimension name (pDim) is mandatory otherwise the process will abort.\r\n# If data needs to be kept (using pIncludeData), data from pDim will be summed.\r\n# Rule can be kept as backup file only or reloaded back.\r\n#EndRegion @DOC\r\n\r\n### Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSub = cThisProcName |'_'| cTimeStamp |'_'| cRandomInt;\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent= 'Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pCube:%pCube%, pDim:%pDim%, pIncludeData:%pIncludeData%, pIncludeRules:%pIncludeRules%, pCtrlObj:%pCtrlObj%, pTemp:%pTemp%.';\r\n\r\n#################################################################################################\r\n#Region - Process Parameters\r\n\r\npJson = IF( JsonType( pJson ) @<> 'object', '{}', pJson );\r\nsMessages = '{\"Process\": \"'|GetProcessName()|'\", \"User\": \"'|TM1User()|'\", \"Info\": [\"Process: '''|GetProcessName()|''' run by User: '''|TM1User()|'''.\"], \"Error\": []}';\r\npDefaultParameters = '{\r\n \"pCube\": null,\r\n \"pDim\": null,\r\n \"pCtrlObj\": 0,\r\n \"pIncludeData\": 0,\r\n \"pIncludeRules\": 1,\r\n \"pLogOutput\": 0,\r\n \"pStrictErrorHandling\": 0,\r\n \"pTemp\": 1\r\n}';\r\n\r\npPassedParameters = '{\r\n \"pCube\": '|StringToJson ( pCube )|',\r\n \"pDim\": '|StringToJson ( pDim )|',\r\n \"pCtrlObj\": '|NumberToString( pCtrlObj )|',\r\n \"pIncludeData\": '|NumberToString( pIncludeData )|',\r\n \"pIncludeRules\": '|NumberToString( pIncludeRules )|',\r\n \"pLogOutput\": '|NumberToString( pLogOutput )|',\r\n \"pStrictErrorHandling\": '|NumberToString( pStrictErrorHandling )|',\r\n \"pTemp\": '|NumberToString( pTemp )|'\r\n}';\r\n\r\npJson = JsonMergePatch( pPassedParameters, pJson );\r\n# String Parameters\r\npCube = JsonToString( JsonGet( pJson, 'pCube' ) );\r\npDim = JsonToString( JsonGet( pJson, 'pDim' ) );\r\n# Numeric Parameters\r\npCtrlObj = StringToNumber( JsonToString( JsonGet( pJson, 'pCtrlObj' ) ) );\r\npIncludeData = StringToNumber( JsonToString( JsonGet( pJson, 'pIncludeData' ) ) );\r\npIncludeRules = StringToNumber( JsonToString( JsonGet( pJson, 'pIncludeRules' ) ) );\r\npLogOutput = StringToNumber( JsonToString( JsonGet( pJson, 'pLogOutput' ) ) );\r\npStrictErrorHandling = StringToNumber( JsonToString( JsonGet( pJson, 'pStrictErrorHandling' ) ) );\r\npTemp = StringToNumber( JsonToString( JsonGet( pJson, 'pTemp' ) ) );\r\n\r\n### Get the parameters that differ from the default\r\npDiffer = JsonDiff( pDefaultParameters, pJson );\r\nnSize = JsonSize( pDiffer );\r\nWHILE( nSize > 0 );\r\n nSize = nSize - 1;\r\n pDiffer = JsonReplace( pDiffer, '/'|NumberToString( nSize )|'/op', '\"add\"' );\r\nEND;\r\npJson = JsonPatch( '{}', pDiffer );\r\n\r\n### LogOutput parameters\r\nsMessages = JsonAdd( sMessages, '/Info/-', pJson );\r\nIF( pLogOutput = 1 );\r\n LogOutput('INFO', JsonToString( sMessages, '/Info/0', 0, ' ' ) );\r\nENDIF;\r\n\r\n#EndRegion - Process Parameters\r\n#################################################################################################\r\n\r\n## check operating system\r\nIf( SubSt( GetProcessErrorFileDirectory, 2, 1 ) @= ':' );\r\n sOS = 'Windows';\r\n sOSDelim = '\\';\r\nElseIf( Scan( '/', GetProcessErrorFileDirectory ) > 0 );\r\n sOS = 'Linux';\r\n sOSDelim = '/';\r\nElse;\r\n sOS = 'Windows';\r\n sOSDelim = '\\';\r\nEndIf;\r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\n### Validate Parameters ###\r\nnErrors = 0;\r\n# Validate cube\r\nIf( Trim( pCube ) @= '' );\r\n nErrors = nErrors + 1;\r\n sMessage = 'No cube specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( CubeExists( pCube ) = 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'Invalid cube specified: %pCube%.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Don't allow system cubes to be modified\r\nIf( SubSt( pCube, 1, 1 ) @= '}' & pCtrlObj <= 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'Do not modify system cubes: %pCube%.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate dimension\r\nIf( Trim( pDim ) @= '' );\r\n nErrors = nErrors + 1;\r\n sMessage = 'No dimension specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( DimensionExists( pDim ) = 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'New dimension: %pDim% does not exist');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\nIF(pIncludeRules = 1 % pIncludeRules = 2);\r\n cCubeRule=CubeRuleGet( pCube );\r\n If(cCubeRule @= '');\r\n pIncludeRules = 0;\r\n LogOutput( 'INFO', Expand( 'No rule found for %pCube%.' ) );\r\n Endif;\r\nEndif; \r\n\r\n### Determine number of dims in source cube & create strings to check and recreate ###\r\nnCount = 1;\r\nsDimString = '';\r\nsDimCheck = '';\r\nsDelim = '+';\r\nnSkip=0;\r\nnIncrement = 1;\r\nWhile( TabDim( pCube, nCount ) @<> '' );\r\n sDim = TabDim( pCube, nCount );\r\n IF(sDim@=pDim);\r\n nSkip = 1;\r\n else;\r\n nSkip = 0;\r\n Endif; \r\n sDimCheck = sDimCheck|'+'|sDim|'+';\r\n IF(nSkip = 0);\r\n sDimString = sDimString|'+'|sDim;\r\n Endif;\r\n nCount = nCount + 1;\r\nEnd;\r\nnDimensionCount = nCount-1;\r\n\r\n#Remove any leading +\r\nIF( Subst( sDimString , 1 , 1 ) @= '+' );\r\n sDimString = Subst ( sDimString , 2 , Long(sDimString)-1 );\r\nEndIf;\r\n\r\nIF( Scan('+'|Lower(pDim)|'+', Lower(sDimCheck)) = 0);\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'The chosen dimension %pDim% does not exists in cube %pCube%.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndif;\r\n\r\n# Check if cube exceeds current max dimenions\r\nIf( nDimensionCount > 27 );\r\n sMessage = 'Process needs to be modified to handle cubes with more than 27 dimensions';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n###### CALLING THE STEP PROCESSES #####\r\n\r\n# Keep the rule\r\nIF(pIncludeRules = 1 % pIncludeRules = 2);\r\n \r\n sProc = '}bedrock.cube.rule.manage';\r\n\r\n nRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCube,\r\n 'pMode', 'UNLOAD'\r\n );\r\n \r\n IF(nRet <> 0);\r\n sMessage = 'Error unloading the rule for %pCube%.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n \r\nEndif; \r\n\r\n# create clone cube with data\r\nIF(pIncludeData = 1);\r\n pCloneCube = pCube | '_Clone';\r\n nIncludeRules = IF(pIncludeRules = 1 % pIncludeRules = 2, 1, 0);\r\n nSuppressRules = IF(nIncludeRules = 1, 1, 0);\r\n \r\n sProc = '}bedrock.cube.clone';\r\n nRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pSrcCube', pCube,\r\n 'pTgtCube', pCloneCube,\r\n 'pIncludeRules', nIncludeRules,\r\n 'pIncludeData', pIncludeData,\r\n 'pSuppressRules', nSuppressRules,\r\n 'pTemp', pTemp,\r\n 'pCubeLogging', 0\r\n );\r\n\r\n IF(nRet <> 0);\r\n sMessage = 'Error creating cloned cube for keeping data.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n \r\nEndif;\r\n\r\n#Processbreak;\r\n\r\n# recreate the cube\r\nsProc = '}bedrock.cube.create';\r\nnRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCube,\r\n 'pDims', sDimString,\r\n 'pRecreate', 1,\r\n 'pDelim', sDelim\r\n );\r\n\r\nIF(nRet <> 0);\r\n sMessage = Expand('Error recreating the cube: %pCube%.');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nENDIF;\r\n\r\n#Processbreak;\r\n\r\n# copy back the data\r\nIF(pIncludeData = 1);\r\n sProc = '}bedrock.cube.data.copy.intercube';\r\n nRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pSrcCube', pCloneCube,\r\n 'pFilter', '',\r\n 'pTgtCube', pCube,\r\n 'pMappingToNewDims', '',\r\n 'pSuppressConsol', 1,\r\n 'pSuppressRules', nSuppressRules,\r\n 'pZeroSource', 0,\r\n 'pZeroTarget', 0,\r\n 'pFactor', 1,\r\n 'pTemp', pTemp,\r\n 'pCubeLogging', 0\r\n ); \r\n \r\n IF(nRet <> 0);\r\n sMessage = Expand('Error copying back the data from clone cube: %pCloneCube%.');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n \r\n # destroy clone cube\r\n IF(pTemp=1);\r\n sProc = '}bedrock.cube.delete';\r\n nRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCloneCube,\r\n 'pCtrlObj', 0\r\n );\r\n\r\n IF(nRet <> 0);\r\n sMessage = Expand('Error deleting cloned cube: %pCloneCube%.');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n Endif;\r\n \r\nEndif; \r\n\r\n# reload the rule\r\nIF(pIncludeRules = 2);\r\n \r\n sProc = '}bedrock.cube.rule.manage';\r\n\r\n nRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCube,\r\n 'pMode', 'LOAD'\r\n );\r\n \r\n IF(nRet <> 0);\r\n sMessage = Expand('Error reloading the rule for %pCube%.');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n # Create error rule file \r\n cErrorRuleName = 'ErrorRuleFile.rux';\r\n\r\n IF(FileExists( Lower(cErrorRuleName) ) = 0 );\r\n sFile = '.' | sOSDelim | Lower(cErrorRuleName);\r\n LogOutput(cMsgErrorLevel, 'Rule could not be attached due to invalid !Dimension references. Please recover from the backup and fix manually.');\r\n ENDIF;\r\n\r\n ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCube,\r\n 'pFileName', Lower(cErrorRuleName),\r\n 'pMode', 'LOAD'\r\n );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n \r\nEndif; \r\n\r\n### End Prolog ###", "MetadataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "DataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "EpilogProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n### Return code & final error message handling\r\nIf( nErrors > 0 );\r\n sMessage = 'the process incurred at least 1 error. Please see above lines in this file for more details.';\r\n nProcessReturnCode = 0;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% Process:%cThisProcName% completed with errors. Check tm1server.log for details.' );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n EndIf;\r\nElse;\r\n sProcessAction = Expand( 'Process:%cThisProcName% successfully deleted dimension %pDim% from the %pCube% cube.' );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% %sProcessAction%' );\r\n nProcessReturnCode = 1;\r\n If( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( sProcessAction ) ); \r\n EndIf;\r\nEndIf;\r\n\r\n### End Epilog ###", @@ -10,21 +10,9 @@ "Type": "None" }, "Parameters": [ - { - "Name": "pLogOutput", - "Prompt": "REQUIRED: Optional: write parameters and action summary to server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, - { - "Name": "pStrictErrorHandling", - "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, { "Name": "pCube", - "Prompt": "REQUIRED: Cube", + "Prompt": "REQUIRED: Cube name", "Value": "", "Type": "String" }, @@ -36,27 +24,45 @@ }, { "Name": "pIncludeData", - "Prompt": "REQUIRED: If 1 then data is kept (copied through clone cube)", - "Value": 1, + "Prompt": "OPTIONAL: Include cube data (Boolean. Default = 0)", + "Value": 0, "Type": "Numeric" }, { "Name": "pIncludeRules", - "Prompt": "REQUIRED: Unload and reload the rule (0 = do not keep the rule, 1 = unload the rule, 2 = unload the rule and reload on new cube)", - "Value": 2, + "Prompt": "OPTIONAL: Include cube rules (Boolean. Default = 1)", + "Value": 1, "Type": "Numeric" }, { "Name": "pCtrlObj", - "Prompt": "REQUIRED: Allow overwrite control cubes", + "Prompt": "OPTIONAL: OPTIONAL: Allow modification of control objects (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" }, { "Name": "pTemp", - "Prompt": "REQUIRED: Delete the clone cube (1 = delete, 0 = not delete)", + "Prompt": "OPTIONAL: Delete/create temporary objects (0 = Do not delete, 1 = Delete, 2 = if view and subsets are created, keep only subsets)", "Value": 1, "Type": "Numeric" + }, + { + "Name": "pLogOutput", + "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pStrictErrorHandling", + "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pJson", + "Prompt": "OPTIONAL: JSON Object with process parameter values. This will overwrite user passed parameters for all included parameters.", + "Value": "{}", + "Type": "String" } ], "Variables": [], diff --git a/bedrock_processes_json/}bedrock.cube.dimension.replace.json b/bedrock_processes_json/}bedrock.cube.dimension.replace.json index 00eb990..ecb2d3f 100644 --- a/bedrock_processes_json/}bedrock.cube.dimension.replace.json +++ b/bedrock_processes_json/}bedrock.cube.dimension.replace.json @@ -1,6 +1,6 @@ { "Name": "}bedrock.cube.dimension.replace", - "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.dimension.replace', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pCube', '', 'pSrcDim', '', 'pTgtDim', '',\r\n \t'pIncludeData', 0, 'pEle', '',\r\n \t'pIncludeRules', 0,\r\n \t'pCtrlObj', 0, 'pTemp', 1\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This TI deletes a dimension and adds another one to an existing cube with the ability to preserve data.\r\n\r\n# Use case: Intended for development/prototyping.\r\n# 1/ Rebuild existing cube after removal of one dimension and adding anothr one without losing all the data.\r\n\r\n# Note:\r\n# Naturally, a valid cube name (pCube) is mandatory otherwise the process will abort.\r\n# Also, valid dimension names (pSrcDim & pTgtDim) are mandatory otherwise the process will abort.\r\n# When data needs to be kept (using pIncludeData) a valid element (pEle) in new dimension must be specified\r\n# where to store the data. Data is summed from original dimension.\r\n# Rule can be kept as backup file only or reloaded back.\r\n#EndRegion @DOC\r\n\r\n\r\n# This process selects the cube and replaces\r\n# the source dimensions from a specified target dimensions.\r\n# This process should only be run on an EMPTY cube or a cube that\r\n# has already had all data exported to a text file\r\n\r\n# Note:\r\n# - This process does not preserve any cube rules as they would likely no longer be\r\n# valid if a dimension is replaced\r\n\r\n##Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pCube:%pCube%, pSrcDim:%pSrcDim%, pTgtDim:%pTgtDim%, pIncludeData:%pIncludeData%, pEle:%pEle%, pIncludeRules:%pIncludeRules%, pCtrlObj:%pCtrlObj%, pTemp:%pTemp%.' ; \r\ncDefaultView = Expand( '%cThisProcName%_%cTimeStamp%_%cRandomInt%' );\r\n\r\n## check operating system\r\nIf( SubSt( GetProcessErrorFileDirectory, 2, 1 ) @= ':' );\r\n sOS = 'Windows';\r\n sOSDelim = '\\';\r\nElseIf( Scan( '/', GetProcessErrorFileDirectory ) > 0 );\r\n sOS = 'Linux';\r\n sOSDelim = '/';\r\nElse;\r\n sOS = 'Windows';\r\n sOSDelim = '\\';\r\nEndIf;\r\n\r\n### Validate Parameters ###\r\nnErrors = 0;\r\n# Validate cube\r\nIf( Trim( pCube ) @= '' );\r\n sMessage = 'No cube specified.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( CubeExists( pCube ) = 0 );\r\n sMessage = Expand( 'Cube %pCube% does not exist.' );\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Don't allow system cubes to be modified\r\nIf( SubSt( pCube, 1, 1 ) @= '}' & pCtrlObj <= 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'Do not modify system cubes: %pCube%.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate source dimension\r\nIf( Trim( pSrcDim ) @= '' );\r\n nErrors = nErrors + 1;\r\n sMessage = 'No source dimension specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( DimensionExists( pSrcDim ) = 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'Source dimension %pSrcDim% does not exist.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate target dimension\r\nIf( Trim( pTgtDim ) @= '' );\r\n nErrors = nErrors + 1;\r\n sMessage = 'No target dimension specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( DimensionExists( pTgtDim ) = 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'Target dimension %pTgtDim% does not exist.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Check that the source and target dimensions are different\r\nIf( pSrcDim @= pTgtDim );\r\n sMessage = Expand('Source and target dimensions are the same: %pSrcDim%');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# check element chosen in new dimension\r\nIf( pIncludeData = 1 & Trim(pEle)@='' );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'No element specified in new dimension %pTgtDim% to store cube data.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\nIf( pIncludeData = 1 & DIMIX(pTgtDim, pEle)=0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'Invalid element %pEle% specified for the new dimension %pTgtDim% to store cube data.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\nIF(pIncludeRules = 1 % pIncludeRules = 2);\r\n sRule=CubeRuleGet( pCube );\r\n If(sRule@= '');\r\n pIncludeRules = 0;\r\n LogOutput( 'INFO', Expand( 'No rule found for %pCube%.' ) );\r\n Endif;\r\nEndif; \r\n\r\n### Determine number of dims in source cube & create strings to check and recreate ###\r\nnCount = 1;\r\nsDimString = '';\r\nsDimCheck = '';\r\nsDelim = '+';\r\nWhile( TabDim( pCube, nCount ) @<> '' );\r\n sDim = TabDim( pCube, nCount );\r\n IF(sDim@=pSrcDim);\r\n sNewDim=pTgtDim;\r\n else;\r\n sNewDim=sDim;\r\n Endif; \r\n IF(nCount = 1);\r\n sDimCheck = '+'|sDim|'+';\r\n sDimString = sNewDim;\r\n elseif(nCount > 1);\r\n sDimCheck = sDimCheck|'+'|sDim|'+';\r\n sDimString = sDimString|'+'|sNewDim;\r\n Endif;\r\n nCount = nCount + 1;\r\nEnd;\r\nnDimensionCount = nCount - 1;\r\n\r\n#Remove any leading +\r\nIF( Subst( sDimString , 1 , 1 ) @= '+' );\r\n sDimString = Subst ( sDimString , 2 , 999 );\r\nEndIf;\r\n\r\n#check source dimension\r\nIF(scan('+'|pSrcDim|'+', sDimCheck)=0);\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'Source Dimension %pSrcDim% does not exist in %pCube%.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndif; \r\n\r\n#check target dimension\r\nIF(scan('+'|pTgtDim|'+', sDimCheck)>0);\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'Target Dimension %pTgtDim% already exists in %pCube%.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndif;\r\n\r\n# Check if cube exceeds current max dimenions\r\nIf( nDimensionCount > 27 );\r\n sMessage = 'Process needs to be modified to handle cubes with more than 27 dimensions';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n###### CALLING THE STEP PROCESSES #####\r\n# Keep the rule\r\nIF(pIncludeRules = 1 % pIncludeRules = 2);\r\n sProc = '}bedrock.cube.rule.manage';\r\n\r\n nRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCube,\r\n 'pMode', 'UNLOAD'\r\n );\r\n \r\n IF(nRet <> 0);\r\n sMessage = 'Error unloading the rule for %pCube%.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf; \r\n ENDIF;\r\n \r\nEndif; \r\n\r\n# create clone cube with data\r\nIF(pIncludeData = 1);\r\n \r\n pCloneCube = pCube | '_Clone';\r\n nIncludeRules = IF(pIncludeRules = 1 % pIncludeRules = 2, 1, 0);\r\n nSuppressRules = IF(nIncludeRules = 1, 1, 0);\r\n \r\n sProc = '}bedrock.cube.clone';\r\n nRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pSrcCube', pCube,\r\n 'pTgtCube', pCloneCube,\r\n 'pIncludeRules', nIncludeRules,\r\n 'pIncludeData', pIncludeData,\r\n 'pSuppressRules', nSuppressRules,\r\n 'pTemp', pTemp,\r\n 'pCubeLogging', 0\r\n );\r\n\r\n IF(nRet <> 0);\r\n sMessage = 'Error creating cloned cube for keeping data.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n \r\nEndif;\r\n\r\n# recreate the cube\r\nsProc = '}bedrock.cube.create';\r\nnRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCube,\r\n 'pDims', sDimString,\r\n 'pRecreate', 1,\r\n 'pDelim', sDelim\r\n );\r\n\r\nIF(nRet <> 0);\r\n sMessage = Expand('Error recreating the cube: %pCube%.');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nENDIF;\r\n\r\n\r\n# copy back the data\r\nIF(pIncludeData = 1);\r\n sEleStartDelim = '\u00a6';\r\n sMappingToNewDims = pTgtDim|sEleStartDelim|pEle;\r\n \r\n nRet = ExecuteProcess('}bedrock.cube.data.copy.intercube',\r\n\t 'pLogOutput',pLogOutput,\r\n\t 'pStrictErrorHandling', pStrictErrorHandling,\r\n\t 'pSrcCube',pCloneCube,\r\n\t 'pFilter','',\r\n\t 'pTgtCube',pCube,\r\n\t 'pMappingToNewDims',sMappingToNewDims,\r\n 'pSuppressConsol', 1,\r\n 'pSuppressRules', nSuppressRules,\r\n\t 'pZeroTarget',0,\r\n\t 'pZeroSource',0,\r\n\t 'pFactor',1,\r\n\t 'pDimDelim','&',\r\n\t 'pEleStartDelim',sEleStartDelim,\r\n\t 'pEleDelim','+',\r\n\t 'pTemp',pTemp,\r\n\t 'pCubeLogging',0);\r\n \r\n IF(nRet <> 0);\r\n sMessage = Expand('Error copying back the data from clone cube: %pCloneCube%.');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n \r\n # destroy clone cube\r\n IF(pTemp=1);\r\n sProc = '}bedrock.cube.delete';\r\n nRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCloneCube,\r\n 'pCtrlObj', 0\r\n );\r\n\r\n IF(nRet <> 0);\r\n sMessage = Expand('Error deleting the clone cube: %pCloneCube%.');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n Endif;\r\n \r\nEndif; \r\n\r\n# reload the rule\r\nIF(pIncludeRules = 2);\r\n \r\n sProc = '}bedrock.cube.rule.manage';\r\n\r\n nRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCube,\r\n 'pMode', 'LOAD'\r\n );\r\n \r\n IF(nRet <> 0);\r\n sMessage = Expand('Error reloading the rule for %pCube%.');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n # Create error rule file \r\n cErrorRuleName = 'ErrorRuleFile.txt';\r\n\r\n IF(FileExists( cErrorRuleName ) = 0 );\r\n sFile = '.' | sOSDelim | cErrorRuleName;\r\n LogOutput(cMsgErrorLevel, 'Rule could not be attached due to invalid !Dimension references. Please recover from the backup and fix manually.');\r\n ENDIF;\r\n\r\n ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCube,\r\n 'pFileName', cErrorRuleName,\r\n 'pMode', 'LOAD'\r\n );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n \r\nEndif; \r\n\r\n### End Prolog ###", + "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.dimension.replace', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pCube', '', 'pSrcDim', '', 'pTgtDim', '',\r\n \t'pIncludeData', 0, 'pEle', '',\r\n \t'pIncludeRules', 0,\r\n \t'pCtrlObj', 0, 'pTemp', 1\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This TI deletes a dimension and adds another one to an existing cube with the ability to preserve data.\r\n\r\n# Use case: Intended for development/prototyping.\r\n# 1/ Rebuild existing cube after removal of one dimension and adding anothr one without losing all the data.\r\n\r\n# Note:\r\n# Naturally, a valid cube name (pCube) is mandatory otherwise the process will abort.\r\n# Also, valid dimension names (pSrcDim & pTgtDim) are mandatory otherwise the process will abort.\r\n# When data needs to be kept (using pIncludeData) a valid element (pEle) in new dimension must be specified\r\n# where to store the data. Data is summed from original dimension.\r\n# Rule can be kept as backup file only or reloaded back.\r\n#EndRegion @DOC\r\n\r\n\r\n# This process selects the cube and replaces\r\n# the source dimensions from a specified target dimensions.\r\n# This process should only be run on an EMPTY cube or a cube that\r\n# has already had all data exported to a text file\r\n\r\n# Note:\r\n# - This process does not preserve any cube rules as they would likely no longer be\r\n# valid if a dimension is replaced\r\n\r\n##Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pCube:%pCube%, pSrcDim:%pSrcDim%, pTgtDim:%pTgtDim%, pIncludeData:%pIncludeData%, pEle:%pEle%, pIncludeRules:%pIncludeRules%, pCtrlObj:%pCtrlObj%, pTemp:%pTemp%.' ; \r\ncDefaultView = Expand( '%cThisProcName%_%cTimeStamp%_%cRandomInt%' );\r\n\r\n#################################################################################################\r\n#Region - Process Parameters\r\n\r\npJson = IF( JsonType( pJson ) @<> 'object', '{}', pJson );\r\nsMessages = '{\"Process\": \"'|GetProcessName()|'\", \"User\": \"'|TM1User()|'\", \"Info\": [\"Process: '''|GetProcessName()|''' run by User: '''|TM1User()|'''.\"], \"Error\": []}';\r\npDefaultParameters = '{\r\n \"pCube\": null,\r\n \"pEle\": \"\",\r\n \"pSrcDim\": null,\r\n \"pTgtDim\": null,\r\n \"pCtrlObj\": 0,\r\n \"pIncludeData\": 0,\r\n \"pIncludeRules\": 1,\r\n \"pLogOutput\": 0,\r\n \"pStrictErrorHandling\": 0,\r\n \"pTemp\": 1\r\n}';\r\n\r\npPassedParameters = '{\r\n \"pCube\": '|StringToJson ( pCube )|',\r\n \"pEle\": '|StringToJson ( pEle )|',\r\n \"pSrcDim\": '|StringToJson ( pSrcDim )|',\r\n \"pTgtDim\": '|StringToJson ( pTgtDim )|',\r\n \"pCtrlObj\": '|NumberToString( pCtrlObj )|',\r\n \"pIncludeData\": '|NumberToString( pIncludeData )|',\r\n \"pIncludeRules\": '|NumberToString( pIncludeRules )|',\r\n \"pLogOutput\": '|NumberToString( pLogOutput )|',\r\n \"pStrictErrorHandling\": '|NumberToString( pStrictErrorHandling )|',\r\n \"pTemp\": '|NumberToString( pTemp )|'\r\n}';\r\n\r\npJson = JsonMergePatch( pPassedParameters, pJson );\r\n# String Parameters\r\npCube = JsonToString( JsonGet( pJson, 'pCube' ) );\r\npEle = JsonToString( JsonGet( pJson, 'pEle' ) );\r\npSrcDim = JsonToString( JsonGet( pJson, 'pSrcDim' ) );\r\npTgtDim = JsonToString( JsonGet( pJson, 'pTgtDim' ) );\r\n# Numeric Parameters\r\npCtrlObj = StringToNumber( JsonToString( JsonGet( pJson, 'pCtrlObj' ) ) );\r\npIncludeData = StringToNumber( JsonToString( JsonGet( pJson, 'pIncludeData' ) ) );\r\npIncludeRules = StringToNumber( JsonToString( JsonGet( pJson, 'pIncludeRules' ) ) );\r\npLogOutput = StringToNumber( JsonToString( JsonGet( pJson, 'pLogOutput' ) ) );\r\npStrictErrorHandling = StringToNumber( JsonToString( JsonGet( pJson, 'pStrictErrorHandling' ) ) );\r\npTemp = StringToNumber( JsonToString( JsonGet( pJson, 'pTemp' ) ) );\r\n\r\n### Get the parameters that differ from the default\r\npDiffer = JsonDiff( pDefaultParameters, pJson );\r\nnSize = JsonSize( pDiffer );\r\nWHILE( nSize > 0 );\r\n nSize = nSize - 1;\r\n pDiffer = JsonReplace( pDiffer, '/'|NumberToString( nSize )|'/op', '\"add\"' );\r\nEND;\r\npJson = JsonPatch( '{}', pDiffer );\r\n\r\n### LogOutput parameters\r\nsMessages = JsonAdd( sMessages, '/Info/-', pJson );\r\nIF( pLogOutput = 1 );\r\n LogOutput('INFO', JsonToString( sMessages, '/Info/0', 0, ' ' ) );\r\nENDIF;\r\n\r\n#EndRegion - Process Parameters\r\n#################################################################################################\r\n\r\n## check operating system\r\nIf( SubSt( GetProcessErrorFileDirectory, 2, 1 ) @= ':' );\r\n sOS = 'Windows';\r\n sOSDelim = '\\';\r\nElseIf( Scan( '/', GetProcessErrorFileDirectory ) > 0 );\r\n sOS = 'Linux';\r\n sOSDelim = '/';\r\nElse;\r\n sOS = 'Windows';\r\n sOSDelim = '\\';\r\nEndIf;\r\n\r\n### Validate Parameters ###\r\nnErrors = 0;\r\n# Validate cube\r\nIf( Trim( pCube ) @= '' );\r\n sMessage = 'No cube specified.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( CubeExists( pCube ) = 0 );\r\n sMessage = Expand( 'Cube %pCube% does not exist.' );\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Don't allow system cubes to be modified\r\nIf( SubSt( pCube, 1, 1 ) @= '}' & pCtrlObj <= 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'Do not modify system cubes: %pCube%.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate source dimension\r\nIf( Trim( pSrcDim ) @= '' );\r\n nErrors = nErrors + 1;\r\n sMessage = 'No source dimension specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( DimensionExists( pSrcDim ) = 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'Source dimension %pSrcDim% does not exist.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate target dimension\r\nIf( Trim( pTgtDim ) @= '' );\r\n nErrors = nErrors + 1;\r\n sMessage = 'No target dimension specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( DimensionExists( pTgtDim ) = 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'Target dimension %pTgtDim% does not exist.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Check that the source and target dimensions are different\r\nIf( pSrcDim @= pTgtDim );\r\n sMessage = Expand('Source and target dimensions are the same: %pSrcDim%');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# check element chosen in new dimension\r\nIf( pIncludeData = 1 & Trim(pEle)@='' );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'No element specified in new dimension %pTgtDim% to store cube data.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\nIf( pIncludeData = 1 & DIMIX(pTgtDim, pEle)=0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'Invalid element %pEle% specified for the new dimension %pTgtDim% to store cube data.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\nIF(pIncludeRules = 1 % pIncludeRules = 2);\r\n sRule=CubeRuleGet( pCube );\r\n If(sRule@= '');\r\n pIncludeRules = 0;\r\n LogOutput( 'INFO', Expand( 'No rule found for %pCube%.' ) );\r\n Endif;\r\nEndif; \r\n\r\n### Determine number of dims in source cube & create strings to check and recreate ###\r\nnCount = 1;\r\nsDimString = '';\r\nsDimCheck = '';\r\nsDelim = '+';\r\nWhile( TabDim( pCube, nCount ) @<> '' );\r\n sDim = TabDim( pCube, nCount );\r\n IF(sDim@=pSrcDim);\r\n sNewDim=pTgtDim;\r\n else;\r\n sNewDim=sDim;\r\n Endif; \r\n IF(nCount = 1);\r\n sDimCheck = '+'|sDim|'+';\r\n sDimString = sNewDim;\r\n elseif(nCount > 1);\r\n sDimCheck = sDimCheck|'+'|sDim|'+';\r\n sDimString = sDimString|'+'|sNewDim;\r\n Endif;\r\n nCount = nCount + 1;\r\nEnd;\r\nnDimensionCount = nCount - 1;\r\n\r\n#Remove any leading +\r\nIF( Subst( sDimString , 1 , 1 ) @= '+' );\r\n sDimString = Subst ( sDimString , 2 , 999 );\r\nEndIf;\r\n\r\n#check source dimension\r\nIF(scan('+'|pSrcDim|'+', sDimCheck)=0);\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'Source Dimension %pSrcDim% does not exist in %pCube%.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndif; \r\n\r\n#check target dimension\r\nIF(scan('+'|pTgtDim|'+', sDimCheck)>0);\r\n nErrors = nErrors + 1;\r\n sMessage = Expand( 'Target Dimension %pTgtDim% already exists in %pCube%.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndif;\r\n\r\n# Check if cube exceeds current max dimenions\r\nIf( nDimensionCount > 27 );\r\n sMessage = 'Process needs to be modified to handle cubes with more than 27 dimensions';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n###### CALLING THE STEP PROCESSES #####\r\n# Keep the rule\r\nIF(pIncludeRules = 1 % pIncludeRules = 2);\r\n sProc = '}bedrock.cube.rule.manage';\r\n\r\n nRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCube,\r\n 'pMode', 'UNLOAD'\r\n );\r\n \r\n IF(nRet <> 0);\r\n sMessage = 'Error unloading the rule for %pCube%.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf; \r\n ENDIF;\r\n \r\nEndif; \r\n\r\n# create clone cube with data\r\nIF(pIncludeData = 1);\r\n \r\n pCloneCube = pCube | '_Clone';\r\n nIncludeRules = IF(pIncludeRules = 1 % pIncludeRules = 2, 1, 0);\r\n nSuppressRules = IF(nIncludeRules = 1, 1, 0);\r\n \r\n sProc = '}bedrock.cube.clone';\r\n nRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pSrcCube', pCube,\r\n 'pTgtCube', pCloneCube,\r\n 'pIncludeRules', nIncludeRules,\r\n 'pIncludeData', pIncludeData,\r\n 'pSuppressRules', nSuppressRules,\r\n 'pTemp', pTemp,\r\n 'pCubeLogging', 0\r\n );\r\n\r\n IF(nRet <> 0);\r\n sMessage = 'Error creating cloned cube for keeping data.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n \r\nEndif;\r\n\r\n# recreate the cube\r\nsProc = '}bedrock.cube.create';\r\nnRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCube,\r\n 'pDims', sDimString,\r\n 'pRecreate', 1,\r\n 'pDelim', sDelim\r\n );\r\n\r\nIF(nRet <> 0);\r\n sMessage = Expand('Error recreating the cube: %pCube%.');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nENDIF;\r\n\r\n\r\n# copy back the data\r\nIF(pIncludeData = 1);\r\n sEleStartDelim = '\u00a6';\r\n sMappingToNewDims = pTgtDim|sEleStartDelim|pEle;\r\n \r\n nRet = ExecuteProcess('}bedrock.cube.data.copy.intercube',\r\n\t 'pLogOutput',pLogOutput,\r\n\t 'pStrictErrorHandling', pStrictErrorHandling,\r\n\t 'pSrcCube',pCloneCube,\r\n\t 'pFilter','',\r\n\t 'pTgtCube',pCube,\r\n\t 'pMappingToNewDims',sMappingToNewDims,\r\n 'pSuppressConsol', 1,\r\n 'pSuppressRules', nSuppressRules,\r\n\t 'pZeroTarget',0,\r\n\t 'pZeroSource',0,\r\n\t 'pFactor',1,\r\n\t 'pDimDelim','&',\r\n\t 'pEleStartDelim',sEleStartDelim,\r\n\t 'pEleDelim','+',\r\n\t 'pTemp',pTemp,\r\n\t 'pCubeLogging',0);\r\n \r\n IF(nRet <> 0);\r\n sMessage = Expand('Error copying back the data from clone cube: %pCloneCube%.');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n \r\n # destroy clone cube\r\n IF(pTemp=1);\r\n sProc = '}bedrock.cube.delete';\r\n nRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCloneCube,\r\n 'pCtrlObj', 0\r\n );\r\n\r\n IF(nRet <> 0);\r\n sMessage = Expand('Error deleting the clone cube: %pCloneCube%.');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n Endif;\r\n \r\nEndif; \r\n\r\n# reload the rule\r\nIF(pIncludeRules = 2);\r\n \r\n sProc = '}bedrock.cube.rule.manage';\r\n\r\n nRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCube,\r\n 'pMode', 'LOAD'\r\n );\r\n \r\n IF(nRet <> 0);\r\n sMessage = Expand('Error reloading the rule for %pCube%.');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n # Create error rule file \r\n cErrorRuleName = 'ErrorRuleFile.txt';\r\n\r\n IF(FileExists( cErrorRuleName ) = 0 );\r\n sFile = '.' | sOSDelim | cErrorRuleName;\r\n LogOutput(cMsgErrorLevel, 'Rule could not be attached due to invalid !Dimension references. Please recover from the backup and fix manually.');\r\n ENDIF;\r\n\r\n ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pCube', pCube,\r\n 'pFileName', cErrorRuleName,\r\n 'pMode', 'LOAD'\r\n );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n \r\nEndif; \r\n\r\n### End Prolog ###", "MetadataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "DataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "EpilogProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n### Return code & final error message handling\r\nIf( nErrors > 0 );\r\n sMessage = 'the process incurred at least 1 error. Please see above lines in this file for more details.';\r\n nProcessReturnCode = 0;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% Process:%cThisProcName% completed with errors. Check tm1server.log for details.' );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n EndIf;\r\nElse;\r\n sProcessAction = Expand( 'Process:%cThisProcName% successfully replaced the %pSrcDim% dimension with the %pTgtDim% in the %pCube% cube. Data was loaded to the %pEle% item.' );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% %sProcessAction%' );\r\n nProcessReturnCode = 1;\r\n If( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( sProcessAction ) ); \r\n EndIf;\r\nEndIf;\r\n \r\n### End Epilog ###", @@ -10,21 +10,9 @@ "Type": "None" }, "Parameters": [ - { - "Name": "pLogOutput", - "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, - { - "Name": "pStrictErrorHandling", - "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, { "Name": "pCube", - "Prompt": "REQUIRED: Cube", + "Prompt": "REQUIRED: Cube name", "Value": "", "Type": "String" }, @@ -42,33 +30,51 @@ }, { "Name": "pIncludeData", - "Prompt": "REQUIRED: If 1 then data is kept (copied through clone cube)", + "Prompt": "OPTIONAL: Include cube data (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" }, { "Name": "pEle", - "Prompt": "REQUIRED: If pIncludeData =1: Element in target dimension to load data to", + "Prompt": "OPTIONAL: Required if IncludeData flag =1. Element of new dimension where the existing data will be stored", "Value": "", "Type": "String" }, { "Name": "pIncludeRules", - "Prompt": "REQUIRED: Unload and reload the rule (0 = do not keep the rule, 1 = unload the rule, 2 = unload the rule and reload on new cube)", - "Value": 0, + "Prompt": "OPTIONAL: Include cube rules (Boolean. Default = 1)", + "Value": 1, "Type": "Numeric" }, { "Name": "pCtrlObj", - "Prompt": "REQUIRED: Allow overwrite control cubes", + "Prompt": "OPTIONAL: OPTIONAL: Allow modification of control objects (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" }, { "Name": "pTemp", - "Prompt": "REQUIRED: Delete the clone cube (1 = delete, 0 = not delete)", + "Prompt": "OPTIONAL: Delete/create temporary objects (0 = Do not delete, 1 = Delete, 2 = if view and subsets are created, keep only subsets)", "Value": 1, "Type": "Numeric" + }, + { + "Name": "pLogOutput", + "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pStrictErrorHandling", + "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pJson", + "Prompt": "OPTIONAL: JSON Object with process parameter values. This will overwrite user passed parameters for all included parameters.", + "Value": "{}", + "Type": "String" } ], "Variables": [], diff --git a/bedrock_processes_json/}bedrock.cube.rule.manage.json b/bedrock_processes_json/}bedrock.cube.rule.manage.json index 131ed33..1c2c22f 100644 --- a/bedrock_processes_json/}bedrock.cube.rule.manage.json +++ b/bedrock_processes_json/}bedrock.cube.rule.manage.json @@ -1,6 +1,6 @@ { "Name": "}bedrock.cube.rule.manage", - "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.rule.manage', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pCube', '', 'pMode', '',\r\n \t'pFileName', '', 'pDelim','&', \r\n \t'pPath', ''\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# ####################\r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process will backup & remove **OR** re-attach the rule file to cube.\r\n\r\n# Use case: Intended to be used in production.\r\n# 1/ Remove rule file before data load to speed up data load.\r\n# 2/ Re-attach rule file after data load.\r\n\r\n# Note:\r\n# Naturally, a valid cube name (pCube) is mandatory otherwise the process will abort.\r\n# The mandatory pMode parameter must be set to 'Unload' to remove/unload the rule file.\r\n# The pMode parameter must be set to 'Load' to re-attach the rule file and apply the rules.\r\n#EndRegion @DOC\r\n\r\n##Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n### Constants ###\r\n\r\ncThisProcName = GetProcessName();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSub = cThisProcName | '_' | cTimeStamp | '_' | cRandomInt;\r\ncCubeDim = '}Cubes';\r\ncCubeHier = cCubeDim;\r\nsPath = '';\r\ncUserName = TM1User();\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pCube:%pCube%, pMode:%pMode%, pFileName:%pFileName%, pDelim:%pDelim%, pPath:%pPath%.' ; \r\ncDimCubes = '}Cubes';\r\n\r\n### check operating system\r\nIf( SubSt( GetProcessErrorFileDirectory, 2, 1 ) @= ':' );\r\n sOS = 'Windows';\r\n sOSDelim = '\\';\r\nElseIf( Scan( '/', GetProcessErrorFileDirectory ) > 0 );\r\n sOS = 'Linux';\r\n sOSDelim = '/';\r\nElse;\r\n sOS = 'Windows';\r\n sOSDelim = '\\';\r\nEndIf;\r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\nnErrors = 0;\r\n\r\n### PROCESS PROPERTIES\r\nDatasourceASCIIDelimiter = '';\r\nDatasourceASCIIQuoteCharacter = '';\r\n\r\n##Validate Mode\r\nIf(upper(pMode) @<> 'LOAD' & upper(pMode) @<> 'UNLOAD');\r\n sMessage = Expand('Invalid Mode: %pMode%. Valid Modes are Load or Unload');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndif;\r\n\r\n##Validate Cube\r\nIf( Trim(pCube) @= '' );\r\n sMessage = Expand('No cube specified');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndif;\r\n\r\n## Default filter delimiters\r\nIf( pDelim @= '' );\r\n pDelim = '&';\r\nEndIf;\r\n\r\n# define backupdir\r\nIf(pPath @<> '');\r\n If(Subst(pPath,long(pPath),1) @= sOSDelim );\r\n sPath = pPath;\r\n Else;\r\n sPath = pPath | sOSDelim;\r\n Endif;\r\nElse;\r\n sPath = '.' | sOSDelim;\r\nEndif;\r\n\r\n## Default files names for storing rule and backups\r\nIF(pFileName@='' % Scan( pDelim, pCube )<>0);\r\n sRuleFileName = '%sCube%.txt';\r\n sBackupFileName = '%sCube%.rux.bkp_%cTimeStamp%.txt';\r\nElse;\r\n sRuleFileName = pFileName;\r\n sBackupFileName = '%pFileName%.bkp_%cTimeStamp%.txt';\r\nEndif; \r\n \r\n# Loop through list of Cubes\r\nsCubes = pCube;\r\nnCubeDelimIndex = 1;\r\n\r\nWhile( nCubeDelimIndex <> 0 );\r\n nCubeDelimIndex = Scan( pDelim, sCubes );\r\n If( nCubeDelimIndex = 0 );\r\n sCube = sCubes;\r\n Else;\r\n sCube = Trim( SubSt( sCubes, 1, nCubeDelimIndex - 1 ) );\r\n sCubes = Trim( Subst( sCubes, nCubeDelimIndex + Long(pDelim), Long( sCubes ) ) );\r\n EndIf;\r\n\r\n sMDX = Expand( '{TM1FILTERBYPATTERN(TM1SUBSETALL([}Cubes]), \"%sCube%\")}' );\r\n\r\n sProc = '}bedrock.hier.sub.create.bymdx';\r\n ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pDim', cDimCubes,\r\n 'pHier', '',\r\n 'pSub', cTempSub,\r\n 'pMDXExpr', sMDX,\r\n 'pConvertToStatic', 1,\r\n 'pTemp', 1\r\n );\r\n\r\n nCube = 1;\r\n nCubes = SubsetGetSize( cDimCubes, cTempSub );\r\n While( nCube <= nCubes );\r\n sCube = SubsetGetElementName( cDimCubes, cTempSub, nCube );\r\n nCube = nCube + 1;\r\n \r\n cCubeRuleFileName = '.' | sOSDelim | sCube | '.txt';\r\n cStoreDirFile = sPath | Expand(sRuleFileName);\r\n\r\n ##Unloading the Rule###\r\n If(Upper(pMode) @= 'UNLOAD');\r\n ##Before unloading, backup the existing rule (saved as .bkp.txt in data directory or with the suffix parameter)\r\n ##and drop current rule\r\n sRule=CubeRuleGet( sCube );\r\n ASCIIOutput(cStoreDirFile, sRule);\r\n ## Check if the saved rule file exists\r\n If( sRule@<>'' );\r\n CubeRuleDestroy( sCube );\r\n Else;\r\n sMessage = Expand('Copy of rule file (%cCubeRuleFileName%) has failed, rule was not unloaded.');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n EndIf;\r\n\r\n ##Loading the Rule###\r\n ElseIf(Upper(pMode) @= 'LOAD');\r\n ##Backup the existing rule (saved as .bkp.txt in given path or data directory) \r\n ##and load the new rule file. New Rule file should available in the given path or in data directory\r\n ## Check if the backup file exists\r\n If( FileExists( cCubeRuleFileName ) <> 0 );\r\n RuleLoadFromFile( sCube, cCubeRuleFileName);\r\n Else;\r\n nErrors = nErrors + 1;\r\n sMessage = 'No Rule file found for cube: ' | sCube;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n EndIf;\r\n\r\n Endif;\r\n End;\r\nEnd;\r\n\r\n### end Prolog ###", + "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.rule.manage', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pCube', '', 'pMode', '',\r\n \t'pFileName', '', 'pDelim','&', \r\n \t'pPath', ''\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# ####################\r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process will backup & remove **OR** re-attach the rule file to cube.\r\n\r\n# Use case: Intended to be used in production.\r\n# 1/ Remove rule file before data load to speed up data load.\r\n# 2/ Re-attach rule file after data load.\r\n\r\n# Note:\r\n# Naturally, a valid cube name (pCube) is mandatory otherwise the process will abort.\r\n# The mandatory pMode parameter must be set to 'Unload' to remove/unload the rule file.\r\n# The pMode parameter must be set to 'Load' to re-attach the rule file and apply the rules.\r\n#EndRegion @DOC\r\n\r\n##Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n### Constants ###\r\n\r\ncThisProcName = GetProcessName();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSub = cThisProcName | '_' | cTimeStamp | '_' | cRandomInt;\r\ncCubeDim = '}Cubes';\r\ncCubeHier = cCubeDim;\r\nsPath = '';\r\ncUserName = TM1User();\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pCube:%pCube%, pMode:%pMode%, pFileName:%pFileName%, pDelim:%pDelim%, pPath:%pPath%.' ; \r\ncDimCubes = '}Cubes';\r\n\r\n#################################################################################################\r\n#Region - Process Parameters\r\n\r\npJson = IF( JsonType( pJson ) @<> 'object', '{}', pJson );\r\nsMessages = '{\"Process\": \"'|GetProcessName()|'\", \"User\": \"'|TM1User()|'\", \"Info\": [\"Process: '''|GetProcessName()|''' run by User: '''|TM1User()|'''.\"], \"Error\": []}';\r\npDefaultParameters = '{\r\n \"pCube\": null,\r\n \"pDelim\": \"&\",\r\n \"pFileName\": \"\",\r\n \"pMode\": null,\r\n \"pPath\": \"\",\r\n \"pLogOutput\": 0,\r\n \"pStrictErrorHandling\": 0\r\n}';\r\n\r\npPassedParameters = '{\r\n \"pCube\": '|StringToJson ( pCube )|',\r\n \"pDelim\": '|StringToJson ( pDelim )|',\r\n \"pFileName\": '|StringToJson ( pFileName )|',\r\n \"pMode\": '|StringToJson ( pMode )|',\r\n \"pPath\": '|StringToJson ( pPath )|',\r\n \"pLogOutput\": '|NumberToString( pLogOutput )|',\r\n \"pStrictErrorHandling\": '|NumberToString( pStrictErrorHandling )|'\r\n}';\r\n\r\npJson = JsonMergePatch( pPassedParameters, pJson );\r\n# String Parameters\r\npCube = JsonToString( JsonGet( pJson, 'pCube' ) );\r\npDelim = JsonToString( JsonGet( pJson, 'pDelim' ) );\r\npFileName = JsonToString( JsonGet( pJson, 'pFileName' ) );\r\npMode = JsonToString( JsonGet( pJson, 'pMode' ) );\r\npPath = JsonToString( JsonGet( pJson, 'pPath' ) );\r\n# Numeric Parameters\r\npLogOutput = StringToNumber( JsonToString( JsonGet( pJson, 'pLogOutput' ) ) );\r\npStrictErrorHandling = StringToNumber( JsonToString( JsonGet( pJson, 'pStrictErrorHandling' ) ) );\r\n\r\n### Get the parameters that differ from the default\r\npDiffer = JsonDiff( pDefaultParameters, pJson );\r\nnSize = JsonSize( pDiffer );\r\nWHILE( nSize > 0 );\r\n nSize = nSize - 1;\r\n pDiffer = JsonReplace( pDiffer, '/'|NumberToString( nSize )|'/op', '\"add\"' );\r\nEND;\r\npJson = JsonPatch( '{}', pDiffer );\r\n\r\n### LogOutput parameters\r\nsMessages = JsonAdd( sMessages, '/Info/-', pJson );\r\nIF( pLogOutput = 1 );\r\n LogOutput('INFO', JsonToString( sMessages, '/Info/0', 0, ' ' ) );\r\nENDIF;\r\n\r\n#EndRegion - Process Parameters\r\n#################################################################################################\r\n\r\n### check operating system\r\nIf( SubSt( GetProcessErrorFileDirectory, 2, 1 ) @= ':' );\r\n sOS = 'Windows';\r\n sOSDelim = '\\';\r\nElseIf( Scan( '/', GetProcessErrorFileDirectory ) > 0 );\r\n sOS = 'Linux';\r\n sOSDelim = '/';\r\nElse;\r\n sOS = 'Windows';\r\n sOSDelim = '\\';\r\nEndIf;\r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\nnErrors = 0;\r\n\r\n### PROCESS PROPERTIES\r\nDatasourceASCIIDelimiter = '';\r\nDatasourceASCIIQuoteCharacter = '';\r\n\r\n##Validate Mode\r\nIf(upper(pMode) @<> 'LOAD' & upper(pMode) @<> 'UNLOAD');\r\n sMessage = Expand('Invalid Mode: %pMode%. Valid Modes are Load or Unload');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndif;\r\n\r\n##Validate Cube\r\nIf( Trim(pCube) @= '' );\r\n sMessage = Expand('No cube specified');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndif;\r\n\r\n## Default filter delimiters\r\nIf( pDelim @= '' );\r\n pDelim = '&';\r\nEndIf;\r\n\r\n# define backupdir\r\nIf(pPath @<> '');\r\n If(Subst(pPath,long(pPath),1) @= sOSDelim );\r\n sPath = pPath;\r\n Else;\r\n sPath = pPath | sOSDelim;\r\n Endif;\r\nElse;\r\n sPath = '.' | sOSDelim;\r\nEndif;\r\n\r\n## Default files names for storing rule and backups\r\nIF(pFileName@='' % Scan( pDelim, pCube )<>0);\r\n sRuleFileName = '%sCube%.txt';\r\n sBackupFileName = '%sCube%.rux.bkp_%cTimeStamp%.txt';\r\nElse;\r\n sRuleFileName = pFileName;\r\n sBackupFileName = '%pFileName%.bkp_%cTimeStamp%.txt';\r\nEndif; \r\n \r\n# Loop through list of Cubes\r\nsCubes = pCube;\r\nnCubeDelimIndex = 1;\r\n\r\nWhile( nCubeDelimIndex <> 0 );\r\n nCubeDelimIndex = Scan( pDelim, sCubes );\r\n If( nCubeDelimIndex = 0 );\r\n sCube = sCubes;\r\n Else;\r\n sCube = Trim( SubSt( sCubes, 1, nCubeDelimIndex - 1 ) );\r\n sCubes = Trim( Subst( sCubes, nCubeDelimIndex + Long(pDelim), Long( sCubes ) ) );\r\n EndIf;\r\n\r\n sMDX = Expand( '{TM1FILTERBYPATTERN(TM1SUBSETALL([}Cubes]), \"%sCube%\")}' );\r\n\r\n sProc = '}bedrock.hier.sub.create.bymdx';\r\n ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pDim', cDimCubes,\r\n 'pHier', '',\r\n 'pSub', cTempSub,\r\n 'pMDXExpr', sMDX,\r\n 'pConvertToStatic', 1,\r\n 'pTemp', 1\r\n );\r\n\r\n nCube = 1;\r\n nCubes = SubsetGetSize( cDimCubes, cTempSub );\r\n While( nCube <= nCubes );\r\n sCube = SubsetGetElementName( cDimCubes, cTempSub, nCube );\r\n nCube = nCube + 1;\r\n \r\n cCubeRuleFileName = '.' | sOSDelim | sCube | '.txt';\r\n cStoreDirFile = sPath | Expand(sRuleFileName);\r\n\r\n ##Unloading the Rule###\r\n If(Upper(pMode) @= 'UNLOAD');\r\n ##Before unloading, backup the existing rule (saved as .bkp.txt in data directory or with the suffix parameter)\r\n ##and drop current rule\r\n sRule=CubeRuleGet( sCube );\r\n ASCIIOutput(cStoreDirFile, sRule);\r\n ## Check if the saved rule file exists\r\n If( sRule@<>'' );\r\n CubeRuleDestroy( sCube );\r\n Else;\r\n sMessage = Expand('Copy of rule file (%cCubeRuleFileName%) has failed, rule was not unloaded.');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n EndIf;\r\n\r\n ##Loading the Rule###\r\n ElseIf(Upper(pMode) @= 'LOAD');\r\n ##Backup the existing rule (saved as .bkp.txt in given path or data directory) \r\n ##and load the new rule file. New Rule file should available in the given path or in data directory\r\n ## Check if the backup file exists\r\n If( FileExists( cCubeRuleFileName ) <> 0 );\r\n RuleLoadFromFile( sCube, cCubeRuleFileName);\r\n Else;\r\n nErrors = nErrors + 1;\r\n sMessage = 'No Rule file found for cube: ' | sCube;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n EndIf;\r\n\r\n Endif;\r\n End;\r\nEnd;\r\n\r\n### end Prolog ###", "MetadataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****", "DataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****", "EpilogProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# ####################\r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n### Return code & final error message handling\r\nIf( nErrors > 0 );\r\n sMessage = 'the process incurred at least 1 error. Please see above lines in this file for more details.';\r\n nProcessReturnCode = 0;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% Process:%cThisProcName% completed with errors. Check tm1server.log for details.' );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n EndIf;\r\nElse;\r\n sProcessAction = Expand( 'Process:%cThisProcName% successfully %pMode% cube rule from cube %pCube% .' );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% %sProcessAction%' );\r\n nProcessReturnCode = 1;\r\n If( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( sProcessAction ) ); \r\n EndIf;\r\nEndIf;\r\n\r\n### End Epilog ###", @@ -10,21 +10,9 @@ "Type": "None" }, "Parameters": [ - { - "Name": "pLogOutput", - "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, - { - "Name": "pStrictErrorHandling", - "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, { "Name": "pCube", - "Prompt": "REQUIRED: Cube Name to Load/Unload rule (Separated by Delimiter, Accepts Wild card)", + "Prompt": "REQUIRED: Cube name", "Value": "", "Type": "String" }, @@ -36,21 +24,39 @@ }, { "Name": "pFileName", - "Prompt": "OPTIONAL: Full file name for storing the rule (if empty = cube name.txt)", + "Prompt": "OPTIONAL: File name (Default = pCube | '_Export.csv')", "Value": "", "Type": "String" }, { "Name": "pDelim", - "Prompt": "OPTIONAL: Delimiter (default value if blank = '&')", + "Prompt": "OPTIONAL: Delimiter for list parameters (Default = '&')", "Value": "&", "Type": "String" }, { "Name": "pPath", - "Prompt": "OPTIONAL: Saves the file and the backup of the existing rule in this location. If Null, backup will be saved in Data Directory. Default value Null", + "Prompt": "OPTIONAL: File directory (Default = GetProcessErrorFileDirectory)", "Value": "", "Type": "String" + }, + { + "Name": "pLogOutput", + "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pStrictErrorHandling", + "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pJson", + "Prompt": "OPTIONAL: JSON Object with process parameter values. This will overwrite user passed parameters for all included parameters.", + "Value": "{}", + "Type": "String" } ], "Variables": [], diff --git a/bedrock_processes_json/}bedrock.cube.rule.processfeeders.json b/bedrock_processes_json/}bedrock.cube.rule.processfeeders.json index fd02d4b..d85f008 100644 --- a/bedrock_processes_json/}bedrock.cube.rule.processfeeders.json +++ b/bedrock_processes_json/}bedrock.cube.rule.processfeeders.json @@ -1,6 +1,6 @@ { "Name": "}bedrock.cube.rule.processfeeders", - "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.rule.processfeeders', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n\t 'pCube', '', 'pDelim', '&'\r\n );\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# ####################\r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process reprocesses feeders when consolidated totals are not adding up.\r\n\r\n# Use case: Intended for Deveopment or production.\r\n#1/ This process would be used any time feeders need to be reprocessed (e.g. when new elements are added to any of the dimensions).\r\n\r\n# Note:\r\n# Naturally, a valid cube name (pCube) is mandatory otherwise the process will abort. Wildcards and lists are acceptable.\r\n# This process will process feeders for a cube.\r\n#EndRegion @DOC\r\n\r\n##Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n### Constants ###\r\n\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSub = cThisProcName |'_'| cTimeStamp |'_'| cRandomInt;\r\nsMessage = \t'';\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pCube:%pCube%, pDelim:%pDelim%.' ; \r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\nnErrors = 0;\r\n\r\n### Validate Parameters ###\r\n# If blank delimiter specified then convert to default\r\nIf( pDelim @= '' );\r\n pDelim = '&';\r\nEndIf;\r\n\r\n# If no cubes have been specified then terminate process\r\nIf( Trim( pCube ) @= '' );\r\n sMessage = 'No cubes specified';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n\r\n### SET DATA SOURCE ###\r\n\r\nDatasourceType = 'NULL';\r\n\r\n\r\n### Split parameter into individual cubes and delete ###\r\n\r\nsCubes = pCube;\r\nnDelimiterIndex = 1;\r\nsMdx = '';\r\n\r\nWhile( nDelimiterIndex <> 0 );\r\n nDelimiterIndex = Scan( pDelim, sCubes );\r\n If( nDelimiterIndex = 0 );\r\n sCube = sCubes;\r\n Else;\r\n sCube = Trim( SubSt( sCubes, 1, nDelimiterIndex - 1 ) );\r\n sCubes = Trim( Subst( sCubes, nDelimiterIndex + Long(pDelim), Long( sCubes ) ) );\r\n EndIf;\r\n \r\n # Check if a wildcard has been used to specify the Cube name.\r\n # If it hasn't then just delete the Cube if it exists\r\n # If it has then search the relevant Cube folder to find the matches\r\n If( Scan( '*', sCube ) = 0 );\r\n If( CubeExists( sCube ) = 1 ); \r\n CubeProcessFeeders( sCube );\r\n Endif;\r\n Else;\r\n # Create subset of cubes using Wildcard\r\n sCubeExp = '\"'|sCube|'\"';\r\n sMdxPart = '{TM1FILTERBYPATTERN( TM1SUBSETALL( [}Cubes] ) ,'| sCubeExp | ')}';\r\n IF( sMdx @= ''); \r\n sMdx = sMdxPart; \r\n ELSE;\r\n sMdx = sMdx | ' + ' | sMdxPart;\r\n ENDIF;\r\n \r\n If( SubsetExists( '}Cubes' , cTempSub ) = 1 );\r\n # If a delimited list of cube names includes wildcards then we may have to re-use the subset multiple times\r\n SubsetMDXSet( '}Cubes' , cTempSub, sMDX );\r\n Else;\r\n # temp subset, therefore no need to destroy in epilog\r\n SubsetCreatebyMDX( cTempSub, sMDX, '}Cubes' , 1 );\r\n EndIf;\r\n \r\n # Loop through cubes in subset created based on wildcard\r\n nCountCubes = SubsetGetSize( '}Cubes' , cTempSub );\r\n While( nCountCubes >= 1 );\r\n sCurrCube = SubsetGetElementName( '}Cubes' , cTempSub, nCountCubes );\r\n # Validate cube name\r\n If( CubeExists( sCurrCube ) = 1 ); \r\n # Process Feeders\r\n CubeProcessFeeders( sCurrCube );\r\n Endif;\r\n nCountCubes = nCountCubes - 1;\r\n End;\r\n EndIf;\r\n\r\nEnd;\r\n\r\n", + "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.rule.processfeeders', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n\t 'pCube', '', 'pDelim', '&'\r\n );\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# ####################\r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process reprocesses feeders when consolidated totals are not adding up.\r\n\r\n# Use case: Intended for Deveopment or production.\r\n#1/ This process would be used any time feeders need to be reprocessed (e.g. when new elements are added to any of the dimensions).\r\n\r\n# Note:\r\n# Naturally, a valid cube name (pCube) is mandatory otherwise the process will abort. Wildcards and lists are acceptable.\r\n# This process will process feeders for a cube.\r\n#EndRegion @DOC\r\n\r\n##Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n### Constants ###\r\n\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSub = cThisProcName |'_'| cTimeStamp |'_'| cRandomInt;\r\nsMessage = \t'';\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pCube:%pCube%, pDelim:%pDelim%.' ; \r\n\r\n#################################################################################################\r\n#Region - Process Parameters\r\n\r\npJson = IF( JsonType( pJson ) @<> 'object', '{}', pJson );\r\nsMessages = '{\"Process\": \"'|GetProcessName()|'\", \"User\": \"'|TM1User()|'\", \"Info\": [\"Process: '''|GetProcessName()|''' run by User: '''|TM1User()|'''.\"], \"Error\": []}';\r\npDefaultParameters = '{\r\n \"pCube\": null,\r\n \"pDelim\": \"&\",\r\n \"pLogOutput\": 0,\r\n \"pStrictErrorHandling\": 0\r\n}';\r\n\r\npPassedParameters = '{\r\n \"pCube\": '|StringToJson ( pCube )|',\r\n \"pDelim\": '|StringToJson ( pDelim )|',\r\n \"pLogOutput\": '|NumberToString( pLogOutput )|',\r\n \"pStrictErrorHandling\": '|NumberToString( pStrictErrorHandling )|'\r\n}';\r\n\r\npJson = JsonMergePatch( pPassedParameters, pJson );\r\n# String Parameters\r\npCube = JsonToString( JsonGet( pJson, 'pCube' ) );\r\npDelim = JsonToString( JsonGet( pJson, 'pDelim' ) );\r\n# Numeric Parameters\r\npLogOutput = StringToNumber( JsonToString( JsonGet( pJson, 'pLogOutput' ) ) );\r\npStrictErrorHandling = StringToNumber( JsonToString( JsonGet( pJson, 'pStrictErrorHandling' ) ) );\r\n\r\n### Get the parameters that differ from the default\r\npDiffer = JsonDiff( pDefaultParameters, pJson );\r\nnSize = JsonSize( pDiffer );\r\nWHILE( nSize > 0 );\r\n nSize = nSize - 1;\r\n pDiffer = JsonReplace( pDiffer, '/'|NumberToString( nSize )|'/op', '\"add\"' );\r\nEND;\r\npJson = JsonPatch( '{}', pDiffer );\r\n\r\n### LogOutput parameters\r\nsMessages = JsonAdd( sMessages, '/Info/-', pJson );\r\nIF( pLogOutput = 1 );\r\n LogOutput('INFO', JsonToString( sMessages, '/Info/0', 0, ' ' ) );\r\nENDIF;\r\n\r\n#EndRegion - Process Parameters\r\n#################################################################################################\r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\nnErrors = 0;\r\n\r\n### Validate Parameters ###\r\n# If blank delimiter specified then convert to default\r\nIf( pDelim @= '' );\r\n pDelim = '&';\r\nEndIf;\r\n\r\n# If no cubes have been specified then terminate process\r\nIf( Trim( pCube ) @= '' );\r\n sMessage = 'No cubes specified';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n\r\n### SET DATA SOURCE ###\r\n\r\nDatasourceType = 'NULL';\r\n\r\n\r\n### Split parameter into individual cubes and delete ###\r\n\r\nsCubes = pCube;\r\nnDelimiterIndex = 1;\r\nsMdx = '';\r\n\r\nWhile( nDelimiterIndex <> 0 );\r\n nDelimiterIndex = Scan( pDelim, sCubes );\r\n If( nDelimiterIndex = 0 );\r\n sCube = sCubes;\r\n Else;\r\n sCube = Trim( SubSt( sCubes, 1, nDelimiterIndex - 1 ) );\r\n sCubes = Trim( Subst( sCubes, nDelimiterIndex + Long(pDelim), Long( sCubes ) ) );\r\n EndIf;\r\n \r\n # Check if a wildcard has been used to specify the Cube name.\r\n # If it hasn't then just delete the Cube if it exists\r\n # If it has then search the relevant Cube folder to find the matches\r\n If( Scan( '*', sCube ) = 0 );\r\n If( CubeExists( sCube ) = 1 ); \r\n CubeProcessFeeders( sCube );\r\n Endif;\r\n Else;\r\n # Create subset of cubes using Wildcard\r\n sCubeExp = '\"'|sCube|'\"';\r\n sMdxPart = '{TM1FILTERBYPATTERN( TM1SUBSETALL( [}Cubes] ) ,'| sCubeExp | ')}';\r\n IF( sMdx @= ''); \r\n sMdx = sMdxPart; \r\n ELSE;\r\n sMdx = sMdx | ' + ' | sMdxPart;\r\n ENDIF;\r\n \r\n If( SubsetExists( '}Cubes' , cTempSub ) = 1 );\r\n # If a delimited list of cube names includes wildcards then we may have to re-use the subset multiple times\r\n SubsetMDXSet( '}Cubes' , cTempSub, sMDX );\r\n Else;\r\n # temp subset, therefore no need to destroy in epilog\r\n SubsetCreatebyMDX( cTempSub, sMDX, '}Cubes' , 1 );\r\n EndIf;\r\n \r\n # Loop through cubes in subset created based on wildcard\r\n nCountCubes = SubsetGetSize( '}Cubes' , cTempSub );\r\n While( nCountCubes >= 1 );\r\n sCurrCube = SubsetGetElementName( '}Cubes' , cTempSub, nCountCubes );\r\n # Validate cube name\r\n If( CubeExists( sCurrCube ) = 1 ); \r\n # Process Feeders\r\n CubeProcessFeeders( sCurrCube );\r\n Endif;\r\n nCountCubes = nCountCubes - 1;\r\n End;\r\n EndIf;\r\n\r\nEnd;\r\n\r\n", "MetadataProcedure": "#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n", "DataProcedure": "#****Begin: Generated Statements***\r\n#****End: Generated Statements****", "EpilogProcedure": "#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n### Return code & final error message handling\r\nIf( nErrors > 0 );\r\n sMessage = 'the process incurred at least 1 error. Please see above lines in this file for more details.';\r\n nProcessReturnCode = 0;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% Process:%cThisProcName% completed with errors. Check tm1server.log for details.' );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n EndIf;\r\nElse;\r\n sProcessAction = Expand( 'Process:%cThisProcName% successfully processed feeders for cube %pCube% .' );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% %sProcessAction%' );\r\n nProcessReturnCode = 1;\r\n If( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( sProcessAction ) ); \r\n EndIf;\r\nEndIf;\r\n\r\n\r\n### End Epilog ###", @@ -10,28 +10,34 @@ "Type": "None" }, "Parameters": [ + { + "Name": "pCube", + "Prompt": "REQUIRED: Cube name", + "Value": "", + "Type": "String" + }, + { + "Name": "pDelim", + "Prompt": "OPTIONAL: Delimiter for list parameters (Default = '&')", + "Value": "&", + "Type": "String" + }, { "Name": "pLogOutput", - "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean True = 1)", + "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" }, { "Name": "pStrictErrorHandling", - "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean True = 1)", + "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" }, { - "Name": "pCube", - "Prompt": "REQUIRED: Process feeders for this cube (Separated by Delimiter, Accepts Wild card)", - "Value": "", - "Type": "String" - }, - { - "Name": "pDelim", - "Prompt": "OPTIONAL: Delimiter (default value if blank = '&')", - "Value": "&", + "Name": "pJson", + "Prompt": "OPTIONAL: JSON Object with process parameter values. This will overwrite user passed parameters for all included parameters.", + "Value": "{}", "Type": "String" } ], diff --git a/bedrock_processes_json/}bedrock.cube.view.create.bymdx.json b/bedrock_processes_json/}bedrock.cube.view.create.bymdx.json index b498687..d36865a 100644 --- a/bedrock_processes_json/}bedrock.cube.view.create.bymdx.json +++ b/bedrock_processes_json/}bedrock.cube.view.create.bymdx.json @@ -1,6 +1,6 @@ { "Name": "}bedrock.cube.view.create.bymdx", - "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.view.create.bymdx', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pCube', '', 'pView', '',\r\n \t'pMDXExpr', '',\r\n \t'pTemp', 1\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock Ver 4.0.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description: \r\n# This process will Create a dynamic view from an MDX expression that evaluates to a non-empty set in the specified dimension.\r\n\r\n# Use case: Intended for development/prototyping or production.\r\n# 1/ Create a view to zero out data.\r\n# 2/ Create a view to use as a source for exporting or copying.\r\n\r\n# Note:\r\n# Naturally, a valid cube name (pCube) is mandatory otherwise the process will abort.\r\n# If the MDX does not compile or produces an empty set the process will error.\r\n# pTemp: This parameter will control whether to make the view temporary (value 1) or if the\r\n# view will be permanently retained (value 0).\r\n#EndRegion @DOC\r\n\r\n##Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n### Constants ###\r\n\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSubset = cThisProcName | '_' | cTimeStamp | '_' | cRandomInt;\r\ncTempFile = GetProcessErrorFileDirectory | cTempSubset | '.csv';\r\nsMessage = \t'';\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pCube:%pCube%, pView:%pView%, pMDXExpr:%pMDXExpr%, pTemp:%pTemp%.' ; \r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\nsMDXExpr = TRIM( pMDXExpr );\r\n\r\n### Validate Parameters ###\r\nnErrors = 0;\r\n\r\n# Validate Cube\r\nIf( Trim( pCube ) @= '' );\r\n sMessage = 'No cube specified.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( CubeExists( pCube ) = 0 );\r\n sMessage = Expand('Cube %pCube% does not exist') ;\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate View\r\nIf( Trim( pView ) @= '' );\r\n sMessage = 'No view specified';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate MDX\r\nIf( Trim( sMDXExpr ) @= '' );\r\n sMessage = 'No MDX expression specified';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate MDX. Checking Cube name mentioned in MDX\r\nIf( SCAN ( pCube , sMDXExpr ) = 0 );\r\n sMessage = 'No Cube Name mentioned in MDX. Not a valid MDX expression';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n## Validate pTemp\r\nIF( pTemp<> 0 & pTemp<> 1 );\r\n nErrors = 1;\r\n sMessage = 'Invalid value for pTemp' | NumberToString( pTemp ) | '. Valid values are 0 and 1';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n### Create View ###\r\nIf( ViewExists( pCube , pView ) = 1 );\r\n ViewDestroy( pCube , pView );\r\nEndIf;\r\n\r\nViewCreatebyMDX ( pCube , pView , sMDXExpr, pTemp ) ; \r\n\r\n### End Prolog ###", + "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.view.create.bymdx', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pCube', '', 'pView', '',\r\n \t'pMDXExpr', '',\r\n \t'pTemp', 1\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock Ver 4.0.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description: \r\n# This process will Create a dynamic view from an MDX expression that evaluates to a non-empty set in the specified dimension.\r\n\r\n# Use case: Intended for development/prototyping or production.\r\n# 1/ Create a view to zero out data.\r\n# 2/ Create a view to use as a source for exporting or copying.\r\n\r\n# Note:\r\n# Naturally, a valid cube name (pCube) is mandatory otherwise the process will abort.\r\n# If the MDX does not compile or produces an empty set the process will error.\r\n# pTemp: This parameter will control whether to make the view temporary (value 1) or if the\r\n# view will be permanently retained (value 0).\r\n#EndRegion @DOC\r\n\r\n##Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n### Constants ###\r\n\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSubset = cThisProcName | '_' | cTimeStamp | '_' | cRandomInt;\r\ncTempFile = GetProcessErrorFileDirectory | cTempSubset | '.csv';\r\nsMessage = \t'';\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pCube:%pCube%, pView:%pView%, pMDXExpr:%pMDXExpr%, pTemp:%pTemp%.' ; \r\n\r\n#################################################################################################\r\n#Region - Process Parameters\r\n\r\npJson = IF( JsonType( pJson ) @<> 'object', '{}', pJson );\r\nsMessages = '{\"Process\": \"'|GetProcessName()|'\", \"User\": \"'|TM1User()|'\", \"Info\": [\"Process: '''|GetProcessName()|''' run by User: '''|TM1User()|'''.\"], \"Error\": []}';\r\npDefaultParameters = '{\r\n \"pCube\": null,\r\n \"pMDXExpr\": null,\r\n \"pView\": null,\r\n \"pLogOutput\": 0,\r\n \"pStrictErrorHandling\": 0,\r\n \"pTemp\": 1\r\n}';\r\n\r\npPassedParameters = '{\r\n \"pCube\": '|StringToJson ( pCube )|',\r\n \"pMDXExpr\": '|StringToJson ( pMDXExpr )|',\r\n \"pView\": '|StringToJson ( pView )|',\r\n \"pLogOutput\": '|NumberToString( pLogOutput )|',\r\n \"pStrictErrorHandling\": '|NumberToString( pStrictErrorHandling )|',\r\n \"pTemp\": '|NumberToString( pTemp )|'\r\n}';\r\n\r\npJson = JsonMergePatch( pPassedParameters, pJson );\r\n# String Parameters\r\npCube = JsonToString( JsonGet( pJson, 'pCube' ) );\r\npMDXExpr = JsonToString( JsonGet( pJson, 'pMDXExpr' ) );\r\npView = JsonToString( JsonGet( pJson, 'pView' ) );\r\n# Numeric Parameters\r\npLogOutput = StringToNumber( JsonToString( JsonGet( pJson, 'pLogOutput' ) ) );\r\npStrictErrorHandling = StringToNumber( JsonToString( JsonGet( pJson, 'pStrictErrorHandling' ) ) );\r\npTemp = StringToNumber( JsonToString( JsonGet( pJson, 'pTemp' ) ) );\r\n\r\n### Get the parameters that differ from the default\r\npDiffer = JsonDiff( pDefaultParameters, pJson );\r\nnSize = JsonSize( pDiffer );\r\nWHILE( nSize > 0 );\r\n nSize = nSize - 1;\r\n pDiffer = JsonReplace( pDiffer, '/'|NumberToString( nSize )|'/op', '\"add\"' );\r\nEND;\r\npJson = JsonPatch( '{}', pDiffer );\r\n\r\n### LogOutput parameters\r\nsMessages = JsonAdd( sMessages, '/Info/-', pJson );\r\nIF( pLogOutput = 1 );\r\n LogOutput('INFO', JsonToString( sMessages, '/Info/0', 0, ' ' ) );\r\nENDIF;\r\n\r\n#EndRegion - Process Parameters\r\n#################################################################################################\r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\nsMDXExpr = TRIM( pMDXExpr );\r\n\r\n### Validate Parameters ###\r\nnErrors = 0;\r\n\r\n# Validate Cube\r\nIf( Trim( pCube ) @= '' );\r\n sMessage = 'No cube specified.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( CubeExists( pCube ) = 0 );\r\n sMessage = Expand('Cube %pCube% does not exist') ;\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate View\r\nIf( Trim( pView ) @= '' );\r\n sMessage = 'No view specified';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate MDX\r\nIf( Trim( sMDXExpr ) @= '' );\r\n sMessage = 'No MDX expression specified';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate MDX. Checking Cube name mentioned in MDX\r\nIf( SCAN ( pCube , sMDXExpr ) = 0 );\r\n sMessage = 'No Cube Name mentioned in MDX. Not a valid MDX expression';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n## Validate pTemp\r\nIF( pTemp<> 0 & pTemp<> 1 );\r\n nErrors = 1;\r\n sMessage = 'Invalid value for pTemp' | NumberToString( pTemp ) | '. Valid values are 0 and 1';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n### Create View ###\r\nIf( ViewExists( pCube , pView ) = 1 );\r\n ViewDestroy( pCube , pView );\r\nEndIf;\r\n\r\nViewCreatebyMDX ( pCube , pView , sMDXExpr, pTemp ) ; \r\n\r\n### End Prolog ###", "MetadataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "DataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "EpilogProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n### Return code & final error message handling\r\nIf( nErrors > 0 );\r\n sMessage = 'the process incurred at least 1 error. Please see above lines in this file for more details.';\r\n nProcessReturnCode = 0;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% Process:%cThisProcName% completed with errors. Check tm1server.log for details.' );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n EndIf;\r\nElse;\r\n sProcessAction = Expand( 'Process:%cThisProcName% successfully created view %pView% in cube %pCube%.' );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% %sProcessAction%' );\r\n nProcessReturnCode = 1;\r\n If( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( sProcessAction ) ); \r\n EndIf;\r\nEndIf;\r\n\r\n### End Epilog ###", @@ -10,27 +10,15 @@ "Type": "None" }, "Parameters": [ - { - "Name": "pLogOutput", - "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, - { - "Name": "pStrictErrorHandling", - "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, { "Name": "pCube", - "Prompt": "REQUIRED: Cube Name", + "Prompt": "REQUIRED: Cube name", "Value": "", "Type": "String" }, { "Name": "pView", - "Prompt": "REQUIRED: View Name", + "Prompt": "REQUIRED: Name of the view", "Value": "", "Type": "String" }, @@ -42,9 +30,27 @@ }, { "Name": "pTemp", - "Prompt": "OPTIONAL: Make View Temporary (1=Temporary)", + "Prompt": "OPTIONAL: Delete/create temporary objects (0 = Do not delete, 1 = Delete, 2 = if view and subsets are created, keep only subsets)", "Value": 1, "Type": "Numeric" + }, + { + "Name": "pLogOutput", + "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pStrictErrorHandling", + "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pJson", + "Prompt": "OPTIONAL: JSON Object with process parameter values. This will overwrite user passed parameters for all included parameters.", + "Value": "{}", + "Type": "String" } ], "Variables": [], diff --git a/bedrock_processes_json/}bedrock.cube.view.create.json b/bedrock_processes_json/}bedrock.cube.view.create.json index c8b695a..2d1000b 100644 --- a/bedrock_processes_json/}bedrock.cube.view.create.json +++ b/bedrock_processes_json/}bedrock.cube.view.create.json @@ -1,6 +1,6 @@ { "Name": "}bedrock.cube.view.create", - "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.view.create', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pCube', '', 'pView', '', 'pFilter', '',\r\n \t'pSuppressZero', 1, 'pSuppressConsol', 1, 'pSuppressRules', 1, 'pSuppressConsolStrings', 1, 'pIncludeDescendants',0,\r\n \t'pDimDelim', '&', 'pEleStartDelim', '\u00a6', 'pEleDelim', '+',\r\n \t'pTemp', 1,'pSandbox', pSandbox,'pSubN', 0\r\n );\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***s\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock Ver 4.0.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process creates a view that can be used for exporting, copying or zeroing out numbers.\r\n\r\n# Use case: Intended for development/prototyping or production.\r\n# 1/ Create a view to zero out data.\r\n# 2/ Create a view to use as a source for exporting or copying.\r\n\r\n# Note:\r\n# Naturally, a valid cube name (pCube) is mandatory otherwise the process will abort.\r\n# The pFilter parameter contains the dimenson and elements to be used for filtering:\r\n# - The format of the pFilter parameter is as follows delimiters of :, & and +: Dim1: Elem1 + Elem2 & Dim2: Elem3 + Elem4.\r\n# - The dimension parameters do not need to be given in the index order of dimensions in the cube.\r\n# - The dimension name is specified as the first member of the delimited string of elements.\r\n# - If consols are skipped the N level children of any consolidated filter elements will be used.\r\n# - Spaces are ignored so use them to make your filter more readable.\r\n# - pTemp: This parameter will control whether to make the view temporary (value 1) or if the\r\n# view will be permanently retained (value 0).\r\n#EndRegion @DOC\r\n\r\n### Global Variables\r\nStringGlobalVariable ('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nStringGlobalVariable('sBedrockViewCreateParsedFilter');\r\nsProcessReturnCode = '';\r\nnProcessReturnCode = 0;\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSubset = cThisProcName | '_' | cTimeStamp | '_' | cRandomInt;\r\ncTempFile = GetProcessErrorFileDirectory | cTempSubset | '.csv';\r\nsMessage = '';\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncMsgInfoLevel = 'INFO';\r\ncMsgInfoContent = '%cThisProcName% : %sMessage% : %cUserName%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pCube:%pCube%, pView:%pView%, pFilter:%pFilter%, pSuppressZero:%pSuppressZero%, pSuppressConsol:%pSuppressConsol%, pSuppressRules:%pSuppressRules%, pDimDelim:%pDimDelim%, pEleStartDelim:%pEleStartDelim%, pEleDelim:%pEleDelim%, pTemp:%pTemp%, pSandbox:%pSandbox%, pSuppressConsolStrings:%pSuppressConsolStrings% pIncludeDescendants %pIncludeDescendants%.' ; \r\n\r\n\r\nsSubset = pView;\r\nsDelimDim = TRIM(pDimDelim);\r\nsElementStartDelim= TRIM(pEleStartDelim);\r\nsDelimElem = TRIM(pEleDelim);\r\n\r\n## LogOutput parameters\r\nIF ( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\nnErrors = 0;\r\n\r\n### Validate Parameters ###\r\n\r\n## Default filter delimiters\r\nIf( pDimDelim @= '' );\r\n pDimDelim = '&';\r\nEndIf;\r\nIf( pEleStartDelim@= '' );\r\n pEleStartDelim= '\u00a6';\r\nEndIf;\r\nIf( pEleDelim @= '' );\r\n pEleDelim = '+';\r\nEndIf;\r\n\r\n# If specified cube does not exist then terminate process\r\nIf( Trim( pCube ) @= '' );\r\n sMessage = 'A cube name must be provided.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( CubeExists( pCube ) = 0 );\r\n sMessage = 'Cube: ' | pCube | ' does not exist.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n## Validate the View parameter\r\nIf( Trim( pView ) @= '' );\r\n sMessage = 'A view name must be provided.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Check the delimiters\r\nIf( sDelimDim @= sElementStartDelim % sDelimDim @= sDelimElem % sElementStartDelim @= sDelimElem );\r\n sMessage = 'The delimiters cannot be the same';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n## Validate pTemp\r\nIF( pTemp<> 0 & pTemp<> 1 );\r\n nErrors = 1;\r\n sMessage = 'Invalid value for pTemp' | NumberToString( pTemp ) | '. Valid values are 0 and 1';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n### If errors occurred terminate process with a major error status ###\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n# Validate Sandbox\r\nIf( TRIM( pSandbox ) @<> '' );\r\n If( ServerSandboxExists( pSandbox ) = 0 );\r\n SetUseActiveSandboxProperty( 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand('Sandbox %pSandbox% is invalid for the current user.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n Else;\r\n ServerActiveSandboxSet( pSandbox );\r\n SetUseActiveSandboxProperty( 1 );\r\n EndIf;\r\nElse;\r\n SetUseActiveSandboxProperty( 0 );\r\nEndIf;\r\n \r\n# Reset all of the subsets that may be attached to the view in the case that dimensions not in the filter\r\nIf( ViewExists( pCube, pView ) = 1 );\r\n ### Reset View ###\r\n sMessage = 'Resetting view ' | pView | ' on cube ' | pCube;\r\n IF ( pLogoutput = 1 );\r\n LogOutput( cMsgInfoLevel, Expand( cMsgInfoContent ) );\r\n EndIf;\r\n nCount = 1;\r\n While( TabDim( pCube, nCount ) @<> '' );\r\n sCubeDimName = TabDim( pCube, nCount );\r\n # Subset is the same name as the view (no way to test if subset assigned, assume it is if same name)\r\n If( SubsetExists( sCubeDimName, sSubset ) = 1 );\r\n # Add all elements\r\n If( SubsetIsAllSet(sCubeDimName, sSubset, 1) <> 1 );\r\n sMessage = Expand('Unable to add all elements on subset %sSubset% in dimension %sCubeDimName%');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\n EndIf;\r\n nCount = nCount + 1;\r\n End;\r\nElse;\r\n ### Create View ###\r\n sMessage = Expand('Creating view %pView% in cube %pCube%');\r\n IF ( pLogoutput = 1 );\r\n LogOutput( cMsgInfoLevel, Expand( cMsgInfoContent ) );\r\n EndIf;\r\n ViewCreate( pCube, pView, pTemp );\r\nEndIf;\r\n\r\nViewExtractSkipCalcsSet( pCube, pView, pSuppressConsol );\r\nViewExtractSkipZeroesSet( pCube, pView, pSuppressZero );\r\nViewExtractSkipRuleValuesSet( pCube, pView, pSuppressRules );\r\n# Fix of issue #141, https://github.com/cubewise-code/bedrock/issues/141\r\nIf( pSuppressConsolStrings <> -1 );\r\n ViewExtractSkipConsolidatedStringsSet( pCube, pView, pSuppressConsolStrings );\r\nEndIf;\r\n\r\n### Split filter and create subsets ###\r\nsFilter = TRIM( pFilter );\r\nsParsedFilter = '';\r\nnChar = 1;\r\nnCharCount = LONG( sFilter );\r\nsWord = '';\r\nsLastDelim = '';\r\nnIndex = 1;\r\n# Add a trailing element delimiter so that the last element is picked up\r\nIf( nCharCount > 0 );\r\n sFilter = sFilter | sDelimElem;\r\n nCharCount = nCharCount + LONG(sDelimElem);\r\nEndIf;\r\n\r\nWHILE (nChar <= nCharCount);\r\n sChar = SUBST( sFilter, nChar, 1);\r\n\r\n # Used for delimiters, required for multiple character delimiters\r\n sDelim = '';\r\n nAddExtra = 0;\r\n\r\n # Ignore spaces\r\n IF (TRIM(sChar) @<> '' );\r\n\r\n ### Dimension Name ###\r\n\r\n # If the delimiter is more than 1 character peek ahead the same amount\r\n # Ignore the first character\r\n sDelim = sChar;\r\n nCount = LONG(sElementStartDelim) - 1;\r\n If( nCount > 0 & nChar + nCount <= nCharCount );\r\n # Add the extra characters\r\n sDelim = sDelim | SUBST( sFilter, nChar + 1, nCount);\r\n # Move to the end of the delimter\r\n nAddExtra = nCount;\r\n EndIf;\r\n\r\n If( sDelim @= sElementStartDelim );\r\n\r\n sChar = sDelim;\r\n\r\n If( sLastDelim @<> '' & sLastDelim @<> sDelimDim );\r\n sMessage = 'The name of a dimension must follow a dimension delimiter (' | sDelimDim | ')';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\n\r\n sDimension = sWord;\r\n nOneDimEleAdded = 0;\r\n \r\n If( DimensionExists( sDimension ) = 0 );\r\n # The dimension does not exist in the model. Cancel process\r\n sMessage = 'Dimension: ' | sDimension | ' does not exist';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\n\r\n ### Determine the dimension is a member of the cube ###\r\n nCount = 1;\r\n nDimensionIndex = 0;\r\n While( TabDim( pCube, nCount ) @<> '' );\r\n sCubeDimName = TabDim( pCube, nCount );\r\n If( sDimension @= sCubeDimName );\r\n nDimensionIndex = nCount;\r\n EndIf;\r\n nCount = nCount + 1;\r\n End;\r\n\r\n If( nDimensionIndex = 0 );\r\n # The dimension does not exist in the cube. Cancel process\r\n sMessage = 'Dimension: ' | sDimension | ' is not a member of: '| pCube | 'cube.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\n\r\n # Create the subset\r\n If( SubsetExists( sDimension, sSubset ) = 1 );\r\n SubsetDeleteAllElements( sDimension, sSubset );\r\n Else;\r\n SubsetCreate( sDimension, sSubset, pTemp ); \r\n EndIf;\r\n\r\n # Attach to the view\r\n ViewSubsetAssign( pCube, pView, sDimension, sSubset );\r\n \r\n #Add to the Parsed filter\r\n IF(sParsedFilter@='');\r\n sParsedFilter=sDimension; \r\n Else;\r\n sParsedFilter=sParsedFilter|sDelimDim|sDimension;\r\n Endif; \r\n\r\n nIndex = 1;\r\n sLastDelim = sChar;\r\n # Clear the word\r\n sWord = '';\r\n Else;\r\n\r\n # Reset extra chars\r\n nAddExtra = 0;\r\n\r\n ### Check both both dim delimiter and element delimiter ###\r\n nIsDelimiter = 0;\r\n\r\n ## Check dimension delimiter first\r\n # If the delimiter is more than 1 character peek ahead the same amount\r\n # Ignore the first character\r\n sDelim = sChar;\r\n nCount = LONG(sDelimDim) - 1;\r\n If( nCount > 0 & nChar + nCount <= nCharCount );\r\n # Add the extra characters\r\n sDelim = sDelim | SUBST( sFilter, nChar + 1, nCount);\r\n # Move to the end of the delimter\r\n nAddExtra = nCount;\r\n EndIf;\r\n\r\n If( sDelim @= sDelimDim );\r\n nIsDelimiter = 1;\r\n sChar = sDelim;\r\n Else;\r\n # Reset extra chars\r\n nAddExtra = 0;\r\n\r\n ## Check element delimiter\r\n\r\n # If the delimiter is more than 1 character peek ahead the same amount\r\n # Ignore the first character\r\n sDelim = sChar;\r\n nCount = LONG(sDelimElem) - 1;\r\n If( nCount > 0 & nChar + nCount <= nCharCount );\r\n # Add the extra characters\r\n sDelim = sDelim | SUBST( sFilter, nChar + 1, nCount);\r\n # Move to the end of the delimter\r\n nAddExtra = nCount;\r\n EndIf;\r\n\r\n If( sDelim @= sDelimElem );\r\n nIsDelimiter = 1;\r\n sChar = sDelim;\r\n Else;\r\n # Reset extra chars\r\n nAddExtra = 0;\r\n EndIf;\r\n\r\n EndIf;\r\n\r\n If ( nIsDelimiter = 1 );\r\n\r\n If( sLastDelim @= '' % sLastDelim @= sDelimDim );\r\n sMessage = 'An element delimiter must follow a dimension name: ' | sChar | ' (' | NumberToString(nChar) | ')';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n EndIf;\r\n\r\n sElement = sWord;\r\n\r\n If( DIMIX( sDimension, sElement ) = 0 );\r\n # The element does not exist in the dimension. Cancel process\r\n sMessage = 'Element: ' | sElement | ' in dimension ' | sDimension | ' does not exist';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n EndIf;\r\n \r\n sElement = DimensionElementPrincipalName(sDimension,sElement);\r\n\r\n If ( (pSuppressConsol = 1 % pIncludeDescendants=1) & DTYPE( sDimension, sElement) @= 'C' );\r\n # Add all N level elements to the subset\r\n # Loop through all elements and check if it is an ancestor\r\n sMessage = 'Element ' | sElement | ' is consolidated' ;\r\n IF ( pLogoutput = 1 );\r\n LogOutput( cMsgInfoLevel, Expand( cMsgInfoContent ) );\r\n EndIf;\r\n nElCount = DIMSIZ ( sDimension );\r\n n = 1;\r\n WHILE ( n <= nElCount );\r\n sEl = DIMNM( sDimension, n );\r\n If( ElIsAnc(sDimension, sElement, sEL) = 1 );\r\n If( pSuppressConsolStrings = 0 );\r\n SubsetElementInsert(sDimension, sSubset, sEl, 0);\r\n ElseIf( DType(sDimension, sEl) @<> 'C' );\r\n SubsetElementInsert(sDimension, sSubset, sEl, 0);\r\n EndIf;\r\n EndIf;\r\n n = n + 1;\r\n END;\r\n \r\n # Add the consolidated element to the subset as well to export strings, if necessary\r\n If ( pSuppressConsolStrings = 0 );\r\n SubsetElementInsert( sDimension, sSubset, sElement, 0 );\r\n EndIf;\r\n\r\n Else;\r\n # Add the element to the subset\r\n SubsetElementInsert( sDimension, sSubset, sElement, 0 );\r\n EndIf;\r\n \r\n #Add to the Parsed filter\r\n If( nOneDimEleAdded = 0 );\r\n sParsedFilter=sParsedFilter|pEleStartDelim|sElement;\r\n nOneDimEleAdded = nOneDimEleAdded + 1;\r\n Else;\r\n sParsedFilter=sParsedFilter|sDelimElem|sElement;\r\n EndIf;\r\n\r\n nIndex = nIndex + 1;\r\n sLastDelim = sChar;\r\n\r\n # Clear the word\r\n sWord = '';\r\n Else;\r\n sWord = sWord | sChar;\r\n EndIf;\r\n\r\n EndIf;\r\n\r\n EndIf;\r\n\r\n nChar = nChar + nAddExtra + 1;\r\n\r\nEND;\r\nsBedrockViewCreateParsedFilter = sParsedFilter;\r\n\r\n# creating N level subset for all dim not included in pFilter \r\n# useful when suppress consolidation is not on\r\nIf(pSubN = 1);\r\n \r\n nCountDimC = 1;\r\n While( TabDim( pCube, nCountDimC ) @<> '' );\r\n sDimC = TabDim( pCube, nCountDimC );\r\n sDimString = lower(sDimC);\r\n \r\n # filters created by other bedrock processes skip spaces from dim names and between separators\r\n While(Scan(' ',sDimString)>0);\r\n sDimString = subst(sDimString, 1, Scan(' ',sDimString)-1)|subst(sDimString,Scan(' ',sDimString)+1,long(sDimString));\r\n End; \r\n sTFilter = lower(sFilter);\r\n While(Scan(' ',sTFilter)>0);\r\n sTFilter = subst(sTFilter, 1, Scan(' ',sTFilter)-1)|subst(sTFilter,Scan(' ',sTFilter)+1,long(sTFilter));\r\n End;\r\n \r\n # to make sure that the name of the dim is not part of the name of another dim\r\n If(Scan(pDimDelim|sDimString|pEleStartDelim, sTFilter)=0 & Scan(sDimString|pEleStartDelim, sTFilter)<>1);\r\n sProc = '}bedrock.hier.sub.create';\r\n nRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pDim', sDimC,\r\n 'pHier', '',\r\n 'pSub', sSubset,\r\n 'pConsol', '',\r\n 'pAttr', '',\r\n 'pAttrValue', '',\r\n 'pLevelFrom', 0,\r\n 'pLevelTo', 0,\r\n 'pExclusions', '',\r\n 'pDelim', pEleDelim,\r\n 'pAddToSubset', 0,\r\n 'pAlias', '',\r\n 'pTemp', pTemp\r\n );\r\n \r\n IF(nRet <> 0);\r\n sMessage = 'Error creating the view from the filter.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n \r\n ViewSubsetAssign( pCube, pView, sDimC, sSubset );\r\n \r\n EndIf;\r\n \r\n nCountDimC = nCountDimC + 1;\r\n End;\r\n\r\n EndIf; \r\n### End Prolog ###", + "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.view.create', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pCube', '', 'pView', '', 'pFilter', '',\r\n \t'pSuppressZero', 1, 'pSuppressConsol', 1, 'pSuppressRules', 1, 'pSuppressConsolStrings', 1, 'pIncludeDescendants',0,\r\n \t'pDimDelim', '&', 'pEleStartDelim', '\u00a6', 'pEleDelim', '+',\r\n \t'pTemp', 1,'pSandbox', pSandbox,'pSubN', 0\r\n );\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***s\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock Ver 4.0.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process creates a view that can be used for exporting, copying or zeroing out numbers.\r\n\r\n# Use case: Intended for development/prototyping or production.\r\n# 1/ Create a view to zero out data.\r\n# 2/ Create a view to use as a source for exporting or copying.\r\n\r\n# Note:\r\n# Naturally, a valid cube name (pCube) is mandatory otherwise the process will abort.\r\n# The pFilter parameter contains the dimenson and elements to be used for filtering:\r\n# - The format of the pFilter parameter is as follows delimiters of :, & and +: Dim1: Elem1 + Elem2 & Dim2: Elem3 + Elem4.\r\n# - The dimension parameters do not need to be given in the index order of dimensions in the cube.\r\n# - The dimension name is specified as the first member of the delimited string of elements.\r\n# - If consols are skipped the N level children of any consolidated filter elements will be used.\r\n# - Spaces are ignored so use them to make your filter more readable.\r\n# - pTemp: This parameter will control whether to make the view temporary (value 1) or if the\r\n# view will be permanently retained (value 0).\r\n#EndRegion @DOC\r\n\r\n### Global Variables\r\nStringGlobalVariable ('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nStringGlobalVariable('sBedrockViewCreateParsedFilter');\r\nsProcessReturnCode = '';\r\nnProcessReturnCode = 0;\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSubset = cThisProcName | '_' | cTimeStamp | '_' | cRandomInt;\r\ncTempFile = GetProcessErrorFileDirectory | cTempSubset | '.csv';\r\nsMessage = '';\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncMsgInfoLevel = 'INFO';\r\ncMsgInfoContent = '%cThisProcName% : %sMessage% : %cUserName%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pCube:%pCube%, pView:%pView%, pFilter:%pFilter%, pSuppressZero:%pSuppressZero%, pSuppressConsol:%pSuppressConsol%, pSuppressRules:%pSuppressRules%, pDimDelim:%pDimDelim%, pEleStartDelim:%pEleStartDelim%, pEleDelim:%pEleDelim%, pTemp:%pTemp%, pSandbox:%pSandbox%, pSuppressConsolStrings:%pSuppressConsolStrings% pIncludeDescendants %pIncludeDescendants%.' ;\r\n\r\n\r\n#################################################################################################\r\n#Region - Process Parameters\r\n\r\npJson = IF( JsonType( pJson ) @<> 'object', '{}', pJson );\r\nsMessages = '{\"Process\": \"'|GetProcessName()|'\", \"User\": \"'|TM1User()|'\", \"Info\": [\"Process: '''|GetProcessName()|''' run by User: '''|TM1User()|'''.\"], \"Error\": []}';\r\npDefaultParameters = '{\r\n \"pCube\": null,\r\n \"pDimDelim\": \"&\",\r\n \"pEleDelim\": \"+\",\r\n \"pEleStartDelim\": \"\u00a6\",\r\n \"pFilter\": \"\",\r\n \"pSandBox\": \"\",\r\n \"pView\": null,\r\n \"pIncludeDescendants\": 0,\r\n \"pLogOutput\": 0,\r\n \"pStrictErrorHandling\": 0,\r\n \"pSubN\": 0,\r\n \"pSuppressConsol\": 1,\r\n \"pSuppressConsolStrings\": 1,\r\n \"pSuppressRules\": 1,\r\n \"pSuppressZero\": 1,\r\n \"pTemp\": 1\r\n}';\r\n\r\npPassedParameters = '{\r\n \"pCube\": '|StringToJson ( pCube )|',\r\n \"pDimDelim\": '|StringToJson ( pDimDelim )|',\r\n \"pEleDelim\": '|StringToJson ( pEleDelim )|',\r\n \"pEleStartDelim\": '|StringToJson ( pEleStartDelim )|',\r\n \"pFilter\": '|StringToJson ( pFilter )|',\r\n \"pSandBox\": '|StringToJson ( pSandBox )|',\r\n \"pView\": '|StringToJson ( pView )|',\r\n \"pIncludeDescendants\": '|NumberToString( pIncludeDescendants )|',\r\n \"pLogOutput\": '|NumberToString( pLogOutput )|',\r\n \"pStrictErrorHandling\": '|NumberToString( pStrictErrorHandling )|',\r\n \"pSubN\": '|NumberToString( pSubN )|',\r\n \"pSuppressConsol\": '|NumberToString( pSuppressConsol )|',\r\n \"pSuppressConsolStrings\": '|NumberToString( pSuppressConsolStrings )|',\r\n \"pSuppressRules\": '|NumberToString( pSuppressRules )|',\r\n \"pSuppressZero\": '|NumberToString( pSuppressZero )|',\r\n \"pTemp\": '|NumberToString( pTemp )|'\r\n}';\r\n\r\npJson = JsonMergePatch( pPassedParameters, pJson );\r\n# String Parameters\r\npCube = JsonToString( JsonGet( pJson, 'pCube' ) );\r\npDimDelim = JsonToString( JsonGet( pJson, 'pDimDelim' ) );\r\npEleDelim = JsonToString( JsonGet( pJson, 'pEleDelim' ) );\r\npEleStartDelim = JsonToString( JsonGet( pJson, 'pEleStartDelim' ) );\r\npFilter = JsonToString( JsonGet( pJson, 'pFilter' ) );\r\npSandBox = JsonToString( JsonGet( pJson, 'pSandBox' ) );\r\npView = JsonToString( JsonGet( pJson, 'pView' ) );\r\n# Numeric Parameters\r\npIncludeDescendants = StringToNumber( JsonToString( JsonGet( pJson, 'pIncludeDescendants' ) ) );\r\npLogOutput = StringToNumber( JsonToString( JsonGet( pJson, 'pLogOutput' ) ) );\r\npStrictErrorHandling = StringToNumber( JsonToString( JsonGet( pJson, 'pStrictErrorHandling' ) ) );\r\npSubN = StringToNumber( JsonToString( JsonGet( pJson, 'pSubN' ) ) );\r\npSuppressConsol = StringToNumber( JsonToString( JsonGet( pJson, 'pSuppressConsol' ) ) );\r\npSuppressConsolStrings = StringToNumber( JsonToString( JsonGet( pJson, 'pSuppressConsolStrings' ) ) );\r\npSuppressRules = StringToNumber( JsonToString( JsonGet( pJson, 'pSuppressRules' ) ) );\r\npSuppressZero = StringToNumber( JsonToString( JsonGet( pJson, 'pSuppressZero' ) ) );\r\npTemp = StringToNumber( JsonToString( JsonGet( pJson, 'pTemp' ) ) );\r\n\r\n### Get the parameters that differ from the default\r\npDiffer = JsonDiff( pDefaultParameters, pJson );\r\nnSize = JsonSize( pDiffer );\r\nWHILE( nSize > 0 );\r\n nSize = nSize - 1;\r\n pDiffer = JsonReplace( pDiffer, '/'|NumberToString( nSize )|'/op', '\"add\"' );\r\nEND;\r\npJson = JsonPatch( '{}', pDiffer );\r\n\r\n### LogOutput parameters\r\nsMessages = JsonAdd( sMessages, '/Info/-', pJson );\r\nIF( pLogOutput = 1 );\r\n LogOutput('INFO', JsonToString( sMessages, '/Info/0', 0, ' ' ) );\r\nENDIF;\r\n\r\n#EndRegion - Process Parameters\r\n#################################################################################################\r\n\r\nsSubset = pView;\r\nsDelimDim = TRIM(pDimDelim);\r\nsElementStartDelim= TRIM(pEleStartDelim);\r\nsDelimElem = TRIM(pEleDelim);\r\n\r\n## LogOutput parameters\r\nIF ( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\nnErrors = 0;\r\n\r\n### Validate Parameters ###\r\n\r\n## Default filter delimiters\r\nIf( pDimDelim @= '' );\r\n pDimDelim = '&';\r\nEndIf;\r\nIf( pEleStartDelim@= '' );\r\n pEleStartDelim= '\u00a6';\r\nEndIf;\r\nIf( pEleDelim @= '' );\r\n pEleDelim = '+';\r\nEndIf;\r\n\r\n# If specified cube does not exist then terminate process\r\nIf( Trim( pCube ) @= '' );\r\n sMessage = 'A cube name must be provided.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( CubeExists( pCube ) = 0 );\r\n sMessage = 'Cube: ' | pCube | ' does not exist.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n## Validate the View parameter\r\nIf( Trim( pView ) @= '' );\r\n sMessage = 'A view name must be provided.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Check the delimiters\r\nIf( sDelimDim @= sElementStartDelim % sDelimDim @= sDelimElem % sElementStartDelim @= sDelimElem );\r\n sMessage = 'The delimiters cannot be the same';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n## Validate pTemp\r\nIF( pTemp<> 0 & pTemp<> 1 );\r\n nErrors = 1;\r\n sMessage = 'Invalid value for pTemp' | NumberToString( pTemp ) | '. Valid values are 0 and 1';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n### If errors occurred terminate process with a major error status ###\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n# Validate Sandbox\r\nIf( TRIM( pSandbox ) @<> '' );\r\n If( ServerSandboxExists( pSandbox ) = 0 );\r\n SetUseActiveSandboxProperty( 0 );\r\n nErrors = nErrors + 1;\r\n sMessage = Expand('Sandbox %pSandbox% is invalid for the current user.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n Else;\r\n ServerActiveSandboxSet( pSandbox );\r\n SetUseActiveSandboxProperty( 1 );\r\n EndIf;\r\nElse;\r\n SetUseActiveSandboxProperty( 0 );\r\nEndIf;\r\n \r\n# Reset all of the subsets that may be attached to the view in the case that dimensions not in the filter\r\nIf( ViewExists( pCube, pView ) = 1 );\r\n ### Reset View ###\r\n sMessage = 'Resetting view ' | pView | ' on cube ' | pCube;\r\n IF ( pLogoutput = 1 );\r\n LogOutput( cMsgInfoLevel, Expand( cMsgInfoContent ) );\r\n EndIf;\r\n nCount = 1;\r\n While( TabDim( pCube, nCount ) @<> '' );\r\n sCubeDimName = TabDim( pCube, nCount );\r\n # Subset is the same name as the view (no way to test if subset assigned, assume it is if same name)\r\n If( SubsetExists( sCubeDimName, sSubset ) = 1 );\r\n # Add all elements\r\n If( SubsetIsAllSet(sCubeDimName, sSubset, 1) <> 1 );\r\n sMessage = Expand('Unable to add all elements on subset %sSubset% in dimension %sCubeDimName%');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\n EndIf;\r\n nCount = nCount + 1;\r\n End;\r\nElse;\r\n ### Create View ###\r\n sMessage = Expand('Creating view %pView% in cube %pCube%');\r\n IF ( pLogoutput = 1 );\r\n LogOutput( cMsgInfoLevel, Expand( cMsgInfoContent ) );\r\n EndIf;\r\n ViewCreate( pCube, pView, pTemp );\r\nEndIf;\r\n\r\nViewExtractSkipCalcsSet( pCube, pView, pSuppressConsol );\r\nViewExtractSkipZeroesSet( pCube, pView, pSuppressZero );\r\nViewExtractSkipRuleValuesSet( pCube, pView, pSuppressRules );\r\n# Fix of issue #141, https://github.com/cubewise-code/bedrock/issues/141\r\nIf( pSuppressConsolStrings <> -1 );\r\n ViewExtractSkipConsolidatedStringsSet( pCube, pView, pSuppressConsolStrings );\r\nEndIf;\r\n\r\n### Split filter and create subsets ###\r\nsFilter = TRIM( pFilter );\r\nsParsedFilter = '';\r\nnChar = 1;\r\nnCharCount = LONG( sFilter );\r\nsWord = '';\r\nsLastDelim = '';\r\nnIndex = 1;\r\n# Add a trailing element delimiter so that the last element is picked up\r\nIf( nCharCount > 0 );\r\n sFilter = sFilter | sDelimElem;\r\n nCharCount = nCharCount + LONG(sDelimElem);\r\nEndIf;\r\n\r\nWHILE (nChar <= nCharCount);\r\n sChar = SUBST( sFilter, nChar, 1);\r\n\r\n # Used for delimiters, required for multiple character delimiters\r\n sDelim = '';\r\n nAddExtra = 0;\r\n\r\n # Ignore spaces\r\n IF (TRIM(sChar) @<> '' );\r\n\r\n ### Dimension Name ###\r\n\r\n # If the delimiter is more than 1 character peek ahead the same amount\r\n # Ignore the first character\r\n sDelim = sChar;\r\n nCount = LONG(sElementStartDelim) - 1;\r\n If( nCount > 0 & nChar + nCount <= nCharCount );\r\n # Add the extra characters\r\n sDelim = sDelim | SUBST( sFilter, nChar + 1, nCount);\r\n # Move to the end of the delimter\r\n nAddExtra = nCount;\r\n EndIf;\r\n\r\n If( sDelim @= sElementStartDelim );\r\n\r\n sChar = sDelim;\r\n\r\n If( sLastDelim @<> '' & sLastDelim @<> sDelimDim );\r\n sMessage = 'The name of a dimension must follow a dimension delimiter (' | sDelimDim | ')';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\n\r\n sDimension = sWord;\r\n nOneDimEleAdded = 0;\r\n \r\n If( DimensionExists( sDimension ) = 0 );\r\n # The dimension does not exist in the model. Cancel process\r\n sMessage = 'Dimension: ' | sDimension | ' does not exist';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\n\r\n ### Determine the dimension is a member of the cube ###\r\n nCount = 1;\r\n nDimensionIndex = 0;\r\n While( TabDim( pCube, nCount ) @<> '' );\r\n sCubeDimName = TabDim( pCube, nCount );\r\n If( sDimension @= sCubeDimName );\r\n nDimensionIndex = nCount;\r\n EndIf;\r\n nCount = nCount + 1;\r\n End;\r\n\r\n If( nDimensionIndex = 0 );\r\n # The dimension does not exist in the cube. Cancel process\r\n sMessage = 'Dimension: ' | sDimension | ' is not a member of: '| pCube | 'cube.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\n\r\n # Create the subset\r\n If( SubsetExists( sDimension, sSubset ) = 1 );\r\n SubsetDeleteAllElements( sDimension, sSubset );\r\n Else;\r\n SubsetCreate( sDimension, sSubset, pTemp ); \r\n EndIf;\r\n\r\n # Attach to the view\r\n ViewSubsetAssign( pCube, pView, sDimension, sSubset );\r\n \r\n #Add to the Parsed filter\r\n IF(sParsedFilter@='');\r\n sParsedFilter=sDimension; \r\n Else;\r\n sParsedFilter=sParsedFilter|sDelimDim|sDimension;\r\n Endif; \r\n\r\n nIndex = 1;\r\n sLastDelim = sChar;\r\n # Clear the word\r\n sWord = '';\r\n Else;\r\n\r\n # Reset extra chars\r\n nAddExtra = 0;\r\n\r\n ### Check both both dim delimiter and element delimiter ###\r\n nIsDelimiter = 0;\r\n\r\n ## Check dimension delimiter first\r\n # If the delimiter is more than 1 character peek ahead the same amount\r\n # Ignore the first character\r\n sDelim = sChar;\r\n nCount = LONG(sDelimDim) - 1;\r\n If( nCount > 0 & nChar + nCount <= nCharCount );\r\n # Add the extra characters\r\n sDelim = sDelim | SUBST( sFilter, nChar + 1, nCount);\r\n # Move to the end of the delimter\r\n nAddExtra = nCount;\r\n EndIf;\r\n\r\n If( sDelim @= sDelimDim );\r\n nIsDelimiter = 1;\r\n sChar = sDelim;\r\n Else;\r\n # Reset extra chars\r\n nAddExtra = 0;\r\n\r\n ## Check element delimiter\r\n\r\n # If the delimiter is more than 1 character peek ahead the same amount\r\n # Ignore the first character\r\n sDelim = sChar;\r\n nCount = LONG(sDelimElem) - 1;\r\n If( nCount > 0 & nChar + nCount <= nCharCount );\r\n # Add the extra characters\r\n sDelim = sDelim | SUBST( sFilter, nChar + 1, nCount);\r\n # Move to the end of the delimter\r\n nAddExtra = nCount;\r\n EndIf;\r\n\r\n If( sDelim @= sDelimElem );\r\n nIsDelimiter = 1;\r\n sChar = sDelim;\r\n Else;\r\n # Reset extra chars\r\n nAddExtra = 0;\r\n EndIf;\r\n\r\n EndIf;\r\n\r\n If ( nIsDelimiter = 1 );\r\n\r\n If( sLastDelim @= '' % sLastDelim @= sDelimDim );\r\n sMessage = 'An element delimiter must follow a dimension name: ' | sChar | ' (' | NumberToString(nChar) | ')';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n EndIf;\r\n\r\n sElement = sWord;\r\n\r\n If( DIMIX( sDimension, sElement ) = 0 );\r\n # The element does not exist in the dimension. Cancel process\r\n sMessage = 'Element: ' | sElement | ' in dimension ' | sDimension | ' does not exist';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n #ProcessError();\r\n EndIf;\r\n \r\n sElement = DimensionElementPrincipalName(sDimension,sElement);\r\n\r\n If ( (pSuppressConsol = 1 % pIncludeDescendants=1) & DTYPE( sDimension, sElement) @= 'C' );\r\n # Add all N level elements to the subset\r\n # Loop through all elements and check if it is an ancestor\r\n sMessage = 'Element ' | sElement | ' is consolidated' ;\r\n IF ( pLogoutput = 1 );\r\n LogOutput( cMsgInfoLevel, Expand( cMsgInfoContent ) );\r\n EndIf;\r\n nElCount = DIMSIZ ( sDimension );\r\n n = 1;\r\n WHILE ( n <= nElCount );\r\n sEl = DIMNM( sDimension, n );\r\n If( ElIsAnc(sDimension, sElement, sEL) = 1 );\r\n If( pSuppressConsolStrings = 0 );\r\n SubsetElementInsert(sDimension, sSubset, sEl, 0);\r\n ElseIf( DType(sDimension, sEl) @<> 'C' );\r\n SubsetElementInsert(sDimension, sSubset, sEl, 0);\r\n EndIf;\r\n EndIf;\r\n n = n + 1;\r\n END;\r\n \r\n # Add the consolidated element to the subset as well to export strings, if necessary\r\n If ( pSuppressConsolStrings = 0 );\r\n SubsetElementInsert( sDimension, sSubset, sElement, 0 );\r\n EndIf;\r\n\r\n Else;\r\n # Add the element to the subset\r\n SubsetElementInsert( sDimension, sSubset, sElement, 0 );\r\n EndIf;\r\n \r\n #Add to the Parsed filter\r\n If( nOneDimEleAdded = 0 );\r\n sParsedFilter=sParsedFilter|pEleStartDelim|sElement;\r\n nOneDimEleAdded = nOneDimEleAdded + 1;\r\n Else;\r\n sParsedFilter=sParsedFilter|sDelimElem|sElement;\r\n EndIf;\r\n\r\n nIndex = nIndex + 1;\r\n sLastDelim = sChar;\r\n\r\n # Clear the word\r\n sWord = '';\r\n Else;\r\n sWord = sWord | sChar;\r\n EndIf;\r\n\r\n EndIf;\r\n\r\n EndIf;\r\n\r\n nChar = nChar + nAddExtra + 1;\r\n\r\nEND;\r\nsBedrockViewCreateParsedFilter = sParsedFilter;\r\n\r\n# creating N level subset for all dim not included in pFilter \r\n# useful when suppress consolidation is not on\r\nIf(pSubN = 1);\r\n \r\n nCountDimC = 1;\r\n While( TabDim( pCube, nCountDimC ) @<> '' );\r\n sDimC = TabDim( pCube, nCountDimC );\r\n sDimString = lower(sDimC);\r\n \r\n # filters created by other bedrock processes skip spaces from dim names and between separators\r\n While(Scan(' ',sDimString)>0);\r\n sDimString = subst(sDimString, 1, Scan(' ',sDimString)-1)|subst(sDimString,Scan(' ',sDimString)+1,long(sDimString));\r\n End; \r\n sTFilter = lower(sFilter);\r\n While(Scan(' ',sTFilter)>0);\r\n sTFilter = subst(sTFilter, 1, Scan(' ',sTFilter)-1)|subst(sTFilter,Scan(' ',sTFilter)+1,long(sTFilter));\r\n End;\r\n \r\n # to make sure that the name of the dim is not part of the name of another dim\r\n If(Scan(pDimDelim|sDimString|pEleStartDelim, sTFilter)=0 & Scan(sDimString|pEleStartDelim, sTFilter)<>1);\r\n sProc = '}bedrock.hier.sub.create';\r\n nRet = ExecuteProcess( sProc,\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pDim', sDimC,\r\n 'pHier', '',\r\n 'pSub', sSubset,\r\n 'pConsol', '',\r\n 'pAttr', '',\r\n 'pAttrValue', '',\r\n 'pLevelFrom', 0,\r\n 'pLevelTo', 0,\r\n 'pExclusions', '',\r\n 'pDelim', pEleDelim,\r\n 'pAddToSubset', 0,\r\n 'pAlias', '',\r\n 'pTemp', pTemp\r\n );\r\n \r\n IF(nRet <> 0);\r\n sMessage = 'Error creating the view from the filter.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n ENDIF;\r\n \r\n ViewSubsetAssign( pCube, pView, sDimC, sSubset );\r\n \r\n EndIf;\r\n \r\n nCountDimC = nCountDimC + 1;\r\n End;\r\n\r\n EndIf; \r\n### End Prolog ###", "MetadataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "DataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "EpilogProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n### Return code & final error message handling ###\r\nIf( nErrors <> 0 );\r\n sMessage = 'the process incurred at least 1 error. Please see above lines in this file for more details.';\r\n nProcessReturnCode = 0;\r\n LogOutput( 'ERROR' , Expand( cMsgErrorContent ) );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% Process:%cThisProcName% completed with errors. Check tm1server.log for details.' );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nElse; \r\n\r\n sProcessAction = Expand( 'Process:%cThisProcName% successfully created View %pView% in Cube %pCube%.' );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% %sProcessAction%' );\r\n nProcessReturnCode = 1;\r\n If( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( sProcessAction ) ); \r\n EndIf;\r\nEndIf;\r\n \r\n### End Epilog ###", @@ -10,101 +10,107 @@ "Type": "None" }, "Parameters": [ - { - "Name": "pLogOutput", - "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, - { - "Name": "pStrictErrorHandling", - "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, { "Name": "pCube", - "Prompt": "REQUIRED: Cube Name", + "Prompt": "REQUIRED: Cube name", "Value": "", "Type": "String" }, { "Name": "pView", - "Prompt": "REQUIRED: Name of the View", + "Prompt": "REQUIRED: Name of the view", "Value": "", "Type": "String" }, { "Name": "pFilter", - "Prompt": "OPTIONAL: Filter: Year\u00a6 2006 + 2007 & Scenario\u00a6 Actual + Budget & Organization\u00a6 North America Operations", + "Prompt": "OPTIONAL: Filter on cube in format: 'dim_one\u00a6 el_one + el_two & dim_two\u00a6 el_one + el_two'", "Value": "", "Type": "String" }, { "Name": "pSuppressZero", - "Prompt": "REQUIRED: Suppress Zero Data (Skip = 1)", + "Prompt": "OPTIONAL: Suppress zeroes (Boolean. Default = 1)", "Value": 1, "Type": "Numeric" }, { "Name": "pSuppressConsol", - "Prompt": "REQUIRED: Suppress Consolidations (Skip = 1)", + "Prompt": "OPTIONAL: Suppress consolidated values (Boolean. Default = 1)", "Value": 1, "Type": "Numeric" }, { "Name": "pSuppressRules", - "Prompt": "REQUIRED: Suppress Rules (Skip = 1)", + "Prompt": "OPTIONAL: Suppress rules (Boolean. Default = 1)", "Value": 1, "Type": "Numeric" }, { "Name": "pSuppressConsolStrings", - "Prompt": "REQUIRED: Suppress Strings on Consolidations (Skip = 1, Include = 0) (Default [Skip] = -1 for backward compatibility)", - "Value": -1, + "Prompt": "OPTIONAL: Suppress consolidated string cells (Boolean. Default = 1)", + "Value": 1, "Type": "Numeric" }, { "Name": "pIncludeDescendants", - "Prompt": "OPTIONAL: Include all descendants when copying consolidated values", + "Prompt": "OPTIONAL: Include all descendants when source has consolidations (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" }, { "Name": "pDimDelim", - "Prompt": "REQUIRED: Delimiter for start of Dimension/Element set", + "Prompt": "OPTIONAL: Delimiter for start of dimension/element set in filter parameters (Default = '&')", "Value": "&", "Type": "String" }, { "Name": "pEleStartDelim", - "Prompt": "REQUIRED: Delimiter for start of element list", + "Prompt": "OPTIONAL: Delimiter for start of element list in filter parameters (Default = '\u00a6')", "Value": "\u00a6", "Type": "String" }, { "Name": "pEleDelim", - "Prompt": "REQUIRED: Delimiter between elements", + "Prompt": "OPTIONAL: Delimiter between elements in filter parameters (Default = '+')", "Value": "+", "Type": "String" }, { "Name": "pTemp", - "Prompt": "OPTIONAL: Make View Temporary (1=Temporary)", + "Prompt": "OPTIONAL: Delete/create temporary objects (0 = Do not delete, 1 = Delete, 2 = if view and subsets are created, keep only subsets)", "Value": 1, "Type": "Numeric" }, { "Name": "pSandBox", - "Prompt": "OPTIONAL: To use sandbox not base data enter the sandbox name (invalid name will result in process error)", + "Prompt": "OPTIONAL: Use sandbox", "Value": "", "Type": "String" }, { "Name": "pSubN", - "Prompt": "OPTIONAL: Create N level subset for all dims not mentioned in pFilter", + "Prompt": "OPTIONAL: Create N level subset for all dims not specified (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pLogOutput", + "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pStrictErrorHandling", + "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" + }, + { + "Name": "pJson", + "Prompt": "OPTIONAL: JSON Object with process parameter values. This will overwrite user passed parameters for all included parameters.", + "Value": "{}", + "Type": "String" } ], "Variables": [], diff --git a/bedrock_processes_json/}bedrock.cube.view.delete.json b/bedrock_processes_json/}bedrock.cube.view.delete.json index ba5ad16..0153cd0 100644 --- a/bedrock_processes_json/}bedrock.cube.view.delete.json +++ b/bedrock_processes_json/}bedrock.cube.view.delete.json @@ -1,6 +1,6 @@ { "Name": "}bedrock.cube.view.delete", - "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.view.delete', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n\t 'pCube', '', 'pView', '', 'pDelim', '&'\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock Ver 4.0.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process deletes public views.\r\n\r\n# Use case: Intended for development/prototyping or production.\r\n# 1/ After a view has been created to zero or as a data source it needs to be deleted.\r\n# 2/ Clean up public views after Go Live.\r\n\r\n# Note:\r\n# This process can work on a single cubes or multiple cubes.\r\n# This process can work on a single view or multiple views.\r\n# When specifying view names wildcards can be included by using the * character. \r\n# **Parameter pCube**.\r\n# - To specify which cubes to delete views from use the pCubes parameter.\r\n# - To delete views from a single cube only just specify that cube name e.g. Sales.\r\n# - To delete views from multiple cubes specify each cube name separated by a delimiter e.g. Sales&Inventory&Cashflow.\r\n# - To delete views from all cubes then set pCubes as *.\r\n# - If any invalid cubes are specified they will be skipped but the process will continue to process the other cubes.\r\n# **Parameter pView**.\r\n# - To specify which views to delete use the pViews parameter.\r\n# - This parameter must be specified, a blank value will cause the process to terminate.\r\n# - To delete a single view only just specify that view name e.g. SalesByProduct.\r\n# - To delete multiple views specify each view name separated by a delimiter e.g. SalesByProduct&SalesByManager&SalesByStore.\r\n# - When specifying view names wildcards are permitted and all views that match the wildcard search string will be deleted.\r\n# - The wildcard search string follows the same format as windows based file wildcards.\r\n# - To delete all views that \"start\" with a specific string use a trailing * e.g. Bedrock*.\r\n# - To delete all views that \"end\" in a specific string use a leading * e.g. *Bedrock.\r\n# - To delete all views that \"contain\" a specific string use leading and trailing *'s e.g. *Bedrock*.\r\n# - To delete a single specific view only don't use *'s at all e.g. Bedrock.\r\n# - To specify multiple search stings list them all separated by a delimiter e.g. Bedrock*;*Temp;*Test*.\r\n# - Specific view names and wildcard based names can both be used together e.g. SalesByProduct;Bedrock*.\r\n# **Parameter pDelim**.\r\n# - The delimiter can be used when specifying multiple cubes and/or multiple views.\r\n# - The default delimiter is &.\r\n# - Any delimiter can be used by specifying a value for pDelimiter.\r\n# - Choose a delimiter that won't be used in either the wildcard search strings or cube names.\r\n#EndRegion @DOC\r\n\r\n\r\n##Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSubset = cThisProcName | '_' | cTimeStamp | '_' | cRandomInt;\r\ncTempFile = GetProcessErrorFileDirectory | cTempSubset | '.csv';\r\nsMessage = \t'';\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pCube:%pCube%, pView:%pView%, pDelim:%pDelim%.' ; \r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\nnErrors = 0;\r\ncDimension = '}Cubes';\r\n\r\n### Validate Parameters ###\r\nnErrors = 0;\r\n\r\n# Validate views\r\nIf( Trim( pView ) @= '' );\r\n sMessage = 'No views specified.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate delimiter\r\nIf( Trim( pDelim ) @= '' );\r\n pDelim = '&';\r\nEndIf;\r\n\r\n### Iterate through cubes ###\r\n\r\n# If no cube has been specified then process all cubes\r\nIf( Trim( pCube ) @= '' );\r\n sMessage = 'No cube specified.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors > 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n# Work through all cubes specified in pCube\r\nsCubes = pCube;\r\nnCubeDelimIndex = 1;\r\nsDelimiter = pDelim;\r\nsMdx = '';\r\nWhile( nCubeDelimIndex <> 0 );\r\n nCubeDelimIndex = Scan( sDelimiter, sCubes );\r\n If( nCubeDelimIndex = 0 );\r\n sCube = Trim( sCubes );\r\n Else;\r\n sCube = Trim( SubSt( sCubes, 1, nCubeDelimIndex - 1 ) );\r\n sCubes = Trim( SubSt( sCubes, nCubeDelimIndex + Long( sDelimiter ), Long( sCubes ) ) );\r\n EndIf;\r\n\r\n # Create subset of cubes using Wildcard to loop through cubes in pCube with wildcard\r\n sCubeExp = '\"'|sCube|'\"';\r\n sMdxPart = Expand('{TM1FILTERBYPATTERN( TM1SUBSETALL( [}Cubes] ), %sCubeExp% )}');\r\n IF( sMdx @= ''); \r\n sMdx = sMdxPart; \r\n ELSE;\r\n sMdx = sMdx | ' + ' | sMdxPart;\r\n ENDIF;\r\nEnd;\r\n \r\nIf( SubsetExists( '}Cubes' , cTempSubset ) = 1 );\r\n # If a delimited list of cube names includes wildcards then we may have to re-use the subset multiple times\r\n SubsetMDXSet( '}Cubes' , cTempSubset, sMDX );\r\nElse;\r\n # temp subset, therefore no need to destroy in epilog\r\n SubsetCreatebyMDX( cTempSubset, sMDX, '}Cubes' , 1 );\r\nEndIf;\r\n \r\n \r\n # Loop through cubess in subset created based on wildcard\r\n nCountCubes = SubsetGetSize( '}Cubes' , cTempSubset );\r\n While( nCountCubes >= 1 );\r\n sCurrentCube = SubsetGetElementName( '}Cubes' , cTempSubset, nCountCubes );\r\n # If a valid cube has been specified then delete specified views from it\r\n If( CubeExists( sCurrentCube ) = 1 );\r\n If( pLogOutput = 1 );\r\n LogOutput( 'INFO', Expand( 'Processing cube %sCurrentCube%.' ) );\r\n EndIf;\r\n # Work through all views specified in pViews\r\n sViews = pView;\r\n nViewDelimIndex = 1;\r\n sMdxView = '';\r\n \r\n While( nViewDelimIndex <> 0 );\r\n nViewDelimIndex = Scan( sDelimiter, sViews );\r\n If( nViewDelimIndex = 0 );\r\n sView = Trim( sViews );\r\n Else;\r\n sView = Trim( SubSt( sViews, 1, nViewDelimIndex - 1 ) );\r\n sViews = Trim( SubSt( sViews, nViewDelimIndex + Long( sDelimiter ), Long( sViews ) ) );\r\n EndIf;\r\n \r\n # Check if a wildcard has been used to specify the view name.\r\n # If it hasn't then just delete the view if it exists\r\n If( Scan( '*', sView ) = 0 );\r\n If( ViewExists( sCurrentCube, sView ) = 1 );\r\n If( pLogOutput = 1 );\r\n LogOutput( 'INFO', Expand( ' Destroying view %sView% in cube %sCurrentCube%.' ) );\r\n EndIf;\r\n ViewDestroy( sCurrentCube, sView );\r\n EndIf;\r\n # If it has then iterate through '}Views_CubeName' dimension\r\n Else;\r\n sDimViews = '}Views_' | sCurrentCube ;\r\n If( DimensionExists( sDimViews ) = 1 );\r\n # Create subset of views using Wildcard to loop through views in current cube\r\n sViewExp = '\"'|sView|'\"';\r\n sMdxViewPart = Expand('{TM1FILTERBYPATTERN( {TM1SUBSETALL([%sDimViews%])}, %sViewExp% )}');\r\n IF( sMdxView @= ''); \r\n sMdxview = sMdxViewPart; \r\n ELSE;\r\n sMdxView = sMdxView | ' + ' | sMdxViewPart;\r\n ENDIF;\r\n If( SubsetExists( sDimViews, cTempSubset ) = 1 );\r\n # If a delimited list of attr names includes wildcards then we may have to re-use the subset multiple times\r\n SubsetMDXSet( sDimViews, cTempSubset, sMdxView );\r\n Else;\r\n # temp subset, therefore no need to destroy in epilog\r\n SubsetCreatebyMDX( cTempSubset, sMdxView, sDimViews, 1 );\r\n EndIf;\r\n \r\n # Loop through subset of views created based on wildcard\r\n nCountView = SubsetGetSize( sDimViews, cTempSubset );\r\n While( nCountView >= 1 );\r\n sViewEle = SubsetGetElementName( sDimViews, cTempSubset, nCountView );\r\n # Validate attribute name in sDim\r\n If( ViewExists( sCurrentCube, sViewEle ) = 1 );\r\n If( pLogOutput = 1 );\r\n LogOutput( 'INFO', Expand( 'Destroying view %sViewEle% in cube %sCurrentCube%.' ) );\r\n EndIf;\r\n ViewDestroy( sCurrentCube, sViewEle );\r\n Endif;\r\n nCountView = nCountView - 1;\r\n End;\r\n EndIf;\r\n EndIf;\r\n \r\n End;\r\n \r\n # Cube does not exist\r\n Else;\r\n sMessage = Expand('Cube %sCurrentCube% does not exist.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\n \r\n nCountCubes = nCountCubes - 1;\r\n End;\r\n\r\n### End Prolog ###", + "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.view.delete', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n\t 'pCube', '', 'pView', '', 'pDelim', '&'\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock Ver 4.0.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process deletes public views.\r\n\r\n# Use case: Intended for development/prototyping or production.\r\n# 1/ After a view has been created to zero or as a data source it needs to be deleted.\r\n# 2/ Clean up public views after Go Live.\r\n\r\n# Note:\r\n# This process can work on a single cubes or multiple cubes.\r\n# This process can work on a single view or multiple views.\r\n# When specifying view names wildcards can be included by using the * character. \r\n# **Parameter pCube**.\r\n# - To specify which cubes to delete views from use the pCubes parameter.\r\n# - To delete views from a single cube only just specify that cube name e.g. Sales.\r\n# - To delete views from multiple cubes specify each cube name separated by a delimiter e.g. Sales&Inventory&Cashflow.\r\n# - To delete views from all cubes then set pCubes as *.\r\n# - If any invalid cubes are specified they will be skipped but the process will continue to process the other cubes.\r\n# **Parameter pView**.\r\n# - To specify which views to delete use the pViews parameter.\r\n# - This parameter must be specified, a blank value will cause the process to terminate.\r\n# - To delete a single view only just specify that view name e.g. SalesByProduct.\r\n# - To delete multiple views specify each view name separated by a delimiter e.g. SalesByProduct&SalesByManager&SalesByStore.\r\n# - When specifying view names wildcards are permitted and all views that match the wildcard search string will be deleted.\r\n# - The wildcard search string follows the same format as windows based file wildcards.\r\n# - To delete all views that \"start\" with a specific string use a trailing * e.g. Bedrock*.\r\n# - To delete all views that \"end\" in a specific string use a leading * e.g. *Bedrock.\r\n# - To delete all views that \"contain\" a specific string use leading and trailing *'s e.g. *Bedrock*.\r\n# - To delete a single specific view only don't use *'s at all e.g. Bedrock.\r\n# - To specify multiple search stings list them all separated by a delimiter e.g. Bedrock*;*Temp;*Test*.\r\n# - Specific view names and wildcard based names can both be used together e.g. SalesByProduct;Bedrock*.\r\n# **Parameter pDelim**.\r\n# - The delimiter can be used when specifying multiple cubes and/or multiple views.\r\n# - The default delimiter is &.\r\n# - Any delimiter can be used by specifying a value for pDelimiter.\r\n# - Choose a delimiter that won't be used in either the wildcard search strings or cube names.\r\n#EndRegion @DOC\r\n\r\n\r\n##Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSubset = cThisProcName | '_' | cTimeStamp | '_' | cRandomInt;\r\ncTempFile = GetProcessErrorFileDirectory | cTempSubset | '.csv';\r\nsMessage = \t'';\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pCube:%pCube%, pView:%pView%, pDelim:%pDelim%.' ;\r\n\r\n#################################################################################################\r\n#Region - Process Parameters\r\n\r\npJson = IF( JsonType( pJson ) @<> 'object', '{}', pJson );\r\nsMessages = '{\"Process\": \"'|GetProcessName()|'\", \"User\": \"'|TM1User()|'\", \"Info\": [\"Process: '''|GetProcessName()|''' run by User: '''|TM1User()|'''.\"], \"Error\": []}';\r\npDefaultParameters = '{\r\n \"pCube\": null,\r\n \"pDelim\": \"&\",\r\n \"pView\": null,\r\n \"pLogOutput\": 0,\r\n \"pStrictErrorHandling\": 0\r\n}';\r\n\r\npPassedParameters = '{\r\n \"pCube\": '|StringToJson ( pCube )|',\r\n \"pDelim\": '|StringToJson ( pDelim )|',\r\n \"pView\": '|StringToJson ( pView )|',\r\n \"pLogOutput\": '|NumberToString( pLogOutput )|',\r\n \"pStrictErrorHandling\": '|NumberToString( pStrictErrorHandling )|'\r\n}';\r\n\r\npJson = JsonMergePatch( pPassedParameters, pJson );\r\n# String Parameters\r\npCube = JsonToString( JsonGet( pJson, 'pCube' ) );\r\npDelim = JsonToString( JsonGet( pJson, 'pDelim' ) );\r\npView = JsonToString( JsonGet( pJson, 'pView' ) );\r\n# Numeric Parameters\r\npLogOutput = StringToNumber( JsonToString( JsonGet( pJson, 'pLogOutput' ) ) );\r\npStrictErrorHandling = StringToNumber( JsonToString( JsonGet( pJson, 'pStrictErrorHandling' ) ) );\r\n\r\n### Get the parameters that differ from the default\r\npDiffer = JsonDiff( pDefaultParameters, pJson );\r\nnSize = JsonSize( pDiffer );\r\nWHILE( nSize > 0 );\r\n nSize = nSize - 1;\r\n pDiffer = JsonReplace( pDiffer, '/'|NumberToString( nSize )|'/op', '\"add\"' );\r\nEND;\r\npJson = JsonPatch( '{}', pDiffer );\r\n\r\n### LogOutput parameters\r\nsMessages = JsonAdd( sMessages, '/Info/-', pJson );\r\nIF( pLogOutput = 1 );\r\n LogOutput('INFO', JsonToString( sMessages, '/Info/0', 0, ' ' ) );\r\nENDIF;\r\n\r\n#EndRegion - Process Parameters\r\n#################################################################################################\r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\nnErrors = 0;\r\ncDimension = '}Cubes';\r\n\r\n### Validate Parameters ###\r\nnErrors = 0;\r\n\r\n# Validate views\r\nIf( Trim( pView ) @= '' );\r\n sMessage = 'No views specified.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate delimiter\r\nIf( Trim( pDelim ) @= '' );\r\n pDelim = '&';\r\nEndIf;\r\n\r\n### Iterate through cubes ###\r\n\r\n# If no cube has been specified then process all cubes\r\nIf( Trim( pCube ) @= '' );\r\n sMessage = 'No cube specified.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors > 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n# Work through all cubes specified in pCube\r\nsCubes = pCube;\r\nnCubeDelimIndex = 1;\r\nsDelimiter = pDelim;\r\nsMdx = '';\r\nWhile( nCubeDelimIndex <> 0 );\r\n nCubeDelimIndex = Scan( sDelimiter, sCubes );\r\n If( nCubeDelimIndex = 0 );\r\n sCube = Trim( sCubes );\r\n Else;\r\n sCube = Trim( SubSt( sCubes, 1, nCubeDelimIndex - 1 ) );\r\n sCubes = Trim( SubSt( sCubes, nCubeDelimIndex + Long( sDelimiter ), Long( sCubes ) ) );\r\n EndIf;\r\n\r\n # Create subset of cubes using Wildcard to loop through cubes in pCube with wildcard\r\n sCubeExp = '\"'|sCube|'\"';\r\n sMdxPart = Expand('{TM1FILTERBYPATTERN( TM1SUBSETALL( [}Cubes] ), %sCubeExp% )}');\r\n IF( sMdx @= ''); \r\n sMdx = sMdxPart; \r\n ELSE;\r\n sMdx = sMdx | ' + ' | sMdxPart;\r\n ENDIF;\r\nEnd;\r\n \r\nIf( SubsetExists( '}Cubes' , cTempSubset ) = 1 );\r\n # If a delimited list of cube names includes wildcards then we may have to re-use the subset multiple times\r\n SubsetMDXSet( '}Cubes' , cTempSubset, sMDX );\r\nElse;\r\n # temp subset, therefore no need to destroy in epilog\r\n SubsetCreatebyMDX( cTempSubset, sMDX, '}Cubes' , 1 );\r\nEndIf;\r\n \r\n \r\n # Loop through cubess in subset created based on wildcard\r\n nCountCubes = SubsetGetSize( '}Cubes' , cTempSubset );\r\n While( nCountCubes >= 1 );\r\n sCurrentCube = SubsetGetElementName( '}Cubes' , cTempSubset, nCountCubes );\r\n # If a valid cube has been specified then delete specified views from it\r\n If( CubeExists( sCurrentCube ) = 1 );\r\n If( pLogOutput = 1 );\r\n LogOutput( 'INFO', Expand( 'Processing cube %sCurrentCube%.' ) );\r\n EndIf;\r\n # Work through all views specified in pViews\r\n sViews = pView;\r\n nViewDelimIndex = 1;\r\n sMdxView = '';\r\n \r\n While( nViewDelimIndex <> 0 );\r\n nViewDelimIndex = Scan( sDelimiter, sViews );\r\n If( nViewDelimIndex = 0 );\r\n sView = Trim( sViews );\r\n Else;\r\n sView = Trim( SubSt( sViews, 1, nViewDelimIndex - 1 ) );\r\n sViews = Trim( SubSt( sViews, nViewDelimIndex + Long( sDelimiter ), Long( sViews ) ) );\r\n EndIf;\r\n \r\n # Check if a wildcard has been used to specify the view name.\r\n # If it hasn't then just delete the view if it exists\r\n If( Scan( '*', sView ) = 0 );\r\n If( ViewExists( sCurrentCube, sView ) = 1 );\r\n If( pLogOutput = 1 );\r\n LogOutput( 'INFO', Expand( ' Destroying view %sView% in cube %sCurrentCube%.' ) );\r\n EndIf;\r\n ViewDestroy( sCurrentCube, sView );\r\n EndIf;\r\n # If it has then iterate through '}Views_CubeName' dimension\r\n Else;\r\n sDimViews = '}Views_' | sCurrentCube ;\r\n If( DimensionExists( sDimViews ) = 1 );\r\n # Create subset of views using Wildcard to loop through views in current cube\r\n sViewExp = '\"'|sView|'\"';\r\n sMdxViewPart = Expand('{TM1FILTERBYPATTERN( {TM1SUBSETALL([%sDimViews%])}, %sViewExp% )}');\r\n IF( sMdxView @= ''); \r\n sMdxview = sMdxViewPart; \r\n ELSE;\r\n sMdxView = sMdxView | ' + ' | sMdxViewPart;\r\n ENDIF;\r\n If( SubsetExists( sDimViews, cTempSubset ) = 1 );\r\n # If a delimited list of attr names includes wildcards then we may have to re-use the subset multiple times\r\n SubsetMDXSet( sDimViews, cTempSubset, sMdxView );\r\n Else;\r\n # temp subset, therefore no need to destroy in epilog\r\n SubsetCreatebyMDX( cTempSubset, sMdxView, sDimViews, 1 );\r\n EndIf;\r\n \r\n # Loop through subset of views created based on wildcard\r\n nCountView = SubsetGetSize( sDimViews, cTempSubset );\r\n While( nCountView >= 1 );\r\n sViewEle = SubsetGetElementName( sDimViews, cTempSubset, nCountView );\r\n # Validate attribute name in sDim\r\n If( ViewExists( sCurrentCube, sViewEle ) = 1 );\r\n If( pLogOutput = 1 );\r\n LogOutput( 'INFO', Expand( 'Destroying view %sViewEle% in cube %sCurrentCube%.' ) );\r\n EndIf;\r\n ViewDestroy( sCurrentCube, sViewEle );\r\n Endif;\r\n nCountView = nCountView - 1;\r\n End;\r\n EndIf;\r\n EndIf;\r\n \r\n End;\r\n \r\n # Cube does not exist\r\n Else;\r\n sMessage = Expand('Cube %sCurrentCube% does not exist.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\n \r\n nCountCubes = nCountCubes - 1;\r\n End;\r\n\r\n### End Prolog ###", "MetadataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "DataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "EpilogProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n### Return code & final error message handling\r\nIf( nErrors > 0 );\r\n sMessage = 'the process incurred at least 1 error. Please see above lines in this file for more details.';\r\n nProcessReturnCode = 0;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% Process:%cThisProcName% completed with errors. Check tm1server.log for details.' );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n EndIf;\r\nElse;\r\n sProcessAction = Expand( 'Process:%cThisProcName% successfully deleted view %pView% from cube %pCube%.' );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% %sProcessAction%' );\r\n nProcessReturnCode = 1;\r\n If( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( sProcessAction ) ); \r\n EndIf;\r\nEndIf;\r\n\r\n\r\n### End Epilog ###", @@ -10,35 +10,41 @@ "Type": "None" }, "Parameters": [ - { - "Name": "pLogOutput", - "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, - { - "Name": "pStrictErrorHandling", - "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, { "Name": "pCube", - "Prompt": "REQUIRED: List of Cubes Separated by Delimiter (For all cubes just the wildcard character alone i.e. *)", + "Prompt": "REQUIRED: Cube name", "Value": "", "Type": "String" }, { "Name": "pView", - "Prompt": "REQUIRED: List of Views Separated by Delimiter. Wildcards Permitted on View Names.", - "Value": "}bedrock*", + "Prompt": "REQUIRED: Delimited list of views", + "Value": "", "Type": "String" }, { "Name": "pDelim", - "Prompt": "OPTIONAL: Delimiter Character (default value if blank = '&')", + "Prompt": "OPTIONAL: Delimiter for list parameters (Default = '&')", "Value": "&", "Type": "String" + }, + { + "Name": "pLogOutput", + "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pStrictErrorHandling", + "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pJson", + "Prompt": "OPTIONAL: JSON Object with process parameter values. This will overwrite user passed parameters for all included parameters.", + "Value": "{}", + "Type": "String" } ], "Variables": [], diff --git a/bedrock_processes_json/}bedrock.cube.view.publish.json b/bedrock_processes_json/}bedrock.cube.view.publish.json index 0a802a9..c7bf1d5 100644 --- a/bedrock_processes_json/}bedrock.cube.view.publish.json +++ b/bedrock_processes_json/}bedrock.cube.view.publish.json @@ -1,6 +1,6 @@ { "Name": "}bedrock.cube.view.publish", - "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.view.publish', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pCube', '', 'pView', '',\r\n \t'pSubPublish', 1, 'pOverwrite', 0\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock Ver 4.0.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process converts a private view to a public view for the named client.\r\n#\r\n# Use case: Intended for development/prototyping or production.\r\n# 1. Make private view public to enable public consumption.\r\n#\r\n# Note:\r\n# * A valid cube name pCube is mandatory otherwise the process will abort.\r\n# * Also, a valid view name pView is mandatory otherwise the process will abort.\r\n# * This process must be run by the user owning the private view; it canot be run by another user.\r\n# * If the view contains private subsets they must also be made public or the view publish will fail.\r\n#EndRegion @DOC\r\n\r\n##Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSubset = cThisProcName | '_' | cTimeStamp | '_' | cRandomInt;\r\ncTempFile = GetProcessErrorFileDirectory | cTempSubset | '.csv';\r\nsMessage = \t'';\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pCube:%pCube%, pView:%pView%, pSubPublish:%pSubPublish%, pOverwrite:%pOverwrite%.' ;\r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\n### Validate Parameters ###\r\nnErrors = 0;\r\n\r\n# create friendly name for user handle\r\nIf( DimIx( '}ElementAttributes_}Clients', '}TM1_DefaultDisplayValue' ) > 0 );\r\n pClient = AttrS( '}Clients', cUserName, '}TM1_DefaultDisplayValue' );\r\n If( pClient @= '' );\r\n pClient = cUserName;\r\n EndIf;\r\nElse;\r\n pClient = cUserName;\r\nEndIf;\r\n\r\n# Validate Cube\r\nIf( Trim( pCube ) @= '' );\r\n sMessage = 'No cube specified';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( CubeExists( pCube ) = 0 );\r\n sMessage = Expand('Cube %pCube% does not exist on server');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate view\r\nIf( Trim( pView ) @= '' );\r\n sMessage = 'No view specified';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# No way to check if private view exists except via file system.\r\n# Could include data directory param and concatenate with user, cube and view to check\r\n# if private view exists to handle error in the case that private view does not exist\r\n\r\n# Check for valid view name, subset publish and overwrite parameters\r\nIf( pSubPublish <> 0 & pSubPublish <> 1 );\r\n sMessage = 'Invalid publish private subsets selection: ' | NumberToString( pSubPublish );\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\nIf( pOverwrite <> 0 & pOverwrite <> 1 );\r\n sMessage = 'Invalid overwrite existing public view selection: ' | NumberToString( pOverwrite );\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\nIf( pOverwrite = 0 & ViewExists( pCube, pView ) = 1 );\r\n # If NOT overwriting current public view AND view of the same name exists then cause minor error ( major error if not handled )\r\n sMessage = 'Public view of same name already exists and Overwrite=0 specified';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n### Publish the view ( and any private subsets ) ###\r\nPublishView( pCube, pView, pSubPublish, pOverwrite );\r\n\r\n### End Prolog ###", + "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.view.publish', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pCube', '', 'pView', '',\r\n \t'pSubPublish', 1, 'pOverwrite', 0\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock Ver 4.0.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process converts a private view to a public view for the named client.\r\n#\r\n# Use case: Intended for development/prototyping or production.\r\n# 1. Make private view public to enable public consumption.\r\n#\r\n# Note:\r\n# * A valid cube name pCube is mandatory otherwise the process will abort.\r\n# * Also, a valid view name pView is mandatory otherwise the process will abort.\r\n# * This process must be run by the user owning the private view; it canot be run by another user.\r\n# * If the view contains private subsets they must also be made public or the view publish will fail.\r\n#EndRegion @DOC\r\n\r\n##Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSubset = cThisProcName | '_' | cTimeStamp | '_' | cRandomInt;\r\ncTempFile = GetProcessErrorFileDirectory | cTempSubset | '.csv';\r\nsMessage = \t'';\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pCube:%pCube%, pView:%pView%, pSubPublish:%pSubPublish%, pOverwrite:%pOverwrite%.' ;\r\n\r\n#################################################################################################\r\n#Region - Process Parameters\r\n\r\npJson = IF( JsonType( pJson ) @<> 'object', '{}', pJson );\r\nsMessages = '{\"Process\": \"'|GetProcessName()|'\", \"User\": \"'|TM1User()|'\", \"Info\": [\"Process: '''|GetProcessName()|''' run by User: '''|TM1User()|'''.\"], \"Error\": []}';\r\npDefaultParameters = '{\r\n \"pCube\": null,\r\n \"pView\": null,\r\n \"pLogOutput\": 0,\r\n \"pOverwrite\": 0,\r\n \"pStrictErrorHandling\": 0,\r\n \"pSubPublish\": 1\r\n}';\r\n\r\npPassedParameters = '{\r\n \"pCube\": '|StringToJson ( pCube )|',\r\n \"pView\": '|StringToJson ( pView )|',\r\n \"pLogOutput\": '|NumberToString( pLogOutput )|',\r\n \"pOverwrite\": '|NumberToString( pOverwrite )|',\r\n \"pStrictErrorHandling\": '|NumberToString( pStrictErrorHandling )|',\r\n \"pSubPublish\": '|NumberToString( pSubPublish )|'\r\n}';\r\n\r\npJson = JsonMergePatch( pPassedParameters, pJson );\r\n# String Parameters\r\npCube = JsonToString( JsonGet( pJson, 'pCube' ) );\r\npView = JsonToString( JsonGet( pJson, 'pView' ) );\r\n# Numeric Parameters\r\npLogOutput = StringToNumber( JsonToString( JsonGet( pJson, 'pLogOutput' ) ) );\r\npOverwrite = StringToNumber( JsonToString( JsonGet( pJson, 'pOverwrite' ) ) );\r\npStrictErrorHandling = StringToNumber( JsonToString( JsonGet( pJson, 'pStrictErrorHandling' ) ) );\r\npSubPublish = StringToNumber( JsonToString( JsonGet( pJson, 'pSubPublish' ) ) );\r\n\r\n### Get the parameters that differ from the default\r\npDiffer = JsonDiff( pDefaultParameters, pJson );\r\nnSize = JsonSize( pDiffer );\r\nWHILE( nSize > 0 );\r\n nSize = nSize - 1;\r\n pDiffer = JsonReplace( pDiffer, '/'|NumberToString( nSize )|'/op', '\"add\"' );\r\nEND;\r\npJson = JsonPatch( '{}', pDiffer );\r\n\r\n### LogOutput parameters\r\nsMessages = JsonAdd( sMessages, '/Info/-', pJson );\r\nIF( pLogOutput = 1 );\r\n LogOutput('INFO', JsonToString( sMessages, '/Info/0', 0, ' ' ) );\r\nENDIF;\r\n\r\n#EndRegion - Process Parameters\r\n#################################################################################################\r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\n### Validate Parameters ###\r\nnErrors = 0;\r\n\r\n# create friendly name for user handle\r\nIf( DimIx( '}ElementAttributes_}Clients', '}TM1_DefaultDisplayValue' ) > 0 );\r\n pClient = AttrS( '}Clients', cUserName, '}TM1_DefaultDisplayValue' );\r\n If( pClient @= '' );\r\n pClient = cUserName;\r\n EndIf;\r\nElse;\r\n pClient = cUserName;\r\nEndIf;\r\n\r\n# Validate Cube\r\nIf( Trim( pCube ) @= '' );\r\n sMessage = 'No cube specified';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( CubeExists( pCube ) = 0 );\r\n sMessage = Expand('Cube %pCube% does not exist on server');\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate view\r\nIf( Trim( pView ) @= '' );\r\n sMessage = 'No view specified';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# No way to check if private view exists except via file system.\r\n# Could include data directory param and concatenate with user, cube and view to check\r\n# if private view exists to handle error in the case that private view does not exist\r\n\r\n# Check for valid view name, subset publish and overwrite parameters\r\nIf( pSubPublish <> 0 & pSubPublish <> 1 );\r\n sMessage = 'Invalid publish private subsets selection: ' | NumberToString( pSubPublish );\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\nIf( pOverwrite <> 0 & pOverwrite <> 1 );\r\n sMessage = 'Invalid overwrite existing public view selection: ' | NumberToString( pOverwrite );\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\nIf( pOverwrite = 0 & ViewExists( pCube, pView ) = 1 );\r\n # If NOT overwriting current public view AND view of the same name exists then cause minor error ( major error if not handled )\r\n sMessage = 'Public view of same name already exists and Overwrite=0 specified';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n### Publish the view ( and any private subsets ) ###\r\nPublishView( pCube, pView, pSubPublish, pOverwrite );\r\n\r\n### End Prolog ###", "MetadataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "DataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "EpilogProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n### Return code & final error message handling\r\nIf( nErrors > 0 );\r\n sMessage = 'the process incurred at least 1 error. Please see above lines in this file for more details.';\r\n nProcessReturnCode = 0;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% Process:%cThisProcName% completed with errors. Check tm1server.log for details.' );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n EndIf;\r\nElse;\r\n sProcessAction = Expand( 'Process:%cThisProcName% successfully published view %pView% in cube %pCube% created by cient %pClient%.' );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% %sProcessAction%' );\r\n nProcessReturnCode = 1;\r\n If( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( sProcessAction ) ); \r\n EndIf;\r\nEndIf;\r\n\r\n### End Epilog ###", @@ -10,41 +10,47 @@ "Type": "None" }, "Parameters": [ - { - "Name": "pLogOutput", - "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, - { - "Name": "pStrictErrorHandling", - "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, { "Name": "pCube", - "Prompt": "REQUIRED: Cube Name", + "Prompt": "REQUIRED: Cube name", "Value": "", "Type": "String" }, { "Name": "pView", - "Prompt": "REQUIRED: Private View Name", + "Prompt": "REQUIRED: Name of the view", "Value": "", "Type": "String" }, { "Name": "pSubPublish", - "Prompt": "OPTIONAL: Publish Private Subsets? (Boolean 1=Yes)", + "Prompt": "OPTIONAL: Publish private subsets (Boolean. Default = 1)", "Value": 1, "Type": "Numeric" }, { "Name": "pOverwrite", - "Prompt": "OPTIONAL: Overwrite Existing Named View? (Boolean 1=Yes)", + "Prompt": "OPTIONAL: Overwrite existing named objects (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" + }, + { + "Name": "pLogOutput", + "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pStrictErrorHandling", + "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pJson", + "Prompt": "OPTIONAL: JSON Object with process parameter values. This will overwrite user passed parameters for all included parameters.", + "Value": "{}", + "Type": "String" } ], "Variables": [], diff --git a/bedrock_processes_json/}bedrock.cube.viewandsubsets.create.json b/bedrock_processes_json/}bedrock.cube.viewandsubsets.create.json index 5559d84..9492665 100644 --- a/bedrock_processes_json/}bedrock.cube.viewandsubsets.create.json +++ b/bedrock_processes_json/}bedrock.cube.viewandsubsets.create.json @@ -1,6 +1,6 @@ { "Name": "}bedrock.cube.viewandsubsets.create", - "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.viewandsubsets.create', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pCube', '', 'pView', '', 'pSub', '', \r\n \t'pDim', '*', 'pDelim', '&',\r\n \t'pSuppressZero', 1, 'pSuppressConsol', 1, 'pSuppressRules', 1,\r\n \t'pTemp', 1, 'pSubN', 0\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock Ver 4.0.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process creates a processing view for the cube and for specified dimensions of the cube. \r\n\r\n# Use case: Intended for development/prototyping or in Production environment.\r\n# 1. Create a view with subsets of the same name that are empty.\r\n\r\n# Note:\r\n# Creates empty subsets and assigns the empty subsets to the view. \r\n# A subsequent process is required to insert elements into subsets otherwise the views will not contain any data.\r\n# Naturally, a valid cube name (pCube) is mandatory otherwise the process will abort.\r\n#EndRegion @DOC\r\n\r\n##Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = '%cThisProcName% : %sMessage% : %cUserName%';\r\ncMsgInfoLevel = 'INFO';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pCube:%pCube%, pView:%pView%, pSubset:%pSub%, pDim:%pDim%, pDelim:%pDelim%, pSuppressZero:%pSuppressZero%, pSuppressConsol:%pSuppressConsol%, pSuppressRules:%pSuppressRules%.'; \r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSubset = cThisProcName |'_'| cTimeStamp |'_'| cRandomInt;\r\nsMessage = '';\r\ncDimCubes = '}Cubes';\r\ncDimDimensions = '}Dimensions';\r\ncAll = 'ALL';\r\ncTemp = If( pTemp >= 1, 1, 0 );\r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\n### Validate Parameters ###\r\n\r\nnErrors = 0;\r\n\r\n# Validate cube\r\nIf( Trim( pCube ) @= '' );\r\n sMessage = 'No cube specified.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate dimensions\r\nIf( Trim( pDim ) @= '' );\r\n sMessage = 'No dimensions specified.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate suppression parameters\r\nIf( pSuppressZero <> 0 & pSuppressZero <> 1 );\r\n sMessage = 'Invalid value for suppress zero parameter.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\nIf( pSuppressConsol <> 0 & pSuppressConsol <> 1 );\r\n sMessage = 'Invalid value for suppress consol parameter.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\nIf( pSuppressRules <> 0 & pSuppressRules <> 1 );\r\n sMessage = 'Invalid value for suppress rules parameter.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate view and subsets\r\nIf( pView @= '' & pSub @= '' );\r\n ## Use standard view name.\r\n cView = cTempSubset;\r\n cSubset = cView;\r\nElseIf( pView @<> '' & pSub @= '' );\r\n ## Use the nominated view name for the subset name.\r\n cView = pView;\r\n cSubset = pView;\r\nElseIf( pView @= '' & pSub @<> '' );\r\n ## Use the nominated subset name for the view name.\r\n cView = pSub;\r\n cSubset = pSub;\r\nElse;\r\n cView = pView;\r\n cSubset = pSub;\r\nEndIf;\r\n\r\n\r\n# Validate delimiter\r\nIf( pDelim @= '' );\r\n pDelim = '&';\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n### Handle All cubes or a cubes list\r\nIf ( TRIM( pCube ) @= cAll );\r\n sMDX = Expand( '{TM1SUBSETALL([%cDimCubes%])}' );\r\nElse;\r\n sCubeTokenizer = TRIM( pCube );\r\n sMDX = '';\r\n ### Loop and tokenize Cube list\r\n While ( sCubeTokenizer @<> '' );\r\n nPos = SCAN( pDelim, sCubeTokenizer );\r\n If ( nPos = 0 );\r\n nPos = LONG( sCubeTokenizer ) + 1;\r\n EndIf;\r\n sSearchCube = TRIM( SUBST( sCubeTokenizer, 1, nPos - 1 ) );\r\n If ( SCAN( '*', sSearchCube ) <> 0 % SCAN( '?', sSearchCube ) <> 0 );\r\n If( sMDX @= '' );\r\n sMDX = Expand( '{TM1FILTERBYPATTERN({TM1SUBSETALL([%cDimCubes%])}, \"%sSearchCube%\")}' );\r\n Else;\r\n sMDX = Expand( '%sMDX% + {TM1FILTERBYPATTERN({TM1SUBSETALL([%cDimCubes%])}, \"%sSearchCube%\")}' );\r\n EndIf;\r\n Else;\r\n If ( CubeExists( sSearchCube ) = 0 );\r\n sMessage = Expand( 'Cube: %sSearchCube% does not exist.' );\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n Else;\r\n If( sMDX @= '' );\r\n sMDX = Expand( '{[%cDimCubes%].[%sSearchCube%]}' );\r\n Else;\r\n sMDX = Expand( '%sMDX% + {[%cDimCubes%].[%sSearchCube%]}' );\r\n EndIf;\r\n EndIf;\r\n EndIf;\r\n ### Consume dimension and delimiter\r\n sCubeTokenizer = TRIM( DELET( sCubeTokenizer, 1, nPos + LONG( pDelim ) - 1 ) );\r\n End;\r\n sMDX = Expand( '{%sMDX%}' );\r\nEndIf;\r\n\r\nIf (SubsetExists( cDimCubes, cTempSubset ) = 1 );\r\n SubsetDestroy( cDimCubes, cTempSubset );\r\nEndIf;\r\nSubsetCreateByMDX( cTempSubset, sMDX, cDimCubes, 1 );\r\n\r\n### Handle All dimensions or a dimension list\r\n### We must exclude hierarchies\r\nIf ( TRIM( pDim ) @= cAll );\r\n sMDX = Expand( '{FILTER(TM1SUBSETALL([%cDimDimensions%]), INSTR([%cDimDimensions%].CurrentMember.Name, '':'' ) = 0 )}' );\r\nElse;\r\n sDimTokenizer = TRIM( pDim );\r\n sMDX = '';\r\n ### Loop and tokenize dimension list\r\n While ( sDimTokenizer @<> '' );\r\n nPos = SCAN( pDelim, sDimTokenizer );\r\n If ( nPos = 0 );\r\n nPos = LONG( sDimTokenizer ) + 1;\r\n EndIf;\r\n sSearchDim = TRIM( SUBST( sDimTokenizer, 1, nPos - 1 ) );\r\n If ( SCAN( ':', sSearchDim ) <> 0 );\r\n sMessage = Expand( 'Dimension: The process is not accepting hierarchies: %sSearchDim%' );\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n ElseIf ( SCAN( '*', sSearchDim ) <> 0 % SCAN( '?', sSearchDim ) <> 0 );\r\n If( sMDX @= '' );\r\n sMDX = Expand( '{TM1FILTERBYPATTERN({FILTER(TM1SUBSETALL([%cDimDimensions%]), INSTR([%cDimDimensions%].CurrentMember.Name, '':'' ) = 0 )}, \"%sSearchDim%\")}' );\r\n Else;\r\n sMDX = Expand( '%sMDX% + {TM1FILTERBYPATTERN({FILTER(TM1SUBSETALL([%cDimDimensions%]), INSTR([%cDimDimensions%].CurrentMember.Name, '':'' ) = 0 )}, \"%sSearchDim%\")}' );\r\n EndIf;\r\n Else;\r\n If ( DimensionExists( sSearchDim ) = 0 );\r\n sMessage = Expand( 'Dimension: %sSearchDim% does not exist.' );\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n Else;\r\n If( sMDX @= '' );\r\n sMDX = Expand( '{[%cDimDimensions%].[%sSearchDim%]}' );\r\n Else;\r\n sMDX = Expand( '%sMDX% + {[%cDimDimensions%].[%sSearchDim%]}' );\r\n EndIf;\r\n EndIf;\r\n EndIf;\r\n ### Consume dimension and delimiter\r\n sDimTokenizer = TRIM( DELET( sDimTokenizer, 1, nPos + LONG( pDelim ) - 1 ) );\r\n End;\r\n sMDX = Expand( '{%sMDX%}' );\r\nEndIf;\r\n\r\nIf (SubsetExists( cDimDimensions, cTempSubset ) = 1 );\r\n SubsetDestroy( cDimDimensions, cTempSubset );\r\nEndIf;\r\nSubsetCreateByMDX( cTempSubset, sMDX, cDimDimensions, 1 );\r\n\r\n### Build Subsets and assign to View ###\r\nnCube = 1;\r\nWhile ( nCube <= SubsetGetSize( cDimCubes, cTempSubset ) );\r\n sCube = SubsetGetElementName( cDimCubes, cTempSubset, nCube );\r\n ### Build View ###\r\n If( ViewExists( sCube, cView ) = 1 );\r\n ViewDestroy( sCube, cView );\r\n EndIf;\r\n nDim = 1;\r\n sDim = TABDIM( sCube, nDim );\r\n While ( sDim @<> '' );\r\n # filter selection has non-empty intersect with current cube dimensions\r\n #If ( SubsetElementExists( cDimDimensions, cTempSubset, sDim ) = 1 ); - bug does not work\r\n IF( SubsetElementGetIndex( cDimDimensions, cTempSubset, sDim, 1 ) > 0 );\r\n # create view if and only if there is at least one match with dimensions\r\n If( ViewExists( sCube, cView ) = 0 );\r\n ViewCreate( sCube, cView, cTemp );\r\n ViewExtractSkipZeroesSet( sCube, cView, pSuppressZero );\r\n ViewExtractSkipCalcsSet( sCube, cView, pSuppressConsol );\r\n ViewExtractSkipRuleValuesSet( sCube, cView, pSuppressRules );\r\n EndIf;\r\n If ( SubsetExists ( sDim, cSubset ) = 1 );\r\n If ( SubsetGetSize( sDim, cSubset ) > 0 );\r\n SubsetDeleteAllElements( sDim, cSubset );\r\n EndIf;\r\n Else;\r\n SubsetCreate( sDim, cSubset, cTemp );\r\n EndIf;\r\n ViewSubsetAssign( sCube, cView, sDim, cSubset );\r\n EndIf;\r\n nDim = nDim + 1;\r\n sDim = TABDIM( sCube, nDim );\r\n End;\r\n \r\n # creating N level subset for all dim not included in pDim for the cube\r\n If(pSubN = 1);\r\n nCountDimC = 1;\r\n While( TabDim( sCube, nCountDimC ) @<> '' );\r\n sDimC = TabDim( sCube, nCountDimC );\r\n If ( ViewExists( sCube, cView ) = 1 & SubsetElementGetIndex( cDimDimensions, cTempSubset, sDimC, 1 ) = 0 );\r\n If ( SubsetExists ( sDimC, cSubset ) = 1 );\r\n If ( SubsetGetSize( sDimC, cSubset ) > 0 );\r\n SubsetDeleteAllElements( sDimC, cSubset );\r\n EndIf;\r\n Else;\r\n SubsetCreate( sDimC, cSubset, cTemp );\r\n Endif; \r\n nElCount = DIMSIZ ( sDimC );\r\n nElC = 1;\r\n WHILE ( nElC <= nElCount );\r\n sEl = DIMNM( sDimC, nElC );\r\n IF(ElementLevel( sDimC, sDimC, sEl )= 0 );\r\n SubsetElementInsert( sDimC, cSubset, sEl, 0 );\r\n EndIf;\r\n nElC = nElC + 1;\r\n END;\r\n ViewSubsetAssign( sCube, cView, sDimC, cSubset );\r\n Endif;\r\n nCountDimC = nCountDimC + 1;\r\n End;\r\n Endif;\r\n\r\n\r\n nCube = nCube + 1;\r\nEnd;\r\n\r\n\r\n### End Prolog ###\r\n\r\n", + "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.viewandsubsets.create', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pCube', '', 'pView', '', 'pSub', '', \r\n \t'pDim', '*', 'pDelim', '&',\r\n \t'pSuppressZero', 1, 'pSuppressConsol', 1, 'pSuppressRules', 1,\r\n \t'pTemp', 1, 'pSubN', 0\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock Ver 4.0.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process creates a processing view for the cube and for specified dimensions of the cube. \r\n\r\n# Use case: Intended for development/prototyping or in Production environment.\r\n# 1. Create a view with subsets of the same name that are empty.\r\n\r\n# Note:\r\n# Creates empty subsets and assigns the empty subsets to the view. \r\n# A subsequent process is required to insert elements into subsets otherwise the views will not contain any data.\r\n# Naturally, a valid cube name (pCube) is mandatory otherwise the process will abort.\r\n#EndRegion @DOC\r\n\r\n##Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = '%cThisProcName% : %sMessage% : %cUserName%';\r\ncMsgInfoLevel = 'INFO';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pCube:%pCube%, pView:%pView%, pSubset:%pSub%, pDim:%pDim%, pDelim:%pDelim%, pSuppressZero:%pSuppressZero%, pSuppressConsol:%pSuppressConsol%, pSuppressRules:%pSuppressRules%.'; \r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSubset = cThisProcName |'_'| cTimeStamp |'_'| cRandomInt;\r\nsMessage = '';\r\ncDimCubes = '}Cubes';\r\ncDimDimensions = '}Dimensions';\r\ncAll = 'ALL';\r\ncTemp = If( pTemp >= 1, 1, 0 );\r\n\r\n#################################################################################################\r\n#Region - Process Parameters\r\n\r\npJson = IF( JsonType( pJson ) @<> 'object', '{}', pJson );\r\nsMessages = '{\"Process\": \"'|GetProcessName()|'\", \"User\": \"'|TM1User()|'\", \"Info\": [\"Process: '''|GetProcessName()|''' run by User: '''|TM1User()|'''.\"], \"Error\": []}';\r\npDefaultParameters = '{\r\n \"pCube\": null,\r\n \"pDelim\": \"&\",\r\n \"pDim\": \"*\",\r\n \"pSub\": \"*\",\r\n \"pView\": \"\",\r\n \"pLogOutput\": 0,\r\n \"pStrictErrorHandling\": 0,\r\n \"pSubN\": 0,\r\n \"pSuppressConsol\": 1,\r\n \"pSuppressRules\": 1,\r\n \"pSuppressZero\": 1,\r\n \"pTemp\": 1\r\n}';\r\n\r\npPassedParameters = '{\r\n \"pCube\": '|StringToJson ( pCube )|',\r\n \"pDelim\": '|StringToJson ( pDelim )|',\r\n \"pDim\": '|StringToJson ( pDim )|',\r\n \"pSub\": '|StringToJson ( pSub )|',\r\n \"pView\": '|StringToJson ( pView )|',\r\n \"pLogOutput\": '|NumberToString( pLogOutput )|',\r\n \"pStrictErrorHandling\": '|NumberToString( pStrictErrorHandling )|',\r\n \"pSubN\": '|NumberToString( pSubN )|',\r\n \"pSuppressConsol\": '|NumberToString( pSuppressConsol )|',\r\n \"pSuppressRules\": '|NumberToString( pSuppressRules )|',\r\n \"pSuppressZero\": '|NumberToString( pSuppressZero )|',\r\n \"pTemp\": '|NumberToString( pTemp )|'\r\n}';\r\n\r\npJson = JsonMergePatch( pPassedParameters, pJson );\r\n# String Parameters\r\npCube = JsonToString( JsonGet( pJson, 'pCube' ) );\r\npDelim = JsonToString( JsonGet( pJson, 'pDelim' ) );\r\npDim = JsonToString( JsonGet( pJson, 'pDim' ) );\r\npSub = JsonToString( JsonGet( pJson, 'pSub' ) );\r\npView = JsonToString( JsonGet( pJson, 'pView' ) );\r\n# Numeric Parameters\r\npLogOutput = StringToNumber( JsonToString( JsonGet( pJson, 'pLogOutput' ) ) );\r\npStrictErrorHandling = StringToNumber( JsonToString( JsonGet( pJson, 'pStrictErrorHandling' ) ) );\r\npSubN = StringToNumber( JsonToString( JsonGet( pJson, 'pSubN' ) ) );\r\npSuppressConsol = StringToNumber( JsonToString( JsonGet( pJson, 'pSuppressConsol' ) ) );\r\npSuppressRules = StringToNumber( JsonToString( JsonGet( pJson, 'pSuppressRules' ) ) );\r\npSuppressZero = StringToNumber( JsonToString( JsonGet( pJson, 'pSuppressZero' ) ) );\r\npTemp = StringToNumber( JsonToString( JsonGet( pJson, 'pTemp' ) ) );\r\n\r\n### Get the parameters that differ from the default\r\npDiffer = JsonDiff( pDefaultParameters, pJson );\r\nnSize = JsonSize( pDiffer );\r\nWHILE( nSize > 0 );\r\n nSize = nSize - 1;\r\n pDiffer = JsonReplace( pDiffer, '/'|NumberToString( nSize )|'/op', '\"add\"' );\r\nEND;\r\npJson = JsonPatch( '{}', pDiffer );\r\n\r\n### LogOutput parameters\r\nsMessages = JsonAdd( sMessages, '/Info/-', pJson );\r\nIF( pLogOutput = 1 );\r\n LogOutput('INFO', JsonToString( sMessages, '/Info/0', 0, ' ' ) );\r\nENDIF;\r\n\r\n#EndRegion - Process Parameters\r\n#################################################################################################\r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\n### Validate Parameters ###\r\n\r\nnErrors = 0;\r\n\r\n# Validate cube\r\nIf( Trim( pCube ) @= '' );\r\n sMessage = 'No cube specified.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate dimensions\r\nIf( Trim( pDim ) @= '' );\r\n sMessage = 'No dimensions specified.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate suppression parameters\r\nIf( pSuppressZero <> 0 & pSuppressZero <> 1 );\r\n sMessage = 'Invalid value for suppress zero parameter.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\nIf( pSuppressConsol <> 0 & pSuppressConsol <> 1 );\r\n sMessage = 'Invalid value for suppress consol parameter.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\nIf( pSuppressRules <> 0 & pSuppressRules <> 1 );\r\n sMessage = 'Invalid value for suppress rules parameter.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate view and subsets\r\nIf( pView @= '' & pSub @= '' );\r\n ## Use standard view name.\r\n cView = cTempSubset;\r\n cSubset = cView;\r\nElseIf( pView @<> '' & pSub @= '' );\r\n ## Use the nominated view name for the subset name.\r\n cView = pView;\r\n cSubset = pView;\r\nElseIf( pView @= '' & pSub @<> '' );\r\n ## Use the nominated subset name for the view name.\r\n cView = pSub;\r\n cSubset = pSub;\r\nElse;\r\n cView = pView;\r\n cSubset = pSub;\r\nEndIf;\r\n\r\n\r\n# Validate delimiter\r\nIf( pDelim @= '' );\r\n pDelim = '&';\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n### Handle All cubes or a cubes list\r\nIf ( TRIM( pCube ) @= cAll );\r\n sMDX = Expand( '{TM1SUBSETALL([%cDimCubes%])}' );\r\nElse;\r\n sCubeTokenizer = TRIM( pCube );\r\n sMDX = '';\r\n ### Loop and tokenize Cube list\r\n While ( sCubeTokenizer @<> '' );\r\n nPos = SCAN( pDelim, sCubeTokenizer );\r\n If ( nPos = 0 );\r\n nPos = LONG( sCubeTokenizer ) + 1;\r\n EndIf;\r\n sSearchCube = TRIM( SUBST( sCubeTokenizer, 1, nPos - 1 ) );\r\n If ( SCAN( '*', sSearchCube ) <> 0 % SCAN( '?', sSearchCube ) <> 0 );\r\n If( sMDX @= '' );\r\n sMDX = Expand( '{TM1FILTERBYPATTERN({TM1SUBSETALL([%cDimCubes%])}, \"%sSearchCube%\")}' );\r\n Else;\r\n sMDX = Expand( '%sMDX% + {TM1FILTERBYPATTERN({TM1SUBSETALL([%cDimCubes%])}, \"%sSearchCube%\")}' );\r\n EndIf;\r\n Else;\r\n If ( CubeExists( sSearchCube ) = 0 );\r\n sMessage = Expand( 'Cube: %sSearchCube% does not exist.' );\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n Else;\r\n If( sMDX @= '' );\r\n sMDX = Expand( '{[%cDimCubes%].[%sSearchCube%]}' );\r\n Else;\r\n sMDX = Expand( '%sMDX% + {[%cDimCubes%].[%sSearchCube%]}' );\r\n EndIf;\r\n EndIf;\r\n EndIf;\r\n ### Consume dimension and delimiter\r\n sCubeTokenizer = TRIM( DELET( sCubeTokenizer, 1, nPos + LONG( pDelim ) - 1 ) );\r\n End;\r\n sMDX = Expand( '{%sMDX%}' );\r\nEndIf;\r\n\r\nIf (SubsetExists( cDimCubes, cTempSubset ) = 1 );\r\n SubsetDestroy( cDimCubes, cTempSubset );\r\nEndIf;\r\nSubsetCreateByMDX( cTempSubset, sMDX, cDimCubes, 1 );\r\n\r\n### Handle All dimensions or a dimension list\r\n### We must exclude hierarchies\r\nIf ( TRIM( pDim ) @= cAll );\r\n sMDX = Expand( '{FILTER(TM1SUBSETALL([%cDimDimensions%]), INSTR([%cDimDimensions%].CurrentMember.Name, '':'' ) = 0 )}' );\r\nElse;\r\n sDimTokenizer = TRIM( pDim );\r\n sMDX = '';\r\n ### Loop and tokenize dimension list\r\n While ( sDimTokenizer @<> '' );\r\n nPos = SCAN( pDelim, sDimTokenizer );\r\n If ( nPos = 0 );\r\n nPos = LONG( sDimTokenizer ) + 1;\r\n EndIf;\r\n sSearchDim = TRIM( SUBST( sDimTokenizer, 1, nPos - 1 ) );\r\n If ( SCAN( ':', sSearchDim ) <> 0 );\r\n sMessage = Expand( 'Dimension: The process is not accepting hierarchies: %sSearchDim%' );\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n ElseIf ( SCAN( '*', sSearchDim ) <> 0 % SCAN( '?', sSearchDim ) <> 0 );\r\n If( sMDX @= '' );\r\n sMDX = Expand( '{TM1FILTERBYPATTERN({FILTER(TM1SUBSETALL([%cDimDimensions%]), INSTR([%cDimDimensions%].CurrentMember.Name, '':'' ) = 0 )}, \"%sSearchDim%\")}' );\r\n Else;\r\n sMDX = Expand( '%sMDX% + {TM1FILTERBYPATTERN({FILTER(TM1SUBSETALL([%cDimDimensions%]), INSTR([%cDimDimensions%].CurrentMember.Name, '':'' ) = 0 )}, \"%sSearchDim%\")}' );\r\n EndIf;\r\n Else;\r\n If ( DimensionExists( sSearchDim ) = 0 );\r\n sMessage = Expand( 'Dimension: %sSearchDim% does not exist.' );\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n Else;\r\n If( sMDX @= '' );\r\n sMDX = Expand( '{[%cDimDimensions%].[%sSearchDim%]}' );\r\n Else;\r\n sMDX = Expand( '%sMDX% + {[%cDimDimensions%].[%sSearchDim%]}' );\r\n EndIf;\r\n EndIf;\r\n EndIf;\r\n ### Consume dimension and delimiter\r\n sDimTokenizer = TRIM( DELET( sDimTokenizer, 1, nPos + LONG( pDelim ) - 1 ) );\r\n End;\r\n sMDX = Expand( '{%sMDX%}' );\r\nEndIf;\r\n\r\nIf (SubsetExists( cDimDimensions, cTempSubset ) = 1 );\r\n SubsetDestroy( cDimDimensions, cTempSubset );\r\nEndIf;\r\nSubsetCreateByMDX( cTempSubset, sMDX, cDimDimensions, 1 );\r\n\r\n### Build Subsets and assign to View ###\r\nnCube = 1;\r\nWhile ( nCube <= SubsetGetSize( cDimCubes, cTempSubset ) );\r\n sCube = SubsetGetElementName( cDimCubes, cTempSubset, nCube );\r\n ### Build View ###\r\n If( ViewExists( sCube, cView ) = 1 );\r\n ViewDestroy( sCube, cView );\r\n EndIf;\r\n nDim = 1;\r\n sDim = TABDIM( sCube, nDim );\r\n While ( sDim @<> '' );\r\n # filter selection has non-empty intersect with current cube dimensions\r\n #If ( SubsetElementExists( cDimDimensions, cTempSubset, sDim ) = 1 ); - bug does not work\r\n IF( SubsetElementGetIndex( cDimDimensions, cTempSubset, sDim, 1 ) > 0 );\r\n # create view if and only if there is at least one match with dimensions\r\n If( ViewExists( sCube, cView ) = 0 );\r\n ViewCreate( sCube, cView, cTemp );\r\n ViewExtractSkipZeroesSet( sCube, cView, pSuppressZero );\r\n ViewExtractSkipCalcsSet( sCube, cView, pSuppressConsol );\r\n ViewExtractSkipRuleValuesSet( sCube, cView, pSuppressRules );\r\n EndIf;\r\n If ( SubsetExists ( sDim, cSubset ) = 1 );\r\n If ( SubsetGetSize( sDim, cSubset ) > 0 );\r\n SubsetDeleteAllElements( sDim, cSubset );\r\n EndIf;\r\n Else;\r\n SubsetCreate( sDim, cSubset, cTemp );\r\n EndIf;\r\n ViewSubsetAssign( sCube, cView, sDim, cSubset );\r\n EndIf;\r\n nDim = nDim + 1;\r\n sDim = TABDIM( sCube, nDim );\r\n End;\r\n \r\n # creating N level subset for all dim not included in pDim for the cube\r\n If(pSubN = 1);\r\n nCountDimC = 1;\r\n While( TabDim( sCube, nCountDimC ) @<> '' );\r\n sDimC = TabDim( sCube, nCountDimC );\r\n If ( ViewExists( sCube, cView ) = 1 & SubsetElementGetIndex( cDimDimensions, cTempSubset, sDimC, 1 ) = 0 );\r\n If ( SubsetExists ( sDimC, cSubset ) = 1 );\r\n If ( SubsetGetSize( sDimC, cSubset ) > 0 );\r\n SubsetDeleteAllElements( sDimC, cSubset );\r\n EndIf;\r\n Else;\r\n SubsetCreate( sDimC, cSubset, cTemp );\r\n Endif; \r\n nElCount = DIMSIZ ( sDimC );\r\n nElC = 1;\r\n WHILE ( nElC <= nElCount );\r\n sEl = DIMNM( sDimC, nElC );\r\n IF(ElementLevel( sDimC, sDimC, sEl )= 0 );\r\n SubsetElementInsert( sDimC, cSubset, sEl, 0 );\r\n EndIf;\r\n nElC = nElC + 1;\r\n END;\r\n ViewSubsetAssign( sCube, cView, sDimC, cSubset );\r\n Endif;\r\n nCountDimC = nCountDimC + 1;\r\n End;\r\n Endif;\r\n\r\n\r\n nCube = nCube + 1;\r\nEnd;\r\n\r\n\r\n### End Prolog ###\r\n\r\n", "MetadataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "DataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "EpilogProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n### Return code & final error message handling\r\nIf( nErrors > 0 );\r\n sMessage = 'the process incurred at least 1 error. Please see above lines in this file for more details.';\r\n nProcessReturnCode = 0;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% Process:%cThisProcName% completed with errors. Check tm1server.log for details.' );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n EndIf;\r\nElse;\r\n sProcessAction = Expand( 'Process:%cThisProcName% successfully created views and subsets for cube %pCube%.' );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% %sProcessAction%' );\r\n nProcessReturnCode = 1;\r\n If( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( sProcessAction ) ); \r\n EndIf;\r\nEndIf;\r\n\r\n### End Epilog ###", @@ -10,77 +10,83 @@ "Type": "None" }, "Parameters": [ - { - "Name": "pLogOutput", - "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean True = 1)", - "Value": 1, - "Type": "Numeric" - }, - { - "Name": "pStrictErrorHandling", - "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, { "Name": "pCube", - "Prompt": "REQUIRED: List of Cubes (Separated by Delimiter, Accepts Wild card)", + "Prompt": "REQUIRED: Cube name", "Value": "", "Type": "String" }, { "Name": "pView", - "Prompt": "OPTIONAL: View (will default to pSubset if left blank)", + "Prompt": "OPTIONAL: View name (Default = pSubset )", "Value": "", "Type": "String" }, { "Name": "pSub", - "Prompt": "OPTIONAL: Subset (will default to pView if left blank)", - "Value": "", + "Prompt": "OPTIONAL: View name (Default = pView )", + "Value": "*", "Type": "String" }, { "Name": "pDim", - "Prompt": "REQUIRED: Dimension(s) to create empty processing subsets for (separated by delimiter), * = all", + "Prompt": "OPTIONAL: Delimited list of dimensions to create empty processing subsets for (Default = '*')", "Value": "*", "Type": "String" }, { "Name": "pDelim", - "Prompt": "OPTIONAL: List Delimiter (default value if blank = '&')", + "Prompt": "OPTIONAL: Delimiter for list parameters (Default = '&')", "Value": "&", "Type": "String" }, { "Name": "pSuppressZero", - "Prompt": "OPTIONAL: Suppress Zeros (Boolean Yes = 1)", + "Prompt": "OPTIONAL: Suppress zeroes (Boolean. Default = 1)", "Value": 1, "Type": "Numeric" }, { "Name": "pSuppressConsol", - "Prompt": "OPTIONAL: Suppress Calcs (Boolean Yes = 1)", + "Prompt": "OPTIONAL: Suppress consolidated values (Boolean. Default = 1)", "Value": 1, "Type": "Numeric" }, { "Name": "pSuppressRules", - "Prompt": "OPTIONAL: Suppress Rules (Boolean Yes = 1)", + "Prompt": "OPTIONAL: Suppress rules (Boolean. Default = 1)", "Value": 1, "Type": "Numeric" }, { "Name": "pTemp", - "Prompt": "OPTIONAL: Make View Temporary (1=Temporary)", + "Prompt": "OPTIONAL: Delete/create temporary objects (0 = Do not delete, 1 = Delete, 2 = if view and subsets are created, keep only subsets)", "Value": 1, "Type": "Numeric" }, { "Name": "pSubN", - "Prompt": "OPTIONAL: Create N level subset for all dims not mentioned in pDim", + "Prompt": "OPTIONAL: Create N level subset for all dims not specified (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" + }, + { + "Name": "pLogOutput", + "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pStrictErrorHandling", + "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pJson", + "Prompt": "OPTIONAL: JSON Object with process parameter values. This will overwrite user passed parameters for all included parameters.", + "Value": "{}", + "Type": "String" } ], "Variables": [], diff --git a/bedrock_processes_json/}bedrock.cube.viewandsubsets.delete.json b/bedrock_processes_json/}bedrock.cube.viewandsubsets.delete.json index 8aaf9fa..3726bfa 100644 --- a/bedrock_processes_json/}bedrock.cube.viewandsubsets.delete.json +++ b/bedrock_processes_json/}bedrock.cube.viewandsubsets.delete.json @@ -1,6 +1,6 @@ { "Name": "}bedrock.cube.viewandsubsets.delete", - "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.viewandsubsets.delete', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n\t 'pCube', '', 'pView', '', 'pSub', '', 'pMode', 1\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process deletes a view and all subsets of the same name.\r\n\r\n# Use case: \r\n# 1. In production environment used in Epilog to remove view & subsets used for processing.\r\n# 2. In development/prototyping to manually clean up views & subsets. \r\n\r\n# Note:\r\n# * Lists and wildcards are not supported in this process\r\n# * A valid cube name pCube is mandatory otherwise the process will abort. \r\n# * A valid view name pView is mandatory otherwise the process will abort.\r\n# * The matching assumption is based on **name**. Subsets of the same name as the view will be deleted (whether they were assigned to the view or not).\r\n# * pMode 0 = Delete views and **indirectly** delete subsets via bedrock process call. If a subset cannot be deleted the process will continue and exit with minor error status.\r\n# * pMode 1 = Delete views and **directly** delete subsets via SubsetDestroy function. If a subset cannot be deleted the process will abort with major error status.\r\n# * pMode 2 = Delete views only and leave subsets as is.\r\n#EndRegion @DOC\r\n\r\n##Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncMsgInfoLevel = 'INFO';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pCube:%pCube%, pView:%pView%, pSub:%pSub%, pMode:%pMode%.' ; \r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSubset = cThisProcName |'_'| cTimeStamp |'_'| cRandomInt;\r\nsMessage = '';\r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\n### Validate Parameters ###\r\nnErrors = 0;\r\n\r\n### Validate Paramters ##\r\nIF( pMode <> 0 & pMode <> 1 & pMode <> 2 );\r\n sMessage = 'Invailid mode value provided %pMode%. Do not destroy views or subsets.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nENDIF;\r\n\r\nIf( Trim( pCube ) @= '' );\r\n sMessage = 'No cube specified.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( CubeExists( pCube ) = 0 ); \r\n sMessage = Expand( 'Invalid cube specified: %pCube%.' );\r\n nErrors = 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate pView \r\nIf( Trim( pView ) @= '' );\r\n sMessage = 'No view specified.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( ViewExists(pCube, pView ) = 0 ); \r\n sMessage = Expand('There is no view :%pView% in %pCube% cube.') ;\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElse;\r\n cView = Trim( pView );\r\nEndIf;\r\n\r\n# Validate psubset\r\nIf( pSub @= '' );\r\n cSubset = Trim( pView );\r\nElse;\r\n cSubset = Trim( pSub );\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors > 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n## Clean up view\r\nViewDestroy( pCube, cView );\r\n\r\n## Clean up subsets\r\nIf( pMode <= 1 );\r\n\r\n nDimCount = 0;\r\n i = 1;\r\n sDimName = TabDim( pCube, i );\r\n While( sDimName @<> '' );\r\n If( SubsetExists ( sDimName, cSubset ) = 1 );\r\n If( pMode = 0 );\r\n # \"indirect\" deletion\r\n nRet = ExecuteProcess( '}bedrock.hier.sub.delete',\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pLogOutput', pLogOutput,\r\n \t'pDim', sDimName,\r\n \t'pHier','',\r\n \t'pSub', cSubset,\r\n \t'pDelim', If( Scan( '&', cSubset ) = 0, '&', ':' ),\r\n \t'pMode', 0\r\n );\r\n If( pLogOutput >= 1 & nRet <> ProcessExitNormal() );\r\n nErrors = nErrors + 1;\r\n sMessage = 'Subset %cSubset% in dimension %sDimName% could not be deleted. It may be used in another view.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\n ElseIf( pMode = 1 );\r\n # pMode=1, \"direct\" deletion\r\n SubsetDestroy( sDimName, cSubset );\r\n EndIf;\r\n EndIf;\r\n i = i + 1;\r\n sDimName = TabDim( pCube, i );\r\n End;\r\n\r\nEndIf;", + "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.cube.viewandsubsets.delete', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n\t 'pCube', '', 'pView', '', 'pSub', '', 'pMode', 1\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process deletes a view and all subsets of the same name.\r\n\r\n# Use case: \r\n# 1. In production environment used in Epilog to remove view & subsets used for processing.\r\n# 2. In development/prototyping to manually clean up views & subsets. \r\n\r\n# Note:\r\n# * Lists and wildcards are not supported in this process\r\n# * A valid cube name pCube is mandatory otherwise the process will abort. \r\n# * A valid view name pView is mandatory otherwise the process will abort.\r\n# * The matching assumption is based on **name**. Subsets of the same name as the view will be deleted (whether they were assigned to the view or not).\r\n# * pMode 0 = Delete views and **indirectly** delete subsets via bedrock process call. If a subset cannot be deleted the process will continue and exit with minor error status.\r\n# * pMode 1 = Delete views and **directly** delete subsets via SubsetDestroy function. If a subset cannot be deleted the process will abort with major error status.\r\n# * pMode 2 = Delete views only and leave subsets as is.\r\n#EndRegion @DOC\r\n\r\n##Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncMsgInfoLevel = 'INFO';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pCube:%pCube%, pView:%pView%, pSub:%pSub%, pMode:%pMode%.' ; \r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSubset = cThisProcName |'_'| cTimeStamp |'_'| cRandomInt;\r\nsMessage = '';\r\n\r\n#################################################################################################\r\n#Region - Process Parameters\r\n\r\npJson = IF( JsonType( pJson ) @<> 'object', '{}', pJson );\r\nsMessages = '{\"Process\": \"'|GetProcessName()|'\", \"User\": \"'|TM1User()|'\", \"Info\": [\"Process: '''|GetProcessName()|''' run by User: '''|TM1User()|'''.\"], \"Error\": []}';\r\npDefaultParameters = '{\r\n \"pCube\": null,\r\n \"pSub\": \"*\",\r\n \"pView\": \"\",\r\n \"pLogOutput\": 0,\r\n \"pMode\": 1,\r\n \"pStrictErrorHandling\": 0\r\n}';\r\n\r\npPassedParameters = '{\r\n \"pCube\": '|StringToJson ( pCube )|',\r\n \"pSub\": '|StringToJson ( pSub )|',\r\n \"pView\": '|StringToJson ( pView )|',\r\n \"pLogOutput\": '|NumberToString( pLogOutput )|',\r\n \"pMode\": '|NumberToString( pMode )|',\r\n \"pStrictErrorHandling\": '|NumberToString( pStrictErrorHandling )|'\r\n}';\r\n\r\npJson = JsonMergePatch( pPassedParameters, pJson );\r\n# String Parameters\r\npCube = JsonToString( JsonGet( pJson, 'pCube' ) );\r\npSub = JsonToString( JsonGet( pJson, 'pSub' ) );\r\npView = JsonToString( JsonGet( pJson, 'pView' ) );\r\n# Numeric Parameters\r\npLogOutput = StringToNumber( JsonToString( JsonGet( pJson, 'pLogOutput' ) ) );\r\npMode = StringToNumber( JsonToString( JsonGet( pJson, 'pMode' ) ) );\r\npStrictErrorHandling = StringToNumber( JsonToString( JsonGet( pJson, 'pStrictErrorHandling' ) ) );\r\n\r\n### Get the parameters that differ from the default\r\npDiffer = JsonDiff( pDefaultParameters, pJson );\r\nnSize = JsonSize( pDiffer );\r\nWHILE( nSize > 0 );\r\n nSize = nSize - 1;\r\n pDiffer = JsonReplace( pDiffer, '/'|NumberToString( nSize )|'/op', '\"add\"' );\r\nEND;\r\npJson = JsonPatch( '{}', pDiffer );\r\n\r\n### LogOutput parameters\r\nsMessages = JsonAdd( sMessages, '/Info/-', pJson );\r\nIF( pLogOutput = 1 );\r\n LogOutput('INFO', JsonToString( sMessages, '/Info/0', 0, ' ' ) );\r\nENDIF;\r\n\r\n#EndRegion - Process Parameters\r\n#################################################################################################\r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\n### Validate Parameters ###\r\nnErrors = 0;\r\n\r\n### Validate Paramters ##\r\nIF( pMode <> 0 & pMode <> 1 & pMode <> 2 );\r\n sMessage = 'Invailid mode value provided %pMode%. Do not destroy views or subsets.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nENDIF;\r\n\r\nIf( Trim( pCube ) @= '' );\r\n sMessage = 'No cube specified.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( CubeExists( pCube ) = 0 ); \r\n sMessage = Expand( 'Invalid cube specified: %pCube%.' );\r\n nErrors = 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate pView \r\nIf( Trim( pView ) @= '' );\r\n sMessage = 'No view specified.';\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( ViewExists(pCube, pView ) = 0 ); \r\n sMessage = Expand('There is no view :%pView% in %pCube% cube.') ;\r\n nErrors = nErrors + 1;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElse;\r\n cView = Trim( pView );\r\nEndIf;\r\n\r\n# Validate psubset\r\nIf( pSub @= '' );\r\n cSubset = Trim( pView );\r\nElse;\r\n cSubset = Trim( pSub );\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors > 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n## Clean up view\r\nViewDestroy( pCube, cView );\r\n\r\n## Clean up subsets\r\nIf( pMode <= 1 );\r\n\r\n nDimCount = 0;\r\n i = 1;\r\n sDimName = TabDim( pCube, i );\r\n While( sDimName @<> '' );\r\n If( SubsetExists ( sDimName, cSubset ) = 1 );\r\n If( pMode = 0 );\r\n # \"indirect\" deletion\r\n nRet = ExecuteProcess( '}bedrock.hier.sub.delete',\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pLogOutput', pLogOutput,\r\n \t'pDim', sDimName,\r\n \t'pHier','',\r\n \t'pSub', cSubset,\r\n \t'pDelim', If( Scan( '&', cSubset ) = 0, '&', ':' ),\r\n \t'pMode', 0\r\n );\r\n If( pLogOutput >= 1 & nRet <> ProcessExitNormal() );\r\n nErrors = nErrors + 1;\r\n sMessage = 'Subset %cSubset% in dimension %sDimName% could not be deleted. It may be used in another view.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\n ElseIf( pMode = 1 );\r\n # pMode=1, \"direct\" deletion\r\n SubsetDestroy( sDimName, cSubset );\r\n EndIf;\r\n EndIf;\r\n i = i + 1;\r\n sDimName = TabDim( pCube, i );\r\n End;\r\n\r\nEndIf;", "MetadataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "DataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "EpilogProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n### Return code & final error message handling\r\nIf( nErrors > 0 );\r\n sMessage = 'the process incurred at least 1 error. Please see above lines in this file for more details.';\r\n nProcessReturnCode = 0;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% Process:%cThisProcName% completed with errors. Check tm1server.log for details.' );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n EndIf;\r\nElse;\r\n sProcessAction = Expand( 'Process:%cThisProcName% successfully deleted views and subsets for cube %pCube%.' );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% %sProcessAction%' );\r\n nProcessReturnCode = 1;\r\n If( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( sProcessAction ) ); \r\n EndIf;\r\nEndIf;\r\n\r\n### End Epilog ###", @@ -10,41 +10,47 @@ "Type": "None" }, "Parameters": [ - { - "Name": "pLogOutput", - "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, - { - "Name": "pStrictErrorHandling", - "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, { "Name": "pCube", - "Prompt": "REQUIRED: Cube Name", + "Prompt": "REQUIRED: Cube name", "Value": "", "Type": "String" }, { "Name": "pView", - "Prompt": "REQUIRED: View Name", + "Prompt": "OPTIONAL: View name (Default = pSubset )", "Value": "", "Type": "String" }, { "Name": "pSub", - "Prompt": "OPTIONAL: Subset Name (will default to pView if left blank)", - "Value": "", + "Prompt": "OPTIONAL: View name (Default = pView )", + "Value": "*", "Type": "String" }, { "Name": "pMode", - "Prompt": "REQUIRED: Delete temporary view and Subset (0 = Delete View and Subsets indirectly 1 = Delete View and Subsets directly 2 = Delete View only )", + "Prompt": "OPTIONAL: Delete temporary view and subsets (0 = Retain View and Subsets, 1 = Delete View and Subsets, 2 = Delete View only. Default = 1)", "Value": 1, "Type": "Numeric" + }, + { + "Name": "pLogOutput", + "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pStrictErrorHandling", + "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pJson", + "Prompt": "OPTIONAL: JSON Object with process parameter values. This will overwrite user passed parameters for all included parameters.", + "Value": "{}", + "Type": "String" } ], "Variables": [], diff --git a/bedrock_processes_json/}bedrock.dim.attr.create.json b/bedrock_processes_json/}bedrock.dim.attr.create.json index e9e6822..9695751 100644 --- a/bedrock_processes_json/}bedrock.dim.attr.create.json +++ b/bedrock_processes_json/}bedrock.dim.attr.create.json @@ -1,6 +1,6 @@ { "Name": "}bedrock.dim.attr.create", - "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.dim.attr.create', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pDim', '', 'pAttr', '',\r\n \t'pPrevAttr', '', 'pAttrType', '',\r\n \t'pDelim', '&'\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process can insert one or more attributes in one or more specified dimensions. \r\n\r\n# Use case: Intended for development/prototyping.\r\n# 1/ Add multiple dimension attributes.\r\n\r\n# Note:\r\n# Delimited lists and/or wild card(*) are acceptable for pDim & pAttr.\r\n# Naturally, valid dimension name(s) (pDim) are mandatory otherwise the process will abort.\r\n# Known limitation: This process can insert multiple attributes to multiple dimensions but only for a single attribute type.\r\n#EndRegion @DOC\r\n\r\n### Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSub = cThisProcName |'_'| cTimeStamp |'_'| cRandomInt;\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent= 'Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'User:%cUserName% Process:%cThisProcName% run with parameters pDim:%pDim%, pPrevAttr:%pPrevAttr%, pAttr:%pAttr%, pAttrType:%pAttrType%, pDelim:%pDelim%.'; \r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\n### Validate Parameters ###\r\nnErrors = 0;\r\n\r\n# Validate dimension\r\nIf( Trim( pDim ) @= '' );\r\n nErrors = 1;\r\n sMessage = 'No dimension specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate attribute\r\nIF( Trim( pAttr ) @= '' );\r\n nErrors = 1;\r\n sMessage = 'No attribute specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate attribute type\r\nIF( Trim( pAttrType ) @= '' );\r\n pAttrType = 'S';\r\nENDIF;\r\n\r\npAttrType = Upper( SubSt( pAttrType, 1, 1 ) );\r\nIf( pAttrType @<> 'A' & pAttrType @<> 'S' & pAttrType @<> 'N' );\r\n nErrors = 1;\r\n sMessage = 'Invalid attribute type specified: ' | pAttrType | '. Defaulted to String type';\r\n LogOutput( 'INFO', Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate previous attribute\r\nIf( DimIx( '}ElementAttributes_' | pDim, pPrevAttr ) = 0 % pPrevAttr @= pAttr );\r\n pPrevAttr = '';\r\nEndIf;\r\n\r\n# If blank delimiter specified then convert to default\r\nIf( pDelim @= '' );\r\n pDelim = '&';\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n# Loop through dimensions in pDim and attributes in pAttr\r\nsDims = pDim;\r\nnDimDelimiterIndex = 1;\r\n# Get 1st dimension\r\nWhile( nDimDelimiterIndex <> 0 );\r\n # Extract 1st dimension > sDim\r\n nDimDelimiterIndex = Scan( pDelim, sDims );\r\n If( nDimDelimiterIndex = 0 );\r\n sDim = sDims;\r\n Else;\r\n sDim = Trim( SubSt( sDims, 1, nDimDelimiterIndex - 1 ) );\r\n sDims = Trim( Subst( sDims, nDimDelimiterIndex + Long(pDelim), Long( sDims ) ) );\r\n EndIf;\r\n \r\n # Check if sDim has wildcard\r\n If( Scan( '*', sDim ) = 0);\r\n # Validate dimension\r\n If( DimensionExists(sDim) = 0 );\r\n nErrors = 1;\r\n sMessage = Expand( 'Dimension \"%sDim%\" does not exist.' );\r\n LogOutput( 'ERROR', Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n Else;\r\n # Loop through attributes in pAttr \r\n sAttrs = pAttr;\r\n nDelimiterIndex = 1;\r\n sAttrDim = '}ElementAttributes_'|sDim ;\r\n While( nDelimiterIndex <> 0 );\r\n \r\n nDelimiterIndex = Scan( pDelim, sAttrs );\r\n If( nDelimiterIndex = 0 );\r\n sAttr = sAttrs;\r\n Else;\r\n sAttr = Trim( SubSt( sAttrs, 1, nDelimiterIndex - 1 ) );\r\n sAttrs = Trim( Subst( sAttrs, nDelimiterIndex + Long(pDelim), Long( sAttrs ) ) );\r\n EndIf;\r\n \r\n # Check to see if attribute already exists.\r\n If( Dimix( sAttrDim , sAttr ) = 1 );\r\n nErrors = 1;\r\n sMessage = 'Attribute ' | sAttr | ' already exist in dimension ' | sDim;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n Else;\r\n AttrInsert( sDim , pPrevAttr , sAttr , pAttrType ) ;\r\n If( pLogOutput = 1 );\r\n LogOutput( 'INFO', Expand( 'Attribute \"%sAttr%\" added to dimension %sDim%.' ) );\r\n EndIf;\r\n Endif;\r\n End;\r\n EndIf; \r\n Else;\r\n # Create subset using Wildcard to loop through dimensions in pDim with wildcard\r\n sDimExp = '\"'|sDim|'\"';\r\n sMdx = '{TM1FILTERBYPATTERN( EXCEPT ( TM1SUBSETALL( [}Dimensions] ) , TM1FILTERBYPATTERN( TM1SUBSETALL( [}Dimensions] ) , \"*:*\") ) ,'| sDimExp | ')}';\r\n If( SubsetExists( '}Dimensions' , cTempSub ) = 1 );\r\n # If a delimited list of attr names includes wildcards then we may have to re-use the subset multiple times\r\n SubsetMDXSet( '}Dimensions' , cTempSub, sMDX );\r\n Else;\r\n # temp subset, therefore no need to destroy in epilog\r\n SubsetCreatebyMDX( cTempSub, sMDX, '}Dimensions' , 1 );\r\n EndIf;\r\n \r\n # Loop through dimensions in subset created based on wildcard\r\n nCountDim = SubsetGetSize( '}Dimensions' , cTempSub );\r\n While( nCountDim >= 1 );\r\n \r\n sDim = SubsetGetElementName( '}Dimensions' , cTempSub, nCountDim );\r\n # Validate dimension name\r\n If( DimensionExists(sDim) = 0 );\r\n nErrors = 1;\r\n sMessage = Expand( 'Dimension \"%sDim%\" does not exist.' );\r\n LogOutput( 'ERROR', Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n Else;\r\n # Loop through attributes in pAttr \r\n sAttrs = pAttr;\r\n nDelimiterIndex = 1;\r\n sAttrDim = '}ElementAttributes_'|sDim ;\r\n While( nDelimiterIndex <> 0 );\r\n \r\n nDelimiterIndex = Scan( pDelim, sAttrs );\r\n If( nDelimiterIndex = 0 );\r\n sAttr = sAttrs;\r\n Else;\r\n sAttr = Trim( SubSt( sAttrs, 1, nDelimiterIndex - 1 ) );\r\n sAttrs = Trim( Subst( sAttrs, nDelimiterIndex + Long(pDelim), Long( sAttrs ) ) );\r\n EndIf;\r\n \r\n # Check to see if attribute already exists.\r\n If( Dimix( sAttrDim , sAttr ) = 1 );\r\n nErrors = 1;\r\n sMessage = 'Attribute ' | sAttr | ' already exist in dimension ' | sDim;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n Else;\r\n AttrInsert( sDim , pPrevAttr , sAttr , pAttrType ) ;\r\n If( pLogOutput = 1 );\r\n LogOutput( 'INFO', Expand( 'Attribute \"%sAttr%\" added to dimension %sDim%.' ) );\r\n EndIf;\r\n Endif;\r\n End; \r\n EndIf;\r\n \r\n nCountDim = nCountDim - 1;\r\n End;\r\n EndIf;\r\n \r\n \r\nEnd;\r\n\r\n### End Prolog ###", + "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.dim.attr.create', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pDim', '', 'pAttr', '',\r\n \t'pPrevAttr', '', 'pAttrType', '',\r\n \t'pDelim', '&'\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process can insert one or more attributes in one or more specified dimensions. \r\n\r\n# Use case: Intended for development/prototyping.\r\n# 1/ Add multiple dimension attributes.\r\n\r\n# Note:\r\n# Delimited lists and/or wild card(*) are acceptable for pDim & pAttr.\r\n# Naturally, valid dimension name(s) (pDim) are mandatory otherwise the process will abort.\r\n# Known limitation: This process can insert multiple attributes to multiple dimensions but only for a single attribute type.\r\n#EndRegion @DOC\r\n\r\n### Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSub = cThisProcName |'_'| cTimeStamp |'_'| cRandomInt;\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent= 'Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'User:%cUserName% Process:%cThisProcName% run with parameters pDim:%pDim%, pPrevAttr:%pPrevAttr%, pAttr:%pAttr%, pAttrType:%pAttrType%, pDelim:%pDelim%.';\r\n\r\n#################################################################################################\r\n#Region - Process Parameters\r\n\r\npJson = IF( JsonType( pJson ) @<> 'object', '{}', pJson );\r\nsMessages = '{\"Process\": \"'|GetProcessName()|'\", \"User\": \"'|TM1User()|'\", \"Info\": [\"Process: '''|GetProcessName()|''' run by User: '''|TM1User()|'''.\"], \"Error\": []}';\r\npDefaultParameters = '{\r\n \"pAttr\": null,\r\n \"pAttrType\": \"S\",\r\n \"pDelim\": \"&\",\r\n \"pDim\": null,\r\n \"pPrevAttr\": \"\",\r\n \"pLogOutput\": 0,\r\n \"pStrictErrorHandling\": 0\r\n}';\r\n\r\npPassedParameters = '{\r\n \"pAttr\": '|StringToJson ( pAttr )|',\r\n \"pAttrType\": '|StringToJson ( pAttrType )|',\r\n \"pDelim\": '|StringToJson ( pDelim )|',\r\n \"pDim\": '|StringToJson ( pDim )|',\r\n \"pPrevAttr\": '|StringToJson ( pPrevAttr )|',\r\n \"pLogOutput\": '|NumberToString( pLogOutput )|',\r\n \"pStrictErrorHandling\": '|NumberToString( pStrictErrorHandling )|'\r\n}';\r\n\r\npJson = JsonMergePatch( pPassedParameters, pJson );\r\n# String Parameters\r\npAttr = JsonToString( JsonGet( pJson, 'pAttr' ) );\r\npAttrType = JsonToString( JsonGet( pJson, 'pAttrType' ) );\r\npDelim = JsonToString( JsonGet( pJson, 'pDelim' ) );\r\npDim = JsonToString( JsonGet( pJson, 'pDim' ) );\r\npPrevAttr = JsonToString( JsonGet( pJson, 'pPrevAttr' ) );\r\n# Numeric Parameters\r\npLogOutput = StringToNumber( JsonToString( JsonGet( pJson, 'pLogOutput' ) ) );\r\npStrictErrorHandling = StringToNumber( JsonToString( JsonGet( pJson, 'pStrictErrorHandling' ) ) );\r\n\r\n### Get the parameters that differ from the default\r\npDiffer = JsonDiff( pDefaultParameters, pJson );\r\nnSize = JsonSize( pDiffer );\r\nWHILE( nSize > 0 );\r\n nSize = nSize - 1;\r\n pDiffer = JsonReplace( pDiffer, '/'|NumberToString( nSize )|'/op', '\"add\"' );\r\nEND;\r\npJson = JsonPatch( '{}', pDiffer );\r\n\r\n### LogOutput parameters\r\nsMessages = JsonAdd( sMessages, '/Info/-', pJson );\r\nIF( pLogOutput = 1 );\r\n LogOutput('INFO', JsonToString( sMessages, '/Info/0', 0, ' ' ) );\r\nENDIF;\r\n\r\n#EndRegion - Process Parameters\r\n#################################################################################################\r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\n### Validate Parameters ###\r\nnErrors = 0;\r\n\r\n# Validate dimension\r\nIf( Trim( pDim ) @= '' );\r\n nErrors = 1;\r\n sMessage = 'No dimension specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate attribute\r\nIF( Trim( pAttr ) @= '' );\r\n nErrors = 1;\r\n sMessage = 'No attribute specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate attribute type\r\nIF( Trim( pAttrType ) @= '' );\r\n pAttrType = 'S';\r\nENDIF;\r\n\r\npAttrType = Upper( SubSt( pAttrType, 1, 1 ) );\r\nIf( pAttrType @<> 'A' & pAttrType @<> 'S' & pAttrType @<> 'N' );\r\n nErrors = 1;\r\n sMessage = 'Invalid attribute type specified: ' | pAttrType | '. Defaulted to String type';\r\n LogOutput( 'INFO', Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate previous attribute\r\nIf( DimIx( '}ElementAttributes_' | pDim, pPrevAttr ) = 0 % pPrevAttr @= pAttr );\r\n pPrevAttr = '';\r\nEndIf;\r\n\r\n# If blank delimiter specified then convert to default\r\nIf( pDelim @= '' );\r\n pDelim = '&';\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n# Loop through dimensions in pDim and attributes in pAttr\r\nsDims = pDim;\r\nnDimDelimiterIndex = 1;\r\n# Get 1st dimension\r\nWhile( nDimDelimiterIndex <> 0 );\r\n # Extract 1st dimension > sDim\r\n nDimDelimiterIndex = Scan( pDelim, sDims );\r\n If( nDimDelimiterIndex = 0 );\r\n sDim = sDims;\r\n Else;\r\n sDim = Trim( SubSt( sDims, 1, nDimDelimiterIndex - 1 ) );\r\n sDims = Trim( Subst( sDims, nDimDelimiterIndex + Long(pDelim), Long( sDims ) ) );\r\n EndIf;\r\n \r\n # Check if sDim has wildcard\r\n If( Scan( '*', sDim ) = 0);\r\n # Validate dimension\r\n If( DimensionExists(sDim) = 0 );\r\n nErrors = 1;\r\n sMessage = Expand( 'Dimension \"%sDim%\" does not exist.' );\r\n LogOutput( 'ERROR', Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n Else;\r\n # Loop through attributes in pAttr \r\n sAttrs = pAttr;\r\n nDelimiterIndex = 1;\r\n sAttrDim = '}ElementAttributes_'|sDim ;\r\n While( nDelimiterIndex <> 0 );\r\n \r\n nDelimiterIndex = Scan( pDelim, sAttrs );\r\n If( nDelimiterIndex = 0 );\r\n sAttr = sAttrs;\r\n Else;\r\n sAttr = Trim( SubSt( sAttrs, 1, nDelimiterIndex - 1 ) );\r\n sAttrs = Trim( Subst( sAttrs, nDelimiterIndex + Long(pDelim), Long( sAttrs ) ) );\r\n EndIf;\r\n \r\n # Check to see if attribute already exists.\r\n If( Dimix( sAttrDim , sAttr ) = 1 );\r\n nErrors = 1;\r\n sMessage = 'Attribute ' | sAttr | ' already exist in dimension ' | sDim;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n Else;\r\n AttrInsert( sDim , pPrevAttr , sAttr , pAttrType ) ;\r\n If( pLogOutput = 1 );\r\n LogOutput( 'INFO', Expand( 'Attribute \"%sAttr%\" added to dimension %sDim%.' ) );\r\n EndIf;\r\n Endif;\r\n End;\r\n EndIf; \r\n Else;\r\n # Create subset using Wildcard to loop through dimensions in pDim with wildcard\r\n sDimExp = '\"'|sDim|'\"';\r\n sMdx = '{TM1FILTERBYPATTERN( EXCEPT ( TM1SUBSETALL( [}Dimensions] ) , TM1FILTERBYPATTERN( TM1SUBSETALL( [}Dimensions] ) , \"*:*\") ) ,'| sDimExp | ')}';\r\n If( SubsetExists( '}Dimensions' , cTempSub ) = 1 );\r\n # If a delimited list of attr names includes wildcards then we may have to re-use the subset multiple times\r\n SubsetMDXSet( '}Dimensions' , cTempSub, sMDX );\r\n Else;\r\n # temp subset, therefore no need to destroy in epilog\r\n SubsetCreatebyMDX( cTempSub, sMDX, '}Dimensions' , 1 );\r\n EndIf;\r\n \r\n # Loop through dimensions in subset created based on wildcard\r\n nCountDim = SubsetGetSize( '}Dimensions' , cTempSub );\r\n While( nCountDim >= 1 );\r\n \r\n sDim = SubsetGetElementName( '}Dimensions' , cTempSub, nCountDim );\r\n # Validate dimension name\r\n If( DimensionExists(sDim) = 0 );\r\n nErrors = 1;\r\n sMessage = Expand( 'Dimension \"%sDim%\" does not exist.' );\r\n LogOutput( 'ERROR', Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\n Else;\r\n # Loop through attributes in pAttr \r\n sAttrs = pAttr;\r\n nDelimiterIndex = 1;\r\n sAttrDim = '}ElementAttributes_'|sDim ;\r\n While( nDelimiterIndex <> 0 );\r\n \r\n nDelimiterIndex = Scan( pDelim, sAttrs );\r\n If( nDelimiterIndex = 0 );\r\n sAttr = sAttrs;\r\n Else;\r\n sAttr = Trim( SubSt( sAttrs, 1, nDelimiterIndex - 1 ) );\r\n sAttrs = Trim( Subst( sAttrs, nDelimiterIndex + Long(pDelim), Long( sAttrs ) ) );\r\n EndIf;\r\n \r\n # Check to see if attribute already exists.\r\n If( Dimix( sAttrDim , sAttr ) = 1 );\r\n nErrors = 1;\r\n sMessage = 'Attribute ' | sAttr | ' already exist in dimension ' | sDim;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n Else;\r\n AttrInsert( sDim , pPrevAttr , sAttr , pAttrType ) ;\r\n If( pLogOutput = 1 );\r\n LogOutput( 'INFO', Expand( 'Attribute \"%sAttr%\" added to dimension %sDim%.' ) );\r\n EndIf;\r\n Endif;\r\n End; \r\n EndIf;\r\n \r\n nCountDim = nCountDim - 1;\r\n End;\r\n EndIf;\r\n \r\n \r\nEnd;\r\n\r\n### End Prolog ###", "MetadataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "DataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "EpilogProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n### Return code & final error message handling\r\nIf( nErrors > 0 );\r\n sMessage = 'the process incurred at least 1 error. Please see above lines in this file for more details.';\r\n nProcessReturnCode = 0;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% Process:%cThisProcName% completed with errors. Check tm1server.log for details.' );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n EndIf;\r\nElse;\r\n sProcessAction = Expand( 'Process:%cThisProcName% successfully created attribute %pAttr% in dimension %pDim%.' );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% %sProcessAction%' );\r\n nProcessReturnCode = 1;\r\n If( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( sProcessAction ) ); \r\n EndIf;\r\nEndIf;\r\n\r\n### End Epilog ###", @@ -10,47 +10,53 @@ "Type": "None" }, "Parameters": [ - { - "Name": "pLogOutput", - "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, - { - "Name": "pStrictErrorHandling", - "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, { "Name": "pDim", - "Prompt": "REQUIRED: dimension name, parameter accepts delimited list and wildcards", + "Prompt": "REQUIRED: Delimited list of dimensions", "Value": "", "Type": "String" }, { "Name": "pAttr", - "Prompt": "REQUIRED: attribute name, parameter accepts delimited list (separate with delimiter for multiple item e.g. Type&Active )", + "Prompt": "REQUIRED: Delimited list of attribute names", "Value": "", "Type": "String" }, { "Name": "pPrevAttr", - "Prompt": "OPTIONAL: insert position (previous attribute) (Defaults to blank)", + "Prompt": "OPTIONAL: Insert position", "Value": "", "Type": "String" }, { "Name": "pAttrType", - "Prompt": "OPTIONAL: attribute type (e.g. A, S or N. If blank then assumed to be type=string)", - "Value": "", + "Prompt": "OPTIONAL: Attribute type ('A', 'S', or 'N'. Default = 'S')", + "Value": "S", "Type": "String" }, { "Name": "pDelim", - "Prompt": "OPTIONAL: delimiter character for attribute list. (Defaults to & if blank)", + "Prompt": "OPTIONAL: Delimiter for list parameters (Default = '&')", "Value": "&", "Type": "String" + }, + { + "Name": "pLogOutput", + "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pStrictErrorHandling", + "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pJson", + "Prompt": "OPTIONAL: JSON Object with process parameter values. This will overwrite user passed parameters for all included parameters.", + "Value": "{}", + "Type": "String" } ], "Variables": [], diff --git a/bedrock_processes_json/}bedrock.dim.attr.delete.json b/bedrock_processes_json/}bedrock.dim.attr.delete.json index 8723a9e..df6ca56 100644 --- a/bedrock_processes_json/}bedrock.dim.attr.delete.json +++ b/bedrock_processes_json/}bedrock.dim.attr.delete.json @@ -1,6 +1,6 @@ { "Name": "}bedrock.dim.attr.delete", - "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.dim.attr.delete', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n\t 'pDim', '', 'pAttr', '', 'pDelim', '&', 'pCtrlObj', 0\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process can delete one or more attributes in one or more specified dimensions.\r\n#\r\n# Use case: Intended for development/prototyping.\r\n# 1. Clean up unused dimension attributes before going to production\r\n#\r\n# Note:\r\n# * Delimited lists and/or wild card(*) are acceptable for pDim & pAttr\r\n# * Multi-character wildcard \"*\" value for pAttr is evaluated as \"ALL\"\r\n# * You cannot specify \"*\" for **both** pDim and pAttr!\r\n#\r\n# Warning:\r\n# 1. As the process accepts wildcards USE WITH GREAT CARE! As if using wildcards for dimensions and attributes any matching attributes \r\n# in any matching dimensions will be removed from the system.\r\n# 2. Multi-character wildcard \"*\" value for pAttr is evaluated as \"ALL\". Setting pAttr to \"*\" will delete all attributes in the spacified dimension.\r\n#EndRegion @DOC\r\n\r\n### Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSub = cThisProcName |'_'| cTimeStamp |'_'| cRandomInt;\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncMsgInfoContent = 'User:%cUserName% Process:%cThisProcName% Message:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pDim:%pDim%, pAttr:%pAttr%, pDelim:%pDelim%, pCtrlObj:%pCtrlObj%.'; \r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\n### Validate Parameters ###\r\nnErrors = 0;\r\n\r\n## Validate dimension\r\nIf( (Trim( pDim ) @= 'ALL' & Trim( pAttr ) @= 'ALL') % (Trim( pDim ) @= '*' & Trim( pAttr ) @= 'ALL') % (Trim( pDim ) @= 'ALL' & Trim( pAttr ) @= '*') % (Trim( pDim ) @= '*' & Trim( pAttr ) @= '*') );\r\n nErrors = 1;\r\n sMessage = 'Deleting all attrbitutes from all dimensions is not supported.';\r\n LogOutput( 'ERROR', Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\nIf( Trim( pDim ) @= '' );\r\n nErrors = 1;\r\n sMessage = 'No dimension specified.';\r\n LogOutput( 'ERROR', Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate attribute\r\nIf( Trim( pAttr ) @= '' );\r\n nErrors = 1;\r\n sMessage = 'No attribute specified.';\r\n LogOutput( 'ERROR', Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# If blank delimiter specified then convert to default\r\nIf( pDelim @= '' );\r\n pDelim = '&';\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors > 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n# Loop through dimensions in pDim and attributes in pAttr\r\nsDims = pDim;\r\nnDimDelimiterIndex = 1;\r\nsMdx = '';\r\n# Get 1st dimension\r\nWhile( nDimDelimiterIndex <> 0 );\r\n # Extract 1st dimension > sDim\r\n nDimDelimiterIndex = Scan( pDelim, sDims );\r\n If( nDimDelimiterIndex = 0 );\r\n sDim = sDims;\r\n Else;\r\n sDim = Trim( SubSt( sDims, 1, nDimDelimiterIndex - 1 ) );\r\n sDims = Trim( Subst( sDims, nDimDelimiterIndex + Long(pDelim), Long( sDims ) ) );\r\n EndIf;\r\n \r\n # Create subset of dimensions using Wildcard to loop through dimensions in pDim with wildcard\r\n sDimExp = '\"'|sDim|'\"';\r\n IF( pCtrlObj = 1 );\r\n sMdxPart = '{TM1FILTERBYPATTERN( EXCEPT( TM1SUBSETALL( [}Dimensions] ) , TM1FILTERBYPATTERN( TM1SUBSETALL( [}Dimensions] ) , \"*:*\") ) ,'| sDimExp | ')}';\r\n ELSE;\r\n sMdxPart = '{TM1FILTERBYPATTERN( EXCEPT( EXCEPT( TM1SUBSETALL( [}Dimensions] ) , TM1FILTERBYPATTERN( TM1SUBSETALL( [}Dimensions] ) , \"*:*\") ) , TM1FILTERBYPATTERN( TM1SUBSETALL( [}Dimensions] ) , \"}*\" ) ) ,'| sDimExp | ')}'; \r\n ENDIF;\r\n IF( sMdx @= ''); \r\n sMdx = sMdxPart; \r\n ELSE;\r\n sMdx = sMdx | ' + ' | sMdxPart;\r\n ENDIF;\r\n \r\n If( SubsetExists( '}Dimensions' , cTempSub ) = 1 );\r\n # If a delimited list of dim names includes wildcards then we may have to re-use the subset multiple times\r\n SubsetMDXSet( '}Dimensions' , cTempSub, sMDX );\r\n Else;\r\n # temp subset, therefore no need to destroy in epilog\r\n SubsetCreatebyMDX( cTempSub, sMDX, '}Dimensions' , 1 );\r\n EndIf;\r\n \r\n # Loop through dimensions in subset created based on wildcard\r\n nCountDim = SubsetGetSize( '}Dimensions' , cTempSub );\r\n While( nCountDim >= 1 );\r\n sDim = SubsetGetElementName( '}Dimensions' , cTempSub, nCountDim );\r\n # Validate dimension name\r\n If( DimensionExists(sDim) = 0 );\r\n nErrors = 1;\r\n sMessage = Expand( 'Dimension %sDim% does not exist.' );\r\n LogOutput( 'ERROR', Expand( cMsgErrorContent ) );\r\n Else;\r\n If( pLogOutput = 1 );\r\n sMessage = Expand( 'Dimension %sDim% being processed....' );\r\n LogOutput( 'INFO', Expand( cMsgInfoContent ) );\r\n EndIf;\r\n # Loop through attributes in pAttr \r\n sAttrs = pAttr;\r\n nDelimiterIndexA = 1;\r\n sAttrDim = '}ElementAttributes_'|sDim ;\r\n sMdxAttr = '';\r\n While( nDelimiterIndexA <> 0 );\r\n\r\n nDelimiterIndexA = Scan( pDelim, sAttrs );\r\n If( nDelimiterIndexA = 0 );\r\n sAttr = sAttrs;\r\n Else;\r\n sAttr = Trim( SubSt( sAttrs, 1, nDelimiterIndexA - 1 ) );\r\n sAttrs = Trim( Subst( sAttrs, nDelimiterIndexA + Long(pDelim), Long( sAttrs ) ) );\r\n EndIf;\r\n\r\n # Validate if sDim has attributes\r\n IF( DimensionExists( '}ElementAttributes_'| sDim ) = 0 );\r\n sMessage = 'Dimension ' | sDim | ' has no attributes.';\r\n LogOutput( 'INFO' , Expand( cMsgInfoContent ) );\r\n ElseIf( sAttr @= '*' );\r\n # Delete attribute cube and dimension if pAttr is blank or set to ALL\r\n CubeDestroy( sAttrDim );\r\n DimensionDestroy( sAttrDim );\r\n Else;\r\n # Create subset of attributes using Wildcard to loop through attributes in pAttr with wildcard\r\n sAttr = '\"'|sAttr|'\"';\r\n sMdxAttrPart = '{TM1FILTERBYPATTERN( {TM1SUBSETALL([ ' |sAttrDim| '])},'| sAttr| ')}';\r\n IF( sMdxAttr @= ''); \r\n sMdxAttr = sMdxAttrPart; \r\n ELSE;\r\n sMdxAttr = sMdxAttr | ' + ' | sMdxAttrPart;\r\n ENDIF;\r\n If( SubsetExists( sAttrDim, cTempSub ) = 1 );\r\n # If a delimited list of attr names includes wildcards then we may have to re-use the subset multiple times\r\n SubsetMDXSet( sAttrDim, cTempSub, sMdxAttr );\r\n Else;\r\n # temp subset, therefore no need to destroy in epilog\r\n SubsetCreatebyMDX( cTempSub, sMdxAttr, sAttrDim, 1 );\r\n EndIf;\r\n \r\n # Loop through subset of attributes created based on wildcard\r\n nCountAttr = SubsetGetSize( sAttrDim, cTempSub );\r\n While( nCountAttr >= 1 );\r\n sAttr = SubsetGetElementName( sAttrDim, cTempSub, nCountAttr );\r\n # Validate attribute name in sDim\r\n If( Dimix( sAttrDim , sAttr ) = 0 );\r\n sMessage = Expand('The %sAttr% attribute does NOT exist in the %sDim% dimension.');\r\n LogOutput( 'INFO' , Expand( cMsgInfoContent ) );\r\n Else;\r\n AttrDelete( sDim , sAttr ) ;\r\n If( pLogOutput = 1 );\r\n LogOutput( 'INFO', Expand( 'Attribute \"%sAttr%\" deleted from dimension %sDim%.' ) );\r\n EndIf;\r\n Endif;\r\n nCountAttr = nCountAttr - 1;\r\n End;\r\n Endif;\r\n \r\n End; \r\n EndIf;\r\n \r\n nCountDim = nCountDim - 1;\r\n End;\r\nEnd;\r\n\r\n### End Prolog ###", + "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.dim.attr.delete', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n\t 'pDim', '', 'pAttr', '', 'pDelim', '&', 'pCtrlObj', 0\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process can delete one or more attributes in one or more specified dimensions.\r\n#\r\n# Use case: Intended for development/prototyping.\r\n# 1. Clean up unused dimension attributes before going to production\r\n#\r\n# Note:\r\n# * Delimited lists and/or wild card(*) are acceptable for pDim & pAttr\r\n# * Multi-character wildcard \"*\" value for pAttr is evaluated as \"ALL\"\r\n# * You cannot specify \"*\" for **both** pDim and pAttr!\r\n#\r\n# Warning:\r\n# 1. As the process accepts wildcards USE WITH GREAT CARE! As if using wildcards for dimensions and attributes any matching attributes \r\n# in any matching dimensions will be removed from the system.\r\n# 2. Multi-character wildcard \"*\" value for pAttr is evaluated as \"ALL\". Setting pAttr to \"*\" will delete all attributes in the spacified dimension.\r\n#EndRegion @DOC\r\n\r\n### Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSub = cThisProcName |'_'| cTimeStamp |'_'| cRandomInt;\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncMsgInfoContent = 'User:%cUserName% Process:%cThisProcName% Message:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pDim:%pDim%, pAttr:%pAttr%, pDelim:%pDelim%, pCtrlObj:%pCtrlObj%.';\r\n\r\n#################################################################################################\r\n#Region - Process Parameters\r\n\r\npJson = IF( JsonType( pJson ) @<> 'object', '{}', pJson );\r\nsMessages = '{\"Process\": \"'|GetProcessName()|'\", \"User\": \"'|TM1User()|'\", \"Info\": [\"Process: '''|GetProcessName()|''' run by User: '''|TM1User()|'''.\"], \"Error\": []}';\r\npDefaultParameters = '{\r\n \"pAttr\": null,\r\n \"pDelim\": \"&\",\r\n \"pDim\": null,\r\n \"pCtrlObj\": 0,\r\n \"pLogOutput\": 0,\r\n \"pStrictErrorHandling\": 0\r\n}';\r\n\r\npPassedParameters = '{\r\n \"pAttr\": '|StringToJson ( pAttr )|',\r\n \"pDelim\": '|StringToJson ( pDelim )|',\r\n \"pDim\": '|StringToJson ( pDim )|',\r\n \"pCtrlObj\": '|NumberToString( pCtrlObj )|',\r\n \"pLogOutput\": '|NumberToString( pLogOutput )|',\r\n \"pStrictErrorHandling\": '|NumberToString( pStrictErrorHandling )|'\r\n}';\r\n\r\npJson = JsonMergePatch( pPassedParameters, pJson );\r\n# String Parameters\r\npAttr = JsonToString( JsonGet( pJson, 'pAttr' ) );\r\npDelim = JsonToString( JsonGet( pJson, 'pDelim' ) );\r\npDim = JsonToString( JsonGet( pJson, 'pDim' ) );\r\n# Numeric Parameters\r\npCtrlObj = StringToNumber( JsonToString( JsonGet( pJson, 'pCtrlObj' ) ) );\r\npLogOutput = StringToNumber( JsonToString( JsonGet( pJson, 'pLogOutput' ) ) );\r\npStrictErrorHandling = StringToNumber( JsonToString( JsonGet( pJson, 'pStrictErrorHandling' ) ) );\r\n\r\n### Get the parameters that differ from the default\r\npDiffer = JsonDiff( pDefaultParameters, pJson );\r\nnSize = JsonSize( pDiffer );\r\nWHILE( nSize > 0 );\r\n nSize = nSize - 1;\r\n pDiffer = JsonReplace( pDiffer, '/'|NumberToString( nSize )|'/op', '\"add\"' );\r\nEND;\r\npJson = JsonPatch( '{}', pDiffer );\r\n\r\n### LogOutput parameters\r\nsMessages = JsonAdd( sMessages, '/Info/-', pJson );\r\nIF( pLogOutput = 1 );\r\n LogOutput('INFO', JsonToString( sMessages, '/Info/0', 0, ' ' ) );\r\nENDIF;\r\n\r\n#EndRegion - Process Parameters\r\n#################################################################################################\r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\n### Validate Parameters ###\r\nnErrors = 0;\r\n\r\n## Validate dimension\r\nIf( (Trim( pDim ) @= 'ALL' & Trim( pAttr ) @= 'ALL') % (Trim( pDim ) @= '*' & Trim( pAttr ) @= 'ALL') % (Trim( pDim ) @= 'ALL' & Trim( pAttr ) @= '*') % (Trim( pDim ) @= '*' & Trim( pAttr ) @= '*') );\r\n nErrors = 1;\r\n sMessage = 'Deleting all attrbitutes from all dimensions is not supported.';\r\n LogOutput( 'ERROR', Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\nIf( Trim( pDim ) @= '' );\r\n nErrors = 1;\r\n sMessage = 'No dimension specified.';\r\n LogOutput( 'ERROR', Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate attribute\r\nIf( Trim( pAttr ) @= '' );\r\n nErrors = 1;\r\n sMessage = 'No attribute specified.';\r\n LogOutput( 'ERROR', Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# If blank delimiter specified then convert to default\r\nIf( pDelim @= '' );\r\n pDelim = '&';\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors > 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n# Loop through dimensions in pDim and attributes in pAttr\r\nsDims = pDim;\r\nnDimDelimiterIndex = 1;\r\nsMdx = '';\r\n# Get 1st dimension\r\nWhile( nDimDelimiterIndex <> 0 );\r\n # Extract 1st dimension > sDim\r\n nDimDelimiterIndex = Scan( pDelim, sDims );\r\n If( nDimDelimiterIndex = 0 );\r\n sDim = sDims;\r\n Else;\r\n sDim = Trim( SubSt( sDims, 1, nDimDelimiterIndex - 1 ) );\r\n sDims = Trim( Subst( sDims, nDimDelimiterIndex + Long(pDelim), Long( sDims ) ) );\r\n EndIf;\r\n \r\n # Create subset of dimensions using Wildcard to loop through dimensions in pDim with wildcard\r\n sDimExp = '\"'|sDim|'\"';\r\n IF( pCtrlObj = 1 );\r\n sMdxPart = '{TM1FILTERBYPATTERN( EXCEPT( TM1SUBSETALL( [}Dimensions] ) , TM1FILTERBYPATTERN( TM1SUBSETALL( [}Dimensions] ) , \"*:*\") ) ,'| sDimExp | ')}';\r\n ELSE;\r\n sMdxPart = '{TM1FILTERBYPATTERN( EXCEPT( EXCEPT( TM1SUBSETALL( [}Dimensions] ) , TM1FILTERBYPATTERN( TM1SUBSETALL( [}Dimensions] ) , \"*:*\") ) , TM1FILTERBYPATTERN( TM1SUBSETALL( [}Dimensions] ) , \"}*\" ) ) ,'| sDimExp | ')}'; \r\n ENDIF;\r\n IF( sMdx @= ''); \r\n sMdx = sMdxPart; \r\n ELSE;\r\n sMdx = sMdx | ' + ' | sMdxPart;\r\n ENDIF;\r\n \r\n If( SubsetExists( '}Dimensions' , cTempSub ) = 1 );\r\n # If a delimited list of dim names includes wildcards then we may have to re-use the subset multiple times\r\n SubsetMDXSet( '}Dimensions' , cTempSub, sMDX );\r\n Else;\r\n # temp subset, therefore no need to destroy in epilog\r\n SubsetCreatebyMDX( cTempSub, sMDX, '}Dimensions' , 1 );\r\n EndIf;\r\n \r\n # Loop through dimensions in subset created based on wildcard\r\n nCountDim = SubsetGetSize( '}Dimensions' , cTempSub );\r\n While( nCountDim >= 1 );\r\n sDim = SubsetGetElementName( '}Dimensions' , cTempSub, nCountDim );\r\n # Validate dimension name\r\n If( DimensionExists(sDim) = 0 );\r\n nErrors = 1;\r\n sMessage = Expand( 'Dimension %sDim% does not exist.' );\r\n LogOutput( 'ERROR', Expand( cMsgErrorContent ) );\r\n Else;\r\n If( pLogOutput = 1 );\r\n sMessage = Expand( 'Dimension %sDim% being processed....' );\r\n LogOutput( 'INFO', Expand( cMsgInfoContent ) );\r\n EndIf;\r\n # Loop through attributes in pAttr \r\n sAttrs = pAttr;\r\n nDelimiterIndexA = 1;\r\n sAttrDim = '}ElementAttributes_'|sDim ;\r\n sMdxAttr = '';\r\n While( nDelimiterIndexA <> 0 );\r\n\r\n nDelimiterIndexA = Scan( pDelim, sAttrs );\r\n If( nDelimiterIndexA = 0 );\r\n sAttr = sAttrs;\r\n Else;\r\n sAttr = Trim( SubSt( sAttrs, 1, nDelimiterIndexA - 1 ) );\r\n sAttrs = Trim( Subst( sAttrs, nDelimiterIndexA + Long(pDelim), Long( sAttrs ) ) );\r\n EndIf;\r\n\r\n # Validate if sDim has attributes\r\n IF( DimensionExists( '}ElementAttributes_'| sDim ) = 0 );\r\n sMessage = 'Dimension ' | sDim | ' has no attributes.';\r\n LogOutput( 'INFO' , Expand( cMsgInfoContent ) );\r\n ElseIf( sAttr @= '*' );\r\n # Delete attribute cube and dimension if pAttr is blank or set to ALL\r\n CubeDestroy( sAttrDim );\r\n DimensionDestroy( sAttrDim );\r\n Else;\r\n # Create subset of attributes using Wildcard to loop through attributes in pAttr with wildcard\r\n sAttr = '\"'|sAttr|'\"';\r\n sMdxAttrPart = '{TM1FILTERBYPATTERN( {TM1SUBSETALL([ ' |sAttrDim| '])},'| sAttr| ')}';\r\n IF( sMdxAttr @= ''); \r\n sMdxAttr = sMdxAttrPart; \r\n ELSE;\r\n sMdxAttr = sMdxAttr | ' + ' | sMdxAttrPart;\r\n ENDIF;\r\n If( SubsetExists( sAttrDim, cTempSub ) = 1 );\r\n # If a delimited list of attr names includes wildcards then we may have to re-use the subset multiple times\r\n SubsetMDXSet( sAttrDim, cTempSub, sMdxAttr );\r\n Else;\r\n # temp subset, therefore no need to destroy in epilog\r\n SubsetCreatebyMDX( cTempSub, sMdxAttr, sAttrDim, 1 );\r\n EndIf;\r\n \r\n # Loop through subset of attributes created based on wildcard\r\n nCountAttr = SubsetGetSize( sAttrDim, cTempSub );\r\n While( nCountAttr >= 1 );\r\n sAttr = SubsetGetElementName( sAttrDim, cTempSub, nCountAttr );\r\n # Validate attribute name in sDim\r\n If( Dimix( sAttrDim , sAttr ) = 0 );\r\n sMessage = Expand('The %sAttr% attribute does NOT exist in the %sDim% dimension.');\r\n LogOutput( 'INFO' , Expand( cMsgInfoContent ) );\r\n Else;\r\n AttrDelete( sDim , sAttr ) ;\r\n If( pLogOutput = 1 );\r\n LogOutput( 'INFO', Expand( 'Attribute \"%sAttr%\" deleted from dimension %sDim%.' ) );\r\n EndIf;\r\n Endif;\r\n nCountAttr = nCountAttr - 1;\r\n End;\r\n Endif;\r\n \r\n End; \r\n EndIf;\r\n \r\n nCountDim = nCountDim - 1;\r\n End;\r\nEnd;\r\n\r\n### End Prolog ###", "MetadataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "DataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "EpilogProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n### Return code & final error message handling\r\nIf( nErrors > 0 );\r\n sMessage = 'the process incurred at least 1 error. Please see above lines in this file for more details.';\r\n nProcessReturnCode = 0;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% Process:%cThisProcName% completed with errors. Check tm1server.log for details.' );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n EndIf;\r\nElse;\r\n sProcessAction = Expand( 'Process:%cThisProcName% successfully deleted attribute(s) %pAttr% from dimension(s) %pDim%.' );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% %sProcessAction%' );\r\n nProcessReturnCode = 1;\r\n If( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( sProcessAction ) ); \r\n EndIf;\r\nEndIf;\r\n\r\n### End Epilog ###\r\n", @@ -10,41 +10,47 @@ "Type": "None" }, "Parameters": [ - { - "Name": "pLogOutput", - "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, - { - "Name": "pStrictErrorHandling", - "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, { "Name": "pDim", - "Prompt": "REQUIRED: dimension name, parameter accepts delimited list and wildcards(*).", + "Prompt": "REQUIRED: Delimited list of dimensions", "Value": "", "Type": "String" }, { "Name": "pAttr", - "Prompt": "REQUIRED: attribute name, parameter accepts delimited list and wildcards (* = ALL).", + "Prompt": "REQUIRED: Delimited list of attribute names", "Value": "", "Type": "String" }, { "Name": "pDelim", - "Prompt": "OPTIONAL: delimiter character for attribute list. (Defaults to & if blank)", + "Prompt": "OPTIONAL: Delimiter for list parameters (Default = '&')", "Value": "&", "Type": "String" }, { "Name": "pCtrlObj", - "Prompt": "REQUIRED: Include control dimensions (1 = include, 0 = not include)", + "Prompt": "OPTIONAL: OPTIONAL: Allow modification of control objects (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" + }, + { + "Name": "pLogOutput", + "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pStrictErrorHandling", + "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pJson", + "Prompt": "OPTIONAL: JSON Object with process parameter values. This will overwrite user passed parameters for all included parameters.", + "Value": "{}", + "Type": "String" } ], "Variables": [], diff --git a/bedrock_processes_json/}bedrock.dim.attr.importfromfile.json b/bedrock_processes_json/}bedrock.dim.attr.importfromfile.json index 77793d3..188be5b 100644 --- a/bedrock_processes_json/}bedrock.dim.attr.importfromfile.json +++ b/bedrock_processes_json/}bedrock.dim.attr.importfromfile.json @@ -1,6 +1,6 @@ { "Name": "}bedrock.dim.attr.importfromfile", - "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.dim.attr.importfromfile', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pDim', '', 'pSrcDir', '', 'pSrcFile', '',\r\n \t'pTitleRows', 1, 'pDelim', ',', 'pQuote', '\"'\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process will create Attributes of the dimension from a file.\r\n\r\n# Use case: Intended for development/prototyping. \r\n#1/ Add multiple dimension attributes of different types.\r\n\r\n# Note:\r\n# The file format is as per the dimension export file applied to an }ElementsAttributes dimension.\r\n# Naturally, a valid diension name (pDim) is mandatory otherwise the process will abort.\r\n# Also, valid path (pSrcDir) & file name (pSrcFile) are mandatory otherwise the process will abort.\r\n#EndRegion @DOC\r\n\r\n### Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pDim:%pDim%, pSrcDir:%pSrcDir%, pSrcFile:%pSrcFile%, pTitleRows:%pTitleRows%, pDelim:%pDelim%, pQuote:%pQuote%.'; \r\ncLenASCIICode = 3;\r\n\r\npDelimiter = TRIM(pDelim);\r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\nnMetaDataCount = 0;\r\n\r\n### Validate Parameters ###\r\n\r\nnErrors = 0;\r\n\r\n## check operating system\r\nIf( SubSt( GetProcessErrorFileDirectory, 2, 1 ) @= ':' );\r\n sOS = 'Windows';\r\n sOSDelim = '\\';\r\nElseIf( Scan( '/', GetProcessErrorFileDirectory ) > 0 );\r\n sOS = 'Linux';\r\n sOSDelim = '/';\r\nElse;\r\n sOS = 'Windows';\r\n sOSDelim = '\\';\r\nEndIf;\r\n\r\n# Validate source dir\r\nIf(Trim( pSrcDir ) @= '' );\r\n pSrcDir = GetProcessErrorFileDirectory;\r\nEndIf;\r\nIf( SubSt( pSrcDir, Long( pSrcDir ), 1 ) @= sOSDelim );\r\n pSrcDir = SubSt( pSrcDir, 1, Long( pSrcDir ) -1 );\r\nEndIf;\r\nIf( FileExists( pSrcDir ) = 0 );\r\n nErrors = 1;\r\n sMessage = 'Invalid source directory specified: folder does not exist.';\r\n DataSourceType = 'NULL';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\npSrcDir = pSrcDir | sOSDelim;\r\n\r\n# Validate source file\r\nsFile = pSrcDir | pSrcFile;\r\nIF ( Trim ( pSrcFile ) @= '' );\r\n nErrors = 1;\r\n sMessage = 'No source file specified.';\r\n DataSourceType = 'NULL';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( FileExists( sFile ) = 0 );\r\n nErrors = 1;\r\n sMessage = 'Invalid path or source file specified: It does not exist.';\r\n DataSourceType = 'NULL';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate dimension\r\nIf( Trim( pDim ) @= '' );\r\n nErrors = 1;\r\n sMessage = 'No dimension specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( DimensionExists( pDim ) = 0 );\r\n nErrors = 1;\r\n sMessage = 'Dimension: ' | pDim | ' does not exist on server.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate file delimiter & quote character\r\nIf( pDelimiter @= '' );\r\n pDelimiter = ',';\r\nElse;\r\n # If length of pDelimiter is exactly 3 chars and each of them is decimal digit, then the pDelimiter is entered as ASCII code\r\n nValid = 0;\r\n If ( LONG(pDelimiter) = cLenASCIICode );\r\n nChar = 1;\r\n While ( nChar <= cLenASCIICode );\r\n If( CODE( pDelimiter, nChar )>=CODE( '0', 1 ) & CODE( pDelimiter, nChar )<=CODE( '9', 1 ) );\r\n nValid = 1;\r\n Else;\r\n nValid = 0;\r\n EndIf;\r\n nChar = nChar + 1;\r\n End;\r\n EndIf;\r\n If ( nValid<>0 );\r\n pDelimiter=CHAR(StringToNumber( pDelimiter ));\r\n Else;\r\n pDelimiter = SubSt( Trim( pDelimiter ), 1, 1 );\r\n EndIf;\r\nEndIf;\r\nIf( pQuote @= '' );\r\n ## Use no quote character \r\nElse;\r\n # If length of pQuote is exactly 3 chars and each of them is decimal digit, then the pQuote is entered as ASCII code\r\n nValid = 0;\r\n If ( LONG(pQuote) = cLenASCIICode );\r\n nChar = 1;\r\n While ( nChar <= cLenASCIICode );\r\n If( CODE( pQuote, nChar ) >= CODE( '0', 1 ) & CODE( pQuote, nChar ) <= CODE( '9', 1 ) );\r\n nValid = 1;\r\n Else;\r\n nValid = 0;\r\n EndIf;\r\n nChar = nChar + 1;\r\n End;\r\n EndIf;\r\n If ( nValid<>0 );\r\n pQuote=CHAR(StringToNumber( pQuote ));\r\n Else;\r\n pQuote = SubSt( Trim( pQuote ), 1, 1 );\r\n EndIf;\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n### Assign Datasource ###\r\n\r\nDataSourceType = 'CHARACTERDELIMITED';\r\nDatasourceNameForServer = sFile;\r\nDatasourceNameForClient = sFile;\r\nDatasourceASCIIHeaderRecords= pTitleRows;\r\nDatasourceASCIIDelimiter = pDelimiter;\r\nDatasourceASCIIQuoteCharacter= pQuote;\r\n\r\n### End Prolog ###", + "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.dim.attr.importfromfile', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pDim', '', 'pSrcDir', '', 'pSrcFile', '',\r\n \t'pTitleRows', 1, 'pDelim', ',', 'pQuote', '\"'\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process will create Attributes of the dimension from a file.\r\n\r\n# Use case: Intended for development/prototyping. \r\n#1/ Add multiple dimension attributes of different types.\r\n\r\n# Note:\r\n# The file format is as per the dimension export file applied to an }ElementsAttributes dimension.\r\n# Naturally, a valid diension name (pDim) is mandatory otherwise the process will abort.\r\n# Also, valid path (pSrcDir) & file name (pSrcFile) are mandatory otherwise the process will abort.\r\n#EndRegion @DOC\r\n\r\n### Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pDim:%pDim%, pSrcDir:%pSrcDir%, pSrcFile:%pSrcFile%, pTitleRows:%pTitleRows%, pDelim:%pDelim%, pQuote:%pQuote%.'; \r\ncLenASCIICode = 3;\r\n\r\n#################################################################################################\r\n#Region - Process Parameters\r\n\r\npJson = IF( JsonType( pJson ) @<> 'object', '{}', pJson );\r\nsMessages = '{\"Process\": \"'|GetProcessName()|'\", \"User\": \"'|TM1User()|'\", \"Info\": [\"Process: '''|GetProcessName()|''' run by User: '''|TM1User()|'''.\"], \"Error\": []}';\r\npDefaultParameters = '{\r\n \"pDelim\": \"&\",\r\n \"pDim\": null,\r\n \"pQuote\": \"\"\",\r\n \"pSrcDir\": \"\",\r\n \"pSrcFile\": \"\",\r\n \"pLogOutput\": 0,\r\n \"pStrictErrorHandling\": 0,\r\n \"pTitleRows\": 1\r\n}';\r\n\r\npPassedParameters = '{\r\n \"pDelim\": '|StringToJson ( pDelim )|',\r\n \"pDim\": '|StringToJson ( pDim )|',\r\n \"pQuote\": '|StringToJson ( pQuote )|',\r\n \"pSrcDir\": '|StringToJson ( pSrcDir )|',\r\n \"pSrcFile\": '|StringToJson ( pSrcFile )|',\r\n \"pLogOutput\": '|NumberToString( pLogOutput )|',\r\n \"pStrictErrorHandling\": '|NumberToString( pStrictErrorHandling )|',\r\n \"pTitleRows\": '|NumberToString( pTitleRows )|'\r\n}';\r\n\r\npJson = JsonMergePatch( pPassedParameters, pJson );\r\n# String Parameters\r\npDelim = JsonToString( JsonGet( pJson, 'pDelim' ) );\r\npDim = JsonToString( JsonGet( pJson, 'pDim' ) );\r\npQuote = JsonToString( JsonGet( pJson, 'pQuote' ) );\r\npSrcDir = JsonToString( JsonGet( pJson, 'pSrcDir' ) );\r\npSrcFile = JsonToString( JsonGet( pJson, 'pSrcFile' ) );\r\n# Numeric Parameters\r\npLogOutput = StringToNumber( JsonToString( JsonGet( pJson, 'pLogOutput' ) ) );\r\npStrictErrorHandling = StringToNumber( JsonToString( JsonGet( pJson, 'pStrictErrorHandling' ) ) );\r\npTitleRows = StringToNumber( JsonToString( JsonGet( pJson, 'pTitleRows' ) ) );\r\n\r\n### Get the parameters that differ from the default\r\npDiffer = JsonDiff( pDefaultParameters, pJson );\r\nnSize = JsonSize( pDiffer );\r\nWHILE( nSize > 0 );\r\n nSize = nSize - 1;\r\n pDiffer = JsonReplace( pDiffer, '/'|NumberToString( nSize )|'/op', '\"add\"' );\r\nEND;\r\npJson = JsonPatch( '{}', pDiffer );\r\n\r\n### LogOutput parameters\r\nsMessages = JsonAdd( sMessages, '/Info/-', pJson );\r\nIF( pLogOutput = 1 );\r\n LogOutput('INFO', JsonToString( sMessages, '/Info/0', 0, ' ' ) );\r\nENDIF;\r\n\r\n#EndRegion - Process Parameters\r\n#################################################################################################\r\n\r\npDelimiter = TRIM(pDelim);\r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\nnMetaDataCount = 0;\r\n\r\n### Validate Parameters ###\r\n\r\nnErrors = 0;\r\n\r\n## check operating system\r\nIf( SubSt( GetProcessErrorFileDirectory, 2, 1 ) @= ':' );\r\n sOS = 'Windows';\r\n sOSDelim = '\\';\r\nElseIf( Scan( '/', GetProcessErrorFileDirectory ) > 0 );\r\n sOS = 'Linux';\r\n sOSDelim = '/';\r\nElse;\r\n sOS = 'Windows';\r\n sOSDelim = '\\';\r\nEndIf;\r\n\r\n# Validate source dir\r\nIf(Trim( pSrcDir ) @= '' );\r\n pSrcDir = GetProcessErrorFileDirectory;\r\nEndIf;\r\nIf( SubSt( pSrcDir, Long( pSrcDir ), 1 ) @= sOSDelim );\r\n pSrcDir = SubSt( pSrcDir, 1, Long( pSrcDir ) -1 );\r\nEndIf;\r\nIf( FileExists( pSrcDir ) = 0 );\r\n nErrors = 1;\r\n sMessage = 'Invalid source directory specified: folder does not exist.';\r\n DataSourceType = 'NULL';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\npSrcDir = pSrcDir | sOSDelim;\r\n\r\n# Validate source file\r\nsFile = pSrcDir | pSrcFile;\r\nIF ( Trim ( pSrcFile ) @= '' );\r\n nErrors = 1;\r\n sMessage = 'No source file specified.';\r\n DataSourceType = 'NULL';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( FileExists( sFile ) = 0 );\r\n nErrors = 1;\r\n sMessage = 'Invalid path or source file specified: It does not exist.';\r\n DataSourceType = 'NULL';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate dimension\r\nIf( Trim( pDim ) @= '' );\r\n nErrors = 1;\r\n sMessage = 'No dimension specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( DimensionExists( pDim ) = 0 );\r\n nErrors = 1;\r\n sMessage = 'Dimension: ' | pDim | ' does not exist on server.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate file delimiter & quote character\r\nIf( pDelimiter @= '' );\r\n pDelimiter = ',';\r\nElse;\r\n # If length of pDelimiter is exactly 3 chars and each of them is decimal digit, then the pDelimiter is entered as ASCII code\r\n nValid = 0;\r\n If ( LONG(pDelimiter) = cLenASCIICode );\r\n nChar = 1;\r\n While ( nChar <= cLenASCIICode );\r\n If( CODE( pDelimiter, nChar )>=CODE( '0', 1 ) & CODE( pDelimiter, nChar )<=CODE( '9', 1 ) );\r\n nValid = 1;\r\n Else;\r\n nValid = 0;\r\n EndIf;\r\n nChar = nChar + 1;\r\n End;\r\n EndIf;\r\n If ( nValid<>0 );\r\n pDelimiter=CHAR(StringToNumber( pDelimiter ));\r\n Else;\r\n pDelimiter = SubSt( Trim( pDelimiter ), 1, 1 );\r\n EndIf;\r\nEndIf;\r\nIf( pQuote @= '' );\r\n ## Use no quote character \r\nElse;\r\n # If length of pQuote is exactly 3 chars and each of them is decimal digit, then the pQuote is entered as ASCII code\r\n nValid = 0;\r\n If ( LONG(pQuote) = cLenASCIICode );\r\n nChar = 1;\r\n While ( nChar <= cLenASCIICode );\r\n If( CODE( pQuote, nChar ) >= CODE( '0', 1 ) & CODE( pQuote, nChar ) <= CODE( '9', 1 ) );\r\n nValid = 1;\r\n Else;\r\n nValid = 0;\r\n EndIf;\r\n nChar = nChar + 1;\r\n End;\r\n EndIf;\r\n If ( nValid<>0 );\r\n pQuote=CHAR(StringToNumber( pQuote ));\r\n Else;\r\n pQuote = SubSt( Trim( pQuote ), 1, 1 );\r\n EndIf;\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n### Assign Datasource ###\r\n\r\nDataSourceType = 'CHARACTERDELIMITED';\r\nDatasourceNameForServer = sFile;\r\nDatasourceNameForClient = sFile;\r\nDatasourceASCIIHeaderRecords= pTitleRows;\r\nDatasourceASCIIDelimiter = pDelimiter;\r\nDatasourceASCIIQuoteCharacter= pQuote;\r\n\r\n### End Prolog ###", "MetadataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n## Metatdata Count\r\nnMetaDataCount = nMetaDataCount + 1;\r\n\r\n### Write data from source file to target dimension ###\r\nsAttrType = Upper(SubSt( vAttrType, 1, 1 ));\r\n\r\n### Validate Record ###\r\nIF(\r\n sAttrType @= 'A' %\r\n sAttrType @= 'N' %\r\n sAttrType @= 'S' );\r\n ## Continute\r\nELSE;\r\n sMessage = 'Invalid attribute type.';\r\n ITEMSKIP;\r\nENDIF;\r\n\r\nAttrInsert( pDim, '', vAttr, sAttrType );\r\n\r\n### End Metadata ###", "DataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "EpilogProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n### Return code & final error message handling\r\nIf( nErrors > 0 );\r\n sMessage = 'the process incurred at least 1 error. Please see above lines in this file for more details.';\r\n nProcessReturnCode = 0;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% Process:%cThisProcName% completed with errors. Check tm1server.log for details.' );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n EndIf;\r\nElse;\r\n sProcessAction = Expand( 'Process:%cThisProcName% successfully created attributes in %pDim% from file %pSrcFile%.' );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% %sProcessAction%' );\r\n nProcessReturnCode = 1;\r\n If( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( sProcessAction ) ); \r\n EndIf;\r\nEndIf;\r\n\r\n### End Epilog ###", @@ -18,53 +18,59 @@ "dataSourceNameForServer": "D:/TM1Models/Bedrock.v4/Data/Attribute.csv" }, "Parameters": [ - { - "Name": "pLogOutput", - "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, - { - "Name": "pStrictErrorHandling", - "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, { "Name": "pDim", - "Prompt": "REQUIRED: dimension name", + "Prompt": "REQUIRED: Delimited list of dimensions", "Value": "", "Type": "String" }, { "Name": "pSrcDir", - "Prompt": "REQUIRED: Source Directory", + "Prompt": "OPTIONAL: File directory (Default = GetProcessErrorFileDirectory)", "Value": "", "Type": "String" }, { "Name": "pSrcFile", - "Prompt": "REQUIRED: Source File Name", + "Prompt": "OPTIONAL: File name (Default = pCube | '_Export.csv')", "Value": "", "Type": "String" }, { "Name": "pTitleRows", - "Prompt": "OPTIONAL: Number of Title Rows to Skip (default = 1)", + "Prompt": "OPTIONAL: Number of title rows to skip (Default = 1)", "Value": 1, "Type": "Numeric" }, { "Name": "pDelim", - "Prompt": "OPTIONAL: File Delimiter Character (Default=comma, exactly 3 digits = ASCII code)", - "Value": ",", + "Prompt": "OPTIONAL: Delimiter for list parameters (Default = '&')", + "Value": "&", "Type": "String" }, { "Name": "pQuote", - "Prompt": "OPTIONAL: Quote Character (Accepts empty quote, exactly 3 digits = ASCII code)", + "Prompt": "OPTIONAL: Quote character (2 or 3 digits = ASCII code. Default = '\"')", "Value": "\"", "Type": "String" + }, + { + "Name": "pLogOutput", + "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pStrictErrorHandling", + "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pJson", + "Prompt": "OPTIONAL: JSON Object with process parameter values. This will overwrite user passed parameters for all included parameters.", + "Value": "{}", + "Type": "String" } ], "Variables": [ diff --git a/bedrock_processes_json/}bedrock.dim.attr.swapalias.json b/bedrock_processes_json/}bedrock.dim.attr.swapalias.json index a979e42..24ed00f 100644 --- a/bedrock_processes_json/}bedrock.dim.attr.swapalias.json +++ b/bedrock_processes_json/}bedrock.dim.attr.swapalias.json @@ -10,28 +10,34 @@ "Type": "None" }, "Parameters": [ + { + "Name": "pDim", + "Prompt": "REQUIRED: Delimited list of dimensions", + "Value": "", + "Type": "String" + }, + { + "Name": "pAlias", + "Prompt": "REQUIRED: Alias name", + "Value": "", + "Type": "String" + }, { "Name": "pLogOutput", - "Prompt": "REQUIRED: True or False (Boolean True = 1)", + "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" }, { "Name": "pStrictErrorHandling", - "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean True = 1)", + "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" }, { - "Name": "pDim", - "Prompt": "REQUIRED: Dimension name", - "Value": "", - "Type": "String" - }, - { - "Name": "pAlias", - "Prompt": "REQUIRED: Alias", - "Value": "", + "Name": "pJson", + "Prompt": "OPTIONAL: JSON Object with process parameter values. This will overwrite user passed parameters.", + "Value": "{}", "Type": "String" } ], diff --git a/bedrock_processes_json/}bedrock.dim.clone.json b/bedrock_processes_json/}bedrock.dim.clone.json index 9e6b8c4..e6acdb3 100644 --- a/bedrock_processes_json/}bedrock.dim.clone.json +++ b/bedrock_processes_json/}bedrock.dim.clone.json @@ -1,6 +1,6 @@ { "Name": "}bedrock.dim.clone", - "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.dim.clone', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pSrcDim', '', 'pTgtDim', '', 'pHier', '*',\r\n \t'pAttr', 0, 'pUnwind', 0, 'pDelim', '&'\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process can clone a source dimension and all the Hierarchies.\r\n\r\n# Use case: Intended for development/prototyping.\r\n# 1/ Replicate a dimension with it's hierarchies for testing.\r\n\r\n# Note:\r\n# If the target dimension:hierarchy already exists then it will be overwritten.\r\n# Naturally, a valid source dimension name (pSrcDim) is mandatory otherwise the process will abort.\r\n#EndRegion @DOC\r\n\r\n### Global Variables\r\nStringGlobalVariable ('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode = 0;\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncSubset = cThisProcName |'_'| cTimeStamp |'_'| cRandomInt;\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = '%cThisProcName% : %sMessage% : %cUserName%';\r\ncMsgInfoContent = 'User:%cUserName% Process:%cThisProcName% Message:%sMessage%';\r\ncLogInfo = '***Parameters for Process:%cThisProcName% for pSrcDim:%pSrcDim%, pTgtDim:%pTgtDim%, pHier:%pHier%, pAttr:%pAttr%, pUnwind:%pUnwind%, pDelim:%pDelim%.';\r\ncLangDim = '}Cultures';\r\nnNumLang = DimSiz( cLangDim );\r\n\r\n## LogOutput parameters\r\nIF ( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\n### Validate Parameters ###\r\nnErrors = 0;\r\n\r\nIf( Scan( '*', pSrcDim )=0 & Scan( '?', pSrcDim )=0 & Scan( pDelim, pSrcDim )=0 & Scan( ':', pSrcDim ) > 0 & pHier @= '' );\r\n # A hierarchy has been passed as dimension. Handle the input error by splitting dim:hier into dimension & hierarchy\r\n pHier = SubSt( pSrcDim, Scan( ':', pSrcDim ) + 1, Long( pSrcDim ) );\r\n pSrcDim = SubSt( pSrcDim, 1, Scan( ':', pSrcDim ) - 1 );\r\nEndIf;\r\n\r\n## Validate dimension\r\nIF( Trim( pSrcDim ) @= '' );\r\n nErrors = 1;\r\n sMessage = 'No source dimension specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIF( DimensionExists( pSrcDim ) = 0 );\r\n nErrors = 1;\r\n sMessage = 'Invalid source dimension: ' | pSrcDim;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\nIf( pTgtDim @= '' % pTgtDim @= pSrcDim );\r\n pTgtDim = pSrcDim | '_Clone';\r\nEndIf;\r\n\r\n# Validate hierarchy\r\nIF( Scan( '*', pSrcDim )=0 & Scan( '?', pSrcDim )=0 & Scan( pDelim, pSrcDim )=0 & pHier @= '');\r\n pHier = pSrcDim;\r\nElseIf( Scan( '*', pHier )=0 & Scan( '?', pHier )=0 & Scan( pDelim, pHier )=0 & pHier @<> '' & HierarchyExists(pSrcDim, pHier) = 0 );\r\n nErrors = 1;\r\n sMessage = 'Invalid dimension hierarchy: ' | pHier;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndif;\r\n\r\nIf( Trim( pHier ) @= '' );\r\n ## use same name as Dimension. Since wildcards are allowed, this is managed inside the code below\r\nEndIf;\r\n\r\n## Default delimiter\r\nIf( pDelim @= '' );\r\n pDelim = '&';\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n### Create target dimension ###\r\n\r\nIf(DimensionExists( pTgtDim ) = 0 );\r\n DimensionCreate( pTgtDim );\r\nElse;\r\n IF(pUnwind = 1 );\r\n nRet = ExecuteProcess('}bedrock.hier.unwind',\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pDim', pTgtDim,\r\n 'pHier', pTgtDim,\r\n 'pConsol', '*',\r\n 'pRecursive', 1\r\n );\r\n ELSEIF(pUnwind = 2 );\r\n # Do nothing;\r\n ELSE;\r\n DimensionDeleteAllElements( pTgtDim );\r\n EndIf;\r\nEndIf;\r\n\r\n### Set the target Sort Order ###\r\n# CellGetS to }DimensionProperties cube removed. Placeholder as expecting a TI function to be made available to be able to read these properties\r\n#sSortElementsType = CELLGETS( '}DimensionProperties', pSrcDim, 'SORTELEMENTSTYPE');\r\n#sSortElementsSense = CELLGETS( '}DimensionProperties', pSrcDim, 'SORTELEMENTSSENSE');\r\n#sSortComponentsType = CELLGETS( '}DimensionProperties', pSrcDim, 'SORTCOMPONENTSTYPE');\r\n#sSortComponentsSense = CELLGETS( '}DimensionProperties', pSrcDim, 'SORTCOMPONENTSSENSE');\r\n\r\n# DimensionSortOrder( pTgtDim, sSortComponentsType, sSortComponentsSense, sSortElementsType , sSortElementsSense);\r\n\r\n\r\nnSourceDimSize = DIMSIZ( pSrcDim );\r\nnIndex = 1;\r\nWHILE( nIndex <= nSourceDimSize );\r\n sElName = DIMNM( pSrcDim, nIndex);\r\n sElType = DTYPE( pSrcDim, sElName);\r\n \r\n DimensionElementInsert( pTgtDim, '', sElName, sElType );\r\n\r\n nIndex = nIndex + 1;\r\nEND;\r\n\r\n### Assign Data Source ###\r\nDatasourceNameForServer = pSrcDim;\r\nDatasourceNameForClient = pSrcDim;\r\nDataSourceType = 'SUBSET';\r\nDatasourceDimensionSubset = 'ALL';\r\n\r\n\r\n### Replicate Attributes ###\r\n# Note: DType on Attr dim returns \"AS\", \"AN\" or \"AA\" need to strip off leading \"A\"\r\nsAttrDim = '}ElementAttributes_' | pSrcDim;\r\nsAttrLoc = '}LocalizedElementAttributes_' | pSrcDim;\r\nsAttrTargetDim = '}ElementAttributes_' | pTgtDim;\r\nsAttrLocTarget = '}LocalizedElementAttributes_' | pTgtDim;\r\n\r\nIf( pAttr = 1 & DimensionExists( sAttrDim ) = 1 );\r\n nNumAttrs = DimSiz( sAttrDim );\r\n nCount = 1;\r\n While( nCount <= nNumAttrs );\r\n sAttrName = DimNm( sAttrDim, nCount );\r\n sAttCheck = SubSt( DTYPE( sAttrDim, sAttrName ), 1, 1 );\r\n IF (sAttCheck @= 'A');\r\n sAttrType = SubSt( DTYPE( sAttrDim, sAttrName ), 2, 1 );\r\n Else;\r\n sAttrType = sAttcheck;\r\n EndIf; \r\n \r\n If ( DimensionExists( sAttrTargetDim ) = 0);\r\n AttrInsert(pTgtDim,'',sAttrName,sAttrType );\r\n ElseIF(DimIx(sAttrTargetDim, sAttrName) = 0);\r\n AttrInsert(pTgtDim,'',sAttrName,sAttrType );\r\n Endif;\r\n \r\n nCount = nCount + 1;\r\n End;\r\nEndIf;\r\n\r\n\r\n### End Prolog ###", + "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.dim.clone', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pSrcDim', '', 'pTgtDim', '', 'pHier', '*',\r\n \t'pAttr', 0, 'pUnwind', 0, 'pDelim', '&'\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process can clone a source dimension and all the Hierarchies.\r\n\r\n# Use case: Intended for development/prototyping.\r\n# 1/ Replicate a dimension with it's hierarchies for testing.\r\n\r\n# Note:\r\n# If the target dimension:hierarchy already exists then it will be overwritten.\r\n# Naturally, a valid source dimension name (pSrcDim) is mandatory otherwise the process will abort.\r\n#EndRegion @DOC\r\n\r\n### Global Variables\r\nStringGlobalVariable ('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode = 0;\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncSubset = cThisProcName |'_'| cTimeStamp |'_'| cRandomInt;\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = '%cThisProcName% : %sMessage% : %cUserName%';\r\ncMsgInfoContent = 'User:%cUserName% Process:%cThisProcName% Message:%sMessage%';\r\ncLogInfo = '***Parameters for Process:%cThisProcName% for pSrcDim:%pSrcDim%, pTgtDim:%pTgtDim%, pHier:%pHier%, pAttr:%pAttr%, pUnwind:%pUnwind%, pDelim:%pDelim%.';\r\ncLangDim = '}Cultures';\r\nnNumLang = DimSiz( cLangDim );\r\n\r\n#################################################################################################\r\n#Region - Process Parameters\r\n\r\npJson = IF( JsonType( pJson ) @<> 'object', '{}', pJson );\r\nsMessages = '{\"Process\": \"'|GetProcessName()|'\", \"User\": \"'|TM1User()|'\", \"Info\": [\"Process: '''|GetProcessName()|''' run by User: '''|TM1User()|'''.\"], \"Error\": []}';\r\npDefaultParameters = '{\r\n \"pDelim\": \"&\",\r\n \"pHier\": \"*\",\r\n \"pSrcDim\": null,\r\n \"pTgtDim\": \"\",\r\n \"pAttr\": 0,\r\n \"pLogOutput\": 0,\r\n \"pStrictErrorHandling\": 0,\r\n \"pSub\": 0,\r\n \"pUnwind\": 0\r\n}';\r\n\r\npPassedParameters = '{\r\n \"pDelim\": '|StringToJson ( pDelim )|',\r\n \"pHier\": '|StringToJson ( pHier )|',\r\n \"pSrcDim\": '|StringToJson ( pSrcDim )|',\r\n \"pTgtDim\": '|StringToJson ( pTgtDim )|',\r\n \"pAttr\": '|NumberToString( pAttr )|',\r\n \"pLogOutput\": '|NumberToString( pLogOutput )|',\r\n \"pStrictErrorHandling\": '|NumberToString( pStrictErrorHandling )|',\r\n \"pSub\": '|NumberToString( pSub )|',\r\n \"pUnwind\": '|NumberToString( pUnwind )|'\r\n}';\r\n\r\npJson = JsonMergePatch( pPassedParameters, pJson );\r\n# String Parameters\r\npDelim = JsonToString( JsonGet( pJson, 'pDelim' ) );\r\npHier = JsonToString( JsonGet( pJson, 'pHier' ) );\r\npSrcDim = JsonToString( JsonGet( pJson, 'pSrcDim' ) );\r\npTgtDim = JsonToString( JsonGet( pJson, 'pTgtDim' ) );\r\n# Numeric Parameters\r\npAttr = StringToNumber( JsonToString( JsonGet( pJson, 'pAttr' ) ) );\r\npLogOutput = StringToNumber( JsonToString( JsonGet( pJson, 'pLogOutput' ) ) );\r\npStrictErrorHandling = StringToNumber( JsonToString( JsonGet( pJson, 'pStrictErrorHandling' ) ) );\r\npSub = StringToNumber( JsonToString( JsonGet( pJson, 'pSub' ) ) );\r\npUnwind = StringToNumber( JsonToString( JsonGet( pJson, 'pUnwind' ) ) );\r\n\r\n### Get the parameters that differ from the default\r\npDiffer = JsonDiff( pDefaultParameters, pJson );\r\nnSize = JsonSize( pDiffer );\r\nWHILE( nSize > 0 );\r\n nSize = nSize - 1;\r\n pDiffer = JsonReplace( pDiffer, '/'|NumberToString( nSize )|'/op', '\"add\"' );\r\nEND;\r\npJson = JsonPatch( '{}', pDiffer );\r\n\r\n### LogOutput parameters\r\nsMessages = JsonAdd( sMessages, '/Info/-', pJson );\r\nIF( pLogOutput = 1 );\r\n LogOutput('INFO', JsonToString( sMessages, '/Info/0', 0, ' ' ) );\r\nENDIF;\r\n\r\n#EndRegion - Process Parameters\r\n#################################################################################################\r\n\r\n## LogOutput parameters\r\nIF ( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\n### Validate Parameters ###\r\nnErrors = 0;\r\n\r\nIf( Scan( '*', pSrcDim )=0 & Scan( '?', pSrcDim )=0 & Scan( pDelim, pSrcDim )=0 & Scan( ':', pSrcDim ) > 0 & pHier @= '' );\r\n # A hierarchy has been passed as dimension. Handle the input error by splitting dim:hier into dimension & hierarchy\r\n pHier = SubSt( pSrcDim, Scan( ':', pSrcDim ) + 1, Long( pSrcDim ) );\r\n pSrcDim = SubSt( pSrcDim, 1, Scan( ':', pSrcDim ) - 1 );\r\nEndIf;\r\n\r\n## Validate dimension\r\nIF( Trim( pSrcDim ) @= '' );\r\n nErrors = 1;\r\n sMessage = 'No source dimension specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIF( DimensionExists( pSrcDim ) = 0 );\r\n nErrors = 1;\r\n sMessage = 'Invalid source dimension: ' | pSrcDim;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\nIf( pTgtDim @= '' % pTgtDim @= pSrcDim );\r\n pTgtDim = pSrcDim | '_Clone';\r\nEndIf;\r\n\r\n# Validate hierarchy\r\nIF( Scan( '*', pSrcDim )=0 & Scan( '?', pSrcDim )=0 & Scan( pDelim, pSrcDim )=0 & pHier @= '');\r\n pHier = pSrcDim;\r\nElseIf( Scan( '*', pHier )=0 & Scan( '?', pHier )=0 & Scan( pDelim, pHier )=0 & pHier @<> '' & HierarchyExists(pSrcDim, pHier) = 0 );\r\n nErrors = 1;\r\n sMessage = 'Invalid dimension hierarchy: ' | pHier;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndif;\r\n\r\nIf( Trim( pHier ) @= '' );\r\n ## use same name as Dimension. Since wildcards are allowed, this is managed inside the code below\r\nEndIf;\r\n\r\n## Default delimiter\r\nIf( pDelim @= '' );\r\n pDelim = '&';\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n### Create target dimension ###\r\n\r\nIf(DimensionExists( pTgtDim ) = 0 );\r\n DimensionCreate( pTgtDim );\r\nElse;\r\n IF(pUnwind = 1 );\r\n nRet = ExecuteProcess('}bedrock.hier.unwind',\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pDim', pTgtDim,\r\n 'pHier', pTgtDim,\r\n 'pConsol', '*',\r\n 'pRecursive', 1\r\n );\r\n ELSEIF(pUnwind = 2 );\r\n # Do nothing;\r\n ELSE;\r\n DimensionDeleteAllElements( pTgtDim );\r\n EndIf;\r\nEndIf;\r\n\r\n### Set the target Sort Order ###\r\n# CellGetS to }DimensionProperties cube removed. Placeholder as expecting a TI function to be made available to be able to read these properties\r\n#sSortElementsType = CELLGETS( '}DimensionProperties', pSrcDim, 'SORTELEMENTSTYPE');\r\n#sSortElementsSense = CELLGETS( '}DimensionProperties', pSrcDim, 'SORTELEMENTSSENSE');\r\n#sSortComponentsType = CELLGETS( '}DimensionProperties', pSrcDim, 'SORTCOMPONENTSTYPE');\r\n#sSortComponentsSense = CELLGETS( '}DimensionProperties', pSrcDim, 'SORTCOMPONENTSSENSE');\r\n\r\n# DimensionSortOrder( pTgtDim, sSortComponentsType, sSortComponentsSense, sSortElementsType , sSortElementsSense);\r\n\r\n\r\nnSourceDimSize = DIMSIZ( pSrcDim );\r\nnIndex = 1;\r\nWHILE( nIndex <= nSourceDimSize );\r\n sElName = DIMNM( pSrcDim, nIndex);\r\n sElType = DTYPE( pSrcDim, sElName);\r\n \r\n DimensionElementInsert( pTgtDim, '', sElName, sElType );\r\n\r\n nIndex = nIndex + 1;\r\nEND;\r\n\r\n### Assign Data Source ###\r\nDatasourceNameForServer = pSrcDim;\r\nDatasourceNameForClient = pSrcDim;\r\nDataSourceType = 'SUBSET';\r\nDatasourceDimensionSubset = 'ALL';\r\n\r\n\r\n### Replicate Attributes ###\r\n# Note: DType on Attr dim returns \"AS\", \"AN\" or \"AA\" need to strip off leading \"A\"\r\nsAttrDim = '}ElementAttributes_' | pSrcDim;\r\nsAttrLoc = '}LocalizedElementAttributes_' | pSrcDim;\r\nsAttrTargetDim = '}ElementAttributes_' | pTgtDim;\r\nsAttrLocTarget = '}LocalizedElementAttributes_' | pTgtDim;\r\n\r\nIf( pAttr = 1 & DimensionExists( sAttrDim ) = 1 );\r\n nNumAttrs = DimSiz( sAttrDim );\r\n nCount = 1;\r\n While( nCount <= nNumAttrs );\r\n sAttrName = DimNm( sAttrDim, nCount );\r\n sAttCheck = SubSt( DTYPE( sAttrDim, sAttrName ), 1, 1 );\r\n IF (sAttCheck @= 'A');\r\n sAttrType = SubSt( DTYPE( sAttrDim, sAttrName ), 2, 1 );\r\n Else;\r\n sAttrType = sAttcheck;\r\n EndIf; \r\n \r\n If ( DimensionExists( sAttrTargetDim ) = 0);\r\n AttrInsert(pTgtDim,'',sAttrName,sAttrType );\r\n ElseIF(DimIx(sAttrTargetDim, sAttrName) = 0);\r\n AttrInsert(pTgtDim,'',sAttrName,sAttrType );\r\n Endif;\r\n \r\n nCount = nCount + 1;\r\n End;\r\nEndIf;\r\n\r\n\r\n### End Prolog ###", "MetadataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock Ver 4.0.0~~##\r\n################################################################################################# \r\n\r\n\r\n### Check for errors in prolog ###\r\n\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n### Add Elements to target dimension ###\r\n\r\nsElType = DType( pSrcDim, vEle );\r\nIF( sElType @= 'C' & ElCompN( pSrcDim, vEle ) > 0 );\r\n nChildren = ElCompN( pSrcDim, vEle );\r\n nCount = 1;\r\n While( nCount <= nChildren );\r\n sChildElement = ElComp( pSrcDim, vEle, nCount );\r\n sChildWeight = ElWeight( pSrcDim, vEle, sChildElement );\r\n DimensionElementComponentAdd( pTgtDim, vEle, sChildElement, sChildWeight );\r\n nCount = nCount + 1;\r\n End;\r\nEndIf;\r\n\r\n### End MetaData ###", "DataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock Ver 4.0.0~~##\r\n################################################################################################# \r\n\r\n\r\n### Check for errors in prolog ###\r\n\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n### Replicate Attributes ###\r\n# Note: DTYPE on Attr dim returns \"AS\", \"AN\" or \"AA\" need to strip off leading \"A\"\r\n\r\nIf( pAttr = 1 & DimensionExists( sAttrDim ) = 1 );\r\n\r\n nAttr = 1;\r\n While( nAttr <= nNumAttrs );\r\n sAttrName = DimNm( sAttrDim, nAttr );\r\n sAttCheck = SubSt( DTYPE( sAttrDim, sAttrName ), 1, 1 );\r\n IF (sAttCheck @= 'A');\r\n sAttrType = SubSt( DTYPE( sAttrDim, sAttrName ), 2, 1 );\r\n Else;\r\n sAttrType = sAttcheck;\r\n sMessage = pSrcDim | ' dimension contains invalid attribute - ' | sAttrName ;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n If( pStrictErrorHandling = 1 );\r\n ItemReject(Expand( cMsgErrorContent ));\r\n EndIf; \r\n EndIf;\r\n If( CellIsUpdateable( sAttrTargetDim, vEle, sAttrName ) = 1 );\r\n If( sAttrType @= 'S' % sAttrType @= 'A' );\r\n #sAttrVal = AttrS( pSrcDim, vEle, sAttrName );\r\n sAttrVal = CellgetS('}ElementAttributes_'| pSrcDim, vEle, sAttrName);\r\n If( sAttrVal @<> '' );\r\n If( sAttrType @= 'A' );\r\n AttrPutS( sAttrVal, pTgtDim, vEle, sAttrName, 1 );\r\n Else;\r\n AttrPutS( sAttrVal, pTgtDim, vEle, sAttrName );\r\n EndIf;\r\n EndIf;\r\n Else;\r\n #nAttrVal = AttrN( pSrcDim, vEle, sAttrName );\r\n nAttrVal = CellgetN('}ElementAttributes_'| pSrcDim, vEle, sAttrName);\r\n If( nAttrVal <> 0 );\r\n AttrPutN( nAttrVal, pTgtDim, vEle, sAttrName );\r\n EndIf;\r\n EndIf;\r\n EndIf;\r\n # check for localized attributes\r\n If( CubeExists( sAttrLoc ) = 1 );\r\n nLang = 1;\r\n While( nLang <= nNumLang );\r\n sLang = DimNm( cLangDim, nLang );\r\n If( sAttrType @= 'A' % sAttrType @= 'S' );\r\n sAttrVal = AttrS( pSrcDim, vEle, sAttrName );\r\n sAttrValLoc = AttrSL( pSrcDim, vEle, sAttrName, sLang );\r\n If( sAttrValLoc @= sAttrVal ); sAttrValLoc = ''; EndIf;\r\n Else;\r\n nAttrVal = AttrN( pSrcDim, vEle, sAttrName );\r\n nAttrValLoc = AttrNL( pSrcDim, vEle, sAttrName, sLang );\r\n EndIf;\r\n If( CubeExists( sAttrLocTarget ) = 0 );\r\n If( sAttrType @= 'A' );\r\n AttrPutS( sAttrValLoc, pTgtDim, vEle, sAttrName, sLang, 1 );\r\n ElseIf( sAttrType @= 'N' );\r\n If( nAttrValLoc <> nAttrVal );\r\n AttrPutN( nAttrValLoc, pTgtDim, vEle, sAttrName, sLang );\r\n EndIf;\r\n Else;\r\n AttrPutS( sAttrValLoc, pTgtDim, vEle, sAttrName, sLang );\r\n EndIf;\r\n ElseIf( CubeExists( sAttrLocTarget ) = 1 );\r\n If( CellIsUpdateable( sAttrLocTarget, vEle, sLang, sAttrName ) = 1 );\r\n If( sAttrType @= 'A' );\r\n AttrPutS( sAttrValLoc, pTgtDim, vEle, sAttrName, sLang, 1 );\r\n ElseIf( sAttrType @= 'N' );\r\n If( nAttrValLoc <> nAttrVal );\r\n AttrPutN( nAttrValLoc, pTgtDim, vEle, sAttrName, sLang );\r\n EndIf;\r\n Else;\r\n AttrPutS( sAttrValLoc, pTgtDim, vEle, sAttrName, sLang );\r\n EndIf;\r\n EndIf;\r\n EndIf;\r\n nLang = nLang + 1;\r\n End;\r\n EndIf;\r\n nAttr = nAttr + 1;\r\n End;\r\n\r\nEndIf;\r\n\r\n### End Data ###", "EpilogProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock Ver 4.0.0~~##\r\n################################################################################################# \r\n\r\n\r\n### Set the target Sort Order ###\r\n# CellPutS to }DimensionProperties cube removed. Placeholder as expecting a TI function to be made available to be able to modify these properties\r\n# CELLPUTS( sSortElementsType, '}DimensionProperties', pTgtDim, 'SORTELEMENTSTYPE');\r\n# CELLPUTS( sSortElementsSense, '}DimensionProperties', pTgtDim, 'SORTELEMENTSSENSE');\r\n# CELLPUTS( sSortComponentsType, '}DimensionProperties', pTgtDim, 'SORTCOMPONENTSTYPE');\r\n# CELLPUTS( sSortComponentsSense, '}DimensionProperties', pTgtDim, 'SORTCOMPONENTSSENSE');\r\n\r\n### Destroy Source Subset ###\r\n\r\n If( SubsetExists( pSrcDim, cSubset ) = 1 );\r\n SubsetDestroy( pSrcDim, cSubset );\r\n EndIf;\r\n\r\n##Clone all the Hierarchies except default hierarchy & Leaves\r\nIf( pHier @= '*' );\r\n sDim = pSrcDim;\r\n sHierDim = '}Hierarchies_' | sDim;\r\n sTargetHierarchy = '';\r\n nMax = DimSiz( sHierDim );\r\n nCtr = 1;\r\n While( nCtr <= nMax );\r\n sEle = DimNm( sHierDim, nCtr );\r\n nElength = Long(sEle);\r\n nElestart = 0;\r\n nElestart = SCAN(':', sEle) + 1;\r\n If(nElestart > 1);\r\n vSourceHierarchy = SUBST(sEle,nElestart,nElength);\r\n If ( vSourceHierarchy @<> 'Leaves');\r\n nRet = ExecuteProcess('}bedrock.hier.clone',\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pSrcDim', sDim,\r\n 'pSrcHier', vSourceHierarchy,\r\n 'pTgtDim', pTgtDim,\r\n 'pTgtHier', vSourceHierarchy,\r\n 'pAttr', pAttr,\r\n 'pUnwind',pUnwind\r\n );\r\n Endif;\r\n sTargetHierarchy = sTargetHierarchy |':'|vSourceHierarchy;\r\n Endif;\r\n nCtr = nCtr + 1;\r\n End;\r\n### Just one hierarchy specified in parameter\r\nElseIf( Scan( '*', pHier )=0 & Scan( '?', pHier )=0 & Scan( pDelim, pHier )=0 & Trim( pHier ) @<> '' );\r\n sDim = pSrcDim;\r\n sHierDim = '}Hierarchies_' | sDim;\r\n sCurrHier = pHier;\r\n sCurrHierName = Subst( sCurrHier, Scan(':', sCurrHier)+1, Long(sCurrHier) );\r\n # Validate hierarchy name in sHierDim\r\n If( Dimix( sHierDim , sDim |':'| sCurrHier ) = 0 );\r\n sMessage = Expand('The \"%sCurrHier%\" hierarchy does NOT exist in the \"%sDim%\" dimension.');\r\n LogOutput( 'INFO' , Expand( cMsgInfoContent ) );\r\n ElseIf( sCurrHierName @= 'Leaves' );\r\n sMessage = 'Invalid Hierarchy: ' | sCurrHier | ' will be skipped....';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n ElseIf( sCurrHierName @<> sDim );\r\n If( pLogOutput = 1 );\r\n sMessage = Expand( 'Hierarchy \"%sCurrHierName%\" in Dimension \"%sDim%\" being processed....' );\r\n LogOutput( 'INFO', Expand( cMsgInfoContent ) );\r\n EndIf;\r\n nRet = ExecuteProcess('}bedrock.hier.clone',\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pSrcDim', sDim,\r\n 'pSrcHier', sCurrHierName,\r\n 'pTgtDim', pTgtDim,\r\n 'pTgtHier', sCurrHierName,\r\n 'pAttr', pAttr,\r\n 'pUnwind',pUnwind\r\n );\r\n Endif;\r\n### Hierachy is a delimited list with no wildcards\r\nElseIf( Scan( '*', pHier )=0 & Scan( '?', pHier )=0 & Trim( pHier ) @<> '' );\r\n \r\n # Loop through hierarchies in pHier\r\n sDim = pSrcDim;\r\n sHierarchies = pHier;\r\n nDelimiterIndexA = 1;\r\n sHierDim = '}Hierarchies_'| sDim ;\r\n sMdxHier = '';\r\n While( nDelimiterIndexA <> 0 );\r\n \r\n nDelimiterIndexA = Scan( pDelim, sHierarchies );\r\n If( nDelimiterIndexA = 0 );\r\n sHierarchy = sHierarchies;\r\n Else;\r\n sHierarchy = Trim( SubSt( sHierarchies, 1, nDelimiterIndexA - 1 ) );\r\n sHierarchies = Trim( Subst( sHierarchies, nDelimiterIndexA + Long(pDelim), Long( sHierarchies ) ) );\r\n EndIf;\r\n sCurrHier = sHierarchy;\r\n sCurrHierName = Subst( sCurrHier, Scan(':', sCurrHier)+1, Long(sCurrHier) );\r\n # Validate hierarchy name in sHierDim\r\n If( Dimix( sHierDim , sDim |':'| sCurrHier ) = 0 );\r\n sMessage = Expand('The \"%sCurrHier%\" hierarchy does NOT exist in the \"%sDim%\" dimension.');\r\n LogOutput( 'INFO' , Expand( cMsgInfoContent ) );\r\n ElseIf( sCurrHierName @= 'Leaves' );\r\n sMessage = 'Invalid Hierarchy: ' | sCurrHier | ' will be skipped....';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n ElseIf( sCurrHierName @<> sDim );\r\n If( pLogOutput = 1 );\r\n sMessage = Expand( 'Hierarchy \"%sCurrHierName%\" in Dimension \"%sDim%\" being processed....' );\r\n LogOutput( 'INFO', Expand( cMsgInfoContent ) );\r\n EndIf;\r\n nRet = ExecuteProcess('}bedrock.hier.clone',\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pSrcDim', sDim,\r\n 'pSrcHier', sCurrHierName,\r\n 'pTgtDim', pTgtDim,\r\n 'pTgtHier', sCurrHierName,\r\n 'pAttr', pAttr,\r\n 'pUnwind',pUnwind\r\n );\r\n Endif;\r\n End;\r\n\r\n### Hierachy has wildcards inside\r\nElseIf( Trim( pHier ) @<> '' );\r\n \r\n # Loop through hierarchies in pHier\r\n sDim = pSrcDim;\r\n sHierarchies = pHier;\r\n nDelimiterIndexA = 1;\r\n sHierDim = '}Hierarchies_'| sDim ;\r\n sMdxHier = '';\r\n While( nDelimiterIndexA <> 0 );\r\n \r\n nDelimiterIndexA = Scan( pDelim, sHierarchies );\r\n If( nDelimiterIndexA = 0 );\r\n sHierarchy = sHierarchies;\r\n Else;\r\n sHierarchy = Trim( SubSt( sHierarchies, 1, nDelimiterIndexA - 1 ) );\r\n sHierarchies = Trim( Subst( sHierarchies, nDelimiterIndexA + Long(pDelim), Long( sHierarchies ) ) );\r\n EndIf;\r\n \r\n # Create subset of Hierarchies using Wildcard\r\n sHierExp = '\"'| sDim | ':' | sHierarchy|'\"';\r\n sMdxHierPart = '{TM1FILTERBYPATTERN( {TM1SUBSETALL([ ' |sHierDim| '])},'| sHierExp | ')}';\r\n IF( sMdxHier @= ''); \r\n sMdxHier = sMdxHierPart; \r\n ELSE;\r\n sMdxHier = sMdxHier | ' + ' | sMdxHierPart;\r\n ENDIF;\r\n End;\r\n \r\n If( SubsetExists( sHierDim, cSubset ) = 1 );\r\n # If a delimited list of attr names includes wildcards then we may have to re-use the subset multiple times\r\n SubsetMDXSet( sHierDim, cSubset, sMdxHier );\r\n Else;\r\n # temp subset, therefore no need to destroy in epilog\r\n SubsetCreatebyMDX( cSubset, sMdxHier, sHierDim, 1 );\r\n EndIf;\r\n \r\n # Loop through subset of hierarchies created based on wildcard\r\n nCountHier = SubsetGetSize( sHierDim, cSubset );\r\n While( nCountHier >= 1 );\r\n sCurrHier = SubsetGetElementName( sHierDim, cSubset , nCountHier );\r\n sCurrHierName = Subst( sCurrHier, Scan(':', sCurrHier)+1, Long(sCurrHier) );\r\n # Validate hierarchy name in sHierDim\r\n If( Dimix( sHierDim , sCurrHier ) = 0 );\r\n sMessage = Expand('The \"%sCurrHier%\" hierarchy does NOT exist in the \"%sDim%\" dimension.');\r\n LogOutput( 'INFO' , Expand( cMsgInfoContent ) );\r\n ElseIf( sCurrHierName @= 'Leaves' );\r\n sMessage = 'Invalid Hierarchy: ' | sCurrHier | ' will be skipped....';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n ElseIf( sCurrHierName @<> sDim );\r\n If( pLogOutput = 1 );\r\n sMessage = Expand( 'Hierarchy \"%sCurrHierName%\" in Dimension \"%sDim%\" being processed....' );\r\n LogOutput( 'INFO', Expand( cMsgInfoContent ) );\r\n EndIf;\r\n nRet = ExecuteProcess('}bedrock.hier.clone',\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pSrcDim', sDim,\r\n 'pSrcHier', sCurrHierName,\r\n 'pTgtDim', pTgtDim,\r\n 'pTgtHier', sCurrHierName,\r\n 'pAttr', pAttr,\r\n 'pUnwind',pUnwind\r\n );\r\n Endif;\r\n \r\n nCountHier = nCountHier - 1;\r\n End;\r\nEndif;\r\n\r\n### Clone dimension subsets\r\nIf( pSub = 1);\r\n nCountSubs = DimSiz ('}Subsets_' | sDim);\r\n While ( nCountSubs >= 1 );\r\n sCurrSub = If( Scan( ':', DimNm ('}Subsets_' | sDim, nCountSubs)) = 0, DimNm ('}Subsets_' | sDim, nCountSubs), Subst( DimNm ('}Subsets_' | sDim, nCountSubs), Scan( ':', DimNm ('}Subsets_' | sDim, nCountSubs))+1, Long(DimNm ('}Subsets_' | sDim, nCountSubs))-Scan( ':', DimNm ('}Subsets_' | sDim, nCountSubs))));\r\n sCurrHier = If( Scan( ':', DimNm ('}Subsets_' | sDim, nCountSubs)) = 0, '', Subst(DimNm ('}Subsets_' | sDim, nCountSubs), 1, Scan( ':', DimNm ('}Subsets_' | sDim, nCountSubs))-1));\r\n\r\n ExecuteProcess('}bedrock.hier.sub.clone',\r\n 'pLogOutput',0,\r\n 'pStrictErrorHandling',0,\r\n 'pSrcDim',sDim,\r\n 'pSrcHier',sCurrHier,\r\n 'pSrcSub',sCurrSub,\r\n 'pTgtDim', pTgtDim,\r\n 'pTgtHier', sCurrHier,\r\n 'pTgtSub',sCurrSub,\r\n 'pTemp',0,\r\n 'pAlias','');\r\n nCountSubs = nCountSubs - 1;\r\n End;\r\nEndif;\r\n \r\n\r\n### Return code & final error message handling\r\nIf( nErrors > 0 );\r\n sMessage = 'the process incurred at least 1 error. Please see above lines in this file for more details.';\r\n nProcessReturnCode = 0;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% Process:%cThisProcName% completed with errors. Check tm1server.log for details.' );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n EndIf;\r\nElse;\r\n sProcessAction = Expand( 'Process:%cThisProcName% has cloned the %pSrcDim% dimension into %pTgtDim%.' );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% %sProcessAction%' );\r\n nProcessReturnCode = 1;\r\n If( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( sProcessAction ) ); \r\n EndIf;\r\nEndIf;\r\n\r\n### End Epilog ###", @@ -13,59 +13,65 @@ "subset": "All" }, "Parameters": [ - { - "Name": "pLogOutput", - "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, - { - "Name": "pStrictErrorHandling", - "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, { "Name": "pSrcDim", - "Prompt": "REQUIRED: Source Dimension", + "Prompt": "REQUIRED: Source dimension name", "Value": "", "Type": "String" }, { "Name": "pTgtDim", - "Prompt": "OPTIONAL: Target Dimension (will default to pSrcDim_clone If blank (or) is same as pSrcDim)", + "Prompt": "OPTIONAL: Target dimension name (Default = pSrcDim | '_Clone')", "Value": "", "Type": "String" }, { "Name": "pHier", - "Prompt": "REQUIRED: Hierarchies to be included (will use default is left blank), accepts wildcards (if = *, then all hierarchies)", + "Prompt": "OPTIONAL: Delimited list of hierarchies to include (Default = '*')", "Value": "*", "Type": "String" }, { "Name": "pAttr", - "Prompt": "REQUIRED: Include Attributes? (Boolean 1=True)", + "Prompt": "OPTIONAL: Include attributes (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" }, { "Name": "pUnwind", - "Prompt": "REQUIRED: 0 = Delete all Elements, 1 = Unwind Existing Elements, 2 = Do not change Existing Elements", + "Prompt": "OPTIONAL: Unwind hierarchies after process (0 = Delete all elements, 1 = Unwind existing elements, 2 = Do not change existing elements. Default = 0)", "Value": 0, "Type": "Numeric" }, { "Name": "pDelim", - "Prompt": "OPTIONAL: delimiter character for element list (required if pEle parameter is used) (default value if blank = '&')", + "Prompt": "OPTIONAL: Delimiter for list parameters (Default = '&')", "Value": "&", "Type": "String" }, { "Name": "pSub", - "Prompt": "OPTIONAL: if 1 = Clone subsets", + "Prompt": "OPTIONAL: Include subsets (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" + }, + { + "Name": "pLogOutput", + "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pStrictErrorHandling", + "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pJson", + "Prompt": "OPTIONAL: JSON Object with process parameter values. This will overwrite user passed parameters for all included parameters.", + "Value": "{}", + "Type": "String" } ], "Variables": [ @@ -77,7 +83,5 @@ "EndByte": 0 } ], - "VariablesUIData": [ - "VarType=32\fColType=827\f" - ] + "VariablesUIData": [] } \ No newline at end of file diff --git a/bedrock_processes_json/}bedrock.dim.create.json b/bedrock_processes_json/}bedrock.dim.create.json index 95cf707..e93461a 100644 --- a/bedrock_processes_json/}bedrock.dim.create.json +++ b/bedrock_processes_json/}bedrock.dim.create.json @@ -1,6 +1,6 @@ { "Name": "}bedrock.dim.create", - "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\nExecuteProcess('}bedrock.dim.create',\r\n 'pLogOutput', 0,\r\n 'pStrictErrorHandling', 0,\r\n 'pDim', '',\r\n 'pDelim', '&');\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock Ver 4.0 ~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process will create new dimensions based on `pDim`.\r\n\r\n# Use case: Intended for Development but could be used in production too.\r\n# 1. Create a new dimension for testing.\r\n# 2. Create a new dimension to reflect new business needs.\r\n\r\n#EndRegion @DOC\r\n\r\n### Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSub = cThisProcName |'_'| cTimeStamp |'_'| cRandomInt;\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncMsgInfoContent = 'User:%cUserName% Process:%cThisProcName% Message:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pDim:%pDim%, pHier:%pHier%, pDelim:%pDelim%.'; \r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\n### Validate Parameters ###\r\nnErrors = 0;\r\n\r\nIf( Scan( '*', pDim ) = 0 & Scan( '?', pDim ) = 0 & Scan( pDelim, pDim ) = 0 & Scan( ':', pDim ) > 0 );\r\n # A hierarchy has been passed as dimension. Handle the input error by splitting dim:hier into dimension & hierarchy\r\n pHier = SubSt( pDim, Scan( ':', pDim ) + 1, Long( pDim ) );\r\n pDim = SubSt( pDim, 1, Scan( ':', pDim ) - 1 );\r\nEndIf;\r\n\r\nIf( Trim( pDim ) @= '' );\r\n nErrors = 1;\r\n sMessage = 'No dimension specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# If blank delimiter specified then convert to default\r\nIf( pDelim @= '' );\r\n pDelim = '&';\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n\r\n# Loop through dimensions in pDim\r\nsDims = pDim;\r\nnDimDelimiterIndex = 1;\r\n# Get 1st dimension\r\nWhile( nDimDelimiterIndex <> 0 );\r\n # Extract 1st dimension > sDim\r\n nDimDelimiterIndex = Scan( pDelim, sDims );\r\n If( nDimDelimiterIndex = 0 );\r\n sDim = sDims;\r\n Else;\r\n sDim = Trim( SubSt( sDims, 1, nDimDelimiterIndex - 1 ) );\r\n sDims = Trim( Subst( sDims, nDimDelimiterIndex + Long(pDelim), Long( sDims ) ) );\r\n EndIf;\r\n \r\n ###Creating Dimension if not exist, where no wildcard\r\n If( Scan( '*', sDim ) = 0 & Scan( '?', sDim ) = 0 & Scan( pDelim, sDim ) = 0 & DimensionExists( sDim ) = 0 );\r\n DimensionCreate( sDim );\r\n If( pLogOutput = 1 );\r\n sMessage = Expand( 'Creating Dimension %sDim%' );\r\n LogOutput( 'INFO', Expand( cMsgInfoContent ) );\r\n EndIf;\r\n EndIf;\r\n \r\nEnd;\r\n\r\n### End Prolog ###", + "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\nExecuteProcess('}bedrock.dim.create',\r\n 'pLogOutput', 0,\r\n 'pStrictErrorHandling', 0,\r\n 'pDim', '',\r\n 'pDelim', '&');\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock Ver 4.0 ~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process will create new dimensions based on `pDim`.\r\n\r\n# Use case: Intended for Development but could be used in production too.\r\n# 1. Create a new dimension for testing.\r\n# 2. Create a new dimension to reflect new business needs.\r\n\r\n#EndRegion @DOC\r\n\r\n### Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSub = cThisProcName |'_'| cTimeStamp |'_'| cRandomInt;\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncMsgInfoContent = 'User:%cUserName% Process:%cThisProcName% Message:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pDim:%pDim%, pHier:%pHier%, pDelim:%pDelim%.';\r\n\r\n#################################################################################################\r\n#Region - Process Parameters\r\n\r\npJson = IF( JsonType( pJson ) @<> 'object', '{}', pJson );\r\nsMessages = '{\"Process\": \"'|GetProcessName()|'\", \"User\": \"'|TM1User()|'\", \"Info\": [\"Process: '''|GetProcessName()|''' run by User: '''|TM1User()|'''.\"], \"Error\": []}';\r\npDefaultParameters = '{\r\n \"pDelim\": \"&\",\r\n \"pDim\": null,\r\n \"pLogOutput\": 0,\r\n \"pStrictErrorHandling\": 0\r\n}';\r\n\r\npPassedParameters = '{\r\n \"pDelim\": '|StringToJson ( pDelim )|',\r\n \"pDim\": '|StringToJson ( pDim )|',\r\n \"pLogOutput\": '|NumberToString( pLogOutput )|',\r\n \"pStrictErrorHandling\": '|NumberToString( pStrictErrorHandling )|'\r\n}';\r\n\r\npJson = JsonMergePatch( pPassedParameters, pJson );\r\n# String Parameters\r\npDelim = JsonToString( JsonGet( pJson, 'pDelim' ) );\r\npDim = JsonToString( JsonGet( pJson, 'pDim' ) );\r\n# Numeric Parameters\r\npLogOutput = StringToNumber( JsonToString( JsonGet( pJson, 'pLogOutput' ) ) );\r\npStrictErrorHandling = StringToNumber( JsonToString( JsonGet( pJson, 'pStrictErrorHandling' ) ) );\r\n\r\n### Get the parameters that differ from the default\r\npDiffer = JsonDiff( pDefaultParameters, pJson );\r\nnSize = JsonSize( pDiffer );\r\nWHILE( nSize > 0 );\r\n nSize = nSize - 1;\r\n pDiffer = JsonReplace( pDiffer, '/'|NumberToString( nSize )|'/op', '\"add\"' );\r\nEND;\r\npJson = JsonPatch( '{}', pDiffer );\r\n\r\n### LogOutput parameters\r\nsMessages = JsonAdd( sMessages, '/Info/-', pJson );\r\nIF( pLogOutput = 1 );\r\n LogOutput('INFO', JsonToString( sMessages, '/Info/0', 0, ' ' ) );\r\nENDIF;\r\n\r\n#EndRegion - Process Parameters\r\n#################################################################################################\r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\n### Validate Parameters ###\r\nnErrors = 0;\r\n\r\nIf( Scan( '*', pDim ) = 0 & Scan( '?', pDim ) = 0 & Scan( pDelim, pDim ) = 0 & Scan( ':', pDim ) > 0 );\r\n # A hierarchy has been passed as dimension. Handle the input error by splitting dim:hier into dimension & hierarchy\r\n pHier = SubSt( pDim, Scan( ':', pDim ) + 1, Long( pDim ) );\r\n pDim = SubSt( pDim, 1, Scan( ':', pDim ) - 1 );\r\nEndIf;\r\n\r\nIf( Trim( pDim ) @= '' );\r\n nErrors = 1;\r\n sMessage = 'No dimension specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# If blank delimiter specified then convert to default\r\nIf( pDelim @= '' );\r\n pDelim = '&';\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n\r\n# Loop through dimensions in pDim\r\nsDims = pDim;\r\nnDimDelimiterIndex = 1;\r\n# Get 1st dimension\r\nWhile( nDimDelimiterIndex <> 0 );\r\n # Extract 1st dimension > sDim\r\n nDimDelimiterIndex = Scan( pDelim, sDims );\r\n If( nDimDelimiterIndex = 0 );\r\n sDim = sDims;\r\n Else;\r\n sDim = Trim( SubSt( sDims, 1, nDimDelimiterIndex - 1 ) );\r\n sDims = Trim( Subst( sDims, nDimDelimiterIndex + Long(pDelim), Long( sDims ) ) );\r\n EndIf;\r\n \r\n ###Creating Dimension if not exist, where no wildcard\r\n If( Scan( '*', sDim ) = 0 & Scan( '?', sDim ) = 0 & Scan( pDelim, sDim ) = 0 & DimensionExists( sDim ) = 0 );\r\n DimensionCreate( sDim );\r\n If( pLogOutput = 1 );\r\n sMessage = Expand( 'Creating Dimension %sDim%' );\r\n LogOutput( 'INFO', Expand( cMsgInfoContent ) );\r\n EndIf;\r\n EndIf;\r\n \r\nEnd;\r\n\r\n### End Prolog ###", "MetadataProcedure": "#****Begin: Generated Statements***\r\n#****End: Generated Statements****", "DataProcedure": "#****Begin: Generated Statements***\r\n#****End: Generated Statements****", "EpilogProcedure": "#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n### Return code & final error message handling\r\nIf( nErrors > 0 );\r\n sMessage = 'the process incurred at least 1 error. Please see above lines in this file for more details.';\r\n nProcessReturnCode = 0;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% Process:%cThisProcName% completed with errors. Check tm1server.log for details.' );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n EndIf;\r\nElse;\r\n sProcessAction = Expand( 'Process:%cThisProcName% successfully created the %pHier% hierarchy in the %pDim% dimension.' );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% %sProcessAction%' );\r\n nProcessReturnCode = 1;\r\n If( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( sProcessAction ) ); \r\n EndIf;\r\nEndIf;\r\n\r\n\r\n\r\n### End Epilog ###", @@ -10,28 +10,34 @@ "Type": "None" }, "Parameters": [ + { + "Name": "pDim", + "Prompt": "REQUIRED: Delimited list of dimensions", + "Value": "", + "Type": "String" + }, + { + "Name": "pDelim", + "Prompt": "OPTIONAL: Delimiter for list parameters (Default = '&')", + "Value": "&", + "Type": "String" + }, { "Name": "pLogOutput", - "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean True = 1)", + "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" }, { "Name": "pStrictErrorHandling", - "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean True = 1)", + "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" }, { - "Name": "pDim", - "Prompt": "REQUIRED: Dimension, accepts delimted list", - "Value": "", - "Type": "String" - }, - { - "Name": "pDelim", - "Prompt": "OPTIONAL: delimiter character for element list. (default value if blank = '&')", - "Value": "&", + "Name": "pJson", + "Prompt": "OPTIONAL: JSON Object with process parameter values. This will overwrite user passed parameters for all included parameters.", + "Value": "{}", "Type": "String" } ], diff --git a/bedrock_processes_json/}bedrock.dim.delete.json b/bedrock_processes_json/}bedrock.dim.delete.json index 362b516..d6115ea 100644 --- a/bedrock_processes_json/}bedrock.dim.delete.json +++ b/bedrock_processes_json/}bedrock.dim.delete.json @@ -1,6 +1,6 @@ { "Name": "}bedrock.dim.delete", - "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.dim.delete', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n\t 'pDim', '', 'pDelim', '&'\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~ Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock Ver 4.0 ~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process deletes a dimension, list of dimensions, or set of dimensions specified by wildcard name match.\r\n\r\n# Use case: Intended for development/prototyping.\r\n# 1. During active agile development to remove dimensions due to renaming, change of requirements, etc.\r\n# 2. Clean up unused dimensions prior to system Go Live.\r\n\r\n# Note:\r\n# * A valid dimension name pDim or list thereof is mandatory otherwise the process will abort.\r\n# * Attribute dimensions are deliberately excluded because these are automatically cleaned up by removing the base dimension.\r\n#EndRegion @DOC\r\n\r\n### Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSub = cThisProcName |'_'| cTimeStamp |'_'| cRandomInt;\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pDim:%pDim%, pDelim:%pDelim%.'; \r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\n### Validate Parameters ###\r\nnErrors = 0;\r\n\r\nIf( Trim( pDim ) @= '' );\r\n nErrors = 1;\r\n sMessage = 'No dimension specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n## Default delimiter\r\nIf( pDelim @= '' );\r\n pDelim = '&';\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n## Dimension delete\r\n# Loop through dimensions in pDim \r\nsDims = Trim( pDim );\r\nnDimDelimiterIndex = 1;\r\n# Get 1st dimension\r\nWhile( nDimDelimiterIndex <> 0 );\r\n # Extract 1st dimension > sDim\r\n nDimDelimiterIndex = Scan( pDelim, sDims );\r\n If( nDimDelimiterIndex = 0 );\r\n sDim = sDims;\r\n Else;\r\n sDim = Trim( SubSt( sDims, 1, nDimDelimiterIndex - 1 ) );\r\n sDims = Trim( Subst( sDims, nDimDelimiterIndex + Long(pDelim), Long( sDims ) ) );\r\n EndIf;\r\n \r\n # Check if sDim has wildcard\r\n If( Scan( '*', sDim ) = 0);\r\n # check if dim is used in a cube\r\n sDimIsUsed ='';\r\n nDimIsUsed = 0;\r\n nCubes = DimSiz( '}Cubes' );\r\n nCube = 1;\r\n While(nCube <= nCubes);\r\n sCube = DimNm( '}Cubes' , nCube );\r\n nDim = 1;\r\n While(TabDim(sCube,nDim)@<>'' & Subst( sCube , 1 , 1) @<>'}' );\r\n sDimInCube = TABDIM(sCube,nDim);\r\n If(sDimInCube@=sDim);\r\n sDimIsUsed = sDimIsUsed | sCube | ' ';\r\n nDimIsUsed = nDimIsUsed+1;\r\n EndIf;\r\n nDim = nDim + 1;\r\n End;\r\n nCube = nCube + 1;\r\n End; \r\n \r\n # Delete if it exists and is not being used in a cube\r\n If( DimensionExists(sDim) = 0 );\r\n nErrors = 1;\r\n sMessage = Expand( 'Dimension \"%sDim%\" does not exist.' );\r\n LogOutput( 'ERROR', Expand( cMsgErrorContent ) );\r\n ElseIF( sDimIsUsed@='');\r\n DimensionDestroy( sDim );\r\n Else;\r\n nErrors = 1;\r\n sMessage = 'The dimension ' | sDim | ' could not be destroyed as it is being used for ' | NumberToString(nDimIsUsed) | ' cube(s) :' | sDimIsUsed;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n Endif;\r\n Else;\r\n # Create subset of dimensions using Wildcard to loop through dimensions in pDim with wildcard\r\n sDimExp = '\"'|sDim|'\"';\r\n sMdx = '{TM1FILTERBYPATTERN( EXCEPT ( EXCEPT ( TM1SUBSETALL( [}Dimensions] ) , TM1FILTERBYPATTERN( TM1SUBSETALL( [}Dimensions] ) , \"*:*\") ), TM1FILTERBYPATTERN( TM1SUBSETALL( [}Dimensions] ) , \"}ElementAttributes_*\") ) ,'| sDimExp | ')}';\r\n If( SubsetExists( '}Dimensions' , cTempSub ) = 1 );\r\n # If a delimited list of dim names includes wildcards then we may have to re-use the subset multiple times\r\n SubsetMDXSet( '}Dimensions' , cTempSub, sMDX );\r\n Else;\r\n # temp subset, therefore no need to destroy in epilog\r\n SubsetCreatebyMDX( cTempSub, sMDX, '}Dimensions' , 1 );\r\n EndIf;\r\n \r\n # Loop through dimensions in subset created based on wildcard\r\n nCountDim = SubsetGetSize( '}Dimensions' , cTempSub );\r\n While( nCountDim >= 1 );\r\n sDim = SubsetGetElementName( '}Dimensions' , cTempSub, nCountDim );\r\n # check if dim is used in a cube\r\n sDimIsUsed ='';\r\n nDimIsUsed = 0;\r\n nCubes = DimSiz( '}Cubes' );\r\n nCube = 1;\r\n While(nCube <= nCubes);\r\n sCube = DimNm( '}Cubes' , nCube );\r\n nDim = 1;\r\n While(TabDim(sCube,nDim)@<>'' & Subst( sCube , 1 , 1) @<>'}' );\r\n sDimInCube = TABDIM(sCube,nDim);\r\n If(sDimInCube@=sDim);\r\n sDimIsUsed = sDimIsUsed | sCube | ' ';\r\n nDimIsUsed = nDimIsUsed+1;\r\n EndIf;\r\n nDim = nDim + 1;\r\n End;\r\n nCube = nCube + 1;\r\n End; \r\n # Delete if it exists and is not being used in a cube\r\n If( DimensionExists(sDim) = 0 );\r\n nErrors = 1;\r\n sMessage = Expand( 'Dimension %sDim% does not exist.' );\r\n LogOutput( 'ERROR', Expand( cMsgErrorContent ) );\r\n ElseIF( sDimIsUsed@='');\r\n DimensionDestroy( sDim );\r\n Else;\r\n nErrors = 1;\r\n sMessage = 'The dimension ' | sDim | ' could not be destroyed as it is being used for ' | NumberToString(nDimIsUsed) | ' cube(s) :' | sDimIsUsed;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n Endif;\r\n IF( SubsetGetSize( '}Dimensions' , cTempSub ) < nCountDim - 1 );\r\n nCountDim = SubsetGetSize( '}Dimensions' , cTempSub );\r\n ELSE;\r\n nCountDim = nCountDim - 1;\r\n ENDIF;\r\n End;\r\n EndIf;\r\n \r\nEnd;\r\n\r\n### End Prolog ###", + "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.dim.delete', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n\t 'pDim', '', 'pDelim', '&'\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~ Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock Ver 4.0 ~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process deletes a dimension, list of dimensions, or set of dimensions specified by wildcard name match.\r\n\r\n# Use case: Intended for development/prototyping.\r\n# 1. During active agile development to remove dimensions due to renaming, change of requirements, etc.\r\n# 2. Clean up unused dimensions prior to system Go Live.\r\n\r\n# Note:\r\n# * A valid dimension name pDim or list thereof is mandatory otherwise the process will abort.\r\n# * Attribute dimensions are deliberately excluded because these are automatically cleaned up by removing the base dimension.\r\n#EndRegion @DOC\r\n\r\n### Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSub = cThisProcName |'_'| cTimeStamp |'_'| cRandomInt;\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pDim:%pDim%, pDelim:%pDelim%.';\r\n\r\n#################################################################################################\r\n#Region - Process Parameters\r\n\r\npJson = IF( JsonType( pJson ) @<> 'object', '{}', pJson );\r\nsMessages = '{\"Process\": \"'|GetProcessName()|'\", \"User\": \"'|TM1User()|'\", \"Info\": [\"Process: '''|GetProcessName()|''' run by User: '''|TM1User()|'''.\"], \"Error\": []}';\r\npDefaultParameters = '{\r\n \"pDelim\": \"&\",\r\n \"pDim\": null,\r\n \"pLogOutput\": 0,\r\n \"pStrictErrorHandling\": 0\r\n}';\r\n\r\npPassedParameters = '{\r\n \"pDelim\": '|StringToJson ( pDelim )|',\r\n \"pDim\": '|StringToJson ( pDim )|',\r\n \"pLogOutput\": '|NumberToString( pLogOutput )|',\r\n \"pStrictErrorHandling\": '|NumberToString( pStrictErrorHandling )|'\r\n}';\r\n\r\npJson = JsonMergePatch( pPassedParameters, pJson );\r\n# String Parameters\r\npDelim = JsonToString( JsonGet( pJson, 'pDelim' ) );\r\npDim = JsonToString( JsonGet( pJson, 'pDim' ) );\r\n# Numeric Parameters\r\npLogOutput = StringToNumber( JsonToString( JsonGet( pJson, 'pLogOutput' ) ) );\r\npStrictErrorHandling = StringToNumber( JsonToString( JsonGet( pJson, 'pStrictErrorHandling' ) ) );\r\n\r\n### Get the parameters that differ from the default\r\npDiffer = JsonDiff( pDefaultParameters, pJson );\r\nnSize = JsonSize( pDiffer );\r\nWHILE( nSize > 0 );\r\n nSize = nSize - 1;\r\n pDiffer = JsonReplace( pDiffer, '/'|NumberToString( nSize )|'/op', '\"add\"' );\r\nEND;\r\npJson = JsonPatch( '{}', pDiffer );\r\n\r\n### LogOutput parameters\r\nsMessages = JsonAdd( sMessages, '/Info/-', pJson );\r\nIF( pLogOutput = 1 );\r\n LogOutput('INFO', JsonToString( sMessages, '/Info/0', 0, ' ' ) );\r\nENDIF;\r\n\r\n#EndRegion - Process Parameters\r\n#################################################################################################\r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\n### Validate Parameters ###\r\nnErrors = 0;\r\n\r\nIf( Trim( pDim ) @= '' );\r\n nErrors = 1;\r\n sMessage = 'No dimension specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n## Default delimiter\r\nIf( pDelim @= '' );\r\n pDelim = '&';\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n## Dimension delete\r\n# Loop through dimensions in pDim \r\nsDims = Trim( pDim );\r\nnDimDelimiterIndex = 1;\r\n# Get 1st dimension\r\nWhile( nDimDelimiterIndex <> 0 );\r\n # Extract 1st dimension > sDim\r\n nDimDelimiterIndex = Scan( pDelim, sDims );\r\n If( nDimDelimiterIndex = 0 );\r\n sDim = sDims;\r\n Else;\r\n sDim = Trim( SubSt( sDims, 1, nDimDelimiterIndex - 1 ) );\r\n sDims = Trim( Subst( sDims, nDimDelimiterIndex + Long(pDelim), Long( sDims ) ) );\r\n EndIf;\r\n \r\n # Check if sDim has wildcard\r\n If( Scan( '*', sDim ) = 0);\r\n # check if dim is used in a cube\r\n sDimIsUsed ='';\r\n nDimIsUsed = 0;\r\n nCubes = DimSiz( '}Cubes' );\r\n nCube = 1;\r\n While(nCube <= nCubes);\r\n sCube = DimNm( '}Cubes' , nCube );\r\n nDim = 1;\r\n While(TabDim(sCube,nDim)@<>'' & Subst( sCube , 1 , 1) @<>'}' );\r\n sDimInCube = TABDIM(sCube,nDim);\r\n If(sDimInCube@=sDim);\r\n sDimIsUsed = sDimIsUsed | sCube | ' ';\r\n nDimIsUsed = nDimIsUsed+1;\r\n EndIf;\r\n nDim = nDim + 1;\r\n End;\r\n nCube = nCube + 1;\r\n End; \r\n \r\n # Delete if it exists and is not being used in a cube\r\n If( DimensionExists(sDim) = 0 );\r\n nErrors = 1;\r\n sMessage = Expand( 'Dimension \"%sDim%\" does not exist.' );\r\n LogOutput( 'ERROR', Expand( cMsgErrorContent ) );\r\n ElseIF( sDimIsUsed@='');\r\n DimensionDestroy( sDim );\r\n Else;\r\n nErrors = 1;\r\n sMessage = 'The dimension ' | sDim | ' could not be destroyed as it is being used for ' | NumberToString(nDimIsUsed) | ' cube(s) :' | sDimIsUsed;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n Endif;\r\n Else;\r\n # Create subset of dimensions using Wildcard to loop through dimensions in pDim with wildcard\r\n sDimExp = '\"'|sDim|'\"';\r\n sMdx = '{TM1FILTERBYPATTERN( EXCEPT ( EXCEPT ( TM1SUBSETALL( [}Dimensions] ) , TM1FILTERBYPATTERN( TM1SUBSETALL( [}Dimensions] ) , \"*:*\") ), TM1FILTERBYPATTERN( TM1SUBSETALL( [}Dimensions] ) , \"}ElementAttributes_*\") ) ,'| sDimExp | ')}';\r\n If( SubsetExists( '}Dimensions' , cTempSub ) = 1 );\r\n # If a delimited list of dim names includes wildcards then we may have to re-use the subset multiple times\r\n SubsetMDXSet( '}Dimensions' , cTempSub, sMDX );\r\n Else;\r\n # temp subset, therefore no need to destroy in epilog\r\n SubsetCreatebyMDX( cTempSub, sMDX, '}Dimensions' , 1 );\r\n EndIf;\r\n \r\n # Loop through dimensions in subset created based on wildcard\r\n nCountDim = SubsetGetSize( '}Dimensions' , cTempSub );\r\n While( nCountDim >= 1 );\r\n sDim = SubsetGetElementName( '}Dimensions' , cTempSub, nCountDim );\r\n # check if dim is used in a cube\r\n sDimIsUsed ='';\r\n nDimIsUsed = 0;\r\n nCubes = DimSiz( '}Cubes' );\r\n nCube = 1;\r\n While(nCube <= nCubes);\r\n sCube = DimNm( '}Cubes' , nCube );\r\n nDim = 1;\r\n While(TabDim(sCube,nDim)@<>'' & Subst( sCube , 1 , 1) @<>'}' );\r\n sDimInCube = TABDIM(sCube,nDim);\r\n If(sDimInCube@=sDim);\r\n sDimIsUsed = sDimIsUsed | sCube | ' ';\r\n nDimIsUsed = nDimIsUsed+1;\r\n EndIf;\r\n nDim = nDim + 1;\r\n End;\r\n nCube = nCube + 1;\r\n End; \r\n # Delete if it exists and is not being used in a cube\r\n If( DimensionExists(sDim) = 0 );\r\n nErrors = 1;\r\n sMessage = Expand( 'Dimension %sDim% does not exist.' );\r\n LogOutput( 'ERROR', Expand( cMsgErrorContent ) );\r\n ElseIF( sDimIsUsed@='');\r\n DimensionDestroy( sDim );\r\n Else;\r\n nErrors = 1;\r\n sMessage = 'The dimension ' | sDim | ' could not be destroyed as it is being used for ' | NumberToString(nDimIsUsed) | ' cube(s) :' | sDimIsUsed;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n Endif;\r\n IF( SubsetGetSize( '}Dimensions' , cTempSub ) < nCountDim - 1 );\r\n nCountDim = SubsetGetSize( '}Dimensions' , cTempSub );\r\n ELSE;\r\n nCountDim = nCountDim - 1;\r\n ENDIF;\r\n End;\r\n EndIf;\r\n \r\nEnd;\r\n\r\n### End Prolog ###", "MetadataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "DataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "EpilogProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n### Return code & final error message handling\r\nIf( nErrors > 0 );\r\n sMessage = 'the process incurred at least 1 error. Please see above lines in this file for more details.';\r\n nProcessReturnCode = 0;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% Process:%cThisProcName% completed with errors. Check tm1server.log for details.' );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n EndIf;\r\nElse;\r\n sProcessAction = Expand( 'Process:%cThisProcName% successfully deleted dimensions %pDim%.' );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% %sProcessAction%' );\r\n nProcessReturnCode = 1;\r\n If( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( sProcessAction ) ); \r\n EndIf;\r\nEndIf;\r\n\r\n### End Epilog ###", @@ -10,28 +10,34 @@ "Type": "None" }, "Parameters": [ + { + "Name": "pDim", + "Prompt": "REQUIRED: Delimited list of dimensions", + "Value": "", + "Type": "String" + }, + { + "Name": "pDelim", + "Prompt": "OPTIONAL: Delimiter for list parameters (Default = '&')", + "Value": "&", + "Type": "String" + }, { "Name": "pLogOutput", - "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean True = 1)", + "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" }, { "Name": "pStrictErrorHandling", - "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean True = 1)", + "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" }, { - "Name": "pDim", - "Prompt": "REQUIRED: Dimension (Delimited list & wildcards (*) acceptable)", - "Value": "", - "Type": "String" - }, - { - "Name": "pDelim", - "Prompt": "REQUIRED: delimiter character for attribute list. (default value if blank = '&')", - "Value": "&", + "Name": "pJson", + "Prompt": "OPTIONAL: JSON Object with process parameter values. This will overwrite user passed parameters for all included parameters.", + "Value": "{}", "Type": "String" } ], diff --git a/bedrock_processes_json/}bedrock.dim.sort.json b/bedrock_processes_json/}bedrock.dim.sort.json index 1826ea1..102693a 100644 --- a/bedrock_processes_json/}bedrock.dim.sort.json +++ b/bedrock_processes_json/}bedrock.dim.sort.json @@ -1,6 +1,6 @@ { "Name": "}bedrock.dim.sort", - "PrologProcedure": "#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess('}bedrock.dim.sort',\r\n 'pCompSortType', 'ByName',\r\n 'pCompSortSense', 'Ascending',\r\n 'pElSortType', 'ByHierarchy',\r\n 'pElSortSense', 'Descending',\r\n 'pLogOutput', 0,\r\n 'pStrictErrorHandling', 0,\r\n 'pDim', '',\r\n 'pDelim', '&');\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n \r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n \r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n \r\n#Region @DOC\r\n# Description:\r\n# This process sets a dimension's sort order using the DimensionSortOrder function. pDimension\r\n# can use wildcards and/or a delimited list.\r\n \r\n# Note:\r\n# Valid dimension name (pDim) is mandatory.\r\n \r\n# Caution: \r\n# Existing DimensionSortOrder properties will be ignored and overwritten.\r\n#EndRegion @DOC\r\n \r\n### Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n \r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSubDim = cThisProcName |'_dims_'| cTimeStamp |'_'| cRandomInt;\r\ncTempSubHier = cThisProcName |'_hiers_'| cTimeStamp |'_'| cRandomInt;\r\ncUserName = TM1User();\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncMsgInfoContent = 'User:%cUserName% Process:%cThisProcName% Message:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters,\r\npCompSortType:%pCompSortType%,\r\npCompSortSense:%pCompSortSense%,\r\npElSortType:%pElSortType%,\r\npElSortSense:%pElSortSense%,\r\npLogOutput:%pLogOutput%,\r\npStrictErrorHandling:%pStrictErrorHandling%,\r\npDim:%pDim%,\r\npDelim:%pDelim%.'; \r\n \r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n \r\n### Validate Parameters ###\r\nnErrors = 0;\r\n \r\n# Validate dimension\r\nIf( Trim( pDim ) @= '' );\r\n nErrors = 1;\r\n sMessage = 'No dimension specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate DimensionSortOrder parameters\r\npCompSortType = UPPER( TRIM( pCompSortType ) );\r\npCompSortSense = UPPER( TRIM( pCompSortSense ) );\r\npElSortType = UPPER( TRIM( pElSortType ) );\r\npElSortSense = UPPER( TRIM( pElSortSense ) );\r\n\r\nIF( pCompSortType @<> 'BYINPUT' & pCompSortType @<> 'BYNAME' );\r\n nErrors = 1;\r\n sMessage = 'Invalid Value for pCompSortType: \"' | pCompSortType | '\". Must be \"ByInput\" or \"ByName\".';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nENDIF;\r\n\r\nIF( pCompSortSense @<> 'ASCENDING' & pCompSortSense @<> 'DESCENDING' );\r\n nErrors = 1;\r\n sMessage = 'Invalid Value for pCompSortSense: \"' | pCompSortSense | '\". Must be \"Ascending\" or \"Descending\".';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nENDIF;\r\n\r\nIF( pElSortType @<> 'BYINPUT' & pElSortType @<> 'BYNAME' & pElSortType @<> 'BYLEVEL' & pElSortType @<> 'BYHIERARCHY' );\r\n nErrors = 1;\r\n sMessage = 'Invalid Value for pElSortType: \"' | pElSortType | '\". Must be \"ByInput\" or \"ByName\" or \"ByLevel\" or \"ByHierarchy\".';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nENDIF;\r\n\r\nIF( pElSortSense @<> 'ASCENDING' & pElSortSense @<> 'DESCENDING' );\r\n nErrors = 1;\r\n sMessage = 'Invalid Value for pElSortSense: \"' | pElSortSense | '\". Must be \"Ascending\" or \"Descending\".';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nENDIF;\r\n \r\n# If blank delimiter specified then convert to default\r\nIf( pDelim @= '' );\r\n pDelim = '&';\r\nEndIf;\r\n \r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n\r\n# Loop through dimensions in pDim\r\nsDims = pDim;\r\nnDimDelimiterIndex = 1;\r\nsMdx = '';\r\n# Get 1st dimension\r\nWhile( nDimDelimiterIndex <> 0 );\r\n # Extract 1st dimension > sDim\r\n nDimDelimiterIndex = Scan( pDelim, sDims );\r\n If( nDimDelimiterIndex = 0 );\r\n sDim = sDims;\r\n Else;\r\n sDim = Trim( SubSt( sDims, 1, nDimDelimiterIndex - 1 ) );\r\n sDims = Trim( Subst( sDims, nDimDelimiterIndex + Long(pDelim), Long( sDims ) ) );\r\n EndIf;\r\n \r\n # Create subset of dimensions using Wildcard to loop through dimensions in pDim with wildcard\r\n sDimExp = '\"'|sDim|'\"';\r\n sMdxPart = '{TM1FILTERBYPATTERN( EXCEPT( TM1SUBSETALL( [}Dimensions] ) , TM1FILTERBYPATTERN( TM1SUBSETALL( [}Dimensions] ) , \"*:*\") ) ,'| sDimExp | ')}';\r\n IF( sMdx @= ''); \r\n sMdx = sMdxPart; \r\n ELSE;\r\n sMdx = sMdx | ' + ' | sMdxPart;\r\n ENDIF;\r\nEnd;\r\n \r\nIf( SubsetExists( '}Dimensions' , cTempSubDim ) = 1 );\r\n # If a delimited list of dim names includes wildcards then we may have to re-use the subset multiple times\r\n SubsetMDXSet( '}Dimensions' , cTempSubDim, sMDX );\r\nElse;\r\n # temp subset, therefore no need to destroy in epilog\r\n SubsetCreatebyMDX( cTempSubDim, sMDX, '}Dimensions' , 1 );\r\nEndIf;\r\n \r\n# Loop through dimensions in subset created based on wildcard\r\nnCountDim = SubsetGetSize( '}Dimensions' , cTempSubDim );\r\nWhile( nCountDim >= 1 );\r\n sDim = SubsetGetElementName( '}Dimensions' , cTempSubDim, nCountDim );\r\n # Validate dimension name\r\n If( DimensionExists(sDim) = 0 );\r\n nErrors = 1;\r\n sMessage = Expand( 'Dimension %sDim% does not exist.' );\r\n LogOutput( 'ERROR', Expand( cMsgErrorContent ) );\r\n Else;\r\n If( pLogOutput = 1 );\r\n sMessage = Expand( 'Dimension %sDim% being processed....' );\r\n LogOutput( 'INFO', Expand( cMsgInfoContent ) );\r\n EndIf;\r\n \r\n DimensionSortOrder( sDim, pCompSortType, pCompSortSense, pElSortType, pElSortSense );\r\n \r\n EndIf;\r\n \r\n nCountDim = nCountDim - 1;\r\nEnd;", + "PrologProcedure": "#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess('}bedrock.dim.sort',\r\n 'pCompSortType', 'ByName',\r\n 'pCompSortSense', 'Ascending',\r\n 'pElSortType', 'ByHierarchy',\r\n 'pElSortSense', 'Descending',\r\n 'pLogOutput', 0,\r\n 'pStrictErrorHandling', 0,\r\n 'pDim', '',\r\n 'pDelim', '&');\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n \r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n \r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n \r\n#Region @DOC\r\n# Description:\r\n# This process sets a dimension's sort order using the DimensionSortOrder function. pDimension\r\n# can use wildcards and/or a delimited list.\r\n \r\n# Note:\r\n# Valid dimension name (pDim) is mandatory.\r\n \r\n# Caution: \r\n# Existing DimensionSortOrder properties will be ignored and overwritten.\r\n#EndRegion @DOC\r\n \r\n### Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n \r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSubDim = cThisProcName |'_dims_'| cTimeStamp |'_'| cRandomInt;\r\ncTempSubHier = cThisProcName |'_hiers_'| cTimeStamp |'_'| cRandomInt;\r\ncUserName = TM1User();\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncMsgInfoContent = 'User:%cUserName% Process:%cThisProcName% Message:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters,\r\npCompSortType:%pCompSortType%,\r\npCompSortSense:%pCompSortSense%,\r\npElSortType:%pElSortType%,\r\npElSortSense:%pElSortSense%,\r\npLogOutput:%pLogOutput%,\r\npStrictErrorHandling:%pStrictErrorHandling%,\r\npDim:%pDim%,\r\npDelim:%pDelim%.';\r\n\r\n#################################################################################################\r\n#Region - Process Parameters\r\n\r\npJson = IF( JsonType( pJson ) @<> 'object', '{}', pJson );\r\nsMessages = '{\"Process\": \"'|GetProcessName()|'\", \"User\": \"'|TM1User()|'\", \"Info\": [\"Process: '''|GetProcessName()|''' run by User: '''|TM1User()|'''.\"], \"Error\": []}';\r\npDefaultParameters = '{\r\n \"pCompSortSense\": \"Ascending\",\r\n \"pCompSortType\": \"ByName\",\r\n \"pDelim\": \"&\",\r\n \"pDim\": null,\r\n \"pElSortSense\": \"Descending\",\r\n \"pElSortType\": \"ByHierarchy\",\r\n \"pLogOutput\": 0,\r\n \"pStrictErrorHandling\": 0\r\n}';\r\n\r\npPassedParameters = '{\r\n \"pCompSortSense\": '|StringToJson ( pCompSortSense )|',\r\n \"pCompSortType\": '|StringToJson ( pCompSortType )|',\r\n \"pDelim\": '|StringToJson ( pDelim )|',\r\n \"pDim\": '|StringToJson ( pDim )|',\r\n \"pElSortSense\": '|StringToJson ( pElSortSense )|',\r\n \"pElSortType\": '|StringToJson ( pElSortType )|',\r\n \"pLogOutput\": '|NumberToString( pLogOutput )|',\r\n \"pStrictErrorHandling\": '|NumberToString( pStrictErrorHandling )|'\r\n}';\r\n\r\npJson = JsonMergePatch( pPassedParameters, pJson );\r\n# String Parameters\r\npCompSortSense = JsonToString( JsonGet( pJson, 'pCompSortSense' ) );\r\npCompSortType = JsonToString( JsonGet( pJson, 'pCompSortType' ) );\r\npDelim = JsonToString( JsonGet( pJson, 'pDelim' ) );\r\npDim = JsonToString( JsonGet( pJson, 'pDim' ) );\r\npElSortSense = JsonToString( JsonGet( pJson, 'pElSortSense' ) );\r\npElSortType = JsonToString( JsonGet( pJson, 'pElSortType' ) );\r\n# Numeric Parameters\r\npLogOutput = StringToNumber( JsonToString( JsonGet( pJson, 'pLogOutput' ) ) );\r\npStrictErrorHandling = StringToNumber( JsonToString( JsonGet( pJson, 'pStrictErrorHandling' ) ) );\r\n\r\n### Get the parameters that differ from the default\r\npDiffer = JsonDiff( pDefaultParameters, pJson );\r\nnSize = JsonSize( pDiffer );\r\nWHILE( nSize > 0 );\r\n nSize = nSize - 1;\r\n pDiffer = JsonReplace( pDiffer, '/'|NumberToString( nSize )|'/op', '\"add\"' );\r\nEND;\r\npJson = JsonPatch( '{}', pDiffer );\r\n\r\n### LogOutput parameters\r\nsMessages = JsonAdd( sMessages, '/Info/-', pJson );\r\nIF( pLogOutput = 1 );\r\n LogOutput('INFO', JsonToString( sMessages, '/Info/0', 0, ' ' ) );\r\nENDIF;\r\n\r\n#EndRegion - Process Parameters\r\n#################################################################################################\r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n \r\n### Validate Parameters ###\r\nnErrors = 0;\r\n \r\n# Validate dimension\r\nIf( Trim( pDim ) @= '' );\r\n nErrors = 1;\r\n sMessage = 'No dimension specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate DimensionSortOrder parameters\r\npCompSortType = UPPER( TRIM( pCompSortType ) );\r\npCompSortSense = UPPER( TRIM( pCompSortSense ) );\r\npElSortType = UPPER( TRIM( pElSortType ) );\r\npElSortSense = UPPER( TRIM( pElSortSense ) );\r\n\r\nIF( pCompSortType @<> 'BYINPUT' & pCompSortType @<> 'BYNAME' );\r\n nErrors = 1;\r\n sMessage = 'Invalid Value for pCompSortType: \"' | pCompSortType | '\". Must be \"ByInput\" or \"ByName\".';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nENDIF;\r\n\r\nIF( pCompSortSense @<> 'ASCENDING' & pCompSortSense @<> 'DESCENDING' );\r\n nErrors = 1;\r\n sMessage = 'Invalid Value for pCompSortSense: \"' | pCompSortSense | '\". Must be \"Ascending\" or \"Descending\".';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nENDIF;\r\n\r\nIF( pElSortType @<> 'BYINPUT' & pElSortType @<> 'BYNAME' & pElSortType @<> 'BYLEVEL' & pElSortType @<> 'BYHIERARCHY' );\r\n nErrors = 1;\r\n sMessage = 'Invalid Value for pElSortType: \"' | pElSortType | '\". Must be \"ByInput\" or \"ByName\" or \"ByLevel\" or \"ByHierarchy\".';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nENDIF;\r\n\r\nIF( pElSortSense @<> 'ASCENDING' & pElSortSense @<> 'DESCENDING' );\r\n nErrors = 1;\r\n sMessage = 'Invalid Value for pElSortSense: \"' | pElSortSense | '\". Must be \"Ascending\" or \"Descending\".';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nENDIF;\r\n \r\n# If blank delimiter specified then convert to default\r\nIf( pDelim @= '' );\r\n pDelim = '&';\r\nEndIf;\r\n \r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n\r\n# Loop through dimensions in pDim\r\nsDims = pDim;\r\nnDimDelimiterIndex = 1;\r\nsMdx = '';\r\n# Get 1st dimension\r\nWhile( nDimDelimiterIndex <> 0 );\r\n # Extract 1st dimension > sDim\r\n nDimDelimiterIndex = Scan( pDelim, sDims );\r\n If( nDimDelimiterIndex = 0 );\r\n sDim = sDims;\r\n Else;\r\n sDim = Trim( SubSt( sDims, 1, nDimDelimiterIndex - 1 ) );\r\n sDims = Trim( Subst( sDims, nDimDelimiterIndex + Long(pDelim), Long( sDims ) ) );\r\n EndIf;\r\n \r\n # Create subset of dimensions using Wildcard to loop through dimensions in pDim with wildcard\r\n sDimExp = '\"'|sDim|'\"';\r\n sMdxPart = '{TM1FILTERBYPATTERN( EXCEPT( TM1SUBSETALL( [}Dimensions] ) , TM1FILTERBYPATTERN( TM1SUBSETALL( [}Dimensions] ) , \"*:*\") ) ,'| sDimExp | ')}';\r\n IF( sMdx @= ''); \r\n sMdx = sMdxPart; \r\n ELSE;\r\n sMdx = sMdx | ' + ' | sMdxPart;\r\n ENDIF;\r\nEnd;\r\n \r\nIf( SubsetExists( '}Dimensions' , cTempSubDim ) = 1 );\r\n # If a delimited list of dim names includes wildcards then we may have to re-use the subset multiple times\r\n SubsetMDXSet( '}Dimensions' , cTempSubDim, sMDX );\r\nElse;\r\n # temp subset, therefore no need to destroy in epilog\r\n SubsetCreatebyMDX( cTempSubDim, sMDX, '}Dimensions' , 1 );\r\nEndIf;\r\n \r\n# Loop through dimensions in subset created based on wildcard\r\nnCountDim = SubsetGetSize( '}Dimensions' , cTempSubDim );\r\nWhile( nCountDim >= 1 );\r\n sDim = SubsetGetElementName( '}Dimensions' , cTempSubDim, nCountDim );\r\n # Validate dimension name\r\n If( DimensionExists(sDim) = 0 );\r\n nErrors = 1;\r\n sMessage = Expand( 'Dimension %sDim% does not exist.' );\r\n LogOutput( 'ERROR', Expand( cMsgErrorContent ) );\r\n Else;\r\n If( pLogOutput = 1 );\r\n sMessage = Expand( 'Dimension %sDim% being processed....' );\r\n LogOutput( 'INFO', Expand( cMsgInfoContent ) );\r\n EndIf;\r\n \r\n DimensionSortOrder( sDim, pCompSortType, pCompSortSense, pElSortType, pElSortSense );\r\n \r\n EndIf;\r\n \r\n nCountDim = nCountDim - 1;\r\nEnd;", "MetadataProcedure": "#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "DataProcedure": "#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "EpilogProcedure": "#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n### Return code & final error message handling\r\nIf( nErrors > 0 );\r\n sMessage = 'the process incurred at least 1 error. Please see above lines in this file for more details.';\r\n nProcessReturnCode = 0;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% Process:%cThisProcName% completed with errors. Check tm1server.log for details.' );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n EndIf;\r\nElse;\r\n sProcessAction = Expand( 'Process:%cThisProcName% sorted dimensions: \"%pDim%\" with the following values: pCompSortType=%pCompSortType%, pCompSortSense=%pCompSortSense%, pElSortType=%pElSortType%, pElSortSense=%pElSortSense%' );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% %sProcessAction%' );\r\n nProcessReturnCode = 1;\r\n If( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( sProcessAction ) ); \r\n EndIf;\r\nEndIf;\r\n\r\n\r\n### End Epilog ###", @@ -12,50 +12,56 @@ "Parameters": [ { "Name": "pCompSortType", - "Prompt": "REQUIRED: sort type for components of consolidated elements \u200b", + "Prompt": "OPTIONAL: Consolidated elements' components sort type (Default = 'ByName')", "Value": "ByName", "Type": "String" }, { "Name": "pCompSortSense", - "Prompt": "REQUIRED: the sense of order for CompSortType either \u2018Ascending\u2019 or \u2018Descending\u2019. This applies only when the CompSortType is ByName. \u200b", + "Prompt": "OPTIONAL: Sort sense for pCompSortType (Default = 'Ascending')", "Value": "Ascending", "Type": "String" }, { "Name": "pElSortType", - "Prompt": "REQUIRED: sort type for all elements\u200b", + "Prompt": "OPTIONAL: Elements' sort type (Default = 'ByHierarchy')", "Value": "ByHierarchy", "Type": "String" }, { "Name": "pElSortSense", - "Prompt": "REQUIRED: the sense of order for ElSortType either \u2018Ascending\u2019 or \u2018Descending\u2019. This applies only when the ElSortType is ByName.\u200b", + "Prompt": "OPTIONAL: Sort sense for pElSortType (Default = 'Descending')", "Value": "Descending", "Type": "String" }, + { + "Name": "pDim", + "Prompt": "REQUIRED: Delimited list of dimensions", + "Value": "", + "Type": "String" + }, + { + "Name": "pDelim", + "Prompt": "OPTIONAL: Delimiter for list parameters (Default = '&')", + "Value": "&", + "Type": "String" + }, { "Name": "pLogOutput", - "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean True = 1)", + "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" }, { "Name": "pStrictErrorHandling", - "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean True = 1)", + "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" }, { - "Name": "pDim", - "Prompt": "REQUIRED: dimension name, accepts wildcards (if = *, then all the dimensions)", - "Value": "", - "Type": "String" - }, - { - "Name": "pDelim", - "Prompt": "OPTIONAL: delimiter character for element list. (default value if blank = '&')", - "Value": "&", + "Name": "pJson", + "Prompt": "OPTIONAL: JSON Object with process parameter values. This will overwrite user passed parameters for all included parameters.", + "Value": "{}", "Type": "String" } ], diff --git a/bedrock_processes_json/}bedrock.hier.clone.json b/bedrock_processes_json/}bedrock.hier.clone.json index 3ae9d37..c283390 100644 --- a/bedrock_processes_json/}bedrock.hier.clone.json +++ b/bedrock_processes_json/}bedrock.hier.clone.json @@ -1,6 +1,6 @@ { "Name": "}bedrock.hier.clone", - "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.hier.clone', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pSrcDim', '', 'pSrcHier', '',\r\n \t'pTgtDim', '', 'pTgtHier', '',\r\n \t'pAttr', 0, 'pUnwind', 0\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process will clone the source dimension Hierarchy.\r\n\r\n# Use case: Mostly in Development.\r\n# 1/ Create a duplicate of an existing hierarchy for testing.\r\n\r\n# Note:\r\n# Valid source dimension name (pSrcDim) and target dimension (pTgtDim) names are mandatory otherwise the process will abort.\r\n# Valid source hierarchy name (pSrcHier) is mandatory otherwise the process will abort.\r\n\r\n# Caution:\r\n# - Target hierarchy cannot be `Leaves`.\r\n# - If the target dimension Hierarchy exists then it will be overwritten.\r\n#EndRegion @DOC\r\n\r\n### Global Varaibales ###\r\nStringGlobalVariable ('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode = 0;\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSub = cThisProcName |'_'| cTimeStamp |'_'| cRandomInt;\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = '%cThisProcName% : %sMessage% : %cUserName%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pSrcDim:%pSrcDim%, pSrcHier:%pSrcHier%, pTgtDim:%pTgtDim%, pTgtHier:%pTgtHier%, pAttr:%pAttr%, pUnwind:%pUnwind%.';\r\ncLangDim = '}Cultures';\r\nnNumLang = DimSiz( cLangDim );\r\n\r\nnProcessSameNamedHier = 0;\r\nsEpilogTgtHier = '';\r\n\r\n## LogOutput parameters\r\nIF ( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\n### Validate Parameters ###\r\nnErrors = 0;\r\n\r\nIf( Scan( ':', pSrcDim ) > 0 & pSrcHier @= '' );\r\n # A hierarchy has been passed as dimension. Handle the input error by splitting dim:hier into dimension & hierarchy\r\n pSrcHier = SubSt( pSrcDim, Scan( ':', pSrcDim ) + 1, Long( pSrcDim ) );\r\n pSrcDim = SubSt( pSrcDim, 1, Scan( ':', pSrcDim ) - 1 );\r\nEndIf;\r\n\r\n## Validate Source dimension\r\nIF( Trim( pSrcDim ) @= '' );\r\n nErrors = 1;\r\n sMessage = 'No source dimension specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\nIF( DimensionExists( pSrcDim ) = 0 );\r\n nErrors = 1;\r\n sMessage = 'Invalid source dimension: ' | pSrcDim;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate Source hierarchy\r\nIF( Trim( pSrcHier ) @= '' );\r\n pSrcHier = pSrcDim;\r\nElseIF(HierarchyExists(pSrcDim,pSrcHier ) = 0 );\r\n nErrors = 1;\r\n sMessage = 'Invalid source hierarchy: ' | pSrcHier;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate Target dimension\r\nIF( Trim( pTgtDim ) @= '' );\r\n nErrors = 1;\r\n sMessage = 'No target dimension specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( Scan( ':', pTgtDim ) > 0 & pTgtHier @= '' );\r\n # A hierarchy has been passed as dimension. Handle the input error by splitting dim:hier into dimension & hierarchy\r\n pTgtHier = SubSt( pTgtDim, Scan( ':', pTgtDim ) + 1, Long( pTgtDim ) );\r\n pTgtDim = SubSt( pTgtDim, 1, Scan( ':', pTgtDim ) - 1 );\r\nEndIf;\r\n\r\nIf ( DimensionExists( pTgtDim ) = 0 );\r\n DimensionCreate( pTgtDim );\r\n ### In this case clone source hierarchy into same-named hierarchy of the new target dimension first. This will allow attributes to be processed in the data tab.\r\n nProcessSameNamedHier = 1;\r\nEndIf;\r\n\r\n# Validate target hierarchy\r\nIf( pSrcDim @= pTgtDim);\r\n If( pTgtHier @= '' % pTgtHier @= pSrcHier );\r\n pTgtHier = pSrcHier | '_Clone';\r\n EndIf;\r\nElseIf(pTgtHier @= '');\r\n If( nProcessSameNamedHier = 1 );\r\n sEpilogTgtHier = pTgtHier;\r\n pTgtHier = pTgtDim;\r\n Else;\r\n pTgtHier = pSrcHier;\r\n EndIf;\r\nElseIf( nProcessSameNamedHier = 1 );\r\n sEpilogTgtHier = pTgtHier;\r\n pTgtHier = pTgtDim;\r\nEndif;\r\n\r\npTgtHier = Trim(pTgtHier);\r\n\r\nIF(pTgtHier @= 'Leaves' );\r\n nErrors = 1;\r\n sMessage = 'Leaves is an invalid selection for Target Hierarchy: ' | pTgtDim |':'|pTgtHier;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\nIf( DimensionExists( pTgtDim ) = 0 );\r\n If( pUnwind >= 1 );\r\n pUnwind = 2;\r\n EndIf;\r\nElseIf( HierarchyExists( pTgtDim, pTgtHier ) = 0 );\r\n If( pUnwind >= 1 );\r\n pUnwind = 2;\r\n EndIf;\r\nEndIf; \r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n### Create target dimension Hierarchy ###\r\nIf( HierarchyExists( pTgtDim, pTgtHier) = 0 );\r\n HierarchyCreate( pTgtDim, pTgtHier );\r\nElse;\r\n IF(pUnwind = 1 );\r\n nRet = ExecuteProcess('}bedrock.hier.unwind',\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pDim', pTgtDim,\r\n 'pHier', pTgtHier,\r\n 'pConsol', '*',\r\n 'pRecursive', 1\r\n );\r\n ELSEIF(pUnwind = 2 );\r\n #Do nothing\r\n ELSEIF(pUnwind = 0 );\r\n HierarchyDeleteAllElements( pTgtDim, pTgtHier );\r\n EndIf;\r\nEndIf;\r\n \r\nIf(pSrcDim @=pSrcHier);\r\n sDimHier = pSrcDim;\r\n Else;\r\n sDimHier =pSrcDim|':'|pSrcHier;\r\n Endif;\r\n \r\n### Set the target Sort Order ###\r\n# CellGetS to }DimensionProperties cube removed\r\n# Placeholder as expecting a TI function to be made available to be able to read these properties\r\n\r\n#HierarchySortOrder(pTgtDim, pTgtHier, sSortComponentsType, sSortComponentsSense, sSortElementsType , sSortElementsSense);\r\n\r\nnSourceHierSize = DimSiz(pSrcDim|':'|pSrcHier);\r\n\r\nnIndex = 1;\r\nWHILE( nIndex <= nSourceHierSize );\r\n sElName = ElementName(pSrcDim, pSrcHier, nIndex);\r\n sElType = ElementType(pSrcDim, pSrcHier, sElName);\r\n HierarchyElementInsert(pTgtDim, pTgtHier, '', sElName, sElType);\r\n nIndex = nIndex + 1;\r\nEND;\r\n\r\n### Assign Data Source ###\r\n\r\nDatasourceNameForServer = pSrcDim|':'|pSrcHier;\r\nDataSourceType = 'SUBSET';\r\nDatasourceDimensionSubset = 'ALL';\r\n\r\n### Replicate Attributes ###\r\n\r\n# Note: DType on Attr dim returns \"AS\", \"AN\" or \"AA\" need to strip off leading \"A\"\r\n\r\nsAttrDim = '}ElementAttributes_' | pSrcDim;\r\nsAttrLoc = '}LocalizedElementAttributes_' | pSrcDim;\r\nsAttrTragetDim = '}ElementAttributes_' | pTgtDim;\r\nsAttrLocTarget = '}LocalizedElementAttributes_' | pTgtDim;\r\n\r\nIf( pAttr = 1 & DimensionExists( sAttrDim ) = 1 );\r\n nNumAttrs = DimSiz( sAttrDim );\r\n nCount = 1;\r\n While( nCount <= nNumAttrs );\r\n sAttrName = DimNm( sAttrDim, nCount );\r\n sAttrType = SubSt(DType( sAttrDim, sAttrName ), 2, 1 );\r\n If ( DimensionExists( sAttrTragetDim ) = 0);\r\n AttrInsert(pTgtDim,'',sAttrName,sAttrType );\r\n ElseIF(DimIx(sAttrTragetDim, sAttrName) = 0);\r\n AttrInsert(pTgtDim,'',sAttrName,sAttrType );\r\n Endif;\r\n nCount = nCount + 1;\r\n End;\r\nEndIf;\r\n\r\n### End Prolog ###", + "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.hier.clone', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pSrcDim', '', 'pSrcHier', '',\r\n \t'pTgtDim', '', 'pTgtHier', '',\r\n \t'pAttr', 0, 'pUnwind', 0\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process will clone the source dimension Hierarchy.\r\n\r\n# Use case: Mostly in Development.\r\n# 1/ Create a duplicate of an existing hierarchy for testing.\r\n\r\n# Note:\r\n# Valid source dimension name (pSrcDim) and target dimension (pTgtDim) names are mandatory otherwise the process will abort.\r\n# Valid source hierarchy name (pSrcHier) is mandatory otherwise the process will abort.\r\n\r\n# Caution:\r\n# - Target hierarchy cannot be `Leaves`.\r\n# - If the target dimension Hierarchy exists then it will be overwritten.\r\n#EndRegion @DOC\r\n\r\n### Global Varaibales ###\r\nStringGlobalVariable ('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode = 0;\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSub = cThisProcName |'_'| cTimeStamp |'_'| cRandomInt;\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = '%cThisProcName% : %sMessage% : %cUserName%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pSrcDim:%pSrcDim%, pSrcHier:%pSrcHier%, pTgtDim:%pTgtDim%, pTgtHier:%pTgtHier%, pAttr:%pAttr%, pUnwind:%pUnwind%.';\r\ncLangDim = '}Cultures';\r\nnNumLang = DimSiz( cLangDim );\r\n\r\n#################################################################################################\r\n#Region - Process Parameters\r\n\r\npJson = IF( JsonType( pJson ) @<> 'object', '{}', pJson );\r\nsMessages = '{\"Process\": \"'|GetProcessName()|'\", \"User\": \"'|TM1User()|'\", \"Info\": [\"Process: '''|GetProcessName()|''' run by User: '''|TM1User()|'''.\"], \"Error\": []}';\r\npDefaultParameters = '{\r\n \"pSrcDim\": null,\r\n \"pSrcHier\": null,\r\n \"pTgtDim\": \"\",\r\n \"pTgtHier\": \"\",\r\n \"pAttr\": 0,\r\n \"pLogOutput\": 0,\r\n \"pStrictErrorHandling\": 0,\r\n \"pUnwind\": 0\r\n}';\r\n\r\npPassedParameters = '{\r\n \"pSrcDim\": '|StringToJson ( pSrcDim )|',\r\n \"pSrcHier\": '|StringToJson ( pSrcHier )|',\r\n \"pTgtDim\": '|StringToJson ( pTgtDim )|',\r\n \"pTgtHier\": '|StringToJson ( pTgtHier )|',\r\n \"pAttr\": '|NumberToString( pAttr )|',\r\n \"pLogOutput\": '|NumberToString( pLogOutput )|',\r\n \"pStrictErrorHandling\": '|NumberToString( pStrictErrorHandling )|',\r\n \"pUnwind\": '|NumberToString( pUnwind )|'\r\n}';\r\n\r\npJson = JsonMergePatch( pPassedParameters, pJson );\r\n# String Parameters\r\npSrcDim = JsonToString( JsonGet( pJson, 'pSrcDim' ) );\r\npSrcHier = JsonToString( JsonGet( pJson, 'pSrcHier' ) );\r\npTgtDim = JsonToString( JsonGet( pJson, 'pTgtDim' ) );\r\npTgtHier = JsonToString( JsonGet( pJson, 'pTgtHier' ) );\r\n# Numeric Parameters\r\npAttr = StringToNumber( JsonToString( JsonGet( pJson, 'pAttr' ) ) );\r\npLogOutput = StringToNumber( JsonToString( JsonGet( pJson, 'pLogOutput' ) ) );\r\npStrictErrorHandling = StringToNumber( JsonToString( JsonGet( pJson, 'pStrictErrorHandling' ) ) );\r\npUnwind = StringToNumber( JsonToString( JsonGet( pJson, 'pUnwind' ) ) );\r\n\r\n### Get the parameters that differ from the default\r\npDiffer = JsonDiff( pDefaultParameters, pJson );\r\nnSize = JsonSize( pDiffer );\r\nWHILE( nSize > 0 );\r\n nSize = nSize - 1;\r\n pDiffer = JsonReplace( pDiffer, '/'|NumberToString( nSize )|'/op', '\"add\"' );\r\nEND;\r\npJson = JsonPatch( '{}', pDiffer );\r\n\r\n### LogOutput parameters\r\nsMessages = JsonAdd( sMessages, '/Info/-', pJson );\r\nIF( pLogOutput = 1 );\r\n LogOutput('INFO', JsonToString( sMessages, '/Info/0', 0, ' ' ) );\r\nENDIF;\r\n\r\n#EndRegion - Process Parameters\r\n#################################################################################################\r\n\r\nnProcessSameNamedHier = 0;\r\nsEpilogTgtHier = '';\r\n\r\n## LogOutput parameters\r\nIF ( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\n### Validate Parameters ###\r\nnErrors = 0;\r\n\r\nIf( Scan( ':', pSrcDim ) > 0 & pSrcHier @= '' );\r\n # A hierarchy has been passed as dimension. Handle the input error by splitting dim:hier into dimension & hierarchy\r\n pSrcHier = SubSt( pSrcDim, Scan( ':', pSrcDim ) + 1, Long( pSrcDim ) );\r\n pSrcDim = SubSt( pSrcDim, 1, Scan( ':', pSrcDim ) - 1 );\r\nEndIf;\r\n\r\n## Validate Source dimension\r\nIF( Trim( pSrcDim ) @= '' );\r\n nErrors = 1;\r\n sMessage = 'No source dimension specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\nIF( DimensionExists( pSrcDim ) = 0 );\r\n nErrors = 1;\r\n sMessage = 'Invalid source dimension: ' | pSrcDim;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate Source hierarchy\r\nIF( Trim( pSrcHier ) @= '' );\r\n pSrcHier = pSrcDim;\r\nElseIF(HierarchyExists(pSrcDim,pSrcHier ) = 0 );\r\n nErrors = 1;\r\n sMessage = 'Invalid source hierarchy: ' | pSrcHier;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# Validate Target dimension\r\nIF( Trim( pTgtDim ) @= '' );\r\n nErrors = 1;\r\n sMessage = 'No target dimension specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( Scan( ':', pTgtDim ) > 0 & pTgtHier @= '' );\r\n # A hierarchy has been passed as dimension. Handle the input error by splitting dim:hier into dimension & hierarchy\r\n pTgtHier = SubSt( pTgtDim, Scan( ':', pTgtDim ) + 1, Long( pTgtDim ) );\r\n pTgtDim = SubSt( pTgtDim, 1, Scan( ':', pTgtDim ) - 1 );\r\nEndIf;\r\n\r\nIf ( DimensionExists( pTgtDim ) = 0 );\r\n DimensionCreate( pTgtDim );\r\n ### In this case clone source hierarchy into same-named hierarchy of the new target dimension first. This will allow attributes to be processed in the data tab.\r\n nProcessSameNamedHier = 1;\r\nEndIf;\r\n\r\n# Validate target hierarchy\r\nIf( pSrcDim @= pTgtDim);\r\n If( pTgtHier @= '' % pTgtHier @= pSrcHier );\r\n pTgtHier = pSrcHier | '_Clone';\r\n EndIf;\r\nElseIf(pTgtHier @= '');\r\n If( nProcessSameNamedHier = 1 );\r\n sEpilogTgtHier = pTgtHier;\r\n pTgtHier = pTgtDim;\r\n Else;\r\n pTgtHier = pSrcHier;\r\n EndIf;\r\nElseIf( nProcessSameNamedHier = 1 );\r\n sEpilogTgtHier = pTgtHier;\r\n pTgtHier = pTgtDim;\r\nEndif;\r\n\r\npTgtHier = Trim(pTgtHier);\r\n\r\nIF(pTgtHier @= 'Leaves' );\r\n nErrors = 1;\r\n sMessage = 'Leaves is an invalid selection for Target Hierarchy: ' | pTgtDim |':'|pTgtHier;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\nIf( DimensionExists( pTgtDim ) = 0 );\r\n If( pUnwind >= 1 );\r\n pUnwind = 2;\r\n EndIf;\r\nElseIf( HierarchyExists( pTgtDim, pTgtHier ) = 0 );\r\n If( pUnwind >= 1 );\r\n pUnwind = 2;\r\n EndIf;\r\nEndIf; \r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n### Create target dimension Hierarchy ###\r\nIf( HierarchyExists( pTgtDim, pTgtHier) = 0 );\r\n HierarchyCreate( pTgtDim, pTgtHier );\r\nElse;\r\n IF(pUnwind = 1 );\r\n nRet = ExecuteProcess('}bedrock.hier.unwind',\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pDim', pTgtDim,\r\n 'pHier', pTgtHier,\r\n 'pConsol', '*',\r\n 'pRecursive', 1\r\n );\r\n ELSEIF(pUnwind = 2 );\r\n #Do nothing\r\n ELSEIF(pUnwind = 0 );\r\n HierarchyDeleteAllElements( pTgtDim, pTgtHier );\r\n EndIf;\r\nEndIf;\r\n \r\nIf(pSrcDim @=pSrcHier);\r\n sDimHier = pSrcDim;\r\n Else;\r\n sDimHier =pSrcDim|':'|pSrcHier;\r\n Endif;\r\n \r\n### Set the target Sort Order ###\r\n# CellGetS to }DimensionProperties cube removed\r\n# Placeholder as expecting a TI function to be made available to be able to read these properties\r\n\r\n#HierarchySortOrder(pTgtDim, pTgtHier, sSortComponentsType, sSortComponentsSense, sSortElementsType , sSortElementsSense);\r\n\r\nnSourceHierSize = DimSiz(pSrcDim|':'|pSrcHier);\r\n\r\nnIndex = 1;\r\nWHILE( nIndex <= nSourceHierSize );\r\n sElName = ElementName(pSrcDim, pSrcHier, nIndex);\r\n sElType = ElementType(pSrcDim, pSrcHier, sElName);\r\n HierarchyElementInsert(pTgtDim, pTgtHier, '', sElName, sElType);\r\n nIndex = nIndex + 1;\r\nEND;\r\n\r\n### Assign Data Source ###\r\n\r\nDatasourceNameForServer = pSrcDim|':'|pSrcHier;\r\nDataSourceType = 'SUBSET';\r\nDatasourceDimensionSubset = 'ALL';\r\n\r\n### Replicate Attributes ###\r\n\r\n# Note: DType on Attr dim returns \"AS\", \"AN\" or \"AA\" need to strip off leading \"A\"\r\n\r\nsAttrDim = '}ElementAttributes_' | pSrcDim;\r\nsAttrLoc = '}LocalizedElementAttributes_' | pSrcDim;\r\nsAttrTragetDim = '}ElementAttributes_' | pTgtDim;\r\nsAttrLocTarget = '}LocalizedElementAttributes_' | pTgtDim;\r\n\r\nIf( pAttr = 1 & DimensionExists( sAttrDim ) = 1 );\r\n nNumAttrs = DimSiz( sAttrDim );\r\n nCount = 1;\r\n While( nCount <= nNumAttrs );\r\n sAttrName = DimNm( sAttrDim, nCount );\r\n sAttrType = SubSt(DType( sAttrDim, sAttrName ), 2, 1 );\r\n If ( DimensionExists( sAttrTragetDim ) = 0);\r\n AttrInsert(pTgtDim,'',sAttrName,sAttrType );\r\n ElseIF(DimIx(sAttrTragetDim, sAttrName) = 0);\r\n AttrInsert(pTgtDim,'',sAttrName,sAttrType );\r\n Endif;\r\n nCount = nCount + 1;\r\n End;\r\nEndIf;\r\n\r\n### End Prolog ###", "MetadataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock Ver 4.0.0~~##\r\n################################################################################################# \r\n\r\n\r\n### Check for errors in prolog ###\r\n\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n### Add Elements to target dimension ###\r\n\r\nsElType = ElementType(pSrcDim, pSrcHier, vEle);\r\n\r\nIF( sElType @= 'C' & ElementComponentCount( pSrcDim, pSrcHier, vEle ) > 0 );\r\n nChildren = ElementComponentCount( pSrcDim, pSrcHier, vEle );\r\n nCount = 1;\r\n While( nCount <= nChildren );\r\n sChildElement = ElementComponent( pSrcDim, pSrcHier, vEle, nCount );\r\n sChildWeight = ElementWeight( pSrcDim,pSrcHier, vEle, sChildElement );\r\n HierarchyElementComponentAdd(pTgtDim, pTgtHier, vEle, sChildElement, sChildWeight);\r\n nCount = nCount + 1;\r\n End;\r\nEndIf;\r\n\r\n### End MetaData ###", "DataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock Ver 4.0.0~~##\r\n################################################################################################# \r\n\r\n\r\n### Check for errors in prolog ###\r\n\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n### Replicate Attributes ###\r\n# Note: DTYPE on Attr dim returns \"AS\", \"AN\" or \"AA\" need to strip off leading \"A\"\r\n\r\nIf( pAttr = 1 & DimensionExists( sAttrDim ) = 1 );\r\n\r\n nAttr = 1;\r\n While( nAttr <= nNumAttrs );\r\n sAttrName = DimNm( sAttrDim, nAttr );\r\n sAttrType = SubSt( DTYPE( sAttrDim, sAttrName ), 2, 1 );\r\n \r\n If( sAttrType @= 'S' % sAttrType @= 'A' );\r\n sAttrVal = ElementAttrS( pSrcDim, pSrcHier, vEle, sAttrName );\r\n \r\n If( sAttrVal @<> '' );\r\n If( CellIsUpdateable( '}ElementAttributes_' | pTgtDim, pTgtHier:vEle, sAttrName ) = 1 );\r\n If( sAttrType @= 'A' );\r\n ElementAttrPutS( sAttrVal, pTgtDim, pTgtHier, vEle, sAttrName, 1 );\r\n Else;\r\n ElementAttrPutS( sAttrVal, pTgtDim, pTgtHier, vEle, sAttrName );\r\n EndIf;\r\n EndIf;\r\n EndIf;\r\n Else;\r\n nAttrVal = ElementAttrN( pSrcDim, pSrcHier, vEle, sAttrName );\r\n If( nAttrVal <> 0 );\r\n If( CellIsUpdateable( '}ElementAttributes_' | pTgtDim, pTgtHier:vEle, sAttrName ) = 1 );\r\n ElementAttrPutN( nAttrVal, pTgtDim, pTgtHier, vEle, sAttrName );\r\n EndIf;\r\n EndIf; \r\n EndIf;\r\n # check for localized attributes\r\n If( CubeExists( sAttrLoc ) = 1 );\r\n nLang = 1;\r\n While( nLang <= nNumLang );\r\n sLang = DimNm( cLangDim, nLang );\r\n If( sAttrType @= 'A' % sAttrType @= 'S' );\r\n sAttrVal = ElementAttrS( pSrcDim, pSrcHier, vEle, sAttrName );\r\n sAttrValLoc = ElementAttrSL( pSrcDim, pSrcHier, vEle, sAttrName, sLang );\r\n If( sAttrValLoc @= sAttrVal ); sAttrValLoc = ''; EndIf;\r\n Else;\r\n nAttrVal = ElementAttrN( pSrcDim, pSrcHier, vEle, sAttrName );\r\n nAttrValLoc = ElementAttrNL( pSrcDim, pSrcHier, vEle, sAttrName, sLang );\r\n EndIf;\r\n If( CubeExists( sAttrLocTarget ) = 0 );\r\n If( sAttrType @= 'A' );\r\n ElementAttrPutS( sAttrValLoc, pTgtDim, pTgtHier, vEle, sAttrName, sLang, 1 );\r\n ElseIf( sAttrType @= 'N' );\r\n ElementAttrPutN( nAttrValLoc, pTgtDim, pTgtHier, vEle, sAttrName, sLang );\r\n Else;\r\n ElementAttrPutS( sAttrValLoc, pTgtDim, pTgtHier, vEle, sAttrName, sLang );\r\n EndIf;\r\n ElseIf(CubeExists( sAttrLocTarget ) = 1 );\r\n If( CellIsUpdateable( sAttrLocTarget, pTgtHier:vEle, sLang, sAttrName ) = 1 );\r\n If( sAttrType @= 'A' );\r\n ElementAttrPutS( sAttrValLoc, pTgtDim, pTgtHier, vEle, sAttrName, sLang, 1 );\r\n ElseIf( sAttrType @= 'N' );\r\n ElementAttrPutN( nAttrValLoc, pTgtDim, pTgtHier, vEle, sAttrName, sLang );\r\n Else;\r\n ElementAttrPutS( sAttrValLoc, pTgtDim, pTgtHier, vEle, sAttrName, sLang );\r\n EndIf;\r\n EndIf;\r\n EndIf;\r\n nLang = nLang + 1;\r\n End;\r\n EndIf;\r\n nAttr = nAttr + 1;\r\n End;\r\n\r\nEndIf;\r\n\r\n### End Data ###", "EpilogProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n\r\nIf(pTgtDim @=pTgtHier);\r\n sTargetDimHier = pTgtDim;\r\nElse;\r\n sTargetDimHier =pTgtDim|':'|pTgtHier;\r\nEndIf;\r\n\r\n### Set the target Sort Order ###\r\n# CellPutS to }DimensionProperties cube removed\r\n# Placeholder as expecting a TI function to be made available to be able to modify these properties\r\n \r\n### If a new dimension has been created, call the process recursively to clone the alternate hierarchy, after the same named hierarchy has been processed\r\nIf( nProcessSameNamedHier = 1 );\r\n nRet = ExecuteProcess('}bedrock.hier.clone',\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n 'pSrcDim', pSrcDim,\r\n 'pSrcHier',pSrcHier,\r\n 'pTgtDim', pTgtDim,\r\n 'pTgtHier', sEpilogTgtHier,\r\n 'pAttr', pAttr,\r\n 'pUnwind', pUnwind\r\n );\r\nEndIf;\r\n \r\n### Return code & final error message handling\r\nIf( nErrors > 0 );\r\n sMessage = 'the process incurred at least 1 error. Please see above lines in this file for more details.';\r\n nProcessReturnCode = 0;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% Process:%cThisProcName% completed with errors. Check tm1server.log for details.' );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n EndIf;\r\nElse;\r\n sProcessAction = Expand( 'Process:%cThisProcName% successfully cloned the %pSrcDim%:%pSrcHier% dimension:hierarchy to %pTgtDim%:%pTgtHier%' );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% %sProcessAction%' );\r\n nProcessReturnCode = 1;\r\n If( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( sProcessAction ) ); \r\n EndIf;\r\nEndIf;\r\n\r\n### End Epilog ###", @@ -13,53 +13,59 @@ "subset": "All" }, "Parameters": [ - { - "Name": "pLogOutput", - "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, - { - "Name": "pStrictErrorHandling", - "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, { "Name": "pSrcDim", - "Prompt": "REQUIRED: Source Dimension", + "Prompt": "REQUIRED: Source dimension name", "Value": "", "Type": "String" }, { "Name": "pSrcHier", - "Prompt": "REQUIRED: Source Hierarchy", + "Prompt": "REQUIRED: Source hierarchy name", "Value": "", "Type": "String" }, { "Name": "pTgtDim", - "Prompt": "REQUIRED: Target Dimension (can be the same as source)", + "Prompt": "OPTIONAL: Target dimension name (Default = pSrcDim)", "Value": "", "Type": "String" }, { "Name": "pTgtHier", - "Prompt": "OPTIONAL: Target Hierarchy (will default to SrcHier_Clone if the dimensions are the same)", + "Prompt": "OPTIONAL: Target hierarchy name (If pSrcDim = pTgtDim, Default = pSrcHier | '_Clone')", "Value": "", "Type": "String" }, { "Name": "pAttr", - "Prompt": "OPTIONAL: Include Attributes? (Boolean 1=True)", + "Prompt": "OPTIONAL: Include attributes (Boolean. Default = 0)", "Value": 0, "Type": "Numeric" }, { "Name": "pUnwind", - "Prompt": "REQUIRED: Unwind? (0 = Delete all Elements, 1 = Unwind Existing Elements, 2 = Do not change Existing Elements (Only relevant if target hierarchy exists) )", + "Prompt": "OPTIONAL: Unwind hierarchies after process (0 = Delete all elements, 1 = Unwind existing elements, 2 = Do not change existing elements. Default = 0)", "Value": 0, "Type": "Numeric" + }, + { + "Name": "pLogOutput", + "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pStrictErrorHandling", + "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pJson", + "Prompt": "OPTIONAL: JSON Object with process parameter values. This will overwrite user passed parameters for all included parameters.", + "Value": "{}", + "Type": "String" } ], "Variables": [ diff --git a/bedrock_processes_json/}bedrock.hier.consol.delete.json b/bedrock_processes_json/}bedrock.hier.consol.delete.json index ebd49c0..4ea6227 100644 --- a/bedrock_processes_json/}bedrock.hier.consol.delete.json +++ b/bedrock_processes_json/}bedrock.hier.consol.delete.json @@ -1,6 +1,6 @@ { "Name": "}bedrock.hier.consol.delete", - "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.hier.consol.delete', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pDim', '', 'pHier', '', 'pEle', '',\r\n \t'pDelim', '&'\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process will delete a specified C-Level item **or** ALL consolidations in the dimension hierarchy. \r\n\r\n# Use case: Could be used during development or in production.\r\n# 1/ Delete a specific or all C-Level items in a hierarchy.\r\n\r\n# Note:\r\n# Valid dimension name (pDim) is mandatory otherwise the process will abort. Control dimensions are excluded.\r\n# The hierarchy (pHier) will default to pDim if not specified, otherwise it must be valid else the process will abort.\r\n# **ALL** consoldidated items in hierarchy will be deleted if consolidated item (pEle) is specified as \\*, otherwise it needs to contain valid c-level item(s). \r\n# Caution: Target hierarchy (pHier) cannot be `Leaves`.\r\n#EndRegion @DOC\r\n\r\n##Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSub = cThisProcName |'_'| cTimeStamp |'_'| cRandomInt;\r\ncUserName = TM1User();\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pDim:%pDim%, pHier:%pHier%, pEle:%pEle%, pDelim:%pDelim%.';\r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\n### Validate Parameters ###\r\nnErrors = 0;\r\n\r\nIf( Scan( ':', pDim ) > 0 & pHier @= '' );\r\n # A hierarchy has been passed as dimension. Handle the input error by splitting dim:hier into dimension & hierarchy\r\n pHier = SubSt( pDim, Scan( ':', pDim ) + 1, Long( pDim ) );\r\n pDim = SubSt( pDim, 1, Scan( ':', pDim ) - 1 );\r\nEndIf;\r\n\r\n## Validate Dimension\r\nIf( Trim( pDim ) @= '' );\r\n nErrors = 1;\r\n sMessage = 'No dimension specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( DimensionExists( pDim ) = 0 );\r\n nErrors = 1;\r\n sMessage = 'Dimension: ' | pDim | ' does not exist on server.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n## Validate Hierarchy\r\nIF(pHier @= 'Leaves' );\r\n nErrors = 1;\r\n sMessage = 'Invalid Hierarchy: ' | pDim |':'|pHier;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n## Validate Elements\r\nIF(pEle @= '' );\r\n nErrors = 1;\r\n sMessage = 'Element cannot be empty. Use * for all elements';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n\r\nIf( Trim( pHier ) @= '' );\r\n sHier = pDim;\r\nElse;\r\n sHier = pHier;\r\nEndIf;\r\n\r\nIf( HierarchyExists( pDim, sHier ) = 0 );\r\n nErrors = 1;\r\n sMessage = 'The Hierarchy ' | sHier | ' does not exist.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# If blank delimiter specified then convert to default\r\nIf( pDelim @= '' );\r\n pDelim = '&';\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors > 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\nsEles = pEle;\r\nnDelimiterIndex = 1;\r\nWhile( nDelimiterIndex <> 0 );\r\n \r\n nDelimiterIndex = Scan( pDelim, sEles );\r\n If( nDelimiterIndex = 0 );\r\n sEle = sEles;\r\n Else;\r\n sEle = Trim( SubSt( sEles, 1, nDelimiterIndex - 1 ) );\r\n sEles = Trim( Subst( sEles, nDelimiterIndex + Long(pDelim), Long( sEles ) ) );\r\n EndIf;\r\n \r\n # Check if a wildcard has been used to specify the Element name.\r\n # If it hasn't then just delete the Element if it exists\r\n If( sEle @= '*' );\r\n nElementIndex = Dimsiz(pDim|':'|sHier);\r\n While( nElementIndex >= 1 );\r\n sEle = ElementName( pDim, sHier, nElementIndex );\r\n sElType = ElementType( pDim, sHier, sEle );\r\n If( sElType @= 'C' );\r\n HierarchyElementDelete( pDim, sHier,sEle );\r\n EndIf;\r\n nElementIndex = nElementIndex - 1;\r\n End;\r\n ElseIf( Scan( '*', sEle ) = 0);\r\n If( HierarchyElementExists( pDim,sHier, sEle ) = 1 );\r\n sElType = ElementType( pDim, sHier, sEle ); \r\n If( sElType @='C' );\r\n HierarchyElementDelete( pDim, sHier,sEle );\r\n EndIf;\r\n Else;\r\n nErrors = 1;\r\n sMessage = 'The Hierarchy ' | sHier | ' does not have element ' | sEle;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\n Else;\r\n # Wildcard search string\r\n sEle = '\"'|sEle|'\"';\r\n sProc = '}bedrock.hier.sub.create.bymdx';\r\n sMdx = '{TM1FILTERBYPATTERN( {TM1SUBSETALL([ ' |pDim|'].['|sHier |' ])},'| sEle| ')}';\r\n ExecuteProcess('}bedrock.hier.sub.create.bymdx',\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pDim', pDim,\r\n \t'pHier', sHier,\r\n \t'pSub', cTempSub,\r\n \t'pMDXExpr', sMdx,\r\n \t'pConvertToStatic', 1,\r\n \t'pTemp', 1\r\n );\r\n nCount = HierarchySubsetGetSize(pDim, sHier, cTempSub);\r\n While( nCount >= 1 );\r\n sElement = HierarchySubsetGetElementName(pDim, sHier, cTempSub, nCount);\r\n sElType = ElementType( pDim, sHier, sElement );\r\n If( sElType @= 'C' );\r\n HierarchyElementDelete( pDim, sHier,sElement );\r\n EndIf; \r\n nCount = nCount - 1;\r\n End;\r\n EndIf;\r\n\r\nEnd;\r\n\r\n### End Prolog ###", + "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.hier.consol.delete', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pDim', '', 'pHier', '', 'pEle', '',\r\n \t'pDelim', '&'\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process will delete a specified C-Level item **or** ALL consolidations in the dimension hierarchy. \r\n\r\n# Use case: Could be used during development or in production.\r\n# 1/ Delete a specific or all C-Level items in a hierarchy.\r\n\r\n# Note:\r\n# Valid dimension name (pDim) is mandatory otherwise the process will abort. Control dimensions are excluded.\r\n# The hierarchy (pHier) will default to pDim if not specified, otherwise it must be valid else the process will abort.\r\n# **ALL** consoldidated items in hierarchy will be deleted if consolidated item (pEle) is specified as \\*, otherwise it needs to contain valid c-level item(s). \r\n# Caution: Target hierarchy (pHier) cannot be `Leaves`.\r\n#EndRegion @DOC\r\n\r\n##Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSub = cThisProcName |'_'| cTimeStamp |'_'| cRandomInt;\r\ncUserName = TM1User();\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent = 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pDim:%pDim%, pHier:%pHier%, pEle:%pEle%, pDelim:%pDelim%.';\r\n\r\n#################################################################################################\r\n#Region - Process Parameters\r\n\r\npJson = IF( JsonType( pJson ) @<> 'object', '{}', pJson );\r\nsMessages = '{\"Process\": \"'|GetProcessName()|'\", \"User\": \"'|TM1User()|'\", \"Info\": [\"Process: '''|GetProcessName()|''' run by User: '''|TM1User()|'''.\"], \"Error\": []}';\r\npDefaultParameters = '{\r\n \"pDelim\": \"&\",\r\n \"pDim\": null,\r\n \"pEle\": null,\r\n \"pHier\": \"\",\r\n \"pLogOutput\": 0,\r\n \"pStrictErrorHandling\": 0\r\n}';\r\n\r\npPassedParameters = '{\r\n \"pDelim\": '|StringToJson ( pDelim )|',\r\n \"pDim\": '|StringToJson ( pDim )|',\r\n \"pEle\": '|StringToJson ( pEle )|',\r\n \"pHier\": '|StringToJson ( pHier )|',\r\n \"pLogOutput\": '|NumberToString( pLogOutput )|',\r\n \"pStrictErrorHandling\": '|NumberToString( pStrictErrorHandling )|'\r\n}';\r\n\r\npJson = JsonMergePatch( pPassedParameters, pJson );\r\n# String Parameters\r\npDelim = JsonToString( JsonGet( pJson, 'pDelim' ) );\r\npDim = JsonToString( JsonGet( pJson, 'pDim' ) );\r\npEle = JsonToString( JsonGet( pJson, 'pEle' ) );\r\npHier = JsonToString( JsonGet( pJson, 'pHier' ) );\r\n# Numeric Parameters\r\npLogOutput = StringToNumber( JsonToString( JsonGet( pJson, 'pLogOutput' ) ) );\r\npStrictErrorHandling = StringToNumber( JsonToString( JsonGet( pJson, 'pStrictErrorHandling' ) ) );\r\n\r\n### Get the parameters that differ from the default\r\npDiffer = JsonDiff( pDefaultParameters, pJson );\r\nnSize = JsonSize( pDiffer );\r\nWHILE( nSize > 0 );\r\n nSize = nSize - 1;\r\n pDiffer = JsonReplace( pDiffer, '/'|NumberToString( nSize )|'/op', '\"add\"' );\r\nEND;\r\npJson = JsonPatch( '{}', pDiffer );\r\n\r\n### LogOutput parameters\r\nsMessages = JsonAdd( sMessages, '/Info/-', pJson );\r\nIF( pLogOutput = 1 );\r\n LogOutput('INFO', JsonToString( sMessages, '/Info/0', 0, ' ' ) );\r\nENDIF;\r\n\r\n#EndRegion - Process Parameters\r\n#################################################################################################\r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\n### Validate Parameters ###\r\nnErrors = 0;\r\n\r\nIf( Scan( ':', pDim ) > 0 & pHier @= '' );\r\n # A hierarchy has been passed as dimension. Handle the input error by splitting dim:hier into dimension & hierarchy\r\n pHier = SubSt( pDim, Scan( ':', pDim ) + 1, Long( pDim ) );\r\n pDim = SubSt( pDim, 1, Scan( ':', pDim ) - 1 );\r\nEndIf;\r\n\r\n## Validate Dimension\r\nIf( Trim( pDim ) @= '' );\r\n nErrors = 1;\r\n sMessage = 'No dimension specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( DimensionExists( pDim ) = 0 );\r\n nErrors = 1;\r\n sMessage = 'Dimension: ' | pDim | ' does not exist on server.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n## Validate Hierarchy\r\nIF(pHier @= 'Leaves' );\r\n nErrors = 1;\r\n sMessage = 'Invalid Hierarchy: ' | pDim |':'|pHier;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n## Validate Elements\r\nIF(pEle @= '' );\r\n nErrors = 1;\r\n sMessage = 'Element cannot be empty. Use * for all elements';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n\r\nIf( Trim( pHier ) @= '' );\r\n sHier = pDim;\r\nElse;\r\n sHier = pHier;\r\nEndIf;\r\n\r\nIf( HierarchyExists( pDim, sHier ) = 0 );\r\n nErrors = 1;\r\n sMessage = 'The Hierarchy ' | sHier | ' does not exist.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n# If blank delimiter specified then convert to default\r\nIf( pDelim @= '' );\r\n pDelim = '&';\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors > 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\nsEles = pEle;\r\nnDelimiterIndex = 1;\r\nWhile( nDelimiterIndex <> 0 );\r\n \r\n nDelimiterIndex = Scan( pDelim, sEles );\r\n If( nDelimiterIndex = 0 );\r\n sEle = sEles;\r\n Else;\r\n sEle = Trim( SubSt( sEles, 1, nDelimiterIndex - 1 ) );\r\n sEles = Trim( Subst( sEles, nDelimiterIndex + Long(pDelim), Long( sEles ) ) );\r\n EndIf;\r\n \r\n # Check if a wildcard has been used to specify the Element name.\r\n # If it hasn't then just delete the Element if it exists\r\n If( sEle @= '*' );\r\n nElementIndex = Dimsiz(pDim|':'|sHier);\r\n While( nElementIndex >= 1 );\r\n sEle = ElementName( pDim, sHier, nElementIndex );\r\n sElType = ElementType( pDim, sHier, sEle );\r\n If( sElType @= 'C' );\r\n HierarchyElementDelete( pDim, sHier,sEle );\r\n EndIf;\r\n nElementIndex = nElementIndex - 1;\r\n End;\r\n ElseIf( Scan( '*', sEle ) = 0);\r\n If( HierarchyElementExists( pDim,sHier, sEle ) = 1 );\r\n sElType = ElementType( pDim, sHier, sEle ); \r\n If( sElType @='C' );\r\n HierarchyElementDelete( pDim, sHier,sEle );\r\n EndIf;\r\n Else;\r\n nErrors = 1;\r\n sMessage = 'The Hierarchy ' | sHier | ' does not have element ' | sEle;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n EndIf;\r\n Else;\r\n # Wildcard search string\r\n sEle = '\"'|sEle|'\"';\r\n sProc = '}bedrock.hier.sub.create.bymdx';\r\n sMdx = '{TM1FILTERBYPATTERN( {TM1SUBSETALL([ ' |pDim|'].['|sHier |' ])},'| sEle| ')}';\r\n ExecuteProcess('}bedrock.hier.sub.create.bymdx',\r\n 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pDim', pDim,\r\n \t'pHier', sHier,\r\n \t'pSub', cTempSub,\r\n \t'pMDXExpr', sMdx,\r\n \t'pConvertToStatic', 1,\r\n \t'pTemp', 1\r\n );\r\n nCount = HierarchySubsetGetSize(pDim, sHier, cTempSub);\r\n While( nCount >= 1 );\r\n sElement = HierarchySubsetGetElementName(pDim, sHier, cTempSub, nCount);\r\n sElType = ElementType( pDim, sHier, sElement );\r\n If( sElType @= 'C' );\r\n HierarchyElementDelete( pDim, sHier,sElement );\r\n EndIf; \r\n nCount = nCount - 1;\r\n End;\r\n EndIf;\r\n\r\nEnd;\r\n\r\n### End Prolog ###", "MetadataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n", "DataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "EpilogProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n### Return code & final error message handling\r\nIf( nErrors > 0 );\r\n sMessage = 'the process incurred at least 1 error. Please see above lines in this file for more details.';\r\n nProcessReturnCode = 0;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% Process:%cThisProcName% completed with errors. Check tm1server.log for details.' );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n EndIf;\r\nElse;\r\n sProcessAction = Expand( 'Process:%cThisProcName% successfully deleted the appropriate consolidated elements in hierarchy %pDim%:%pHier%.' );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% %sProcessAction%' );\r\n nProcessReturnCode = 1;\r\n If( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( sProcessAction ) ); \r\n EndIf;\r\nEndIf;\r\n\r\n### End Epilog ###", @@ -10,41 +10,47 @@ "Type": "None" }, "Parameters": [ - { - "Name": "pLogOutput", - "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, - { - "Name": "pStrictErrorHandling", - "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, { "Name": "pDim", - "Prompt": "REQUIRED: Dimension name", + "Prompt": "REQUIRED: Delimited list of dimensions", "Value": "", "Type": "String" }, { "Name": "pHier", - "Prompt": "OPTIONAL: Hierarchy name (if blank then same named hierarchy as dimension is assumed)", + "Prompt": "OPTIONAL: Hierarchy name (Default = pDim)", "Value": "", "Type": "String" }, { "Name": "pEle", - "Prompt": "OPTIONAL: Filter on elements (element list separated by delimiter, accepts wildcards (if * then all the consolidation elements get deleted))", + "Prompt": "REQUIRED: Delimited list of elements", "Value": "", "Type": "String" }, { "Name": "pDelim", - "Prompt": "OPTIONAL: Delimiter character for element list (default to '&' if blank)", + "Prompt": "OPTIONAL: Delimiter for list parameters (Default = '&')", "Value": "&", "Type": "String" + }, + { + "Name": "pLogOutput", + "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pStrictErrorHandling", + "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pJson", + "Prompt": "OPTIONAL: JSON Object with process parameter values. This will overwrite user passed parameters for all included parameters.", + "Value": "{}", + "Type": "String" } ], "Variables": [], diff --git a/bedrock_processes_json/}bedrock.hier.consol.flat.create.json b/bedrock_processes_json/}bedrock.hier.consol.flat.create.json index e9341eb..b61f4c1 100644 --- a/bedrock_processes_json/}bedrock.hier.consol.flat.create.json +++ b/bedrock_processes_json/}bedrock.hier.consol.flat.create.json @@ -1,6 +1,6 @@ { "Name": "}bedrock.hier.consol.flat.create", - "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.hier.consol.flat.create', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pDim', '', 'pHier', '',\r\n \t'pSrcConsol', '', 'pTgtConsol', '', 'pWeight', 1\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n### Start Prolog ###\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process will add consolidated element pTgtConsol in the dimension hierarchy. \r\n\r\n# Use case: Intended for Development but could be used in production too.\r\n# 1/ Create a new hierarchy for testing.\r\n# 2/ Create a new hierarchy to reflect new business needs.\r\n\r\n# Note:\r\n# If source parent element (pSrcConsol) is defined then all its leaf elements will be copied to target\r\n# parent element consolidation. Otherwise all leaf elements in the dimension hierarchy will be \r\n# added into target parent element consolidation.\r\n# Valid source dimension name (pDim), hierarchy (pHier) and taget parent element (pTgtConsol)\r\n# are mandatory otherwise the process will abort.\r\n# Weight of all added elements into target parent consolidation will be assigned accoring to\r\n# pWeight parameter value.\r\n\r\n# Caution: If the target element pTgtConsol exists in the hierarchy, then it will be overwritten.\r\n#EndRegion @DOC\r\n\r\n### Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSub = cThisProcName |'_'| cTimeStamp |'_'| cRandomInt;\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent= 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pDim=%pDim%, pHier=%pHier%, pSrcConsol=%pSrcConsol%, pTgtConsol=%pTgtConsol%.';\r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\n### Validate Parameters ###\r\nnErrors = 0;\r\n\r\nIf( Scan( ':', pDim ) > 0 & pHier @= '' );\r\n # A hierarchy has been passed as dimension. Handle the input error by splitting dim:hier into dimension & hierarchy\r\n pHier = SubSt( pDim, Scan( ':', pDim ) + 1, Long( pDim ) );\r\n pDim = SubSt( pDim, 1, Scan( ':', pDim ) - 1 );\r\nEndIf;\r\n\r\nIF( Trim( pDim ) @= '' );\r\n ## No dimension nominated.\r\n nErrors = 1;\r\n sMessage = 'No dimension specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\nIf( DimensionExists( pDim) = 0 );\r\n ## Dimension does not exist in the model.\r\n nErrors = 1;\r\n sMessage = 'The dimension does not exist in the model: ' | pDim;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\nIF( SUBST( pDim, 1, 1 ) @= '}' );\r\n ## Nominated dimension is a system dimension.\r\n nErrors = 1;\r\n sMessage = 'Can not modify a system dimension with this Bedrock.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n## Validate hierarchy\r\nIF( Trim( pHier ) @= '' );\r\n pHier = pDim;\r\nEndIf;\r\n\r\nIF( HierarchyExists(pDim, pHier ) = 0 % pHier @= 'Leaves');\r\n nErrors = 1;\r\n sMessage = 'Invalid dimension Hierarchy: ' | pDim |':'|pHier;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n## Validate consolidation Parameter\r\npTgtConsol = Trim( pTgtConsol );\r\nIf( pTgtConsol @= '');\r\n nErrors = 1;\r\n sMessage = 'No target parent element supplied.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( pTgtConsol @= pSrcConsol );\r\n nErrors = 1;\r\n sMessage = 'Target and source consolidations can''t be the same elements: ' | pTgtConsol |':'| pSrcConsol;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndif;\r\n\r\n## Validate Member Consolidation\r\npSrcConsol = Trim( pSrcConsol );\r\nIF( pSrcConsol @<> '' );\r\n ## A source consolidation has been nominated.\r\n IF( ElementIndex( pDim, pHier, pSrcConsol ) = 0 );\r\n ## The Member Consolidation does not exist in the dimension.\r\n nErrors = 1;\r\n sMessage = Expand('Source consolidation %pSrcConsol% does not exist in the dimension:hierarchy: %pDim%:%pHier%.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n ENDIF;\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n### UNWIND CONSOLIDATION ###\r\nIF( ElementIndex( pDim, pHier, pTgtConsol ) > 0 );\r\n ExecuteProcess('}bedrock.hier.unwind'\r\n ,'pStrictErrorHandling', pStrictErrorHandling\r\n ,'pDim', pDim\r\n ,'pHier',pHier\r\n ,'pConsol', pTgtConsol\r\n ,'pRecursive', 0\r\n );\r\nElse;\r\n HierarchyElementInsert( pDim, pHier, '', pTgtConsol, 'C' );\r\nENDIF;\r\n\r\n### Assign Datasource ###\r\nDatasourceNameForServer = pDim|':'|pHier;\r\nDataSourceDimensionSubset = 'All';\r\n\r\n### End Prolog ###", + "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.hier.consol.flat.create', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pDim', '', 'pHier', '',\r\n \t'pSrcConsol', '', 'pTgtConsol', '', 'pWeight', 1\r\n\t);\r\nEndIf;\r\n#EndRegion CallThisProcess\r\n\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n### Start Prolog ###\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock-5 Ver 5.0~~##\r\n################################################################################################# \r\n\r\n#Region @DOC\r\n# Description:\r\n# This process will add consolidated element pTgtConsol in the dimension hierarchy. \r\n\r\n# Use case: Intended for Development but could be used in production too.\r\n# 1/ Create a new hierarchy for testing.\r\n# 2/ Create a new hierarchy to reflect new business needs.\r\n\r\n# Note:\r\n# If source parent element (pSrcConsol) is defined then all its leaf elements will be copied to target\r\n# parent element consolidation. Otherwise all leaf elements in the dimension hierarchy will be \r\n# added into target parent element consolidation.\r\n# Valid source dimension name (pDim), hierarchy (pHier) and taget parent element (pTgtConsol)\r\n# are mandatory otherwise the process will abort.\r\n# Weight of all added elements into target parent consolidation will be assigned accoring to\r\n# pWeight parameter value.\r\n\r\n# Caution: If the target element pTgtConsol exists in the hierarchy, then it will be overwritten.\r\n#EndRegion @DOC\r\n\r\n### Global Variables\r\nStringGlobalVariable('sProcessReturnCode');\r\nNumericGlobalVariable('nProcessReturnCode');\r\nnProcessReturnCode= 0;\r\n\r\n### Constants ###\r\ncThisProcName = GetProcessName();\r\ncUserName = TM1User();\r\ncTimeStamp = TimSt( Now, '\\Y\\m\\d\\h\\i\\s' );\r\ncRandomInt = NumberToString( INT( RAND( ) * 1000 ));\r\ncTempSub = cThisProcName |'_'| cTimeStamp |'_'| cRandomInt;\r\ncMsgErrorLevel = 'ERROR';\r\ncMsgErrorContent= 'User:%cUserName% Process:%cThisProcName% ErrorMsg:%sMessage%';\r\ncLogInfo = 'Process:%cThisProcName% run with parameters pDim=%pDim%, pHier=%pHier%, pSrcConsol=%pSrcConsol%, pTgtConsol=%pTgtConsol%.';\r\n\r\n#################################################################################################\r\n#Region - Process Parameters\r\n\r\npJson = IF( JsonType( pJson ) @<> 'object', '{}', pJson );\r\nsMessages = '{\"Process\": \"'|GetProcessName()|'\", \"User\": \"'|TM1User()|'\", \"Info\": [\"Process: '''|GetProcessName()|''' run by User: '''|TM1User()|'''.\"], \"Error\": []}';\r\npDefaultParameters = '{\r\n \"pDim\": null,\r\n \"pHier\": \"\",\r\n \"pSrcConsol\": \"\",\r\n \"pTgtConsol\": \"\",\r\n \"pLogOutput\": 0,\r\n \"pStrictErrorHandling\": 0,\r\n \"pWeight\": 1\r\n}';\r\n\r\npPassedParameters = '{\r\n \"pDim\": '|StringToJson ( pDim )|',\r\n \"pHier\": '|StringToJson ( pHier )|',\r\n \"pSrcConsol\": '|StringToJson ( pSrcConsol )|',\r\n \"pTgtConsol\": '|StringToJson ( pTgtConsol )|',\r\n \"pLogOutput\": '|NumberToString( pLogOutput )|',\r\n \"pStrictErrorHandling\": '|NumberToString( pStrictErrorHandling )|',\r\n \"pWeight\": '|NumberToString( pWeight )|'\r\n}';\r\n\r\npJson = JsonMergePatch( pPassedParameters, pJson );\r\n# String Parameters\r\npDim = JsonToString( JsonGet( pJson, 'pDim' ) );\r\npHier = JsonToString( JsonGet( pJson, 'pHier' ) );\r\npSrcConsol = JsonToString( JsonGet( pJson, 'pSrcConsol' ) );\r\npTgtConsol = JsonToString( JsonGet( pJson, 'pTgtConsol' ) );\r\n# Numeric Parameters\r\npLogOutput = StringToNumber( JsonToString( JsonGet( pJson, 'pLogOutput' ) ) );\r\npStrictErrorHandling = StringToNumber( JsonToString( JsonGet( pJson, 'pStrictErrorHandling' ) ) );\r\npWeight = StringToNumber( JsonToString( JsonGet( pJson, 'pWeight' ) ) );\r\n\r\n### Get the parameters that differ from the default\r\npDiffer = JsonDiff( pDefaultParameters, pJson );\r\nnSize = JsonSize( pDiffer );\r\nWHILE( nSize > 0 );\r\n nSize = nSize - 1;\r\n pDiffer = JsonReplace( pDiffer, '/'|NumberToString( nSize )|'/op', '\"add\"' );\r\nEND;\r\npJson = JsonPatch( '{}', pDiffer );\r\n\r\n### LogOutput parameters\r\nsMessages = JsonAdd( sMessages, '/Info/-', pJson );\r\nIF( pLogOutput = 1 );\r\n LogOutput('INFO', JsonToString( sMessages, '/Info/0', 0, ' ' ) );\r\nENDIF;\r\n\r\n#EndRegion - Process Parameters\r\n#################################################################################################\r\n\r\n## LogOutput parameters\r\nIF( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( cLogInfo ) ); \r\nENDIF;\r\n\r\n### Validate Parameters ###\r\nnErrors = 0;\r\n\r\nIf( Scan( ':', pDim ) > 0 & pHier @= '' );\r\n # A hierarchy has been passed as dimension. Handle the input error by splitting dim:hier into dimension & hierarchy\r\n pHier = SubSt( pDim, Scan( ':', pDim ) + 1, Long( pDim ) );\r\n pDim = SubSt( pDim, 1, Scan( ':', pDim ) - 1 );\r\nEndIf;\r\n\r\nIF( Trim( pDim ) @= '' );\r\n ## No dimension nominated.\r\n nErrors = 1;\r\n sMessage = 'No dimension specified.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\nIf( DimensionExists( pDim) = 0 );\r\n ## Dimension does not exist in the model.\r\n nErrors = 1;\r\n sMessage = 'The dimension does not exist in the model: ' | pDim;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\nIF( SUBST( pDim, 1, 1 ) @= '}' );\r\n ## Nominated dimension is a system dimension.\r\n nErrors = 1;\r\n sMessage = 'Can not modify a system dimension with this Bedrock.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n## Validate hierarchy\r\nIF( Trim( pHier ) @= '' );\r\n pHier = pDim;\r\nEndIf;\r\n\r\nIF( HierarchyExists(pDim, pHier ) = 0 % pHier @= 'Leaves');\r\n nErrors = 1;\r\n sMessage = 'Invalid dimension Hierarchy: ' | pDim |':'|pHier;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndIf;\r\n\r\n## Validate consolidation Parameter\r\npTgtConsol = Trim( pTgtConsol );\r\nIf( pTgtConsol @= '');\r\n nErrors = 1;\r\n sMessage = 'No target parent element supplied.';\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nElseIf( pTgtConsol @= pSrcConsol );\r\n nErrors = 1;\r\n sMessage = 'Target and source consolidations can''t be the same elements: ' | pTgtConsol |':'| pSrcConsol;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\nEndif;\r\n\r\n## Validate Member Consolidation\r\npSrcConsol = Trim( pSrcConsol );\r\nIF( pSrcConsol @<> '' );\r\n ## A source consolidation has been nominated.\r\n IF( ElementIndex( pDim, pHier, pSrcConsol ) = 0 );\r\n ## The Member Consolidation does not exist in the dimension.\r\n nErrors = 1;\r\n sMessage = Expand('Source consolidation %pSrcConsol% does not exist in the dimension:hierarchy: %pDim%:%pHier%.');\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n ENDIF;\r\nEndIf;\r\n\r\n### Check for errors before continuing\r\nIf( nErrors <> 0 );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n Else;\r\n ProcessBreak;\r\n EndIf;\r\nEndIf;\r\n\r\n### UNWIND CONSOLIDATION ###\r\nIF( ElementIndex( pDim, pHier, pTgtConsol ) > 0 );\r\n ExecuteProcess('}bedrock.hier.unwind'\r\n ,'pStrictErrorHandling', pStrictErrorHandling\r\n ,'pDim', pDim\r\n ,'pHier',pHier\r\n ,'pConsol', pTgtConsol\r\n ,'pRecursive', 0\r\n );\r\nElse;\r\n HierarchyElementInsert( pDim, pHier, '', pTgtConsol, 'C' );\r\nENDIF;\r\n\r\n### Assign Datasource ###\r\nDatasourceNameForServer = pDim|':'|pHier;\r\nDataSourceDimensionSubset = 'All';\r\n\r\n### End Prolog ###", "MetadataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock Ver 4.0.0~~##\r\n################################################################################################# \r\n\r\n### Start Metadata ###\r\n\r\n### VALIDATE RECORD ###\r\n\r\nsElType = ElementType( pDim, pHier, vElement );\r\nIF( sElType @<> 'N' );\r\n ## The element is not a 'N' element.\r\n ITEMSKIP;\r\nENDIF;\r\n\r\nIF( pSrcConsol @<> '' );\r\n ## A member consolidation is been used.\r\n IF( ElementIsAncestor( pDim, pHier, pSrcConsol, vElement ) = 0 );\r\n ## The element is not a member of the nominated consolidation.\r\n ITEMSKIP;\r\n ENDIF;\r\nENDIF; \r\n\r\n### BUILD CONSOLIDATION ###\r\n\r\nIf( nErrors = 0 );\r\n HierarchyElementComponentAdd( pDim, pHier, pTgtConsol, vElement, pWeight );\r\nEndIf;\r\n\r\n### End Metadata ###", "DataProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n", "EpilogProcedure": "\r\n#****Begin: Generated Statements***\r\n#****End: Generated Statements****\r\n\r\n################################################################################################# \r\n##~~Join the bedrock TM1 community on GitHub https://github.com/cubewise-code/bedrock Ver 4.0.0~~##\r\n################################################################################################# \r\n\r\n### Return code & final error message handling\r\nIf( nErrors > 0 );\r\n sMessage = 'the process incurred at least 1 error. Please see above lines in this file for more details.';\r\n nProcessReturnCode = 0;\r\n LogOutput( cMsgErrorLevel, Expand( cMsgErrorContent ) );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% Process:%cThisProcName% completed with errors. Check tm1server.log for details.' );\r\n If( pStrictErrorHandling = 1 ); \r\n ProcessQuit; \r\n EndIf;\r\nElse;\r\n sProcessAction = Expand( 'Process:%cThisProcName% successfully created a consolidation %pTgtConsol% in the hierarchy %pDim%:%pHier%.' );\r\n sProcessReturnCode = Expand( '%sProcessReturnCode% %sProcessAction%' );\r\n nProcessReturnCode = 1;\r\n If( pLogoutput = 1 );\r\n LogOutput('INFO', Expand( sProcessAction ) ); \r\n EndIf;\r\nEndIf;", @@ -13,27 +13,15 @@ "subset": "All" }, "Parameters": [ - { - "Name": "pLogOutput", - "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, - { - "Name": "pStrictErrorHandling", - "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean True = 1)", - "Value": 0, - "Type": "Numeric" - }, { "Name": "pDim", - "Prompt": "REQUIRED: Dimension", + "Prompt": "REQUIRED: Delimited list of dimensions", "Value": "", "Type": "String" }, { "Name": "pHier", - "Prompt": "OPTIONAL: Hierarchy (will default to dimension name if blank)", + "Prompt": "OPTIONAL: Hierarchy name (Default = pDim)", "Value": "", "Type": "String" }, @@ -45,15 +33,33 @@ }, { "Name": "pTgtConsol", - "Prompt": "REQUIRED: Target consolidated element name", + "Prompt": "OPTIONAL: Target consolidated element name", "Value": "", "Type": "String" }, { "Name": "pWeight", - "Prompt": "OPTIONAL: Component Weight", + "Prompt": "OPTIONAL: Component weight (Default = 1)", "Value": 1, "Type": "Numeric" + }, + { + "Name": "pLogOutput", + "Prompt": "OPTIONAL: Write parameters and action summary to server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pStrictErrorHandling", + "Prompt": "OPTIONAL: On encountering any error, exit with major error status by ProcessQuit after writing to the server message log (Boolean. Default = 0)", + "Value": 0, + "Type": "Numeric" + }, + { + "Name": "pJson", + "Prompt": "OPTIONAL: JSON Object with process parameter values. This will overwrite user passed parameters for all included parameters.", + "Value": "{}", + "Type": "String" } ], "Variables": [ diff --git a/bedrock_processes_json/}bedrock.hier.create.fromattribute.json b/bedrock_processes_json/}bedrock.hier.create.fromattribute.json index c8305eb..c7def8a 100644 --- a/bedrock_processes_json/}bedrock.hier.create.fromattribute.json +++ b/bedrock_processes_json/}bedrock.hier.create.fromattribute.json @@ -1,6 +1,6 @@ { "Name": "}bedrock.hier.create.fromattribute", - "PrologProcedure": "#Region CallThisProcess\r\n# A snippet of code provided as an example how to call this process should the developer be working on a system without access to an editor with auto-complete.\r\nIf( 1 = 0 );\r\n ExecuteProcess( '}bedrock.hier.create.fromattribute', 'pLogOutput', pLogOutput,\r\n 'pStrictErrorHandling', pStrictErrorHandling,\r\n \t'pDim', '', 'pSrcHier', '', 'pTgtHier', '', 'pAttr', '',\r\n \t'pTopNode', 'Total